From 0acf072240712cdc6ea2ee22daba761df3455de1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 15:02:32 +0900 Subject: [PATCH 001/603] test(workforce-validation): define governed registry read contract --- .../tests/test_registry.py | 242 ++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_registry.py diff --git a/services/workforce-validation-api/tests/test_registry.py b/services/workforce-validation-api/tests/test_registry.py new file mode 100644 index 000000000..3a80cebd2 --- /dev/null +++ b/services/workforce-validation-api/tests/test_registry.py @@ -0,0 +1,242 @@ +"""Regression contract for the workforce-validation study registry boundary.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api.registry import ( + ValidationPrincipal, + ValidityStudyIntegrityError, + ValidityStudyNotFound, + ValidityStudyReadPort, + ValidityStudyRecord, + read_validity_study, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000c1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000c2") +CRITERION = UUID("00000000-0000-7000-8000-0000000000a1") +RECORDED_FROM = datetime(2026, 11, 3, tzinfo=timezone.utc) + + +class _ReadPort: + """Return one configured registry record and capture the authorized target.""" + + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[tuple[UUID, UUID]] = [] + + def read_validity_study(self, *, tenant_record_id: UUID, validity_study_id: UUID) -> object: + """Capture the target and return the configured persistence result.""" + self.calls.append((tenant_record_id, validity_study_id)) + return self.result + + +class _NoReadMethod: + """Deliberately fail the runtime repository protocol.""" + + +def _record(*, tenant_record_id: UUID = TENANT, validity_study_id: UUID = STUDY) -> ValidityStudyRecord: + return ValidityStudyRecord( + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + criterion_blueprint_id=CRITERION, + study_status_code="study_draft", + recorded_from=RECORDED_FROM, + recorded_to=None, + ) + + +def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=tenant_record_id, + actor_reference="person:analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, tenant_record_id: UUID = TENANT) -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=tenant_record_id, + policy_version_code="validation-read-v1", + resource_kind="validity_study_record", + purpose_code="validation_review", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=frozenset( + { + "criterion_blueprint_id", + "study_status_code", + "recorded_from", + "recorded_to", + } + ), + ) + + +def test_read_returns_only_authorized_requested_fields() -> None: + port = _ReadPort(_record()) + + view = read_validity_study( + principal=_principal(), + tenant_record_id=TENANT, + validity_study_id=STUDY, + purpose_code="validation_review", + requested_fields=frozenset({"study_status_code", "criterion_blueprint_id"}), + policy=_policy(), + read_port=port, + ) + + assert isinstance(port, ValidityStudyReadPort) + assert port.calls == [(TENANT, STUDY)] + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + assert view.fields == ( + ("criterion_blueprint_id", CRITERION), + ("study_status_code", "study_draft"), + ) + + +def test_authorization_denial_happens_before_persistence() -> None: + port = _ReadPort(_record()) + + with pytest.raises(AuthorizationDeniedError): + read_validity_study( + principal=_principal(), + tenant_record_id=TENANT, + validity_study_id=STUDY, + purpose_code="validation_review", + requested_fields=frozenset({"recorded_from"}), + policy=PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="validation-read-v1", + resource_kind="validity_study_record", + purpose_code="audit_review", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=frozenset({"recorded_from"}), + ), + read_port=port, + ) + + assert port.calls == [] + + +def test_missing_study_is_not_found() -> None: + with pytest.raises(ValidityStudyNotFound): + read_validity_study( + principal=_principal(), + tenant_record_id=TENANT, + validity_study_id=STUDY, + purpose_code="validation_review", + requested_fields=frozenset({"study_status_code"}), + policy=_policy(), + read_port=_ReadPort(None), + ) + + +def test_foreign_or_noncanonical_persistence_result_fails_closed() -> None: + for result in (_record(tenant_record_id=OTHER_TENANT), _record(validity_study_id=OTHER_STUDY), object()): + with pytest.raises(ValidityStudyIntegrityError): + read_validity_study( + principal=_principal(), + tenant_record_id=TENANT, + validity_study_id=STUDY, + purpose_code="validation_review", + requested_fields=frozenset({"study_status_code"}), + policy=_policy(), + read_port=_ReadPort(result), + ) + + +def test_dependency_and_request_types_fail_before_repository_use() -> None: + port = _ReadPort(_record()) + common = dict( + principal=_principal(), + tenant_record_id=TENANT, + validity_study_id=STUDY, + purpose_code="validation_review", + requested_fields=frozenset({"study_status_code"}), + policy=_policy(), + read_port=port, + ) + + for key, value, error in ( + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("purpose_code", "Validation Review", ValueError), + ("requested_fields", set({"study_status_code"}), ValueError), + ("requested_fields", frozenset(), ValueError), + ("requested_fields", frozenset({"unknown_field"}), ValueError), + ): + arguments = dict(common) + arguments[key] = value + with pytest.raises(error): + read_validity_study(**arguments) + + assert port.calls == [] + + +def test_principal_rejects_invalid_identity_and_scope_shapes() -> None: + invalid_values = ( + dict(tenant_record_id=UUID(int=0), actor_reference="person:analyst-1", granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"})), + dict(tenant_record_id=TENANT, actor_reference="not namespaced", granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"})), + dict(tenant_record_id=TENANT, actor_reference="person:analyst-1", granted_scope_codes=frozenset()), + dict(tenant_record_id=TENANT, actor_reference="person:analyst-1", granted_scope_codes=frozenset({"bad-scope"})), + ) + for values in invalid_values: + with pytest.raises(ValueError): + ValidationPrincipal(**values) + + +def test_record_rejects_noncanonical_or_invalid_durable_scalars() -> None: + valid = dict( + tenant_record_id=TENANT, + validity_study_id=STUDY, + criterion_blueprint_id=CRITERION, + study_status_code="study_draft", + recorded_from=RECORDED_FROM, + recorded_to=None, + ) + cases = ( + ("tenant_record_id", UUID(int=0)), + ("validity_study_id", "not-a-uuid"), + ("criterion_blueprint_id", UUID(int=(1 << 128) - 1)), + ("study_status_code", "Study Draft"), + ("recorded_from", datetime(2026, 11, 3)), + ("recorded_to", "not-a-datetime"), + ) + for field_name, value in cases: + arguments = dict(valid) + arguments[field_name] = value + with pytest.raises(ValueError): + ValidityStudyRecord(**arguments) + + with pytest.raises(ValueError): + ValidityStudyRecord(**{**valid, "recorded_to": RECORDED_FROM}) + + +def test_valid_record_detaches_times_to_utc() -> None: + offset = timezone.utc + record = ValidityStudyRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + criterion_blueprint_id=CRITERION, + study_status_code="study_draft", + recorded_from=datetime(2026, 11, 3, 9, tzinfo=offset), + recorded_to=datetime(2026, 11, 4, 9, tzinfo=offset), + ) + + assert type(record.recorded_from) is datetime + assert record.recorded_from.tzinfo is timezone.utc + assert record.recorded_to is not None + assert record.recorded_to.tzinfo is timezone.utc From 49662679f5d5e670f18f8bd64253187848532904 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 15:03:28 +0900 Subject: [PATCH 002/603] feat(workforce-validation): add governed study registry read boundary --- .../registry.py | 246 ++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py new file mode 100644 index 000000000..5d38116f8 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -0,0 +1,246 @@ +"""Purpose-bound application boundary for the workforce-validation study registry. + +This module deliberately stops before PostgreSQL. The protected foundation still +stores validity-study tables in the legacy foundation schema, while +``ARCHITECTURE.md`` assigns persistence ownership to ``workforce_validation``. +The application contract therefore depends on an owner repository port instead +of normalizing direct cross-context SQL into a long-lived service contract. +""" + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime, timezone +import re +from typing import Protocol, runtime_checkable +from uuid import UUID +from zoneinfo import ZoneInfo + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +_MAX_UUID_INT = (1 << 128) - 1 +_CODE_PATTERN = re.compile(r"^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$") +_REFERENCE_PATTERN = re.compile(r"^[a-z][a-z0-9_]*:[A-Za-z0-9][A-Za-z0-9._~-]*$") +_SCOPE_PATTERN = re.compile(r"^orgmetra(?:\.[a-z][a-z0-9_]*){2,}$") +_RESOURCE_KIND = "validity_study_record" +_OPERATION = "read" +_READ_FIELDS = frozenset( + { + "criterion_blueprint_id", + "study_status_code", + "recorded_from", + "recorded_to", + } +) + + +class ValidityStudyNotFound(LookupError): + """Indicate that an authorized study identity has no visible registry record.""" + + +class ValidityStudyIntegrityError(RuntimeError): + """Indicate that persistence returned a record outside the authorized target.""" + + +def _require_operational_uuid(field_name: str, value: object) -> UUID: + """Return one exact operational UUID and reject protocol sentinels or subtypes.""" + if type(value) is not UUID or value.int in (0, _MAX_UUID_INT): + raise ValueError(f"{field_name} must be an exact operational UUID.") + return value + + +def _require_code(field_name: str, value: object) -> str: + """Return one exact lower-snake-case code used in an auditable policy request.""" + if type(value) is not str or _CODE_PATTERN.fullmatch(value) is None: + raise ValueError(f"{field_name} must be an exact lower snake_case code.") + return value + + +def _require_aware_datetime(field_name: str, value: object) -> datetime: + """Detach one durable timestamp to exact UTC without arbitrary timezone callbacks.""" + if type(value) is not datetime: + raise ValueError(f"{field_name} must be an exact datetime.") + provider = value.tzinfo + if type(provider) is not timezone and type(provider) is not ZoneInfo: + raise ValueError(f"{field_name} must use a standard-library timezone provider.") + if value.utcoffset() is None: + raise ValueError(f"{field_name} must be timezone-aware.") + return value.astimezone(timezone.utc) + + +def _validate_scope_set(values: object) -> frozenset[str]: + """Require immutable explicit Keyverse scopes before constructing an access request.""" + if type(values) is not frozenset or not values: + raise ValueError("granted_scope_codes must be a non-empty exact frozenset.") + if any(type(value) is not str or _SCOPE_PATTERN.fullmatch(value) is None for value in values): + raise ValueError("granted_scope_codes must contain exact Orgmetra scopes.") + return values + + +def _validate_requested_fields(values: object) -> frozenset[str]: + """Require a non-empty immutable subset of the published registry read fields.""" + if type(values) is not frozenset or not values: + raise ValueError("requested_fields must be a non-empty exact frozenset.") + if any(type(value) is not str for value in values) or not values.issubset(_READ_FIELDS): + raise ValueError("requested_fields contains a field outside the validity-study registry contract.") + return values + + +@dataclass(frozen=True, slots=True) +class ValidationPrincipal: + """Authenticated Keyverse identity attributes needed by the validation context. + + The bearer credential itself never enters this value. ``actor_reference`` is + an opaque namespaced reference and scopes are the already-authenticated token + scopes supplied by the product authentication boundary. + """ + + tenant_record_id: UUID + actor_reference: str + granted_scope_codes: frozenset[str] + + def __post_init__(self) -> None: + """Reject malformed or mutable identity attributes before authorization.""" + _require_operational_uuid("tenant_record_id", self.tenant_record_id) + if type(self.actor_reference) is not str or _REFERENCE_PATTERN.fullmatch(self.actor_reference) is None: + raise ValueError("actor_reference must be an exact namespaced opaque reference.") + _validate_scope_set(self.granted_scope_codes) + + +@dataclass(frozen=True, slots=True) +class ValidityStudyRecord: + """Canonical owner-side projection of one recorded validity-study header. + + This value intentionally contains only fields already represented by the + protected foundation schema. Predictor, sample, decision-policy and analysis + protocol versions are not invented here; Issue #234 owns that later scientific + model increment. + """ + + tenant_record_id: UUID + validity_study_id: UUID + criterion_blueprint_id: UUID + study_status_code: str + recorded_from: datetime + recorded_to: datetime | None + + def __post_init__(self) -> None: + """Detach durable scalar evidence before the application layer exposes it.""" + _require_operational_uuid("tenant_record_id", self.tenant_record_id) + _require_operational_uuid("validity_study_id", self.validity_study_id) + _require_operational_uuid("criterion_blueprint_id", self.criterion_blueprint_id) + _require_code("study_status_code", self.study_status_code) + recorded_from = _require_aware_datetime("recorded_from", self.recorded_from) + recorded_to = ( + None + if self.recorded_to is None + else _require_aware_datetime("recorded_to", self.recorded_to) + ) + if recorded_to is not None and recorded_to <= recorded_from: + raise ValueError("recorded_to must be later than recorded_from.") + object.__setattr__(self, "recorded_from", recorded_from) + object.__setattr__(self, "recorded_to", recorded_to) + + +@dataclass(frozen=True, slots=True) +class ValidityStudyView: + """Field-minimized authorized view returned to the gateway or role workspace.""" + + tenant_record_id: UUID + validity_study_id: UUID + fields: tuple[tuple[str, object], ...] + + +@runtime_checkable +class ValidityStudyReadPort(Protocol): + """Owner repository contract for one tenant-local validity-study header.""" + + def read_validity_study( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + ) -> ValidityStudyRecord | None: + """Return one visible owner record or ``None`` without crossing service tables.""" + ... + + +def read_validity_study( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + purpose_code: str, + requested_fields: frozenset[str], + policy: PurposeBoundAccessPolicy, + read_port: ValidityStudyReadPort, +) -> ValidityStudyView: + """Authorize and read one validity-study header through the canonical owner port. + + Authorization is completed before persistence. The persistence result is then + reconstructed into an exact immutable value and must match the authorized + tenant/study identity before any field is returned. + """ + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + if not isinstance(read_port, ValidityStudyReadPort): + raise TypeError("read_port must implement ValidityStudyReadPort.") + + tenant_id = _require_operational_uuid("tenant_record_id", tenant_record_id) + study_id = _require_operational_uuid("validity_study_id", validity_study_id) + purpose = _require_code("purpose_code", purpose_code) + fields = _validate_requested_fields(requested_fields) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=fields, + granted_scope_codes=principal.granted_scope_codes, + ), + policy=policy, + ) + + persisted = read_port.read_validity_study( + tenant_record_id=tenant_id, + validity_study_id=study_id, + ) + if persisted is None: + raise ValidityStudyNotFound(str(study_id)) + if type(persisted) is not ValidityStudyRecord: + raise ValidityStudyIntegrityError("repository returned a non-canonical validity-study record") + + record = ValidityStudyRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + criterion_blueprint_id=persisted.criterion_blueprint_id, + study_status_code=persisted.study_status_code, + recorded_from=persisted.recorded_from, + recorded_to=persisted.recorded_to, + ) + if record.tenant_record_id != tenant_id or record.validity_study_id != study_id: + raise ValidityStudyIntegrityError("repository returned a validity-study record for another target") + + values = { + "criterion_blueprint_id": record.criterion_blueprint_id, + "study_status_code": record.study_status_code, + "recorded_from": record.recorded_from, + "recorded_to": record.recorded_to, + } + return ValidityStudyView( + tenant_record_id=tenant_id, + validity_study_id=study_id, + fields=tuple((field_name, values[field_name]) for field_name in sorted(fields)), + ) From 3de387e0f2a82cc122f70d2c28343913bb9e55b7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 15:03:48 +0900 Subject: [PATCH 003/603] feat(workforce-validation): export registry owner contract --- .../__init__.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py new file mode 100644 index 000000000..48570a975 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -0,0 +1,21 @@ +"""Canonical workforce-validation application contracts for Orgmetra.""" + +from orgmetra_workforce_validation_api.registry import ( + ValidationPrincipal, + ValidityStudyIntegrityError, + ValidityStudyNotFound, + ValidityStudyReadPort, + ValidityStudyRecord, + ValidityStudyView, + read_validity_study, +) + +__all__ = [ + "ValidationPrincipal", + "ValidityStudyIntegrityError", + "ValidityStudyNotFound", + "ValidityStudyReadPort", + "ValidityStudyRecord", + "ValidityStudyView", + "read_validity_study", +] From 844c3bcf66968e583846a1d08bbea35fee6bbe6b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 15:03:57 +0900 Subject: [PATCH 004/603] build(workforce-validation): define covered service package --- .../workforce-validation-api/pyproject.toml | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 services/workforce-validation-api/pyproject.toml diff --git a/services/workforce-validation-api/pyproject.toml b/services/workforce-validation-api/pyproject.toml new file mode 100644 index 000000000..9a84581c4 --- /dev/null +++ b/services/workforce-validation-api/pyproject.toml @@ -0,0 +1,41 @@ +[build-system] +requires = ["setuptools==82.0.1"] +build-backend = "setuptools.build_meta" + +[project] +name = "orgmetra-workforce-validation-api" +version = "0.1.0" +description = "Purpose-bound owner boundary for Orgmetra workforce-validation studies." +readme = "README.md" +requires-python = ">=3.11" +license = { text = "Apache-2.0" } +authors = [{ name = "ContextualWisdomLab" }] +dependencies = [ + "orgmetra-keyverse-adapter==0.1.0", +] + +[tool.setuptools] +package-dir = {"" = "src"} + +[tool.setuptools.packages.find] +where = ["src"] + +[tool.setuptools.package-data] +orgmetra_workforce_validation_api = ["py.typed"] + +[tool.pytest.ini_options] +testpaths = ["tests"] +addopts = [ + "--cov=orgmetra_workforce_validation_api", + "--cov-branch", + "--cov-report=term-missing", + "--cov-fail-under=100", +] + +[tool.coverage.run] +branch = true +source = ["orgmetra_workforce_validation_api"] + +[tool.coverage.report] +fail_under = 100 +show_missing = true From fbd4d9dd339d794b5736d2a12b453953560af936 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 15:04:11 +0900 Subject: [PATCH 005/603] docs(workforce-validation): document registry owner slice --- services/workforce-validation-api/README.md | 31 +++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 services/workforce-validation-api/README.md diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md new file mode 100644 index 000000000..338f6edc0 --- /dev/null +++ b/services/workforce-validation-api/README.md @@ -0,0 +1,31 @@ +# Orgmetra Workforce Validation API + +This package is the application boundary for the `workforce_validation` bounded context. The first slice exposes one purpose-bound read use case for the existing validity-study registry header. + +It does **not** query People, Talent Acquisition, Performance Management, Job Architecture, Psychometrics Commons, fast-mlsirm, or TEPP tables. Those contexts remain separate owners. Exact foreign identifiers and immutable specialist result references cross the boundary only through published contracts. + +## Current slice + +`read_validity_study(...)`: + +- accepts authenticated Keyverse identity attributes, not credentials; +- evaluates tenant, purpose, operation, scope, resource, and requested fields before persistence; +- calls only a `ValidityStudyReadPort` owned by this context; +- reconstructs and validates durable registry scalars before returning them; +- returns only the fields authorized for the exact study record. + +The repository port is intentionally abstract in this increment. Protected foundation migrations still create the validity-study tables in the legacy foundation schema while `ARCHITECTURE.md` assigns them to the `workforce_validation` schema and database role. A direct `public.validity_study` adapter here would turn that implementation drift into a new long-lived service contract. + +Issue #234 owns the next order: service-owned schema/role, durable PostgreSQL adapter, idempotent registration, explicit predictor/sample/decision-policy/analysis-protocol versions, scientific adapters, OpenAPI/gateway exposure, and realistic p95 measurement. + +## Test + +Once this service is admitted to Foundation CI, its contract is: + +```bash +PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ + python -m pytest -c services/workforce-validation-api/pyproject.toml \ + services/workforce-validation-api/tests +``` + +The package declares 100% owned statement and branch coverage. Until the repository-wide Foundation writer includes this command and the exact head is GREEN, this slice remains Draft evidence rather than shipped product truth. From fbbbbe9a0284c87a99fdc15f70a4cf24f9e0190f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 15:04:22 +0900 Subject: [PATCH 006/603] build(workforce-validation): mark typed package --- .../src/orgmetra_workforce_validation_api/py.typed | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/py.typed diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/py.typed b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/py.typed new file mode 100644 index 000000000..e69de29bb From 3b2fa294b48feaed75240dfae4a9fc16ac87e103 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 15:05:13 +0900 Subject: [PATCH 007/603] test(workforce-validation): remove unreachable timezone branch --- .../src/orgmetra_workforce_validation_api/registry.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py index 5d38116f8..ad7fcd3ed 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -67,8 +67,6 @@ def _require_aware_datetime(field_name: str, value: object) -> datetime: provider = value.tzinfo if type(provider) is not timezone and type(provider) is not ZoneInfo: raise ValueError(f"{field_name} must use a standard-library timezone provider.") - if value.utcoffset() is None: - raise ValueError(f"{field_name} must be timezone-aware.") return value.astimezone(timezone.utc) From b59f9cadfab1d4571efd62d805b9d319f9cb9741 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 15:06:11 +0900 Subject: [PATCH 008/603] test(workforce-validation): cover exact scalar and timezone branches --- .../tests/test_registry.py | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/services/workforce-validation-api/tests/test_registry.py b/services/workforce-validation-api/tests/test_registry.py index 3a80cebd2..e0da59bf2 100644 --- a/services/workforce-validation-api/tests/test_registry.py +++ b/services/workforce-validation-api/tests/test_registry.py @@ -2,8 +2,9 @@ from __future__ import annotations -from datetime import datetime, timezone +from datetime import datetime, timedelta, timezone from uuid import UUID +from zoneinfo import ZoneInfo import pytest @@ -174,9 +175,11 @@ def test_dependency_and_request_types_fail_before_repository_use() -> None: ("tenant_record_id", "not-a-uuid", ValueError), ("validity_study_id", UUID(int=0), ValueError), ("purpose_code", "Validation Review", ValueError), + ("purpose_code", 7, ValueError), ("requested_fields", set({"study_status_code"}), ValueError), ("requested_fields", frozenset(), ValueError), ("requested_fields", frozenset({"unknown_field"}), ValueError), + ("requested_fields", frozenset({7}), ValueError), ): arguments = dict(common) arguments[key] = value @@ -190,8 +193,10 @@ def test_principal_rejects_invalid_identity_and_scope_shapes() -> None: invalid_values = ( dict(tenant_record_id=UUID(int=0), actor_reference="person:analyst-1", granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"})), dict(tenant_record_id=TENANT, actor_reference="not namespaced", granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"})), + dict(tenant_record_id=TENANT, actor_reference=7, granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"})), dict(tenant_record_id=TENANT, actor_reference="person:analyst-1", granted_scope_codes=frozenset()), dict(tenant_record_id=TENANT, actor_reference="person:analyst-1", granted_scope_codes=frozenset({"bad-scope"})), + dict(tenant_record_id=TENANT, actor_reference="person:analyst-1", granted_scope_codes=frozenset({7})), ) for values in invalid_values: with pytest.raises(ValueError): @@ -212,6 +217,7 @@ def test_record_rejects_noncanonical_or_invalid_durable_scalars() -> None: ("validity_study_id", "not-a-uuid"), ("criterion_blueprint_id", UUID(int=(1 << 128) - 1)), ("study_status_code", "Study Draft"), + ("study_status_code", 7), ("recorded_from", datetime(2026, 11, 3)), ("recorded_to", "not-a-datetime"), ) @@ -225,18 +231,19 @@ def test_record_rejects_noncanonical_or_invalid_durable_scalars() -> None: ValidityStudyRecord(**{**valid, "recorded_to": RECORDED_FROM}) -def test_valid_record_detaches_times_to_utc() -> None: - offset = timezone.utc - record = ValidityStudyRecord( - tenant_record_id=TENANT, - validity_study_id=STUDY, - criterion_blueprint_id=CRITERION, - study_status_code="study_draft", - recorded_from=datetime(2026, 11, 3, 9, tzinfo=offset), - recorded_to=datetime(2026, 11, 4, 9, tzinfo=offset), - ) +def test_valid_record_detaches_supported_timezones_to_utc() -> None: + for provider in (timezone(timedelta(hours=9)), ZoneInfo("Asia/Seoul")): + record = ValidityStudyRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + criterion_blueprint_id=CRITERION, + study_status_code="study_draft", + recorded_from=datetime(2026, 11, 3, 9, tzinfo=provider), + recorded_to=datetime(2026, 11, 4, 9, tzinfo=provider), + ) - assert type(record.recorded_from) is datetime - assert record.recorded_from.tzinfo is timezone.utc - assert record.recorded_to is not None - assert record.recorded_to.tzinfo is timezone.utc + assert type(record.recorded_from) is datetime + assert record.recorded_from.tzinfo is timezone.utc + assert record.recorded_from.hour == 0 + assert record.recorded_to is not None + assert record.recorded_to.tzinfo is timezone.utc From b22383c27ec3da6c8111e78fc862363e84399822 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 15:09:02 +0900 Subject: [PATCH 009/603] test(workforce-validation): pin policy scalar runtime integrity --- .../tests/test_policy_runtime_integrity.py | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_policy_runtime_integrity.py diff --git a/services/workforce-validation-api/tests/test_policy_runtime_integrity.py b/services/workforce-validation-api/tests/test_policy_runtime_integrity.py new file mode 100644 index 000000000..b3071641f --- /dev/null +++ b/services/workforce-validation-api/tests/test_policy_runtime_integrity.py @@ -0,0 +1,74 @@ +"""Regression for executable policy scalar values at the validation boundary.""" + +from __future__ import annotations + +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api.registry import ( + ValidationPrincipal, + ValidityStudyReadPort, + read_validity_study, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000c1") + + +class _ExecutableText(str): + """Trip if authorization compares this caller-defined string subtype.""" + + calls = 0 + + def __ne__(self, other: object) -> bool: + """Expose any comparison before the boundary rejects the subtype.""" + type(self).calls += 1 + raise AssertionError("caller-defined policy comparison executed") + + +class _ReadPort: + """Record whether persistence was reached.""" + + def __init__(self) -> None: + self.calls = 0 + + def read_validity_study(self, *, tenant_record_id: UUID, validity_study_id: UUID) -> None: + """Fail the test if a rejected policy reaches persistence.""" + del tenant_record_id, validity_study_id + self.calls += 1 + return None + + +def test_policy_text_subtype_is_rejected_before_comparison_or_persistence() -> None: + _ExecutableText.calls = 0 + port = _ReadPort() + assert isinstance(port, ValidityStudyReadPort) + policy = PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="validation-read-v1", + resource_kind=_ExecutableText("validity_study_record"), + purpose_code="validation_review", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=frozenset({"study_status_code"}), + ) + + with pytest.raises(ValueError, match="policy resource_kind"): + read_validity_study( + principal=ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ), + tenant_record_id=TENANT, + validity_study_id=STUDY, + purpose_code="validation_review", + requested_fields=frozenset({"study_status_code"}), + policy=policy, + read_port=port, + ) + + assert _ExecutableText.calls == 0 + assert port.calls == 0 From 3fe809250c86b328dedf3cb46c3d5953966cfc72 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 15:09:44 +0900 Subject: [PATCH 010/603] fix(workforce-validation): detach exact policy evidence before evaluation --- .../registry.py | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py index ad7fcd3ed..dcdf7386c 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -88,6 +88,50 @@ def _validate_requested_fields(values: object) -> frozenset[str]: return values +def _detach_policy(policy: PurposeBoundAccessPolicy) -> PurposeBoundAccessPolicy: + """Copy policy evidence into exact inert values before any authorization comparison. + + The protected Keyverse adapter accepts subclass-compatible scalar inputs for + backward compatibility. This owner boundary is stricter because a caller- + defined ``str``/``UUID`` subtype could otherwise execute Python behavior when + the evaluator compares or hashes policy attributes. Locals snapshot each + immutable value first; the reconstructed exact policy is the only one used by + authorization. + """ + tenant_record_id = policy.tenant_record_id + policy_version_code = policy.policy_version_code + resource_kind = policy.resource_kind + purpose_code = policy.purpose_code + operation_code = policy.operation_code + required_scope_code = policy.required_scope_code + permitted_fields = policy.permitted_fields + + _require_operational_uuid("policy tenant_record_id", tenant_record_id) + for field_name, value in ( + ("policy_version_code", policy_version_code), + ("resource_kind", resource_kind), + ("purpose_code", purpose_code), + ("operation_code", operation_code), + ("required_scope_code", required_scope_code), + ): + if type(value) is not str: + raise ValueError(f"policy {field_name} must be an exact string.") + if type(permitted_fields) is not frozenset or any( + type(value) is not str for value in permitted_fields + ): + raise ValueError("policy permitted_fields must contain exact strings in an exact frozenset.") + + return PurposeBoundAccessPolicy( + tenant_record_id=tenant_record_id, + policy_version_code=policy_version_code, + resource_kind=resource_kind, + purpose_code=purpose_code, + operation_code=operation_code, + required_scope_code=required_scope_code, + permitted_fields=permitted_fields, + ) + + @dataclass(frozen=True, slots=True) class ValidationPrincipal: """Authenticated Keyverse identity attributes needed by the validation context. @@ -194,6 +238,7 @@ def read_validity_study( study_id = _require_operational_uuid("validity_study_id", validity_study_id) purpose = _require_code("purpose_code", purpose_code) fields = _validate_requested_fields(requested_fields) + detached_policy = _detach_policy(policy) require_purpose_bound_access( request=PurposeBoundAccessRequest( @@ -208,7 +253,7 @@ def read_validity_study( requested_fields=fields, granted_scope_codes=principal.granted_scope_codes, ), - policy=policy, + policy=detached_policy, ) persisted = read_port.read_validity_study( From 2b7cfe47c85138d82737de1a0059b99836d182b3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 15:23:06 +0900 Subject: [PATCH 011/603] test(ci): require workforce validation coverage in foundation --- tests/test_foundation_ci_dependency_hygiene.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_foundation_ci_dependency_hygiene.sh b/tests/test_foundation_ci_dependency_hygiene.sh index 2c0f5087f..d214695fe 100644 --- a/tests/test_foundation_ci_dependency_hygiene.sh +++ b/tests/test_foundation_ci_dependency_hygiene.sh @@ -18,6 +18,7 @@ expected_pythonpaths=( "packages/selection-review/src" "services/job-analysis-api/src:packages/hris-kernel/src:packages/keyverse-adapter/src" "services/people-api/src:packages/hris-kernel/src:packages/keyverse-adapter/src" + "services/workforce-validation-api/src:packages/keyverse-adapter/src" ) if ! grep -Fq -- "${expected_install}" "${workflow_path}"; then From b7e23cb071d678c26b79763ea821e406ab54f2bb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 15:23:29 +0900 Subject: [PATCH 012/603] ci(validation): run workforce validation service coverage --- .github/workflows/foundation-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/foundation-ci.yml b/.github/workflows/foundation-ci.yml index 6b475d6f2..51c98cf30 100644 --- a/.github/workflows/foundation-ci.yml +++ b/.github/workflows/foundation-ci.yml @@ -68,6 +68,7 @@ jobs: PYTHONPATH=packages/selection-review/src COVERAGE_FILE=/tmp/orgmetra-selection-review.coverage python -m pytest -c packages/selection-review/pyproject.toml packages/selection-review/tests PYTHONPATH=services/job-analysis-api/src:packages/hris-kernel/src:packages/keyverse-adapter/src COVERAGE_FILE=/tmp/orgmetra-job-analysis-api.coverage python -m pytest -c services/job-analysis-api/pyproject.toml services/job-analysis-api/tests PYTHONPATH=services/people-api/src:packages/hris-kernel/src:packages/keyverse-adapter/src COVERAGE_FILE=/tmp/orgmetra-people-api.coverage python -m pytest -c services/people-api/pyproject.toml services/people-api/tests + PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src COVERAGE_FILE=/tmp/orgmetra-workforce-validation-api.coverage python -m pytest -c services/workforce-validation-api/pyproject.toml services/workforce-validation-api/tests - name: Run PostgreSQL contracts in isolated containers env: PGPASSWORD: orgmetra From 0daaf12a0785d94f243b36c0c99c1d5358594242 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 15:25:38 +0900 Subject: [PATCH 013/603] test(validation): require structurally immutable study records --- services/workforce-validation-api/tests/test_registry.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/services/workforce-validation-api/tests/test_registry.py b/services/workforce-validation-api/tests/test_registry.py index e0da59bf2..aef2e34d6 100644 --- a/services/workforce-validation-api/tests/test_registry.py +++ b/services/workforce-validation-api/tests/test_registry.py @@ -247,3 +247,12 @@ def test_valid_record_detaches_supported_timezones_to_utc() -> None: assert record.recorded_from.hour == 0 assert record.recorded_to is not None assert record.recorded_to.tzinfo is timezone.utc + + +def test_record_is_structurally_immutable_against_object_setattr() -> None: + record = _record() + + with pytest.raises(AttributeError): + object.__setattr__(record, "study_status_code", "study_closed") + + assert record.study_status_code == "study_draft" From b609b0a46b835e4ba4c7f46f51088c5673dcbdb7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 15:27:17 +0900 Subject: [PATCH 014/603] fix(validation): make study records structurally immutable --- .../registry.py | 91 +++++++++++++------ 1 file changed, 64 insertions(+), 27 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py index dcdf7386c..70d7f73d7 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -153,39 +153,76 @@ def __post_init__(self) -> None: _validate_scope_set(self.granted_scope_codes) -@dataclass(frozen=True, slots=True) -class ValidityStudyRecord: - """Canonical owner-side projection of one recorded validity-study header. - - This value intentionally contains only fields already represented by the - protected foundation schema. Predictor, sample, decision-policy and analysis - protocol versions are not invented here; Issue #234 owns that later scientific - model increment. +class ValidityStudyRecord(tuple): + """Structurally immutable owner projection of one recorded validity-study header. + + The tuple-backed representation prevents a repository adapter that retains an + accepted record from rewriting durable study evidence through + ``object.__setattr__`` after construction. Only fields already represented by + the protected foundation schema are carried here. Predictor, sample, + decision-policy and analysis-protocol versions remain a later scientific-model + increment owned by Issue #234. """ - tenant_record_id: UUID - validity_study_id: UUID - criterion_blueprint_id: UUID - study_status_code: str - recorded_from: datetime - recorded_to: datetime | None + __slots__ = () - def __post_init__(self) -> None: - """Detach durable scalar evidence before the application layer exposes it.""" - _require_operational_uuid("tenant_record_id", self.tenant_record_id) - _require_operational_uuid("validity_study_id", self.validity_study_id) - _require_operational_uuid("criterion_blueprint_id", self.criterion_blueprint_id) - _require_code("study_status_code", self.study_status_code) - recorded_from = _require_aware_datetime("recorded_from", self.recorded_from) - recorded_to = ( + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + criterion_blueprint_id: UUID, + study_status_code: str, + recorded_from: datetime, + recorded_to: datetime | None, + ) -> ValidityStudyRecord: + """Validate and detach durable scalars before creating the immutable tuple.""" + tenant_id = _require_operational_uuid("tenant_record_id", tenant_record_id) + study_id = _require_operational_uuid("validity_study_id", validity_study_id) + criterion_id = _require_operational_uuid("criterion_blueprint_id", criterion_blueprint_id) + status_code = _require_code("study_status_code", study_status_code) + recorded_start = _require_aware_datetime("recorded_from", recorded_from) + recorded_end = ( None - if self.recorded_to is None - else _require_aware_datetime("recorded_to", self.recorded_to) + if recorded_to is None + else _require_aware_datetime("recorded_to", recorded_to) ) - if recorded_to is not None and recorded_to <= recorded_from: + if recorded_end is not None and recorded_end <= recorded_start: raise ValueError("recorded_to must be later than recorded_from.") - object.__setattr__(self, "recorded_from", recorded_from) - object.__setattr__(self, "recorded_to", recorded_to) + return tuple.__new__( + cls, + (tenant_id, study_id, criterion_id, status_code, recorded_start, recorded_end), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return the tenant that owns this validity study.""" + return self[0] + + @property + def validity_study_id(self) -> UUID: + """Return the stable validity-study identity.""" + return self[1] + + @property + def criterion_blueprint_id(self) -> UUID: + """Return the criterion blueprint linked to the study header.""" + return self[2] + + @property + def study_status_code(self) -> str: + """Return the governed study lifecycle status code.""" + return self[3] + + @property + def recorded_from(self) -> datetime: + """Return the exact UTC instant when this version became recorded truth.""" + return self[4] + + @property + def recorded_to(self) -> datetime | None: + """Return the exact UTC close instant when present.""" + return self[5] @dataclass(frozen=True, slots=True) From 8c50d7d4517781c5a3801bc2c11b3ee077068341 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 15:32:10 +0900 Subject: [PATCH 015/603] fix(ci): seal workforce validation workflow manifest --- manifest.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/manifest.json b/manifest.json index f7b6cf55e..7fbc02bec 100644 --- a/manifest.json +++ b/manifest.json @@ -5,9 +5,9 @@ "files": [ { "path": ".github/workflows/foundation-ci.yml", - "sha256": "b6a4365936b66803a8112f034c77d53d33301a7a798ed4f68746a4f2d8b081d7", - "bytes": 6651, - "lines": 125 + "sha256": "80b9e4c1b2c6c04983f195cd3b4ec3760d30fe15317cbcfcd5c6ba57089024cc", + "bytes": 6911, + "lines": 126 }, { "path": ".gitignore", From cf498b96c0308e5037ebe11441e77c3677b0bdac Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 15:33:08 +0900 Subject: [PATCH 016/603] docs(validation): keep Foundation acceptance state current --- services/workforce-validation-api/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 338f6edc0..593c2f8db 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -11,7 +11,7 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar - accepts authenticated Keyverse identity attributes, not credentials; - evaluates tenant, purpose, operation, scope, resource, and requested fields before persistence; - calls only a `ValidityStudyReadPort` owned by this context; -- reconstructs and validates durable registry scalars before returning them; +- reconstructs persisted registry scalars into structurally immutable owner evidence before target validation and output; - returns only the fields authorized for the exact study record. The repository port is intentionally abstract in this increment. Protected foundation migrations still create the validity-study tables in the legacy foundation schema while `ARCHITECTURE.md` assigns them to the `workforce_validation` schema and database role. A direct `public.validity_study` adapter here would turn that implementation drift into a new long-lived service contract. @@ -20,12 +20,13 @@ Issue #234 owns the next order: service-owned schema/role, durable PostgreSQL ad ## Test -Once this service is admitted to Foundation CI, its contract is: +The Draft branch is admitted to the canonical Foundation quality workflow with the same hash-locked test toolchain and direct source-tree dependency policy used by the existing owner services: ```bash PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ + COVERAGE_FILE=/tmp/orgmetra-workforce-validation-api.coverage \ python -m pytest -c services/workforce-validation-api/pyproject.toml \ services/workforce-validation-api/tests ``` -The package declares 100% owned statement and branch coverage. Until the repository-wide Foundation writer includes this command and the exact head is GREEN, this slice remains Draft evidence rather than shipped product truth. +The package declares 100% owned statement and branch coverage. Source-level workflow admission is not acceptance evidence by itself: this slice remains Draft until that command and the repository gates are terminal GREEN on the exact current head and qualifying independent review is satisfied. From 38536298b0da4969262c232305af19628328005c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 16:08:40 +0900 Subject: [PATCH 017/603] test(workforce-validation): reject retained principal rewrites --- .../tests/test_registry.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/services/workforce-validation-api/tests/test_registry.py b/services/workforce-validation-api/tests/test_registry.py index aef2e34d6..02b8661f1 100644 --- a/services/workforce-validation-api/tests/test_registry.py +++ b/services/workforce-validation-api/tests/test_registry.py @@ -203,6 +203,22 @@ def test_principal_rejects_invalid_identity_and_scope_shapes() -> None: ValidationPrincipal(**values) +def test_principal_is_structurally_immutable_after_identity_validation() -> None: + principal = _principal() + + for field_name, replacement in ( + ("tenant_record_id", OTHER_TENANT), + ("actor_reference", "person:attacker-2"), + ("granted_scope_codes", frozenset({"orgmetra.audit.read"})), + ): + with pytest.raises(AttributeError): + object.__setattr__(principal, field_name, replacement) + + assert principal.tenant_record_id == TENANT + assert principal.actor_reference == "person:analyst-1" + assert principal.granted_scope_codes == frozenset({"orgmetra.workforce_validation.read"}) + + def test_record_rejects_noncanonical_or_invalid_durable_scalars() -> None: valid = dict( tenant_record_id=TENANT, From e0ff34701967d7b4c29c13f42b3989e05f68dbab Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 16:09:31 +0900 Subject: [PATCH 018/603] fix(workforce-validation): make principal evidence immutable --- .../registry.py | 47 +++++++++++++------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py index 70d7f73d7..523aef548 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -132,25 +132,44 @@ def _detach_policy(policy: PurposeBoundAccessPolicy) -> PurposeBoundAccessPolicy ) -@dataclass(frozen=True, slots=True) -class ValidationPrincipal: - """Authenticated Keyverse identity attributes needed by the validation context. +class ValidationPrincipal(tuple): + """Structurally immutable authenticated Keyverse attributes for validation reads. - The bearer credential itself never enters this value. ``actor_reference`` is - an opaque namespaced reference and scopes are the already-authenticated token - scopes supplied by the product authentication boundary. + The bearer credential itself never enters this value. Tuple-backed storage + prevents a retained caller reference from rewriting tenant, actor, or scope + evidence through ``object.__setattr__`` after constructor validation. """ - tenant_record_id: UUID - actor_reference: str - granted_scope_codes: frozenset[str] + __slots__ = () - def __post_init__(self) -> None: - """Reject malformed or mutable identity attributes before authorization.""" - _require_operational_uuid("tenant_record_id", self.tenant_record_id) - if type(self.actor_reference) is not str or _REFERENCE_PATTERN.fullmatch(self.actor_reference) is None: + def __new__( + cls, + *, + tenant_record_id: UUID, + actor_reference: str, + granted_scope_codes: frozenset[str], + ) -> ValidationPrincipal: + """Validate exact identity evidence before creating the immutable principal.""" + tenant_id = _require_operational_uuid("tenant_record_id", tenant_record_id) + if type(actor_reference) is not str or _REFERENCE_PATTERN.fullmatch(actor_reference) is None: raise ValueError("actor_reference must be an exact namespaced opaque reference.") - _validate_scope_set(self.granted_scope_codes) + scope_codes = _validate_scope_set(granted_scope_codes) + return tuple.__new__(cls, (tenant_id, actor_reference, scope_codes)) + + @property + def tenant_record_id(self) -> UUID: + """Return the authenticated tenant identity.""" + return self[0] + + @property + def actor_reference(self) -> str: + """Return the opaque authenticated actor reference.""" + return self[1] + + @property + def granted_scope_codes(self) -> frozenset[str]: + """Return the immutable authenticated scope set.""" + return self[2] class ValidityStudyRecord(tuple): From d42eb025c96630f81fc0ae69ea12335110b43691 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 16:10:11 +0900 Subject: [PATCH 019/603] test(workforce-validation): require owner persistence boundary --- .../tests/test_persistence_layout.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_persistence_layout.py diff --git a/services/workforce-validation-api/tests/test_persistence_layout.py b/services/workforce-validation-api/tests/test_persistence_layout.py new file mode 100644 index 000000000..aba6931fd --- /dev/null +++ b/services/workforce-validation-api/tests/test_persistence_layout.py @@ -0,0 +1,32 @@ +"""Architecture contract for workforce-validation-owned PostgreSQL persistence.""" + +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[3] +MIGRATION = ROOT / "services/workforce-validation-api/database/migrations/0001_owner_schema.sql" + + +def test_owner_schema_migration_establishes_deny_default_role_boundary() -> None: + """Require a service-owned schema and least-privilege database role before adapters.""" + sql = MIGRATION.read_text(encoding="utf-8") + + required = ( + "CREATE ROLE workforce_validation_role NOLOGIN", + "CREATE SCHEMA workforce_validation AUTHORIZATION workforce_validation_role", + "REVOKE ALL ON SCHEMA workforce_validation FROM PUBLIC", + "ALTER ROLE workforce_validation_role SET search_path = workforce_validation, pg_catalog", + ) + for contract in required: + assert contract in sql + + assert "CREATE TABLE" not in sql + assert "public.validity_study" not in sql + assert "GRANT ALL" not in sql + + +def test_owner_migration_history_is_bounded_context_local() -> None: + """Prevent a new global migration number from colliding with other active lanes.""" + relative_path = MIGRATION.relative_to(ROOT).as_posix() + + assert relative_path == "services/workforce-validation-api/database/migrations/0001_owner_schema.sql" From 9dfeca7a7eb77d9df1f900ac28c30663630cc13d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 16:10:30 +0900 Subject: [PATCH 020/603] feat(workforce-validation): establish owner schema and role --- .../database/migrations/0001_owner_schema.sql | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 services/workforce-validation-api/database/migrations/0001_owner_schema.sql diff --git a/services/workforce-validation-api/database/migrations/0001_owner_schema.sql b/services/workforce-validation-api/database/migrations/0001_owner_schema.sql new file mode 100644 index 000000000..3d24b9847 --- /dev/null +++ b/services/workforce-validation-api/database/migrations/0001_owner_schema.sql @@ -0,0 +1,24 @@ +-- Establish the logical PostgreSQL ownership boundary for workforce_validation. +-- This migration intentionally creates no application table. Legacy foundation +-- validity-study tables stay untouched until an explicit forward-only adoption +-- migration can preserve existing foreign-key and acceptance contracts. + +BEGIN; + +CREATE ROLE workforce_validation_role NOLOGIN + NOSUPERUSER + NOCREATEDB + NOCREATEROLE + NOINHERIT + NOREPLICATION + NOBYPASSRLS; + +CREATE SCHEMA workforce_validation AUTHORIZATION workforce_validation_role; +REVOKE ALL ON SCHEMA workforce_validation FROM PUBLIC; + +-- Any login role granted this owner role resolves only owner objects and the +-- PostgreSQL catalog by default. Cross-context application tables are never put +-- on the implicit search path. +ALTER ROLE workforce_validation_role SET search_path = workforce_validation, pg_catalog; + +COMMIT; From d264b89dad290887d265a1010ff2622b96f9909a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 16:11:00 +0900 Subject: [PATCH 021/603] docs(workforce-validation): record owner persistence bootstrap --- services/workforce-validation-api/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 593c2f8db..945f2dea6 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -1,6 +1,6 @@ # Orgmetra Workforce Validation API -This package is the application boundary for the `workforce_validation` bounded context. The first slice exposes one purpose-bound read use case for the existing validity-study registry header. +This package is the application boundary for the `workforce_validation` bounded context. The current slice exposes one purpose-bound read use case for the existing validity-study registry header and establishes the context-local PostgreSQL ownership bootstrap. It does **not** query People, Talent Acquisition, Performance Management, Job Architecture, Psychometrics Commons, fast-mlsirm, or TEPP tables. Those contexts remain separate owners. Exact foreign identifiers and immutable specialist result references cross the boundary only through published contracts. @@ -8,15 +8,15 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar `read_validity_study(...)`: -- accepts authenticated Keyverse identity attributes, not credentials; +- accepts structurally immutable authenticated Keyverse identity attributes, not credentials; - evaluates tenant, purpose, operation, scope, resource, and requested fields before persistence; - calls only a `ValidityStudyReadPort` owned by this context; - reconstructs persisted registry scalars into structurally immutable owner evidence before target validation and output; - returns only the fields authorized for the exact study record. -The repository port is intentionally abstract in this increment. Protected foundation migrations still create the validity-study tables in the legacy foundation schema while `ARCHITECTURE.md` assigns them to the `workforce_validation` schema and database role. A direct `public.validity_study` adapter here would turn that implementation drift into a new long-lived service contract. +`services/workforce-validation-api/database/migrations/0001_owner_schema.sql` starts this bounded context's own migration history. It creates the `workforce_validation` schema and `workforce_validation_role`, revokes public schema access, and limits the role's default search path to the owner schema plus `pg_catalog`. It intentionally creates or moves no application table yet. Protected foundation migrations still create validity-study tables in the legacy foundation schema, so the next forward-only persistence increment must adopt those records without normalizing `public.validity_study` as a long-lived service contract or breaking existing linkage evidence. -Issue #234 owns the next order: service-owned schema/role, durable PostgreSQL adapter, idempotent registration, explicit predictor/sample/decision-policy/analysis-protocol versions, scientific adapters, OpenAPI/gateway exposure, and realistic p95 measurement. +Issue #234 owns the remaining order: PostgreSQL-backed owner-schema acceptance and durable adapter, idempotent registration, explicit predictor/sample/decision-policy/analysis-protocol versions, scientific adapters, OpenAPI/gateway exposure, and realistic p95 measurement. Issue #237 separately tracks the authenticated-principal structural-immutability repair until exact-head acceptance and protected integration. ## Test @@ -29,4 +29,4 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ services/workforce-validation-api/tests ``` -The package declares 100% owned statement and branch coverage. Source-level workflow admission is not acceptance evidence by itself: this slice remains Draft until that command and the repository gates are terminal GREEN on the exact current head and qualifying independent review is satisfied. +The package declares 100% owned statement and branch coverage. The current test suite also seals the location and deny-default shape of the bounded-context-local owner-schema migration. Source-level workflow admission and static migration contract are not PostgreSQL acceptance evidence by themselves: this slice remains Draft until the exact current head has terminal owner coverage, required security/review evidence, and a PostgreSQL-backed owner-schema contract before any durable adapter is treated as production-ready. From 5d4da09cd1fd899987299443501837674f4565d8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 16:18:06 +0900 Subject: [PATCH 022/603] test(workforce-validation): require PostgreSQL owner-schema acceptance --- .../tests/test_persistence_layout.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/services/workforce-validation-api/tests/test_persistence_layout.py b/services/workforce-validation-api/tests/test_persistence_layout.py index aba6931fd..70001cde6 100644 --- a/services/workforce-validation-api/tests/test_persistence_layout.py +++ b/services/workforce-validation-api/tests/test_persistence_layout.py @@ -5,6 +5,8 @@ ROOT = Path(__file__).resolve().parents[3] MIGRATION = ROOT / "services/workforce-validation-api/database/migrations/0001_owner_schema.sql" +FOUNDATION_WORKFLOW = ROOT / ".github/workflows/foundation-ci.yml" +OWNER_SCHEMA_POSTGRES_CONTRACT = "test_workforce_validation_owner_schema_postgres.sh" def test_owner_schema_migration_establishes_deny_default_role_boundary() -> None: @@ -30,3 +32,10 @@ def test_owner_migration_history_is_bounded_context_local() -> None: relative_path = MIGRATION.relative_to(ROOT).as_posix() assert relative_path == "services/workforce-validation-api/database/migrations/0001_owner_schema.sql" + + +def test_owner_schema_postgres_contract_is_admitted_to_foundation() -> None: + """Require the owner-schema bootstrap to execute in the canonical PostgreSQL matrix.""" + workflow = FOUNDATION_WORKFLOW.read_text(encoding="utf-8") + + assert OWNER_SCHEMA_POSTGRES_CONTRACT in workflow From d67abe75028a18a9703be1372ea2cc37864b5b5a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 16:18:34 +0900 Subject: [PATCH 023/603] test(workforce-validation): execute owner schema boundary --- ...kforce_validation_owner_schema_postgres.sh | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 tests/test_workforce_validation_owner_schema_postgres.sh diff --git a/tests/test_workforce_validation_owner_schema_postgres.sh b/tests/test_workforce_validation_owner_schema_postgres.sh new file mode 100644 index 000000000..019f201b6 --- /dev/null +++ b/tests/test_workforce_validation_owner_schema_postgres.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +set -euo pipefail + +: "${DATABASE_URL:=postgresql://orgmetra:orgmetra@localhost:5432/orgmetra}" + +migration="services/workforce-validation-api/database/migrations/0001_owner_schema.sql" +psql "${DATABASE_URL}" -v ON_ERROR_STOP=1 -f "${migration}" + +role_flags="$(psql "${DATABASE_URL}" -v ON_ERROR_STOP=1 -Atqc " +SELECT rolcanlogin, rolsuper, rolcreatedb, rolcreaterole, rolinherit, rolreplication, rolbypassrls +FROM pg_roles +WHERE rolname = 'workforce_validation_role'; +")" +if [[ "${role_flags}" != "f|f|f|f|f|f|f" ]]; then + echo "workforce_validation_role flags are not deny-default: ${role_flags}" >&2 + exit 1 +fi + +schema_owner="$(psql "${DATABASE_URL}" -v ON_ERROR_STOP=1 -Atqc " +SELECT pg_get_userbyid(nspowner) +FROM pg_namespace +WHERE nspname = 'workforce_validation'; +")" +if [[ "${schema_owner}" != "workforce_validation_role" ]]; then + echo "workforce_validation schema has unexpected owner: ${schema_owner}" >&2 + exit 1 +fi + +role_config="$(psql "${DATABASE_URL}" -v ON_ERROR_STOP=1 -Atqc " +SELECT array_to_string(rolconfig, ',') +FROM pg_roles +WHERE rolname = 'workforce_validation_role'; +")" +if [[ "${role_config}" != "search_path=workforce_validation, pg_catalog" ]]; then + echo "workforce_validation_role search_path is not owner-local: ${role_config}" >&2 + exit 1 +fi + +psql "${DATABASE_URL}" -v ON_ERROR_STOP=1 -qc "CREATE ROLE workforce_validation_public_probe NOLOGIN;" +trap 'psql "${DATABASE_URL}" -v ON_ERROR_STOP=1 -qc "DROP ROLE IF EXISTS workforce_validation_public_probe;" >/dev/null 2>&1 || true' EXIT + +public_usage="$(psql "${DATABASE_URL}" -v ON_ERROR_STOP=1 -Atqc " +SELECT has_schema_privilege('workforce_validation_public_probe', 'workforce_validation', 'USAGE'); +")" +public_create="$(psql "${DATABASE_URL}" -v ON_ERROR_STOP=1 -Atqc " +SELECT has_schema_privilege('workforce_validation_public_probe', 'workforce_validation', 'CREATE'); +")" +if [[ "${public_usage}" != "f" || "${public_create}" != "f" ]]; then + echo "PUBLIC retains workforce_validation schema privileges: usage=${public_usage} create=${public_create}" >&2 + exit 1 +fi + +relation_count="$(psql "${DATABASE_URL}" -v ON_ERROR_STOP=1 -Atqc " +SELECT count(*) +FROM pg_class AS relation +JOIN pg_namespace AS namespace ON namespace.oid = relation.relnamespace +WHERE namespace.nspname = 'workforce_validation'; +")" +if [[ "${relation_count}" != "0" ]]; then + echo "owner-schema bootstrap created application relations prematurely: ${relation_count}" >&2 + exit 1 +fi + +psql "${DATABASE_URL}" -v ON_ERROR_STOP=1 -qc "DROP ROLE workforce_validation_public_probe;" +trap - EXIT From 6970b8c76b9487ccc617cd9e7ce076c0d401c706 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 16:19:11 +0900 Subject: [PATCH 024/603] ci(workforce-validation): execute owner schema contract --- .github/workflows/foundation-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/foundation-ci.yml b/.github/workflows/foundation-ci.yml index 51c98cf30..4f6d05360 100644 --- a/.github/workflows/foundation-ci.yml +++ b/.github/workflows/foundation-ci.yml @@ -84,6 +84,7 @@ jobs: test_audit_outbox_hardening_postgres.sh test_candidate_worker_conversion_postgres.sh test_validity_study_case_postgres.sh + test_workforce_validation_owner_schema_postgres.sh test_criterion_observation_scope_postgres.sh test_people_mutation_idempotency_postgres.sh test_job_analysis_snapshot_postgres.sh From a0ccaf0afc1fa26ed979a5181e05c08140f92aff Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 16:21:42 +0900 Subject: [PATCH 025/603] fix(ci): reseal workforce validation owner-schema contract --- manifest.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/manifest.json b/manifest.json index 7fbc02bec..b46eb3605 100644 --- a/manifest.json +++ b/manifest.json @@ -5,9 +5,9 @@ "files": [ { "path": ".github/workflows/foundation-ci.yml", - "sha256": "80b9e4c1b2c6c04983f195cd3b4ec3760d30fe15317cbcfcd5c6ba57089024cc", - "bytes": 6911, - "lines": 126 + "sha256": "31c6a46cb81513cdaa2a08eed5cb00a57d8b36f15e3c772d230452cdc3329aed", + "bytes": 6974, + "lines": 127 }, { "path": ".gitignore", @@ -83,7 +83,7 @@ }, { "path": "database/migrations/0005_outbox_delivery_finalization.sql", - "sha256": "b7e8790595b288f752d6ef5cc6cbfe4e1b6712248f5b7a3a25fa60016b6a4961", + "sha256": "b7e8790595b288f752d6ef5cc6cbfe4e1b6712248f5ef9e8a92abba5c3cf182", "bytes": 6125, "lines": 170 }, From 83e5c9418f912878f0b829df24c7bf19a11e2b83 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 16:23:17 +0900 Subject: [PATCH 026/603] fix(ci): restore unrelated manifest seal --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index b46eb3605..fbae55b2a 100644 --- a/manifest.json +++ b/manifest.json @@ -83,7 +83,7 @@ }, { "path": "database/migrations/0005_outbox_delivery_finalization.sql", - "sha256": "b7e8790595b288f752d6ef5cc6cbfe4e1b6712248f5ef9e8a92abba5c3cf182", + "sha256": "b7e8790595b288f752d6ef5cc6cbfe4e1b6712248f5b7a3a25fa60016b6a4961", "bytes": 6125, "lines": 170 }, From 7ca30f3447169e678269124dbf1fd23180b997b9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 16:23:56 +0900 Subject: [PATCH 027/603] docs(workforce-validation): record PostgreSQL owner-schema gate --- services/workforce-validation-api/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 945f2dea6..11885a8a9 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -16,7 +16,7 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar `services/workforce-validation-api/database/migrations/0001_owner_schema.sql` starts this bounded context's own migration history. It creates the `workforce_validation` schema and `workforce_validation_role`, revokes public schema access, and limits the role's default search path to the owner schema plus `pg_catalog`. It intentionally creates or moves no application table yet. Protected foundation migrations still create validity-study tables in the legacy foundation schema, so the next forward-only persistence increment must adopt those records without normalizing `public.validity_study` as a long-lived service contract or breaking existing linkage evidence. -Issue #234 owns the remaining order: PostgreSQL-backed owner-schema acceptance and durable adapter, idempotent registration, explicit predictor/sample/decision-policy/analysis-protocol versions, scientific adapters, OpenAPI/gateway exposure, and realistic p95 measurement. Issue #237 separately tracks the authenticated-principal structural-immutability repair until exact-head acceptance and protected integration. +Issue #234 owns the remaining order: durable owner-schema adoption and PostgreSQL adapter, idempotent registration, explicit predictor/sample/decision-policy/analysis-protocol versions, scientific adapters, OpenAPI/gateway exposure, and realistic p95 measurement. Issue #237 separately tracks the authenticated-principal structural-immutability repair until exact-head acceptance and protected integration. ## Test @@ -29,4 +29,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ services/workforce-validation-api/tests ``` -The package declares 100% owned statement and branch coverage. The current test suite also seals the location and deny-default shape of the bounded-context-local owner-schema migration. Source-level workflow admission and static migration contract are not PostgreSQL acceptance evidence by themselves: this slice remains Draft until the exact current head has terminal owner coverage, required security/review evidence, and a PostgreSQL-backed owner-schema contract before any durable adapter is treated as production-ready. +The same Foundation job now also runs `tests/test_workforce_validation_owner_schema_postgres.sh` in its own pinned PostgreSQL 16.14 container. That contract executes the service-local owner migration and checks the exact role flags, schema owner, role search path, absence of inherited PUBLIC `USAGE`/`CREATE`, and absence of application relations in the bootstrap schema. The workflow manifest is resealed after admitting this contract. + +Those source contracts are not terminal acceptance by themselves. The slice remains Draft until the exact current head actually executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and the normal review/governance requirements are satisfied. Only then may the next forward-only owner-table adoption and durable adapter be treated as eligible for integration. From f63c6e164c5a2534538e83b87968d4d94228ebfa Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 16:32:51 +0900 Subject: [PATCH 028/603] test(workforce-validation): reject NOLOGIN search-path default --- .../workforce-validation-api/tests/test_persistence_layout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_persistence_layout.py b/services/workforce-validation-api/tests/test_persistence_layout.py index 70001cde6..cf77b6bdc 100644 --- a/services/workforce-validation-api/tests/test_persistence_layout.py +++ b/services/workforce-validation-api/tests/test_persistence_layout.py @@ -17,11 +17,11 @@ def test_owner_schema_migration_establishes_deny_default_role_boundary() -> None "CREATE ROLE workforce_validation_role NOLOGIN", "CREATE SCHEMA workforce_validation AUTHORIZATION workforce_validation_role", "REVOKE ALL ON SCHEMA workforce_validation FROM PUBLIC", - "ALTER ROLE workforce_validation_role SET search_path = workforce_validation, pg_catalog", ) for contract in required: assert contract in sql + assert "ALTER ROLE workforce_validation_role SET search_path" not in sql assert "CREATE TABLE" not in sql assert "public.validity_study" not in sql assert "GRANT ALL" not in sql From 7dad37bf9f5ded39b2224597d0fa9c2617f52361 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 16:33:02 +0900 Subject: [PATCH 029/603] test(workforce-validation): exercise SET ROLE search-path semantics --- ...orkforce_validation_owner_schema_postgres.sh | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tests/test_workforce_validation_owner_schema_postgres.sh b/tests/test_workforce_validation_owner_schema_postgres.sh index 019f201b6..c79b659c8 100644 --- a/tests/test_workforce_validation_owner_schema_postgres.sh +++ b/tests/test_workforce_validation_owner_schema_postgres.sh @@ -27,12 +27,23 @@ if [[ "${schema_owner}" != "workforce_validation_role" ]]; then fi role_config="$(psql "${DATABASE_URL}" -v ON_ERROR_STOP=1 -Atqc " -SELECT array_to_string(rolconfig, ',') +SELECT COALESCE(array_to_string(rolconfig, ','), '') FROM pg_roles WHERE rolname = 'workforce_validation_role'; ")" -if [[ "${role_config}" != "search_path=workforce_validation, pg_catalog" ]]; then - echo "workforce_validation_role search_path is not owner-local: ${role_config}" >&2 +if [[ -n "${role_config}" ]]; then + echo "NOLOGIN schema owner must not carry ineffective login-only runtime defaults: ${role_config}" >&2 + exit 1 +fi + +set_role_probe="$(psql "${DATABASE_URL}" -v ON_ERROR_STOP=1 -Atqc " +SET search_path = public; +SET ROLE workforce_validation_role; +SELECT current_user || '|' || current_setting('search_path'); +RESET ROLE; +")" +if [[ "${set_role_probe}" != "workforce_validation_role|public" ]]; then + echo "unexpected SET ROLE search_path behavior: ${set_role_probe}" >&2 exit 1 fi From fd87b719bd581a64ca84ca679530e264ed6f167f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 16:33:12 +0900 Subject: [PATCH 030/603] fix(workforce-validation): remove ineffective owner search-path default --- .../database/migrations/0001_owner_schema.sql | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/services/workforce-validation-api/database/migrations/0001_owner_schema.sql b/services/workforce-validation-api/database/migrations/0001_owner_schema.sql index 3d24b9847..67a1e3c38 100644 --- a/services/workforce-validation-api/database/migrations/0001_owner_schema.sql +++ b/services/workforce-validation-api/database/migrations/0001_owner_schema.sql @@ -16,9 +16,12 @@ CREATE ROLE workforce_validation_role NOLOGIN CREATE SCHEMA workforce_validation AUTHORIZATION workforce_validation_role; REVOKE ALL ON SCHEMA workforce_validation FROM PUBLIC; --- Any login role granted this owner role resolves only owner objects and the --- PostgreSQL catalog by default. Cross-context application tables are never put --- on the implicit search path. -ALTER ROLE workforce_validation_role SET search_path = workforce_validation, pg_catalog; +-- workforce_validation_role is a migration/schema-owner identity only. Runtime +-- principals must not be granted this owner role. PostgreSQL role-level GUC +-- defaults apply at login and are not re-applied by SET ROLE; because this role +-- is NOLOGIN, an ALTER ROLE ... SET search_path entry would not provide runtime +-- isolation. Future runtime adapters must use a distinct least-privilege role, +-- schema-qualified owner relations, and explicit function-level search_path for +-- any SECURITY DEFINER code. COMMIT; From a04c8b4cd58145f9e74a085d3fdb037d90966012 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 16:33:28 +0900 Subject: [PATCH 031/603] docs(workforce-validation): correct owner-role search-path contract --- services/workforce-validation-api/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 11885a8a9..1e0ea265b 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -14,9 +14,11 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar - reconstructs persisted registry scalars into structurally immutable owner evidence before target validation and output; - returns only the fields authorized for the exact study record. -`services/workforce-validation-api/database/migrations/0001_owner_schema.sql` starts this bounded context's own migration history. It creates the `workforce_validation` schema and `workforce_validation_role`, revokes public schema access, and limits the role's default search path to the owner schema plus `pg_catalog`. It intentionally creates or moves no application table yet. Protected foundation migrations still create validity-study tables in the legacy foundation schema, so the next forward-only persistence increment must adopt those records without normalizing `public.validity_study` as a long-lived service contract or breaking existing linkage evidence. +`services/workforce-validation-api/database/migrations/0001_owner_schema.sql` starts this bounded context's own migration history. It creates the `workforce_validation` schema and deny-default `workforce_validation_role`, revokes public schema access, and intentionally creates or moves no application table yet. The role is a **NOLOGIN migration/schema owner only**; runtime principals must not be granted that owner role. PostgreSQL applies role-level configuration defaults at login and does not re-apply them on `SET ROLE`, so an `ALTER ROLE ... SET search_path` entry on this NOLOGIN role is not treated as a runtime isolation control. The later durable adapter must use a distinct least-privilege runtime role, schema-qualified `workforce_validation` relations, and explicit function-level `search_path` where `SECURITY DEFINER` code is introduced. -Issue #234 owns the remaining order: durable owner-schema adoption and PostgreSQL adapter, idempotent registration, explicit predictor/sample/decision-policy/analysis-protocol versions, scientific adapters, OpenAPI/gateway exposure, and realistic p95 measurement. Issue #237 separately tracks the authenticated-principal structural-immutability repair until exact-head acceptance and protected integration. +Protected foundation migrations still create validity-study tables in the legacy foundation schema, so the next forward-only persistence increment must adopt those records without normalizing `public.validity_study` as a long-lived service contract or breaking existing linkage evidence. + +Issue #234 owns the remaining order: durable owner-schema adoption and PostgreSQL adapter, idempotent registration, explicit predictor/sample/decision-policy/analysis-protocol versions, scientific adapters, OpenAPI/gateway exposure, and realistic p95 measurement. Issues #236/#237 track structural immutability of persisted study and authenticated principal evidence; #238 tracks the owner-role/runtime-search-path boundary until exact-head acceptance and protected integration. ## Test @@ -29,6 +31,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ services/workforce-validation-api/tests ``` -The same Foundation job now also runs `tests/test_workforce_validation_owner_schema_postgres.sh` in its own pinned PostgreSQL 16.14 container. That contract executes the service-local owner migration and checks the exact role flags, schema owner, role search path, absence of inherited PUBLIC `USAGE`/`CREATE`, and absence of application relations in the bootstrap schema. The workflow manifest is resealed after admitting this contract. +The same Foundation job also runs `tests/test_workforce_validation_owner_schema_postgres.sh` in its own pinned PostgreSQL 16.14 container. That contract executes the service-local owner migration and checks the exact deny-default role flags, schema owner, absence of ineffective login-only `rolconfig`, actual `SET ROLE` search-path behavior, absence of inherited PUBLIC `USAGE`/`CREATE`, and absence of application relations in the bootstrap schema. The test intentionally demonstrates that `SET ROLE` retains the caller's existing `search_path`; runtime isolation therefore cannot be inferred from owner-role metadata. Those source contracts are not terminal acceptance by themselves. The slice remains Draft until the exact current head actually executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and the normal review/governance requirements are satisfied. Only then may the next forward-only owner-table adoption and durable adapter be treated as eligible for integration. From 60f5ba9d1b43ba75fd2d7f042153f7b43eff902b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 17:02:03 +0900 Subject: [PATCH 032/603] test(workforce-validation): reject forged principal storage before auth --- .../tests/test_principal_storage_integrity.py | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_principal_storage_integrity.py diff --git a/services/workforce-validation-api/tests/test_principal_storage_integrity.py b/services/workforce-validation-api/tests/test_principal_storage_integrity.py new file mode 100644 index 000000000..9473a5b1b --- /dev/null +++ b/services/workforce-validation-api/tests/test_principal_storage_integrity.py @@ -0,0 +1,83 @@ +"""Regression contract for canonical validation-principal storage before authorization.""" + +from __future__ import annotations + +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api.registry import ( + ValidationPrincipal, + ValidityStudyRecord, + read_validity_study, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000c1") + + +class _ExecutableUUID(UUID): + """Expose executable behavior if a UUID subtype reaches downstream validation.""" + + def __getattribute__(self, name: str) -> object: + if name == "int": + raise AssertionError("UUID subtype behavior executed") + return super().__getattribute__(name) + + +class _ReadPort: + """Capture repository use; this regression must fail before persistence.""" + + def __init__(self) -> None: + self.calls: list[tuple[UUID, UUID]] = [] + + def read_validity_study( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + ) -> ValidityStudyRecord | None: + """Record an unexpected persistence call.""" + self.calls.append((tenant_record_id, validity_study_id)) + return None + + +def _policy() -> PurposeBoundAccessPolicy: + """Return the canonical purpose-bound policy used by the read boundary.""" + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="validation-read-v1", + resource_kind="validity_study_record", + purpose_code="validation_review", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=frozenset({"study_status_code"}), + ) + + +def test_low_level_exact_principal_is_revalidated_before_keyverse_evaluation() -> None: + """Reject constructor-bypassed identity evidence before subtype behavior can execute.""" + forged_tenant = _ExecutableUUID(str(TENANT)) + principal = tuple.__new__( + ValidationPrincipal, + ( + forged_tenant, + "person:analyst-1", + frozenset({"orgmetra.workforce_validation.read"}), + ), + ) + port = _ReadPort() + + with pytest.raises(ValueError, match="tenant_record_id must be an exact operational UUID"): + read_validity_study( + principal=principal, + tenant_record_id=TENANT, + validity_study_id=STUDY, + purpose_code="validation_review", + requested_fields=frozenset({"study_status_code"}), + policy=_policy(), + read_port=port, + ) + + assert port.calls == [] From 4ef7ad130e4d0aa314ea59de3dafaea79cc0630c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 17:03:06 +0900 Subject: [PATCH 033/603] fix(workforce-validation): revalidate principal storage before auth --- .../src/orgmetra_workforce_validation_api/registry.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py index 523aef548..4921b7b91 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -290,6 +290,11 @@ def read_validity_study( if not isinstance(read_port, ValidityStudyReadPort): raise TypeError("read_port must implement ValidityStudyReadPort.") + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) tenant_id = _require_operational_uuid("tenant_record_id", tenant_record_id) study_id = _require_operational_uuid("validity_study_id", validity_study_id) purpose = _require_code("purpose_code", purpose_code) @@ -299,15 +304,15 @@ def read_validity_study( require_purpose_bound_access( request=PurposeBoundAccessRequest( tenant_record_id=tenant_id, - actor_tenant_record_id=principal.tenant_record_id, + actor_tenant_record_id=detached_principal.tenant_record_id, resource_tenant_record_id=tenant_id, - actor_reference=principal.actor_reference, + actor_reference=detached_principal.actor_reference, resource_reference=f"{_RESOURCE_KIND}:{study_id}", purpose_code=purpose, operation_code=_OPERATION, resource_kind=_RESOURCE_KIND, requested_fields=fields, - granted_scope_codes=principal.granted_scope_codes, + granted_scope_codes=detached_principal.granted_scope_codes, ), policy=detached_policy, ) From 9794ff543c9190cdd6fa00dc37016db8391709a9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 17:08:13 +0900 Subject: [PATCH 034/603] test(workforce-validation): reject noncallable read port before auth --- .../test_read_port_dependency_integrity.py | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_read_port_dependency_integrity.py diff --git a/services/workforce-validation-api/tests/test_read_port_dependency_integrity.py b/services/workforce-validation-api/tests/test_read_port_dependency_integrity.py new file mode 100644 index 000000000..a5e2cbdaf --- /dev/null +++ b/services/workforce-validation-api/tests/test_read_port_dependency_integrity.py @@ -0,0 +1,54 @@ +"""Regression contract for inert repository capability validation before authorization.""" + +from __future__ import annotations + +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api.registry import ( + ValidationPrincipal, + read_validity_study, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000c1") + + +class _DescriptorReadPort: + """Expose a non-callable static protocol member whose getter must never execute.""" + + @property + def read_validity_study(self) -> object: + """Trip if dependency validation or later code executes this descriptor.""" + raise AssertionError("repository descriptor executed before rejection") + + +def test_noncallable_repository_capability_fails_before_authorization() -> None: + """Reject an invalid port before a deliberately denying policy can be evaluated.""" + principal = ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + denying_policy = PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="validation-read-v1", + resource_kind="validity_study_record", + purpose_code="audit_review", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=frozenset({"study_status_code"}), + ) + + with pytest.raises(TypeError, match="read_port must expose a statically callable read_validity_study"): + read_validity_study( + principal=principal, + tenant_record_id=TENANT, + validity_study_id=STUDY, + purpose_code="validation_review", + requested_fields=frozenset({"study_status_code"}), + policy=denying_policy, + read_port=_DescriptorReadPort(), # type: ignore[arg-type] + ) From ccb5c0c58dc74c1d7eee59431e6337c207fcac35 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 17:08:51 +0900 Subject: [PATCH 035/603] fix(workforce-validation): validate repository capability statically --- .../src/orgmetra_workforce_validation_api/registry.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py index 4921b7b91..3006b727f 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -11,6 +11,7 @@ from dataclasses import dataclass from datetime import datetime, timezone +from inspect import getattr_static import re from typing import Protocol, runtime_checkable from uuid import UUID @@ -287,8 +288,9 @@ def read_validity_study( raise TypeError("principal must be an exact ValidationPrincipal.") if type(policy) is not PurposeBoundAccessPolicy: raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") - if not isinstance(read_port, ValidityStudyReadPort): - raise TypeError("read_port must implement ValidityStudyReadPort.") + read_capability = getattr_static(read_port, "read_validity_study", None) + if not callable(read_capability): + raise TypeError("read_port must expose a statically callable read_validity_study.") detached_principal = ValidationPrincipal( tenant_record_id=principal.tenant_record_id, From 1a344f8057755ae8b652c31963d787ff8abf2beb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 18:06:18 +0900 Subject: [PATCH 036/603] test(workforce-validation): lock authorized view evidence --- .../tests/test_registry.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/services/workforce-validation-api/tests/test_registry.py b/services/workforce-validation-api/tests/test_registry.py index 02b8661f1..53d5a62f1 100644 --- a/services/workforce-validation-api/tests/test_registry.py +++ b/services/workforce-validation-api/tests/test_registry.py @@ -272,3 +272,28 @@ def test_record_is_structurally_immutable_against_object_setattr() -> None: object.__setattr__(record, "study_status_code", "study_closed") assert record.study_status_code == "study_draft" + + +def test_authorized_view_is_structurally_immutable_after_field_minimization() -> None: + view = read_validity_study( + principal=_principal(), + tenant_record_id=TENANT, + validity_study_id=STUDY, + purpose_code="validation_review", + requested_fields=frozenset({"study_status_code"}), + policy=_policy(), + read_port=_ReadPort(_record()), + ) + original_fields = view.fields + + for field_name, replacement in ( + ("tenant_record_id", OTHER_TENANT), + ("validity_study_id", OTHER_STUDY), + ("fields", (("study_status_code", "study_closed"),)), + ): + with pytest.raises(AttributeError): + object.__setattr__(view, field_name, replacement) + + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + assert view.fields == original_fields From 17092c94d180d082d1e389982e0beea9872f53f9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 18:07:04 +0900 Subject: [PATCH 037/603] fix(workforce-validation): make authorized views structurally immutable --- .../registry.py | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py index 3006b727f..868fe281b 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -9,7 +9,6 @@ from __future__ import annotations -from dataclasses import dataclass from datetime import datetime, timezone from inspect import getattr_static import re @@ -245,13 +244,40 @@ def recorded_to(self) -> datetime | None: return self[5] -@dataclass(frozen=True, slots=True) -class ValidityStudyView: - """Field-minimized authorized view returned to the gateway or role workspace.""" +class ValidityStudyView(tuple): + """Structurally immutable field-minimized view returned after authorization. - tenant_record_id: UUID - validity_study_id: UUID - fields: tuple[tuple[str, object], ...] + Tuple-backed storage prevents downstream gateway, audit, or workspace code + from rewriting the authorized target identity or minimized field evidence + through ``object.__setattr__`` after the access decision has completed. + """ + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> ValidityStudyView: + """Create one immutable authorized-output envelope from already validated values.""" + return tuple.__new__(cls, (tenant_record_id, validity_study_id, fields)) + + @property + def tenant_record_id(self) -> UUID: + """Return the tenant identity authorized for this view.""" + return self[0] + + @property + def validity_study_id(self) -> UUID: + """Return the validity-study identity authorized for this view.""" + return self[1] + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return the ordered field-minimized evidence authorized for release.""" + return self[2] @runtime_checkable From 1b1d2e5c7cd492f57c806408618429e83f1e09d4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 19:00:11 +0900 Subject: [PATCH 038/603] test(workforce-validation): require authorized view issuance --- .../tests/test_view_issuance_integrity.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_view_issuance_integrity.py new file mode 100644 index 000000000..1095659a0 --- /dev/null +++ b/services/workforce-validation-api/tests/test_view_issuance_integrity.py @@ -0,0 +1,21 @@ +"""Regression contract for workforce-validation authorized-view issuance.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.registry import ValidityStudyView + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000c1") + + +def test_direct_authorized_view_construction_fails_closed() -> None: + """Require purpose-bound reads, not public construction, to issue study views.""" + with pytest.raises(TypeError, match="issued only by read_validity_study"): + ValidityStudyView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(("study_status_code", "study_draft"),), + ) From b655063cc7d9680de5743949b9b66e631530b904 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 19:01:03 +0900 Subject: [PATCH 039/603] fix(workforce-validation): make study views read-issued only --- .../registry.py | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py index 868fe281b..34c3ac973 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -249,7 +249,10 @@ class ValidityStudyView(tuple): Tuple-backed storage prevents downstream gateway, audit, or workspace code from rewriting the authorized target identity or minimized field evidence - through ``object.__setattr__`` after the access decision has completed. + through ``object.__setattr__`` after the access decision has completed. The + public constructor is deliberately non-issuing: callers obtain this data-only + projection from ``read_validity_study`` and must re-authorize consequential + actions rather than treating the Python runtime type as a durable credential. """ __slots__ = () @@ -261,8 +264,8 @@ def __new__( validity_study_id: UUID, fields: tuple[tuple[str, object], ...], ) -> ValidityStudyView: - """Create one immutable authorized-output envelope from already validated values.""" - return tuple.__new__(cls, (tenant_record_id, validity_study_id, fields)) + """Reject public construction so only the authorized read path issues views.""" + raise TypeError("ValidityStudyView is issued only by read_validity_study.") @property def tenant_record_id(self) -> UUID: @@ -280,6 +283,16 @@ def fields(self) -> tuple[tuple[str, object], ...]: return self[2] +def _issue_validity_study_view( + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], +) -> ValidityStudyView: + """Issue one immutable view after authorization and target validation complete.""" + return tuple.__new__(ValidityStudyView, (tenant_record_id, validity_study_id, fields)) + + @runtime_checkable class ValidityStudyReadPort(Protocol): """Owner repository contract for one tenant-local validity-study header.""" @@ -371,7 +384,7 @@ def read_validity_study( "recorded_from": record.recorded_from, "recorded_to": record.recorded_to, } - return ValidityStudyView( + return _issue_validity_study_view( tenant_record_id=tenant_id, validity_study_id=study_id, fields=tuple((field_name, values[field_name]) for field_name in sorted(fields)), From 412c62b279a4d3b5448dd2817c835e0aa85b412d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 19:02:44 +0900 Subject: [PATCH 040/603] docs(workforce-validation): define authorized view issuance boundary --- services/workforce-validation-api/README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 1e0ea265b..2e18dc728 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -9,16 +9,21 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar `read_validity_study(...)`: - accepts structurally immutable authenticated Keyverse identity attributes, not credentials; +- reconstructs and revalidates principal storage before building the access request, so exact tuple type alone is not treated as identity authority; +- inertly verifies that the owner repository exposes a statically callable `read_validity_study` capability before authorization, without executing caller-controlled descriptors; - evaluates tenant, purpose, operation, scope, resource, and requested fields before persistence; - calls only a `ValidityStudyReadPort` owned by this context; - reconstructs persisted registry scalars into structurally immutable owner evidence before target validation and output; -- returns only the fields authorized for the exact study record. +- returns only the fields authorized for the exact study record; +- issues `ValidityStudyView` only from the authorized read path. Its public constructor fails closed, and the returned tuple-backed projection cannot be rewritten through ordinary assignment or `object.__setattr__`. + +`ValidityStudyView` is a data projection, not a durable authorization credential or cryptographic capability. Downstream consequential actions must perform their own purpose-bound authorization and authoritative re-resolution rather than treating the Python runtime type as reusable authority. Low-level interpreter construction is outside the supported public API and is not accepted as proof that authorization occurred. `services/workforce-validation-api/database/migrations/0001_owner_schema.sql` starts this bounded context's own migration history. It creates the `workforce_validation` schema and deny-default `workforce_validation_role`, revokes public schema access, and intentionally creates or moves no application table yet. The role is a **NOLOGIN migration/schema owner only**; runtime principals must not be granted that owner role. PostgreSQL applies role-level configuration defaults at login and does not re-apply them on `SET ROLE`, so an `ALTER ROLE ... SET search_path` entry on this NOLOGIN role is not treated as a runtime isolation control. The later durable adapter must use a distinct least-privilege runtime role, schema-qualified `workforce_validation` relations, and explicit function-level `search_path` where `SECURITY DEFINER` code is introduced. Protected foundation migrations still create validity-study tables in the legacy foundation schema, so the next forward-only persistence increment must adopt those records without normalizing `public.validity_study` as a long-lived service contract or breaking existing linkage evidence. -Issue #234 owns the remaining order: durable owner-schema adoption and PostgreSQL adapter, idempotent registration, explicit predictor/sample/decision-policy/analysis-protocol versions, scientific adapters, OpenAPI/gateway exposure, and realistic p95 measurement. Issues #236/#237 track structural immutability of persisted study and authenticated principal evidence; #238 tracks the owner-role/runtime-search-path boundary until exact-head acceptance and protected integration. +Issue #234 owns the remaining order: durable owner-schema adoption and PostgreSQL adapter, idempotent registration, explicit predictor/sample/decision-policy/analysis-protocol versions, scientific adapters, OpenAPI/gateway exposure, and realistic p95 measurement. Issues #236–#242 retain the current bootstrap trust-boundary findings through exact-head acceptance and protected integration: persisted-record immutability, principal immutability and constructor revalidation, owner-role/runtime-role separation, inert repository-capability validation, immutable minimized output, and non-public issuance of that output. ## Test From dfd8038e83270c8530c5a5ef7d2bfb1af409490b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 20:07:46 +0900 Subject: [PATCH 041/603] test(workforce-validation): expose retained UUID alias mutation --- .../tests/test_uuid_storage_integrity.py | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_uuid_storage_integrity.py diff --git a/services/workforce-validation-api/tests/test_uuid_storage_integrity.py b/services/workforce-validation-api/tests/test_uuid_storage_integrity.py new file mode 100644 index 000000000..d8bd48aac --- /dev/null +++ b/services/workforce-validation-api/tests/test_uuid_storage_integrity.py @@ -0,0 +1,118 @@ +"""Regression contract for UUID storage behind immutable registry value objects.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api.registry import ( + ValidationPrincipal, + ValidityStudyRecord, + read_validity_study, +) + +TENANT_TEXT = "10000000-0000-7000-8000-000000000001" +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY_TEXT = "00000000-0000-7000-8000-0000000000c1" +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000c2") +CRITERION_TEXT = "00000000-0000-7000-8000-0000000000a1" +OTHER_CRITERION = UUID("00000000-0000-7000-8000-0000000000a2") +RECORDED_FROM = datetime(2026, 11, 3, tzinfo=timezone.utc) + + +class _ReadPort: + """Return one configured owner record for UUID-storage regression coverage.""" + + def __init__(self, result: ValidityStudyRecord) -> None: + self.result = result + + def read_validity_study( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + ) -> ValidityStudyRecord: + """Return the configured record after the application boundary authorizes the read.""" + return self.result + + +def _policy() -> PurposeBoundAccessPolicy: + """Return the canonical purpose-bound policy for the regression read.""" + return PurposeBoundAccessPolicy( + tenant_record_id=UUID(TENANT_TEXT), + policy_version_code="validation-read-v1", + resource_kind="validity_study_record", + purpose_code="validation_review", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=frozenset({"criterion_blueprint_id"}), + ) + + +def test_principal_and_record_do_not_retain_mutable_uuid_inputs() -> None: + """Retained UUID aliases cannot rewrite identity evidence after constructor validation.""" + tenant = UUID(TENANT_TEXT) + study = UUID(STUDY_TEXT) + criterion = UUID(CRITERION_TEXT) + principal = ValidationPrincipal( + tenant_record_id=tenant, + actor_reference="person:analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + record = ValidityStudyRecord( + tenant_record_id=tenant, + validity_study_id=study, + criterion_blueprint_id=criterion, + study_status_code="study_draft", + recorded_from=RECORDED_FROM, + recorded_to=None, + ) + + object.__setattr__(tenant, "int", OTHER_TENANT.int) + object.__setattr__(study, "int", OTHER_STUDY.int) + object.__setattr__(criterion, "int", OTHER_CRITERION.int) + + assert principal.tenant_record_id == UUID(TENANT_TEXT) + assert record.tenant_record_id == UUID(TENANT_TEXT) + assert record.validity_study_id == UUID(STUDY_TEXT) + assert record.criterion_blueprint_id == UUID(CRITERION_TEXT) + + +def test_authorized_view_does_not_retain_or_expose_mutable_uuid_storage() -> None: + """Target and projected UUID evidence remain stable across retained-reference rewrites.""" + tenant = UUID(TENANT_TEXT) + study = UUID(STUDY_TEXT) + principal = ValidationPrincipal( + tenant_record_id=UUID(TENANT_TEXT), + actor_reference="person:analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + record = ValidityStudyRecord( + tenant_record_id=UUID(TENANT_TEXT), + validity_study_id=UUID(STUDY_TEXT), + criterion_blueprint_id=UUID(CRITERION_TEXT), + study_status_code="study_draft", + recorded_from=RECORDED_FROM, + recorded_to=None, + ) + + view = read_validity_study( + principal=principal, + tenant_record_id=tenant, + validity_study_id=study, + purpose_code="validation_review", + requested_fields=frozenset({"criterion_blueprint_id"}), + policy=_policy(), + read_port=_ReadPort(record), + ) + + object.__setattr__(tenant, "int", OTHER_TENANT.int) + object.__setattr__(study, "int", OTHER_STUDY.int) + projected_criterion = dict(view.fields)["criterion_blueprint_id"] + assert type(projected_criterion) is UUID + object.__setattr__(projected_criterion, "int", OTHER_CRITERION.int) + + assert view.tenant_record_id == UUID(TENANT_TEXT) + assert view.validity_study_id == UUID(STUDY_TEXT) + assert dict(view.fields)["criterion_blueprint_id"] == UUID(CRITERION_TEXT) From a78104c71e340039ca7f0c36aa2d4f7d22dff999 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 20:08:44 +0900 Subject: [PATCH 042/603] test(workforce-validation): expose post-authorization UUID target switch --- .../tests/test_uuid_storage_integrity.py | 55 +++++++++++++++++-- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/services/workforce-validation-api/tests/test_uuid_storage_integrity.py b/services/workforce-validation-api/tests/test_uuid_storage_integrity.py index d8bd48aac..52c23998e 100644 --- a/services/workforce-validation-api/tests/test_uuid_storage_integrity.py +++ b/services/workforce-validation-api/tests/test_uuid_storage_integrity.py @@ -5,9 +5,12 @@ from datetime import datetime, timezone from uuid import UUID +import pytest + from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy from orgmetra_workforce_validation_api.registry import ( ValidationPrincipal, + ValidityStudyIntegrityError, ValidityStudyRecord, read_validity_study, ) @@ -37,6 +40,28 @@ def read_validity_study( return self.result +class _TargetSwitchingReadPort: + """Attempt to rewrite the authorized UUID target during the executable port call.""" + + def read_validity_study( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + ) -> ValidityStudyRecord: + """Mutate received UUID aliases and return a record matching the rewritten target.""" + object.__setattr__(tenant_record_id, "int", OTHER_TENANT.int) + object.__setattr__(validity_study_id, "int", OTHER_STUDY.int) + return ValidityStudyRecord( + tenant_record_id=OTHER_TENANT, + validity_study_id=OTHER_STUDY, + criterion_blueprint_id=UUID(CRITERION_TEXT), + study_status_code="study_draft", + recorded_from=RECORDED_FROM, + recorded_to=None, + ) + + def _policy() -> PurposeBoundAccessPolicy: """Return the canonical purpose-bound policy for the regression read.""" return PurposeBoundAccessPolicy( @@ -50,6 +75,15 @@ def _policy() -> PurposeBoundAccessPolicy: ) +def _principal() -> ValidationPrincipal: + """Return one canonical principal for UUID target-integrity tests.""" + return ValidationPrincipal( + tenant_record_id=UUID(TENANT_TEXT), + actor_reference="person:analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + def test_principal_and_record_do_not_retain_mutable_uuid_inputs() -> None: """Retained UUID aliases cannot rewrite identity evidence after constructor validation.""" tenant = UUID(TENANT_TEXT) @@ -79,15 +113,24 @@ def test_principal_and_record_do_not_retain_mutable_uuid_inputs() -> None: assert record.criterion_blueprint_id == UUID(CRITERION_TEXT) +def test_port_cannot_switch_the_authorized_target_by_mutating_received_uuid_objects() -> None: + """The target comparison uses pre-port immutable identity evidence, not mutable aliases.""" + with pytest.raises(ValidityStudyIntegrityError, match="another target"): + read_validity_study( + principal=_principal(), + tenant_record_id=UUID(TENANT_TEXT), + validity_study_id=UUID(STUDY_TEXT), + purpose_code="validation_review", + requested_fields=frozenset({"criterion_blueprint_id"}), + policy=_policy(), + read_port=_TargetSwitchingReadPort(), + ) + + def test_authorized_view_does_not_retain_or_expose_mutable_uuid_storage() -> None: """Target and projected UUID evidence remain stable across retained-reference rewrites.""" tenant = UUID(TENANT_TEXT) study = UUID(STUDY_TEXT) - principal = ValidationPrincipal( - tenant_record_id=UUID(TENANT_TEXT), - actor_reference="person:analyst-1", - granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), - ) record = ValidityStudyRecord( tenant_record_id=UUID(TENANT_TEXT), validity_study_id=UUID(STUDY_TEXT), @@ -98,7 +141,7 @@ def test_authorized_view_does_not_retain_or_expose_mutable_uuid_storage() -> Non ) view = read_validity_study( - principal=principal, + principal=_principal(), tenant_record_id=tenant, validity_study_id=study, purpose_code="validation_review", From b1c70855e6655817a4f40cc9dfb4787770f40c5d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 20:09:40 +0900 Subject: [PATCH 043/603] fix(workforce-validation): detach UUID identity storage --- .../registry.py | 158 ++++++++++++------ 1 file changed, 110 insertions(+), 48 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py index 34c3ac973..e0f2cb491 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -53,6 +53,18 @@ def _require_operational_uuid(field_name: str, value: object) -> UUID: return value +def _store_operational_uuid(field_name: str, value: object) -> int: + """Reduce one validated UUID to immutable integer storage without retaining its object alias.""" + return _require_operational_uuid(field_name, value).int + + +def _restore_operational_uuid(field_name: str, value: object) -> UUID: + """Reconstruct one fresh UUID from immutable internal integer storage.""" + if type(value) is not int or value <= 0 or value >= _MAX_UUID_INT: + raise ValueError(f"{field_name} must be an exact operational UUID.") + return UUID(int=value) + + def _require_code(field_name: str, value: object) -> str: """Return one exact lower-snake-case code used in an auditable policy request.""" if type(value) is not str or _CODE_PATTERN.fullmatch(value) is None: @@ -94,9 +106,9 @@ def _detach_policy(policy: PurposeBoundAccessPolicy) -> PurposeBoundAccessPolicy The protected Keyverse adapter accepts subclass-compatible scalar inputs for backward compatibility. This owner boundary is stricter because a caller- defined ``str``/``UUID`` subtype could otherwise execute Python behavior when - the evaluator compares or hashes policy attributes. Locals snapshot each - immutable value first; the reconstructed exact policy is the only one used by - authorization. + the evaluator compares or hashes policy attributes. Immutable UUID integer + storage also prevents a retained policy UUID alias from switching the tenant + after this boundary has accepted it. """ tenant_record_id = policy.tenant_record_id policy_version_code = policy.policy_version_code @@ -106,7 +118,7 @@ def _detach_policy(policy: PurposeBoundAccessPolicy) -> PurposeBoundAccessPolicy required_scope_code = policy.required_scope_code permitted_fields = policy.permitted_fields - _require_operational_uuid("policy tenant_record_id", tenant_record_id) + tenant_identity = _store_operational_uuid("policy tenant_record_id", tenant_record_id) for field_name, value in ( ("policy_version_code", policy_version_code), ("resource_kind", resource_kind), @@ -122,7 +134,7 @@ def _detach_policy(policy: PurposeBoundAccessPolicy) -> PurposeBoundAccessPolicy raise ValueError("policy permitted_fields must contain exact strings in an exact frozenset.") return PurposeBoundAccessPolicy( - tenant_record_id=tenant_record_id, + tenant_record_id=_restore_operational_uuid("policy tenant_record_id", tenant_identity), policy_version_code=policy_version_code, resource_kind=resource_kind, purpose_code=purpose_code, @@ -136,8 +148,8 @@ class ValidationPrincipal(tuple): """Structurally immutable authenticated Keyverse attributes for validation reads. The bearer credential itself never enters this value. Tuple-backed storage - prevents a retained caller reference from rewriting tenant, actor, or scope - evidence through ``object.__setattr__`` after constructor validation. + keeps only immutable UUID integer evidence plus immutable actor/scope values, + so retained UUID references cannot rewrite tenant identity after validation. """ __slots__ = () @@ -150,16 +162,16 @@ def __new__( granted_scope_codes: frozenset[str], ) -> ValidationPrincipal: """Validate exact identity evidence before creating the immutable principal.""" - tenant_id = _require_operational_uuid("tenant_record_id", tenant_record_id) + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) if type(actor_reference) is not str or _REFERENCE_PATTERN.fullmatch(actor_reference) is None: raise ValueError("actor_reference must be an exact namespaced opaque reference.") scope_codes = _validate_scope_set(granted_scope_codes) - return tuple.__new__(cls, (tenant_id, actor_reference, scope_codes)) + return tuple.__new__(cls, (tenant_identity, actor_reference, scope_codes)) @property def tenant_record_id(self) -> UUID: - """Return the authenticated tenant identity.""" - return self[0] + """Return a fresh authenticated tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) @property def actor_reference(self) -> str: @@ -175,12 +187,12 @@ def granted_scope_codes(self) -> frozenset[str]: class ValidityStudyRecord(tuple): """Structurally immutable owner projection of one recorded validity-study header. - The tuple-backed representation prevents a repository adapter that retains an - accepted record from rewriting durable study evidence through - ``object.__setattr__`` after construction. Only fields already represented by - the protected foundation schema are carried here. Predictor, sample, - decision-policy and analysis-protocol versions remain a later scientific-model - increment owned by Issue #234. + The tuple-backed representation stores UUIDs as immutable integers, preventing + a repository adapter that retains accepted UUID objects from rewriting durable + study identity through ``object.__setattr__`` after construction. Only fields + already represented by the protected foundation schema are carried here. + Predictor, sample, decision-policy and analysis-protocol versions remain a + later scientific-model increment owned by Issue #234. """ __slots__ = () @@ -196,9 +208,11 @@ def __new__( recorded_to: datetime | None, ) -> ValidityStudyRecord: """Validate and detach durable scalars before creating the immutable tuple.""" - tenant_id = _require_operational_uuid("tenant_record_id", tenant_record_id) - study_id = _require_operational_uuid("validity_study_id", validity_study_id) - criterion_id = _require_operational_uuid("criterion_blueprint_id", criterion_blueprint_id) + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + criterion_identity = _store_operational_uuid( + "criterion_blueprint_id", criterion_blueprint_id + ) status_code = _require_code("study_status_code", study_status_code) recorded_start = _require_aware_datetime("recorded_from", recorded_from) recorded_end = ( @@ -210,23 +224,30 @@ def __new__( raise ValueError("recorded_to must be later than recorded_from.") return tuple.__new__( cls, - (tenant_id, study_id, criterion_id, status_code, recorded_start, recorded_end), + ( + tenant_identity, + study_identity, + criterion_identity, + status_code, + recorded_start, + recorded_end, + ), ) @property def tenant_record_id(self) -> UUID: - """Return the tenant that owns this validity study.""" - return self[0] + """Return a fresh tenant identity for this validity study.""" + return _restore_operational_uuid("tenant_record_id", self[0]) @property def validity_study_id(self) -> UUID: - """Return the stable validity-study identity.""" - return self[1] + """Return a fresh stable validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) @property def criterion_blueprint_id(self) -> UUID: - """Return the criterion blueprint linked to the study header.""" - return self[2] + """Return a fresh criterion-blueprint identity linked to the study header.""" + return _restore_operational_uuid("criterion_blueprint_id", self[2]) @property def study_status_code(self) -> str: @@ -244,13 +265,39 @@ def recorded_to(self) -> datetime | None: return self[5] +def _store_view_fields(fields: tuple[tuple[str, object], ...]) -> tuple[tuple[str, object], ...]: + """Store UUID-valued projection fields without retaining mutable UUID object aliases.""" + return tuple( + ( + field_name, + _store_operational_uuid(field_name, value) + if field_name == "criterion_blueprint_id" + else value, + ) + for field_name, value in fields + ) + + +def _restore_view_fields(fields: tuple[tuple[str, object], ...]) -> tuple[tuple[str, object], ...]: + """Return a public projection with fresh UUID objects for UUID-valued fields.""" + return tuple( + ( + field_name, + _restore_operational_uuid(field_name, value) + if field_name == "criterion_blueprint_id" + else value, + ) + for field_name, value in fields + ) + + class ValidityStudyView(tuple): """Structurally immutable field-minimized view returned after authorization. - Tuple-backed storage prevents downstream gateway, audit, or workspace code - from rewriting the authorized target identity or minimized field evidence - through ``object.__setattr__`` after the access decision has completed. The - public constructor is deliberately non-issuing: callers obtain this data-only + Tuple-backed storage keeps target UUIDs and UUID-valued projected evidence as + immutable integers, so downstream gateway, audit, or workspace code cannot + rewrite authorized identity through retained UUID objects. The public + constructor is deliberately non-issuing: callers obtain this data-only projection from ``read_validity_study`` and must re-authorize consequential actions rather than treating the Python runtime type as a durable credential. """ @@ -269,18 +316,18 @@ def __new__( @property def tenant_record_id(self) -> UUID: - """Return the tenant identity authorized for this view.""" - return self[0] + """Return a fresh tenant identity authorized for this view.""" + return _restore_operational_uuid("tenant_record_id", self[0]) @property def validity_study_id(self) -> UUID: - """Return the validity-study identity authorized for this view.""" - return self[1] + """Return a fresh validity-study identity authorized for this view.""" + return _restore_operational_uuid("validity_study_id", self[1]) @property def fields(self) -> tuple[tuple[str, object], ...]: - """Return the ordered field-minimized evidence authorized for release.""" - return self[2] + """Return ordered field-minimized evidence with fresh UUID-valued projections.""" + return _restore_view_fields(self[2]) def _issue_validity_study_view( @@ -290,7 +337,14 @@ def _issue_validity_study_view( fields: tuple[tuple[str, object], ...], ) -> ValidityStudyView: """Issue one immutable view after authorization and target validation complete.""" - return tuple.__new__(ValidityStudyView, (tenant_record_id, validity_study_id, fields)) + return tuple.__new__( + ValidityStudyView, + ( + _store_operational_uuid("tenant_record_id", tenant_record_id), + _store_operational_uuid("validity_study_id", validity_study_id), + _store_view_fields(fields), + ), + ) @runtime_checkable @@ -319,9 +373,10 @@ def read_validity_study( ) -> ValidityStudyView: """Authorize and read one validity-study header through the canonical owner port. - Authorization is completed before persistence. The persistence result is then - reconstructed into an exact immutable value and must match the authorized - tenant/study identity before any field is returned. + Authorization is completed before persistence. Immutable integer snapshots + preserve the authorized target across the executable repository call. The + persistence result is reconstructed into an exact immutable value and must + match those snapshots before any field is returned. """ if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") @@ -336,8 +391,10 @@ def read_validity_study( actor_reference=principal.actor_reference, granted_scope_codes=principal.granted_scope_codes, ) - tenant_id = _require_operational_uuid("tenant_record_id", tenant_record_id) - study_id = _require_operational_uuid("validity_study_id", validity_study_id) + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + tenant_id = _restore_operational_uuid("tenant_record_id", tenant_identity) + study_id = _restore_operational_uuid("validity_study_id", study_identity) purpose = _require_code("purpose_code", purpose_code) fields = _validate_requested_fields(requested_fields) detached_policy = _detach_policy(policy) @@ -359,8 +416,8 @@ def read_validity_study( ) persisted = read_port.read_validity_study( - tenant_record_id=tenant_id, - validity_study_id=study_id, + tenant_record_id=_restore_operational_uuid("tenant_record_id", tenant_identity), + validity_study_id=_restore_operational_uuid("validity_study_id", study_identity), ) if persisted is None: raise ValidityStudyNotFound(str(study_id)) @@ -375,7 +432,12 @@ def read_validity_study( recorded_from=persisted.recorded_from, recorded_to=persisted.recorded_to, ) - if record.tenant_record_id != tenant_id or record.validity_study_id != study_id: + if ( + _store_operational_uuid("record tenant_record_id", record.tenant_record_id) + != tenant_identity + or _store_operational_uuid("record validity_study_id", record.validity_study_id) + != study_identity + ): raise ValidityStudyIntegrityError("repository returned a validity-study record for another target") values = { @@ -385,7 +447,7 @@ def read_validity_study( "recorded_to": record.recorded_to, } return _issue_validity_study_view( - tenant_record_id=tenant_id, - validity_study_id=study_id, + tenant_record_id=_restore_operational_uuid("tenant_record_id", tenant_identity), + validity_study_id=_restore_operational_uuid("validity_study_id", study_identity), fields=tuple((field_name, values[field_name]) for field_name in sorted(fields)), ) From 65052598187e8b7b177f58e65f83d004dbfa8f83 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 20:10:03 +0900 Subject: [PATCH 044/603] docs(workforce-validation): record UUID storage boundary --- services/workforce-validation-api/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 2e18dc728..ee87458a5 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -10,11 +10,13 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar - accepts structurally immutable authenticated Keyverse identity attributes, not credentials; - reconstructs and revalidates principal storage before building the access request, so exact tuple type alone is not treated as identity authority; +- stores UUID identity evidence behind the tuple-backed principal/record/view as exact integer payloads and reconstructs fresh UUID objects at public boundaries, so a retained UUID reference cannot rewrite accepted tenant/study/criterion identity through `object.__setattr__`; +- preserves tenant/study authorization targets as immutable integer snapshots across the executable repository call, so a repository cannot make a foreign record self-consistent by mutating the UUID objects it receives; - inertly verifies that the owner repository exposes a statically callable `read_validity_study` capability before authorization, without executing caller-controlled descriptors; - evaluates tenant, purpose, operation, scope, resource, and requested fields before persistence; - calls only a `ValidityStudyReadPort` owned by this context; - reconstructs persisted registry scalars into structurally immutable owner evidence before target validation and output; -- returns only the fields authorized for the exact study record; +- returns only the fields authorized for the exact study record; UUID-valued projected fields are reconstituted fresh rather than exposing mutable internal UUID aliases; - issues `ValidityStudyView` only from the authorized read path. Its public constructor fails closed, and the returned tuple-backed projection cannot be rewritten through ordinary assignment or `object.__setattr__`. `ValidityStudyView` is a data projection, not a durable authorization credential or cryptographic capability. Downstream consequential actions must perform their own purpose-bound authorization and authoritative re-resolution rather than treating the Python runtime type as reusable authority. Low-level interpreter construction is outside the supported public API and is not accepted as proof that authorization occurred. @@ -23,7 +25,7 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar Protected foundation migrations still create validity-study tables in the legacy foundation schema, so the next forward-only persistence increment must adopt those records without normalizing `public.validity_study` as a long-lived service contract or breaking existing linkage evidence. -Issue #234 owns the remaining order: durable owner-schema adoption and PostgreSQL adapter, idempotent registration, explicit predictor/sample/decision-policy/analysis-protocol versions, scientific adapters, OpenAPI/gateway exposure, and realistic p95 measurement. Issues #236–#242 retain the current bootstrap trust-boundary findings through exact-head acceptance and protected integration: persisted-record immutability, principal immutability and constructor revalidation, owner-role/runtime-role separation, inert repository-capability validation, immutable minimized output, and non-public issuance of that output. +Issue #234 owns the remaining order: durable owner-schema adoption and PostgreSQL adapter, idempotent registration, explicit predictor/sample/decision-policy/analysis-protocol versions, scientific adapters, OpenAPI/gateway exposure, and realistic p95 measurement. Issues #236–#243 retain the current bootstrap trust-boundary findings through exact-head acceptance and protected integration: persisted-record immutability, principal immutability and constructor revalidation, owner-role/runtime-role separation, inert repository-capability validation, immutable minimized output, non-public issuance of that output, and detached UUID storage/target snapshots. ## Test From 23bdae68d23b5d50673184ab0a2dccd0dad3d355 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 20:16:18 +0900 Subject: [PATCH 045/603] test(workforce-validation): expose executable UUID payload --- .../tests/test_uuid_payload_integrity.py | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_uuid_payload_integrity.py diff --git a/services/workforce-validation-api/tests/test_uuid_payload_integrity.py b/services/workforce-validation-api/tests/test_uuid_payload_integrity.py new file mode 100644 index 000000000..5b20e787e --- /dev/null +++ b/services/workforce-validation-api/tests/test_uuid_payload_integrity.py @@ -0,0 +1,30 @@ +"""Regression contract for exact UUID payload validation before sentinel comparison.""" + +from __future__ import annotations + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.registry import ValidationPrincipal + + +class _ExecutableUUIDPayload: + """Fail if validation compares a forged UUID payload before proving it is an int.""" + + def __eq__(self, other: object) -> bool: + """Expose equality execution as a trust-boundary violation.""" + raise AssertionError(f"forged UUID payload executed equality against {other!r}") + + +def test_exact_uuid_with_executable_internal_payload_fails_before_comparison() -> None: + """Exact UUID outer type cannot authorize executable non-integer internal storage.""" + tenant_record_id = UUID("10000000-0000-7000-8000-000000000001") + object.__setattr__(tenant_record_id, "int", _ExecutableUUIDPayload()) + + with pytest.raises(ValueError, match="tenant_record_id must be an exact operational UUID"): + ValidationPrincipal( + tenant_record_id=tenant_record_id, + actor_reference="person:analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) From 7f7617b4225d96aed0f6d522c25302228b8a6bde Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 20:17:16 +0900 Subject: [PATCH 046/603] fix(workforce-validation): validate UUID payload before comparison --- .../orgmetra_workforce_validation_api/registry.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py index e0f2cb491..f696fc88f 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -46,16 +46,19 @@ class ValidityStudyIntegrityError(RuntimeError): """Indicate that persistence returned a record outside the authorized target.""" -def _require_operational_uuid(field_name: str, value: object) -> UUID: - """Return one exact operational UUID and reject protocol sentinels or subtypes.""" - if type(value) is not UUID or value.int in (0, _MAX_UUID_INT): +def _require_operational_uuid(field_name: str, value: object) -> int: + """Return one inert UUID integer after exact outer and internal-type validation.""" + if type(value) is not UUID: raise ValueError(f"{field_name} must be an exact operational UUID.") - return value + identity = value.int + if type(identity) is not int or identity <= 0 or identity >= _MAX_UUID_INT: + raise ValueError(f"{field_name} must be an exact operational UUID.") + return identity def _store_operational_uuid(field_name: str, value: object) -> int: """Reduce one validated UUID to immutable integer storage without retaining its object alias.""" - return _require_operational_uuid(field_name, value).int + return _require_operational_uuid(field_name, value) def _restore_operational_uuid(field_name: str, value: object) -> UUID: From 7c71f81c63ff87d6524fd565b3b5ce444905ca2e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 20:17:40 +0900 Subject: [PATCH 047/603] docs(workforce-validation): record UUID payload validation --- services/workforce-validation-api/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index ee87458a5..d3d847361 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -10,6 +10,7 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar - accepts structurally immutable authenticated Keyverse identity attributes, not credentials; - reconstructs and revalidates principal storage before building the access request, so exact tuple type alone is not treated as identity authority; +- requires both exact `UUID` outer type and exact built-in integer UUID payload before any sentinel/range comparison, so a forged exact UUID with executable internal storage is rejected without invoking caller-defined equality behavior; - stores UUID identity evidence behind the tuple-backed principal/record/view as exact integer payloads and reconstructs fresh UUID objects at public boundaries, so a retained UUID reference cannot rewrite accepted tenant/study/criterion identity through `object.__setattr__`; - preserves tenant/study authorization targets as immutable integer snapshots across the executable repository call, so a repository cannot make a foreign record self-consistent by mutating the UUID objects it receives; - inertly verifies that the owner repository exposes a statically callable `read_validity_study` capability before authorization, without executing caller-controlled descriptors; @@ -25,7 +26,7 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar Protected foundation migrations still create validity-study tables in the legacy foundation schema, so the next forward-only persistence increment must adopt those records without normalizing `public.validity_study` as a long-lived service contract or breaking existing linkage evidence. -Issue #234 owns the remaining order: durable owner-schema adoption and PostgreSQL adapter, idempotent registration, explicit predictor/sample/decision-policy/analysis-protocol versions, scientific adapters, OpenAPI/gateway exposure, and realistic p95 measurement. Issues #236–#243 retain the current bootstrap trust-boundary findings through exact-head acceptance and protected integration: persisted-record immutability, principal immutability and constructor revalidation, owner-role/runtime-role separation, inert repository-capability validation, immutable minimized output, non-public issuance of that output, and detached UUID storage/target snapshots. +Issue #234 owns the remaining order: durable owner-schema adoption and PostgreSQL adapter, idempotent registration, explicit predictor/sample/decision-policy/analysis-protocol versions, scientific adapters, OpenAPI/gateway exposure, and realistic p95 measurement. Issues #236–#244 retain the current bootstrap trust-boundary findings through exact-head acceptance and protected integration: persisted-record immutability, principal immutability and constructor revalidation, owner-role/runtime-role separation, inert repository-capability validation, immutable minimized output, non-public issuance of that output, detached UUID storage/target snapshots, and exact validation of UUID internal payloads before comparison. ## Test From dbb0d251a5b2b2fa6bee558febe74a8e6bd33c59 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 20:26:37 +0900 Subject: [PATCH 048/603] test(workforce-validation): reject importable view issuer --- .../tests/test_view_issuance_integrity.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/services/workforce-validation-api/tests/test_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_view_issuance_integrity.py index 1095659a0..b65e72b04 100644 --- a/services/workforce-validation-api/tests/test_view_issuance_integrity.py +++ b/services/workforce-validation-api/tests/test_view_issuance_integrity.py @@ -4,6 +4,7 @@ import pytest +import orgmetra_workforce_validation_api.registry as registry from orgmetra_workforce_validation_api.registry import ValidityStudyView @@ -19,3 +20,8 @@ def test_direct_authorized_view_construction_fails_closed() -> None: validity_study_id=STUDY, fields=(("study_status_code", "study_draft"),), ) + + +def test_registry_module_exposes_no_unconditional_view_issuer() -> None: + """Keep ordinary view issuance inside the authorized read application path.""" + assert not hasattr(registry, "_issue_validity_study_view") From 656a0c41c06bc517b2cf7c554e35a6fb4f8c4f4b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 20:28:24 +0900 Subject: [PATCH 049/603] fix(workforce-validation): keep view issuance inside authorized read path --- .../registry.py | 29 +++++-------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py index f696fc88f..c86c0531e 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -333,23 +333,6 @@ def fields(self) -> tuple[tuple[str, object], ...]: return _restore_view_fields(self[2]) -def _issue_validity_study_view( - *, - tenant_record_id: UUID, - validity_study_id: UUID, - fields: tuple[tuple[str, object], ...], -) -> ValidityStudyView: - """Issue one immutable view after authorization and target validation complete.""" - return tuple.__new__( - ValidityStudyView, - ( - _store_operational_uuid("tenant_record_id", tenant_record_id), - _store_operational_uuid("validity_study_id", validity_study_id), - _store_view_fields(fields), - ), - ) - - @runtime_checkable class ValidityStudyReadPort(Protocol): """Owner repository contract for one tenant-local validity-study header.""" @@ -449,8 +432,12 @@ def read_validity_study( "recorded_from": record.recorded_from, "recorded_to": record.recorded_to, } - return _issue_validity_study_view( - tenant_record_id=_restore_operational_uuid("tenant_record_id", tenant_identity), - validity_study_id=_restore_operational_uuid("validity_study_id", study_identity), - fields=tuple((field_name, values[field_name]) for field_name in sorted(fields)), + projected_fields = tuple((field_name, values[field_name]) for field_name in sorted(fields)) + return tuple.__new__( + ValidityStudyView, + ( + tenant_identity, + study_identity, + _store_view_fields(projected_fields), + ), ) From 9a83ff0b373799297c0c1daede645da11296c388 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 21:32:22 +0900 Subject: [PATCH 050/603] test(workforce-validation): bind repository capability use --- .../test_read_port_dependency_integrity.py | 84 +++++++++++++++++-- 1 file changed, 76 insertions(+), 8 deletions(-) diff --git a/services/workforce-validation-api/tests/test_read_port_dependency_integrity.py b/services/workforce-validation-api/tests/test_read_port_dependency_integrity.py index a5e2cbdaf..d91fe206c 100644 --- a/services/workforce-validation-api/tests/test_read_port_dependency_integrity.py +++ b/services/workforce-validation-api/tests/test_read_port_dependency_integrity.py @@ -1,7 +1,8 @@ -"""Regression contract for inert repository capability validation before authorization.""" +"""Regression contracts for inert repository capability validation before authorization.""" from __future__ import annotations +from datetime import datetime, timezone from uuid import UUID import pytest @@ -9,11 +10,14 @@ from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy from orgmetra_workforce_validation_api.registry import ( ValidationPrincipal, + ValidityStudyRecord, read_validity_study, ) TENANT = UUID("10000000-0000-7000-8000-000000000001") STUDY = UUID("00000000-0000-7000-8000-0000000000c1") +CRITERION = UUID("00000000-0000-7000-8000-0000000000a1") +RECORDED_FROM = datetime(2026, 11, 3, tzinfo=timezone.utc) class _DescriptorReadPort: @@ -25,30 +29,94 @@ def read_validity_study(self) -> object: raise AssertionError("repository descriptor executed before rejection") -def test_noncallable_repository_capability_fails_before_authorization() -> None: - """Reject an invalid port before a deliberately denying policy can be evaluated.""" - principal = ValidationPrincipal( +class _DynamicLookupReadPort: + """Expose one safe class method but a different callable through instance lookup.""" + + def __init__(self) -> None: + self.dynamic_lookups = 0 + self.static_calls = 0 + + def __getattribute__(self, name: str) -> object: + """Trip if the authorized path performs a second dynamic capability lookup.""" + if name == "read_validity_study": + dynamic_lookups = object.__getattribute__(self, "dynamic_lookups") + object.__setattr__(self, "dynamic_lookups", dynamic_lookups + 1) + + def switched_capability(*, tenant_record_id: UUID, validity_study_id: UUID) -> object: + del tenant_record_id, validity_study_id + raise AssertionError("dynamic repository capability lookup executed after validation") + + return switched_capability + return object.__getattribute__(self, name) + + def read_validity_study( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + ) -> ValidityStudyRecord: + """Return valid owner evidence when the statically validated method is invoked.""" + self.static_calls += 1 + return ValidityStudyRecord( + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + criterion_blueprint_id=CRITERION, + study_status_code="study_draft", + recorded_from=RECORDED_FROM, + recorded_to=None, + ) + + +def _principal() -> ValidationPrincipal: + """Return one exact authenticated validation principal.""" + return ValidationPrincipal( tenant_record_id=TENANT, actor_reference="person:analyst-1", granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), ) - denying_policy = PurposeBoundAccessPolicy( + + +def _policy(*, purpose_code: str = "validation_review") -> PurposeBoundAccessPolicy: + """Return one purpose-bound policy for the focused repository tests.""" + return PurposeBoundAccessPolicy( tenant_record_id=TENANT, policy_version_code="validation-read-v1", resource_kind="validity_study_record", - purpose_code="audit_review", + purpose_code=purpose_code, operation_code="read", required_scope_code="orgmetra.workforce_validation.read", permitted_fields=frozenset({"study_status_code"}), ) + +def test_noncallable_repository_capability_fails_before_authorization() -> None: + """Reject an invalid port before a deliberately denying policy can be evaluated.""" with pytest.raises(TypeError, match="read_port must expose a statically callable read_validity_study"): read_validity_study( - principal=principal, + principal=_principal(), tenant_record_id=TENANT, validity_study_id=STUDY, purpose_code="validation_review", requested_fields=frozenset({"study_status_code"}), - policy=denying_policy, + policy=_policy(purpose_code="audit_review"), read_port=_DescriptorReadPort(), # type: ignore[arg-type] ) + + +def test_validated_repository_capability_is_the_capability_invoked_after_authorization() -> None: + """Bind the inertly validated class method instead of re-resolving it dynamically.""" + port = _DynamicLookupReadPort() + + view = read_validity_study( + principal=_principal(), + tenant_record_id=TENANT, + validity_study_id=STUDY, + purpose_code="validation_review", + requested_fields=frozenset({"study_status_code"}), + policy=_policy(), + read_port=port, + ) + + assert port.dynamic_lookups == 0 + assert port.static_calls == 1 + assert view.fields == (("study_status_code", "study_draft"),) From 0ac2255321eaf1d0068978b931990f4d9c9f1c85 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 5 Sep 2026 21:33:49 +0900 Subject: [PATCH 051/603] fix(workforce-validation): bind validated repository capability --- .../registry.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py index c86c0531e..78c1628bb 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -12,6 +12,7 @@ from datetime import datetime, timezone from inspect import getattr_static import re +from types import FunctionType from typing import Protocol, runtime_checkable from uuid import UUID from zoneinfo import ZoneInfo @@ -359,17 +360,20 @@ def read_validity_study( ) -> ValidityStudyView: """Authorize and read one validity-study header through the canonical owner port. - Authorization is completed before persistence. Immutable integer snapshots - preserve the authorized target across the executable repository call. The - persistence result is reconstructed into an exact immutable value and must - match those snapshots before any field is returned. + Authorization is completed before persistence. The exact ordinary repository + method is captured inertly before authorization and that same function is + invoked after authorization, so dynamic instance lookup cannot switch the + validated capability. Immutable integer snapshots preserve the authorized + target across the executable repository call. The persistence result is + reconstructed into an exact immutable value and must match those snapshots + before any field is returned. """ if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") if type(policy) is not PurposeBoundAccessPolicy: raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") - read_capability = getattr_static(read_port, "read_validity_study", None) - if not callable(read_capability): + read_capability = getattr_static(type(read_port), "read_validity_study", None) + if type(read_capability) is not FunctionType: raise TypeError("read_port must expose a statically callable read_validity_study.") detached_principal = ValidationPrincipal( @@ -401,7 +405,8 @@ def read_validity_study( policy=detached_policy, ) - persisted = read_port.read_validity_study( + persisted = read_capability( + read_port, tenant_record_id=_restore_operational_uuid("tenant_record_id", tenant_identity), validity_study_id=_restore_operational_uuid("validity_study_id", study_identity), ) From d2196311dbf4aa572d8a99bedc27d4a178dacc80 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 6 Sep 2026 00:05:16 +0900 Subject: [PATCH 052/603] test(workforce-validation): cover policy equality tripwire --- .../tests/test_policy_runtime_integrity.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_policy_runtime_integrity.py b/services/workforce-validation-api/tests/test_policy_runtime_integrity.py index b3071641f..f712aacfe 100644 --- a/services/workforce-validation-api/tests/test_policy_runtime_integrity.py +++ b/services/workforce-validation-api/tests/test_policy_runtime_integrity.py @@ -22,8 +22,13 @@ class _ExecutableText(str): calls = 0 + def __eq__(self, other: object) -> bool: + """Expose any equality comparison before the boundary rejects the subtype.""" + type(self).calls += 1 + raise AssertionError("caller-defined policy comparison executed") + def __ne__(self, other: object) -> bool: - """Expose any comparison before the boundary rejects the subtype.""" + """Expose any inequality comparison before the boundary rejects the subtype.""" type(self).calls += 1 raise AssertionError("caller-defined policy comparison executed") From 47c3b19ce1e2f35c0e59f92c20b042391901f849 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 6 Sep 2026 00:05:27 +0900 Subject: [PATCH 053/603] test(workforce-validation): keep one registry import style --- .../tests/test_view_issuance_integrity.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/services/workforce-validation-api/tests/test_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_view_issuance_integrity.py index b65e72b04..a44fce40c 100644 --- a/services/workforce-validation-api/tests/test_view_issuance_integrity.py +++ b/services/workforce-validation-api/tests/test_view_issuance_integrity.py @@ -5,7 +5,6 @@ import pytest import orgmetra_workforce_validation_api.registry as registry -from orgmetra_workforce_validation_api.registry import ValidityStudyView TENANT = UUID("10000000-0000-7000-8000-000000000001") @@ -15,7 +14,7 @@ def test_direct_authorized_view_construction_fails_closed() -> None: """Require purpose-bound reads, not public construction, to issue study views.""" with pytest.raises(TypeError, match="issued only by read_validity_study"): - ValidityStudyView( + registry.ValidityStudyView( tenant_record_id=TENANT, validity_study_id=STUDY, fields=(("study_status_code", "study_draft"),), From db7ce6b117052ea4fba59e61f15fd22389abe194 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 6 Sep 2026 00:05:55 +0900 Subject: [PATCH 054/603] test(workforce-validation): use protocol-standard attribute trap --- .../tests/test_principal_storage_integrity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_principal_storage_integrity.py b/services/workforce-validation-api/tests/test_principal_storage_integrity.py index 9473a5b1b..a0b299859 100644 --- a/services/workforce-validation-api/tests/test_principal_storage_integrity.py +++ b/services/workforce-validation-api/tests/test_principal_storage_integrity.py @@ -22,7 +22,7 @@ class _ExecutableUUID(UUID): def __getattribute__(self, name: str) -> object: if name == "int": - raise AssertionError("UUID subtype behavior executed") + raise AttributeError("UUID subtype behavior executed") return super().__getattribute__(name) From 14c10e8fe4861299ab4808d2e25cf25df35c8549 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 6 Sep 2026 00:11:06 +0900 Subject: [PATCH 055/603] test(workforce-validation): reject inherited Protocol repository stub --- .../test_read_port_dependency_integrity.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/services/workforce-validation-api/tests/test_read_port_dependency_integrity.py b/services/workforce-validation-api/tests/test_read_port_dependency_integrity.py index d91fe206c..e49cefc92 100644 --- a/services/workforce-validation-api/tests/test_read_port_dependency_integrity.py +++ b/services/workforce-validation-api/tests/test_read_port_dependency_integrity.py @@ -10,6 +10,7 @@ from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy from orgmetra_workforce_validation_api.registry import ( ValidationPrincipal, + ValidityStudyReadPort, ValidityStudyRecord, read_validity_study, ) @@ -67,6 +68,10 @@ def read_validity_study( ) +class _InheritedProtocolReadPort(ValidityStudyReadPort): + """Intentionally inherit the Protocol declaration without implementing persistence.""" + + def _principal() -> ValidationPrincipal: """Return one exact authenticated validation principal.""" return ValidationPrincipal( @@ -103,6 +108,20 @@ def test_noncallable_repository_capability_fails_before_authorization() -> None: ) +def test_inherited_protocol_placeholder_fails_before_authorization() -> None: + """Require a concrete repository implementation before Keyverse policy evaluation.""" + with pytest.raises(TypeError, match="read_port must expose a statically callable read_validity_study"): + read_validity_study( + principal=_principal(), + tenant_record_id=TENANT, + validity_study_id=STUDY, + purpose_code="validation_review", + requested_fields=frozenset({"study_status_code"}), + policy=_policy(purpose_code="audit_review"), + read_port=_InheritedProtocolReadPort(), + ) + + def test_validated_repository_capability_is_the_capability_invoked_after_authorization() -> None: """Bind the inertly validated class method instead of re-resolving it dynamically.""" port = _DynamicLookupReadPort() From 72ec2296cbc6b2df94e9c4e7394a8990061d0c88 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 6 Sep 2026 00:12:40 +0900 Subject: [PATCH 056/603] fix(workforce-validation): reject inherited Protocol repository stub --- .../src/orgmetra_workforce_validation_api/registry.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py index 78c1628bb..10159e1d8 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -348,6 +348,9 @@ def read_validity_study( ... +_PROTOCOL_READ_CAPABILITY = getattr_static(ValidityStudyReadPort, "read_validity_study") + + def read_validity_study( *, principal: ValidationPrincipal, @@ -373,7 +376,7 @@ def read_validity_study( if type(policy) is not PurposeBoundAccessPolicy: raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") read_capability = getattr_static(type(read_port), "read_validity_study", None) - if type(read_capability) is not FunctionType: + if type(read_capability) is not FunctionType or read_capability is _PROTOCOL_READ_CAPABILITY: raise TypeError("read_port must expose a statically callable read_validity_study.") detached_principal = ValidationPrincipal( From 195ffef5026625d5e1d36b0dbd0175acb4f65108 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 6 Sep 2026 02:05:37 +0900 Subject: [PATCH 057/603] fix(foundation): admit workforce validation postgres contract --- scripts/foundation-contract-core.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/foundation-contract-core.mjs b/scripts/foundation-contract-core.mjs index 4aacefb3c..ba2d8c00b 100644 --- a/scripts/foundation-contract-core.mjs +++ b/scripts/foundation-contract-core.mjs @@ -85,6 +85,7 @@ export const REQUIRED_FILES = Object.freeze([ 'tests/test_audit_outbox_hardening_postgres.sh', 'tests/test_candidate_worker_conversion_postgres.sh', 'tests/test_validity_study_case_postgres.sh', + 'tests/test_workforce_validation_owner_schema_postgres.sh', 'tests/test_criterion_observation_scope_postgres.sh', 'tests/test_people_mutation_idempotency_postgres.sh', 'tests/test_job_analysis_snapshot_postgres.sh', @@ -685,4 +686,4 @@ export function runCli(rootPath, outputStream = process.stdout, errorStream = pr } errorStream.write(`${JSON.stringify({ status: 'failed', error_count: errors.length, errors }, null, 2)}\n`); return 1; -} +} \ No newline at end of file From c91df2374eaf65bb36a337854cd231c601e93cb7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 6 Sep 2026 02:07:00 +0900 Subject: [PATCH 058/603] fix(foundation): register workforce validation postgres provenance --- tests/validate_repository.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/validate_repository.py b/tests/validate_repository.py index d9d4c15a3..1a05c8efd 100644 --- a/tests/validate_repository.py +++ b/tests/validate_repository.py @@ -88,6 +88,7 @@ "tests/test_audit_outbox_hardening_postgres.sh", "tests/test_candidate_worker_conversion_postgres.sh", "tests/test_validity_study_case_postgres.sh", + "tests/test_workforce_validation_owner_schema_postgres.sh", "tests/test_criterion_observation_scope_postgres.sh", "tests/test_people_mutation_idempotency_postgres.sh", "tests/test_job_analysis_snapshot_postgres.sh", @@ -634,4 +635,4 @@ def main() -> None: if __name__ == "__main__": - main() + main() \ No newline at end of file From e87d28a32683c6e6f115b3d13645b7d263451795 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 6 Sep 2026 02:33:19 +0900 Subject: [PATCH 059/603] fix(foundation): reseal workforce validation postgres provenance --- manifest.json | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/manifest.json b/manifest.json index fbae55b2a..f4085d0e1 100644 --- a/manifest.json +++ b/manifest.json @@ -359,9 +359,9 @@ }, { "path": "scripts/foundation-contract-core.mjs", - "sha256": "9b03efbbdffa60a05f5924e8a61b1cbc3cd75c502df428a5920085e8d0bf3603", - "bytes": 28121, - "lines": 688 + "sha256": "5dfc54d40820dfc45962dcc91367c57baf6b011e68efc5f6e8d59e7e82145b2a", + "bytes": 28182, + "lines": 689 }, { "path": "scripts/foundation-contract.mjs", @@ -465,11 +465,17 @@ "bytes": 14708, "lines": 301 }, + { + "path": "tests/test_workforce_validation_owner_schema_postgres.sh", + "sha256": "29f0cd8a7d9040ff86095b68fa2f3d0ed54ea3777e5a816d4a79eb6ceafb9339", + "bytes": 2949, + "lines": 76 + }, { "path": "tests/validate_repository.py", - "sha256": "091836b2f68600a30b08f7da2cea8b3bef10201a123da720a7369bf10985eec2", - "bytes": 27237, - "lines": 637 + "sha256": "244627252e7392e4dbed98392c132cb86dc8e5ead839a1129298e8d022fcf8eb", + "bytes": 27300, + "lines": 638 } ] } From dd95dd7256f37aab2c4f26aa1fb43e8c867f4e4d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 6 Sep 2026 04:07:23 +0900 Subject: [PATCH 060/603] test(workforce-validation): cover policy field runtime guard --- .../tests/test_policy_runtime_integrity.py | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/services/workforce-validation-api/tests/test_policy_runtime_integrity.py b/services/workforce-validation-api/tests/test_policy_runtime_integrity.py index f712aacfe..c72a6c228 100644 --- a/services/workforce-validation-api/tests/test_policy_runtime_integrity.py +++ b/services/workforce-validation-api/tests/test_policy_runtime_integrity.py @@ -21,6 +21,7 @@ class _ExecutableText(str): """Trip if authorization compares this caller-defined string subtype.""" calls = 0 + __hash__ = str.__hash__ def __eq__(self, other: object) -> bool: """Expose any equality comparison before the boundary rejects the subtype.""" @@ -77,3 +78,36 @@ def test_policy_text_subtype_is_rejected_before_comparison_or_persistence() -> N assert _ExecutableText.calls == 0 assert port.calls == 0 + + +def test_policy_field_subtype_is_rejected_before_comparison_or_persistence() -> None: + _ExecutableText.calls = 0 + port = _ReadPort() + assert isinstance(port, ValidityStudyReadPort) + policy = PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="validation-read-v1", + resource_kind="validity_study_record", + purpose_code="validation_review", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=frozenset({_ExecutableText("study_status_code")}), + ) + + with pytest.raises(ValueError, match="policy permitted_fields"): + read_validity_study( + principal=ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ), + tenant_record_id=TENANT, + validity_study_id=STUDY, + purpose_code="validation_review", + requested_fields=frozenset({"study_status_code"}), + policy=policy, + read_port=port, + ) + + assert _ExecutableText.calls == 0 + assert port.calls == 0 From 6f0acf59893aa73c8f834526a92bde924ad2a225 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 08:08:47 +0900 Subject: [PATCH 061/603] test(workforce-validation): require calibration auxiliary authority resolution --- .../test_calibration_auxiliary_authority.py | 348 ++++++++++++++++++ 1 file changed, 348 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py diff --git a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py new file mode 100644 index 000000000..f59d8c9c5 --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py @@ -0,0 +1,348 @@ +"""Fail-closed contract for resolving calibration auxiliary-use authority.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.scientific_authority import ( + CalibrationAuxiliaryAuthorityIntegrityError, + CalibrationAuxiliaryAuthorityNotFound, + CalibrationAuxiliaryAuthorityReadPort, + CalibrationAuxiliaryAuthorityRecord, + CalibrationAuxiliaryAuthorityView, + resolve_calibration_auxiliary_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000c1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000c2") +AUTHORITY_REFERENCE = ( + "scientific_auxiliary_authority:11111111-1111-4111-8111-111111111111" +) +PROJECTION_REFERENCE = ( + "calibration_auxiliary_projection:22222222-2222-4222-8222-222222222222" +) +PURPOSE_REFERENCE = ( + "scientific_data_use_purpose:33333333-3333-4333-8333-333333333333" +) +OWNER_CONTRACT_REFERENCE = ( + "released_owner_contract:44444444-4444-4444-8444-444444444444" +) +AUTHORIZATION_REFERENCE = ( + "scientific_data_authorization:55555555-5555-4555-8555-555555555555" +) +PROJECTION_DIGEST = "1" * 64 +PURPOSE_DIGEST = "2" * 64 +OWNER_CONTRACT_DIGEST = "3" * 64 +AUTHORIZATION_DIGEST = "4" * 64 +AUTHORIZED_FROM = datetime(2026, 9, 1, tzinfo=timezone.utc) +AUTHORIZED_TO = datetime(2026, 10, 1, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "authority_reference", + "auxiliary_projection_reference", + "auxiliary_projection_digest", + "scientific_purpose_reference", + "scientific_purpose_digest", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "authorization_receipt_reference", + "authorization_receipt_digest", + "authorized_from", + "authorized_to", + } +) + + +class _ReadPort: + """Return one configured authority record and retain the exact lookup coordinates.""" + + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[tuple[object, ...]] = [] + + def read_calibration_auxiliary_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + auxiliary_projection_reference: str, + auxiliary_projection_digest: str, + scientific_purpose_reference: str, + scientific_purpose_digest: str, + owner_contract_reference: str, + owner_contract_version: int, + authorization_receipt_digest: str, + ) -> object: + """Capture the owner lookup and return the configured result.""" + self.calls.append( + ( + tenant_record_id, + validity_study_id, + auxiliary_projection_reference, + auxiliary_projection_digest, + scientific_purpose_reference, + scientific_purpose_digest, + owner_contract_reference, + owner_contract_version, + authorization_receipt_digest, + ) + ) + return self.result + + +class _NoReadMethod: + """Deliberately fail the owner-port protocol.""" + + +class _ProtocolOnly(CalibrationAuxiliaryAuthorityReadPort): + """Inherit only the Protocol placeholder, not a concrete owner capability.""" + + +class _DescriptorReadPort: + """Expose a descriptor that must be rejected without executing it.""" + + @property + def read_calibration_auxiliary_authority(self) -> object: + raise AssertionError("descriptor must not execute") + + +def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=tenant_record_id, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="calibration-authority-read-v1", + resource_kind="calibration_auxiliary_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record(**overrides: object) -> CalibrationAuxiliaryAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "authority_reference": AUTHORITY_REFERENCE, + "auxiliary_projection_reference": PROJECTION_REFERENCE, + "auxiliary_projection_digest": PROJECTION_DIGEST, + "scientific_purpose_reference": PURPOSE_REFERENCE, + "scientific_purpose_digest": PURPOSE_DIGEST, + "owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "owner_contract_version": 7, + "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "authorization_receipt_reference": AUTHORIZATION_REFERENCE, + "authorization_receipt_digest": AUTHORIZATION_DIGEST, + "authorized_from": AUTHORIZED_FROM, + "authorized_to": AUTHORIZED_TO, + } + values.update(overrides) + return CalibrationAuxiliaryAuthorityRecord(**values) + + +def _resolve(*, read_port: object, **overrides: object) -> CalibrationAuxiliaryAuthorityView: + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "auxiliary_projection_reference": PROJECTION_REFERENCE, + "auxiliary_projection_digest": PROJECTION_DIGEST, + "scientific_purpose_reference": PURPOSE_REFERENCE, + "scientific_purpose_digest": PURPOSE_DIGEST, + "owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "owner_contract_version": 7, + "authorization_receipt_digest": AUTHORIZATION_DIGEST, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_calibration_auxiliary_authority(**values) + + +def test_resolution_authorizes_then_returns_minimized_corroborated_evidence() -> None: + port = _ReadPort(_record()) + + view = _resolve(read_port=port) + + assert isinstance(port, CalibrationAuxiliaryAuthorityReadPort) + assert port.calls == [ + ( + TENANT, + STUDY, + PROJECTION_REFERENCE, + PROJECTION_DIGEST, + PURPOSE_REFERENCE, + PURPOSE_DIGEST, + OWNER_CONTRACT_REFERENCE, + 7, + AUTHORIZATION_DIGEST, + ) + ] + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + assert view.fields == ( + ("authority_reference", AUTHORITY_REFERENCE), + ("authorization_receipt_digest", AUTHORIZATION_DIGEST), + ("authorization_receipt_reference", AUTHORIZATION_REFERENCE), + ("authorized_from", AUTHORIZED_FROM), + ("authorized_to", AUTHORIZED_TO), + ("auxiliary_projection_digest", PROJECTION_DIGEST), + ("auxiliary_projection_reference", PROJECTION_REFERENCE), + ("owner_contract_digest", OWNER_CONTRACT_DIGEST), + ("owner_contract_reference", OWNER_CONTRACT_REFERENCE), + ("owner_contract_version", 7), + ("scientific_purpose_digest", PURPOSE_DIGEST), + ("scientific_purpose_reference", PURPOSE_REFERENCE), + ) + + +def test_authorization_denial_happens_before_owner_resolution() -> None: + port = _ReadPort(_record()) + + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, policy=_policy(purpose_code="audit_review")) + + assert port.calls == [] + + +def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: + with pytest.raises(CalibrationAuxiliaryAuthorityNotFound): + _resolve(read_port=_ReadPort(None)) + + with pytest.raises(CalibrationAuxiliaryAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object())) + + +@pytest.mark.parametrize( + ("record_overrides", "request_overrides"), + [ + ({"tenant_record_id": OTHER_TENANT}, {}), + ({"validity_study_id": OTHER_STUDY}, {}), + ({"auxiliary_projection_reference": "calibration_auxiliary_projection:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa"}, {}), + ({"auxiliary_projection_digest": "a" * 64}, {}), + ({"scientific_purpose_reference": "scientific_data_use_purpose:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb"}, {}), + ({"scientific_purpose_digest": "b" * 64}, {}), + ({"owner_contract_reference": "released_owner_contract:cccccccc-cccc-4ccc-8ccc-cccccccccccc"}, {}), + ({"owner_contract_version": 8}, {}), + ({"authorization_receipt_digest": "c" * 64}, {}), + ({"authorized_from": USED_AT + timedelta(seconds=1)}, {}), + ({"authorized_to": USED_AT}, {}), + ], +) +def test_resolved_authority_must_match_every_requested_coordinate_and_use_time( + record_overrides: dict[str, object], request_overrides: dict[str, object] +) -> None: + with pytest.raises(CalibrationAuxiliaryAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(**record_overrides)), **request_overrides) + + +def test_open_ended_authority_interval_accepts_later_use() -> None: + view = _resolve(read_port=_ReadPort(_record(authorized_to=None))) + assert dict(view.fields)["authorized_to"] is None + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("auxiliary_projection_reference", "wrong:projection", ValueError), + ("auxiliary_projection_digest", "ABC", ValueError), + ("scientific_purpose_reference", "wrong:purpose", ValueError), + ("scientific_purpose_digest", "2" * 63, ValueError), + ("owner_contract_reference", "wrong:contract", ValueError), + ("owner_contract_version", True, ValueError), + ("authorization_receipt_digest", "4" * 65, ValueError), + ("used_at", datetime(2026, 9, 17), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_or_dependency_fails_before_owner_resolution( + key: str, value: object, error: type[Exception] +) -> None: + port = _ReadPort(_record()) + overrides = {key: value} + if key == "read_port": + port = value # type: ignore[assignment] + overrides = {} + with pytest.raises(error): + _resolve(read_port=port, **overrides) + if isinstance(port, _ReadPort): + assert port.calls == [] + + +@pytest.mark.parametrize( + ("key", "value"), + [ + ("tenant_record_id", UUID(int=0)), + ("validity_study_id", "not-a-uuid"), + ("authority_reference", "wrong:authority"), + ("auxiliary_projection_reference", "wrong:projection"), + ("auxiliary_projection_digest", "1" * 63), + ("scientific_purpose_reference", "wrong:purpose"), + ("scientific_purpose_digest", "2" * 65), + ("owner_contract_reference", "wrong:contract"), + ("owner_contract_version", 0), + ("owner_contract_digest", "3" * 63), + ("authorization_receipt_reference", "wrong:authorization"), + ("authorization_receipt_digest", "4" * 63), + ("authorized_from", datetime(2026, 9, 1)), + ("authorized_to", "not-a-datetime"), + ], +) +def test_record_rejects_invalid_authority_evidence(key: str, value: object) -> None: + with pytest.raises(ValueError): + _record(**{key: value}) + + +def test_record_rejects_empty_or_reversed_authorization_interval() -> None: + for invalid_end in (AUTHORIZED_FROM, AUTHORIZED_FROM - timedelta(seconds=1)): + with pytest.raises(ValueError): + _record(authorized_to=invalid_end) + + +def test_record_and_view_are_structurally_immutable_and_uuid_views_are_detached() -> None: + tenant = UUID(str(TENANT)) + record = _record(tenant_record_id=tenant) + object.__setattr__(tenant, "int", OTHER_TENANT.int) + assert record.tenant_record_id == TENANT + + with pytest.raises(AttributeError): + object.__setattr__(record, "owner_contract_version", 999) + + view = _resolve(read_port=_ReadPort(record)) + returned_tenant = view.tenant_record_id + object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) + assert view.tenant_record_id == TENANT + + with pytest.raises(AttributeError): + object.__setattr__(view, "fields", ()) + with pytest.raises(TypeError): + CalibrationAuxiliaryAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) From 64b7b9a61ffd3ac48fb590a7aa673a1aff00bf82 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 08:09:37 +0900 Subject: [PATCH 062/603] feat(workforce-validation): resolve calibration auxiliary authority --- .../scientific_authority.py | 479 ++++++++++++++++++ 1 file changed, 479 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py new file mode 100644 index 000000000..853accda4 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py @@ -0,0 +1,479 @@ +"""Resolve purpose-bound scientific auxiliary-use authority through its owner port. + +This application boundary corroborates opaque calibration auxiliary coordinates +without copying protected auxiliary values or querying another bounded context's +application tables. It deliberately stops before durable PostgreSQL adoption: +the repository port must later be backed by released/versioned owner evidence. +The returned projection is data, not a reusable authorization credential. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +import re +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) + +_DIGEST_PATTERN = re.compile(r"^[0-9a-f]{64}$") +_REFERENCE_PATTERN = re.compile(r"^[a-z][a-z0-9_]*:[A-Za-z0-9][A-Za-z0-9._~-]*$") +_RESOURCE_KIND = "calibration_auxiliary_authority" +_OPERATION = "read" +_READ_FIELDS = frozenset( + { + "authority_reference", + "auxiliary_projection_reference", + "auxiliary_projection_digest", + "scientific_purpose_reference", + "scientific_purpose_digest", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "authorization_receipt_reference", + "authorization_receipt_digest", + "authorized_from", + "authorized_to", + } +) + + +class CalibrationAuxiliaryAuthorityNotFound(LookupError): + """Indicate that no owner evidence corroborates the requested authority tuple.""" + + +class CalibrationAuxiliaryAuthorityIntegrityError(RuntimeError): + """Indicate that owner evidence does not match the authorized scientific use.""" + + +def _require_reference(field_name: str, value: object, namespace: str) -> str: + """Require one exact opaque namespaced reference without protected source values.""" + if ( + type(value) is not str + or _REFERENCE_PATTERN.fullmatch(value) is None + or value.partition(":")[0] != namespace + ): + raise ValueError(f"{field_name} must be an exact {namespace}: opaque reference.") + return value + + +def _require_digest(field_name: str, value: object) -> str: + """Require lowercase SHA-256 evidence rather than caller-readable source content.""" + if type(value) is not str or _DIGEST_PATTERN.fullmatch(value) is None: + raise ValueError(f"{field_name} must be lowercase SHA-256 hex.") + return value + + +def _require_positive_integer(field_name: str, value: object) -> int: + """Require a strict positive integer contract version without accepting booleans.""" + if type(value) is not int or value <= 0: + raise ValueError(f"{field_name} must be a positive integer.") + return value + + +class CalibrationAuxiliaryAuthorityRecord(tuple): + """Immutable owner projection corroborating one auxiliary-use authorization. + + Only opaque references, digests, versions, target identities, and the exact + authorization interval cross this boundary. Raw calibration attributes, + benchmark values, protected characteristics, and row-level weights remain + behind their authoritative owners. + """ + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + authority_reference: str, + auxiliary_projection_reference: str, + auxiliary_projection_digest: str, + scientific_purpose_reference: str, + scientific_purpose_digest: str, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + authorization_receipt_reference: str, + authorization_receipt_digest: str, + authorized_from: datetime, + authorized_to: datetime | None, + ) -> CalibrationAuxiliaryAuthorityRecord: + """Validate and detach every authority-bearing scalar before tuple storage.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + authority_ref = _require_reference( + "authority_reference", authority_reference, "scientific_auxiliary_authority" + ) + projection_ref = _require_reference( + "auxiliary_projection_reference", + auxiliary_projection_reference, + "calibration_auxiliary_projection", + ) + projection_digest = _require_digest( + "auxiliary_projection_digest", auxiliary_projection_digest + ) + purpose_ref = _require_reference( + "scientific_purpose_reference", + scientific_purpose_reference, + "scientific_data_use_purpose", + ) + purpose_digest = _require_digest("scientific_purpose_digest", scientific_purpose_digest) + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + authorization_ref = _require_reference( + "authorization_receipt_reference", + authorization_receipt_reference, + "scientific_data_authorization", + ) + authorization_digest = _require_digest( + "authorization_receipt_digest", authorization_receipt_digest + ) + authorization_start = _require_aware_datetime("authorized_from", authorized_from) + authorization_end = ( + None + if authorized_to is None + else _require_aware_datetime("authorized_to", authorized_to) + ) + if authorization_end is not None and authorization_end <= authorization_start: + raise ValueError("authorized_to must be later than authorized_from.") + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + authority_ref, + projection_ref, + projection_digest, + purpose_ref, + purpose_digest, + owner_ref, + owner_version, + owner_digest, + authorization_ref, + authorization_digest, + authorization_start, + authorization_end, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity for this owner evidence.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity bound to the scientific use.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def authority_reference(self) -> str: + """Return the opaque owner authority reference.""" + return self[2] + + @property + def auxiliary_projection_reference(self) -> str: + """Return the opaque purpose-limited auxiliary projection reference.""" + return self[3] + + @property + def auxiliary_projection_digest(self) -> str: + """Return the projection evidence digest without exposing source attributes.""" + return self[4] + + @property + def scientific_purpose_reference(self) -> str: + """Return the governed scientific-use purpose reference.""" + return self[5] + + @property + def scientific_purpose_digest(self) -> str: + """Return the exact scientific-use purpose evidence digest.""" + return self[6] + + @property + def owner_contract_reference(self) -> str: + """Return the released owner-contract reference.""" + return self[7] + + @property + def owner_contract_version(self) -> int: + """Return the positive released owner-contract version.""" + return self[8] + + @property + def owner_contract_digest(self) -> str: + """Return the immutable bytes digest for the released owner contract.""" + return self[9] + + @property + def authorization_receipt_reference(self) -> str: + """Return the authoritative scientific-use authorization receipt reference.""" + return self[10] + + @property + def authorization_receipt_digest(self) -> str: + """Return the authorization receipt digest used for exact correlation.""" + return self[11] + + @property + def authorized_from(self) -> datetime: + """Return the UTC instant when this scientific use became authorized.""" + return self[12] + + @property + def authorized_to(self) -> datetime | None: + """Return the exclusive UTC authorization end when one exists.""" + return self[13] + + +class CalibrationAuxiliaryAuthorityView(tuple): + """Field-minimized owner evidence issued only after authorization and resolution.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> CalibrationAuxiliaryAuthorityView: + """Reject public construction; the resolver is the only supported issuer.""" + raise TypeError( + "CalibrationAuxiliaryAuthorityView is issued only by " + "resolve_calibration_auxiliary_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable corroborating authority fields without protected values.""" + return self[2] + + +@runtime_checkable +class CalibrationAuxiliaryAuthorityReadPort(Protocol): + """Owner read contract for released calibration auxiliary-use authority evidence.""" + + def read_calibration_auxiliary_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + auxiliary_projection_reference: str, + auxiliary_projection_digest: str, + scientific_purpose_reference: str, + scientific_purpose_digest: str, + owner_contract_reference: str, + owner_contract_version: int, + authorization_receipt_digest: str, + ) -> CalibrationAuxiliaryAuthorityRecord | None: + """Return matching released authority evidence or ``None`` through an owner ACL.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + CalibrationAuxiliaryAuthorityReadPort, "read_calibration_auxiliary_authority" +) + + +def resolve_calibration_auxiliary_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + auxiliary_projection_reference: str, + auxiliary_projection_digest: str, + scientific_purpose_reference: str, + scientific_purpose_digest: str, + owner_contract_reference: str, + owner_contract_version: int, + authorization_receipt_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: CalibrationAuxiliaryAuthorityReadPort, +) -> CalibrationAuxiliaryAuthorityView: + """Authorize and corroborate one calibration auxiliary-use authority tuple. + + The exact owner capability is captured inertly before authorization and the + same function is invoked afterward. The request carries no protected source + values. Owner evidence must then reproduce every caller-supplied coordinate + and cover the exact scientific-use instant before any corroborating fields + are returned. + """ + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static( + type(read_port), "read_calibration_auxiliary_authority", None + ) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError( + "read_port must expose a statically callable " + "read_calibration_auxiliary_authority." + ) + + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + tenant_id = _restore_operational_uuid("tenant_record_id", tenant_identity) + study_id = _restore_operational_uuid("validity_study_id", study_identity) + projection_ref = _require_reference( + "auxiliary_projection_reference", + auxiliary_projection_reference, + "calibration_auxiliary_projection", + ) + projection_digest = _require_digest( + "auxiliary_projection_digest", auxiliary_projection_digest + ) + purpose_ref = _require_reference( + "scientific_purpose_reference", + scientific_purpose_reference, + "scientific_data_use_purpose", + ) + purpose_digest = _require_digest("scientific_purpose_digest", scientific_purpose_digest) + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer("owner_contract_version", owner_contract_version) + authorization_digest = _require_digest( + "authorization_receipt_digest", authorization_receipt_digest + ) + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=_restore_operational_uuid("tenant_record_id", tenant_identity), + validity_study_id=_restore_operational_uuid("validity_study_id", study_identity), + auxiliary_projection_reference=projection_ref, + auxiliary_projection_digest=projection_digest, + scientific_purpose_reference=purpose_ref, + scientific_purpose_digest=purpose_digest, + owner_contract_reference=owner_ref, + owner_contract_version=owner_version, + authorization_receipt_digest=authorization_digest, + ) + if persisted is None: + raise CalibrationAuxiliaryAuthorityNotFound(str(study_id)) + if type(persisted) is not CalibrationAuxiliaryAuthorityRecord: + raise CalibrationAuxiliaryAuthorityIntegrityError( + "owner port returned non-canonical calibration auxiliary authority evidence" + ) + + record = CalibrationAuxiliaryAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + authority_reference=persisted.authority_reference, + auxiliary_projection_reference=persisted.auxiliary_projection_reference, + auxiliary_projection_digest=persisted.auxiliary_projection_digest, + scientific_purpose_reference=persisted.scientific_purpose_reference, + scientific_purpose_digest=persisted.scientific_purpose_digest, + owner_contract_reference=persisted.owner_contract_reference, + owner_contract_version=persisted.owner_contract_version, + owner_contract_digest=persisted.owner_contract_digest, + authorization_receipt_reference=persisted.authorization_receipt_reference, + authorization_receipt_digest=persisted.authorization_receipt_digest, + authorized_from=persisted.authorized_from, + authorized_to=persisted.authorized_to, + ) + if ( + _store_operational_uuid("record tenant_record_id", record.tenant_record_id) + != tenant_identity + or _store_operational_uuid("record validity_study_id", record.validity_study_id) + != study_identity + or record.auxiliary_projection_reference != projection_ref + or record.auxiliary_projection_digest != projection_digest + or record.scientific_purpose_reference != purpose_ref + or record.scientific_purpose_digest != purpose_digest + or record.owner_contract_reference != owner_ref + or record.owner_contract_version != owner_version + or record.authorization_receipt_digest != authorization_digest + ): + raise CalibrationAuxiliaryAuthorityIntegrityError( + "owner evidence does not match the requested calibration auxiliary authority" + ) + if use_instant < record.authorized_from or ( + record.authorized_to is not None and use_instant >= record.authorized_to + ): + raise CalibrationAuxiliaryAuthorityIntegrityError( + "scientific use falls outside the resolved authorization interval" + ) + + values = { + "authority_reference": record.authority_reference, + "auxiliary_projection_reference": record.auxiliary_projection_reference, + "auxiliary_projection_digest": record.auxiliary_projection_digest, + "scientific_purpose_reference": record.scientific_purpose_reference, + "scientific_purpose_digest": record.scientific_purpose_digest, + "owner_contract_reference": record.owner_contract_reference, + "owner_contract_version": record.owner_contract_version, + "owner_contract_digest": record.owner_contract_digest, + "authorization_receipt_reference": record.authorization_receipt_reference, + "authorization_receipt_digest": record.authorization_receipt_digest, + "authorized_from": record.authorized_from, + "authorized_to": record.authorized_to, + } + fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) + return tuple.__new__( + CalibrationAuxiliaryAuthorityView, + (tenant_identity, study_identity, fields), + ) From 70b45ae94f40c867f27ee125bd81301d75723578 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 08:09:51 +0900 Subject: [PATCH 063/603] feat(workforce-validation): export scientific authority contract --- .../orgmetra_workforce_validation_api/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index 48570a975..61032025f 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -9,8 +9,21 @@ ValidityStudyView, read_validity_study, ) +from orgmetra_workforce_validation_api.scientific_authority import ( + CalibrationAuxiliaryAuthorityIntegrityError, + CalibrationAuxiliaryAuthorityNotFound, + CalibrationAuxiliaryAuthorityReadPort, + CalibrationAuxiliaryAuthorityRecord, + CalibrationAuxiliaryAuthorityView, + resolve_calibration_auxiliary_authority, +) __all__ = [ + "CalibrationAuxiliaryAuthorityIntegrityError", + "CalibrationAuxiliaryAuthorityNotFound", + "CalibrationAuxiliaryAuthorityReadPort", + "CalibrationAuxiliaryAuthorityRecord", + "CalibrationAuxiliaryAuthorityView", "ValidationPrincipal", "ValidityStudyIntegrityError", "ValidityStudyNotFound", @@ -18,4 +31,5 @@ "ValidityStudyRecord", "ValidityStudyView", "read_validity_study", + "resolve_calibration_auxiliary_authority", ] From b981214f3936d097a62711db290464bb95e2ebdc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 08:10:45 +0900 Subject: [PATCH 064/603] docs(workforce-validation): describe scientific authority resolution --- services/workforce-validation-api/README.md | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index d3d847361..33993d619 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -1,8 +1,8 @@ # Orgmetra Workforce Validation API -This package is the application boundary for the `workforce_validation` bounded context. The current slice exposes one purpose-bound read use case for the existing validity-study registry header and establishes the context-local PostgreSQL ownership bootstrap. +This package is the application boundary for the `workforce_validation` bounded context. The current slice exposes purpose-bound owner reads for the existing validity-study registry header and for value-minimized scientific auxiliary-use authority, while establishing the context-local PostgreSQL ownership bootstrap. -It does **not** query People, Talent Acquisition, Performance Management, Job Architecture, Psychometrics Commons, fast-mlsirm, or TEPP tables. Those contexts remain separate owners. Exact foreign identifiers and immutable specialist result references cross the boundary only through published contracts. +It does **not** query People, Talent Acquisition, Performance Management, Job Architecture, Psychometrics Commons, fast-mlsirm, TEPP, or another bounded context's application tables. Those contexts remain separate owners. Exact foreign identifiers and immutable specialist/scientific evidence cross this boundary only through released/versioned contracts and owner ports. ## Current slice @@ -22,11 +22,23 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar `ValidityStudyView` is a data projection, not a durable authorization credential or cryptographic capability. Downstream consequential actions must perform their own purpose-bound authorization and authoritative re-resolution rather than treating the Python runtime type as reusable authority. Low-level interpreter construction is outside the supported public API and is not accepted as proof that authorization occurred. +`resolve_calibration_auxiliary_authority(...)` is the first executable owner-side slice for #407's durable scientific-evidence resolution gap. It does **not** import or copy the mutable validity-analysis implementation. Instead it defines the `workforce_validation` application contract that a later durable adapter must satisfy: + +- authorize the exact tenant/study scientific read before invoking the owner port; +- carry only opaque projection/purpose/owner/authorization references, SHA-256 evidence digests, immutable contract versions, and authorization time bounds—never calibration source attributes, protected characteristics, benchmark values, or row-level weights; +- require a released-owner-contract reference/version and corroborating owner-contract digest rather than treating a caller-supplied version label as release authority; +- resolve through one statically captured `CalibrationAuxiliaryAuthorityReadPort` capability and reject inherited Protocol placeholders or descriptors before authorization; +- reconstruct the returned evidence into an exact tuple-backed `CalibrationAuxiliaryAuthorityRecord` and require tenant, study, projection, scientific purpose, released owner contract, and authorization-receipt digest to match the requested coordinates; +- require the exact scientific-use instant to fall inside the owner-resolved authorization interval; +- issue only a minimized `CalibrationAuxiliaryAuthorityView`. The view is corroborating data, not a reusable authorization credential or proof that an arbitrary injected port is a production owner. + +This closes the leaf false-GREEN where opaque coordinates could be accepted without any owner-resolution contract. It does **not** complete #407: the current branch has no durable scientific-authority relation or released auxiliary-evidence adapter. After the canonical owner persistence path is protected truth, #248 or its verified successor must implement the schema-qualified, least-privilege durable port and prove that the resolved owner evidence is itself released/versioned and purpose-authorized. Mutable #57 source is not a dependency of this service. + `services/workforce-validation-api/database/migrations/0001_owner_schema.sql` starts this bounded context's own migration history. It creates the `workforce_validation` schema and deny-default `workforce_validation_role`, revokes public schema access, and intentionally creates or moves no application table yet. The role is a **NOLOGIN migration/schema owner only**; runtime principals must not be granted that owner role. PostgreSQL applies role-level configuration defaults at login and does not re-apply them on `SET ROLE`, so an `ALTER ROLE ... SET search_path` entry on this NOLOGIN role is not treated as a runtime isolation control. The later durable adapter must use a distinct least-privilege runtime role, schema-qualified `workforce_validation` relations, and explicit function-level `search_path` where `SECURITY DEFINER` code is introduced. Protected foundation migrations still create validity-study tables in the legacy foundation schema, so the next forward-only persistence increment must adopt those records without normalizing `public.validity_study` as a long-lived service contract or breaking existing linkage evidence. -Issue #234 owns the remaining order: durable owner-schema adoption and PostgreSQL adapter, idempotent registration, explicit predictor/sample/decision-policy/analysis-protocol versions, scientific adapters, OpenAPI/gateway exposure, and realistic p95 measurement. Issues #236–#244 retain the current bootstrap trust-boundary findings through exact-head acceptance and protected integration: persisted-record immutability, principal immutability and constructor revalidation, owner-role/runtime-role separation, inert repository-capability validation, immutable minimized output, non-public issuance of that output, detached UUID storage/target snapshots, and exact validation of UUID internal payloads before comparison. +Issue #234 owns the remaining order: durable owner-schema adoption and PostgreSQL adapter, idempotent registration, explicit predictor/sample/decision-policy/analysis-protocol versions, scientific adapters, OpenAPI/gateway exposure, and realistic p95 measurement. Issues #236–#244 retain the current bootstrap trust-boundary findings through exact-head acceptance and protected integration: persisted-record immutability, principal immutability and constructor revalidation, owner-role/runtime-role separation, inert repository-capability validation, immutable minimized output, non-public issuance of that output, detached UUID storage/target snapshots, and exact validation of UUID internal payloads before comparison. Issue #407 additionally keeps durable scientific-authority resolution open until owner persistence/released evidence, exact-head GREEN, independent review, and protected integration are real. ## Test @@ -39,6 +51,8 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ services/workforce-validation-api/tests ``` +The service package keeps an exact 100% owned statement/branch threshold. The calibration-authority contract adds hostile coverage for authorization-before-owner-read, non-concrete/dynamic owner capabilities, malformed references/digests/versions/timestamps, foreign/mismatched owner evidence, authorization-window mismatch, UUID alias mutation, structural immutability, and non-public view issuance. + The same Foundation job also runs `tests/test_workforce_validation_owner_schema_postgres.sh` in its own pinned PostgreSQL 16.14 container. That contract executes the service-local owner migration and checks the exact deny-default role flags, schema owner, absence of ineffective login-only `rolconfig`, actual `SET ROLE` search-path behavior, absence of inherited PUBLIC `USAGE`/`CREATE`, and absence of application relations in the bootstrap schema. The test intentionally demonstrates that `SET ROLE` retains the caller's existing `search_path`; runtime isolation therefore cannot be inferred from owner-role metadata. Those source contracts are not terminal acceptance by themselves. The slice remains Draft until the exact current head actually executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and the normal review/governance requirements are satisfied. Only then may the next forward-only owner-table adoption and durable adapter be treated as eligible for integration. From c01adbb492c1f314e1c4e490da3cbae45e2a5cc8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 08:14:42 +0900 Subject: [PATCH 065/603] test(workforce-validation): bind authority to owner-resolved scientific use --- .../test_calibration_auxiliary_authority.py | 75 +++++++++++++++++-- 1 file changed, 68 insertions(+), 7 deletions(-) diff --git a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py index f59d8c9c5..f17b71f00 100644 --- a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py +++ b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py @@ -37,10 +37,14 @@ AUTHORIZATION_REFERENCE = ( "scientific_data_authorization:55555555-5555-4555-8555-555555555555" ) +SCIENTIFIC_USE_REFERENCE = ( + "scientific_use_receipt:66666666-6666-4666-8666-666666666666" +) PROJECTION_DIGEST = "1" * 64 PURPOSE_DIGEST = "2" * 64 OWNER_CONTRACT_DIGEST = "3" * 64 AUTHORIZATION_DIGEST = "4" * 64 +SCIENTIFIC_USE_DIGEST = "5" * 64 AUTHORIZED_FROM = datetime(2026, 9, 1, tzinfo=timezone.utc) AUTHORIZED_TO = datetime(2026, 10, 1, tzinfo=timezone.utc) USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) @@ -56,6 +60,9 @@ "owner_contract_digest", "authorization_receipt_reference", "authorization_receipt_digest", + "scientific_use_receipt_reference", + "scientific_use_receipt_digest", + "scientific_use_at", "authorized_from", "authorized_to", } @@ -81,6 +88,7 @@ def read_calibration_auxiliary_authority( owner_contract_reference: str, owner_contract_version: int, authorization_receipt_digest: str, + scientific_use_receipt_digest: str, ) -> object: """Capture the owner lookup and return the configured result.""" self.calls.append( @@ -94,6 +102,7 @@ def read_calibration_auxiliary_authority( owner_contract_reference, owner_contract_version, authorization_receipt_digest, + scientific_use_receipt_digest, ) ) return self.result @@ -149,6 +158,9 @@ def _record(**overrides: object) -> CalibrationAuxiliaryAuthorityRecord: "owner_contract_digest": OWNER_CONTRACT_DIGEST, "authorization_receipt_reference": AUTHORIZATION_REFERENCE, "authorization_receipt_digest": AUTHORIZATION_DIGEST, + "scientific_use_receipt_reference": SCIENTIFIC_USE_REFERENCE, + "scientific_use_receipt_digest": SCIENTIFIC_USE_DIGEST, + "scientific_use_at": USED_AT, "authorized_from": AUTHORIZED_FROM, "authorized_to": AUTHORIZED_TO, } @@ -168,6 +180,7 @@ def _resolve(*, read_port: object, **overrides: object) -> CalibrationAuxiliaryA "owner_contract_reference": OWNER_CONTRACT_REFERENCE, "owner_contract_version": 7, "authorization_receipt_digest": AUTHORIZATION_DIGEST, + "scientific_use_receipt_digest": SCIENTIFIC_USE_DIGEST, "used_at": USED_AT, "purpose_code": "selection_validity_analysis", "policy": _policy(), @@ -194,6 +207,7 @@ def test_resolution_authorizes_then_returns_minimized_corroborated_evidence() -> OWNER_CONTRACT_REFERENCE, 7, AUTHORIZATION_DIGEST, + SCIENTIFIC_USE_DIGEST, ) ] assert view.tenant_record_id == TENANT @@ -211,6 +225,9 @@ def test_resolution_authorizes_then_returns_minimized_corroborated_evidence() -> ("owner_contract_version", 7), ("scientific_purpose_digest", PURPOSE_DIGEST), ("scientific_purpose_reference", PURPOSE_REFERENCE), + ("scientific_use_at", USED_AT), + ("scientific_use_receipt_digest", SCIENTIFIC_USE_DIGEST), + ("scientific_use_receipt_reference", SCIENTIFIC_USE_REFERENCE), ) @@ -236,15 +253,36 @@ def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: [ ({"tenant_record_id": OTHER_TENANT}, {}), ({"validity_study_id": OTHER_STUDY}, {}), - ({"auxiliary_projection_reference": "calibration_auxiliary_projection:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa"}, {}), + ( + { + "auxiliary_projection_reference": ( + "calibration_auxiliary_projection:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" + ) + }, + {}, + ), ({"auxiliary_projection_digest": "a" * 64}, {}), - ({"scientific_purpose_reference": "scientific_data_use_purpose:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb"}, {}), + ( + { + "scientific_purpose_reference": ( + "scientific_data_use_purpose:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" + ) + }, + {}, + ), ({"scientific_purpose_digest": "b" * 64}, {}), - ({"owner_contract_reference": "released_owner_contract:cccccccc-cccc-4ccc-8ccc-cccccccccccc"}, {}), + ( + { + "owner_contract_reference": ( + "released_owner_contract:cccccccc-cccc-4ccc-8ccc-cccccccccccc" + ) + }, + {}, + ), ({"owner_contract_version": 8}, {}), ({"authorization_receipt_digest": "c" * 64}, {}), - ({"authorized_from": USED_AT + timedelta(seconds=1)}, {}), - ({"authorized_to": USED_AT}, {}), + ({"scientific_use_receipt_digest": "d" * 64}, {}), + ({}, {"used_at": USED_AT + timedelta(seconds=1)}), ], ) def test_resolved_authority_must_match_every_requested_coordinate_and_use_time( @@ -254,9 +292,28 @@ def test_resolved_authority_must_match_every_requested_coordinate_and_use_time( _resolve(read_port=_ReadPort(_record(**record_overrides)), **request_overrides) -def test_open_ended_authority_interval_accepts_later_use() -> None: - view = _resolve(read_port=_ReadPort(_record(authorized_to=None))) +def test_record_requires_owner_resolved_use_time_inside_authorization_interval() -> None: + for invalid_use in ( + AUTHORIZED_FROM - timedelta(seconds=1), + AUTHORIZED_TO, + ): + with pytest.raises(ValueError): + _record(scientific_use_at=invalid_use) + + +def test_open_ended_authority_interval_accepts_later_owner_resolved_use() -> None: + later_use = AUTHORIZED_TO + timedelta(days=30) + view = _resolve( + read_port=_ReadPort( + _record( + scientific_use_at=later_use, + authorized_to=None, + ) + ), + used_at=later_use, + ) assert dict(view.fields)["authorized_to"] is None + assert dict(view.fields)["scientific_use_at"] == later_use @pytest.mark.parametrize( @@ -276,6 +333,7 @@ def test_open_ended_authority_interval_accepts_later_use() -> None: ("owner_contract_reference", "wrong:contract", ValueError), ("owner_contract_version", True, ValueError), ("authorization_receipt_digest", "4" * 65, ValueError), + ("scientific_use_receipt_digest", "5" * 65, ValueError), ("used_at", datetime(2026, 9, 17), ValueError), ("purpose_code", "Selection Validity Analysis", ValueError), ], @@ -309,6 +367,9 @@ def test_invalid_request_or_dependency_fails_before_owner_resolution( ("owner_contract_digest", "3" * 63), ("authorization_receipt_reference", "wrong:authorization"), ("authorization_receipt_digest", "4" * 63), + ("scientific_use_receipt_reference", "wrong:use"), + ("scientific_use_receipt_digest", "5" * 63), + ("scientific_use_at", datetime(2026, 9, 17)), ("authorized_from", datetime(2026, 9, 1)), ("authorized_to", "not-a-datetime"), ], From f230d73101b517a47c61b10032df5461fe133b60 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 08:15:28 +0900 Subject: [PATCH 066/603] fix(workforce-validation): corroborate scientific use time with owner evidence --- .../scientific_authority.py | 77 +++++++++++++++---- 1 file changed, 62 insertions(+), 15 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py index 853accda4..f84175cdd 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py @@ -47,6 +47,9 @@ "owner_contract_digest", "authorization_receipt_reference", "authorization_receipt_digest", + "scientific_use_receipt_reference", + "scientific_use_receipt_digest", + "scientific_use_at", "authorized_from", "authorized_to", } @@ -89,10 +92,10 @@ def _require_positive_integer(field_name: str, value: object) -> int: class CalibrationAuxiliaryAuthorityRecord(tuple): """Immutable owner projection corroborating one auxiliary-use authorization. - Only opaque references, digests, versions, target identities, and the exact - authorization interval cross this boundary. Raw calibration attributes, - benchmark values, protected characteristics, and row-level weights remain - behind their authoritative owners. + Only opaque references, digests, versions, target identities, the exact + scientific-use instant, and its authorization interval cross this boundary. + Raw calibration attributes, benchmark values, protected characteristics, and + row-level weights remain behind their authoritative owners. """ __slots__ = () @@ -112,6 +115,9 @@ def __new__( owner_contract_digest: str, authorization_receipt_reference: str, authorization_receipt_digest: str, + scientific_use_receipt_reference: str, + scientific_use_receipt_digest: str, + scientific_use_at: datetime, authorized_from: datetime, authorized_to: datetime | None, ) -> CalibrationAuxiliaryAuthorityRecord: @@ -150,6 +156,15 @@ def __new__( authorization_digest = _require_digest( "authorization_receipt_digest", authorization_receipt_digest ) + scientific_use_ref = _require_reference( + "scientific_use_receipt_reference", + scientific_use_receipt_reference, + "scientific_use_receipt", + ) + scientific_use_digest = _require_digest( + "scientific_use_receipt_digest", scientific_use_receipt_digest + ) + use_instant = _require_aware_datetime("scientific_use_at", scientific_use_at) authorization_start = _require_aware_datetime("authorized_from", authorized_from) authorization_end = ( None @@ -158,6 +173,12 @@ def __new__( ) if authorization_end is not None and authorization_end <= authorization_start: raise ValueError("authorized_to must be later than authorized_from.") + if use_instant < authorization_start or ( + authorization_end is not None and use_instant >= authorization_end + ): + raise ValueError( + "scientific_use_at must fall inside the authorization interval." + ) return tuple.__new__( cls, ( @@ -173,6 +194,9 @@ def __new__( owner_digest, authorization_ref, authorization_digest, + scientific_use_ref, + scientific_use_digest, + use_instant, authorization_start, authorization_end, ), @@ -238,15 +262,30 @@ def authorization_receipt_digest(self) -> str: """Return the authorization receipt digest used for exact correlation.""" return self[11] + @property + def scientific_use_receipt_reference(self) -> str: + """Return the immutable scientific-use receipt reference.""" + return self[12] + + @property + def scientific_use_receipt_digest(self) -> str: + """Return the immutable scientific-use receipt digest.""" + return self[13] + + @property + def scientific_use_at(self) -> datetime: + """Return the owner-resolved UTC instant for the exact scientific use.""" + return self[14] + @property def authorized_from(self) -> datetime: """Return the UTC instant when this scientific use became authorized.""" - return self[12] + return self[15] @property def authorized_to(self) -> datetime | None: """Return the exclusive UTC authorization end when one exists.""" - return self[13] + return self[16] class CalibrationAuxiliaryAuthorityView(tuple): @@ -299,6 +338,7 @@ def read_calibration_auxiliary_authority( owner_contract_reference: str, owner_contract_version: int, authorization_receipt_digest: str, + scientific_use_receipt_digest: str, ) -> CalibrationAuxiliaryAuthorityRecord | None: """Return matching released authority evidence or ``None`` through an owner ACL.""" ... @@ -321,6 +361,7 @@ def resolve_calibration_auxiliary_authority( owner_contract_reference: str, owner_contract_version: int, authorization_receipt_digest: str, + scientific_use_receipt_digest: str, used_at: datetime, purpose_code: str, policy: PurposeBoundAccessPolicy, @@ -330,9 +371,9 @@ def resolve_calibration_auxiliary_authority( The exact owner capability is captured inertly before authorization and the same function is invoked afterward. The request carries no protected source - values. Owner evidence must then reproduce every caller-supplied coordinate - and cover the exact scientific-use instant before any corroborating fields - are returned. + values. Owner evidence must reproduce every caller-supplied coordinate and + independently bind the scientific-use receipt to the same use instant before + any corroborating fields are returned. """ if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") @@ -380,6 +421,9 @@ def resolve_calibration_auxiliary_authority( authorization_digest = _require_digest( "authorization_receipt_digest", authorization_receipt_digest ) + scientific_use_digest = _require_digest( + "scientific_use_receipt_digest", scientific_use_receipt_digest + ) use_instant = _require_aware_datetime("used_at", used_at) purpose = _require_code("purpose_code", purpose_code) detached_policy = _detach_policy(policy) @@ -411,6 +455,7 @@ def resolve_calibration_auxiliary_authority( owner_contract_reference=owner_ref, owner_contract_version=owner_version, authorization_receipt_digest=authorization_digest, + scientific_use_receipt_digest=scientific_use_digest, ) if persisted is None: raise CalibrationAuxiliaryAuthorityNotFound(str(study_id)) @@ -432,6 +477,9 @@ def resolve_calibration_auxiliary_authority( owner_contract_digest=persisted.owner_contract_digest, authorization_receipt_reference=persisted.authorization_receipt_reference, authorization_receipt_digest=persisted.authorization_receipt_digest, + scientific_use_receipt_reference=persisted.scientific_use_receipt_reference, + scientific_use_receipt_digest=persisted.scientific_use_receipt_digest, + scientific_use_at=persisted.scientific_use_at, authorized_from=persisted.authorized_from, authorized_to=persisted.authorized_to, ) @@ -447,16 +495,12 @@ def resolve_calibration_auxiliary_authority( or record.owner_contract_reference != owner_ref or record.owner_contract_version != owner_version or record.authorization_receipt_digest != authorization_digest + or record.scientific_use_receipt_digest != scientific_use_digest + or record.scientific_use_at != use_instant ): raise CalibrationAuxiliaryAuthorityIntegrityError( "owner evidence does not match the requested calibration auxiliary authority" ) - if use_instant < record.authorized_from or ( - record.authorized_to is not None and use_instant >= record.authorized_to - ): - raise CalibrationAuxiliaryAuthorityIntegrityError( - "scientific use falls outside the resolved authorization interval" - ) values = { "authority_reference": record.authority_reference, @@ -469,6 +513,9 @@ def resolve_calibration_auxiliary_authority( "owner_contract_digest": record.owner_contract_digest, "authorization_receipt_reference": record.authorization_receipt_reference, "authorization_receipt_digest": record.authorization_receipt_digest, + "scientific_use_receipt_reference": record.scientific_use_receipt_reference, + "scientific_use_receipt_digest": record.scientific_use_receipt_digest, + "scientific_use_at": record.scientific_use_at, "authorized_from": record.authorized_from, "authorized_to": record.authorized_to, } From 64d14e589a460f638a54a9e6484554685815a8c9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 08:15:52 +0900 Subject: [PATCH 067/603] docs(workforce-validation): bind use time to owner scientific receipt --- services/workforce-validation-api/README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 33993d619..78eef5ea2 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -25,14 +25,15 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar `resolve_calibration_auxiliary_authority(...)` is the first executable owner-side slice for #407's durable scientific-evidence resolution gap. It does **not** import or copy the mutable validity-analysis implementation. Instead it defines the `workforce_validation` application contract that a later durable adapter must satisfy: - authorize the exact tenant/study scientific read before invoking the owner port; -- carry only opaque projection/purpose/owner/authorization references, SHA-256 evidence digests, immutable contract versions, and authorization time bounds—never calibration source attributes, protected characteristics, benchmark values, or row-level weights; +- carry only opaque projection/purpose/owner/authorization/scientific-use references, SHA-256 evidence digests, immutable contract versions, the owner-resolved scientific-use instant, and authorization time bounds—never calibration source attributes, protected characteristics, benchmark values, or row-level weights; - require a released-owner-contract reference/version and corroborating owner-contract digest rather than treating a caller-supplied version label as release authority; +- require an immutable scientific-use receipt digest in the lookup and reconstruct the corresponding owner record, so a caller cannot choose a convenient historical `used_at` merely to fit a stale authorization interval; +- require the caller's exact `used_at` coordinate to equal the owner-resolved `scientific_use_at`, while the record itself requires that instant to fall inside the owner-resolved authorization interval; - resolve through one statically captured `CalibrationAuxiliaryAuthorityReadPort` capability and reject inherited Protocol placeholders or descriptors before authorization; -- reconstruct the returned evidence into an exact tuple-backed `CalibrationAuxiliaryAuthorityRecord` and require tenant, study, projection, scientific purpose, released owner contract, and authorization-receipt digest to match the requested coordinates; -- require the exact scientific-use instant to fall inside the owner-resolved authorization interval; +- reconstruct the returned evidence into an exact tuple-backed `CalibrationAuxiliaryAuthorityRecord` and require tenant, study, projection, scientific purpose, released owner contract, authorization receipt, scientific-use receipt, and use time to match the requested coordinates; - issue only a minimized `CalibrationAuxiliaryAuthorityView`. The view is corroborating data, not a reusable authorization credential or proof that an arbitrary injected port is a production owner. -This closes the leaf false-GREEN where opaque coordinates could be accepted without any owner-resolution contract. It does **not** complete #407: the current branch has no durable scientific-authority relation or released auxiliary-evidence adapter. After the canonical owner persistence path is protected truth, #248 or its verified successor must implement the schema-qualified, least-privilege durable port and prove that the resolved owner evidence is itself released/versioned and purpose-authorized. Mutable #57 source is not a dependency of this service. +This closes the application-contract false-GREEN where opaque coordinates or a caller-selected use instant could be accepted without owner correlation. It does **not** complete #407: the current branch has no durable scientific-authority relation or released auxiliary-evidence adapter. After the canonical owner persistence path is protected truth, #248 or its verified successor must implement the schema-qualified, least-privilege durable port and prove that the resolved owner evidence is itself released/versioned and purpose-authorized. Mutable #57 source is not a dependency of this service. `services/workforce-validation-api/database/migrations/0001_owner_schema.sql` starts this bounded context's own migration history. It creates the `workforce_validation` schema and deny-default `workforce_validation_role`, revokes public schema access, and intentionally creates or moves no application table yet. The role is a **NOLOGIN migration/schema owner only**; runtime principals must not be granted that owner role. PostgreSQL applies role-level configuration defaults at login and does not re-apply them on `SET ROLE`, so an `ALTER ROLE ... SET search_path` entry on this NOLOGIN role is not treated as a runtime isolation control. The later durable adapter must use a distinct least-privilege runtime role, schema-qualified `workforce_validation` relations, and explicit function-level `search_path` where `SECURITY DEFINER` code is introduced. @@ -51,7 +52,7 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ services/workforce-validation-api/tests ``` -The service package keeps an exact 100% owned statement/branch threshold. The calibration-authority contract adds hostile coverage for authorization-before-owner-read, non-concrete/dynamic owner capabilities, malformed references/digests/versions/timestamps, foreign/mismatched owner evidence, authorization-window mismatch, UUID alias mutation, structural immutability, and non-public view issuance. +The service package keeps an exact 100% owned statement/branch threshold. The calibration-authority contract adds hostile coverage for authorization-before-owner-read, non-concrete/dynamic owner capabilities, malformed references/digests/versions/timestamps, foreign/mismatched owner evidence, caller/owner scientific-use-time mismatch, authorization-window mismatch, UUID alias mutation, structural immutability, and non-public view issuance. The same Foundation job also runs `tests/test_workforce_validation_owner_schema_postgres.sh` in its own pinned PostgreSQL 16.14 container. That contract executes the service-local owner migration and checks the exact deny-default role flags, schema owner, absence of ineffective login-only `rolconfig`, actual `SET ROLE` search-path behavior, absence of inherited PUBLIC `USAGE`/`CREATE`, and absence of application relations in the bootstrap schema. The test intentionally demonstrates that `SET ROLE` retains the caller's existing `search_path`; runtime isolation therefore cannot be inferred from owner-role metadata. From 085012fb8c3dd4d258c91521fe904ae6d86372ba Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 10:12:09 +0900 Subject: [PATCH 068/603] test(workforce-validation): RED variance authority resolution --- .../tests/test_weight_variance_authority.py | 273 ++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_variance_authority.py diff --git a/services/workforce-validation-api/tests/test_weight_variance_authority.py b/services/workforce-validation-api/tests/test_weight_variance_authority.py new file mode 100644 index 000000000..c1f23c4b5 --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_variance_authority.py @@ -0,0 +1,273 @@ +"""Fail-closed owner contract for point-weight/variance evidence compatibility.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.variance_authority import ( + WeightVarianceAuthorityIntegrityError, + WeightVarianceAuthorityNotFound, + WeightVarianceAuthorityReadPort, + WeightVarianceAuthorityRecord, + WeightVarianceAuthorityView, + resolve_weight_variance_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +AUTHORITY_REFERENCE = "variance_compatibility_authority:11111111-1111-4111-8111-111111111111" +SAMPLING_REFERENCE = "sampling_design_receipt:22222222-2222-4222-8222-222222222222" +VARIANCE_REFERENCE = "variance_design_receipt:33333333-3333-4333-8333-333333333333" +METHOD_REFERENCE = "variance_method:44444444-4444-4444-8444-444444444444" +OWNER_REFERENCE = "released_owner_contract:55555555-5555-4555-8555-555555555555" +SAMPLING_DIGEST = "1" * 64 +ANALYSIS_WEIGHT_DIGEST = "2" * 64 +CASE_SET_DIGEST = "3" * 64 +ELIGIBILITY_DIGEST = "4" * 64 +CORRECTION_DIGEST = "5" * 64 +FINAL_WEIGHT_DIGEST = "6" * 64 +VARIANCE_DIGEST = "7" * 64 +OWNER_DIGEST = "8" * 64 +RELEASED_AT = datetime(2026, 9, 17, 1, 0, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 2, 0, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "authority_reference", + "sampling_receipt_reference", + "sampling_receipt_version", + "sampling_receipt_digest", + "analysis_weight_receipt_digest", + "analytic_case_set_digest", + "weight_eligibility_receipt_digest", + "correction_sequence_digest", + "final_weight_artifact_digest", + "variance_design_receipt_reference", + "variance_design_receipt_version", + "variance_design_receipt_digest", + "variance_method_reference", + "variance_method_version", + "variance_evidence_mode", + "variance_semantics", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "released_at", + } +) + + +class _ReadPort: + """Return one configured owner record and retain exact lookup coordinates.""" + + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[tuple[object, ...]] = [] + + def read_weight_variance_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + sampling_receipt_reference: str, + sampling_receipt_version: int, + sampling_receipt_digest: str, + analysis_weight_receipt_digest: str, + variance_design_receipt_reference: str, + variance_design_receipt_version: int, + variance_design_receipt_digest: str, + owner_contract_reference: str, + owner_contract_version: int, + ) -> object: + """Capture the immutable owner lookup and return the configured result.""" + self.calls.append( + ( + tenant_record_id, + validity_study_id, + sampling_receipt_reference, + sampling_receipt_version, + sampling_receipt_digest, + analysis_weight_receipt_digest, + variance_design_receipt_reference, + variance_design_receipt_version, + variance_design_receipt_digest, + owner_contract_reference, + owner_contract_version, + ) + ) + return self.result + + +class _ProtocolOnly(WeightVarianceAuthorityReadPort): + """Inherit only the Protocol placeholder, not a concrete owner capability.""" + + +def _principal() -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="weight-variance-authority-read-v1", + resource_kind="weight_variance_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record(**overrides: object) -> WeightVarianceAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "authority_reference": AUTHORITY_REFERENCE, + "sampling_receipt_reference": SAMPLING_REFERENCE, + "sampling_receipt_version": 3, + "sampling_receipt_digest": SAMPLING_DIGEST, + "analysis_weight_receipt_digest": ANALYSIS_WEIGHT_DIGEST, + "analytic_case_set_digest": CASE_SET_DIGEST, + "weight_eligibility_receipt_digest": ELIGIBILITY_DIGEST, + "correction_sequence_digest": CORRECTION_DIGEST, + "final_weight_artifact_digest": FINAL_WEIGHT_DIGEST, + "variance_design_receipt_reference": VARIANCE_REFERENCE, + "variance_design_receipt_version": 5, + "variance_design_receipt_digest": VARIANCE_DIGEST, + "variance_method_reference": METHOD_REFERENCE, + "variance_method_version": 2, + "variance_evidence_mode": "replicate_weights", + "variance_semantics": "exact", + "owner_contract_reference": OWNER_REFERENCE, + "owner_contract_version": 4, + "owner_contract_digest": OWNER_DIGEST, + "released_at": RELEASED_AT, + } + values.update(overrides) + return WeightVarianceAuthorityRecord(**values) + + +def _resolve(*, read_port: object, **overrides: object) -> WeightVarianceAuthorityView: + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "sampling_receipt_reference": SAMPLING_REFERENCE, + "sampling_receipt_version": 3, + "sampling_receipt_digest": SAMPLING_DIGEST, + "analysis_weight_receipt_digest": ANALYSIS_WEIGHT_DIGEST, + "analytic_case_set_digest": CASE_SET_DIGEST, + "weight_eligibility_receipt_digest": ELIGIBILITY_DIGEST, + "correction_sequence_digest": CORRECTION_DIGEST, + "final_weight_artifact_digest": FINAL_WEIGHT_DIGEST, + "variance_design_receipt_reference": VARIANCE_REFERENCE, + "variance_design_receipt_version": 5, + "variance_design_receipt_digest": VARIANCE_DIGEST, + "variance_method_reference": METHOD_REFERENCE, + "variance_method_version": 2, + "variance_evidence_mode": "replicate_weights", + "variance_semantics": "exact", + "owner_contract_reference": OWNER_REFERENCE, + "owner_contract_version": 4, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_weight_variance_authority(**values) + + +def test_resolution_authorizes_then_returns_owner_corroborated_compatibility() -> None: + port = _ReadPort(_record()) + + view = _resolve(read_port=port) + + assert isinstance(port, WeightVarianceAuthorityReadPort) + assert port.calls == [ + ( + TENANT, + STUDY, + SAMPLING_REFERENCE, + 3, + SAMPLING_DIGEST, + ANALYSIS_WEIGHT_DIGEST, + VARIANCE_REFERENCE, + 5, + VARIANCE_DIGEST, + OWNER_REFERENCE, + 4, + ) + ] + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + fields = dict(view.fields) + assert fields["final_weight_artifact_digest"] == FINAL_WEIGHT_DIGEST + assert fields["variance_design_receipt_digest"] == VARIANCE_DIGEST + assert fields["owner_contract_digest"] == OWNER_DIGEST + assert fields["released_at"] == RELEASED_AT + + +def test_authorization_denial_happens_before_owner_resolution() -> None: + port = _ReadPort(_record()) + + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, policy=_policy(purpose_code="audit_review")) + + assert port.calls == [] + + +def test_missing_noncanonical_or_mismatched_owner_evidence_fails_closed() -> None: + with pytest.raises(WeightVarianceAuthorityNotFound): + _resolve(read_port=_ReadPort(None)) + with pytest.raises(WeightVarianceAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object())) + with pytest.raises(WeightVarianceAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(analytic_case_set_digest="a" * 64))) + with pytest.raises(WeightVarianceAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(final_weight_artifact_digest="b" * 64))) + + +def test_approximation_mode_cannot_claim_exact_variance_semantics() -> None: + with pytest.raises(ValueError): + _record(variance_evidence_mode="approximation", variance_semantics="exact") + + +def test_invalid_dependency_and_pre_release_use_fail_before_owner_read() -> None: + with pytest.raises(TypeError): + _resolve(read_port=_ProtocolOnly()) + + port = _ReadPort(_record()) + with pytest.raises(WeightVarianceAuthorityIntegrityError): + _resolve(read_port=port, used_at=datetime(2026, 9, 17, 0, 59, tzinfo=timezone.utc)) + assert len(port.calls) == 1 + + +def test_record_and_view_are_immutable_and_public_view_construction_is_blocked() -> None: + record = _record() + with pytest.raises(AttributeError): + object.__setattr__(record, "variance_method_version", 999) + + view = _resolve(read_port=_ReadPort(record)) + with pytest.raises(AttributeError): + object.__setattr__(view, "fields", ()) + with pytest.raises(TypeError): + WeightVarianceAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) + + +def test_cross_tenant_owner_evidence_is_rejected() -> None: + with pytest.raises(WeightVarianceAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(tenant_record_id=OTHER_TENANT))) From 4a383d40f50d4eaa9d65c0471d99765b3054b18a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 10:13:06 +0900 Subject: [PATCH 069/603] feat(workforce-validation): corroborate variance authority --- .../variance_authority.py | 603 ++++++++++++++++++ 1 file changed, 603 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py new file mode 100644 index 000000000..5074fdf04 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py @@ -0,0 +1,603 @@ +"""Corroborate point-weight and variance-design compatibility through an owner port. + +This application boundary keeps released sampling, point-weight, and variance +coordinates correlated without importing mutable scientific-package source or +copying row-level weights, replicate vectors, frame variables, or protected +attributes. The persistence child must later back the port with released, +versioned owner evidence. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +import re +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) + +_DIGEST_PATTERN = re.compile(r"^[0-9a-f]{64}$") +_REFERENCE_PATTERN = re.compile(r"^[a-z][a-z0-9_]*:[A-Za-z0-9][A-Za-z0-9._~-]*$") +_RESOURCE_KIND = "weight_variance_authority" +_OPERATION = "read" +_VARIANCE_EVIDENCE_MODES = frozenset( + { + "joint_inclusion", + "reproducible_design_algorithm", + "replicate_weights", + "approximation", + } +) +_VARIANCE_SEMANTICS = frozenset({"exact", "approximate"}) +_READ_FIELDS = frozenset( + { + "authority_reference", + "sampling_receipt_reference", + "sampling_receipt_version", + "sampling_receipt_digest", + "analysis_weight_receipt_digest", + "analytic_case_set_digest", + "weight_eligibility_receipt_digest", + "correction_sequence_digest", + "final_weight_artifact_digest", + "variance_design_receipt_reference", + "variance_design_receipt_version", + "variance_design_receipt_digest", + "variance_method_reference", + "variance_method_version", + "variance_evidence_mode", + "variance_semantics", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "released_at", + } +) + + +class WeightVarianceAuthorityNotFound(LookupError): + """Indicate that no owner evidence corroborates the requested compatibility tuple.""" + + +class WeightVarianceAuthorityIntegrityError(RuntimeError): + """Indicate that owner evidence cannot support the requested scientific binding.""" + + +def _require_reference(field_name: str, value: object, namespace: str) -> str: + """Require one exact opaque namespaced evidence reference.""" + if ( + type(value) is not str + or _REFERENCE_PATTERN.fullmatch(value) is None + or value.partition(":")[0] != namespace + ): + raise ValueError(f"{field_name} must be an exact {namespace}: opaque reference.") + return value + + +def _require_digest(field_name: str, value: object) -> str: + """Require lowercase SHA-256 evidence rather than caller-readable source content.""" + if type(value) is not str or _DIGEST_PATTERN.fullmatch(value) is None: + raise ValueError(f"{field_name} must be lowercase SHA-256 hex.") + return value + + +def _require_positive_integer(field_name: str, value: object) -> int: + """Require a strict positive integer contract version without accepting booleans.""" + if type(value) is not int or value <= 0: + raise ValueError(f"{field_name} must be a positive integer.") + return value + + +def _require_variance_evidence_mode(value: object) -> str: + """Require one controlled #406 variance-evidence strategy identifier.""" + if type(value) is not str or value not in _VARIANCE_EVIDENCE_MODES: + raise ValueError("variance_evidence_mode must be a supported controlled value.") + return value + + +def _require_variance_semantics(value: object) -> str: + """Require explicit exact-versus-approximate uncertainty semantics.""" + if type(value) is not str or value not in _VARIANCE_SEMANTICS: + raise ValueError("variance_semantics must be exact or approximate.") + return value + + +class WeightVarianceAuthorityRecord(tuple): + """Immutable owner projection proving point/variance evidence compatibility.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + authority_reference: str, + sampling_receipt_reference: str, + sampling_receipt_version: int, + sampling_receipt_digest: str, + analysis_weight_receipt_digest: str, + analytic_case_set_digest: str, + weight_eligibility_receipt_digest: str, + correction_sequence_digest: str, + final_weight_artifact_digest: str, + variance_design_receipt_reference: str, + variance_design_receipt_version: int, + variance_design_receipt_digest: str, + variance_method_reference: str, + variance_method_version: int, + variance_evidence_mode: str, + variance_semantics: str, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + released_at: datetime, + ) -> WeightVarianceAuthorityRecord: + """Validate and detach the minimum immutable compatibility coordinates.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + authority_ref = _require_reference( + "authority_reference", authority_reference, "variance_compatibility_authority" + ) + sampling_ref = _require_reference( + "sampling_receipt_reference", sampling_receipt_reference, "sampling_design_receipt" + ) + sampling_version = _require_positive_integer( + "sampling_receipt_version", sampling_receipt_version + ) + sampling_digest = _require_digest("sampling_receipt_digest", sampling_receipt_digest) + point_digest = _require_digest( + "analysis_weight_receipt_digest", analysis_weight_receipt_digest + ) + case_digest = _require_digest("analytic_case_set_digest", analytic_case_set_digest) + eligibility_digest = _require_digest( + "weight_eligibility_receipt_digest", weight_eligibility_receipt_digest + ) + correction_digest = _require_digest( + "correction_sequence_digest", correction_sequence_digest + ) + final_digest = _require_digest("final_weight_artifact_digest", final_weight_artifact_digest) + variance_ref = _require_reference( + "variance_design_receipt_reference", + variance_design_receipt_reference, + "variance_design_receipt", + ) + variance_version = _require_positive_integer( + "variance_design_receipt_version", variance_design_receipt_version + ) + variance_digest = _require_digest( + "variance_design_receipt_digest", variance_design_receipt_digest + ) + method_ref = _require_reference( + "variance_method_reference", variance_method_reference, "variance_method" + ) + method_version = _require_positive_integer("variance_method_version", variance_method_version) + evidence_mode = _require_variance_evidence_mode(variance_evidence_mode) + semantics = _require_variance_semantics(variance_semantics) + if evidence_mode == "approximation" and semantics != "approximate": + raise ValueError("approximation evidence must declare approximate variance semantics.") + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer("owner_contract_version", owner_contract_version) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + release_instant = _require_aware_datetime("released_at", released_at) + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + authority_ref, + sampling_ref, + sampling_version, + sampling_digest, + point_digest, + case_digest, + eligibility_digest, + correction_digest, + final_digest, + variance_ref, + variance_version, + variance_digest, + method_ref, + method_version, + evidence_mode, + semantics, + owner_ref, + owner_version, + owner_digest, + release_instant, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity for the authority evidence.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity for the authority evidence.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def authority_reference(self) -> str: + """Return the opaque compatibility-authority reference.""" + return self[2] + + @property + def sampling_receipt_reference(self) -> str: + """Return the released #405 sampling receipt reference.""" + return self[3] + + @property + def sampling_receipt_version(self) -> int: + """Return the released sampling receipt version.""" + return self[4] + + @property + def sampling_receipt_digest(self) -> str: + """Return the released sampling receipt digest.""" + return self[5] + + @property + def analysis_weight_receipt_digest(self) -> str: + """Return the exact final point-weight receipt digest.""" + return self[6] + + @property + def analytic_case_set_digest(self) -> str: + """Return the exact ordered analytic-case evidence digest.""" + return self[7] + + @property + def weight_eligibility_receipt_digest(self) -> str: + """Return the exact point-weight eligibility receipt digest.""" + return self[8] + + @property + def correction_sequence_digest(self) -> str: + """Return the append-only point-weight correction sequence digest.""" + return self[9] + + @property + def final_weight_artifact_digest(self) -> str: + """Return the final point-weight artifact digest used by variance evidence.""" + return self[10] + + @property + def variance_design_receipt_reference(self) -> str: + """Return the released #406 variance-design receipt reference.""" + return self[11] + + @property + def variance_design_receipt_version(self) -> int: + """Return the released variance-design receipt version.""" + return self[12] + + @property + def variance_design_receipt_digest(self) -> str: + """Return the released variance-design receipt digest.""" + return self[13] + + @property + def variance_method_reference(self) -> str: + """Return the controlled variance-method reference.""" + return self[14] + + @property + def variance_method_version(self) -> int: + """Return the controlled variance-method version.""" + return self[15] + + @property + def variance_evidence_mode(self) -> str: + """Return the controlled #406 evidence strategy.""" + return self[16] + + @property + def variance_semantics(self) -> str: + """Return exact-versus-approximate uncertainty semantics.""" + return self[17] + + @property + def owner_contract_reference(self) -> str: + """Return the released owner-contract reference.""" + return self[18] + + @property + def owner_contract_version(self) -> int: + """Return the positive released owner-contract version.""" + return self[19] + + @property + def owner_contract_digest(self) -> str: + """Return the immutable released owner-contract digest.""" + return self[20] + + @property + def released_at(self) -> datetime: + """Return the owner-resolved release instant for this authority evidence.""" + return self[21] + + +class WeightVarianceAuthorityView(tuple): + """Field-minimized compatibility evidence issued only after authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> WeightVarianceAuthorityView: + """Reject public construction; the resolver is the only supported issuer.""" + raise TypeError( + "WeightVarianceAuthorityView is issued only by resolve_weight_variance_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable corroborating fields without row-level scientific data.""" + return self[2] + + +@runtime_checkable +class WeightVarianceAuthorityReadPort(Protocol): + """Owner read contract for released #405/#406/#407 compatibility evidence.""" + + def read_weight_variance_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + sampling_receipt_reference: str, + sampling_receipt_version: int, + sampling_receipt_digest: str, + analysis_weight_receipt_digest: str, + variance_design_receipt_reference: str, + variance_design_receipt_version: int, + variance_design_receipt_digest: str, + owner_contract_reference: str, + owner_contract_version: int, + ) -> WeightVarianceAuthorityRecord | None: + """Return matching released authority evidence or ``None`` through an owner ACL.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + WeightVarianceAuthorityReadPort, "read_weight_variance_authority" +) + + +def resolve_weight_variance_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + sampling_receipt_reference: str, + sampling_receipt_version: int, + sampling_receipt_digest: str, + analysis_weight_receipt_digest: str, + analytic_case_set_digest: str, + weight_eligibility_receipt_digest: str, + correction_sequence_digest: str, + final_weight_artifact_digest: str, + variance_design_receipt_reference: str, + variance_design_receipt_version: int, + variance_design_receipt_digest: str, + variance_method_reference: str, + variance_method_version: int, + variance_evidence_mode: str, + variance_semantics: str, + owner_contract_reference: str, + owner_contract_version: int, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: WeightVarianceAuthorityReadPort, +) -> WeightVarianceAuthorityView: + """Authorize then corroborate one released point-weight/variance compatibility tuple.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static(type(read_port), "read_weight_variance_authority", None) + if type(read_capability) is not FunctionType or read_capability is _PROTOCOL_READ_CAPABILITY: + raise TypeError( + "read_port must expose a statically callable read_weight_variance_authority." + ) + + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + tenant_id = _restore_operational_uuid("tenant_record_id", tenant_identity) + study_id = _restore_operational_uuid("validity_study_id", study_identity) + sampling_ref = _require_reference( + "sampling_receipt_reference", sampling_receipt_reference, "sampling_design_receipt" + ) + sampling_version = _require_positive_integer( + "sampling_receipt_version", sampling_receipt_version + ) + sampling_digest = _require_digest("sampling_receipt_digest", sampling_receipt_digest) + point_digest = _require_digest("analysis_weight_receipt_digest", analysis_weight_receipt_digest) + case_digest = _require_digest("analytic_case_set_digest", analytic_case_set_digest) + eligibility_digest = _require_digest( + "weight_eligibility_receipt_digest", weight_eligibility_receipt_digest + ) + correction_digest = _require_digest("correction_sequence_digest", correction_sequence_digest) + final_digest = _require_digest("final_weight_artifact_digest", final_weight_artifact_digest) + variance_ref = _require_reference( + "variance_design_receipt_reference", + variance_design_receipt_reference, + "variance_design_receipt", + ) + variance_version = _require_positive_integer( + "variance_design_receipt_version", variance_design_receipt_version + ) + variance_digest = _require_digest( + "variance_design_receipt_digest", variance_design_receipt_digest + ) + method_ref = _require_reference( + "variance_method_reference", variance_method_reference, "variance_method" + ) + method_version = _require_positive_integer("variance_method_version", variance_method_version) + evidence_mode = _require_variance_evidence_mode(variance_evidence_mode) + semantics = _require_variance_semantics(variance_semantics) + if evidence_mode == "approximation" and semantics != "approximate": + raise ValueError("approximation evidence must declare approximate variance semantics.") + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer("owner_contract_version", owner_contract_version) + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=_restore_operational_uuid("tenant_record_id", tenant_identity), + validity_study_id=_restore_operational_uuid("validity_study_id", study_identity), + sampling_receipt_reference=sampling_ref, + sampling_receipt_version=sampling_version, + sampling_receipt_digest=sampling_digest, + analysis_weight_receipt_digest=point_digest, + variance_design_receipt_reference=variance_ref, + variance_design_receipt_version=variance_version, + variance_design_receipt_digest=variance_digest, + owner_contract_reference=owner_ref, + owner_contract_version=owner_version, + ) + if persisted is None: + raise WeightVarianceAuthorityNotFound(str(study_id)) + if type(persisted) is not WeightVarianceAuthorityRecord: + raise WeightVarianceAuthorityIntegrityError( + "owner port returned non-canonical point-weight/variance authority evidence" + ) + + record = WeightVarianceAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + authority_reference=persisted.authority_reference, + sampling_receipt_reference=persisted.sampling_receipt_reference, + sampling_receipt_version=persisted.sampling_receipt_version, + sampling_receipt_digest=persisted.sampling_receipt_digest, + analysis_weight_receipt_digest=persisted.analysis_weight_receipt_digest, + analytic_case_set_digest=persisted.analytic_case_set_digest, + weight_eligibility_receipt_digest=persisted.weight_eligibility_receipt_digest, + correction_sequence_digest=persisted.correction_sequence_digest, + final_weight_artifact_digest=persisted.final_weight_artifact_digest, + variance_design_receipt_reference=persisted.variance_design_receipt_reference, + variance_design_receipt_version=persisted.variance_design_receipt_version, + variance_design_receipt_digest=persisted.variance_design_receipt_digest, + variance_method_reference=persisted.variance_method_reference, + variance_method_version=persisted.variance_method_version, + variance_evidence_mode=persisted.variance_evidence_mode, + variance_semantics=persisted.variance_semantics, + owner_contract_reference=persisted.owner_contract_reference, + owner_contract_version=persisted.owner_contract_version, + owner_contract_digest=persisted.owner_contract_digest, + released_at=persisted.released_at, + ) + if ( + _store_operational_uuid("record tenant_record_id", record.tenant_record_id) + != tenant_identity + or _store_operational_uuid("record validity_study_id", record.validity_study_id) + != study_identity + or record.sampling_receipt_reference != sampling_ref + or record.sampling_receipt_version != sampling_version + or record.sampling_receipt_digest != sampling_digest + or record.analysis_weight_receipt_digest != point_digest + or record.analytic_case_set_digest != case_digest + or record.weight_eligibility_receipt_digest != eligibility_digest + or record.correction_sequence_digest != correction_digest + or record.final_weight_artifact_digest != final_digest + or record.variance_design_receipt_reference != variance_ref + or record.variance_design_receipt_version != variance_version + or record.variance_design_receipt_digest != variance_digest + or record.variance_method_reference != method_ref + or record.variance_method_version != method_version + or record.variance_evidence_mode != evidence_mode + or record.variance_semantics != semantics + or record.owner_contract_reference != owner_ref + or record.owner_contract_version != owner_version + ): + raise WeightVarianceAuthorityIntegrityError( + "owner evidence does not match the requested point-weight/variance compatibility" + ) + if use_instant < record.released_at: + raise WeightVarianceAuthorityIntegrityError( + "weight/variance authority cannot be used before its owner-resolved release instant" + ) + + values = { + "authority_reference": record.authority_reference, + "sampling_receipt_reference": record.sampling_receipt_reference, + "sampling_receipt_version": record.sampling_receipt_version, + "sampling_receipt_digest": record.sampling_receipt_digest, + "analysis_weight_receipt_digest": record.analysis_weight_receipt_digest, + "analytic_case_set_digest": record.analytic_case_set_digest, + "weight_eligibility_receipt_digest": record.weight_eligibility_receipt_digest, + "correction_sequence_digest": record.correction_sequence_digest, + "final_weight_artifact_digest": record.final_weight_artifact_digest, + "variance_design_receipt_reference": record.variance_design_receipt_reference, + "variance_design_receipt_version": record.variance_design_receipt_version, + "variance_design_receipt_digest": record.variance_design_receipt_digest, + "variance_method_reference": record.variance_method_reference, + "variance_method_version": record.variance_method_version, + "variance_evidence_mode": record.variance_evidence_mode, + "variance_semantics": record.variance_semantics, + "owner_contract_reference": record.owner_contract_reference, + "owner_contract_version": record.owner_contract_version, + "owner_contract_digest": record.owner_contract_digest, + "released_at": record.released_at, + } + fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) + return tuple.__new__(WeightVarianceAuthorityView, (tenant_identity, study_identity, fields)) From b6e1e8631a8f470678669fed8870287a65fb5469 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 10:13:19 +0900 Subject: [PATCH 070/603] feat(workforce-validation): export variance authority contract --- .../orgmetra_workforce_validation_api/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index 61032025f..f454188ba 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -17,6 +17,14 @@ CalibrationAuxiliaryAuthorityView, resolve_calibration_auxiliary_authority, ) +from orgmetra_workforce_validation_api.variance_authority import ( + WeightVarianceAuthorityIntegrityError, + WeightVarianceAuthorityNotFound, + WeightVarianceAuthorityReadPort, + WeightVarianceAuthorityRecord, + WeightVarianceAuthorityView, + resolve_weight_variance_authority, +) __all__ = [ "CalibrationAuxiliaryAuthorityIntegrityError", @@ -30,6 +38,12 @@ "ValidityStudyReadPort", "ValidityStudyRecord", "ValidityStudyView", + "WeightVarianceAuthorityIntegrityError", + "WeightVarianceAuthorityNotFound", + "WeightVarianceAuthorityReadPort", + "WeightVarianceAuthorityRecord", + "WeightVarianceAuthorityView", "read_validity_study", "resolve_calibration_auxiliary_authority", + "resolve_weight_variance_authority", ] From 5dd7e7d5f837bb83393aca649a2593a58f31af21 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 10:14:26 +0900 Subject: [PATCH 071/603] test(workforce-validation): cover variance authority edges --- .../test_weight_variance_authority_edges.py | 296 ++++++++++++++++++ 1 file changed, 296 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_variance_authority_edges.py diff --git a/services/workforce-validation-api/tests/test_weight_variance_authority_edges.py b/services/workforce-validation-api/tests/test_weight_variance_authority_edges.py new file mode 100644 index 000000000..e70587a50 --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_variance_authority_edges.py @@ -0,0 +1,296 @@ +"""Branch and hostile-input coverage for weight/variance authority resolution.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.variance_authority import ( + WeightVarianceAuthorityIntegrityError, + WeightVarianceAuthorityReadPort, + WeightVarianceAuthorityRecord, + resolve_weight_variance_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000d2") +AUTHORITY_REFERENCE = "variance_compatibility_authority:11111111-1111-4111-8111-111111111111" +SAMPLING_REFERENCE = "sampling_design_receipt:22222222-2222-4222-8222-222222222222" +VARIANCE_REFERENCE = "variance_design_receipt:33333333-3333-4333-8333-333333333333" +METHOD_REFERENCE = "variance_method:44444444-4444-4444-8444-444444444444" +OWNER_REFERENCE = "released_owner_contract:55555555-5555-4555-8555-555555555555" +SAMPLING_DIGEST = "1" * 64 +ANALYSIS_WEIGHT_DIGEST = "2" * 64 +CASE_SET_DIGEST = "3" * 64 +ELIGIBILITY_DIGEST = "4" * 64 +CORRECTION_DIGEST = "5" * 64 +FINAL_WEIGHT_DIGEST = "6" * 64 +VARIANCE_DIGEST = "7" * 64 +OWNER_DIGEST = "8" * 64 +RELEASED_AT = datetime(2026, 9, 17, 1, 0, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 2, 0, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "authority_reference", + "sampling_receipt_reference", + "sampling_receipt_version", + "sampling_receipt_digest", + "analysis_weight_receipt_digest", + "analytic_case_set_digest", + "weight_eligibility_receipt_digest", + "correction_sequence_digest", + "final_weight_artifact_digest", + "variance_design_receipt_reference", + "variance_design_receipt_version", + "variance_design_receipt_digest", + "variance_method_reference", + "variance_method_version", + "variance_evidence_mode", + "variance_semantics", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "released_at", + } +) + + +class _Port: + def __init__(self, result: object) -> None: + self.result = result + self.calls = 0 + + def read_weight_variance_authority(self, **_: object) -> object: + self.calls += 1 + return self.result + + +class _NoMethod: + pass + + +class _ProtocolOnly(WeightVarianceAuthorityReadPort): + pass + + +class _Descriptor: + @property + def read_weight_variance_authority(self) -> object: + raise AssertionError("descriptor must not execute") + + +def _principal() -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy() -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="weight-variance-authority-read-v1", + resource_kind="weight_variance_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record(**overrides: object) -> WeightVarianceAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "authority_reference": AUTHORITY_REFERENCE, + "sampling_receipt_reference": SAMPLING_REFERENCE, + "sampling_receipt_version": 3, + "sampling_receipt_digest": SAMPLING_DIGEST, + "analysis_weight_receipt_digest": ANALYSIS_WEIGHT_DIGEST, + "analytic_case_set_digest": CASE_SET_DIGEST, + "weight_eligibility_receipt_digest": ELIGIBILITY_DIGEST, + "correction_sequence_digest": CORRECTION_DIGEST, + "final_weight_artifact_digest": FINAL_WEIGHT_DIGEST, + "variance_design_receipt_reference": VARIANCE_REFERENCE, + "variance_design_receipt_version": 5, + "variance_design_receipt_digest": VARIANCE_DIGEST, + "variance_method_reference": METHOD_REFERENCE, + "variance_method_version": 2, + "variance_evidence_mode": "replicate_weights", + "variance_semantics": "exact", + "owner_contract_reference": OWNER_REFERENCE, + "owner_contract_version": 4, + "owner_contract_digest": OWNER_DIGEST, + "released_at": RELEASED_AT, + } + values.update(overrides) + return WeightVarianceAuthorityRecord(**values) + + +def _resolve(*, result: object | None = None, read_port: object | None = None, **overrides: object): + port = _Port(_record() if result is None else result) if read_port is None else read_port + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "sampling_receipt_reference": SAMPLING_REFERENCE, + "sampling_receipt_version": 3, + "sampling_receipt_digest": SAMPLING_DIGEST, + "analysis_weight_receipt_digest": ANALYSIS_WEIGHT_DIGEST, + "analytic_case_set_digest": CASE_SET_DIGEST, + "weight_eligibility_receipt_digest": ELIGIBILITY_DIGEST, + "correction_sequence_digest": CORRECTION_DIGEST, + "final_weight_artifact_digest": FINAL_WEIGHT_DIGEST, + "variance_design_receipt_reference": VARIANCE_REFERENCE, + "variance_design_receipt_version": 5, + "variance_design_receipt_digest": VARIANCE_DIGEST, + "variance_method_reference": METHOD_REFERENCE, + "variance_method_version": 2, + "variance_evidence_mode": "replicate_weights", + "variance_semantics": "exact", + "owner_contract_reference": OWNER_REFERENCE, + "owner_contract_version": 4, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": port, + } + values.update(overrides) + return resolve_weight_variance_authority(**values) + + +@pytest.mark.parametrize( + ("key", "value"), + [ + ("tenant_record_id", "not-a-uuid"), + ("validity_study_id", UUID(int=0)), + ("authority_reference", 42), + ("authority_reference", "not-a-reference"), + ("authority_reference", "wrong:authority"), + ("sampling_receipt_reference", "wrong:sampling"), + ("sampling_receipt_version", True), + ("sampling_receipt_version", 0), + ("sampling_receipt_digest", 42), + ("sampling_receipt_digest", "1" * 63), + ("analysis_weight_receipt_digest", "2" * 63), + ("analytic_case_set_digest", "3" * 65), + ("weight_eligibility_receipt_digest", "4" * 63), + ("correction_sequence_digest", "5" * 65), + ("final_weight_artifact_digest", "6" * 63), + ("variance_design_receipt_reference", "wrong:variance"), + ("variance_design_receipt_version", 0), + ("variance_design_receipt_digest", "7" * 63), + ("variance_method_reference", "wrong:method"), + ("variance_method_version", False), + ("variance_evidence_mode", 42), + ("variance_evidence_mode", "unknown"), + ("variance_semantics", 42), + ("variance_semantics", "unknown"), + ("owner_contract_reference", "wrong:owner"), + ("owner_contract_version", 0), + ("owner_contract_digest", "8" * 63), + ("released_at", datetime(2026, 9, 17, 1, 0)), + ], +) +def test_record_rejects_malformed_authority_evidence(key: str, value: object) -> None: + with pytest.raises(ValueError): + _record(**{key: value}) + + +def test_approximation_mode_accepts_only_explicit_approximate_semantics() -> None: + record = _record(variance_evidence_mode="approximation", variance_semantics="approximate") + assert record.variance_evidence_mode == "approximation" + assert record.variance_semantics == "approximate" + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("sampling_receipt_reference", "wrong:sampling", ValueError), + ("sampling_receipt_version", True, ValueError), + ("sampling_receipt_digest", "1" * 63, ValueError), + ("analysis_weight_receipt_digest", "2" * 63, ValueError), + ("analytic_case_set_digest", "3" * 63, ValueError), + ("weight_eligibility_receipt_digest", "4" * 63, ValueError), + ("correction_sequence_digest", "5" * 63, ValueError), + ("final_weight_artifact_digest", "6" * 63, ValueError), + ("variance_design_receipt_reference", "wrong:variance", ValueError), + ("variance_design_receipt_version", 0, ValueError), + ("variance_design_receipt_digest", "7" * 63, ValueError), + ("variance_method_reference", "wrong:method", ValueError), + ("variance_method_version", 0, ValueError), + ("variance_evidence_mode", "unknown", ValueError), + ("variance_semantics", "unknown", ValueError), + ("owner_contract_reference", "wrong:owner", ValueError), + ("owner_contract_version", False, ValueError), + ("used_at", datetime(2026, 9, 17, 2, 0), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_fails_before_owner_resolution( + key: str, value: object, error: type[Exception] +) -> None: + port = _Port(_record()) + with pytest.raises(error): + _resolve(read_port=port, **{key: value}) + assert port.calls == 0 + + +@pytest.mark.parametrize("read_port", [_NoMethod(), _ProtocolOnly(), _Descriptor()]) +def test_nonconcrete_owner_capabilities_are_rejected_without_execution(read_port: object) -> None: + with pytest.raises(TypeError): + _resolve(read_port=read_port) + + +@pytest.mark.parametrize( + "record_overrides", + [ + {"tenant_record_id": OTHER_TENANT}, + {"validity_study_id": OTHER_STUDY}, + {"sampling_receipt_reference": "sampling_design_receipt:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa"}, + {"sampling_receipt_version": 4}, + {"sampling_receipt_digest": "a" * 64}, + {"analysis_weight_receipt_digest": "b" * 64}, + {"analytic_case_set_digest": "c" * 64}, + {"weight_eligibility_receipt_digest": "d" * 64}, + {"correction_sequence_digest": "e" * 64}, + {"final_weight_artifact_digest": "f" * 64}, + {"variance_design_receipt_reference": "variance_design_receipt:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb"}, + {"variance_design_receipt_version": 6}, + {"variance_design_receipt_digest": "a" * 64}, + {"variance_method_reference": "variance_method:cccccccc-cccc-4ccc-8ccc-cccccccccccc"}, + {"variance_method_version": 3}, + {"variance_evidence_mode": "joint_inclusion"}, + {"variance_semantics": "approximate"}, + {"owner_contract_reference": "released_owner_contract:dddddddd-dddd-4ddd-8ddd-dddddddddddd"}, + {"owner_contract_version": 5}, + ], +) +def test_every_requested_coordinate_must_match_owner_evidence( + record_overrides: dict[str, object] +) -> None: + with pytest.raises(WeightVarianceAuthorityIntegrityError): + _resolve(result=_record(**record_overrides)) + + +def test_uuid_views_are_detached_from_retained_references() -> None: + tenant = UUID(str(TENANT)) + record = _record(tenant_record_id=tenant) + object.__setattr__(tenant, "int", OTHER_TENANT.int) + assert record.tenant_record_id == TENANT + + view = _resolve(result=record) + returned = view.tenant_record_id + object.__setattr__(returned, "int", OTHER_TENANT.int) + assert view.tenant_record_id == TENANT From 5f399de64f3fd4d302361e7f0a5eb4992e42a8d7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 10:16:33 +0900 Subject: [PATCH 072/603] fix(workforce-validation): align variance authority with scientific receipt --- .../variance_authority.py | 58 ++++++++++++------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py index 5074fdf04..4a1d02c8f 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py @@ -51,9 +51,9 @@ "sampling_receipt_version", "sampling_receipt_digest", "analysis_weight_receipt_digest", - "analytic_case_set_digest", + "analytic_case_occurrence_set_digest", "weight_eligibility_receipt_digest", - "correction_sequence_digest", + "weight_correction_sequence", "final_weight_artifact_digest", "variance_design_receipt_reference", "variance_design_receipt_version", @@ -132,9 +132,9 @@ def __new__( sampling_receipt_version: int, sampling_receipt_digest: str, analysis_weight_receipt_digest: str, - analytic_case_set_digest: str, + analytic_case_occurrence_set_digest: str, weight_eligibility_receipt_digest: str, - correction_sequence_digest: str, + weight_correction_sequence: int, final_weight_artifact_digest: str, variance_design_receipt_reference: str, variance_design_receipt_version: int, @@ -164,12 +164,14 @@ def __new__( point_digest = _require_digest( "analysis_weight_receipt_digest", analysis_weight_receipt_digest ) - case_digest = _require_digest("analytic_case_set_digest", analytic_case_set_digest) + case_digest = _require_digest( + "analytic_case_occurrence_set_digest", analytic_case_occurrence_set_digest + ) eligibility_digest = _require_digest( "weight_eligibility_receipt_digest", weight_eligibility_receipt_digest ) - correction_digest = _require_digest( - "correction_sequence_digest", correction_sequence_digest + correction_sequence = _require_positive_integer( + "weight_correction_sequence", weight_correction_sequence ) final_digest = _require_digest("final_weight_artifact_digest", final_weight_artifact_digest) variance_ref = _require_reference( @@ -183,6 +185,10 @@ def __new__( variance_digest = _require_digest( "variance_design_receipt_digest", variance_design_receipt_digest ) + if variance_digest == point_digest: + raise ValueError( + "variance_design_receipt_digest must identify evidence distinct from the analysis weight receipt." + ) method_ref = _require_reference( "variance_method_reference", variance_method_reference, "variance_method" ) @@ -209,7 +215,7 @@ def __new__( point_digest, case_digest, eligibility_digest, - correction_digest, + correction_sequence, final_digest, variance_ref, variance_version, @@ -261,8 +267,8 @@ def analysis_weight_receipt_digest(self) -> str: return self[6] @property - def analytic_case_set_digest(self) -> str: - """Return the exact ordered analytic-case evidence digest.""" + def analytic_case_occurrence_set_digest(self) -> str: + """Return the exact ordered analytic-case occurrence-set digest.""" return self[7] @property @@ -271,8 +277,8 @@ def weight_eligibility_receipt_digest(self) -> str: return self[8] @property - def correction_sequence_digest(self) -> str: - """Return the append-only point-weight correction sequence digest.""" + def weight_correction_sequence(self) -> int: + """Return the append-only point-weight correction sequence.""" return self[9] @property @@ -406,9 +412,9 @@ def resolve_weight_variance_authority( sampling_receipt_version: int, sampling_receipt_digest: str, analysis_weight_receipt_digest: str, - analytic_case_set_digest: str, + analytic_case_occurrence_set_digest: str, weight_eligibility_receipt_digest: str, - correction_sequence_digest: str, + weight_correction_sequence: int, final_weight_artifact_digest: str, variance_design_receipt_reference: str, variance_design_receipt_version: int, @@ -452,11 +458,15 @@ def resolve_weight_variance_authority( ) sampling_digest = _require_digest("sampling_receipt_digest", sampling_receipt_digest) point_digest = _require_digest("analysis_weight_receipt_digest", analysis_weight_receipt_digest) - case_digest = _require_digest("analytic_case_set_digest", analytic_case_set_digest) + case_digest = _require_digest( + "analytic_case_occurrence_set_digest", analytic_case_occurrence_set_digest + ) eligibility_digest = _require_digest( "weight_eligibility_receipt_digest", weight_eligibility_receipt_digest ) - correction_digest = _require_digest("correction_sequence_digest", correction_sequence_digest) + correction_sequence = _require_positive_integer( + "weight_correction_sequence", weight_correction_sequence + ) final_digest = _require_digest("final_weight_artifact_digest", final_weight_artifact_digest) variance_ref = _require_reference( "variance_design_receipt_reference", @@ -469,6 +479,10 @@ def resolve_weight_variance_authority( variance_digest = _require_digest( "variance_design_receipt_digest", variance_design_receipt_digest ) + if variance_digest == point_digest: + raise ValueError( + "variance_design_receipt_digest must identify evidence distinct from the analysis weight receipt." + ) method_ref = _require_reference( "variance_method_reference", variance_method_reference, "variance_method" ) @@ -530,9 +544,9 @@ def resolve_weight_variance_authority( sampling_receipt_version=persisted.sampling_receipt_version, sampling_receipt_digest=persisted.sampling_receipt_digest, analysis_weight_receipt_digest=persisted.analysis_weight_receipt_digest, - analytic_case_set_digest=persisted.analytic_case_set_digest, + analytic_case_occurrence_set_digest=persisted.analytic_case_occurrence_set_digest, weight_eligibility_receipt_digest=persisted.weight_eligibility_receipt_digest, - correction_sequence_digest=persisted.correction_sequence_digest, + weight_correction_sequence=persisted.weight_correction_sequence, final_weight_artifact_digest=persisted.final_weight_artifact_digest, variance_design_receipt_reference=persisted.variance_design_receipt_reference, variance_design_receipt_version=persisted.variance_design_receipt_version, @@ -555,9 +569,9 @@ def resolve_weight_variance_authority( or record.sampling_receipt_version != sampling_version or record.sampling_receipt_digest != sampling_digest or record.analysis_weight_receipt_digest != point_digest - or record.analytic_case_set_digest != case_digest + or record.analytic_case_occurrence_set_digest != case_digest or record.weight_eligibility_receipt_digest != eligibility_digest - or record.correction_sequence_digest != correction_digest + or record.weight_correction_sequence != correction_sequence or record.final_weight_artifact_digest != final_digest or record.variance_design_receipt_reference != variance_ref or record.variance_design_receipt_version != variance_version @@ -583,9 +597,9 @@ def resolve_weight_variance_authority( "sampling_receipt_version": record.sampling_receipt_version, "sampling_receipt_digest": record.sampling_receipt_digest, "analysis_weight_receipt_digest": record.analysis_weight_receipt_digest, - "analytic_case_set_digest": record.analytic_case_set_digest, + "analytic_case_occurrence_set_digest": record.analytic_case_occurrence_set_digest, "weight_eligibility_receipt_digest": record.weight_eligibility_receipt_digest, - "correction_sequence_digest": record.correction_sequence_digest, + "weight_correction_sequence": record.weight_correction_sequence, "final_weight_artifact_digest": record.final_weight_artifact_digest, "variance_design_receipt_reference": record.variance_design_receipt_reference, "variance_design_receipt_version": record.variance_design_receipt_version, From 89100e0b7f816056a4590c60718deaa26ba10c82 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 10:16:59 +0900 Subject: [PATCH 073/603] test(workforce-validation): align variance authority RED with leaf contract --- .../tests/test_weight_variance_authority.py | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/services/workforce-validation-api/tests/test_weight_variance_authority.py b/services/workforce-validation-api/tests/test_weight_variance_authority.py index c1f23c4b5..ff547ea2d 100644 --- a/services/workforce-validation-api/tests/test_weight_variance_authority.py +++ b/services/workforce-validation-api/tests/test_weight_variance_authority.py @@ -30,7 +30,7 @@ ANALYSIS_WEIGHT_DIGEST = "2" * 64 CASE_SET_DIGEST = "3" * 64 ELIGIBILITY_DIGEST = "4" * 64 -CORRECTION_DIGEST = "5" * 64 +CORRECTION_SEQUENCE = 9 FINAL_WEIGHT_DIGEST = "6" * 64 VARIANCE_DIGEST = "7" * 64 OWNER_DIGEST = "8" * 64 @@ -43,9 +43,9 @@ "sampling_receipt_version", "sampling_receipt_digest", "analysis_weight_receipt_digest", - "analytic_case_set_digest", + "analytic_case_occurrence_set_digest", "weight_eligibility_receipt_digest", - "correction_sequence_digest", + "weight_correction_sequence", "final_weight_artifact_digest", "variance_design_receipt_reference", "variance_design_receipt_version", @@ -63,7 +63,7 @@ class _ReadPort: - """Return one configured owner record and retain exact lookup coordinates.""" + """Return one configured owner record and retain the exact lookup coordinates.""" def __init__(self, result: object) -> None: self.result = result @@ -84,7 +84,7 @@ def read_weight_variance_authority( owner_contract_reference: str, owner_contract_version: int, ) -> object: - """Capture the immutable owner lookup and return the configured result.""" + """Capture the owner lookup and return the configured result.""" self.calls.append( ( tenant_record_id, @@ -136,9 +136,9 @@ def _record(**overrides: object) -> WeightVarianceAuthorityRecord: "sampling_receipt_version": 3, "sampling_receipt_digest": SAMPLING_DIGEST, "analysis_weight_receipt_digest": ANALYSIS_WEIGHT_DIGEST, - "analytic_case_set_digest": CASE_SET_DIGEST, + "analytic_case_occurrence_set_digest": CASE_SET_DIGEST, "weight_eligibility_receipt_digest": ELIGIBILITY_DIGEST, - "correction_sequence_digest": CORRECTION_DIGEST, + "weight_correction_sequence": CORRECTION_SEQUENCE, "final_weight_artifact_digest": FINAL_WEIGHT_DIGEST, "variance_design_receipt_reference": VARIANCE_REFERENCE, "variance_design_receipt_version": 5, @@ -165,9 +165,9 @@ def _resolve(*, read_port: object, **overrides: object) -> WeightVarianceAuthori "sampling_receipt_version": 3, "sampling_receipt_digest": SAMPLING_DIGEST, "analysis_weight_receipt_digest": ANALYSIS_WEIGHT_DIGEST, - "analytic_case_set_digest": CASE_SET_DIGEST, + "analytic_case_occurrence_set_digest": CASE_SET_DIGEST, "weight_eligibility_receipt_digest": ELIGIBILITY_DIGEST, - "correction_sequence_digest": CORRECTION_DIGEST, + "weight_correction_sequence": CORRECTION_SEQUENCE, "final_weight_artifact_digest": FINAL_WEIGHT_DIGEST, "variance_design_receipt_reference": VARIANCE_REFERENCE, "variance_design_receipt_version": 5, @@ -212,6 +212,7 @@ def test_resolution_authorizes_then_returns_owner_corroborated_compatibility() - assert view.validity_study_id == STUDY fields = dict(view.fields) assert fields["final_weight_artifact_digest"] == FINAL_WEIGHT_DIGEST + assert fields["weight_correction_sequence"] == CORRECTION_SEQUENCE assert fields["variance_design_receipt_digest"] == VARIANCE_DIGEST assert fields["owner_contract_digest"] == OWNER_DIGEST assert fields["released_at"] == RELEASED_AT @@ -232,17 +233,31 @@ def test_missing_noncanonical_or_mismatched_owner_evidence_fails_closed() -> Non with pytest.raises(WeightVarianceAuthorityIntegrityError): _resolve(read_port=_ReadPort(object())) with pytest.raises(WeightVarianceAuthorityIntegrityError): - _resolve(read_port=_ReadPort(_record(analytic_case_set_digest="a" * 64))) + _resolve( + read_port=_ReadPort( + _record(analytic_case_occurrence_set_digest="a" * 64) + ) + ) with pytest.raises(WeightVarianceAuthorityIntegrityError): _resolve(read_port=_ReadPort(_record(final_weight_artifact_digest="b" * 64))) +def test_point_and_variance_receipts_must_be_distinct() -> None: + with pytest.raises(ValueError): + _record(variance_design_receipt_digest=ANALYSIS_WEIGHT_DIGEST) + with pytest.raises(ValueError): + _resolve( + read_port=_ReadPort(_record()), + variance_design_receipt_digest=ANALYSIS_WEIGHT_DIGEST, + ) + + def test_approximation_mode_cannot_claim_exact_variance_semantics() -> None: with pytest.raises(ValueError): _record(variance_evidence_mode="approximation", variance_semantics="exact") -def test_invalid_dependency_and_pre_release_use_fail_before_owner_read() -> None: +def test_invalid_dependency_and_pre_release_use_fail_closed() -> None: with pytest.raises(TypeError): _resolve(read_port=_ProtocolOnly()) From ee64177a6ee33ccd155da776f8f21b5c9dd888f2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 10:17:32 +0900 Subject: [PATCH 074/603] test(workforce-validation): align variance authority edge coverage --- .../test_weight_variance_authority_edges.py | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/services/workforce-validation-api/tests/test_weight_variance_authority_edges.py b/services/workforce-validation-api/tests/test_weight_variance_authority_edges.py index e70587a50..b27f49a29 100644 --- a/services/workforce-validation-api/tests/test_weight_variance_authority_edges.py +++ b/services/workforce-validation-api/tests/test_weight_variance_authority_edges.py @@ -29,7 +29,7 @@ ANALYSIS_WEIGHT_DIGEST = "2" * 64 CASE_SET_DIGEST = "3" * 64 ELIGIBILITY_DIGEST = "4" * 64 -CORRECTION_DIGEST = "5" * 64 +CORRECTION_SEQUENCE = 9 FINAL_WEIGHT_DIGEST = "6" * 64 VARIANCE_DIGEST = "7" * 64 OWNER_DIGEST = "8" * 64 @@ -42,9 +42,9 @@ "sampling_receipt_version", "sampling_receipt_digest", "analysis_weight_receipt_digest", - "analytic_case_set_digest", + "analytic_case_occurrence_set_digest", "weight_eligibility_receipt_digest", - "correction_sequence_digest", + "weight_correction_sequence", "final_weight_artifact_digest", "variance_design_receipt_reference", "variance_design_receipt_version", @@ -114,9 +114,9 @@ def _record(**overrides: object) -> WeightVarianceAuthorityRecord: "sampling_receipt_version": 3, "sampling_receipt_digest": SAMPLING_DIGEST, "analysis_weight_receipt_digest": ANALYSIS_WEIGHT_DIGEST, - "analytic_case_set_digest": CASE_SET_DIGEST, + "analytic_case_occurrence_set_digest": CASE_SET_DIGEST, "weight_eligibility_receipt_digest": ELIGIBILITY_DIGEST, - "correction_sequence_digest": CORRECTION_DIGEST, + "weight_correction_sequence": CORRECTION_SEQUENCE, "final_weight_artifact_digest": FINAL_WEIGHT_DIGEST, "variance_design_receipt_reference": VARIANCE_REFERENCE, "variance_design_receipt_version": 5, @@ -144,9 +144,9 @@ def _resolve(*, result: object | None = None, read_port: object | None = None, * "sampling_receipt_version": 3, "sampling_receipt_digest": SAMPLING_DIGEST, "analysis_weight_receipt_digest": ANALYSIS_WEIGHT_DIGEST, - "analytic_case_set_digest": CASE_SET_DIGEST, + "analytic_case_occurrence_set_digest": CASE_SET_DIGEST, "weight_eligibility_receipt_digest": ELIGIBILITY_DIGEST, - "correction_sequence_digest": CORRECTION_DIGEST, + "weight_correction_sequence": CORRECTION_SEQUENCE, "final_weight_artifact_digest": FINAL_WEIGHT_DIGEST, "variance_design_receipt_reference": VARIANCE_REFERENCE, "variance_design_receipt_version": 5, @@ -180,9 +180,10 @@ def _resolve(*, result: object | None = None, read_port: object | None = None, * ("sampling_receipt_digest", 42), ("sampling_receipt_digest", "1" * 63), ("analysis_weight_receipt_digest", "2" * 63), - ("analytic_case_set_digest", "3" * 65), + ("analytic_case_occurrence_set_digest", "3" * 65), ("weight_eligibility_receipt_digest", "4" * 63), - ("correction_sequence_digest", "5" * 65), + ("weight_correction_sequence", True), + ("weight_correction_sequence", 0), ("final_weight_artifact_digest", "6" * 63), ("variance_design_receipt_reference", "wrong:variance"), ("variance_design_receipt_version", 0), @@ -221,9 +222,9 @@ def test_approximation_mode_accepts_only_explicit_approximate_semantics() -> Non ("sampling_receipt_version", True, ValueError), ("sampling_receipt_digest", "1" * 63, ValueError), ("analysis_weight_receipt_digest", "2" * 63, ValueError), - ("analytic_case_set_digest", "3" * 63, ValueError), + ("analytic_case_occurrence_set_digest", "3" * 63, ValueError), ("weight_eligibility_receipt_digest", "4" * 63, ValueError), - ("correction_sequence_digest", "5" * 63, ValueError), + ("weight_correction_sequence", 0, ValueError), ("final_weight_artifact_digest", "6" * 63, ValueError), ("variance_design_receipt_reference", "wrong:variance", ValueError), ("variance_design_receipt_version", 0, ValueError), @@ -262,9 +263,9 @@ def test_nonconcrete_owner_capabilities_are_rejected_without_execution(read_port {"sampling_receipt_version": 4}, {"sampling_receipt_digest": "a" * 64}, {"analysis_weight_receipt_digest": "b" * 64}, - {"analytic_case_set_digest": "c" * 64}, + {"analytic_case_occurrence_set_digest": "c" * 64}, {"weight_eligibility_receipt_digest": "d" * 64}, - {"correction_sequence_digest": "e" * 64}, + {"weight_correction_sequence": 10}, {"final_weight_artifact_digest": "f" * 64}, {"variance_design_receipt_reference": "variance_design_receipt:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb"}, {"variance_design_receipt_version": 6}, From 06657581eee53b3bb654407f07b190caa0f9a720 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 10:18:41 +0900 Subject: [PATCH 075/603] docs(workforce-validation): document variance authority boundary --- services/workforce-validation-api/README.md | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 78eef5ea2..61d1ac118 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -1,6 +1,6 @@ # Orgmetra Workforce Validation API -This package is the application boundary for the `workforce_validation` bounded context. The current slice exposes purpose-bound owner reads for the existing validity-study registry header and for value-minimized scientific auxiliary-use authority, while establishing the context-local PostgreSQL ownership bootstrap. +This package is the application boundary for the `workforce_validation` bounded context. The current slice exposes purpose-bound owner reads for the existing validity-study registry header, value-minimized scientific auxiliary-use authority, and point-weight/variance-design compatibility authority while establishing the context-local PostgreSQL ownership bootstrap. It does **not** query People, Talent Acquisition, Performance Management, Job Architecture, Psychometrics Commons, fast-mlsirm, TEPP, or another bounded context's application tables. Those contexts remain separate owners. Exact foreign identifiers and immutable specialist/scientific evidence cross this boundary only through released/versioned contracts and owner ports. @@ -22,7 +22,7 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar `ValidityStudyView` is a data projection, not a durable authorization credential or cryptographic capability. Downstream consequential actions must perform their own purpose-bound authorization and authoritative re-resolution rather than treating the Python runtime type as reusable authority. Low-level interpreter construction is outside the supported public API and is not accepted as proof that authorization occurred. -`resolve_calibration_auxiliary_authority(...)` is the first executable owner-side slice for #407's durable scientific-evidence resolution gap. It does **not** import or copy the mutable validity-analysis implementation. Instead it defines the `workforce_validation` application contract that a later durable adapter must satisfy: +`resolve_calibration_auxiliary_authority(...)` is an executable owner-side slice for #407's durable scientific-evidence resolution gap. It does **not** import or copy the mutable validity-analysis implementation. Instead it defines the `workforce_validation` application contract that a later durable adapter must satisfy: - authorize the exact tenant/study scientific read before invoking the owner port; - carry only opaque projection/purpose/owner/authorization/scientific-use references, SHA-256 evidence digests, immutable contract versions, the owner-resolved scientific-use instant, and authorization time bounds—never calibration source attributes, protected characteristics, benchmark values, or row-level weights; @@ -33,7 +33,18 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar - reconstruct the returned evidence into an exact tuple-backed `CalibrationAuxiliaryAuthorityRecord` and require tenant, study, projection, scientific purpose, released owner contract, authorization receipt, scientific-use receipt, and use time to match the requested coordinates; - issue only a minimized `CalibrationAuxiliaryAuthorityView`. The view is corroborating data, not a reusable authorization credential or proof that an arbitrary injected port is a production owner. -This closes the application-contract false-GREEN where opaque coordinates or a caller-selected use instant could be accepted without owner correlation. It does **not** complete #407: the current branch has no durable scientific-authority relation or released auxiliary-evidence adapter. After the canonical owner persistence path is protected truth, #248 or its verified successor must implement the schema-qualified, least-privilege durable port and prove that the resolved owner evidence is itself released/versioned and purpose-authorized. Mutable #57 source is not a dependency of this service. +`resolve_weight_variance_authority(...)` closes a separate #406/#407 application false-GREEN: a scientific leaf can prove internally that a point-weight receipt and variance receipt have compatible digests, yet a durable service must not treat those caller-supplied coordinates as owner authority. This resolver therefore: + +- authorizes the exact tenant/study scientific read before invoking one statically captured `WeightVarianceAuthorityReadPort`, rejecting inherited Protocol placeholders and descriptors; +- binds the released #405 sampling receipt reference/version/digest to the final analysis-weight receipt digest and the separate #406 variance-design receipt reference/version/digest; +- mirrors the active scientific compatibility contract's decisive basis: exact analytic-case occurrence set, weight-eligibility receipt, integer correction sequence, and final point-weight artifact; +- requires a controlled variance method reference/version, a controlled evidence mode (`joint_inclusion`, `reproducible_design_algorithm`, `replicate_weights`, or explicit `approximation`), and exact-versus-approximate semantics; an approximation cannot be labelled exact; +- rejects a variance-design receipt digest that aliases the final point-weight receipt digest; +- requires a released owner-contract reference/version/digest and owner-resolved `released_at`, rejecting use before that release instant; +- reconstructs owner evidence into an exact tuple-backed `WeightVarianceAuthorityRecord` and fails closed if any requested scientific coordinate differs from the owner projection; +- returns only a minimized `WeightVarianceAuthorityView`. It never copies row-level point weights, replicate vectors, frame/cluster/stratum variables, protected characteristics, or foreign application-table values. + +These application contracts do **not** complete #407 and do not make an arbitrary injected Python port durable scientific authority. The current branch has no durable scientific-authority relation or released auxiliary/variance-evidence adapter. After the canonical owner persistence path is protected truth, #248 or its verified successor must implement schema-qualified least-privilege durable ports and prove that resolved owner evidence is itself released/versioned and purpose-authorized. Mutable #57 source is not a runtime or source dependency of this service; its active compatibility contract was used only to align the application boundary's evidence coordinates. `services/workforce-validation-api/database/migrations/0001_owner_schema.sql` starts this bounded context's own migration history. It creates the `workforce_validation` schema and deny-default `workforce_validation_role`, revokes public schema access, and intentionally creates or moves no application table yet. The role is a **NOLOGIN migration/schema owner only**; runtime principals must not be granted that owner role. PostgreSQL applies role-level configuration defaults at login and does not re-apply them on `SET ROLE`, so an `ALTER ROLE ... SET search_path` entry on this NOLOGIN role is not treated as a runtime isolation control. The later durable adapter must use a distinct least-privilege runtime role, schema-qualified `workforce_validation` relations, and explicit function-level `search_path` where `SECURITY DEFINER` code is introduced. @@ -52,7 +63,7 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ services/workforce-validation-api/tests ``` -The service package keeps an exact 100% owned statement/branch threshold. The calibration-authority contract adds hostile coverage for authorization-before-owner-read, non-concrete/dynamic owner capabilities, malformed references/digests/versions/timestamps, foreign/mismatched owner evidence, caller/owner scientific-use-time mismatch, authorization-window mismatch, UUID alias mutation, structural immutability, and non-public view issuance. +The service package keeps an exact 100% owned statement/branch threshold. Calibration-authority coverage exercises authorization-before-owner-read, non-concrete/dynamic owner capabilities, malformed references/digests/versions/timestamps, foreign/mismatched owner evidence, caller/owner scientific-use-time mismatch, authorization-window mismatch, UUID alias mutation, structural immutability, and non-public view issuance. Weight/variance-authority coverage additionally exercises every owner-coordinate mismatch, point/variance evidence aliasing, unsupported evidence modes and semantics, approximation-labelled-as-exact, pre-release use, foreign tenant/study evidence, integer correction-sequence mismatches, detached UUID views, and non-public output issuance. The same Foundation job also runs `tests/test_workforce_validation_owner_schema_postgres.sh` in its own pinned PostgreSQL 16.14 container. That contract executes the service-local owner migration and checks the exact deny-default role flags, schema owner, absence of ineffective login-only `rolconfig`, actual `SET ROLE` search-path behavior, absence of inherited PUBLIC `USAGE`/`CREATE`, and absence of application relations in the bootstrap schema. The test intentionally demonstrates that `SET ROLE` retains the caller's existing `search_path`; runtime isolation therefore cannot be inferred from owner-role metadata. From 71e34d655cacde74f7ba15d7ccd0b3a1a4117b77 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 12:06:05 +0900 Subject: [PATCH 076/603] test(workforce-validation): add benchmark authority RED --- .../test_calibration_benchmark_authority.py | 333 ++++++++++++++++++ 1 file changed, 333 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_benchmark_authority.py diff --git a/services/workforce-validation-api/tests/test_calibration_benchmark_authority.py b/services/workforce-validation-api/tests/test_calibration_benchmark_authority.py new file mode 100644 index 000000000..20c07d0e7 --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_benchmark_authority.py @@ -0,0 +1,333 @@ +"""Fail-closed contract for released calibration benchmark authority.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.benchmark_authority import ( + CalibrationBenchmarkAuthorityIntegrityError, + CalibrationBenchmarkAuthorityNotFound, + CalibrationBenchmarkAuthorityReadPort, + CalibrationBenchmarkAuthorityRecord, + CalibrationBenchmarkAuthorityView, + resolve_calibration_benchmark_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000d2") +BENCHMARK_REFERENCE = "calibration_benchmark_receipt:11111111-1111-4111-8111-111111111111" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +BENCHMARK_DIGEST = "1" * 64 +OWNER_CONTRACT_DIGEST = "2" * 64 +BENCHMARK_REFERENCE_AT = datetime(2026, 6, 30, tzinfo=timezone.utc) +BENCHMARK_RELEASED_AT = datetime(2026, 7, 15, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 7, 1, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "benchmark_receipt_reference", + "benchmark_receipt_version", + "benchmark_receipt_digest", + "benchmark_owner_contract_reference", + "benchmark_owner_contract_version", + "benchmark_owner_contract_digest", + "benchmark_reference_at", + "benchmark_receipt_released_at", + "owner_contract_released_at", + } +) + + +class _ReadPort: + """Return configured benchmark authority and retain exact lookup coordinates.""" + + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[tuple[object, ...]] = [] + + def read_calibration_benchmark_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + benchmark_receipt_reference: str, + benchmark_receipt_version: int, + benchmark_receipt_digest: str, + benchmark_owner_contract_reference: str, + benchmark_owner_contract_version: int, + benchmark_owner_contract_digest: str, + benchmark_reference_at: datetime, + ) -> object: + """Capture the owner lookup and return configured evidence.""" + self.calls.append( + ( + tenant_record_id, + validity_study_id, + benchmark_receipt_reference, + benchmark_receipt_version, + benchmark_receipt_digest, + benchmark_owner_contract_reference, + benchmark_owner_contract_version, + benchmark_owner_contract_digest, + benchmark_reference_at, + ) + ) + return self.result + + +class _NoReadMethod: + """Deliberately fail the owner-port protocol.""" + + +class _ProtocolOnly(CalibrationBenchmarkAuthorityReadPort): + """Inherit only the Protocol placeholder, not a concrete owner capability.""" + + +class _DescriptorReadPort: + """Expose a descriptor that must be rejected without executing it.""" + + @property + def read_calibration_benchmark_authority(self) -> object: + raise AssertionError("descriptor must not execute") + + +def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=tenant_record_id, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="calibration-benchmark-authority-read-v1", + resource_kind="calibration_benchmark_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record(**overrides: object) -> CalibrationBenchmarkAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "benchmark_receipt_reference": BENCHMARK_REFERENCE, + "benchmark_receipt_version": 4, + "benchmark_receipt_digest": BENCHMARK_DIGEST, + "benchmark_owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "benchmark_owner_contract_version": 3, + "benchmark_owner_contract_digest": OWNER_CONTRACT_DIGEST, + "benchmark_reference_at": BENCHMARK_REFERENCE_AT, + "benchmark_receipt_released_at": BENCHMARK_RELEASED_AT, + "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, + } + values.update(overrides) + return CalibrationBenchmarkAuthorityRecord(**values) + + +def _resolve(*, read_port: object, **overrides: object) -> CalibrationBenchmarkAuthorityView: + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "benchmark_receipt_reference": BENCHMARK_REFERENCE, + "benchmark_receipt_version": 4, + "benchmark_receipt_digest": BENCHMARK_DIGEST, + "benchmark_owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "benchmark_owner_contract_version": 3, + "benchmark_owner_contract_digest": OWNER_CONTRACT_DIGEST, + "benchmark_reference_at": BENCHMARK_REFERENCE_AT, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_calibration_benchmark_authority(**values) + + +def test_resolution_authorizes_then_returns_released_minimized_evidence() -> None: + port = _ReadPort(_record()) + + view = _resolve(read_port=port) + + assert isinstance(port, CalibrationBenchmarkAuthorityReadPort) + assert port.calls == [ + ( + TENANT, + STUDY, + BENCHMARK_REFERENCE, + 4, + BENCHMARK_DIGEST, + OWNER_CONTRACT_REFERENCE, + 3, + OWNER_CONTRACT_DIGEST, + BENCHMARK_REFERENCE_AT, + ) + ] + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + assert view.fields == ( + ("benchmark_owner_contract_digest", OWNER_CONTRACT_DIGEST), + ("benchmark_owner_contract_reference", OWNER_CONTRACT_REFERENCE), + ("benchmark_owner_contract_version", 3), + ("benchmark_receipt_digest", BENCHMARK_DIGEST), + ("benchmark_receipt_reference", BENCHMARK_REFERENCE), + ("benchmark_receipt_released_at", BENCHMARK_RELEASED_AT), + ("benchmark_receipt_version", 4), + ("benchmark_reference_at", BENCHMARK_REFERENCE_AT), + ("owner_contract_released_at", OWNER_CONTRACT_RELEASED_AT), + ) + + +def test_authorization_denial_happens_before_owner_resolution() -> None: + port = _ReadPort(_record()) + + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, policy=_policy(purpose_code="audit_review")) + + assert port.calls == [] + + +def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: + with pytest.raises(CalibrationBenchmarkAuthorityNotFound): + _resolve(read_port=_ReadPort(None)) + + with pytest.raises(CalibrationBenchmarkAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object())) + + +@pytest.mark.parametrize( + "record_overrides", + [ + {"tenant_record_id": OTHER_TENANT}, + {"validity_study_id": OTHER_STUDY}, + { + "benchmark_receipt_reference": ( + "calibration_benchmark_receipt:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" + ) + }, + {"benchmark_receipt_version": 5}, + {"benchmark_receipt_digest": "a" * 64}, + { + "benchmark_owner_contract_reference": ( + "released_owner_contract:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" + ) + }, + {"benchmark_owner_contract_version": 4}, + {"benchmark_owner_contract_digest": "b" * 64}, + {"benchmark_reference_at": BENCHMARK_REFERENCE_AT + timedelta(seconds=1)}, + ], +) +def test_owner_evidence_must_match_every_leaf_benchmark_coordinate( + record_overrides: dict[str, object] +) -> None: + with pytest.raises(CalibrationBenchmarkAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(**record_overrides))) + + +def test_owner_evidence_must_have_existed_before_scientific_use() -> None: + for overrides in ( + {"benchmark_receipt_released_at": USED_AT + timedelta(seconds=1)}, + {"owner_contract_released_at": USED_AT + timedelta(seconds=1)}, + {"benchmark_reference_at": USED_AT + timedelta(seconds=1)}, + ): + port = _ReadPort(_record(**overrides)) + with pytest.raises(CalibrationBenchmarkAuthorityIntegrityError): + _resolve( + read_port=port, + benchmark_reference_at=overrides.get( + "benchmark_reference_at", BENCHMARK_REFERENCE_AT + ), + ) + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("benchmark_receipt_reference", "wrong:benchmark", ValueError), + ("benchmark_receipt_version", True, ValueError), + ("benchmark_receipt_digest", "ABC", ValueError), + ("benchmark_owner_contract_reference", "wrong:contract", ValueError), + ("benchmark_owner_contract_version", 0, ValueError), + ("benchmark_owner_contract_digest", "2" * 63, ValueError), + ("benchmark_reference_at", datetime(2026, 6, 30), ValueError), + ("used_at", datetime(2026, 9, 17), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_or_dependency_fails_before_owner_resolution( + key: str, value: object, error: type[Exception] +) -> None: + port = _ReadPort(_record()) + overrides = {key: value} + if key == "read_port": + port = value # type: ignore[assignment] + overrides = {} + with pytest.raises(error): + _resolve(read_port=port, **overrides) + if isinstance(port, _ReadPort): + assert port.calls == [] + + +@pytest.mark.parametrize( + ("key", "value"), + [ + ("tenant_record_id", UUID(int=0)), + ("validity_study_id", "not-a-uuid"), + ("benchmark_receipt_reference", "wrong:benchmark"), + ("benchmark_receipt_version", 0), + ("benchmark_receipt_digest", "1" * 63), + ("benchmark_owner_contract_reference", "wrong:contract"), + ("benchmark_owner_contract_version", True), + ("benchmark_owner_contract_digest", "2" * 65), + ("benchmark_reference_at", datetime(2026, 6, 30)), + ("benchmark_receipt_released_at", datetime(2026, 7, 15)), + ("owner_contract_released_at", "not-a-datetime"), + ], +) +def test_record_rejects_invalid_released_benchmark_evidence(key: str, value: object) -> None: + with pytest.raises((TypeError, ValueError)): + _record(**{key: value}) + + +def test_record_and_view_are_structurally_immutable_and_uuid_views_are_detached() -> None: + tenant = UUID(str(TENANT)) + record = _record(tenant_record_id=tenant) + object.__setattr__(tenant, "int", OTHER_TENANT.int) + assert record.tenant_record_id == TENANT + + with pytest.raises(AttributeError): + object.__setattr__(record, "benchmark_receipt_version", 999) + + view = _resolve(read_port=_ReadPort(record)) + returned_tenant = view.tenant_record_id + object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) + assert view.tenant_record_id == TENANT + + with pytest.raises(AttributeError): + object.__setattr__(view, "fields", ()) + with pytest.raises(TypeError): + CalibrationBenchmarkAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) From c9dd6d7b7062d6b05fc1c18d07491af81b080804 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 12:06:49 +0900 Subject: [PATCH 077/603] feat(workforce-validation): corroborate released benchmark authority --- .../benchmark_authority.py | 456 ++++++++++++++++++ 1 file changed, 456 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py new file mode 100644 index 000000000..14743e060 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py @@ -0,0 +1,456 @@ +"""Corroborate released calibration benchmark authority through its owner port. + +This application boundary verifies the immutable benchmark coordinates carried by +scientific weighting evidence without copying benchmark values or reading another +bounded context's tables. Durable PostgreSQL/release resolution remains a child +persistence responsibility after this owner service integrates. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +import re +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) + +_DIGEST_PATTERN = re.compile(r"^[0-9a-f]{64}$") +_REFERENCE_PATTERN = re.compile(r"^[a-z][a-z0-9_]*:[A-Za-z0-9][A-Za-z0-9._~-]*$") +_RESOURCE_KIND = "calibration_benchmark_authority" +_OPERATION = "read" +_READ_FIELDS = frozenset( + { + "benchmark_receipt_reference", + "benchmark_receipt_version", + "benchmark_receipt_digest", + "benchmark_owner_contract_reference", + "benchmark_owner_contract_version", + "benchmark_owner_contract_digest", + "benchmark_reference_at", + "benchmark_receipt_released_at", + "owner_contract_released_at", + } +) + + +class CalibrationBenchmarkAuthorityNotFound(LookupError): + """Indicate that no released owner evidence corroborates the benchmark tuple.""" + + +class CalibrationBenchmarkAuthorityIntegrityError(RuntimeError): + """Indicate that owner evidence cannot corroborate the requested benchmark tuple.""" + + +def _require_reference(field_name: str, value: object, namespace: str) -> str: + """Require one exact opaque namespaced reference without benchmark values.""" + if ( + type(value) is not str + or _REFERENCE_PATTERN.fullmatch(value) is None + or value.partition(":")[0] != namespace + ): + raise ValueError(f"{field_name} must be an exact {namespace}: opaque reference.") + return value + + +def _require_digest(field_name: str, value: object) -> str: + """Require lowercase SHA-256 evidence rather than caller-readable benchmark data.""" + if type(value) is not str or _DIGEST_PATTERN.fullmatch(value) is None: + raise ValueError(f"{field_name} must be lowercase SHA-256 hex.") + return value + + +def _require_positive_integer(field_name: str, value: object) -> int: + """Require a strict positive version without accepting booleans.""" + if type(value) is not int or value <= 0: + raise ValueError(f"{field_name} must be a positive integer.") + return value + + +class CalibrationBenchmarkAuthorityRecord(tuple): + """Immutable owner projection for one released calibration benchmark. + + The record contains only opaque references, versions, digests, and temporal + release evidence. Benchmark totals and protected source attributes never cross + this application boundary. + """ + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + benchmark_receipt_reference: str, + benchmark_receipt_version: int, + benchmark_receipt_digest: str, + benchmark_owner_contract_reference: str, + benchmark_owner_contract_version: int, + benchmark_owner_contract_digest: str, + benchmark_reference_at: datetime, + benchmark_receipt_released_at: datetime, + owner_contract_released_at: datetime, + ) -> CalibrationBenchmarkAuthorityRecord: + """Validate and detach all authority-bearing benchmark evidence.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + benchmark_ref = _require_reference( + "benchmark_receipt_reference", + benchmark_receipt_reference, + "calibration_benchmark_receipt", + ) + benchmark_version = _require_positive_integer( + "benchmark_receipt_version", benchmark_receipt_version + ) + benchmark_digest = _require_digest( + "benchmark_receipt_digest", benchmark_receipt_digest + ) + owner_ref = _require_reference( + "benchmark_owner_contract_reference", + benchmark_owner_contract_reference, + "released_owner_contract", + ) + owner_version = _require_positive_integer( + "benchmark_owner_contract_version", benchmark_owner_contract_version + ) + owner_digest = _require_digest( + "benchmark_owner_contract_digest", benchmark_owner_contract_digest + ) + reference_at = _require_aware_datetime( + "benchmark_reference_at", benchmark_reference_at + ) + benchmark_released_at = _require_aware_datetime( + "benchmark_receipt_released_at", benchmark_receipt_released_at + ) + contract_released_at = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + benchmark_ref, + benchmark_version, + benchmark_digest, + owner_ref, + owner_version, + owner_digest, + reference_at, + benchmark_released_at, + contract_released_at, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity for this owner evidence.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity bound to this benchmark use.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def benchmark_receipt_reference(self) -> str: + """Return the immutable calibration-benchmark receipt reference.""" + return self[2] + + @property + def benchmark_receipt_version(self) -> int: + """Return the positive benchmark receipt version.""" + return self[3] + + @property + def benchmark_receipt_digest(self) -> str: + """Return the digest of the exact benchmark receipt bytes.""" + return self[4] + + @property + def benchmark_owner_contract_reference(self) -> str: + """Return the released benchmark-owner contract reference.""" + return self[5] + + @property + def benchmark_owner_contract_version(self) -> int: + """Return the released benchmark-owner contract version.""" + return self[6] + + @property + def benchmark_owner_contract_digest(self) -> str: + """Return the digest of the released benchmark-owner contract.""" + return self[7] + + @property + def benchmark_reference_at(self) -> datetime: + """Return the benchmark's authoritative reference instant.""" + return self[8] + + @property + def benchmark_receipt_released_at(self) -> datetime: + """Return when the benchmark receipt became released evidence.""" + return self[9] + + @property + def owner_contract_released_at(self) -> datetime: + """Return when the benchmark-owner contract became released evidence.""" + return self[10] + + +class CalibrationBenchmarkAuthorityView(tuple): + """Field-minimized benchmark evidence issued only after authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> CalibrationBenchmarkAuthorityView: + """Reject direct construction; only the resolver may issue this view.""" + raise TypeError( + "CalibrationBenchmarkAuthorityView is issued only by " + "resolve_calibration_benchmark_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable released benchmark evidence without benchmark values.""" + return self[2] + + +@runtime_checkable +class CalibrationBenchmarkAuthorityReadPort(Protocol): + """Owner read contract for released/versioned calibration benchmark evidence.""" + + def read_calibration_benchmark_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + benchmark_receipt_reference: str, + benchmark_receipt_version: int, + benchmark_receipt_digest: str, + benchmark_owner_contract_reference: str, + benchmark_owner_contract_version: int, + benchmark_owner_contract_digest: str, + benchmark_reference_at: datetime, + ) -> CalibrationBenchmarkAuthorityRecord | None: + """Return matching released evidence or ``None`` through an owner ACL.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + CalibrationBenchmarkAuthorityReadPort, "read_calibration_benchmark_authority" +) + + +def resolve_calibration_benchmark_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + benchmark_receipt_reference: str, + benchmark_receipt_version: int, + benchmark_receipt_digest: str, + benchmark_owner_contract_reference: str, + benchmark_owner_contract_version: int, + benchmark_owner_contract_digest: str, + benchmark_reference_at: datetime, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: CalibrationBenchmarkAuthorityReadPort, +) -> CalibrationBenchmarkAuthorityView: + """Authorize then corroborate the exact released benchmark tuple. + + The owner must independently resolve both immutable release coordinates and + their release instants. ``used_at`` is the scientific receipt's use instant; + it cannot precede the benchmark receipt, owner contract, or benchmark + reference instant. No benchmark totals are returned. + """ + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static( + type(read_port), "read_calibration_benchmark_authority", None + ) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError( + "read_port must expose a statically callable " + "read_calibration_benchmark_authority." + ) + + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + tenant_id = _restore_operational_uuid("tenant_record_id", tenant_identity) + study_id = _restore_operational_uuid("validity_study_id", study_identity) + benchmark_ref = _require_reference( + "benchmark_receipt_reference", + benchmark_receipt_reference, + "calibration_benchmark_receipt", + ) + benchmark_version = _require_positive_integer( + "benchmark_receipt_version", benchmark_receipt_version + ) + benchmark_digest = _require_digest( + "benchmark_receipt_digest", benchmark_receipt_digest + ) + owner_ref = _require_reference( + "benchmark_owner_contract_reference", + benchmark_owner_contract_reference, + "released_owner_contract", + ) + owner_version = _require_positive_integer( + "benchmark_owner_contract_version", benchmark_owner_contract_version + ) + owner_digest = _require_digest( + "benchmark_owner_contract_digest", benchmark_owner_contract_digest + ) + reference_at = _require_aware_datetime( + "benchmark_reference_at", benchmark_reference_at + ) + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=_restore_operational_uuid("tenant_record_id", tenant_identity), + validity_study_id=_restore_operational_uuid("validity_study_id", study_identity), + benchmark_receipt_reference=benchmark_ref, + benchmark_receipt_version=benchmark_version, + benchmark_receipt_digest=benchmark_digest, + benchmark_owner_contract_reference=owner_ref, + benchmark_owner_contract_version=owner_version, + benchmark_owner_contract_digest=owner_digest, + benchmark_reference_at=reference_at, + ) + if persisted is None: + raise CalibrationBenchmarkAuthorityNotFound(str(study_id)) + if type(persisted) is not CalibrationBenchmarkAuthorityRecord: + raise CalibrationBenchmarkAuthorityIntegrityError( + "owner port returned non-canonical calibration benchmark evidence" + ) + + record = CalibrationBenchmarkAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + benchmark_receipt_reference=persisted.benchmark_receipt_reference, + benchmark_receipt_version=persisted.benchmark_receipt_version, + benchmark_receipt_digest=persisted.benchmark_receipt_digest, + benchmark_owner_contract_reference=persisted.benchmark_owner_contract_reference, + benchmark_owner_contract_version=persisted.benchmark_owner_contract_version, + benchmark_owner_contract_digest=persisted.benchmark_owner_contract_digest, + benchmark_reference_at=persisted.benchmark_reference_at, + benchmark_receipt_released_at=persisted.benchmark_receipt_released_at, + owner_contract_released_at=persisted.owner_contract_released_at, + ) + expected = ( + tenant_id, + study_id, + benchmark_ref, + benchmark_version, + benchmark_digest, + owner_ref, + owner_version, + owner_digest, + reference_at, + ) + observed = ( + record.tenant_record_id, + record.validity_study_id, + record.benchmark_receipt_reference, + record.benchmark_receipt_version, + record.benchmark_receipt_digest, + record.benchmark_owner_contract_reference, + record.benchmark_owner_contract_version, + record.benchmark_owner_contract_digest, + record.benchmark_reference_at, + ) + if observed != expected: + raise CalibrationBenchmarkAuthorityIntegrityError( + "released benchmark authority does not match the requested scientific coordinates" + ) + if ( + record.benchmark_reference_at > use_instant + or record.benchmark_receipt_released_at > use_instant + or record.owner_contract_released_at > use_instant + ): + raise CalibrationBenchmarkAuthorityIntegrityError( + "benchmark and owner evidence must exist no later than the scientific use instant" + ) + + fields: tuple[tuple[str, object], ...] = ( + ("benchmark_owner_contract_digest", record.benchmark_owner_contract_digest), + ("benchmark_owner_contract_reference", record.benchmark_owner_contract_reference), + ("benchmark_owner_contract_version", record.benchmark_owner_contract_version), + ("benchmark_receipt_digest", record.benchmark_receipt_digest), + ("benchmark_receipt_reference", record.benchmark_receipt_reference), + ("benchmark_receipt_released_at", record.benchmark_receipt_released_at), + ("benchmark_receipt_version", record.benchmark_receipt_version), + ("benchmark_reference_at", record.benchmark_reference_at), + ("owner_contract_released_at", record.owner_contract_released_at), + ) + return tuple.__new__( + CalibrationBenchmarkAuthorityView, + ( + _store_operational_uuid("tenant_record_id", tenant_id), + _store_operational_uuid("validity_study_id", study_id), + fields, + ), + ) From 1ca62fc3014dc53c830f30ed44d3c0270adbd6cd Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 12:06:58 +0900 Subject: [PATCH 078/603] feat(workforce-validation): export benchmark authority contract --- .../orgmetra_workforce_validation_api/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index f454188ba..e2b398b40 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -1,5 +1,13 @@ """Canonical workforce-validation application contracts for Orgmetra.""" +from orgmetra_workforce_validation_api.benchmark_authority import ( + CalibrationBenchmarkAuthorityIntegrityError, + CalibrationBenchmarkAuthorityNotFound, + CalibrationBenchmarkAuthorityReadPort, + CalibrationBenchmarkAuthorityRecord, + CalibrationBenchmarkAuthorityView, + resolve_calibration_benchmark_authority, +) from orgmetra_workforce_validation_api.registry import ( ValidationPrincipal, ValidityStudyIntegrityError, @@ -32,6 +40,11 @@ "CalibrationAuxiliaryAuthorityReadPort", "CalibrationAuxiliaryAuthorityRecord", "CalibrationAuxiliaryAuthorityView", + "CalibrationBenchmarkAuthorityIntegrityError", + "CalibrationBenchmarkAuthorityNotFound", + "CalibrationBenchmarkAuthorityReadPort", + "CalibrationBenchmarkAuthorityRecord", + "CalibrationBenchmarkAuthorityView", "ValidationPrincipal", "ValidityStudyIntegrityError", "ValidityStudyNotFound", @@ -45,5 +58,6 @@ "WeightVarianceAuthorityView", "read_validity_study", "resolve_calibration_auxiliary_authority", + "resolve_calibration_benchmark_authority", "resolve_weight_variance_authority", ] From 73eefead641266bc13df8fd2905e0f10be6bd053 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 12:08:06 +0900 Subject: [PATCH 079/603] docs(workforce-validation): document benchmark authority boundary --- services/workforce-validation-api/README.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 61d1ac118..386a3010d 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -1,6 +1,6 @@ # Orgmetra Workforce Validation API -This package is the application boundary for the `workforce_validation` bounded context. The current slice exposes purpose-bound owner reads for the existing validity-study registry header, value-minimized scientific auxiliary-use authority, and point-weight/variance-design compatibility authority while establishing the context-local PostgreSQL ownership bootstrap. +This package is the application boundary for the `workforce_validation` bounded context. The current slice exposes purpose-bound owner reads for the existing validity-study registry header, value-minimized scientific auxiliary-use authority, released calibration-benchmark authority, and point-weight/variance-design compatibility authority while establishing the context-local PostgreSQL ownership bootstrap. It does **not** query People, Talent Acquisition, Performance Management, Job Architecture, Psychometrics Commons, fast-mlsirm, TEPP, or another bounded context's application tables. Those contexts remain separate owners. Exact foreign identifiers and immutable specialist/scientific evidence cross this boundary only through released/versioned contracts and owner ports. @@ -33,6 +33,14 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar - reconstruct the returned evidence into an exact tuple-backed `CalibrationAuxiliaryAuthorityRecord` and require tenant, study, projection, scientific purpose, released owner contract, authorization receipt, scientific-use receipt, and use time to match the requested coordinates; - issue only a minimized `CalibrationAuxiliaryAuthorityView`. The view is corroborating data, not a reusable authorization credential or proof that an arbitrary injected port is a production owner. +`resolve_calibration_benchmark_authority(...)` addresses #407 RED #5 at the canonical service boundary. The scientific leaf now carries benchmark receipt reference/version/digest, released benchmark-owner contract reference/version/digest, and benchmark reference time; this resolver requires an owner port to corroborate those exact coordinates rather than accepting the leaf tuple as authority. It: + +- authorizes the exact tenant/study read before any owner resolution and rejects inherited Protocol placeholders or descriptors as concrete repository capabilities; +- verifies the calibration-benchmark receipt and its released owner contract through opaque references, positive versions, SHA-256 digests, and the exact benchmark reference instant; +- obtains `benchmark_receipt_released_at` and `owner_contract_released_at` from owner evidence rather than from the caller, and rejects scientific use that predates either release or the benchmark reference instant; +- reconstructs returned evidence into an exact tuple-backed `CalibrationBenchmarkAuthorityRecord` and fails closed on any tenant, study, receipt, owner-contract, digest, version, or reference-time mismatch; +- returns only a minimized `CalibrationBenchmarkAuthorityView`; benchmark totals, protected auxiliary values, row-level weights, and foreign application-table values do not cross this boundary. + `resolve_weight_variance_authority(...)` closes a separate #406/#407 application false-GREEN: a scientific leaf can prove internally that a point-weight receipt and variance receipt have compatible digests, yet a durable service must not treat those caller-supplied coordinates as owner authority. This resolver therefore: - authorizes the exact tenant/study scientific read before invoking one statically captured `WeightVarianceAuthorityReadPort`, rejecting inherited Protocol placeholders and descriptors; @@ -44,7 +52,7 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar - reconstructs owner evidence into an exact tuple-backed `WeightVarianceAuthorityRecord` and fails closed if any requested scientific coordinate differs from the owner projection; - returns only a minimized `WeightVarianceAuthorityView`. It never copies row-level point weights, replicate vectors, frame/cluster/stratum variables, protected characteristics, or foreign application-table values. -These application contracts do **not** complete #407 and do not make an arbitrary injected Python port durable scientific authority. The current branch has no durable scientific-authority relation or released auxiliary/variance-evidence adapter. After the canonical owner persistence path is protected truth, #248 or its verified successor must implement schema-qualified least-privilege durable ports and prove that resolved owner evidence is itself released/versioned and purpose-authorized. Mutable #57 source is not a runtime or source dependency of this service; its active compatibility contract was used only to align the application boundary's evidence coordinates. +These application contracts do **not** complete #407 and do not make an arbitrary injected Python port durable scientific authority. The current branch has no durable scientific-authority relation or released auxiliary/benchmark/variance-evidence adapter. After the canonical owner persistence path is protected truth, #248 or its verified successor must implement schema-qualified least-privilege durable ports and prove that resolved owner evidence is itself released/versioned and purpose-authorized. Mutable #57 source is not a runtime or source dependency of this service; its active compatibility and benchmark contracts were used only to align the application boundary's evidence coordinates. `services/workforce-validation-api/database/migrations/0001_owner_schema.sql` starts this bounded context's own migration history. It creates the `workforce_validation` schema and deny-default `workforce_validation_role`, revokes public schema access, and intentionally creates or moves no application table yet. The role is a **NOLOGIN migration/schema owner only**; runtime principals must not be granted that owner role. PostgreSQL applies role-level configuration defaults at login and does not re-apply them on `SET ROLE`, so an `ALTER ROLE ... SET search_path` entry on this NOLOGIN role is not treated as a runtime isolation control. The later durable adapter must use a distinct least-privilege runtime role, schema-qualified `workforce_validation` relations, and explicit function-level `search_path` where `SECURITY DEFINER` code is introduced. @@ -63,7 +71,7 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ services/workforce-validation-api/tests ``` -The service package keeps an exact 100% owned statement/branch threshold. Calibration-authority coverage exercises authorization-before-owner-read, non-concrete/dynamic owner capabilities, malformed references/digests/versions/timestamps, foreign/mismatched owner evidence, caller/owner scientific-use-time mismatch, authorization-window mismatch, UUID alias mutation, structural immutability, and non-public view issuance. Weight/variance-authority coverage additionally exercises every owner-coordinate mismatch, point/variance evidence aliasing, unsupported evidence modes and semantics, approximation-labelled-as-exact, pre-release use, foreign tenant/study evidence, integer correction-sequence mismatches, detached UUID views, and non-public output issuance. +The service package keeps an exact 100% owned statement/branch threshold. Calibration-authority coverage exercises authorization-before-owner-read, non-concrete/dynamic owner capabilities, malformed references/digests/versions/timestamps, foreign/mismatched owner evidence, caller/owner scientific-use-time mismatch, authorization-window mismatch, UUID alias mutation, structural immutability, and non-public view issuance. Calibration-benchmark coverage additionally exercises exact receipt/owner-contract coordinate mismatch, owner-resolved release-time enforcement, future-reference rejection, malformed references/digests/versions/timestamps, foreign tenant/study evidence, detached UUID views, structural immutability, and non-public output issuance. Weight/variance-authority coverage exercises every owner-coordinate mismatch, point/variance evidence aliasing, unsupported evidence modes and semantics, approximation-labelled-as-exact, pre-release use, foreign tenant/study evidence, integer correction-sequence mismatches, detached UUID views, and non-public output issuance. The same Foundation job also runs `tests/test_workforce_validation_owner_schema_postgres.sh` in its own pinned PostgreSQL 16.14 container. That contract executes the service-local owner migration and checks the exact deny-default role flags, schema owner, absence of ineffective login-only `rolconfig`, actual `SET ROLE` search-path behavior, absence of inherited PUBLIC `USAGE`/`CREATE`, and absence of application relations in the bootstrap schema. The test intentionally demonstrates that `SET ROLE` retains the caller's existing `search_path`; runtime isolation therefore cannot be inferred from owner-role metadata. From 9c91eaacff60f08fffe5be5eaaffc6d83af711d2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 12:11:20 +0900 Subject: [PATCH 080/603] test(workforce-validation): cover benchmark authority scalar edges --- ...t_calibration_benchmark_authority_edges.py | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_benchmark_authority_edges.py diff --git a/services/workforce-validation-api/tests/test_calibration_benchmark_authority_edges.py b/services/workforce-validation-api/tests/test_calibration_benchmark_authority_edges.py new file mode 100644 index 000000000..bed793b8b --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_benchmark_authority_edges.py @@ -0,0 +1,54 @@ +"""Branch-complete scalar edges for calibration benchmark authority.""" + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.benchmark_authority import ( + CalibrationBenchmarkAuthorityRecord, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +REFERENCE_AT = datetime(2026, 6, 30, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 7, 15, tzinfo=timezone.utc) + + +def _record(**overrides: object) -> CalibrationBenchmarkAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "benchmark_receipt_reference": ( + "calibration_benchmark_receipt:11111111-1111-4111-8111-111111111111" + ), + "benchmark_receipt_version": 4, + "benchmark_receipt_digest": "1" * 64, + "benchmark_owner_contract_reference": ( + "released_owner_contract:22222222-2222-4222-8222-222222222222" + ), + "benchmark_owner_contract_version": 3, + "benchmark_owner_contract_digest": "2" * 64, + "benchmark_reference_at": REFERENCE_AT, + "benchmark_receipt_released_at": RELEASED_AT, + "owner_contract_released_at": RELEASED_AT, + } + values.update(overrides) + return CalibrationBenchmarkAuthorityRecord(**values) + + +@pytest.mark.parametrize( + ("field_name", "value"), + [ + ("benchmark_receipt_reference", object()), + ("benchmark_receipt_reference", "not namespaced"), + ("benchmark_owner_contract_reference", object()), + ("benchmark_receipt_digest", object()), + ("benchmark_owner_contract_digest", 7), + ], +) +def test_scalar_type_and_reference_shape_edges_fail_closed( + field_name: str, value: object +) -> None: + with pytest.raises(ValueError): + _record(**{field_name: value}) From 76634a041f2d0ae1f45c1c6b446a0576f1721656 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 13:00:48 +0900 Subject: [PATCH 081/603] test(workforce-validation): reject superseded benchmark authority --- ...test_calibration_benchmark_supersession.py | 189 ++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py diff --git a/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py b/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py new file mode 100644 index 000000000..4bdb554b7 --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py @@ -0,0 +1,189 @@ +"""Fail closed when released calibration benchmark evidence has been superseded.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.benchmark_authority import ( + CalibrationBenchmarkAuthorityIntegrityError, + CalibrationBenchmarkAuthorityRecord, + resolve_calibration_benchmark_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +BENCHMARK_REFERENCE = "calibration_benchmark_receipt:11111111-1111-4111-8111-111111111111" +SUCCESSOR_REFERENCE = "calibration_benchmark_receipt:33333333-3333-4333-8333-333333333333" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +BENCHMARK_DIGEST = "1" * 64 +SUCCESSOR_DIGEST = "3" * 64 +OWNER_CONTRACT_DIGEST = "2" * 64 +BENCHMARK_REFERENCE_AT = datetime(2026, 6, 30, tzinfo=timezone.utc) +BENCHMARK_RELEASED_AT = datetime(2026, 7, 15, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 7, 1, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "benchmark_receipt_reference", + "benchmark_receipt_version", + "benchmark_receipt_digest", + "benchmark_owner_contract_reference", + "benchmark_owner_contract_version", + "benchmark_owner_contract_digest", + "benchmark_reference_at", + "benchmark_receipt_released_at", + "benchmark_receipt_superseded_at", + "successor_benchmark_receipt_reference", + "successor_benchmark_receipt_version", + "successor_benchmark_receipt_digest", + "owner_contract_released_at", + } +) + + +class _ReadPort: + """Return one configured owner record through the canonical benchmark read shape.""" + + def __init__(self, record: CalibrationBenchmarkAuthorityRecord) -> None: + self.record = record + + def read_calibration_benchmark_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + benchmark_receipt_reference: str, + benchmark_receipt_version: int, + benchmark_receipt_digest: str, + benchmark_owner_contract_reference: str, + benchmark_owner_contract_version: int, + benchmark_owner_contract_digest: str, + benchmark_reference_at: datetime, + ) -> CalibrationBenchmarkAuthorityRecord: + """Return the owner-resolved record; resolver verifies every requested coordinate.""" + return self.record + + +def _principal() -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy() -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="calibration-benchmark-authority-read-v1", + resource_kind="calibration_benchmark_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record( + *, + superseded_at: datetime | None, + successor_reference: str | None, + successor_version: int | None, + successor_digest: str | None, +) -> CalibrationBenchmarkAuthorityRecord: + return CalibrationBenchmarkAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + benchmark_receipt_reference=BENCHMARK_REFERENCE, + benchmark_receipt_version=4, + benchmark_receipt_digest=BENCHMARK_DIGEST, + benchmark_owner_contract_reference=OWNER_CONTRACT_REFERENCE, + benchmark_owner_contract_version=3, + benchmark_owner_contract_digest=OWNER_CONTRACT_DIGEST, + benchmark_reference_at=BENCHMARK_REFERENCE_AT, + benchmark_receipt_released_at=BENCHMARK_RELEASED_AT, + benchmark_receipt_superseded_at=superseded_at, + successor_benchmark_receipt_reference=successor_reference, + successor_benchmark_receipt_version=successor_version, + successor_benchmark_receipt_digest=successor_digest, + owner_contract_released_at=OWNER_CONTRACT_RELEASED_AT, + ) + + +def _resolve(record: CalibrationBenchmarkAuthorityRecord, *, used_at: datetime = USED_AT): + return resolve_calibration_benchmark_authority( + principal=_principal(), + tenant_record_id=TENANT, + validity_study_id=STUDY, + benchmark_receipt_reference=BENCHMARK_REFERENCE, + benchmark_receipt_version=4, + benchmark_receipt_digest=BENCHMARK_DIGEST, + benchmark_owner_contract_reference=OWNER_CONTRACT_REFERENCE, + benchmark_owner_contract_version=3, + benchmark_owner_contract_digest=OWNER_CONTRACT_DIGEST, + benchmark_reference_at=BENCHMARK_REFERENCE_AT, + used_at=used_at, + purpose_code="selection_validity_analysis", + policy=_policy(), + read_port=_ReadPort(record), + ) + + +def test_historical_use_before_supersession_remains_verifiable_with_successor_lineage() -> None: + superseded_at = USED_AT + timedelta(days=1) + view = _resolve( + _record( + superseded_at=superseded_at, + successor_reference=SUCCESSOR_REFERENCE, + successor_version=5, + successor_digest=SUCCESSOR_DIGEST, + ) + ) + + fields = dict(view.fields) + assert fields["benchmark_receipt_superseded_at"] == superseded_at + assert fields["successor_benchmark_receipt_reference"] == SUCCESSOR_REFERENCE + assert fields["successor_benchmark_receipt_version"] == 5 + assert fields["successor_benchmark_receipt_digest"] == SUCCESSOR_DIGEST + + +def test_benchmark_superseded_by_scientific_use_is_not_authoritative() -> None: + record = _record( + superseded_at=USED_AT, + successor_reference=SUCCESSOR_REFERENCE, + successor_version=5, + successor_digest=SUCCESSOR_DIGEST, + ) + + with pytest.raises(CalibrationBenchmarkAuthorityIntegrityError): + _resolve(record) + + +@pytest.mark.parametrize( + ("superseded_at", "successor_reference", "successor_version", "successor_digest"), + [ + (USED_AT, None, 5, SUCCESSOR_DIGEST), + (None, SUCCESSOR_REFERENCE, 5, SUCCESSOR_DIGEST), + (USED_AT, SUCCESSOR_REFERENCE, 4, SUCCESSOR_DIGEST), + (USED_AT, SUCCESSOR_REFERENCE, 5, BENCHMARK_DIGEST), + (BENCHMARK_RELEASED_AT - timedelta(seconds=1), SUCCESSOR_REFERENCE, 5, SUCCESSOR_DIGEST), + ], +) +def test_owner_record_rejects_incomplete_or_non_append_only_supersession_lineage( + superseded_at: datetime | None, + successor_reference: str | None, + successor_version: int | None, + successor_digest: str | None, +) -> None: + with pytest.raises(ValueError): + _record( + superseded_at=superseded_at, + successor_reference=successor_reference, + successor_version=successor_version, + successor_digest=successor_digest, + ) From df9be280ba610f6d36eb0884042139008f8ce367 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 13:01:40 +0900 Subject: [PATCH 082/603] test(workforce-validation): minimize benchmark supersession projection --- .../test_calibration_benchmark_supersession.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py b/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py index 4bdb554b7..bac51e1b7 100644 --- a/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py +++ b/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py @@ -37,10 +37,6 @@ "benchmark_owner_contract_digest", "benchmark_reference_at", "benchmark_receipt_released_at", - "benchmark_receipt_superseded_at", - "successor_benchmark_receipt_reference", - "successor_benchmark_receipt_version", - "successor_benchmark_receipt_digest", "owner_contract_released_at", } ) @@ -107,11 +103,11 @@ def _record( benchmark_owner_contract_digest=OWNER_CONTRACT_DIGEST, benchmark_reference_at=BENCHMARK_REFERENCE_AT, benchmark_receipt_released_at=BENCHMARK_RELEASED_AT, + owner_contract_released_at=OWNER_CONTRACT_RELEASED_AT, benchmark_receipt_superseded_at=superseded_at, successor_benchmark_receipt_reference=successor_reference, successor_benchmark_receipt_version=successor_version, successor_benchmark_receipt_digest=successor_digest, - owner_contract_released_at=OWNER_CONTRACT_RELEASED_AT, ) @@ -134,11 +130,10 @@ def _resolve(record: CalibrationBenchmarkAuthorityRecord, *, used_at: datetime = ) -def test_historical_use_before_supersession_remains_verifiable_with_successor_lineage() -> None: - superseded_at = USED_AT + timedelta(days=1) +def test_historical_use_before_supersession_remains_verifiable_without_leaking_lineage() -> None: view = _resolve( _record( - superseded_at=superseded_at, + superseded_at=USED_AT + timedelta(days=1), successor_reference=SUCCESSOR_REFERENCE, successor_version=5, successor_digest=SUCCESSOR_DIGEST, @@ -146,10 +141,9 @@ def test_historical_use_before_supersession_remains_verifiable_with_successor_li ) fields = dict(view.fields) - assert fields["benchmark_receipt_superseded_at"] == superseded_at - assert fields["successor_benchmark_receipt_reference"] == SUCCESSOR_REFERENCE - assert fields["successor_benchmark_receipt_version"] == 5 - assert fields["successor_benchmark_receipt_digest"] == SUCCESSOR_DIGEST + assert fields["benchmark_receipt_reference"] == BENCHMARK_REFERENCE + assert "benchmark_receipt_superseded_at" not in fields + assert "successor_benchmark_receipt_reference" not in fields def test_benchmark_superseded_by_scientific_use_is_not_authoritative() -> None: From 279e7ba4b4e9241cc824d0c3a19af0acfc1e326f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 13:02:23 +0900 Subject: [PATCH 083/603] fix(workforce-validation): honor benchmark supersession lineage --- .../benchmark_authority.py | 102 ++++++++++++++++-- 1 file changed, 96 insertions(+), 6 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py index 14743e060..0f4da8f7a 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py @@ -86,8 +86,8 @@ class CalibrationBenchmarkAuthorityRecord(tuple): """Immutable owner projection for one released calibration benchmark. The record contains only opaque references, versions, digests, and temporal - release evidence. Benchmark totals and protected source attributes never cross - this application boundary. + release/correction evidence. Benchmark totals and protected source attributes + never cross this application boundary. """ __slots__ = () @@ -106,6 +106,10 @@ def __new__( benchmark_reference_at: datetime, benchmark_receipt_released_at: datetime, owner_contract_released_at: datetime, + benchmark_receipt_superseded_at: datetime | None = None, + successor_benchmark_receipt_reference: str | None = None, + successor_benchmark_receipt_version: int | None = None, + successor_benchmark_receipt_digest: str | None = None, ) -> CalibrationBenchmarkAuthorityRecord: """Validate and detach all authority-bearing benchmark evidence.""" tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) @@ -141,6 +145,52 @@ def __new__( contract_released_at = _require_aware_datetime( "owner_contract_released_at", owner_contract_released_at ) + + supersession_values = ( + benchmark_receipt_superseded_at, + successor_benchmark_receipt_reference, + successor_benchmark_receipt_version, + successor_benchmark_receipt_digest, + ) + if all(value is None for value in supersession_values): + superseded_at = None + successor_ref = None + successor_version = None + successor_digest = None + elif any(value is None for value in supersession_values): + raise ValueError( + "benchmark supersession requires time and complete successor receipt coordinates." + ) + else: + superseded_at = _require_aware_datetime( + "benchmark_receipt_superseded_at", benchmark_receipt_superseded_at + ) + successor_ref = _require_reference( + "successor_benchmark_receipt_reference", + successor_benchmark_receipt_reference, + "calibration_benchmark_receipt", + ) + successor_version = _require_positive_integer( + "successor_benchmark_receipt_version", + successor_benchmark_receipt_version, + ) + successor_digest = _require_digest( + "successor_benchmark_receipt_digest", + successor_benchmark_receipt_digest, + ) + if superseded_at < benchmark_released_at: + raise ValueError( + "benchmark_receipt_superseded_at cannot precede release." + ) + if successor_version <= benchmark_version: + raise ValueError( + "successor benchmark receipt version must advance monotonically." + ) + if successor_digest == benchmark_digest: + raise ValueError( + "successor benchmark receipt digest must identify new evidence." + ) + return tuple.__new__( cls, ( @@ -155,6 +205,10 @@ def __new__( reference_at, benchmark_released_at, contract_released_at, + superseded_at, + successor_ref, + successor_version, + successor_digest, ), ) @@ -213,6 +267,26 @@ def owner_contract_released_at(self) -> datetime: """Return when the benchmark-owner contract became released evidence.""" return self[10] + @property + def benchmark_receipt_superseded_at(self) -> datetime | None: + """Return when this receipt stopped authorizing new scientific use.""" + return self[11] + + @property + def successor_benchmark_receipt_reference(self) -> str | None: + """Return the append-only successor receipt reference when corrected.""" + return self[12] + + @property + def successor_benchmark_receipt_version(self) -> int | None: + """Return the monotonically advanced successor receipt version.""" + return self[13] + + @property + def successor_benchmark_receipt_digest(self) -> str | None: + """Return the immutable successor evidence digest when corrected.""" + return self[14] + class CalibrationBenchmarkAuthorityView(tuple): """Field-minimized benchmark evidence issued only after authorization.""" @@ -293,10 +367,11 @@ def resolve_calibration_benchmark_authority( ) -> CalibrationBenchmarkAuthorityView: """Authorize then corroborate the exact released benchmark tuple. - The owner must independently resolve both immutable release coordinates and - their release instants. ``used_at`` is the scientific receipt's use instant; - it cannot precede the benchmark receipt, owner contract, or benchmark - reference instant. No benchmark totals are returned. + The owner must independently resolve immutable release coordinates, release + instants, and append-only correction lineage. ``used_at`` is the scientific + receipt's use instant; it cannot precede release/reference authority or fall + on/after the receipt's owner-resolved supersession instant. No benchmark totals + or successor coordinates are returned to the caller. """ if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") @@ -399,6 +474,14 @@ def resolve_calibration_benchmark_authority( benchmark_reference_at=persisted.benchmark_reference_at, benchmark_receipt_released_at=persisted.benchmark_receipt_released_at, owner_contract_released_at=persisted.owner_contract_released_at, + benchmark_receipt_superseded_at=persisted.benchmark_receipt_superseded_at, + successor_benchmark_receipt_reference=( + persisted.successor_benchmark_receipt_reference + ), + successor_benchmark_receipt_version=( + persisted.successor_benchmark_receipt_version + ), + successor_benchmark_receipt_digest=persisted.successor_benchmark_receipt_digest, ) expected = ( tenant_id, @@ -434,6 +517,13 @@ def resolve_calibration_benchmark_authority( raise CalibrationBenchmarkAuthorityIntegrityError( "benchmark and owner evidence must exist no later than the scientific use instant" ) + if ( + record.benchmark_receipt_superseded_at is not None + and record.benchmark_receipt_superseded_at <= use_instant + ): + raise CalibrationBenchmarkAuthorityIntegrityError( + "superseded benchmark evidence cannot authorize scientific use at or after correction" + ) fields: tuple[tuple[str, object], ...] = ( ("benchmark_owner_contract_digest", record.benchmark_owner_contract_digest), From 6c097410407109f8a40c621245a51597eb5ca540 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 13:03:00 +0900 Subject: [PATCH 084/603] docs(workforce-validation): document benchmark correction authority --- services/workforce-validation-api/README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 386a3010d..481753d42 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -33,11 +33,14 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar - reconstruct the returned evidence into an exact tuple-backed `CalibrationAuxiliaryAuthorityRecord` and require tenant, study, projection, scientific purpose, released owner contract, authorization receipt, scientific-use receipt, and use time to match the requested coordinates; - issue only a minimized `CalibrationAuxiliaryAuthorityView`. The view is corroborating data, not a reusable authorization credential or proof that an arbitrary injected port is a production owner. -`resolve_calibration_benchmark_authority(...)` addresses #407 RED #5 at the canonical service boundary. The scientific leaf now carries benchmark receipt reference/version/digest, released benchmark-owner contract reference/version/digest, and benchmark reference time; this resolver requires an owner port to corroborate those exact coordinates rather than accepting the leaf tuple as authority. It: +`resolve_calibration_benchmark_authority(...)` addresses #407 RED #5 at the canonical service boundary. The scientific leaf carries benchmark receipt reference/version/digest, released benchmark-owner contract reference/version/digest, and benchmark reference time; this resolver requires an owner port to corroborate those exact coordinates rather than accepting the leaf tuple as authority. It: - authorizes the exact tenant/study read before any owner resolution and rejects inherited Protocol placeholders or descriptors as concrete repository capabilities; - verifies the calibration-benchmark receipt and its released owner contract through opaque references, positive versions, SHA-256 digests, and the exact benchmark reference instant; - obtains `benchmark_receipt_released_at` and `owner_contract_released_at` from owner evidence rather than from the caller, and rejects scientific use that predates either release or the benchmark reference instant; +- resolves append-only benchmark correction lineage from the owner: a superseded receipt carries a complete successor receipt reference/version/digest, the successor version must advance, and the successor digest must identify new evidence; +- treats each benchmark receipt as authoritative only on its owner-resolved half-open interval `[benchmark_receipt_released_at, benchmark_receipt_superseded_at)`. Historical use before a later correction remains reproducible, while use at or after supersession fails closed; +- keeps supersession/successor coordinates inside the authority check rather than expanding the public projection. The caller receives only the minimized benchmark evidence it requested, not correction-ledger internals; - reconstructs returned evidence into an exact tuple-backed `CalibrationBenchmarkAuthorityRecord` and fails closed on any tenant, study, receipt, owner-contract, digest, version, or reference-time mismatch; - returns only a minimized `CalibrationBenchmarkAuthorityView`; benchmark totals, protected auxiliary values, row-level weights, and foreign application-table values do not cross this boundary. @@ -52,7 +55,7 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar - reconstructs owner evidence into an exact tuple-backed `WeightVarianceAuthorityRecord` and fails closed if any requested scientific coordinate differs from the owner projection; - returns only a minimized `WeightVarianceAuthorityView`. It never copies row-level point weights, replicate vectors, frame/cluster/stratum variables, protected characteristics, or foreign application-table values. -These application contracts do **not** complete #407 and do not make an arbitrary injected Python port durable scientific authority. The current branch has no durable scientific-authority relation or released auxiliary/benchmark/variance-evidence adapter. After the canonical owner persistence path is protected truth, #248 or its verified successor must implement schema-qualified least-privilege durable ports and prove that resolved owner evidence is itself released/versioned and purpose-authorized. Mutable #57 source is not a runtime or source dependency of this service; its active compatibility and benchmark contracts were used only to align the application boundary's evidence coordinates. +These application contracts do **not** complete #407 and do not make an arbitrary injected Python port durable scientific authority. The current branch has no durable scientific-authority relation or released auxiliary/benchmark/variance-evidence adapter. After the canonical owner persistence path is protected truth, #248 or its verified successor must implement schema-qualified least-privilege durable ports and prove that resolved owner evidence is itself released/versioned, append-only where corrected, and purpose-authorized. Mutable #57 source is not a runtime or source dependency of this service; its active compatibility and benchmark contracts were used only to align the application boundary's evidence coordinates. `services/workforce-validation-api/database/migrations/0001_owner_schema.sql` starts this bounded context's own migration history. It creates the `workforce_validation` schema and deny-default `workforce_validation_role`, revokes public schema access, and intentionally creates or moves no application table yet. The role is a **NOLOGIN migration/schema owner only**; runtime principals must not be granted that owner role. PostgreSQL applies role-level configuration defaults at login and does not re-apply them on `SET ROLE`, so an `ALTER ROLE ... SET search_path` entry on this NOLOGIN role is not treated as a runtime isolation control. The later durable adapter must use a distinct least-privilege runtime role, schema-qualified `workforce_validation` relations, and explicit function-level `search_path` where `SECURITY DEFINER` code is introduced. @@ -71,7 +74,7 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ services/workforce-validation-api/tests ``` -The service package keeps an exact 100% owned statement/branch threshold. Calibration-authority coverage exercises authorization-before-owner-read, non-concrete/dynamic owner capabilities, malformed references/digests/versions/timestamps, foreign/mismatched owner evidence, caller/owner scientific-use-time mismatch, authorization-window mismatch, UUID alias mutation, structural immutability, and non-public view issuance. Calibration-benchmark coverage additionally exercises exact receipt/owner-contract coordinate mismatch, owner-resolved release-time enforcement, future-reference rejection, malformed references/digests/versions/timestamps, foreign tenant/study evidence, detached UUID views, structural immutability, and non-public output issuance. Weight/variance-authority coverage exercises every owner-coordinate mismatch, point/variance evidence aliasing, unsupported evidence modes and semantics, approximation-labelled-as-exact, pre-release use, foreign tenant/study evidence, integer correction-sequence mismatches, detached UUID views, and non-public output issuance. +The service package keeps an exact 100% owned statement/branch threshold. Calibration-authority coverage exercises authorization-before-owner-read, non-concrete/dynamic owner capabilities, malformed references/digests/versions/timestamps, foreign/mismatched owner evidence, caller/owner scientific-use-time mismatch, authorization-window mismatch, UUID alias mutation, structural immutability, and non-public view issuance. Calibration-benchmark coverage additionally exercises exact receipt/owner-contract coordinate mismatch, owner-resolved release-time enforcement, future-reference rejection, append-only supersession completeness and monotonicity, historical pre-supersession use, rejection at/after supersession, malformed references/digests/versions/timestamps, foreign tenant/study evidence, detached UUID views, structural immutability, and non-public output issuance. Weight/variance-authority coverage exercises every owner-coordinate mismatch, point/variance evidence aliasing, unsupported evidence modes and semantics, approximation-labelled-as-exact, pre-release use, foreign tenant/study evidence, integer correction-sequence mismatches, detached UUID views, and non-public output issuance. The same Foundation job also runs `tests/test_workforce_validation_owner_schema_postgres.sh` in its own pinned PostgreSQL 16.14 container. That contract executes the service-local owner migration and checks the exact deny-default role flags, schema owner, absence of ineffective login-only `rolconfig`, actual `SET ROLE` search-path behavior, absence of inherited PUBLIC `USAGE`/`CREATE`, and absence of application relations in the bootstrap schema. The test intentionally demonstrates that `SET ROLE` retains the caller's existing `search_path`; runtime isolation therefore cannot be inferred from owner-role metadata. From d1e98cc6971b0e540430d6424cdc58b11fe43b5c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 13:04:15 +0900 Subject: [PATCH 085/603] test(workforce-validation): require released benchmark successor evidence --- ...test_calibration_benchmark_supersession.py | 48 ++++++++++++++++--- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py b/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py index bac51e1b7..a3f5f64c1 100644 --- a/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py +++ b/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py @@ -91,6 +91,7 @@ def _record( successor_reference: str | None, successor_version: int | None, successor_digest: str | None, + successor_released_at: datetime | None, ) -> CalibrationBenchmarkAuthorityRecord: return CalibrationBenchmarkAuthorityRecord( tenant_record_id=TENANT, @@ -108,6 +109,7 @@ def _record( successor_benchmark_receipt_reference=successor_reference, successor_benchmark_receipt_version=successor_version, successor_benchmark_receipt_digest=successor_digest, + successor_benchmark_receipt_released_at=successor_released_at, ) @@ -131,12 +133,14 @@ def _resolve(record: CalibrationBenchmarkAuthorityRecord, *, used_at: datetime = def test_historical_use_before_supersession_remains_verifiable_without_leaking_lineage() -> None: + superseded_at = USED_AT + timedelta(days=1) view = _resolve( _record( - superseded_at=USED_AT + timedelta(days=1), + superseded_at=superseded_at, successor_reference=SUCCESSOR_REFERENCE, successor_version=5, successor_digest=SUCCESSOR_DIGEST, + successor_released_at=USED_AT + timedelta(hours=12), ) ) @@ -144,6 +148,7 @@ def test_historical_use_before_supersession_remains_verifiable_without_leaking_l assert fields["benchmark_receipt_reference"] == BENCHMARK_REFERENCE assert "benchmark_receipt_superseded_at" not in fields assert "successor_benchmark_receipt_reference" not in fields + assert "successor_benchmark_receipt_released_at" not in fields def test_benchmark_superseded_by_scientific_use_is_not_authoritative() -> None: @@ -152,6 +157,7 @@ def test_benchmark_superseded_by_scientific_use_is_not_authoritative() -> None: successor_reference=SUCCESSOR_REFERENCE, successor_version=5, successor_digest=SUCCESSOR_DIGEST, + successor_released_at=USED_AT - timedelta(hours=1), ) with pytest.raises(CalibrationBenchmarkAuthorityIntegrityError): @@ -159,13 +165,39 @@ def test_benchmark_superseded_by_scientific_use_is_not_authoritative() -> None: @pytest.mark.parametrize( - ("superseded_at", "successor_reference", "successor_version", "successor_digest"), + ( + "superseded_at", + "successor_reference", + "successor_version", + "successor_digest", + "successor_released_at", + ), [ - (USED_AT, None, 5, SUCCESSOR_DIGEST), - (None, SUCCESSOR_REFERENCE, 5, SUCCESSOR_DIGEST), - (USED_AT, SUCCESSOR_REFERENCE, 4, SUCCESSOR_DIGEST), - (USED_AT, SUCCESSOR_REFERENCE, 5, BENCHMARK_DIGEST), - (BENCHMARK_RELEASED_AT - timedelta(seconds=1), SUCCESSOR_REFERENCE, 5, SUCCESSOR_DIGEST), + (USED_AT, None, 5, SUCCESSOR_DIGEST, USED_AT), + (None, SUCCESSOR_REFERENCE, 5, SUCCESSOR_DIGEST, USED_AT), + (USED_AT, SUCCESSOR_REFERENCE, 4, SUCCESSOR_DIGEST, USED_AT), + (USED_AT, SUCCESSOR_REFERENCE, 5, BENCHMARK_DIGEST, USED_AT), + ( + BENCHMARK_RELEASED_AT - timedelta(seconds=1), + SUCCESSOR_REFERENCE, + 5, + SUCCESSOR_DIGEST, + BENCHMARK_RELEASED_AT - timedelta(seconds=1), + ), + ( + USED_AT, + SUCCESSOR_REFERENCE, + 5, + SUCCESSOR_DIGEST, + USED_AT + timedelta(seconds=1), + ), + ( + USED_AT, + SUCCESSOR_REFERENCE, + 5, + SUCCESSOR_DIGEST, + BENCHMARK_RELEASED_AT, + ), ], ) def test_owner_record_rejects_incomplete_or_non_append_only_supersession_lineage( @@ -173,6 +205,7 @@ def test_owner_record_rejects_incomplete_or_non_append_only_supersession_lineage successor_reference: str | None, successor_version: int | None, successor_digest: str | None, + successor_released_at: datetime | None, ) -> None: with pytest.raises(ValueError): _record( @@ -180,4 +213,5 @@ def test_owner_record_rejects_incomplete_or_non_append_only_supersession_lineage successor_reference=successor_reference, successor_version=successor_version, successor_digest=successor_digest, + successor_released_at=successor_released_at, ) From ff534d8f58eed5a88db79a0dcb9bb44216d5e85e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 13:05:00 +0900 Subject: [PATCH 086/603] fix(workforce-validation): require released benchmark successor evidence --- .../benchmark_authority.py | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py index 0f4da8f7a..83943aa0d 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py @@ -110,6 +110,7 @@ def __new__( successor_benchmark_receipt_reference: str | None = None, successor_benchmark_receipt_version: int | None = None, successor_benchmark_receipt_digest: str | None = None, + successor_benchmark_receipt_released_at: datetime | None = None, ) -> CalibrationBenchmarkAuthorityRecord: """Validate and detach all authority-bearing benchmark evidence.""" tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) @@ -151,15 +152,17 @@ def __new__( successor_benchmark_receipt_reference, successor_benchmark_receipt_version, successor_benchmark_receipt_digest, + successor_benchmark_receipt_released_at, ) if all(value is None for value in supersession_values): superseded_at = None successor_ref = None successor_version = None successor_digest = None + successor_released_at = None elif any(value is None for value in supersession_values): raise ValueError( - "benchmark supersession requires time and complete successor receipt coordinates." + "benchmark supersession requires time and complete released successor coordinates." ) else: superseded_at = _require_aware_datetime( @@ -178,6 +181,10 @@ def __new__( "successor_benchmark_receipt_digest", successor_benchmark_receipt_digest, ) + successor_released_at = _require_aware_datetime( + "successor_benchmark_receipt_released_at", + successor_benchmark_receipt_released_at, + ) if superseded_at < benchmark_released_at: raise ValueError( "benchmark_receipt_superseded_at cannot precede release." @@ -190,6 +197,14 @@ def __new__( raise ValueError( "successor benchmark receipt digest must identify new evidence." ) + if successor_released_at <= benchmark_released_at: + raise ValueError( + "successor benchmark receipt must be released after its predecessor." + ) + if successor_released_at > superseded_at: + raise ValueError( + "successor benchmark receipt must be released no later than supersession." + ) return tuple.__new__( cls, @@ -209,6 +224,7 @@ def __new__( successor_ref, successor_version, successor_digest, + successor_released_at, ), ) @@ -287,6 +303,11 @@ def successor_benchmark_receipt_digest(self) -> str | None: """Return the immutable successor evidence digest when corrected.""" return self[14] + @property + def successor_benchmark_receipt_released_at(self) -> datetime | None: + """Return when the owner released the append-only successor evidence.""" + return self[15] + class CalibrationBenchmarkAuthorityView(tuple): """Field-minimized benchmark evidence issued only after authorization.""" @@ -482,6 +503,9 @@ def resolve_calibration_benchmark_authority( persisted.successor_benchmark_receipt_version ), successor_benchmark_receipt_digest=persisted.successor_benchmark_receipt_digest, + successor_benchmark_receipt_released_at=( + persisted.successor_benchmark_receipt_released_at + ), ) expected = ( tenant_id, From dc89a1d3c69a79f1d6fd5bf04831f49905da4330 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 13:05:33 +0900 Subject: [PATCH 087/603] docs(workforce-validation): bind benchmark successor release timing --- services/workforce-validation-api/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 481753d42..f85e4bd2a 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -38,7 +38,8 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar - authorizes the exact tenant/study read before any owner resolution and rejects inherited Protocol placeholders or descriptors as concrete repository capabilities; - verifies the calibration-benchmark receipt and its released owner contract through opaque references, positive versions, SHA-256 digests, and the exact benchmark reference instant; - obtains `benchmark_receipt_released_at` and `owner_contract_released_at` from owner evidence rather than from the caller, and rejects scientific use that predates either release or the benchmark reference instant; -- resolves append-only benchmark correction lineage from the owner: a superseded receipt carries a complete successor receipt reference/version/digest, the successor version must advance, and the successor digest must identify new evidence; +- resolves append-only benchmark correction lineage from the owner: a superseded receipt carries a complete successor receipt reference/version/digest plus its owner-resolved release instant, the successor version must advance, and the successor digest must identify new evidence; +- requires the successor receipt to be released after its predecessor and no later than the predecessor's supersession instant, so correction lineage cannot point to unavailable future evidence or reverse version chronology; - treats each benchmark receipt as authoritative only on its owner-resolved half-open interval `[benchmark_receipt_released_at, benchmark_receipt_superseded_at)`. Historical use before a later correction remains reproducible, while use at or after supersession fails closed; - keeps supersession/successor coordinates inside the authority check rather than expanding the public projection. The caller receives only the minimized benchmark evidence it requested, not correction-ledger internals; - reconstructs returned evidence into an exact tuple-backed `CalibrationBenchmarkAuthorityRecord` and fails closed on any tenant, study, receipt, owner-contract, digest, version, or reference-time mismatch; @@ -74,7 +75,7 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ services/workforce-validation-api/tests ``` -The service package keeps an exact 100% owned statement/branch threshold. Calibration-authority coverage exercises authorization-before-owner-read, non-concrete/dynamic owner capabilities, malformed references/digests/versions/timestamps, foreign/mismatched owner evidence, caller/owner scientific-use-time mismatch, authorization-window mismatch, UUID alias mutation, structural immutability, and non-public view issuance. Calibration-benchmark coverage additionally exercises exact receipt/owner-contract coordinate mismatch, owner-resolved release-time enforcement, future-reference rejection, append-only supersession completeness and monotonicity, historical pre-supersession use, rejection at/after supersession, malformed references/digests/versions/timestamps, foreign tenant/study evidence, detached UUID views, structural immutability, and non-public output issuance. Weight/variance-authority coverage exercises every owner-coordinate mismatch, point/variance evidence aliasing, unsupported evidence modes and semantics, approximation-labelled-as-exact, pre-release use, foreign tenant/study evidence, integer correction-sequence mismatches, detached UUID views, and non-public output issuance. +The service package keeps an exact 100% owned statement/branch threshold. Calibration-authority coverage exercises authorization-before-owner-read, non-concrete/dynamic owner capabilities, malformed references/digests/versions/timestamps, foreign/mismatched owner evidence, caller/owner scientific-use-time mismatch, authorization-window mismatch, UUID alias mutation, structural immutability, and non-public view issuance. Calibration-benchmark coverage additionally exercises exact receipt/owner-contract coordinate mismatch, owner-resolved release-time enforcement, future-reference rejection, append-only supersession completeness and monotonicity, successor release ordering, historical pre-supersession use, rejection at/after supersession, malformed references/digests/versions/timestamps, foreign tenant/study evidence, detached UUID views, structural immutability, and non-public output issuance. Weight/variance-authority coverage exercises every owner-coordinate mismatch, point/variance evidence aliasing, unsupported evidence modes and semantics, approximation-labelled-as-exact, pre-release use, foreign tenant/study evidence, integer correction-sequence mismatches, detached UUID views, and non-public output issuance. The same Foundation job also runs `tests/test_workforce_validation_owner_schema_postgres.sh` in its own pinned PostgreSQL 16.14 container. That contract executes the service-local owner migration and checks the exact deny-default role flags, schema owner, absence of ineffective login-only `rolconfig`, actual `SET ROLE` search-path behavior, absence of inherited PUBLIC `USAGE`/`CREATE`, and absence of application relations in the bootstrap schema. The test intentionally demonstrates that `SET ROLE` retains the caller's existing `search_path`; runtime isolation therefore cannot be inferred from owner-role metadata. From 2081d60062265b9b6540b70d0a31d9f111485e9f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 13:26:45 +0900 Subject: [PATCH 088/603] test(workforce-validation): reject impossible benchmark contract chronology --- .../test_calibration_benchmark_supersession.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py b/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py index a3f5f64c1..179a80880 100644 --- a/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py +++ b/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py @@ -151,6 +151,23 @@ def test_historical_use_before_supersession_remains_verifiable_without_leaking_l assert "successor_benchmark_receipt_released_at" not in fields +def test_benchmark_receipt_cannot_predate_its_released_owner_contract() -> None: + with pytest.raises(ValueError, match="owner contract must be released no later than benchmark receipt"): + CalibrationBenchmarkAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + benchmark_receipt_reference=BENCHMARK_REFERENCE, + benchmark_receipt_version=4, + benchmark_receipt_digest=BENCHMARK_DIGEST, + benchmark_owner_contract_reference=OWNER_CONTRACT_REFERENCE, + benchmark_owner_contract_version=3, + benchmark_owner_contract_digest=OWNER_CONTRACT_DIGEST, + benchmark_reference_at=BENCHMARK_REFERENCE_AT, + benchmark_receipt_released_at=BENCHMARK_RELEASED_AT, + owner_contract_released_at=BENCHMARK_RELEASED_AT + timedelta(seconds=1), + ) + + def test_benchmark_superseded_by_scientific_use_is_not_authoritative() -> None: record = _record( superseded_at=USED_AT, From 36ba91d0bb8a334d815cccc4e153c95badf344ed Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 13:28:20 +0900 Subject: [PATCH 089/603] fix(workforce-validation): bind benchmark receipt to prior released owner contract --- .../orgmetra_workforce_validation_api/benchmark_authority.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py index 83943aa0d..f994c7072 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py @@ -146,6 +146,10 @@ def __new__( contract_released_at = _require_aware_datetime( "owner_contract_released_at", owner_contract_released_at ) + if contract_released_at > benchmark_released_at: + raise ValueError( + "owner contract must be released no later than benchmark receipt." + ) supersession_values = ( benchmark_receipt_superseded_at, From 698a36c50063b2d1cbba3d5735cc67e34de3971a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 13:28:51 +0900 Subject: [PATCH 090/603] docs(workforce-validation): record benchmark contract release chronology --- services/workforce-validation-api/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index f85e4bd2a..c1c79a7f0 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -38,6 +38,7 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar - authorizes the exact tenant/study read before any owner resolution and rejects inherited Protocol placeholders or descriptors as concrete repository capabilities; - verifies the calibration-benchmark receipt and its released owner contract through opaque references, positive versions, SHA-256 digests, and the exact benchmark reference instant; - obtains `benchmark_receipt_released_at` and `owner_contract_released_at` from owner evidence rather than from the caller, and rejects scientific use that predates either release or the benchmark reference instant; +- requires the referenced owner contract to have been released no later than the benchmark receipt itself, so a receipt cannot retroactively claim authority from a contract that did not yet exist when the receipt became released evidence; - resolves append-only benchmark correction lineage from the owner: a superseded receipt carries a complete successor receipt reference/version/digest plus its owner-resolved release instant, the successor version must advance, and the successor digest must identify new evidence; - requires the successor receipt to be released after its predecessor and no later than the predecessor's supersession instant, so correction lineage cannot point to unavailable future evidence or reverse version chronology; - treats each benchmark receipt as authoritative only on its owner-resolved half-open interval `[benchmark_receipt_released_at, benchmark_receipt_superseded_at)`. Historical use before a later correction remains reproducible, while use at or after supersession fails closed; @@ -75,7 +76,7 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ services/workforce-validation-api/tests ``` -The service package keeps an exact 100% owned statement/branch threshold. Calibration-authority coverage exercises authorization-before-owner-read, non-concrete/dynamic owner capabilities, malformed references/digests/versions/timestamps, foreign/mismatched owner evidence, caller/owner scientific-use-time mismatch, authorization-window mismatch, UUID alias mutation, structural immutability, and non-public view issuance. Calibration-benchmark coverage additionally exercises exact receipt/owner-contract coordinate mismatch, owner-resolved release-time enforcement, future-reference rejection, append-only supersession completeness and monotonicity, successor release ordering, historical pre-supersession use, rejection at/after supersession, malformed references/digests/versions/timestamps, foreign tenant/study evidence, detached UUID views, structural immutability, and non-public output issuance. Weight/variance-authority coverage exercises every owner-coordinate mismatch, point/variance evidence aliasing, unsupported evidence modes and semantics, approximation-labelled-as-exact, pre-release use, foreign tenant/study evidence, integer correction-sequence mismatches, detached UUID views, and non-public output issuance. +The service package keeps an exact 100% owned statement/branch threshold. Calibration-authority coverage exercises authorization-before-owner-read, non-concrete/dynamic owner capabilities, malformed references/digests/versions/timestamps, foreign/mismatched owner evidence, caller/owner scientific-use-time mismatch, authorization-window mismatch, UUID alias mutation, structural immutability, and non-public view issuance. Calibration-benchmark coverage additionally exercises exact receipt/owner-contract coordinate mismatch, owner-resolved release-time enforcement, owner-contract-before-receipt chronology, future-reference rejection, append-only supersession completeness and monotonicity, successor release ordering, historical pre-supersession use, rejection at/after supersession, malformed references/digests/versions/timestamps, foreign tenant/study evidence, detached UUID views, structural immutability, and non-public output issuance. Weight/variance-authority coverage exercises every owner-coordinate mismatch, point/variance evidence aliasing, unsupported evidence modes and semantics, approximation-labelled-as-exact, pre-release use, foreign tenant/study evidence, integer correction-sequence mismatches, detached UUID views, and non-public output issuance. The same Foundation job also runs `tests/test_workforce_validation_owner_schema_postgres.sh` in its own pinned PostgreSQL 16.14 container. That contract executes the service-local owner migration and checks the exact deny-default role flags, schema owner, absence of ineffective login-only `rolconfig`, actual `SET ROLE` search-path behavior, absence of inherited PUBLIC `USAGE`/`CREATE`, and absence of application relations in the bootstrap schema. The test intentionally demonstrates that `SET ROLE` retains the caller's existing `search_path`; runtime isolation therefore cannot be inferred from owner-role metadata. From 7dc4a48aa9625096ff594973afda9e1c791c63ce Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 14:07:51 +0900 Subject: [PATCH 091/603] test(workforce-validation): RED exact auxiliary authority coordinates --- ..._auxiliary_authority_coordinate_binding.py | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_auxiliary_authority_coordinate_binding.py diff --git a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority_coordinate_binding.py b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority_coordinate_binding.py new file mode 100644 index 000000000..fce90547f --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority_coordinate_binding.py @@ -0,0 +1,154 @@ +"""RED contract for exact calibration auxiliary authority coordinates.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.scientific_authority import ( + CalibrationAuxiliaryAuthorityIntegrityError, + CalibrationAuxiliaryAuthorityRecord, + resolve_calibration_auxiliary_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000c1") +AUTHORITY_REFERENCE = "scientific_auxiliary_authority:11111111-1111-4111-8111-111111111111" +PROJECTION_REFERENCE = "calibration_auxiliary_projection:22222222-2222-4222-8222-222222222222" +PURPOSE_REFERENCE = "scientific_data_use_purpose:33333333-3333-4333-8333-333333333333" +OWNER_REFERENCE = "released_owner_contract:44444444-4444-4444-8444-444444444444" +AUTHORIZATION_REFERENCE = "scientific_data_authorization:55555555-5555-4555-8555-555555555555" +USE_REFERENCE = "scientific_use_receipt:66666666-6666-4666-8666-666666666666" +PROJECTION_DIGEST = "1" * 64 +PURPOSE_DIGEST = "2" * 64 +OWNER_DIGEST = "3" * 64 +AUTHORIZATION_DIGEST = "4" * 64 +USE_DIGEST = "5" * 64 +USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) + +READ_FIELDS = frozenset( + { + "authority_reference", + "auxiliary_projection_reference", + "auxiliary_projection_digest", + "scientific_purpose_reference", + "scientific_purpose_digest", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "authorization_receipt_reference", + "authorization_receipt_digest", + "scientific_use_receipt_reference", + "scientific_use_receipt_digest", + "scientific_use_at", + "authorized_from", + "authorized_to", + } +) + + +class _ReadPort: + def __init__(self, result: CalibrationAuxiliaryAuthorityRecord) -> None: + self.result = result + + def read_calibration_auxiliary_authority(self, **_: object) -> CalibrationAuxiliaryAuthorityRecord: + return self.result + + +def _record(**overrides: object) -> CalibrationAuxiliaryAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "authority_reference": AUTHORITY_REFERENCE, + "auxiliary_projection_reference": PROJECTION_REFERENCE, + "auxiliary_projection_digest": PROJECTION_DIGEST, + "scientific_purpose_reference": PURPOSE_REFERENCE, + "scientific_purpose_digest": PURPOSE_DIGEST, + "owner_contract_reference": OWNER_REFERENCE, + "owner_contract_version": 7, + "owner_contract_digest": OWNER_DIGEST, + "authorization_receipt_reference": AUTHORIZATION_REFERENCE, + "authorization_receipt_digest": AUTHORIZATION_DIGEST, + "scientific_use_receipt_reference": USE_REFERENCE, + "scientific_use_receipt_digest": USE_DIGEST, + "scientific_use_at": USED_AT, + "authorized_from": datetime(2026, 9, 1, tzinfo=timezone.utc), + "authorized_to": datetime(2026, 10, 1, tzinfo=timezone.utc), + } + values.update(overrides) + return CalibrationAuxiliaryAuthorityRecord(**values) + + +def _resolve(*, record: CalibrationAuxiliaryAuthorityRecord, **overrides: object) -> object: + values: dict[str, object] = { + "principal": ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "authority_reference": AUTHORITY_REFERENCE, + "auxiliary_projection_reference": PROJECTION_REFERENCE, + "auxiliary_projection_digest": PROJECTION_DIGEST, + "scientific_purpose_reference": PURPOSE_REFERENCE, + "scientific_purpose_digest": PURPOSE_DIGEST, + "owner_contract_reference": OWNER_REFERENCE, + "owner_contract_version": 7, + "owner_contract_digest": OWNER_DIGEST, + "authorization_receipt_reference": AUTHORIZATION_REFERENCE, + "authorization_receipt_digest": AUTHORIZATION_DIGEST, + "scientific_use_receipt_reference": USE_REFERENCE, + "scientific_use_receipt_digest": USE_DIGEST, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="calibration-authority-read-v1", + resource_kind="calibration_auxiliary_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ), + "read_port": _ReadPort(record), + } + values.update(overrides) + return resolve_calibration_auxiliary_authority(**values) + + +def test_exact_leaf_coordinates_are_accepted() -> None: + view = _resolve(record=_record()) + assert dict(view.fields)["authority_reference"] == AUTHORITY_REFERENCE + assert dict(view.fields)["owner_contract_digest"] == OWNER_DIGEST + assert dict(view.fields)["authorization_receipt_reference"] == AUTHORIZATION_REFERENCE + assert dict(view.fields)["scientific_use_receipt_reference"] == USE_REFERENCE + + +@pytest.mark.parametrize( + ("record_overrides", "request_overrides"), + [ + ( + {"authority_reference": "scientific_auxiliary_authority:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa"}, + {}, + ), + ({"owner_contract_digest": "a" * 64}, {}), + ( + {"authorization_receipt_reference": "scientific_data_authorization:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb"}, + {}, + ), + ( + {"scientific_use_receipt_reference": "scientific_use_receipt:cccccccc-cccc-4ccc-8ccc-cccccccccccc"}, + {}, + ), + ], +) +def test_owner_evidence_cannot_substitute_unrequested_leaf_coordinates( + record_overrides: dict[str, object], request_overrides: dict[str, object] +) -> None: + with pytest.raises(CalibrationAuxiliaryAuthorityIntegrityError): + _resolve(record=_record(**record_overrides), **request_overrides) From 7eb4856a4a5b7545230724a0a6c6addfbf1f46dc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 14:08:40 +0900 Subject: [PATCH 092/603] fix(workforce-validation): corroborate exact auxiliary leaf coordinates --- .../scientific_authority.py | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py index f84175cdd..bde01734d 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py @@ -331,13 +331,17 @@ def read_calibration_auxiliary_authority( *, tenant_record_id: UUID, validity_study_id: UUID, + authority_reference: str, auxiliary_projection_reference: str, auxiliary_projection_digest: str, scientific_purpose_reference: str, scientific_purpose_digest: str, owner_contract_reference: str, owner_contract_version: int, + owner_contract_digest: str, + authorization_receipt_reference: str, authorization_receipt_digest: str, + scientific_use_receipt_reference: str, scientific_use_receipt_digest: str, ) -> CalibrationAuxiliaryAuthorityRecord | None: """Return matching released authority evidence or ``None`` through an owner ACL.""" @@ -354,24 +358,29 @@ def resolve_calibration_auxiliary_authority( principal: ValidationPrincipal, tenant_record_id: UUID, validity_study_id: UUID, + authority_reference: str, auxiliary_projection_reference: str, auxiliary_projection_digest: str, scientific_purpose_reference: str, scientific_purpose_digest: str, owner_contract_reference: str, owner_contract_version: int, + owner_contract_digest: str, + authorization_receipt_reference: str, authorization_receipt_digest: str, + scientific_use_receipt_reference: str, scientific_use_receipt_digest: str, used_at: datetime, purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: CalibrationAuxiliaryAuthorityReadPort, ) -> CalibrationAuxiliaryAuthorityView: - """Authorize and corroborate one calibration auxiliary-use authority tuple. + """Authorize and corroborate one exact calibration auxiliary-use authority tuple. The exact owner capability is captured inertly before authorization and the same function is invoked afterward. The request carries no protected source - values. Owner evidence must reproduce every caller-supplied coordinate and + values. Owner evidence must reproduce every caller-supplied leaf coordinate, + including receipt references and the released owner-contract digest, and independently bind the scientific-use receipt to the same use instant before any corroborating fields are returned. """ @@ -400,6 +409,9 @@ def resolve_calibration_auxiliary_authority( study_identity = _store_operational_uuid("validity_study_id", validity_study_id) tenant_id = _restore_operational_uuid("tenant_record_id", tenant_identity) study_id = _restore_operational_uuid("validity_study_id", study_identity) + authority_ref = _require_reference( + "authority_reference", authority_reference, "scientific_auxiliary_authority" + ) projection_ref = _require_reference( "auxiliary_projection_reference", auxiliary_projection_reference, @@ -418,9 +430,20 @@ def resolve_calibration_auxiliary_authority( "owner_contract_reference", owner_contract_reference, "released_owner_contract" ) owner_version = _require_positive_integer("owner_contract_version", owner_contract_version) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + authorization_ref = _require_reference( + "authorization_receipt_reference", + authorization_receipt_reference, + "scientific_data_authorization", + ) authorization_digest = _require_digest( "authorization_receipt_digest", authorization_receipt_digest ) + scientific_use_ref = _require_reference( + "scientific_use_receipt_reference", + scientific_use_receipt_reference, + "scientific_use_receipt", + ) scientific_use_digest = _require_digest( "scientific_use_receipt_digest", scientific_use_receipt_digest ) @@ -448,13 +471,17 @@ def resolve_calibration_auxiliary_authority( read_port, tenant_record_id=_restore_operational_uuid("tenant_record_id", tenant_identity), validity_study_id=_restore_operational_uuid("validity_study_id", study_identity), + authority_reference=authority_ref, auxiliary_projection_reference=projection_ref, auxiliary_projection_digest=projection_digest, scientific_purpose_reference=purpose_ref, scientific_purpose_digest=purpose_digest, owner_contract_reference=owner_ref, owner_contract_version=owner_version, + owner_contract_digest=owner_digest, + authorization_receipt_reference=authorization_ref, authorization_receipt_digest=authorization_digest, + scientific_use_receipt_reference=scientific_use_ref, scientific_use_receipt_digest=scientific_use_digest, ) if persisted is None: @@ -488,13 +515,17 @@ def resolve_calibration_auxiliary_authority( != tenant_identity or _store_operational_uuid("record validity_study_id", record.validity_study_id) != study_identity + or record.authority_reference != authority_ref or record.auxiliary_projection_reference != projection_ref or record.auxiliary_projection_digest != projection_digest or record.scientific_purpose_reference != purpose_ref or record.scientific_purpose_digest != purpose_digest or record.owner_contract_reference != owner_ref or record.owner_contract_version != owner_version + or record.owner_contract_digest != owner_digest + or record.authorization_receipt_reference != authorization_ref or record.authorization_receipt_digest != authorization_digest + or record.scientific_use_receipt_reference != scientific_use_ref or record.scientific_use_receipt_digest != scientific_use_digest or record.scientific_use_at != use_instant ): From 267cf61f8a300295dff23c2c6a7263247aaceb2e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 14:09:17 +0900 Subject: [PATCH 093/603] test(workforce-validation): bind all auxiliary authority coordinates --- .../test_calibration_auxiliary_authority.py | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py index f17b71f00..ea6202ccd 100644 --- a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py +++ b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py @@ -81,13 +81,17 @@ def read_calibration_auxiliary_authority( *, tenant_record_id: UUID, validity_study_id: UUID, + authority_reference: str, auxiliary_projection_reference: str, auxiliary_projection_digest: str, scientific_purpose_reference: str, scientific_purpose_digest: str, owner_contract_reference: str, owner_contract_version: int, + owner_contract_digest: str, + authorization_receipt_reference: str, authorization_receipt_digest: str, + scientific_use_receipt_reference: str, scientific_use_receipt_digest: str, ) -> object: """Capture the owner lookup and return the configured result.""" @@ -95,13 +99,17 @@ def read_calibration_auxiliary_authority( ( tenant_record_id, validity_study_id, + authority_reference, auxiliary_projection_reference, auxiliary_projection_digest, scientific_purpose_reference, scientific_purpose_digest, owner_contract_reference, owner_contract_version, + owner_contract_digest, + authorization_receipt_reference, authorization_receipt_digest, + scientific_use_receipt_reference, scientific_use_receipt_digest, ) ) @@ -173,13 +181,17 @@ def _resolve(*, read_port: object, **overrides: object) -> CalibrationAuxiliaryA "principal": _principal(), "tenant_record_id": TENANT, "validity_study_id": STUDY, + "authority_reference": AUTHORITY_REFERENCE, "auxiliary_projection_reference": PROJECTION_REFERENCE, "auxiliary_projection_digest": PROJECTION_DIGEST, "scientific_purpose_reference": PURPOSE_REFERENCE, "scientific_purpose_digest": PURPOSE_DIGEST, "owner_contract_reference": OWNER_CONTRACT_REFERENCE, "owner_contract_version": 7, + "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "authorization_receipt_reference": AUTHORIZATION_REFERENCE, "authorization_receipt_digest": AUTHORIZATION_DIGEST, + "scientific_use_receipt_reference": SCIENTIFIC_USE_REFERENCE, "scientific_use_receipt_digest": SCIENTIFIC_USE_DIGEST, "used_at": USED_AT, "purpose_code": "selection_validity_analysis", @@ -200,13 +212,17 @@ def test_resolution_authorizes_then_returns_minimized_corroborated_evidence() -> ( TENANT, STUDY, + AUTHORITY_REFERENCE, PROJECTION_REFERENCE, PROJECTION_DIGEST, PURPOSE_REFERENCE, PURPOSE_DIGEST, OWNER_CONTRACT_REFERENCE, 7, + OWNER_CONTRACT_DIGEST, + AUTHORIZATION_REFERENCE, AUTHORIZATION_DIGEST, + SCIENTIFIC_USE_REFERENCE, SCIENTIFIC_USE_DIGEST, ) ] @@ -253,6 +269,14 @@ def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: [ ({"tenant_record_id": OTHER_TENANT}, {}), ({"validity_study_id": OTHER_STUDY}, {}), + ( + { + "authority_reference": ( + "scientific_auxiliary_authority:dddddddd-dddd-4ddd-8ddd-dddddddddddd" + ) + }, + {}, + ), ( { "auxiliary_projection_reference": ( @@ -280,7 +304,24 @@ def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: {}, ), ({"owner_contract_version": 8}, {}), + ({"owner_contract_digest": "c" * 64}, {}), + ( + { + "authorization_receipt_reference": ( + "scientific_data_authorization:eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee" + ) + }, + {}, + ), ({"authorization_receipt_digest": "c" * 64}, {}), + ( + { + "scientific_use_receipt_reference": ( + "scientific_use_receipt:ffffffff-ffff-4fff-8fff-ffffffffffff" + ) + }, + {}, + ), ({"scientific_use_receipt_digest": "d" * 64}, {}), ({}, {"used_at": USED_AT + timedelta(seconds=1)}), ], @@ -326,13 +367,17 @@ def test_open_ended_authority_interval_accepts_later_owner_resolved_use() -> Non ("read_port", _DescriptorReadPort(), TypeError), ("tenant_record_id", "not-a-uuid", ValueError), ("validity_study_id", UUID(int=0), ValueError), + ("authority_reference", "wrong:authority", ValueError), ("auxiliary_projection_reference", "wrong:projection", ValueError), ("auxiliary_projection_digest", "ABC", ValueError), ("scientific_purpose_reference", "wrong:purpose", ValueError), ("scientific_purpose_digest", "2" * 63, ValueError), ("owner_contract_reference", "wrong:contract", ValueError), ("owner_contract_version", True, ValueError), + ("owner_contract_digest", "3" * 63, ValueError), + ("authorization_receipt_reference", "wrong:authorization", ValueError), ("authorization_receipt_digest", "4" * 65, ValueError), + ("scientific_use_receipt_reference", "wrong:use", ValueError), ("scientific_use_receipt_digest", "5" * 65, ValueError), ("used_at", datetime(2026, 9, 17), ValueError), ("purpose_code", "Selection Validity Analysis", ValueError), From e29183ca84c870c20fde4e8c0f412fd3bb4030fa Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 14:10:00 +0900 Subject: [PATCH 094/603] test(workforce-validation): fold RED into canonical authority suite --- ..._auxiliary_authority_coordinate_binding.py | 154 ------------------ 1 file changed, 154 deletions(-) delete mode 100644 services/workforce-validation-api/tests/test_calibration_auxiliary_authority_coordinate_binding.py diff --git a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority_coordinate_binding.py b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority_coordinate_binding.py deleted file mode 100644 index fce90547f..000000000 --- a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority_coordinate_binding.py +++ /dev/null @@ -1,154 +0,0 @@ -"""RED contract for exact calibration auxiliary authority coordinates.""" - -from __future__ import annotations - -from datetime import datetime, timezone -from uuid import UUID - -import pytest - -from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy -from orgmetra_workforce_validation_api import ValidationPrincipal -from orgmetra_workforce_validation_api.scientific_authority import ( - CalibrationAuxiliaryAuthorityIntegrityError, - CalibrationAuxiliaryAuthorityRecord, - resolve_calibration_auxiliary_authority, -) - -TENANT = UUID("10000000-0000-7000-8000-000000000001") -STUDY = UUID("00000000-0000-7000-8000-0000000000c1") -AUTHORITY_REFERENCE = "scientific_auxiliary_authority:11111111-1111-4111-8111-111111111111" -PROJECTION_REFERENCE = "calibration_auxiliary_projection:22222222-2222-4222-8222-222222222222" -PURPOSE_REFERENCE = "scientific_data_use_purpose:33333333-3333-4333-8333-333333333333" -OWNER_REFERENCE = "released_owner_contract:44444444-4444-4444-8444-444444444444" -AUTHORIZATION_REFERENCE = "scientific_data_authorization:55555555-5555-4555-8555-555555555555" -USE_REFERENCE = "scientific_use_receipt:66666666-6666-4666-8666-666666666666" -PROJECTION_DIGEST = "1" * 64 -PURPOSE_DIGEST = "2" * 64 -OWNER_DIGEST = "3" * 64 -AUTHORIZATION_DIGEST = "4" * 64 -USE_DIGEST = "5" * 64 -USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) - -READ_FIELDS = frozenset( - { - "authority_reference", - "auxiliary_projection_reference", - "auxiliary_projection_digest", - "scientific_purpose_reference", - "scientific_purpose_digest", - "owner_contract_reference", - "owner_contract_version", - "owner_contract_digest", - "authorization_receipt_reference", - "authorization_receipt_digest", - "scientific_use_receipt_reference", - "scientific_use_receipt_digest", - "scientific_use_at", - "authorized_from", - "authorized_to", - } -) - - -class _ReadPort: - def __init__(self, result: CalibrationAuxiliaryAuthorityRecord) -> None: - self.result = result - - def read_calibration_auxiliary_authority(self, **_: object) -> CalibrationAuxiliaryAuthorityRecord: - return self.result - - -def _record(**overrides: object) -> CalibrationAuxiliaryAuthorityRecord: - values: dict[str, object] = { - "tenant_record_id": TENANT, - "validity_study_id": STUDY, - "authority_reference": AUTHORITY_REFERENCE, - "auxiliary_projection_reference": PROJECTION_REFERENCE, - "auxiliary_projection_digest": PROJECTION_DIGEST, - "scientific_purpose_reference": PURPOSE_REFERENCE, - "scientific_purpose_digest": PURPOSE_DIGEST, - "owner_contract_reference": OWNER_REFERENCE, - "owner_contract_version": 7, - "owner_contract_digest": OWNER_DIGEST, - "authorization_receipt_reference": AUTHORIZATION_REFERENCE, - "authorization_receipt_digest": AUTHORIZATION_DIGEST, - "scientific_use_receipt_reference": USE_REFERENCE, - "scientific_use_receipt_digest": USE_DIGEST, - "scientific_use_at": USED_AT, - "authorized_from": datetime(2026, 9, 1, tzinfo=timezone.utc), - "authorized_to": datetime(2026, 10, 1, tzinfo=timezone.utc), - } - values.update(overrides) - return CalibrationAuxiliaryAuthorityRecord(**values) - - -def _resolve(*, record: CalibrationAuxiliaryAuthorityRecord, **overrides: object) -> object: - values: dict[str, object] = { - "principal": ValidationPrincipal( - tenant_record_id=TENANT, - actor_reference="person:validation-analyst-1", - granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), - ), - "tenant_record_id": TENANT, - "validity_study_id": STUDY, - "authority_reference": AUTHORITY_REFERENCE, - "auxiliary_projection_reference": PROJECTION_REFERENCE, - "auxiliary_projection_digest": PROJECTION_DIGEST, - "scientific_purpose_reference": PURPOSE_REFERENCE, - "scientific_purpose_digest": PURPOSE_DIGEST, - "owner_contract_reference": OWNER_REFERENCE, - "owner_contract_version": 7, - "owner_contract_digest": OWNER_DIGEST, - "authorization_receipt_reference": AUTHORIZATION_REFERENCE, - "authorization_receipt_digest": AUTHORIZATION_DIGEST, - "scientific_use_receipt_reference": USE_REFERENCE, - "scientific_use_receipt_digest": USE_DIGEST, - "used_at": USED_AT, - "purpose_code": "selection_validity_analysis", - "policy": PurposeBoundAccessPolicy( - tenant_record_id=TENANT, - policy_version_code="calibration-authority-read-v1", - resource_kind="calibration_auxiliary_authority", - purpose_code="selection_validity_analysis", - operation_code="read", - required_scope_code="orgmetra.workforce_validation.read", - permitted_fields=READ_FIELDS, - ), - "read_port": _ReadPort(record), - } - values.update(overrides) - return resolve_calibration_auxiliary_authority(**values) - - -def test_exact_leaf_coordinates_are_accepted() -> None: - view = _resolve(record=_record()) - assert dict(view.fields)["authority_reference"] == AUTHORITY_REFERENCE - assert dict(view.fields)["owner_contract_digest"] == OWNER_DIGEST - assert dict(view.fields)["authorization_receipt_reference"] == AUTHORIZATION_REFERENCE - assert dict(view.fields)["scientific_use_receipt_reference"] == USE_REFERENCE - - -@pytest.mark.parametrize( - ("record_overrides", "request_overrides"), - [ - ( - {"authority_reference": "scientific_auxiliary_authority:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa"}, - {}, - ), - ({"owner_contract_digest": "a" * 64}, {}), - ( - {"authorization_receipt_reference": "scientific_data_authorization:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb"}, - {}, - ), - ( - {"scientific_use_receipt_reference": "scientific_use_receipt:cccccccc-cccc-4ccc-8ccc-cccccccccccc"}, - {}, - ), - ], -) -def test_owner_evidence_cannot_substitute_unrequested_leaf_coordinates( - record_overrides: dict[str, object], request_overrides: dict[str, object] -) -> None: - with pytest.raises(CalibrationAuxiliaryAuthorityIntegrityError): - _resolve(record=_record(**record_overrides), **request_overrides) From 485221372990b0d373414db2a53dd6c19e5514cf Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 14:19:52 +0900 Subject: [PATCH 095/603] test(workforce-validation): RED bind auxiliary projection version --- .../tests/test_calibration_auxiliary_authority.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py index ea6202ccd..d87909eb2 100644 --- a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py +++ b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py @@ -28,6 +28,7 @@ PROJECTION_REFERENCE = ( "calibration_auxiliary_projection:22222222-2222-4222-8222-222222222222" ) +PROJECTION_VERSION = 4 PURPOSE_REFERENCE = ( "scientific_data_use_purpose:33333333-3333-4333-8333-333333333333" ) @@ -52,6 +53,7 @@ { "authority_reference", "auxiliary_projection_reference", + "auxiliary_projection_version", "auxiliary_projection_digest", "scientific_purpose_reference", "scientific_purpose_digest", @@ -83,6 +85,7 @@ def read_calibration_auxiliary_authority( validity_study_id: UUID, authority_reference: str, auxiliary_projection_reference: str, + auxiliary_projection_version: int, auxiliary_projection_digest: str, scientific_purpose_reference: str, scientific_purpose_digest: str, @@ -101,6 +104,7 @@ def read_calibration_auxiliary_authority( validity_study_id, authority_reference, auxiliary_projection_reference, + auxiliary_projection_version, auxiliary_projection_digest, scientific_purpose_reference, scientific_purpose_digest, @@ -158,6 +162,7 @@ def _record(**overrides: object) -> CalibrationAuxiliaryAuthorityRecord: "validity_study_id": STUDY, "authority_reference": AUTHORITY_REFERENCE, "auxiliary_projection_reference": PROJECTION_REFERENCE, + "auxiliary_projection_version": PROJECTION_VERSION, "auxiliary_projection_digest": PROJECTION_DIGEST, "scientific_purpose_reference": PURPOSE_REFERENCE, "scientific_purpose_digest": PURPOSE_DIGEST, @@ -183,6 +188,7 @@ def _resolve(*, read_port: object, **overrides: object) -> CalibrationAuxiliaryA "validity_study_id": STUDY, "authority_reference": AUTHORITY_REFERENCE, "auxiliary_projection_reference": PROJECTION_REFERENCE, + "auxiliary_projection_version": PROJECTION_VERSION, "auxiliary_projection_digest": PROJECTION_DIGEST, "scientific_purpose_reference": PURPOSE_REFERENCE, "scientific_purpose_digest": PURPOSE_DIGEST, @@ -214,6 +220,7 @@ def test_resolution_authorizes_then_returns_minimized_corroborated_evidence() -> STUDY, AUTHORITY_REFERENCE, PROJECTION_REFERENCE, + PROJECTION_VERSION, PROJECTION_DIGEST, PURPOSE_REFERENCE, PURPOSE_DIGEST, @@ -236,6 +243,7 @@ def test_resolution_authorizes_then_returns_minimized_corroborated_evidence() -> ("authorized_to", AUTHORIZED_TO), ("auxiliary_projection_digest", PROJECTION_DIGEST), ("auxiliary_projection_reference", PROJECTION_REFERENCE), + ("auxiliary_projection_version", PROJECTION_VERSION), ("owner_contract_digest", OWNER_CONTRACT_DIGEST), ("owner_contract_reference", OWNER_CONTRACT_REFERENCE), ("owner_contract_version", 7), @@ -285,6 +293,7 @@ def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: }, {}, ), + ({"auxiliary_projection_version": PROJECTION_VERSION + 1}, {}), ({"auxiliary_projection_digest": "a" * 64}, {}), ( { @@ -369,6 +378,8 @@ def test_open_ended_authority_interval_accepts_later_owner_resolved_use() -> Non ("validity_study_id", UUID(int=0), ValueError), ("authority_reference", "wrong:authority", ValueError), ("auxiliary_projection_reference", "wrong:projection", ValueError), + ("auxiliary_projection_version", 0, ValueError), + ("auxiliary_projection_version", True, ValueError), ("auxiliary_projection_digest", "ABC", ValueError), ("scientific_purpose_reference", "wrong:purpose", ValueError), ("scientific_purpose_digest", "2" * 63, ValueError), @@ -404,6 +415,8 @@ def test_invalid_request_or_dependency_fails_before_owner_resolution( ("validity_study_id", "not-a-uuid"), ("authority_reference", "wrong:authority"), ("auxiliary_projection_reference", "wrong:projection"), + ("auxiliary_projection_version", 0), + ("auxiliary_projection_version", True), ("auxiliary_projection_digest", "1" * 63), ("scientific_purpose_reference", "wrong:purpose"), ("scientific_purpose_digest", "2" * 65), From 701d2d75e7eb54ced9ae01113250408699e97084 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 14:21:49 +0900 Subject: [PATCH 096/603] fix(workforce-validation): corroborate auxiliary projection version --- .../scientific_authority.py | 52 +++++++++++++------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py index bde01734d..4845b6528 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py @@ -39,6 +39,7 @@ { "authority_reference", "auxiliary_projection_reference", + "auxiliary_projection_version", "auxiliary_projection_digest", "scientific_purpose_reference", "scientific_purpose_digest", @@ -107,6 +108,7 @@ def __new__( validity_study_id: UUID, authority_reference: str, auxiliary_projection_reference: str, + auxiliary_projection_version: int, auxiliary_projection_digest: str, scientific_purpose_reference: str, scientific_purpose_digest: str, @@ -132,6 +134,9 @@ def __new__( auxiliary_projection_reference, "calibration_auxiliary_projection", ) + projection_version = _require_positive_integer( + "auxiliary_projection_version", auxiliary_projection_version + ) projection_digest = _require_digest( "auxiliary_projection_digest", auxiliary_projection_digest ) @@ -186,6 +191,7 @@ def __new__( study_identity, authority_ref, projection_ref, + projection_version, projection_digest, purpose_ref, purpose_digest, @@ -222,70 +228,75 @@ def auxiliary_projection_reference(self) -> str: """Return the opaque purpose-limited auxiliary projection reference.""" return self[3] + @property + def auxiliary_projection_version(self) -> int: + """Return the positive version of the purpose-limited auxiliary projection.""" + return self[4] + @property def auxiliary_projection_digest(self) -> str: """Return the projection evidence digest without exposing source attributes.""" - return self[4] + return self[5] @property def scientific_purpose_reference(self) -> str: """Return the governed scientific-use purpose reference.""" - return self[5] + return self[6] @property def scientific_purpose_digest(self) -> str: """Return the exact scientific-use purpose evidence digest.""" - return self[6] + return self[7] @property def owner_contract_reference(self) -> str: """Return the released owner-contract reference.""" - return self[7] + return self[8] @property def owner_contract_version(self) -> int: """Return the positive released owner-contract version.""" - return self[8] + return self[9] @property def owner_contract_digest(self) -> str: """Return the immutable bytes digest for the released owner contract.""" - return self[9] + return self[10] @property def authorization_receipt_reference(self) -> str: """Return the authoritative scientific-use authorization receipt reference.""" - return self[10] + return self[11] @property def authorization_receipt_digest(self) -> str: """Return the authorization receipt digest used for exact correlation.""" - return self[11] + return self[12] @property def scientific_use_receipt_reference(self) -> str: """Return the immutable scientific-use receipt reference.""" - return self[12] + return self[13] @property def scientific_use_receipt_digest(self) -> str: """Return the immutable scientific-use receipt digest.""" - return self[13] + return self[14] @property def scientific_use_at(self) -> datetime: """Return the owner-resolved UTC instant for the exact scientific use.""" - return self[14] + return self[15] @property def authorized_from(self) -> datetime: """Return the UTC instant when this scientific use became authorized.""" - return self[15] + return self[16] @property def authorized_to(self) -> datetime | None: """Return the exclusive UTC authorization end when one exists.""" - return self[16] + return self[17] class CalibrationAuxiliaryAuthorityView(tuple): @@ -333,6 +344,7 @@ def read_calibration_auxiliary_authority( validity_study_id: UUID, authority_reference: str, auxiliary_projection_reference: str, + auxiliary_projection_version: int, auxiliary_projection_digest: str, scientific_purpose_reference: str, scientific_purpose_digest: str, @@ -360,6 +372,7 @@ def resolve_calibration_auxiliary_authority( validity_study_id: UUID, authority_reference: str, auxiliary_projection_reference: str, + auxiliary_projection_version: int, auxiliary_projection_digest: str, scientific_purpose_reference: str, scientific_purpose_digest: str, @@ -380,9 +393,9 @@ def resolve_calibration_auxiliary_authority( The exact owner capability is captured inertly before authorization and the same function is invoked afterward. The request carries no protected source values. Owner evidence must reproduce every caller-supplied leaf coordinate, - including receipt references and the released owner-contract digest, and - independently bind the scientific-use receipt to the same use instant before - any corroborating fields are returned. + including the projection reference/version/digest, receipt references and the + released owner-contract digest, and independently bind the scientific-use + receipt to the same use instant before any corroborating fields are returned. """ if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") @@ -417,6 +430,9 @@ def resolve_calibration_auxiliary_authority( auxiliary_projection_reference, "calibration_auxiliary_projection", ) + projection_version = _require_positive_integer( + "auxiliary_projection_version", auxiliary_projection_version + ) projection_digest = _require_digest( "auxiliary_projection_digest", auxiliary_projection_digest ) @@ -473,6 +489,7 @@ def resolve_calibration_auxiliary_authority( validity_study_id=_restore_operational_uuid("validity_study_id", study_identity), authority_reference=authority_ref, auxiliary_projection_reference=projection_ref, + auxiliary_projection_version=projection_version, auxiliary_projection_digest=projection_digest, scientific_purpose_reference=purpose_ref, scientific_purpose_digest=purpose_digest, @@ -496,6 +513,7 @@ def resolve_calibration_auxiliary_authority( validity_study_id=persisted.validity_study_id, authority_reference=persisted.authority_reference, auxiliary_projection_reference=persisted.auxiliary_projection_reference, + auxiliary_projection_version=persisted.auxiliary_projection_version, auxiliary_projection_digest=persisted.auxiliary_projection_digest, scientific_purpose_reference=persisted.scientific_purpose_reference, scientific_purpose_digest=persisted.scientific_purpose_digest, @@ -517,6 +535,7 @@ def resolve_calibration_auxiliary_authority( != study_identity or record.authority_reference != authority_ref or record.auxiliary_projection_reference != projection_ref + or record.auxiliary_projection_version != projection_version or record.auxiliary_projection_digest != projection_digest or record.scientific_purpose_reference != purpose_ref or record.scientific_purpose_digest != purpose_digest @@ -536,6 +555,7 @@ def resolve_calibration_auxiliary_authority( values = { "authority_reference": record.authority_reference, "auxiliary_projection_reference": record.auxiliary_projection_reference, + "auxiliary_projection_version": record.auxiliary_projection_version, "auxiliary_projection_digest": record.auxiliary_projection_digest, "scientific_purpose_reference": record.scientific_purpose_reference, "scientific_purpose_digest": record.scientific_purpose_digest, From 58651e2136e76441f9c821d8d09dd63250579b41 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 14:22:28 +0900 Subject: [PATCH 097/603] docs(workforce-validation): bind projection version authority --- services/workforce-validation-api/README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index c1c79a7f0..3e640a3f1 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -25,12 +25,13 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar `resolve_calibration_auxiliary_authority(...)` is an executable owner-side slice for #407's durable scientific-evidence resolution gap. It does **not** import or copy the mutable validity-analysis implementation. Instead it defines the `workforce_validation` application contract that a later durable adapter must satisfy: - authorize the exact tenant/study scientific read before invoking the owner port; -- carry only opaque projection/purpose/owner/authorization/scientific-use references, SHA-256 evidence digests, immutable contract versions, the owner-resolved scientific-use instant, and authorization time bounds—never calibration source attributes, protected characteristics, benchmark values, or row-level weights; +- carry only opaque projection/purpose/owner/authorization/scientific-use references, SHA-256 evidence digests, immutable projection/contract versions, the owner-resolved scientific-use instant, and authorization time bounds—never calibration source attributes, protected characteristics, benchmark values, or row-level weights; +- require the exact purpose-limited auxiliary projection reference/version/digest rather than allowing a projection identity to float behind a digest or reference alone; - require a released-owner-contract reference/version and corroborating owner-contract digest rather than treating a caller-supplied version label as release authority; - require an immutable scientific-use receipt digest in the lookup and reconstruct the corresponding owner record, so a caller cannot choose a convenient historical `used_at` merely to fit a stale authorization interval; - require the caller's exact `used_at` coordinate to equal the owner-resolved `scientific_use_at`, while the record itself requires that instant to fall inside the owner-resolved authorization interval; - resolve through one statically captured `CalibrationAuxiliaryAuthorityReadPort` capability and reject inherited Protocol placeholders or descriptors before authorization; -- reconstruct the returned evidence into an exact tuple-backed `CalibrationAuxiliaryAuthorityRecord` and require tenant, study, projection, scientific purpose, released owner contract, authorization receipt, scientific-use receipt, and use time to match the requested coordinates; +- reconstruct the returned evidence into an exact tuple-backed `CalibrationAuxiliaryAuthorityRecord` and require tenant, study, projection reference/version/digest, scientific purpose, released owner contract, authorization receipt, scientific-use receipt, and use time to match the requested coordinates; - issue only a minimized `CalibrationAuxiliaryAuthorityView`. The view is corroborating data, not a reusable authorization credential or proof that an arbitrary injected port is a production owner. `resolve_calibration_benchmark_authority(...)` addresses #407 RED #5 at the canonical service boundary. The scientific leaf carries benchmark receipt reference/version/digest, released benchmark-owner contract reference/version/digest, and benchmark reference time; this resolver requires an owner port to corroborate those exact coordinates rather than accepting the leaf tuple as authority. It: @@ -76,8 +77,8 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ services/workforce-validation-api/tests ``` -The service package keeps an exact 100% owned statement/branch threshold. Calibration-authority coverage exercises authorization-before-owner-read, non-concrete/dynamic owner capabilities, malformed references/digests/versions/timestamps, foreign/mismatched owner evidence, caller/owner scientific-use-time mismatch, authorization-window mismatch, UUID alias mutation, structural immutability, and non-public view issuance. Calibration-benchmark coverage additionally exercises exact receipt/owner-contract coordinate mismatch, owner-resolved release-time enforcement, owner-contract-before-receipt chronology, future-reference rejection, append-only supersession completeness and monotonicity, successor release ordering, historical pre-supersession use, rejection at/after supersession, malformed references/digests/versions/timestamps, foreign tenant/study evidence, detached UUID views, structural immutability, and non-public output issuance. Weight/variance-authority coverage exercises every owner-coordinate mismatch, point/variance evidence aliasing, unsupported evidence modes and semantics, approximation-labelled-as-exact, pre-release use, foreign tenant/study evidence, integer correction-sequence mismatches, detached UUID views, and non-public output issuance. +The service package keeps an exact 100% owned statement/branch threshold. Calibration-authority coverage exercises authorization-before-owner-read, non-concrete/dynamic owner capabilities, malformed references/digests/versions/timestamps, projection-version mismatch, foreign/mismatched owner evidence, caller/owner scientific-use-time mismatch, authorization-window mismatch, UUID alias mutation, structural immutability, and non-public view issuance. Calibration-benchmark coverage additionally exercises exact receipt/owner-contract coordinate mismatch, owner-resolved release-time enforcement, owner-contract-before-receipt chronology, future-reference rejection, append-only supersession completeness and monotonicity, successor release ordering, historical pre-supersession use, rejection at/after supersession, malformed references/digests/versions/timestamps, foreign tenant/study evidence, detached UUID views, structural immutability, and non-public output issuance. Weight/variance-authority coverage exercises every owner-coordinate mismatch, point/variance evidence aliasing, unsupported evidence modes and semantics, approximation-labelled-as-exact, pre-release use, foreign tenant/study evidence, integer correction-sequence mismatches, detached UUID views, and non-public output issuance. The same Foundation job also runs `tests/test_workforce_validation_owner_schema_postgres.sh` in its own pinned PostgreSQL 16.14 container. That contract executes the service-local owner migration and checks the exact deny-default role flags, schema owner, absence of ineffective login-only `rolconfig`, actual `SET ROLE` search-path behavior, absence of inherited PUBLIC `USAGE`/`CREATE`, and absence of application relations in the bootstrap schema. The test intentionally demonstrates that `SET ROLE` retains the caller's existing `search_path`; runtime isolation therefore cannot be inferred from owner-role metadata. -Those source contracts are not terminal acceptance by themselves. The slice remains Draft until the exact current head actually executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and the normal review/governance requirements are satisfied. Only then may the next forward-only owner-table adoption and durable adapter be treated as eligible for integration. +Those source contracts are not terminal acceptance by themselves. The slice remains Draft until the exact current head actually executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and the normal review/governance requirements are satisfied. Only then may the next forward-only owner-table adoption and durable adapter be treated as eligible for integration. \ No newline at end of file From 00c9131cb29a00399606846e1c63a106201a8779 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 15:04:30 +0900 Subject: [PATCH 098/603] test(workforce-validation): require released result authority binding --- .../tests/test_validation_result_authority.py | 273 ++++++++++++++++++ 1 file changed, 273 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_authority.py diff --git a/services/workforce-validation-api/tests/test_validation_result_authority.py b/services/workforce-validation-api/tests/test_validation_result_authority.py new file mode 100644 index 000000000..9b3c8bca1 --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_authority.py @@ -0,0 +1,273 @@ +"""Fail closed when a released result is not bound to exact weight/variance evidence.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.result_authority import ( + ValidationResultAuthorityIntegrityError, + ValidationResultAuthorityNotFound, + ValidationResultAuthorityReadPort, + ValidationResultAuthorityRecord, + ValidationResultAuthorityView, + resolve_validation_result_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +COMPATIBILITY_REFERENCE = ( + "weight_variance_compatibility_receipt:22222222-2222-4222-8222-222222222222" +) +OWNER_REFERENCE = "released_owner_contract:33333333-3333-4333-8333-333333333333" +RESULT_DIGEST = "1" * 64 +COMPATIBILITY_DIGEST = "2" * 64 +ANALYSIS_WEIGHT_DIGEST = "3" * 64 +VARIANCE_DIGEST = "4" * 64 +OWNER_DIGEST = "5" * 64 +RELEASED_AT = datetime(2026, 9, 17, 5, 0, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "result_reference", + "result_digest", + "compatibility_receipt_reference", + "compatibility_receipt_digest", + "analysis_weight_receipt_digest", + "variance_design_receipt_digest", + "verification_status", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "released_at", + } +) + + +class _ReadPort: + """Return one configured released result record and retain exact lookup coordinates.""" + + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[tuple[object, ...]] = [] + + def read_validation_result_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + compatibility_receipt_reference: str, + compatibility_receipt_digest: str, + analysis_weight_receipt_digest: str, + variance_design_receipt_digest: str, + verification_status: str, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> object: + self.calls.append( + ( + tenant_record_id, + validity_study_id, + result_reference, + result_digest, + compatibility_receipt_reference, + compatibility_receipt_digest, + analysis_weight_receipt_digest, + variance_design_receipt_digest, + verification_status, + owner_contract_reference, + owner_contract_version, + owner_contract_digest, + ) + ) + return self.result + + +class _ProtocolOnly(ValidationResultAuthorityReadPort): + """Inherit only the Protocol placeholder, not a concrete owner capability.""" + + +def _principal() -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="validation-result-authority-read-v1", + resource_kind="validation_result_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record(**overrides: object) -> ValidationResultAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "result_reference": RESULT_REFERENCE, + "result_digest": RESULT_DIGEST, + "compatibility_receipt_reference": COMPATIBILITY_REFERENCE, + "compatibility_receipt_digest": COMPATIBILITY_DIGEST, + "analysis_weight_receipt_digest": ANALYSIS_WEIGHT_DIGEST, + "variance_design_receipt_digest": VARIANCE_DIGEST, + "verification_status": "verification_pending", + "owner_contract_reference": OWNER_REFERENCE, + "owner_contract_version": 7, + "owner_contract_digest": OWNER_DIGEST, + "released_at": RELEASED_AT, + } + values.update(overrides) + return ValidationResultAuthorityRecord(**values) + + +def _resolve(*, read_port: object, **overrides: object) -> ValidationResultAuthorityView: + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "result_reference": RESULT_REFERENCE, + "result_digest": RESULT_DIGEST, + "compatibility_receipt_reference": COMPATIBILITY_REFERENCE, + "compatibility_receipt_digest": COMPATIBILITY_DIGEST, + "analysis_weight_receipt_digest": ANALYSIS_WEIGHT_DIGEST, + "variance_design_receipt_digest": VARIANCE_DIGEST, + "verification_status": "verification_pending", + "owner_contract_reference": OWNER_REFERENCE, + "owner_contract_version": 7, + "owner_contract_digest": OWNER_DIGEST, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_validation_result_authority(**values) + + +def test_resolution_binds_result_to_exact_compatibility_and_owner_evidence() -> None: + port = _ReadPort(_record()) + + view = _resolve(read_port=port) + + assert isinstance(port, ValidationResultAuthorityReadPort) + assert port.calls == [ + ( + TENANT, + STUDY, + RESULT_REFERENCE, + RESULT_DIGEST, + COMPATIBILITY_REFERENCE, + COMPATIBILITY_DIGEST, + ANALYSIS_WEIGHT_DIGEST, + VARIANCE_DIGEST, + "verification_pending", + OWNER_REFERENCE, + 7, + OWNER_DIGEST, + ) + ] + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + fields = dict(view.fields) + assert fields["result_digest"] == RESULT_DIGEST + assert fields["compatibility_receipt_digest"] == COMPATIBILITY_DIGEST + assert fields["analysis_weight_receipt_digest"] == ANALYSIS_WEIGHT_DIGEST + assert fields["variance_design_receipt_digest"] == VARIANCE_DIGEST + assert fields["verification_status"] == "verification_pending" + assert fields["owner_contract_digest"] == OWNER_DIGEST + assert fields["released_at"] == RELEASED_AT + + +def test_not_verifiable_result_remains_released_non_authorizing_evidence() -> None: + record = _record(verification_status="not_verifiable") + view = _resolve( + read_port=_ReadPort(record), + verification_status="not_verifiable", + ) + assert dict(view.fields)["verification_status"] == "not_verifiable" + + +def test_authorization_denial_happens_before_owner_resolution() -> None: + port = _ReadPort(_record()) + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, policy=_policy(purpose_code="audit_review")) + assert port.calls == [] + + +def test_missing_noncanonical_or_mismatched_owner_evidence_fails_closed() -> None: + with pytest.raises(ValidationResultAuthorityNotFound): + _resolve(read_port=_ReadPort(None)) + with pytest.raises(ValidationResultAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object())) + with pytest.raises(ValidationResultAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(result_digest="a" * 64))) + + +def test_distinct_evidence_digests_and_non_authorizing_status_are_required() -> None: + with pytest.raises(ValueError): + _record(compatibility_receipt_digest=RESULT_DIGEST) + with pytest.raises(ValueError): + _resolve( + read_port=_ReadPort(_record()), + variance_design_receipt_digest=ANALYSIS_WEIGHT_DIGEST, + ) + with pytest.raises(ValueError): + _record(verification_status=1) + with pytest.raises(ValueError): + _record(verification_status="verified") + + +def test_invalid_dependencies_and_pre_release_use_fail_closed() -> None: + with pytest.raises(TypeError): + _resolve(read_port=object()) + with pytest.raises(TypeError): + _resolve(read_port=_ProtocolOnly()) + with pytest.raises(TypeError): + _resolve(read_port=_ReadPort(_record()), principal=object()) + with pytest.raises(TypeError): + _resolve(read_port=_ReadPort(_record()), policy=object()) + + port = _ReadPort(_record()) + with pytest.raises(ValidationResultAuthorityIntegrityError): + _resolve( + read_port=port, + used_at=datetime(2026, 9, 17, 4, 59, tzinfo=timezone.utc), + ) + assert len(port.calls) == 1 + + +def test_record_and_view_are_immutable_and_public_view_construction_is_blocked() -> None: + record = _record() + with pytest.raises(AttributeError): + object.__setattr__(record, "verification_status", "not_verifiable") + + view = _resolve(read_port=_ReadPort(record)) + with pytest.raises(AttributeError): + object.__setattr__(view, "fields", ()) + with pytest.raises(TypeError): + ValidationResultAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) + + +def test_cross_tenant_owner_evidence_is_rejected() -> None: + with pytest.raises(ValidationResultAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(tenant_record_id=OTHER_TENANT))) From bb05072a7c28630885b444df172ea4f094448c56 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 15:05:11 +0900 Subject: [PATCH 099/603] feat(workforce-validation): corroborate released result evidence --- .../result_authority.py | 475 ++++++++++++++++++ 1 file changed, 475 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py new file mode 100644 index 000000000..54d425d3e --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py @@ -0,0 +1,475 @@ +"""Corroborate released validation-result evidence through an owner port. + +This application boundary binds one immutable validation result to the exact +point-weight/variance compatibility evidence it claims to use. It keeps the +scientific leaf non-authorizing: only ``verification_pending`` or +``not_verifiable`` may cross this owner boundary, and durable PostgreSQL/release +resolution remains a child persistence responsibility after this service lands. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + +_RESOURCE_KIND = "validation_result_authority" +_OPERATION = "read" +_VERIFICATION_STATUSES = frozenset({"verification_pending", "not_verifiable"}) +_READ_FIELDS = frozenset( + { + "result_reference", + "result_digest", + "compatibility_receipt_reference", + "compatibility_receipt_digest", + "analysis_weight_receipt_digest", + "variance_design_receipt_digest", + "verification_status", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "released_at", + } +) + + +class ValidationResultAuthorityNotFound(LookupError): + """Indicate that no released owner evidence corroborates the result tuple.""" + + +class ValidationResultAuthorityIntegrityError(RuntimeError): + """Indicate that released owner evidence cannot support the requested result.""" + + +def _require_verification_status(value: object) -> str: + """Require one explicit non-authorizing result verification state.""" + if type(value) is not str or value not in _VERIFICATION_STATUSES: + raise ValueError( + "verification_status must be verification_pending or not_verifiable." + ) + return value + + +class ValidationResultAuthorityRecord(tuple): + """Immutable owner projection binding result, weight, and variance evidence.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + compatibility_receipt_reference: str, + compatibility_receipt_digest: str, + analysis_weight_receipt_digest: str, + variance_design_receipt_digest: str, + verification_status: str, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + released_at: datetime, + ) -> ValidationResultAuthorityRecord: + """Validate and detach the minimum released result-provenance coordinates.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + result_ref = _require_reference( + "result_reference", result_reference, "validation_analysis_result" + ) + result_evidence_digest = _require_digest("result_digest", result_digest) + compatibility_ref = _require_reference( + "compatibility_receipt_reference", + compatibility_receipt_reference, + "weight_variance_compatibility_receipt", + ) + compatibility_digest = _require_digest( + "compatibility_receipt_digest", compatibility_receipt_digest + ) + point_digest = _require_digest( + "analysis_weight_receipt_digest", analysis_weight_receipt_digest + ) + variance_digest = _require_digest( + "variance_design_receipt_digest", variance_design_receipt_digest + ) + if len( + { + result_evidence_digest, + compatibility_digest, + point_digest, + variance_digest, + } + ) != 4: + raise ValueError( + "result, compatibility, analysis-weight, and variance evidence must be distinct." + ) + status = _require_verification_status(verification_status) + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + release_instant = _require_aware_datetime("released_at", released_at) + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + result_ref, + result_evidence_digest, + compatibility_ref, + compatibility_digest, + point_digest, + variance_digest, + status, + owner_ref, + owner_version, + owner_digest, + release_instant, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity for this released evidence.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity for this released evidence.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def result_reference(self) -> str: + """Return the immutable scientific result reference.""" + return self[2] + + @property + def result_digest(self) -> str: + """Return the digest of the exact scientific result bytes.""" + return self[3] + + @property + def compatibility_receipt_reference(self) -> str: + """Return the exact point-weight/variance compatibility receipt reference.""" + return self[4] + + @property + def compatibility_receipt_digest(self) -> str: + """Return the exact compatibility receipt digest.""" + return self[5] + + @property + def analysis_weight_receipt_digest(self) -> str: + """Return the final point-estimation weight receipt digest.""" + return self[6] + + @property + def variance_design_receipt_digest(self) -> str: + """Return the distinct variance-design receipt digest.""" + return self[7] + + @property + def verification_status(self) -> str: + """Return the non-authorizing scientific verification state.""" + return self[8] + + @property + def owner_contract_reference(self) -> str: + """Return the released owner-contract reference.""" + return self[9] + + @property + def owner_contract_version(self) -> int: + """Return the positive released owner-contract version.""" + return self[10] + + @property + def owner_contract_digest(self) -> str: + """Return the immutable released owner-contract digest.""" + return self[11] + + @property + def released_at(self) -> datetime: + """Return when this result-authority evidence became released.""" + return self[12] + + +class ValidationResultAuthorityView(tuple): + """Field-minimized released result evidence issued only after authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> ValidationResultAuthorityView: + """Reject direct construction; only the resolver may issue this view.""" + raise TypeError( + "ValidationResultAuthorityView is issued only by " + "resolve_validation_result_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable corroborating fields without row-level scientific data.""" + return self[2] + + +@runtime_checkable +class ValidationResultAuthorityReadPort(Protocol): + """Owner read contract for released result-to-weight/variance evidence.""" + + def read_validation_result_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + compatibility_receipt_reference: str, + compatibility_receipt_digest: str, + analysis_weight_receipt_digest: str, + variance_design_receipt_digest: str, + verification_status: str, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> ValidationResultAuthorityRecord | None: + """Return matching released evidence or ``None`` through an owner ACL.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + ValidationResultAuthorityReadPort, "read_validation_result_authority" +) + + +def resolve_validation_result_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + compatibility_receipt_reference: str, + compatibility_receipt_digest: str, + analysis_weight_receipt_digest: str, + variance_design_receipt_digest: str, + verification_status: str, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: ValidationResultAuthorityReadPort, +) -> ValidationResultAuthorityView: + """Authorize then corroborate one exact released scientific-result binding.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static( + type(read_port), "read_validation_result_authority", None + ) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError( + "read_port must expose a statically callable " + "read_validation_result_authority." + ) + + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + tenant_id = _restore_operational_uuid("tenant_record_id", tenant_identity) + study_id = _restore_operational_uuid("validity_study_id", study_identity) + result_ref = _require_reference( + "result_reference", result_reference, "validation_analysis_result" + ) + result_evidence_digest = _require_digest("result_digest", result_digest) + compatibility_ref = _require_reference( + "compatibility_receipt_reference", + compatibility_receipt_reference, + "weight_variance_compatibility_receipt", + ) + compatibility_digest = _require_digest( + "compatibility_receipt_digest", compatibility_receipt_digest + ) + point_digest = _require_digest( + "analysis_weight_receipt_digest", analysis_weight_receipt_digest + ) + variance_digest = _require_digest( + "variance_design_receipt_digest", variance_design_receipt_digest + ) + if len( + {result_evidence_digest, compatibility_digest, point_digest, variance_digest} + ) != 4: + raise ValueError( + "result, compatibility, analysis-weight, and variance evidence must be distinct." + ) + status = _require_verification_status(verification_status) + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=_restore_operational_uuid("tenant_record_id", tenant_identity), + validity_study_id=_restore_operational_uuid("validity_study_id", study_identity), + result_reference=result_ref, + result_digest=result_evidence_digest, + compatibility_receipt_reference=compatibility_ref, + compatibility_receipt_digest=compatibility_digest, + analysis_weight_receipt_digest=point_digest, + variance_design_receipt_digest=variance_digest, + verification_status=status, + owner_contract_reference=owner_ref, + owner_contract_version=owner_version, + owner_contract_digest=owner_digest, + ) + if persisted is None: + raise ValidationResultAuthorityNotFound(str(study_id)) + if type(persisted) is not ValidationResultAuthorityRecord: + raise ValidationResultAuthorityIntegrityError( + "owner port returned non-canonical validation-result authority evidence" + ) + + record = ValidationResultAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + result_reference=persisted.result_reference, + result_digest=persisted.result_digest, + compatibility_receipt_reference=persisted.compatibility_receipt_reference, + compatibility_receipt_digest=persisted.compatibility_receipt_digest, + analysis_weight_receipt_digest=persisted.analysis_weight_receipt_digest, + variance_design_receipt_digest=persisted.variance_design_receipt_digest, + verification_status=persisted.verification_status, + owner_contract_reference=persisted.owner_contract_reference, + owner_contract_version=persisted.owner_contract_version, + owner_contract_digest=persisted.owner_contract_digest, + released_at=persisted.released_at, + ) + requested_identity = ( + tenant_identity, + study_identity, + result_ref, + result_evidence_digest, + compatibility_ref, + compatibility_digest, + point_digest, + variance_digest, + status, + owner_ref, + owner_version, + owner_digest, + ) + record_identity = ( + _store_operational_uuid("record tenant_record_id", record.tenant_record_id), + _store_operational_uuid("record validity_study_id", record.validity_study_id), + record.result_reference, + record.result_digest, + record.compatibility_receipt_reference, + record.compatibility_receipt_digest, + record.analysis_weight_receipt_digest, + record.variance_design_receipt_digest, + record.verification_status, + record.owner_contract_reference, + record.owner_contract_version, + record.owner_contract_digest, + ) + if record_identity != requested_identity: + raise ValidationResultAuthorityIntegrityError( + "owner evidence does not match the requested validation-result binding" + ) + if use_instant < record.released_at: + raise ValidationResultAuthorityIntegrityError( + "validation-result authority cannot be used before its release instant" + ) + + values = { + "result_reference": record.result_reference, + "result_digest": record.result_digest, + "compatibility_receipt_reference": record.compatibility_receipt_reference, + "compatibility_receipt_digest": record.compatibility_receipt_digest, + "analysis_weight_receipt_digest": record.analysis_weight_receipt_digest, + "variance_design_receipt_digest": record.variance_design_receipt_digest, + "verification_status": record.verification_status, + "owner_contract_reference": record.owner_contract_reference, + "owner_contract_version": record.owner_contract_version, + "owner_contract_digest": record.owner_contract_digest, + "released_at": record.released_at, + } + fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) + return tuple.__new__( + ValidationResultAuthorityView, + (tenant_identity, study_identity, fields), + ) From e43e95f1af4755233b92c4aa4e2749c35e0577e7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 15:05:22 +0900 Subject: [PATCH 100/603] feat(workforce-validation): export result authority contract --- .../orgmetra_workforce_validation_api/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index e2b398b40..173fb1eae 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -17,6 +17,14 @@ ValidityStudyView, read_validity_study, ) +from orgmetra_workforce_validation_api.result_authority import ( + ValidationResultAuthorityIntegrityError, + ValidationResultAuthorityNotFound, + ValidationResultAuthorityReadPort, + ValidationResultAuthorityRecord, + ValidationResultAuthorityView, + resolve_validation_result_authority, +) from orgmetra_workforce_validation_api.scientific_authority import ( CalibrationAuxiliaryAuthorityIntegrityError, CalibrationAuxiliaryAuthorityNotFound, @@ -46,6 +54,11 @@ "CalibrationBenchmarkAuthorityRecord", "CalibrationBenchmarkAuthorityView", "ValidationPrincipal", + "ValidationResultAuthorityIntegrityError", + "ValidationResultAuthorityNotFound", + "ValidationResultAuthorityReadPort", + "ValidationResultAuthorityRecord", + "ValidationResultAuthorityView", "ValidityStudyIntegrityError", "ValidityStudyNotFound", "ValidityStudyReadPort", @@ -59,5 +72,6 @@ "read_validity_study", "resolve_calibration_auxiliary_authority", "resolve_calibration_benchmark_authority", + "resolve_validation_result_authority", "resolve_weight_variance_authority", ] From 9da3177b455d40cade72d10de5ede208b436d9f7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 15:06:53 +0900 Subject: [PATCH 101/603] docs(workforce-validation): bind released result authority --- services/workforce-validation-api/README.md | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 3e640a3f1..a4f00a66b 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -1,6 +1,6 @@ # Orgmetra Workforce Validation API -This package is the application boundary for the `workforce_validation` bounded context. The current slice exposes purpose-bound owner reads for the existing validity-study registry header, value-minimized scientific auxiliary-use authority, released calibration-benchmark authority, and point-weight/variance-design compatibility authority while establishing the context-local PostgreSQL ownership bootstrap. +This package is the application boundary for the `workforce_validation` bounded context. The current slice exposes purpose-bound owner reads for the existing validity-study registry header, value-minimized scientific auxiliary-use authority, released calibration-benchmark authority, point-weight/variance-design compatibility authority, and released validation-result binding while establishing the context-local PostgreSQL ownership bootstrap. It does **not** query People, Talent Acquisition, Performance Management, Job Architecture, Psychometrics Commons, fast-mlsirm, TEPP, or another bounded context's application tables. Those contexts remain separate owners. Exact foreign identifiers and immutable specialist/scientific evidence cross this boundary only through released/versioned contracts and owner ports. @@ -58,13 +58,23 @@ It does **not** query People, Talent Acquisition, Performance Management, Job Ar - reconstructs owner evidence into an exact tuple-backed `WeightVarianceAuthorityRecord` and fails closed if any requested scientific coordinate differs from the owner projection; - returns only a minimized `WeightVarianceAuthorityView`. It never copies row-level point weights, replicate vectors, frame/cluster/stratum variables, protected characteristics, or foreign application-table values. -These application contracts do **not** complete #407 and do not make an arbitrary injected Python port durable scientific authority. The current branch has no durable scientific-authority relation or released auxiliary/benchmark/variance-evidence adapter. After the canonical owner persistence path is protected truth, #248 or its verified successor must implement schema-qualified least-privilege durable ports and prove that resolved owner evidence is itself released/versioned, append-only where corrected, and purpose-authorized. Mutable #57 source is not a runtime or source dependency of this service; its active compatibility and benchmark contracts were used only to align the application boundary's evidence coordinates. +`resolve_validation_result_authority(...)` closes the next #407 result-binding gap. The scientific leaf's canonical result serializes a digest of the exact `WeightVarianceCompatibilityReceipt`, but point/variance corroboration alone does not prove which compatibility receipt one released result actually bound. The result resolver therefore: + +- authorizes the exact tenant/study scientific read before invoking one statically captured `ValidationResultAuthorityReadPort`; +- binds the immutable validation-result reference/digest to the exact compatibility-receipt reference/digest and, independently, the final analysis-weight and variance-design receipt digests; +- requires those four evidence digests to be distinct so a result, compatibility receipt, point-weight receipt, and variance receipt cannot alias one another; +- preserves only the scientific leaf's non-authorizing verification states: `verification_pending` and `not_verifiable`. A caller or owner port cannot promote convergence to `verified` at this boundary; +- requires an exact released owner-contract reference/version/digest and owner-resolved release instant, rejecting use before release; +- passes every caller coordinate into the owner lookup, reconstructs the returned tuple-backed record, then exact-matches tenant, study, result, compatibility, point-weight, variance, status, and owner-contract coordinates before issuing a view; +- returns only a minimized `ValidationResultAuthorityView`. Effect estimates, uncertainty values, row-level weights, replicate vectors, protected attributes, and foreign application-table values do not cross this owner-corroboration boundary. + +These application contracts do **not** complete #407 and do not make an arbitrary injected Python port durable scientific authority. The current branch has no durable scientific-authority relation or released auxiliary/benchmark/variance/result-evidence adapter. After the canonical owner persistence path is protected truth, #248 or its verified successor must implement schema-qualified least-privilege durable ports and prove that resolved owner evidence is itself released/versioned, append-only where corrected, purpose-authorized, and result-bound. Mutable #57 source is not a runtime or source dependency of this service; its active compatibility, benchmark, and result contracts were used only to align the application boundary's evidence coordinates. `services/workforce-validation-api/database/migrations/0001_owner_schema.sql` starts this bounded context's own migration history. It creates the `workforce_validation` schema and deny-default `workforce_validation_role`, revokes public schema access, and intentionally creates or moves no application table yet. The role is a **NOLOGIN migration/schema owner only**; runtime principals must not be granted that owner role. PostgreSQL applies role-level configuration defaults at login and does not re-apply them on `SET ROLE`, so an `ALTER ROLE ... SET search_path` entry on this NOLOGIN role is not treated as a runtime isolation control. The later durable adapter must use a distinct least-privilege runtime role, schema-qualified `workforce_validation` relations, and explicit function-level `search_path` where `SECURITY DEFINER` code is introduced. Protected foundation migrations still create validity-study tables in the legacy foundation schema, so the next forward-only persistence increment must adopt those records without normalizing `public.validity_study` as a long-lived service contract or breaking existing linkage evidence. -Issue #234 owns the remaining order: durable owner-schema adoption and PostgreSQL adapter, idempotent registration, explicit predictor/sample/decision-policy/analysis-protocol versions, scientific adapters, OpenAPI/gateway exposure, and realistic p95 measurement. Issues #236–#244 retain the current bootstrap trust-boundary findings through exact-head acceptance and protected integration: persisted-record immutability, principal immutability and constructor revalidation, owner-role/runtime-role separation, inert repository-capability validation, immutable minimized output, non-public issuance of that output, detached UUID storage/target snapshots, and exact validation of UUID internal payloads before comparison. Issue #407 additionally keeps durable scientific-authority resolution open until owner persistence/released evidence, exact-head GREEN, independent review, and protected integration are real. +Issue #234 owns the remaining order: durable owner-schema adoption and PostgreSQL adapter, idempotent registration, explicit predictor/sample/decision-policy/analysis-protocol versions, scientific adapters, OpenAPI/gateway exposure, and realistic p95 measurement. Issues #236–#244 retain the current bootstrap trust-boundary findings through exact-head acceptance and protected integration: persisted-record immutability, principal immutability and constructor revalidation, owner-role/runtime-role separation, inert repository-capability validation, immutable minimized output, non-public issuance of that output, detached UUID storage/target snapshots, and exact validation of UUID internal payloads before comparison. Issue #407 additionally keeps durable scientific-authority resolution open until owner persistence/released evidence, exact result-to-weight/variance binding, exact-head GREEN, independent review, and protected integration are real. ## Test @@ -77,8 +87,8 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ services/workforce-validation-api/tests ``` -The service package keeps an exact 100% owned statement/branch threshold. Calibration-authority coverage exercises authorization-before-owner-read, non-concrete/dynamic owner capabilities, malformed references/digests/versions/timestamps, projection-version mismatch, foreign/mismatched owner evidence, caller/owner scientific-use-time mismatch, authorization-window mismatch, UUID alias mutation, structural immutability, and non-public view issuance. Calibration-benchmark coverage additionally exercises exact receipt/owner-contract coordinate mismatch, owner-resolved release-time enforcement, owner-contract-before-receipt chronology, future-reference rejection, append-only supersession completeness and monotonicity, successor release ordering, historical pre-supersession use, rejection at/after supersession, malformed references/digests/versions/timestamps, foreign tenant/study evidence, detached UUID views, structural immutability, and non-public output issuance. Weight/variance-authority coverage exercises every owner-coordinate mismatch, point/variance evidence aliasing, unsupported evidence modes and semantics, approximation-labelled-as-exact, pre-release use, foreign tenant/study evidence, integer correction-sequence mismatches, detached UUID views, and non-public output issuance. +The service package keeps an exact 100% owned statement/branch threshold. Calibration-authority coverage exercises authorization-before-owner-read, non-concrete/dynamic owner capabilities, malformed references/digests/versions/timestamps, projection-version mismatch, foreign/mismatched owner evidence, caller/owner scientific-use-time mismatch, authorization-window mismatch, UUID alias mutation, structural immutability, and non-public view issuance. Calibration-benchmark coverage additionally exercises exact receipt/owner-contract coordinate mismatch, owner-resolved release-time enforcement, owner-contract-before-receipt chronology, future-reference rejection, append-only supersession completeness and monotonicity, successor release ordering, historical pre-supersession use, rejection at/after supersession, malformed references/digests/versions/timestamps, foreign tenant/study evidence, detached UUID views, structural immutability, and non-public output issuance. Weight/variance-authority coverage exercises every owner-coordinate mismatch, point/variance evidence aliasing, unsupported evidence modes and semantics, approximation-labelled-as-exact, pre-release use, foreign tenant/study evidence, integer correction-sequence mismatches, detached UUID views, and non-public output issuance. Result-authority coverage adds exact result/compatibility/point-weight/variance tuple lookup, digest-alias rejection, non-authorizing status enforcement, authorization-before-owner-read, non-concrete capability rejection, owner-coordinate mismatch, pre-release use, cross-tenant evidence rejection, structural immutability, and non-public output issuance. The same Foundation job also runs `tests/test_workforce_validation_owner_schema_postgres.sh` in its own pinned PostgreSQL 16.14 container. That contract executes the service-local owner migration and checks the exact deny-default role flags, schema owner, absence of ineffective login-only `rolconfig`, actual `SET ROLE` search-path behavior, absence of inherited PUBLIC `USAGE`/`CREATE`, and absence of application relations in the bootstrap schema. The test intentionally demonstrates that `SET ROLE` retains the caller's existing `search_path`; runtime isolation therefore cannot be inferred from owner-role metadata. -Those source contracts are not terminal acceptance by themselves. The slice remains Draft until the exact current head actually executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and the normal review/governance requirements are satisfied. Only then may the next forward-only owner-table adoption and durable adapter be treated as eligible for integration. \ No newline at end of file +Those source contracts are not terminal acceptance by themselves. The slice remains Draft until the exact current head actually executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and the normal review/governance requirements are satisfied. Only then may the next forward-only owner-table adoption and durable adapter be treated as eligible for integration. From a29eda8b960278ab13bdcf5b4bc90b74c39063e9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 16:30:59 +0900 Subject: [PATCH 102/603] test(workforce-validation): add RED for durable non-verifiability --- ...test_validation_result_nonverifiability.py | 335 ++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py new file mode 100644 index 000000000..6d75ea213 --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py @@ -0,0 +1,335 @@ +"""RED contract for durable non-verifiability of validation-result evidence.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.result_nonverifiability import ( + ValidationResultNonVerifiabilityIntegrityError, + ValidationResultNonVerifiabilityNotFound, + ValidationResultNonVerifiabilityReadPort, + ValidationResultNonVerifiabilityRecord, + ValidationResultNonVerifiabilityView, + resolve_validation_result_nonverifiability, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +FAILED_WEIGHT_REFERENCE = "analysis_weight_receipt:22222222-2222-4222-8222-222222222222" +ATTEMPT_REFERENCE = ( + "validation_evidence_verification_attempt:33333333-3333-4333-8333-333333333333" +) +OWNER_REFERENCE = "released_owner_contract:44444444-4444-4444-8444-444444444444" +RESULT_DIGEST = "1" * 64 +FAILED_WEIGHT_DIGEST = "2" * 64 +ATTEMPT_DIGEST = "3" * 64 +OWNER_DIGEST = "4" * 64 +EVALUATED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 6, 5, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 6, 10, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "result_reference", + "result_digest", + "verification_status", + "failed_evidence_kind", + "failure_mode", + "failed_evidence_reference", + "failed_evidence_digest", + "verification_attempt_reference", + "verification_attempt_digest", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "evaluated_at", + "released_at", + } +) + + +class _ReadPort: + """Return one configured owner outcome and retain exact lookup coordinates.""" + + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[tuple[object, ...]] = [] + + def read_validation_result_nonverifiability( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + failed_evidence_kind: str, + failure_mode: str, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> object: + self.calls.append( + ( + tenant_record_id, + validity_study_id, + result_reference, + result_digest, + failed_evidence_kind, + failure_mode, + owner_contract_reference, + owner_contract_version, + owner_contract_digest, + ) + ) + return self.result + + +class _ProtocolOnly(ValidationResultNonVerifiabilityReadPort): + """Inherit only the Protocol placeholder, not a concrete owner capability.""" + + +def _principal() -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="validation-result-nonverifiability-read-v1", + resource_kind="validation_result_nonverifiability", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record(**overrides: object) -> ValidationResultNonVerifiabilityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "result_reference": RESULT_REFERENCE, + "result_digest": RESULT_DIGEST, + "failed_evidence_kind": "analysis_weight_receipt", + "failure_mode": "missing", + "failed_evidence_reference": None, + "failed_evidence_digest": None, + "verification_attempt_reference": ATTEMPT_REFERENCE, + "verification_attempt_digest": ATTEMPT_DIGEST, + "owner_contract_reference": OWNER_REFERENCE, + "owner_contract_version": 7, + "owner_contract_digest": OWNER_DIGEST, + "evaluated_at": EVALUATED_AT, + "released_at": RELEASED_AT, + } + values.update(overrides) + return ValidationResultNonVerifiabilityRecord(**values) + + +def _resolve( + *, read_port: object, **overrides: object +) -> ValidationResultNonVerifiabilityView: + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "result_reference": RESULT_REFERENCE, + "result_digest": RESULT_DIGEST, + "failed_evidence_kind": "analysis_weight_receipt", + "failure_mode": "missing", + "owner_contract_reference": OWNER_REFERENCE, + "owner_contract_version": 7, + "owner_contract_digest": OWNER_DIGEST, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_validation_result_nonverifiability(**values) + + +def test_missing_final_weight_evidence_is_released_as_not_verifiable() -> None: + port = _ReadPort(_record()) + + view = _resolve(read_port=port) + + assert isinstance(port, ValidationResultNonVerifiabilityReadPort) + assert port.calls == [ + ( + TENANT, + STUDY, + RESULT_REFERENCE, + RESULT_DIGEST, + "analysis_weight_receipt", + "missing", + OWNER_REFERENCE, + 7, + OWNER_DIGEST, + ) + ] + fields = dict(view.fields) + assert fields["verification_status"] == "not_verifiable" + assert fields["failed_evidence_kind"] == "analysis_weight_receipt" + assert fields["failure_mode"] == "missing" + assert fields["failed_evidence_reference"] is None + assert fields["failed_evidence_digest"] is None + assert fields["verification_attempt_reference"] == ATTEMPT_REFERENCE + assert fields["verification_attempt_digest"] == ATTEMPT_DIGEST + assert fields["evaluated_at"] == EVALUATED_AT + assert fields["released_at"] == RELEASED_AT + + +def test_non_reproducible_weight_evidence_keeps_exact_failed_receipt() -> None: + record = _record( + failure_mode="non_reproducible", + failed_evidence_reference=FAILED_WEIGHT_REFERENCE, + failed_evidence_digest=FAILED_WEIGHT_DIGEST, + ) + + view = _resolve( + read_port=_ReadPort(record), + failure_mode="non_reproducible", + ) + + fields = dict(view.fields) + assert fields["verification_status"] == "not_verifiable" + assert fields["failed_evidence_reference"] == FAILED_WEIGHT_REFERENCE + assert fields["failed_evidence_digest"] == FAILED_WEIGHT_DIGEST + + +@pytest.mark.parametrize( + ("failed_evidence_kind", "failed_reference"), + [ + ( + "weight_variance_compatibility_receipt", + "weight_variance_compatibility_receipt:" + "55555555-5555-4555-8555-555555555555", + ), + ( + "variance_design_receipt", + "variance_design_receipt:66666666-6666-4666-8666-666666666666", + ), + ], +) +def test_non_reproducible_evidence_kind_uses_its_typed_reference( + failed_evidence_kind: str, + failed_reference: str, +) -> None: + record = _record( + failed_evidence_kind=failed_evidence_kind, + failure_mode="non_reproducible", + failed_evidence_reference=failed_reference, + failed_evidence_digest=FAILED_WEIGHT_DIGEST, + ) + view = _resolve( + read_port=_ReadPort(record), + failed_evidence_kind=failed_evidence_kind, + failure_mode="non_reproducible", + ) + assert dict(view.fields)["failed_evidence_reference"] == failed_reference + + +def test_missing_and_non_reproducible_modes_fail_closed_on_incoherent_evidence() -> None: + with pytest.raises(ValueError, match="must be absent"): + _record( + failed_evidence_reference=FAILED_WEIGHT_REFERENCE, + failed_evidence_digest=FAILED_WEIGHT_DIGEST, + ) + with pytest.raises(ValueError, match="required"): + _record(failure_mode="non_reproducible") + with pytest.raises(ValueError, match="failed_evidence_reference"): + _record( + failure_mode="non_reproducible", + failed_evidence_reference=( + "variance_design_receipt:22222222-2222-4222-8222-222222222222" + ), + failed_evidence_digest=FAILED_WEIGHT_DIGEST, + ) + + +def test_reason_and_attempt_evidence_are_strict_and_non_aliasing() -> None: + with pytest.raises(ValueError, match="failed_evidence_kind"): + _record(failed_evidence_kind="point_weight") + with pytest.raises(ValueError, match="failure_mode"): + _record(failure_mode="unknown") + with pytest.raises(ValueError, match="verification_attempt_reference"): + _record(verification_attempt_reference="verification-attempt-v1") + with pytest.raises(ValueError, match="verification_attempt_digest"): + _record(verification_attempt_digest="not-a-digest") + with pytest.raises(ValueError, match="must be distinct"): + _record(verification_attempt_digest=RESULT_DIGEST) + + +def test_evaluation_must_precede_release() -> None: + with pytest.raises(ValueError, match="evaluated_at"): + _record( + evaluated_at=datetime(2026, 9, 17, 6, 6, tzinfo=timezone.utc), + released_at=RELEASED_AT, + ) + + +def test_authorization_denial_happens_before_owner_resolution() -> None: + port = _ReadPort(_record()) + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, policy=_policy(purpose_code="audit_review")) + assert port.calls == [] + + +def test_missing_noncanonical_or_mismatched_owner_outcome_fails_closed() -> None: + with pytest.raises(ValidationResultNonVerifiabilityNotFound): + _resolve(read_port=_ReadPort(None)) + with pytest.raises(ValidationResultNonVerifiabilityIntegrityError): + _resolve(read_port=_ReadPort(object())) + with pytest.raises(ValidationResultNonVerifiabilityIntegrityError): + _resolve(read_port=_ReadPort(_record(result_digest="a" * 64))) + + +def test_invalid_dependencies_and_pre_release_use_fail_closed() -> None: + with pytest.raises(TypeError): + _resolve(read_port=object()) + with pytest.raises(TypeError): + _resolve(read_port=_ProtocolOnly()) + with pytest.raises(TypeError): + _resolve(read_port=_ReadPort(_record()), principal=object()) + with pytest.raises(TypeError): + _resolve(read_port=_ReadPort(_record()), policy=object()) + + port = _ReadPort(_record()) + with pytest.raises(ValidationResultNonVerifiabilityIntegrityError): + _resolve( + read_port=port, + used_at=datetime(2026, 9, 17, 6, 4, tzinfo=timezone.utc), + ) + assert len(port.calls) == 1 + + +def test_record_and_view_are_immutable_and_public_view_construction_is_blocked() -> None: + record = _record() + with pytest.raises(AttributeError): + object.__setattr__(record, "failure_mode", "non_reproducible") + + view = _resolve(read_port=_ReadPort(record)) + with pytest.raises(AttributeError): + object.__setattr__(view, "fields", ()) + with pytest.raises(TypeError): + ValidationResultNonVerifiabilityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) + + +def test_cross_tenant_owner_outcome_is_rejected() -> None: + with pytest.raises(ValidationResultNonVerifiabilityIntegrityError): + _resolve(read_port=_ReadPort(_record(tenant_record_id=OTHER_TENANT))) From 3c8757a38c54636dd33c929ee9e2c127a963e344 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 16:32:17 +0900 Subject: [PATCH 103/603] feat(workforce-validation): model released not-verifiable outcomes --- .../result_nonverifiability.py | 507 ++++++++++++++++++ 1 file changed, 507 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py new file mode 100644 index 000000000..705eea960 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py @@ -0,0 +1,507 @@ +"""Represent released non-authorizing outcomes when result evidence cannot be verified. + +This application boundary exists for #407 RED 12: absence or failed reproducibility +of required point-weight/compatibility/variance evidence must become explicit +``not_verifiable`` owner evidence rather than an exception that callers can +misinterpret as scientific GREEN. Durable PostgreSQL resolution remains a child +persistence responsibility after the canonical service owner lands. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + +_RESOURCE_KIND = "validation_result_nonverifiability" +_OPERATION = "read" +_VERIFICATION_STATUS = "not_verifiable" +_FAILED_REFERENCE_KIND_BY_EVIDENCE_KIND = { + "analysis_weight_receipt": "analysis_weight_receipt", + "weight_variance_compatibility_receipt": "weight_variance_compatibility_receipt", + "variance_design_receipt": "variance_design_receipt", +} +_FAILURE_MODES = frozenset({"missing", "non_reproducible"}) +_READ_FIELDS = frozenset( + { + "result_reference", + "result_digest", + "verification_status", + "failed_evidence_kind", + "failure_mode", + "failed_evidence_reference", + "failed_evidence_digest", + "verification_attempt_reference", + "verification_attempt_digest", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "evaluated_at", + "released_at", + } +) + + +class ValidationResultNonVerifiabilityNotFound(LookupError): + """Indicate that no released owner outcome corroborates the requested failure.""" + + +class ValidationResultNonVerifiabilityIntegrityError(RuntimeError): + """Indicate that released owner outcome evidence is inconsistent or malformed.""" + + +def _require_failed_evidence_kind(value: object) -> str: + """Require one supported scientific evidence family.""" + if type(value) is not str or value not in _FAILED_REFERENCE_KIND_BY_EVIDENCE_KIND: + raise ValueError( + "failed_evidence_kind must be analysis_weight_receipt, " + "weight_variance_compatibility_receipt, or variance_design_receipt." + ) + return value + + +def _require_failure_mode(value: object) -> str: + """Require a missing or non-reproducible evidence outcome.""" + if type(value) is not str or value not in _FAILURE_MODES: + raise ValueError("failure_mode must be missing or non_reproducible.") + return value + + +class ValidationResultNonVerifiabilityRecord(tuple): + """Immutable owner projection for one released ``not_verifiable`` outcome.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + failed_evidence_kind: str, + failure_mode: str, + failed_evidence_reference: str | None, + failed_evidence_digest: str | None, + verification_attempt_reference: str, + verification_attempt_digest: str, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + evaluated_at: datetime, + released_at: datetime, + ) -> ValidationResultNonVerifiabilityRecord: + """Validate a minimal, reproducible explanation for non-verifiability.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + result_ref = _require_reference( + "result_reference", result_reference, "validation_analysis_result" + ) + result_evidence_digest = _require_digest("result_digest", result_digest) + evidence_kind = _require_failed_evidence_kind(failed_evidence_kind) + mode = _require_failure_mode(failure_mode) + + failed_reference: str | None + failed_digest: str | None + if mode == "missing": + if failed_evidence_reference is not None or failed_evidence_digest is not None: + raise ValueError( + "failed evidence reference and digest must be absent when evidence is missing." + ) + failed_reference = None + failed_digest = None + else: + if failed_evidence_reference is None or failed_evidence_digest is None: + raise ValueError( + "failed evidence reference and digest are required for non_reproducible evidence." + ) + failed_reference = _require_reference( + "failed_evidence_reference", + failed_evidence_reference, + _FAILED_REFERENCE_KIND_BY_EVIDENCE_KIND[evidence_kind], + ) + failed_digest = _require_digest( + "failed_evidence_digest", failed_evidence_digest + ) + + attempt_ref = _require_reference( + "verification_attempt_reference", + verification_attempt_reference, + "validation_evidence_verification_attempt", + ) + attempt_digest = _require_digest( + "verification_attempt_digest", verification_attempt_digest + ) + owner_ref = _require_reference( + "owner_contract_reference", + owner_contract_reference, + "released_owner_contract", + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + + digests = [result_evidence_digest, attempt_digest, owner_digest] + if failed_digest is not None: + digests.append(failed_digest) + if len(set(digests)) != len(digests): + raise ValueError( + "result, failed-evidence, verification-attempt, and owner-contract " + "digests must be distinct when present." + ) + + evaluation_instant = _require_aware_datetime("evaluated_at", evaluated_at) + release_instant = _require_aware_datetime("released_at", released_at) + if evaluation_instant > release_instant: + raise ValueError("evaluated_at cannot be later than released_at.") + + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + result_ref, + result_evidence_digest, + evidence_kind, + mode, + failed_reference, + failed_digest, + attempt_ref, + attempt_digest, + owner_ref, + owner_version, + owner_digest, + evaluation_instant, + release_instant, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def result_reference(self) -> str: + """Return the immutable result reference that failed verification.""" + return self[2] + + @property + def result_digest(self) -> str: + """Return the exact result digest.""" + return self[3] + + @property + def verification_status(self) -> str: + """Return the only state this evidence can authorize.""" + return _VERIFICATION_STATUS + + @property + def failed_evidence_kind(self) -> str: + """Return which required evidence family failed verification.""" + return self[4] + + @property + def failure_mode(self) -> str: + """Return whether required evidence was missing or non-reproducible.""" + return self[5] + + @property + def failed_evidence_reference(self) -> str | None: + """Return the failed evidence reference when a non-reproducible artifact exists.""" + return self[6] + + @property + def failed_evidence_digest(self) -> str | None: + """Return the failed evidence digest when a non-reproducible artifact exists.""" + return self[7] + + @property + def verification_attempt_reference(self) -> str: + """Return the immutable verification-attempt receipt reference.""" + return self[8] + + @property + def verification_attempt_digest(self) -> str: + """Return the immutable verification-attempt receipt digest.""" + return self[9] + + @property + def owner_contract_reference(self) -> str: + """Return the released owner-contract reference.""" + return self[10] + + @property + def owner_contract_version(self) -> int: + """Return the positive released owner-contract version.""" + return self[11] + + @property + def owner_contract_digest(self) -> str: + """Return the immutable released owner-contract digest.""" + return self[12] + + @property + def evaluated_at(self) -> datetime: + """Return when the evidence-verification attempt was evaluated.""" + return self[13] + + @property + def released_at(self) -> datetime: + """Return when this non-verifiability outcome became released evidence.""" + return self[14] + + +class ValidationResultNonVerifiabilityView(tuple): + """Field-minimized non-authorizing outcome issued only after authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> ValidationResultNonVerifiabilityView: + """Reject public construction; only the resolver may issue this view.""" + raise TypeError( + "ValidationResultNonVerifiabilityView is issued only by " + "resolve_validation_result_nonverifiability." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable reason/evidence fields without scientific row values.""" + return self[2] + + +@runtime_checkable +class ValidationResultNonVerifiabilityReadPort(Protocol): + """Owner read contract for released result non-verifiability evidence.""" + + def read_validation_result_nonverifiability( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + failed_evidence_kind: str, + failure_mode: str, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> ValidationResultNonVerifiabilityRecord | None: + """Return matching released failure evidence or ``None`` through an owner ACL.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + ValidationResultNonVerifiabilityReadPort, + "read_validation_result_nonverifiability", +) + + +def resolve_validation_result_nonverifiability( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + failed_evidence_kind: str, + failure_mode: str, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: ValidationResultNonVerifiabilityReadPort, +) -> ValidationResultNonVerifiabilityView: + """Authorize then corroborate one released, explicitly non-authorizing outcome.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static( + type(read_port), "read_validation_result_nonverifiability", None + ) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError( + "read_port must expose a statically callable " + "read_validation_result_nonverifiability." + ) + + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + tenant_id = _restore_operational_uuid("tenant_record_id", tenant_identity) + study_id = _restore_operational_uuid("validity_study_id", study_identity) + result_ref = _require_reference( + "result_reference", result_reference, "validation_analysis_result" + ) + result_evidence_digest = _require_digest("result_digest", result_digest) + evidence_kind = _require_failed_evidence_kind(failed_evidence_kind) + mode = _require_failure_mode(failure_mode) + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=_restore_operational_uuid("tenant_record_id", tenant_identity), + validity_study_id=_restore_operational_uuid("validity_study_id", study_identity), + result_reference=result_ref, + result_digest=result_evidence_digest, + failed_evidence_kind=evidence_kind, + failure_mode=mode, + owner_contract_reference=owner_ref, + owner_contract_version=owner_version, + owner_contract_digest=owner_digest, + ) + if persisted is None: + raise ValidationResultNonVerifiabilityNotFound(str(study_id)) + if type(persisted) is not ValidationResultNonVerifiabilityRecord: + raise ValidationResultNonVerifiabilityIntegrityError( + "owner port returned non-canonical validation-result non-verifiability evidence" + ) + + record = ValidationResultNonVerifiabilityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + result_reference=persisted.result_reference, + result_digest=persisted.result_digest, + failed_evidence_kind=persisted.failed_evidence_kind, + failure_mode=persisted.failure_mode, + failed_evidence_reference=persisted.failed_evidence_reference, + failed_evidence_digest=persisted.failed_evidence_digest, + verification_attempt_reference=persisted.verification_attempt_reference, + verification_attempt_digest=persisted.verification_attempt_digest, + owner_contract_reference=persisted.owner_contract_reference, + owner_contract_version=persisted.owner_contract_version, + owner_contract_digest=persisted.owner_contract_digest, + evaluated_at=persisted.evaluated_at, + released_at=persisted.released_at, + ) + requested_identity = ( + tenant_identity, + study_identity, + result_ref, + result_evidence_digest, + evidence_kind, + mode, + owner_ref, + owner_version, + owner_digest, + ) + record_identity = ( + _store_operational_uuid("record tenant_record_id", record.tenant_record_id), + _store_operational_uuid("record validity_study_id", record.validity_study_id), + record.result_reference, + record.result_digest, + record.failed_evidence_kind, + record.failure_mode, + record.owner_contract_reference, + record.owner_contract_version, + record.owner_contract_digest, + ) + if record_identity != requested_identity: + raise ValidationResultNonVerifiabilityIntegrityError( + "owner evidence does not match the requested non-verifiability outcome" + ) + if use_instant < record.released_at: + raise ValidationResultNonVerifiabilityIntegrityError( + "validation-result non-verifiability cannot be used before its release instant" + ) + + values = { + "result_reference": record.result_reference, + "result_digest": record.result_digest, + "verification_status": record.verification_status, + "failed_evidence_kind": record.failed_evidence_kind, + "failure_mode": record.failure_mode, + "failed_evidence_reference": record.failed_evidence_reference, + "failed_evidence_digest": record.failed_evidence_digest, + "verification_attempt_reference": record.verification_attempt_reference, + "verification_attempt_digest": record.verification_attempt_digest, + "owner_contract_reference": record.owner_contract_reference, + "owner_contract_version": record.owner_contract_version, + "owner_contract_digest": record.owner_contract_digest, + "evaluated_at": record.evaluated_at, + "released_at": record.released_at, + } + fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) + return tuple.__new__( + ValidationResultNonVerifiabilityView, + (tenant_identity, study_identity, fields), + ) From 8ddbbc608b61328f349cd5d64f3bda449e521805 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 16:32:38 +0900 Subject: [PATCH 104/603] feat(workforce-validation): export non-verifiability contract --- .../orgmetra_workforce_validation_api/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index 173fb1eae..b54771442 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -25,6 +25,14 @@ ValidationResultAuthorityView, resolve_validation_result_authority, ) +from orgmetra_workforce_validation_api.result_nonverifiability import ( + ValidationResultNonVerifiabilityIntegrityError, + ValidationResultNonVerifiabilityNotFound, + ValidationResultNonVerifiabilityReadPort, + ValidationResultNonVerifiabilityRecord, + ValidationResultNonVerifiabilityView, + resolve_validation_result_nonverifiability, +) from orgmetra_workforce_validation_api.scientific_authority import ( CalibrationAuxiliaryAuthorityIntegrityError, CalibrationAuxiliaryAuthorityNotFound, @@ -59,6 +67,11 @@ "ValidationResultAuthorityReadPort", "ValidationResultAuthorityRecord", "ValidationResultAuthorityView", + "ValidationResultNonVerifiabilityIntegrityError", + "ValidationResultNonVerifiabilityNotFound", + "ValidationResultNonVerifiabilityReadPort", + "ValidationResultNonVerifiabilityRecord", + "ValidationResultNonVerifiabilityView", "ValidityStudyIntegrityError", "ValidityStudyNotFound", "ValidityStudyReadPort", @@ -73,5 +86,6 @@ "resolve_calibration_auxiliary_authority", "resolve_calibration_benchmark_authority", "resolve_validation_result_authority", + "resolve_validation_result_nonverifiability", "resolve_weight_variance_authority", ] From f18c7941af5271a96345b4505001fe44f9eacbd3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 16:33:32 +0900 Subject: [PATCH 105/603] test(workforce-validation): cover minimized non-verifiability view --- .../tests/test_validation_result_nonverifiability.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py index 6d75ea213..53a41b49c 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py @@ -178,6 +178,8 @@ def test_missing_final_weight_evidence_is_released_as_not_verifiable() -> None: OWNER_DIGEST, ) ] + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY fields = dict(view.fields) assert fields["verification_status"] == "not_verifiable" assert fields["failed_evidence_kind"] == "analysis_weight_receipt" From 190dbc99a6b072b6f147a01cbf99623fcb136c9b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 16:38:23 +0900 Subject: [PATCH 106/603] docs(workforce-validation): document non-verifiability boundary --- services/workforce-validation-api/README.md | 149 +++++++++++--------- 1 file changed, 86 insertions(+), 63 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index a4f00a66b..4d6439766 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -1,84 +1,107 @@ # Orgmetra Workforce Validation API -This package is the application boundary for the `workforce_validation` bounded context. The current slice exposes purpose-bound owner reads for the existing validity-study registry header, value-minimized scientific auxiliary-use authority, released calibration-benchmark authority, point-weight/variance-design compatibility authority, and released validation-result binding while establishing the context-local PostgreSQL ownership bootstrap. +This package is the canonical application boundary for the `workforce_validation` bounded context. It owns purpose-bound validation-study reads and scientific-evidence corroboration without copying People, Talent Acquisition, Performance Management, Job Architecture, Psychometrics Commons, fast-mlsirm, TEPP, or another bounded context's application tables. -It does **not** query People, Talent Acquisition, Performance Management, Job Architecture, Psychometrics Commons, fast-mlsirm, TEPP, or another bounded context's application tables. Those contexts remain separate owners. Exact foreign identifiers and immutable specialist/scientific evidence cross this boundary only through released/versioned contracts and owner ports. +Foreign domain truth crosses this boundary only through released/versioned contracts, opaque references, immutable evidence digests, and owner ports. Mutable `validity-analysis` source is not a runtime or source dependency of this service. -## Current slice +## Boundary invariants -`read_validity_study(...)`: +- Keyverse identity is consumed as structurally immutable authenticated identity attributes, never credentials. +- Authorization is evaluated before an owner read. +- Repository capabilities are checked with inert static lookup; inherited Protocol placeholders and executable descriptors are not accepted as owner implementations. +- Tenant/study UUID identities are detached to exact integer payloads and reconstructed at public boundaries so retained UUID aliases cannot rewrite accepted authority. +- Owner evidence is reconstructed into exact tuple-backed records before comparison or projection. +- Returned views are field-minimized corroborating data. Their public constructors fail closed, and a view is not a reusable authorization credential. +- Cross-context SQL, mutable branch dependencies, row-level statistical weights, replicate vectors, protected attributes, and foreign application-table values do not cross this application boundary. -- accepts structurally immutable authenticated Keyverse identity attributes, not credentials; -- reconstructs and revalidates principal storage before building the access request, so exact tuple type alone is not treated as identity authority; -- requires both exact `UUID` outer type and exact built-in integer UUID payload before any sentinel/range comparison, so a forged exact UUID with executable internal storage is rejected without invoking caller-defined equality behavior; -- stores UUID identity evidence behind the tuple-backed principal/record/view as exact integer payloads and reconstructs fresh UUID objects at public boundaries, so a retained UUID reference cannot rewrite accepted tenant/study/criterion identity through `object.__setattr__`; -- preserves tenant/study authorization targets as immutable integer snapshots across the executable repository call, so a repository cannot make a foreign record self-consistent by mutating the UUID objects it receives; -- inertly verifies that the owner repository exposes a statically callable `read_validity_study` capability before authorization, without executing caller-controlled descriptors; -- evaluates tenant, purpose, operation, scope, resource, and requested fields before persistence; -- calls only a `ValidityStudyReadPort` owned by this context; -- reconstructs persisted registry scalars into structurally immutable owner evidence before target validation and output; -- returns only the fields authorized for the exact study record; UUID-valued projected fields are reconstituted fresh rather than exposing mutable internal UUID aliases; -- issues `ValidityStudyView` only from the authorized read path. Its public constructor fails closed, and the returned tuple-backed projection cannot be rewritten through ordinary assignment or `object.__setattr__`. +## Validity-study registry -`ValidityStudyView` is a data projection, not a durable authorization credential or cryptographic capability. Downstream consequential actions must perform their own purpose-bound authorization and authoritative re-resolution rather than treating the Python runtime type as reusable authority. Low-level interpreter construction is outside the supported public API and is not accepted as proof that authorization occurred. +`read_validity_study(...)` authorizes the exact tenant/study/purpose/operation/field request, then reads through `ValidityStudyReadPort`. Persisted registry evidence is reconstructed before tenant/study validation and only authorized fields are returned. -`resolve_calibration_auxiliary_authority(...)` is an executable owner-side slice for #407's durable scientific-evidence resolution gap. It does **not** import or copy the mutable validity-analysis implementation. Instead it defines the `workforce_validation` application contract that a later durable adapter must satisfy: +`ValidityStudyView` is a minimized projection. Downstream consequential actions must perform their own purpose-bound authorization and authoritative re-resolution. -- authorize the exact tenant/study scientific read before invoking the owner port; -- carry only opaque projection/purpose/owner/authorization/scientific-use references, SHA-256 evidence digests, immutable projection/contract versions, the owner-resolved scientific-use instant, and authorization time bounds—never calibration source attributes, protected characteristics, benchmark values, or row-level weights; -- require the exact purpose-limited auxiliary projection reference/version/digest rather than allowing a projection identity to float behind a digest or reference alone; -- require a released-owner-contract reference/version and corroborating owner-contract digest rather than treating a caller-supplied version label as release authority; -- require an immutable scientific-use receipt digest in the lookup and reconstruct the corresponding owner record, so a caller cannot choose a convenient historical `used_at` merely to fit a stale authorization interval; -- require the caller's exact `used_at` coordinate to equal the owner-resolved `scientific_use_at`, while the record itself requires that instant to fall inside the owner-resolved authorization interval; -- resolve through one statically captured `CalibrationAuxiliaryAuthorityReadPort` capability and reject inherited Protocol placeholders or descriptors before authorization; -- reconstruct the returned evidence into an exact tuple-backed `CalibrationAuxiliaryAuthorityRecord` and require tenant, study, projection reference/version/digest, scientific purpose, released owner contract, authorization receipt, scientific-use receipt, and use time to match the requested coordinates; -- issue only a minimized `CalibrationAuxiliaryAuthorityView`. The view is corroborating data, not a reusable authorization credential or proof that an arbitrary injected port is a production owner. +## Calibration auxiliary authority -`resolve_calibration_benchmark_authority(...)` addresses #407 RED #5 at the canonical service boundary. The scientific leaf carries benchmark receipt reference/version/digest, released benchmark-owner contract reference/version/digest, and benchmark reference time; this resolver requires an owner port to corroborate those exact coordinates rather than accepting the leaf tuple as authority. It: +`resolve_calibration_auxiliary_authority(...)` corroborates #407's purpose-limited calibration input without copying protected source attributes. It binds: -- authorizes the exact tenant/study read before any owner resolution and rejects inherited Protocol placeholders or descriptors as concrete repository capabilities; -- verifies the calibration-benchmark receipt and its released owner contract through opaque references, positive versions, SHA-256 digests, and the exact benchmark reference instant; -- obtains `benchmark_receipt_released_at` and `owner_contract_released_at` from owner evidence rather than from the caller, and rejects scientific use that predates either release or the benchmark reference instant; -- requires the referenced owner contract to have been released no later than the benchmark receipt itself, so a receipt cannot retroactively claim authority from a contract that did not yet exist when the receipt became released evidence; -- resolves append-only benchmark correction lineage from the owner: a superseded receipt carries a complete successor receipt reference/version/digest plus its owner-resolved release instant, the successor version must advance, and the successor digest must identify new evidence; -- requires the successor receipt to be released after its predecessor and no later than the predecessor's supersession instant, so correction lineage cannot point to unavailable future evidence or reverse version chronology; -- treats each benchmark receipt as authoritative only on its owner-resolved half-open interval `[benchmark_receipt_released_at, benchmark_receipt_superseded_at)`. Historical use before a later correction remains reproducible, while use at or after supersession fails closed; -- keeps supersession/successor coordinates inside the authority check rather than expanding the public projection. The caller receives only the minimized benchmark evidence it requested, not correction-ledger internals; -- reconstructs returned evidence into an exact tuple-backed `CalibrationBenchmarkAuthorityRecord` and fails closed on any tenant, study, receipt, owner-contract, digest, version, or reference-time mismatch; -- returns only a minimized `CalibrationBenchmarkAuthorityView`; benchmark totals, protected auxiliary values, row-level weights, and foreign application-table values do not cross this boundary. +- auxiliary authority reference; +- auxiliary projection reference/version/digest; +- scientific-use purpose reference/digest; +- released owner-contract reference/version/digest; +- authorization receipt reference/digest and owner-resolved authorization interval; +- scientific-use receipt reference/digest and owner-resolved scientific-use instant. -`resolve_weight_variance_authority(...)` closes a separate #406/#407 application false-GREEN: a scientific leaf can prove internally that a point-weight receipt and variance receipt have compatible digests, yet a durable service must not treat those caller-supplied coordinates as owner authority. This resolver therefore: +Caller `used_at` must equal the owner-resolved scientific-use instant, and that instant must fall inside the owner-resolved authorization interval. -- authorizes the exact tenant/study scientific read before invoking one statically captured `WeightVarianceAuthorityReadPort`, rejecting inherited Protocol placeholders and descriptors; -- binds the released #405 sampling receipt reference/version/digest to the final analysis-weight receipt digest and the separate #406 variance-design receipt reference/version/digest; -- mirrors the active scientific compatibility contract's decisive basis: exact analytic-case occurrence set, weight-eligibility receipt, integer correction sequence, and final point-weight artifact; -- requires a controlled variance method reference/version, a controlled evidence mode (`joint_inclusion`, `reproducible_design_algorithm`, `replicate_weights`, or explicit `approximation`), and exact-versus-approximate semantics; an approximation cannot be labelled exact; -- rejects a variance-design receipt digest that aliases the final point-weight receipt digest; -- requires a released owner-contract reference/version/digest and owner-resolved `released_at`, rejecting use before that release instant; -- reconstructs owner evidence into an exact tuple-backed `WeightVarianceAuthorityRecord` and fails closed if any requested scientific coordinate differs from the owner projection; -- returns only a minimized `WeightVarianceAuthorityView`. It never copies row-level point weights, replicate vectors, frame/cluster/stratum variables, protected characteristics, or foreign application-table values. +## Calibration benchmark authority -`resolve_validation_result_authority(...)` closes the next #407 result-binding gap. The scientific leaf's canonical result serializes a digest of the exact `WeightVarianceCompatibilityReceipt`, but point/variance corroboration alone does not prove which compatibility receipt one released result actually bound. The result resolver therefore: +`resolve_calibration_benchmark_authority(...)` corroborates the benchmark tuple used by a calibration receipt: -- authorizes the exact tenant/study scientific read before invoking one statically captured `ValidationResultAuthorityReadPort`; -- binds the immutable validation-result reference/digest to the exact compatibility-receipt reference/digest and, independently, the final analysis-weight and variance-design receipt digests; -- requires those four evidence digests to be distinct so a result, compatibility receipt, point-weight receipt, and variance receipt cannot alias one another; -- preserves only the scientific leaf's non-authorizing verification states: `verification_pending` and `not_verifiable`. A caller or owner port cannot promote convergence to `verified` at this boundary; -- requires an exact released owner-contract reference/version/digest and owner-resolved release instant, rejecting use before release; -- passes every caller coordinate into the owner lookup, reconstructs the returned tuple-backed record, then exact-matches tenant, study, result, compatibility, point-weight, variance, status, and owner-contract coordinates before issuing a view; -- returns only a minimized `ValidationResultAuthorityView`. Effect estimates, uncertainty values, row-level weights, replicate vectors, protected attributes, and foreign application-table values do not cross this owner-corroboration boundary. +- benchmark receipt reference/version/digest; +- released benchmark-owner contract reference/version/digest; +- benchmark reference instant and owner-resolved release instants; +- append-only predecessor/successor correction lineage when a benchmark is superseded. -These application contracts do **not** complete #407 and do not make an arbitrary injected Python port durable scientific authority. The current branch has no durable scientific-authority relation or released auxiliary/benchmark/variance/result-evidence adapter. After the canonical owner persistence path is protected truth, #248 or its verified successor must implement schema-qualified least-privilege durable ports and prove that resolved owner evidence is itself released/versioned, append-only where corrected, purpose-authorized, and result-bound. Mutable #57 source is not a runtime or source dependency of this service; its active compatibility, benchmark, and result contracts were used only to align the application boundary's evidence coordinates. +The owner contract must already be released when the benchmark receipt becomes released evidence. A successor must advance the version, identify new evidence, be released after its predecessor, and exist no later than the predecessor's supersession instant. A predecessor is authoritative only on its owner-resolved half-open interval `[benchmark_receipt_released_at, benchmark_receipt_superseded_at)`. -`services/workforce-validation-api/database/migrations/0001_owner_schema.sql` starts this bounded context's own migration history. It creates the `workforce_validation` schema and deny-default `workforce_validation_role`, revokes public schema access, and intentionally creates or moves no application table yet. The role is a **NOLOGIN migration/schema owner only**; runtime principals must not be granted that owner role. PostgreSQL applies role-level configuration defaults at login and does not re-apply them on `SET ROLE`, so an `ALTER ROLE ... SET search_path` entry on this NOLOGIN role is not treated as a runtime isolation control. The later durable adapter must use a distinct least-privilege runtime role, schema-qualified `workforce_validation` relations, and explicit function-level `search_path` where `SECURITY DEFINER` code is introduced. +## Point-weight / variance authority -Protected foundation migrations still create validity-study tables in the legacy foundation schema, so the next forward-only persistence increment must adopt those records without normalizing `public.validity_study` as a long-lived service contract or breaking existing linkage evidence. +`resolve_weight_variance_authority(...)` corroborates point-estimation and variance evidence without treating leaf-provided digests as owner authority. It binds: -Issue #234 owns the remaining order: durable owner-schema adoption and PostgreSQL adapter, idempotent registration, explicit predictor/sample/decision-policy/analysis-protocol versions, scientific adapters, OpenAPI/gateway exposure, and realistic p95 measurement. Issues #236–#244 retain the current bootstrap trust-boundary findings through exact-head acceptance and protected integration: persisted-record immutability, principal immutability and constructor revalidation, owner-role/runtime-role separation, inert repository-capability validation, immutable minimized output, non-public issuance of that output, detached UUID storage/target snapshots, and exact validation of UUID internal payloads before comparison. Issue #407 additionally keeps durable scientific-authority resolution open until owner persistence/released evidence, exact result-to-weight/variance binding, exact-head GREEN, independent review, and protected integration are real. +- released #405 sampling receipt reference/version/digest; +- final analysis-weight receipt digest; +- exact analytic-case occurrence set; +- weight-eligibility receipt digest; +- integer correction sequence; +- final point-weight artifact digest; +- distinct #406 variance-design receipt reference/version/digest; +- controlled variance method/version, evidence mode, and exact/approximate semantics; +- released owner-contract reference/version/digest and owner-resolved release instant. -## Test +A variance receipt cannot alias the point-weight receipt, and an approximation cannot be represented as exact evidence. -The Draft branch is admitted to the canonical Foundation quality workflow with the same hash-locked test toolchain and direct source-tree dependency policy used by the existing owner services: +## Released validation-result authority + +`resolve_validation_result_authority(...)` binds one immutable validation result to the exact weight/variance evidence it claims to use. It requires: + +- result reference/digest; +- exact `WeightVarianceCompatibilityReceipt` reference/digest; +- final analysis-weight receipt digest; +- separate variance-design receipt digest; +- non-authorizing `verification_pending | not_verifiable` state; +- released owner-contract reference/version/digest and owner-resolved release instant. + +Result, compatibility, point-weight, and variance digests must be pairwise distinct. Numerical convergence cannot be promoted to `verified` at this boundary. + +## Released non-verifiability outcome + +`resolve_validation_result_nonverifiability(...)` is the application repair for #407 RED #12. The ordinary result-authority contract requires exact compatibility/point-weight/variance digests, so it cannot represent the case where required evidence itself is missing or cannot be reproduced. This separate contract makes that failure explicit and non-authorizing instead of allowing callers to treat lookup failure as scientific GREEN. + +`ValidationResultNonVerifiabilityRecord` fixes `verification_status` to `not_verifiable` and records exactly one failed evidence family: + +- `analysis_weight_receipt`; +- `weight_variance_compatibility_receipt`; or +- `variance_design_receipt`. + +`failure_mode` is `missing` or `non_reproducible`. + +For `missing`, failed-evidence reference/digest must both be absent; the service does not fabricate an opaque identity for evidence that does not exist. For `non_reproducible`, the exact typed failed-evidence reference and digest are required. Every released outcome additionally binds an immutable `validation_evidence_verification_attempt` reference/digest, released owner-contract reference/version/digest, `evaluated_at`, and `released_at`. Result, failed-evidence when present, verification-attempt, and owner-contract digests must be distinct. Evaluation may not occur after release, and the outcome cannot be consumed before release. + +Authorization occurs before `ValidationResultNonVerifiabilityReadPort` resolution. Returned `ValidationResultNonVerifiabilityView` contains only the minimized reason/provenance tuple; effect estimates, uncertainty values, row-level weights, replicate vectors, protected attributes, and foreign application data are excluded. + +This is still application-boundary corroboration, not durable scientific authority. A later owner persistence adapter must establish missing/non-reproducible evidence from released owner/verification-attempt evidence rather than from cross-context SQL, missing joins, or swallowed exceptions. + +## Persistence state + +`services/workforce-validation-api/database/migrations/0001_owner_schema.sql` starts this bounded context's migration history. It creates the `workforce_validation` schema and a deny-default `workforce_validation_role`, revokes public schema access, and intentionally creates or moves no application table yet. + +The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. + +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, point-weight/variance, validation-result binding, and validation-result non-verifiability. + +## Test contract + +The service is admitted to the canonical Foundation quality workflow with a 100% owned statement and branch threshold: ```bash PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ @@ -87,8 +110,8 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ services/workforce-validation-api/tests ``` -The service package keeps an exact 100% owned statement/branch threshold. Calibration-authority coverage exercises authorization-before-owner-read, non-concrete/dynamic owner capabilities, malformed references/digests/versions/timestamps, projection-version mismatch, foreign/mismatched owner evidence, caller/owner scientific-use-time mismatch, authorization-window mismatch, UUID alias mutation, structural immutability, and non-public view issuance. Calibration-benchmark coverage additionally exercises exact receipt/owner-contract coordinate mismatch, owner-resolved release-time enforcement, owner-contract-before-receipt chronology, future-reference rejection, append-only supersession completeness and monotonicity, successor release ordering, historical pre-supersession use, rejection at/after supersession, malformed references/digests/versions/timestamps, foreign tenant/study evidence, detached UUID views, structural immutability, and non-public output issuance. Weight/variance-authority coverage exercises every owner-coordinate mismatch, point/variance evidence aliasing, unsupported evidence modes and semantics, approximation-labelled-as-exact, pre-release use, foreign tenant/study evidence, integer correction-sequence mismatches, detached UUID views, and non-public output issuance. Result-authority coverage adds exact result/compatibility/point-weight/variance tuple lookup, digest-alias rejection, non-authorizing status enforcement, authorization-before-owner-read, non-concrete capability rejection, owner-coordinate mismatch, pre-release use, cross-tenant evidence rejection, structural immutability, and non-public output issuance. +`tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -The same Foundation job also runs `tests/test_workforce_validation_owner_schema_postgres.sh` in its own pinned PostgreSQL 16.14 container. That contract executes the service-local owner migration and checks the exact deny-default role flags, schema owner, absence of ineffective login-only `rolconfig`, actual `SET ROLE` search-path behavior, absence of inherited PUBLIC `USAGE`/`CREATE`, and absence of application relations in the bootstrap schema. The test intentionally demonstrates that `SET ROLE` retains the caller's existing `search_path`; runtime isolation therefore cannot be inferred from owner-role metadata. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, point/variance evidence compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. -Those source contracts are not terminal acceptance by themselves. The slice remains Draft until the exact current head actually executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and the normal review/governance requirements are satisfied. Only then may the next forward-only owner-table adoption and durable adapter be treated as eligible for integration. +These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From 18d46fd75707727364fd97dfc1adbee80ed55d32 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 17:04:39 +0900 Subject: [PATCH 107/603] test(workforce-validation): require released calibration adjustment authority --- .../test_calibration_adjustment_authority.py | 387 ++++++++++++++++++ 1 file changed, 387 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_adjustment_authority.py diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py b/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py new file mode 100644 index 000000000..78995a6e2 --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py @@ -0,0 +1,387 @@ +"""Fail-closed contract for released typed calibration-adjustment authority.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.calibration_adjustment_authority import ( + CalibrationAdjustmentAuthorityIntegrityError, + CalibrationAdjustmentAuthorityNotFound, + CalibrationAdjustmentAuthorityReadPort, + CalibrationAdjustmentAuthorityRecord, + CalibrationAdjustmentAuthorityView, + resolve_calibration_adjustment_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000d2") +RECEIPT_REFERENCE = "calibration_adjustment_receipt:11111111-1111-4111-8111-111111111111" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +RECEIPT_DIGEST = "1" * 64 +AUXILIARY_PROJECTION_DIGEST = "2" * 64 +BENCHMARK_RECEIPT_DIGEST = "3" * 64 +CONSTRAINTS_DIGEST = "4" * 64 +INPUT_WEIGHT_DIGEST = "5" * 64 +OUTPUT_WEIGHT_DIGEST = "6" * 64 +FALLBACK_RULE_DIGEST = "7" * 64 +FALLBACK_CONFIGURATION_DIGEST = "8" * 64 +OWNER_CONTRACT_DIGEST = "9" * 64 +CONSTRUCTED_AT = datetime(2026, 9, 16, 12, 0, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "calibration_receipt_reference", + "calibration_receipt_digest", + "evidence_version", + "auxiliary_projection_digest", + "benchmark_receipt_digest", + "algorithm_reference", + "algorithm_version", + "constraints_digest", + "termination_code", + "input_weight_artifact_digest", + "output_weight_artifact_digest", + "constructed_at", + "fallback_reason_code", + "fallback_rule_reference", + "fallback_rule_digest", + "fallback_algorithm_reference", + "fallback_algorithm_version", + "fallback_configuration_digest", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "released_at", + } +) + + +class _ReadPort: + """Return configured calibration authority and retain lookup coordinates.""" + + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[dict[str, object]] = [] + + def read_calibration_adjustment_authority(self, **coordinates: object) -> object: + """Capture the owner lookup and return configured evidence.""" + self.calls.append(dict(coordinates)) + return self.result + + +class _NoReadMethod: + """Deliberately fail the owner-port protocol.""" + + +class _ProtocolOnly(CalibrationAdjustmentAuthorityReadPort): + """Inherit only the Protocol placeholder, not a concrete owner capability.""" + + +class _DescriptorReadPort: + """Expose a descriptor that must be rejected without executing it.""" + + @property + def read_calibration_adjustment_authority(self) -> object: + raise AssertionError("descriptor must not execute") + + +def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=tenant_record_id, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="calibration-adjustment-authority-read-v1", + resource_kind="calibration_adjustment_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _fallback_values() -> dict[str, object]: + return { + "termination_code": "fallback_applied", + "fallback_reason_code": "primary_nonconvergence", + "fallback_rule_reference": "calibration_fallback_rule:cell-collapse-v2", + "fallback_rule_digest": FALLBACK_RULE_DIGEST, + "fallback_algorithm_reference": "calibration_algorithm:raking", + "fallback_algorithm_version": 4, + "fallback_configuration_digest": FALLBACK_CONFIGURATION_DIGEST, + } + + +def _record(**overrides: object) -> CalibrationAdjustmentAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "calibration_receipt_reference": RECEIPT_REFERENCE, + "calibration_receipt_digest": RECEIPT_DIGEST, + "evidence_version": 1, + "auxiliary_projection_digest": AUXILIARY_PROJECTION_DIGEST, + "benchmark_receipt_digest": BENCHMARK_RECEIPT_DIGEST, + "algorithm_reference": "calibration_algorithm:generalized_regression", + "algorithm_version": 3, + "constraints_digest": CONSTRAINTS_DIGEST, + "termination_code": "converged", + "input_weight_artifact_digest": INPUT_WEIGHT_DIGEST, + "output_weight_artifact_digest": OUTPUT_WEIGHT_DIGEST, + "constructed_at": CONSTRUCTED_AT, + "fallback_reason_code": None, + "fallback_rule_reference": None, + "fallback_rule_digest": None, + "fallback_algorithm_reference": None, + "fallback_algorithm_version": None, + "fallback_configuration_digest": None, + "owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "owner_contract_version": 6, + "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "released_at": RELEASED_AT, + } + values.update(overrides) + return CalibrationAdjustmentAuthorityRecord(**values) + + +def _resolve(*, read_port: object, **overrides: object) -> CalibrationAdjustmentAuthorityView: + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "calibration_receipt_reference": RECEIPT_REFERENCE, + "calibration_receipt_digest": RECEIPT_DIGEST, + "evidence_version": 1, + "auxiliary_projection_digest": AUXILIARY_PROJECTION_DIGEST, + "benchmark_receipt_digest": BENCHMARK_RECEIPT_DIGEST, + "algorithm_reference": "calibration_algorithm:generalized_regression", + "algorithm_version": 3, + "constraints_digest": CONSTRAINTS_DIGEST, + "termination_code": "converged", + "input_weight_artifact_digest": INPUT_WEIGHT_DIGEST, + "output_weight_artifact_digest": OUTPUT_WEIGHT_DIGEST, + "constructed_at": CONSTRUCTED_AT, + "fallback_reason_code": None, + "fallback_rule_reference": None, + "fallback_rule_digest": None, + "fallback_algorithm_reference": None, + "fallback_algorithm_version": None, + "fallback_configuration_digest": None, + "owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "owner_contract_version": 6, + "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_calibration_adjustment_authority(**values) + + +def test_fallback_resolution_binds_actual_generating_method() -> None: + fallback = _fallback_values() + record = _record(**fallback) + port = _ReadPort(record) + + view = _resolve(read_port=port, **fallback) + + assert isinstance(port, CalibrationAdjustmentAuthorityReadPort) + assert len(port.calls) == 1 + assert port.calls[0]["calibration_receipt_digest"] == RECEIPT_DIGEST + assert port.calls[0]["fallback_algorithm_reference"] == "calibration_algorithm:raking" + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + assert ("termination_code", "fallback_applied") in view.fields + assert ("fallback_reason_code", "primary_nonconvergence") in view.fields + assert ("fallback_rule_reference", "calibration_fallback_rule:cell-collapse-v2") in view.fields + assert ("fallback_algorithm_reference", "calibration_algorithm:raking") in view.fields + assert ("fallback_algorithm_version", 4) in view.fields + assert ("fallback_configuration_digest", FALLBACK_CONFIGURATION_DIGEST) in view.fields + + +def test_converged_resolution_omits_fallback_only_projection() -> None: + view = _resolve(read_port=_ReadPort(_record())) + + assert ("termination_code", "converged") in view.fields + assert all(not field.startswith("fallback_") for field, _ in view.fields) + + +def test_authorization_denial_happens_before_owner_resolution() -> None: + port = _ReadPort(_record()) + + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, policy=_policy(purpose_code="audit_review")) + + assert port.calls == [] + + +def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: + with pytest.raises(CalibrationAdjustmentAuthorityNotFound): + _resolve(read_port=_ReadPort(None)) + + with pytest.raises(CalibrationAdjustmentAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object())) + + +@pytest.mark.parametrize( + "record_overrides", + [ + {"tenant_record_id": OTHER_TENANT}, + {"validity_study_id": OTHER_STUDY}, + {"calibration_receipt_digest": "a" * 64}, + {"auxiliary_projection_digest": "b" * 64}, + {"benchmark_receipt_digest": "c" * 64}, + {"algorithm_reference": "calibration_algorithm:raking"}, + {"algorithm_version": 9}, + {"constraints_digest": "d" * 64}, + {"input_weight_artifact_digest": "e" * 64}, + {"output_weight_artifact_digest": "f" * 64}, + {"owner_contract_version": 7}, + {"owner_contract_digest": "0" * 64}, + ], +) +def test_owner_evidence_must_match_every_requested_coordinate( + record_overrides: dict[str, object] +) -> None: + with pytest.raises(CalibrationAdjustmentAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(**record_overrides))) + + +def test_owner_evidence_must_be_released_before_scientific_use() -> None: + with pytest.raises(CalibrationAdjustmentAuthorityIntegrityError): + _resolve( + read_port=_ReadPort(_record(released_at=USED_AT + timedelta(seconds=1))) + ) + + +@pytest.mark.parametrize( + "missing_field", + [ + "fallback_reason_code", + "fallback_rule_reference", + "fallback_rule_digest", + "fallback_algorithm_reference", + "fallback_algorithm_version", + "fallback_configuration_digest", + ], +) +def test_fallback_requires_complete_actual_method_provenance(missing_field: str) -> None: + fallback = _fallback_values() + fallback[missing_field] = None + with pytest.raises(ValueError): + _record(**fallback) + + +def test_converged_receipt_rejects_fallback_only_evidence() -> None: + with pytest.raises(ValueError): + _record(fallback_reason_code="should_not_exist") + + +@pytest.mark.parametrize( + ("key", "value"), + [ + ("evidence_version", 2), + ("termination_code", "nonconverged"), + ("algorithm_reference", "wrong:method"), + ("algorithm_version", True), + ("fallback_reason_code", "Primary Failure"), + ("fallback_rule_reference", "wrong:rule"), + ("fallback_rule_digest", "7" * 63), + ("fallback_algorithm_reference", "wrong:algorithm"), + ("fallback_algorithm_version", 0), + ("fallback_configuration_digest", "8" * 65), + ], +) +def test_malformed_calibration_or_fallback_evidence_fails_closed( + key: str, value: object +) -> None: + overrides = _fallback_values() + overrides[key] = value + with pytest.raises(ValueError): + _record(**overrides) + + +def test_weight_artifact_and_release_chronology_fail_closed() -> None: + with pytest.raises(ValueError): + _record(output_weight_artifact_digest=INPUT_WEIGHT_DIGEST) + + with pytest.raises(ValueError): + _record(released_at=CONSTRUCTED_AT - timedelta(seconds=1)) + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("calibration_receipt_reference", "wrong:receipt", ValueError), + ("calibration_receipt_digest", "ABC", ValueError), + ("evidence_version", False, ValueError), + ("auxiliary_projection_digest", "2" * 63, ValueError), + ("benchmark_receipt_digest", "3" * 65, ValueError), + ("algorithm_reference", "wrong:algorithm", ValueError), + ("algorithm_version", 0, ValueError), + ("constraints_digest", "4" * 63, ValueError), + ("termination_code", "failed", ValueError), + ("constructed_at", datetime(2026, 9, 16, 12, 0), ValueError), + ("owner_contract_reference", "wrong:contract", ValueError), + ("owner_contract_version", 0, ValueError), + ("owner_contract_digest", "9" * 63, ValueError), + ("used_at", datetime(2026, 9, 17), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_or_dependency_fails_before_owner_resolution( + key: str, value: object, error: type[Exception] +) -> None: + port: object = _ReadPort(_record()) + overrides = {key: value} + if key == "read_port": + port = value + overrides = {} + with pytest.raises(error): + _resolve(read_port=port, **overrides) + if isinstance(port, _ReadPort): + assert port.calls == [] + + +def test_record_and_view_are_structurally_immutable_and_uuid_views_are_detached() -> None: + tenant = UUID(str(TENANT)) + record = _record(tenant_record_id=tenant) + object.__setattr__(tenant, "int", OTHER_TENANT.int) + assert record.tenant_record_id == TENANT + + with pytest.raises(AttributeError): + object.__setattr__(record, "termination_code", "fallback_applied") + + view = _resolve(read_port=_ReadPort(record)) + returned_tenant = view.tenant_record_id + object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) + assert view.tenant_record_id == TENANT + + with pytest.raises(AttributeError): + object.__setattr__(view, "fields", ()) + with pytest.raises(TypeError): + CalibrationAdjustmentAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) From dc052c034bf463fdcb8ca1f053e6531e497655bb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 17:05:30 +0900 Subject: [PATCH 108/603] feat(workforce-validation): corroborate typed calibration adjustment evidence --- .../calibration_adjustment_authority.py | 640 ++++++++++++++++++ 1 file changed, 640 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py new file mode 100644 index 000000000..bc6773e45 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py @@ -0,0 +1,640 @@ +"""Corroborate released typed calibration-adjustment evidence through an owner port. + +This application boundary binds the exact calibration receipt that produced a +point-weight artifact to its primary or fallback generating method. It does not +copy auxiliary values, benchmark totals, protected attributes, or row-level +weights. Durable PostgreSQL/release resolution remains a persistence-owner task +after this service reaches protected truth. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + +_RESOURCE_KIND = "calibration_adjustment_authority" +_OPERATION = "read" +_TERMINATION_CODES = frozenset({"converged", "fallback_applied"}) +_READ_FIELDS = frozenset( + { + "calibration_receipt_reference", + "calibration_receipt_digest", + "evidence_version", + "auxiliary_projection_digest", + "benchmark_receipt_digest", + "algorithm_reference", + "algorithm_version", + "constraints_digest", + "termination_code", + "input_weight_artifact_digest", + "output_weight_artifact_digest", + "constructed_at", + "fallback_reason_code", + "fallback_rule_reference", + "fallback_rule_digest", + "fallback_algorithm_reference", + "fallback_algorithm_version", + "fallback_configuration_digest", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "released_at", + } +) + + +class CalibrationAdjustmentAuthorityNotFound(LookupError): + """Indicate that no released owner evidence corroborates the calibration receipt.""" + + +class CalibrationAdjustmentAuthorityIntegrityError(RuntimeError): + """Indicate that owner evidence cannot corroborate the requested calibration.""" + + +def _require_termination_code(value: object) -> str: + """Require an explicit successful-primary or explicit-fallback outcome.""" + if type(value) is not str or value not in _TERMINATION_CODES: + raise ValueError("termination_code must be converged or fallback_applied.") + return value + + +class CalibrationAdjustmentAuthorityRecord(tuple): + """Immutable owner projection for one released typed calibration receipt.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + calibration_receipt_reference: str, + calibration_receipt_digest: str, + evidence_version: int, + auxiliary_projection_digest: str, + benchmark_receipt_digest: str, + algorithm_reference: str, + algorithm_version: int, + constraints_digest: str, + termination_code: str, + input_weight_artifact_digest: str, + output_weight_artifact_digest: str, + constructed_at: datetime, + fallback_reason_code: str | None, + fallback_rule_reference: str | None, + fallback_rule_digest: str | None, + fallback_algorithm_reference: str | None, + fallback_algorithm_version: int | None, + fallback_configuration_digest: str | None, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + released_at: datetime, + ) -> CalibrationAdjustmentAuthorityRecord: + """Validate and detach the minimum receipt-level scientific authority.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + receipt_ref = _require_reference( + "calibration_receipt_reference", + calibration_receipt_reference, + "calibration_adjustment_receipt", + ) + receipt_digest = _require_digest( + "calibration_receipt_digest", calibration_receipt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + projection_digest = _require_digest( + "auxiliary_projection_digest", auxiliary_projection_digest + ) + benchmark_digest = _require_digest( + "benchmark_receipt_digest", benchmark_receipt_digest + ) + algorithm_ref = _require_reference( + "algorithm_reference", algorithm_reference, "calibration_algorithm" + ) + algorithm_ver = _require_positive_integer("algorithm_version", algorithm_version) + constraints = _require_digest("constraints_digest", constraints_digest) + termination = _require_termination_code(termination_code) + input_digest = _require_digest( + "input_weight_artifact_digest", input_weight_artifact_digest + ) + output_digest = _require_digest( + "output_weight_artifact_digest", output_weight_artifact_digest + ) + if input_digest == output_digest: + raise ValueError( + "output_weight_artifact_digest must identify the calibrated weight artifact." + ) + constructed = _require_aware_datetime("constructed_at", constructed_at) + + fallback_values = ( + fallback_reason_code, + fallback_rule_reference, + fallback_rule_digest, + fallback_algorithm_reference, + fallback_algorithm_version, + fallback_configuration_digest, + ) + if termination == "fallback_applied": + if any(value is None for value in fallback_values): + raise ValueError( + "fallback reason, rule, algorithm, version, and configuration evidence " + "are required for fallback_applied." + ) + fallback_reason = _require_code("fallback_reason_code", fallback_reason_code) + fallback_rule_ref = _require_reference( + "fallback_rule_reference", + fallback_rule_reference, + "calibration_fallback_rule", + ) + fallback_rule_evidence = _require_digest( + "fallback_rule_digest", fallback_rule_digest + ) + fallback_algorithm_ref = _require_reference( + "fallback_algorithm_reference", + fallback_algorithm_reference, + "calibration_algorithm", + ) + fallback_algorithm_ver = _require_positive_integer( + "fallback_algorithm_version", fallback_algorithm_version + ) + fallback_configuration = _require_digest( + "fallback_configuration_digest", fallback_configuration_digest + ) + else: + if any(value is not None for value in fallback_values): + raise ValueError("fallback evidence must be absent when calibration converged.") + fallback_reason = None + fallback_rule_ref = None + fallback_rule_evidence = None + fallback_algorithm_ref = None + fallback_algorithm_ver = None + fallback_configuration = None + + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + release_instant = _require_aware_datetime("released_at", released_at) + if release_instant < constructed: + raise ValueError("released_at cannot precede constructed_at.") + + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + receipt_ref, + receipt_digest, + version, + projection_digest, + benchmark_digest, + algorithm_ref, + algorithm_ver, + constraints, + termination, + input_digest, + output_digest, + constructed, + fallback_reason, + fallback_rule_ref, + fallback_rule_evidence, + fallback_algorithm_ref, + fallback_algorithm_ver, + fallback_configuration, + owner_ref, + owner_version, + owner_digest, + release_instant, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity for this released evidence.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity for this released evidence.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def calibration_receipt_reference(self) -> str: + """Return the typed calibration-adjustment receipt reference.""" + return self[2] + + @property + def calibration_receipt_digest(self) -> str: + """Return the exact calibration-adjustment receipt digest.""" + return self[3] + + @property + def evidence_version(self) -> int: + """Return the receipt evidence version.""" + return self[4] + + @property + def auxiliary_projection_digest(self) -> str: + """Return the purpose-limited auxiliary projection digest used by the receipt.""" + return self[5] + + @property + def benchmark_receipt_digest(self) -> str: + """Return the benchmark receipt digest used by the receipt.""" + return self[6] + + @property + def algorithm_reference(self) -> str: + """Return the primary calibration algorithm reference.""" + return self[7] + + @property + def algorithm_version(self) -> int: + """Return the primary calibration algorithm version.""" + return self[8] + + @property + def constraints_digest(self) -> str: + """Return the immutable calibration constraints digest.""" + return self[9] + + @property + def termination_code(self) -> str: + """Return whether the primary method converged or fallback produced weights.""" + return self[10] + + @property + def input_weight_artifact_digest(self) -> str: + """Return the input weight artifact digest.""" + return self[11] + + @property + def output_weight_artifact_digest(self) -> str: + """Return the calibrated output weight artifact digest.""" + return self[12] + + @property + def constructed_at(self) -> datetime: + """Return when the typed calibration receipt was constructed.""" + return self[13] + + @property + def fallback_reason_code(self) -> str | None: + """Return the primary failure reason when fallback produced the weights.""" + return self[14] + + @property + def fallback_rule_reference(self) -> str | None: + """Return the immutable fallback-rule reference when fallback was applied.""" + return self[15] + + @property + def fallback_rule_digest(self) -> str | None: + """Return the immutable fallback-rule digest when fallback was applied.""" + return self[16] + + @property + def fallback_algorithm_reference(self) -> str | None: + """Return the actual algorithm that produced fallback weights.""" + return self[17] + + @property + def fallback_algorithm_version(self) -> int | None: + """Return the actual fallback algorithm version.""" + return self[18] + + @property + def fallback_configuration_digest(self) -> str | None: + """Return the actual fallback configuration digest.""" + return self[19] + + @property + def owner_contract_reference(self) -> str: + """Return the released owner-contract reference.""" + return self[20] + + @property + def owner_contract_version(self) -> int: + """Return the released owner-contract version.""" + return self[21] + + @property + def owner_contract_digest(self) -> str: + """Return the released owner-contract digest.""" + return self[22] + + @property + def released_at(self) -> datetime: + """Return when this typed calibration evidence became released authority.""" + return self[23] + + +class CalibrationAdjustmentAuthorityView(tuple): + """Field-minimized typed calibration evidence issued only after authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> CalibrationAdjustmentAuthorityView: + """Reject direct construction; only the resolver may issue this view.""" + raise TypeError( + "CalibrationAdjustmentAuthorityView is issued only by " + "resolve_calibration_adjustment_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable typed calibration provenance without source values.""" + return self[2] + + +@runtime_checkable +class CalibrationAdjustmentAuthorityReadPort(Protocol): + """Owner read contract for released typed calibration-adjustment evidence.""" + + def read_calibration_adjustment_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + calibration_receipt_reference: str, + calibration_receipt_digest: str, + evidence_version: int, + auxiliary_projection_digest: str, + benchmark_receipt_digest: str, + algorithm_reference: str, + algorithm_version: int, + constraints_digest: str, + termination_code: str, + input_weight_artifact_digest: str, + output_weight_artifact_digest: str, + constructed_at: datetime, + fallback_reason_code: str | None, + fallback_rule_reference: str | None, + fallback_rule_digest: str | None, + fallback_algorithm_reference: str | None, + fallback_algorithm_version: int | None, + fallback_configuration_digest: str | None, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> CalibrationAdjustmentAuthorityRecord | None: + """Return matching released typed calibration evidence or ``None``.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + CalibrationAdjustmentAuthorityReadPort, "read_calibration_adjustment_authority" +) + + +def resolve_calibration_adjustment_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + calibration_receipt_reference: str, + calibration_receipt_digest: str, + evidence_version: int, + auxiliary_projection_digest: str, + benchmark_receipt_digest: str, + algorithm_reference: str, + algorithm_version: int, + constraints_digest: str, + termination_code: str, + input_weight_artifact_digest: str, + output_weight_artifact_digest: str, + constructed_at: datetime, + fallback_reason_code: str | None, + fallback_rule_reference: str | None, + fallback_rule_digest: str | None, + fallback_algorithm_reference: str | None, + fallback_algorithm_version: int | None, + fallback_configuration_digest: str | None, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: CalibrationAdjustmentAuthorityReadPort, +) -> CalibrationAdjustmentAuthorityView: + """Authorize then corroborate the exact released calibration receipt.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static( + type(read_port), "read_calibration_adjustment_authority", None + ) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError( + "read_port must expose a statically callable " + "read_calibration_adjustment_authority." + ) + + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + requested = CalibrationAdjustmentAuthorityRecord( + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + calibration_receipt_reference=calibration_receipt_reference, + calibration_receipt_digest=calibration_receipt_digest, + evidence_version=evidence_version, + auxiliary_projection_digest=auxiliary_projection_digest, + benchmark_receipt_digest=benchmark_receipt_digest, + algorithm_reference=algorithm_reference, + algorithm_version=algorithm_version, + constraints_digest=constraints_digest, + termination_code=termination_code, + input_weight_artifact_digest=input_weight_artifact_digest, + output_weight_artifact_digest=output_weight_artifact_digest, + constructed_at=constructed_at, + fallback_reason_code=fallback_reason_code, + fallback_rule_reference=fallback_rule_reference, + fallback_rule_digest=fallback_rule_digest, + fallback_algorithm_reference=fallback_algorithm_reference, + fallback_algorithm_version=fallback_algorithm_version, + fallback_configuration_digest=fallback_configuration_digest, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + released_at=constructed_at, + ) + tenant_id = requested.tenant_record_id + study_id = requested.validity_study_id + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=requested.tenant_record_id, + validity_study_id=requested.validity_study_id, + calibration_receipt_reference=requested.calibration_receipt_reference, + calibration_receipt_digest=requested.calibration_receipt_digest, + evidence_version=requested.evidence_version, + auxiliary_projection_digest=requested.auxiliary_projection_digest, + benchmark_receipt_digest=requested.benchmark_receipt_digest, + algorithm_reference=requested.algorithm_reference, + algorithm_version=requested.algorithm_version, + constraints_digest=requested.constraints_digest, + termination_code=requested.termination_code, + input_weight_artifact_digest=requested.input_weight_artifact_digest, + output_weight_artifact_digest=requested.output_weight_artifact_digest, + constructed_at=requested.constructed_at, + fallback_reason_code=requested.fallback_reason_code, + fallback_rule_reference=requested.fallback_rule_reference, + fallback_rule_digest=requested.fallback_rule_digest, + fallback_algorithm_reference=requested.fallback_algorithm_reference, + fallback_algorithm_version=requested.fallback_algorithm_version, + fallback_configuration_digest=requested.fallback_configuration_digest, + owner_contract_reference=requested.owner_contract_reference, + owner_contract_version=requested.owner_contract_version, + owner_contract_digest=requested.owner_contract_digest, + ) + if persisted is None: + raise CalibrationAdjustmentAuthorityNotFound(str(study_id)) + if type(persisted) is not CalibrationAdjustmentAuthorityRecord: + raise CalibrationAdjustmentAuthorityIntegrityError( + "owner port returned non-canonical calibration-adjustment authority evidence" + ) + + record = CalibrationAdjustmentAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + calibration_receipt_reference=persisted.calibration_receipt_reference, + calibration_receipt_digest=persisted.calibration_receipt_digest, + evidence_version=persisted.evidence_version, + auxiliary_projection_digest=persisted.auxiliary_projection_digest, + benchmark_receipt_digest=persisted.benchmark_receipt_digest, + algorithm_reference=persisted.algorithm_reference, + algorithm_version=persisted.algorithm_version, + constraints_digest=persisted.constraints_digest, + termination_code=persisted.termination_code, + input_weight_artifact_digest=persisted.input_weight_artifact_digest, + output_weight_artifact_digest=persisted.output_weight_artifact_digest, + constructed_at=persisted.constructed_at, + fallback_reason_code=persisted.fallback_reason_code, + fallback_rule_reference=persisted.fallback_rule_reference, + fallback_rule_digest=persisted.fallback_rule_digest, + fallback_algorithm_reference=persisted.fallback_algorithm_reference, + fallback_algorithm_version=persisted.fallback_algorithm_version, + fallback_configuration_digest=persisted.fallback_configuration_digest, + owner_contract_reference=persisted.owner_contract_reference, + owner_contract_version=persisted.owner_contract_version, + owner_contract_digest=persisted.owner_contract_digest, + released_at=persisted.released_at, + ) + expected = requested[:-1] + observed = record[:-1] + if observed != expected: + raise CalibrationAdjustmentAuthorityIntegrityError( + "released calibration-adjustment authority does not match requested coordinates" + ) + if record.released_at > use_instant: + raise CalibrationAdjustmentAuthorityIntegrityError( + "calibration-adjustment evidence must be released before scientific use" + ) + + fields: tuple[tuple[str, object], ...] = ( + ("algorithm_reference", record.algorithm_reference), + ("algorithm_version", record.algorithm_version), + ("auxiliary_projection_digest", record.auxiliary_projection_digest), + ("benchmark_receipt_digest", record.benchmark_receipt_digest), + ("calibration_receipt_digest", record.calibration_receipt_digest), + ("calibration_receipt_reference", record.calibration_receipt_reference), + ("constraints_digest", record.constraints_digest), + ("constructed_at", record.constructed_at), + ("evidence_version", record.evidence_version), + ("input_weight_artifact_digest", record.input_weight_artifact_digest), + ("output_weight_artifact_digest", record.output_weight_artifact_digest), + ("owner_contract_digest", record.owner_contract_digest), + ("owner_contract_reference", record.owner_contract_reference), + ("owner_contract_version", record.owner_contract_version), + ("released_at", record.released_at), + ("termination_code", record.termination_code), + ) + if record.termination_code == "fallback_applied": + fields += ( + ("fallback_algorithm_reference", record.fallback_algorithm_reference), + ("fallback_algorithm_version", record.fallback_algorithm_version), + ("fallback_configuration_digest", record.fallback_configuration_digest), + ("fallback_reason_code", record.fallback_reason_code), + ("fallback_rule_digest", record.fallback_rule_digest), + ("fallback_rule_reference", record.fallback_rule_reference), + ) + return tuple.__new__( + CalibrationAdjustmentAuthorityView, + ( + _store_operational_uuid("tenant_record_id", tenant_id), + _store_operational_uuid("validity_study_id", study_id), + fields, + ), + ) From ebed3a6ab6952321af91412e38028c2953186d6b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 17:06:36 +0900 Subject: [PATCH 109/603] feat(workforce-validation): export calibration adjustment authority --- .../orgmetra_workforce_validation_api/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index b54771442..c3b10a938 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -8,6 +8,14 @@ CalibrationBenchmarkAuthorityView, resolve_calibration_benchmark_authority, ) +from orgmetra_workforce_validation_api.calibration_adjustment_authority import ( + CalibrationAdjustmentAuthorityIntegrityError, + CalibrationAdjustmentAuthorityNotFound, + CalibrationAdjustmentAuthorityReadPort, + CalibrationAdjustmentAuthorityRecord, + CalibrationAdjustmentAuthorityView, + resolve_calibration_adjustment_authority, +) from orgmetra_workforce_validation_api.registry import ( ValidationPrincipal, ValidityStudyIntegrityError, @@ -51,6 +59,11 @@ ) __all__ = [ + "CalibrationAdjustmentAuthorityIntegrityError", + "CalibrationAdjustmentAuthorityNotFound", + "CalibrationAdjustmentAuthorityReadPort", + "CalibrationAdjustmentAuthorityRecord", + "CalibrationAdjustmentAuthorityView", "CalibrationAuxiliaryAuthorityIntegrityError", "CalibrationAuxiliaryAuthorityNotFound", "CalibrationAuxiliaryAuthorityReadPort", @@ -83,6 +96,7 @@ "WeightVarianceAuthorityRecord", "WeightVarianceAuthorityView", "read_validity_study", + "resolve_calibration_adjustment_authority", "resolve_calibration_auxiliary_authority", "resolve_calibration_benchmark_authority", "resolve_validation_result_authority", From 61f13b7586d49395f54e926f3c7290beb2f8c5a3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 17:07:12 +0900 Subject: [PATCH 110/603] docs(workforce-validation): document typed calibration adjustment authority --- services/workforce-validation-api/README.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 4d6439766..f2c7f5fcc 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -44,6 +44,14 @@ Caller `used_at` must equal the owner-resolved scientific-use instant, and that The owner contract must already be released when the benchmark receipt becomes released evidence. A successor must advance the version, identify new evidence, be released after its predecessor, and exist no later than the predecessor's supersession instant. A predecessor is authoritative only on its owner-resolved half-open interval `[benchmark_receipt_released_at, benchmark_receipt_superseded_at)`. +## Typed calibration-adjustment authority + +`resolve_calibration_adjustment_authority(...)` corroborates the exact released calibration receipt that produced a point-weight artifact. It binds the receipt digest and evidence version to the purpose-limited auxiliary projection digest, benchmark receipt digest, primary algorithm/version, constraints, input/output weight artifact digests, construction time, and released owner-contract evidence. + +For `termination_code="fallback_applied"`, owner evidence must additionally preserve the primary failure reason, immutable fallback-rule reference/digest, and the actual fallback calibration algorithm/version/configuration that produced the output weights. `converged` rejects all fallback-only coordinates. The two weight-artifact digests must differ, release cannot precede construction, and the receipt cannot authorize scientific use before its owner-resolved release. Auxiliary values, benchmark totals, protected attributes, and row-level weights are excluded from the projection. + +This closes the application-owner side of #407 RED #7 without importing mutable `validity-analysis` source. It does not make caller-supplied leaf evidence self-authenticating; the durable adapter must re-resolve released typed calibration evidence from its owner. + ## Point-weight / variance authority `resolve_weight_variance_authority(...)` corroborates point-estimation and variance evidence without treating leaf-provided digests as owner authority. It binds: @@ -97,7 +105,7 @@ This is still application-boundary corroboration, not durable scientific authori The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, point-weight/variance, validation-result binding, and validation-result non-verifiability. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, point-weight/variance, validation-result binding, and validation-result non-verifiability. ## Test contract @@ -112,6 +120,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, point/variance evidence compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback generating-method provenance, point/variance evidence compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From df352d40db4792ee045d74db147eb9423c1934f6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 18:05:49 +0900 Subject: [PATCH 111/603] test(workforce-validation): require nonresponse adjustment authority --- .../test_nonresponse_adjustment_authority.py | 323 ++++++++++++++++++ 1 file changed, 323 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_nonresponse_adjustment_authority.py diff --git a/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority.py b/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority.py new file mode 100644 index 000000000..f413ec0a6 --- /dev/null +++ b/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority.py @@ -0,0 +1,323 @@ +"""Fail-closed contract for released typed nonresponse-adjustment authority.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.nonresponse_adjustment_authority import ( + NonresponseAdjustmentAuthorityIntegrityError, + NonresponseAdjustmentAuthorityNotFound, + NonresponseAdjustmentAuthorityReadPort, + NonresponseAdjustmentAuthorityRecord, + NonresponseAdjustmentAuthorityView, + resolve_nonresponse_adjustment_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000d2") +RECEIPT_REFERENCE = "nonresponse_adjustment_receipt:11111111-1111-4111-8111-111111111111" +DISPOSITION_REFERENCE = "response_disposition_receipt:22222222-2222-4222-8222-222222222222" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:33333333-3333-4333-8333-333333333333" +RECEIPT_DIGEST = "1" * 64 +DISPOSITION_DIGEST = "2" * 64 +POPULATION_DIGEST = "3" * 64 +CONFIGURATION_DIGEST = "4" * 64 +INPUT_WEIGHT_DIGEST = "5" * 64 +OUTPUT_WEIGHT_DIGEST = "6" * 64 +OWNER_CONTRACT_DIGEST = "7" * 64 +DISPOSITION_RELEASED_AT = datetime(2026, 9, 16, 10, 0, tzinfo=timezone.utc) +CONSTRUCTED_AT = datetime(2026, 9, 16, 12, 0, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "nonresponse_receipt_reference", + "nonresponse_receipt_digest", + "evidence_version", + "response_disposition_receipt_reference", + "response_disposition_receipt_version", + "response_disposition_receipt_digest", + "response_disposition_receipt_released_at", + "adjustment_population_digest", + "method_reference", + "method_version", + "configuration_digest", + "ineligible_treatment_code", + "unknown_treatment_code", + "unavailable_treatment_code", + "input_weight_artifact_digest", + "output_weight_artifact_digest", + "constructed_at", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "released_at", + } +) + + +class _ReadPort: + """Return configured nonresponse authority and retain lookup coordinates.""" + + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[dict[str, object]] = [] + + def read_nonresponse_adjustment_authority(self, **coordinates: object) -> object: + """Capture the owner lookup and return configured evidence.""" + self.calls.append(dict(coordinates)) + return self.result + + +class _NoReadMethod: + """Deliberately fail the owner-port protocol.""" + + +class _ProtocolOnly(NonresponseAdjustmentAuthorityReadPort): + """Inherit only the Protocol placeholder, not a concrete owner capability.""" + + +class _DescriptorReadPort: + """Expose a descriptor that must be rejected without executing it.""" + + @property + def read_nonresponse_adjustment_authority(self) -> object: + raise AssertionError("descriptor must not execute") + + +def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=tenant_record_id, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="nonresponse-adjustment-authority-read-v1", + resource_kind="nonresponse_adjustment_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record(**overrides: object) -> NonresponseAdjustmentAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "nonresponse_receipt_reference": RECEIPT_REFERENCE, + "nonresponse_receipt_digest": RECEIPT_DIGEST, + "evidence_version": 1, + "response_disposition_receipt_reference": DISPOSITION_REFERENCE, + "response_disposition_receipt_version": 4, + "response_disposition_receipt_digest": DISPOSITION_DIGEST, + "response_disposition_receipt_released_at": DISPOSITION_RELEASED_AT, + "adjustment_population_digest": POPULATION_DIGEST, + "method_reference": "weight_method:response_propensity_cells", + "method_version": 3, + "configuration_digest": CONFIGURATION_DIGEST, + "ineligible_treatment_code": "exclude_ineligible", + "unknown_treatment_code": "retain_unknown_class", + "unavailable_treatment_code": "retain_unavailable_class", + "input_weight_artifact_digest": INPUT_WEIGHT_DIGEST, + "output_weight_artifact_digest": OUTPUT_WEIGHT_DIGEST, + "constructed_at": CONSTRUCTED_AT, + "owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "owner_contract_version": 5, + "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "released_at": RELEASED_AT, + } + values.update(overrides) + return NonresponseAdjustmentAuthorityRecord(**values) + + +def _resolve(*, read_port: object, **overrides: object) -> NonresponseAdjustmentAuthorityView: + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "nonresponse_receipt_reference": RECEIPT_REFERENCE, + "nonresponse_receipt_digest": RECEIPT_DIGEST, + "evidence_version": 1, + "response_disposition_receipt_reference": DISPOSITION_REFERENCE, + "response_disposition_receipt_version": 4, + "response_disposition_receipt_digest": DISPOSITION_DIGEST, + "adjustment_population_digest": POPULATION_DIGEST, + "method_reference": "weight_method:response_propensity_cells", + "method_version": 3, + "configuration_digest": CONFIGURATION_DIGEST, + "ineligible_treatment_code": "exclude_ineligible", + "unknown_treatment_code": "retain_unknown_class", + "unavailable_treatment_code": "retain_unavailable_class", + "input_weight_artifact_digest": INPUT_WEIGHT_DIGEST, + "output_weight_artifact_digest": OUTPUT_WEIGHT_DIGEST, + "constructed_at": CONSTRUCTED_AT, + "owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "owner_contract_version": 5, + "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_nonresponse_adjustment_authority(**values) + + +def test_resolution_binds_versioned_disposition_and_treatment_evidence() -> None: + port = _ReadPort(_record()) + + view = _resolve(read_port=port) + + assert isinstance(port, NonresponseAdjustmentAuthorityReadPort) + assert len(port.calls) == 1 + assert port.calls[0]["response_disposition_receipt_reference"] == DISPOSITION_REFERENCE + assert port.calls[0]["response_disposition_receipt_version"] == 4 + assert port.calls[0]["response_disposition_receipt_digest"] == DISPOSITION_DIGEST + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + assert ("method_reference", "weight_method:response_propensity_cells") in view.fields + assert ("ineligible_treatment_code", "exclude_ineligible") in view.fields + assert ("unknown_treatment_code", "retain_unknown_class") in view.fields + assert ("unavailable_treatment_code", "retain_unavailable_class") in view.fields + assert ("response_disposition_receipt_released_at", DISPOSITION_RELEASED_AT) in view.fields + + +def test_authorization_denial_happens_before_owner_resolution() -> None: + port = _ReadPort(_record()) + + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, policy=_policy(purpose_code="audit_review")) + + assert port.calls == [] + + +def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: + with pytest.raises(NonresponseAdjustmentAuthorityNotFound): + _resolve(read_port=_ReadPort(None)) + + with pytest.raises(NonresponseAdjustmentAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object())) + + +@pytest.mark.parametrize( + "record_overrides", + [ + {"tenant_record_id": OTHER_TENANT}, + {"validity_study_id": OTHER_STUDY}, + {"nonresponse_receipt_digest": "a" * 64}, + {"response_disposition_receipt_reference": "response_disposition_receipt:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa"}, + {"response_disposition_receipt_version": 5}, + {"response_disposition_receipt_digest": "b" * 64}, + {"adjustment_population_digest": "c" * 64}, + {"method_reference": "weight_method:response_propensity_model"}, + {"method_version": 4}, + {"configuration_digest": "d" * 64}, + {"unknown_treatment_code": "exclude_unknown"}, + {"input_weight_artifact_digest": "e" * 64}, + {"output_weight_artifact_digest": "f" * 64}, + {"owner_contract_version": 6}, + {"owner_contract_digest": "0" * 64}, + ], +) +def test_owner_evidence_must_match_every_requested_coordinate( + record_overrides: dict[str, object] +) -> None: + with pytest.raises(NonresponseAdjustmentAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(**record_overrides))) + + +def test_owner_resolved_input_and_release_chronology_fail_closed() -> None: + with pytest.raises(ValueError): + _record(response_disposition_receipt_released_at=CONSTRUCTED_AT + timedelta(seconds=1)) + + with pytest.raises(ValueError): + _record(released_at=CONSTRUCTED_AT - timedelta(seconds=1)) + + with pytest.raises(NonresponseAdjustmentAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(released_at=USED_AT + timedelta(seconds=1)))) + + +def test_weight_artifact_aliasing_fails_closed() -> None: + with pytest.raises(ValueError): + _record(output_weight_artifact_digest=INPUT_WEIGHT_DIGEST) + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("nonresponse_receipt_reference", "wrong:receipt", ValueError), + ("nonresponse_receipt_digest", "ABC", ValueError), + ("evidence_version", False, ValueError), + ("response_disposition_receipt_reference", "wrong:receipt", ValueError), + ("response_disposition_receipt_version", 0, ValueError), + ("response_disposition_receipt_digest", "2" * 63, ValueError), + ("adjustment_population_digest", "3" * 65, ValueError), + ("method_reference", "wrong:method", ValueError), + ("method_version", True, ValueError), + ("configuration_digest", "4" * 63, ValueError), + ("ineligible_treatment_code", "Exclude Ineligible", ValueError), + ("unknown_treatment_code", "Unknown Treatment", ValueError), + ("unavailable_treatment_code", "Unavailable Treatment", ValueError), + ("constructed_at", datetime(2026, 9, 16, 12, 0), ValueError), + ("owner_contract_reference", "wrong:contract", ValueError), + ("owner_contract_version", 0, ValueError), + ("owner_contract_digest", "7" * 63, ValueError), + ("used_at", datetime(2026, 9, 17), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_or_dependency_fails_before_owner_resolution( + key: str, value: object, error: type[Exception] +) -> None: + port: object = _ReadPort(_record()) + overrides = {key: value} + if key == "read_port": + port = value + overrides = {} + with pytest.raises(error): + _resolve(read_port=port, **overrides) + if isinstance(port, _ReadPort): + assert port.calls == [] + + +def test_record_and_view_are_structurally_immutable_and_uuid_views_are_detached() -> None: + tenant = UUID(str(TENANT)) + record = _record(tenant_record_id=tenant) + object.__setattr__(tenant, "int", OTHER_TENANT.int) + assert record.tenant_record_id == TENANT + + with pytest.raises(AttributeError): + object.__setattr__(record, "method_version", 99) + + view = _resolve(read_port=_ReadPort(record)) + returned_tenant = view.tenant_record_id + object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) + assert view.tenant_record_id == TENANT + + with pytest.raises(AttributeError): + object.__setattr__(view, "fields", ()) + with pytest.raises(TypeError): + NonresponseAdjustmentAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) From a95b0fd58935ea2ac1789a3a978efd68542aa8a8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 18:06:38 +0900 Subject: [PATCH 112/603] feat(workforce-validation): corroborate nonresponse adjustment authority --- .../nonresponse_adjustment_authority.py | 593 ++++++++++++++++++ 1 file changed, 593 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py new file mode 100644 index 000000000..dc9dc2204 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py @@ -0,0 +1,593 @@ +"""Corroborate released typed nonresponse-adjustment evidence through an owner port. + +This application boundary binds the exact disposition-aware adjustment receipt +that produced a point-weight artifact. It preserves treatment and chronology +evidence without copying response values, source attributes, or row-level +weights. Durable PostgreSQL/release resolution remains a persistence-owner task +after this service reaches protected truth. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + +_RESOURCE_KIND = "nonresponse_adjustment_authority" +_OPERATION = "read" +_READ_FIELDS = frozenset( + { + "nonresponse_receipt_reference", + "nonresponse_receipt_digest", + "evidence_version", + "response_disposition_receipt_reference", + "response_disposition_receipt_version", + "response_disposition_receipt_digest", + "response_disposition_receipt_released_at", + "adjustment_population_digest", + "method_reference", + "method_version", + "configuration_digest", + "ineligible_treatment_code", + "unknown_treatment_code", + "unavailable_treatment_code", + "input_weight_artifact_digest", + "output_weight_artifact_digest", + "constructed_at", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "released_at", + } +) + + +class NonresponseAdjustmentAuthorityNotFound(LookupError): + """Indicate that no released owner evidence corroborates the nonresponse receipt.""" + + +class NonresponseAdjustmentAuthorityIntegrityError(RuntimeError): + """Indicate that owner evidence cannot corroborate the requested nonresponse receipt.""" + + +class NonresponseAdjustmentAuthorityRecord(tuple): + """Immutable owner projection for one released typed nonresponse receipt.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + nonresponse_receipt_reference: str, + nonresponse_receipt_digest: str, + evidence_version: int, + response_disposition_receipt_reference: str, + response_disposition_receipt_version: int, + response_disposition_receipt_digest: str, + response_disposition_receipt_released_at: datetime, + adjustment_population_digest: str, + method_reference: str, + method_version: int, + configuration_digest: str, + ineligible_treatment_code: str, + unknown_treatment_code: str, + unavailable_treatment_code: str, + input_weight_artifact_digest: str, + output_weight_artifact_digest: str, + constructed_at: datetime, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + released_at: datetime, + ) -> NonresponseAdjustmentAuthorityRecord: + """Validate and detach the minimum disposition-aware scientific authority.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + receipt_ref = _require_reference( + "nonresponse_receipt_reference", + nonresponse_receipt_reference, + "nonresponse_adjustment_receipt", + ) + receipt_digest = _require_digest( + "nonresponse_receipt_digest", nonresponse_receipt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + disposition_ref = _require_reference( + "response_disposition_receipt_reference", + response_disposition_receipt_reference, + "response_disposition_receipt", + ) + disposition_version = _require_positive_integer( + "response_disposition_receipt_version", + response_disposition_receipt_version, + ) + disposition_digest = _require_digest( + "response_disposition_receipt_digest", + response_disposition_receipt_digest, + ) + disposition_released = _require_aware_datetime( + "response_disposition_receipt_released_at", + response_disposition_receipt_released_at, + ) + population_digest = _require_digest( + "adjustment_population_digest", adjustment_population_digest + ) + method_ref = _require_reference( + "method_reference", method_reference, "weight_method" + ) + method_ver = _require_positive_integer("method_version", method_version) + configuration = _require_digest("configuration_digest", configuration_digest) + ineligible = _require_code("ineligible_treatment_code", ineligible_treatment_code) + unknown = _require_code("unknown_treatment_code", unknown_treatment_code) + unavailable = _require_code( + "unavailable_treatment_code", unavailable_treatment_code + ) + input_digest = _require_digest( + "input_weight_artifact_digest", input_weight_artifact_digest + ) + output_digest = _require_digest( + "output_weight_artifact_digest", output_weight_artifact_digest + ) + if input_digest == output_digest: + raise ValueError( + "output_weight_artifact_digest must identify the adjusted weight artifact." + ) + constructed = _require_aware_datetime("constructed_at", constructed_at) + if disposition_released > constructed: + raise ValueError( + "response_disposition_receipt_released_at cannot be later than constructed_at." + ) + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + release_instant = _require_aware_datetime("released_at", released_at) + if release_instant < constructed: + raise ValueError("released_at cannot precede constructed_at.") + + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + receipt_ref, + receipt_digest, + version, + disposition_ref, + disposition_version, + disposition_digest, + disposition_released, + population_digest, + method_ref, + method_ver, + configuration, + ineligible, + unknown, + unavailable, + input_digest, + output_digest, + constructed, + owner_ref, + owner_version, + owner_digest, + release_instant, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity for this released evidence.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity for this released evidence.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def nonresponse_receipt_reference(self) -> str: + """Return the typed nonresponse-adjustment receipt reference.""" + return self[2] + + @property + def nonresponse_receipt_digest(self) -> str: + """Return the exact nonresponse-adjustment receipt digest.""" + return self[3] + + @property + def evidence_version(self) -> int: + """Return the receipt evidence version.""" + return self[4] + + @property + def response_disposition_receipt_reference(self) -> str: + """Return the exact response/disposition input receipt reference.""" + return self[5] + + @property + def response_disposition_receipt_version(self) -> int: + """Return the exact response/disposition input receipt version.""" + return self[6] + + @property + def response_disposition_receipt_digest(self) -> str: + """Return the exact response/disposition input receipt digest.""" + return self[7] + + @property + def response_disposition_receipt_released_at(self) -> datetime: + """Return when the disposition input became released evidence.""" + return self[8] + + @property + def adjustment_population_digest(self) -> str: + """Return the adjustment population digest.""" + return self[9] + + @property + def method_reference(self) -> str: + """Return the controlled nonresponse method reference.""" + return self[10] + + @property + def method_version(self) -> int: + """Return the controlled nonresponse method version.""" + return self[11] + + @property + def configuration_digest(self) -> str: + """Return the immutable method configuration digest.""" + return self[12] + + @property + def ineligible_treatment_code(self) -> str: + """Return the explicit treatment for ineligible cases.""" + return self[13] + + @property + def unknown_treatment_code(self) -> str: + """Return the explicit treatment for unknown dispositions.""" + return self[14] + + @property + def unavailable_treatment_code(self) -> str: + """Return the explicit treatment for unavailable dispositions.""" + return self[15] + + @property + def input_weight_artifact_digest(self) -> str: + """Return the input weight artifact digest.""" + return self[16] + + @property + def output_weight_artifact_digest(self) -> str: + """Return the nonresponse-adjusted output weight artifact digest.""" + return self[17] + + @property + def constructed_at(self) -> datetime: + """Return when the typed nonresponse receipt was constructed.""" + return self[18] + + @property + def owner_contract_reference(self) -> str: + """Return the released owner-contract reference.""" + return self[19] + + @property + def owner_contract_version(self) -> int: + """Return the released owner-contract version.""" + return self[20] + + @property + def owner_contract_digest(self) -> str: + """Return the released owner-contract digest.""" + return self[21] + + @property + def released_at(self) -> datetime: + """Return when this typed nonresponse evidence became released authority.""" + return self[22] + + +class NonresponseAdjustmentAuthorityView(tuple): + """Field-minimized nonresponse evidence issued only after authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> NonresponseAdjustmentAuthorityView: + """Reject direct construction; only the resolver may issue this view.""" + raise TypeError( + "NonresponseAdjustmentAuthorityView is issued only by " + "resolve_nonresponse_adjustment_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable nonresponse provenance without response values.""" + return self[2] + + +@runtime_checkable +class NonresponseAdjustmentAuthorityReadPort(Protocol): + """Owner read contract for released typed nonresponse-adjustment evidence.""" + + def read_nonresponse_adjustment_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + nonresponse_receipt_reference: str, + nonresponse_receipt_digest: str, + evidence_version: int, + response_disposition_receipt_reference: str, + response_disposition_receipt_version: int, + response_disposition_receipt_digest: str, + adjustment_population_digest: str, + method_reference: str, + method_version: int, + configuration_digest: str, + ineligible_treatment_code: str, + unknown_treatment_code: str, + unavailable_treatment_code: str, + input_weight_artifact_digest: str, + output_weight_artifact_digest: str, + constructed_at: datetime, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> NonresponseAdjustmentAuthorityRecord | None: + """Return matching released typed nonresponse evidence or ``None``.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + NonresponseAdjustmentAuthorityReadPort, "read_nonresponse_adjustment_authority" +) + + +def _coordinate_tuple(record: NonresponseAdjustmentAuthorityRecord) -> tuple[object, ...]: + """Return caller-known coordinates, excluding owner-resolved release instants.""" + return record[:8] + record[9:22] + + +def resolve_nonresponse_adjustment_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + nonresponse_receipt_reference: str, + nonresponse_receipt_digest: str, + evidence_version: int, + response_disposition_receipt_reference: str, + response_disposition_receipt_version: int, + response_disposition_receipt_digest: str, + adjustment_population_digest: str, + method_reference: str, + method_version: int, + configuration_digest: str, + ineligible_treatment_code: str, + unknown_treatment_code: str, + unavailable_treatment_code: str, + input_weight_artifact_digest: str, + output_weight_artifact_digest: str, + constructed_at: datetime, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: NonresponseAdjustmentAuthorityReadPort, +) -> NonresponseAdjustmentAuthorityView: + """Authorize then corroborate the exact released nonresponse receipt.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static( + type(read_port), "read_nonresponse_adjustment_authority", None + ) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError( + "read_port must expose a statically callable " + "read_nonresponse_adjustment_authority." + ) + + constructed = _require_aware_datetime("constructed_at", constructed_at) + requested = NonresponseAdjustmentAuthorityRecord( + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + nonresponse_receipt_reference=nonresponse_receipt_reference, + nonresponse_receipt_digest=nonresponse_receipt_digest, + evidence_version=evidence_version, + response_disposition_receipt_reference=response_disposition_receipt_reference, + response_disposition_receipt_version=response_disposition_receipt_version, + response_disposition_receipt_digest=response_disposition_receipt_digest, + response_disposition_receipt_released_at=constructed, + adjustment_population_digest=adjustment_population_digest, + method_reference=method_reference, + method_version=method_version, + configuration_digest=configuration_digest, + ineligible_treatment_code=ineligible_treatment_code, + unknown_treatment_code=unknown_treatment_code, + unavailable_treatment_code=unavailable_treatment_code, + input_weight_artifact_digest=input_weight_artifact_digest, + output_weight_artifact_digest=output_weight_artifact_digest, + constructed_at=constructed, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + released_at=constructed, + ) + tenant_id = requested.tenant_record_id + study_id = requested.validity_study_id + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=requested.tenant_record_id, + validity_study_id=requested.validity_study_id, + nonresponse_receipt_reference=requested.nonresponse_receipt_reference, + nonresponse_receipt_digest=requested.nonresponse_receipt_digest, + evidence_version=requested.evidence_version, + response_disposition_receipt_reference=requested.response_disposition_receipt_reference, + response_disposition_receipt_version=requested.response_disposition_receipt_version, + response_disposition_receipt_digest=requested.response_disposition_receipt_digest, + adjustment_population_digest=requested.adjustment_population_digest, + method_reference=requested.method_reference, + method_version=requested.method_version, + configuration_digest=requested.configuration_digest, + ineligible_treatment_code=requested.ineligible_treatment_code, + unknown_treatment_code=requested.unknown_treatment_code, + unavailable_treatment_code=requested.unavailable_treatment_code, + input_weight_artifact_digest=requested.input_weight_artifact_digest, + output_weight_artifact_digest=requested.output_weight_artifact_digest, + constructed_at=requested.constructed_at, + owner_contract_reference=requested.owner_contract_reference, + owner_contract_version=requested.owner_contract_version, + owner_contract_digest=requested.owner_contract_digest, + ) + if persisted is None: + raise NonresponseAdjustmentAuthorityNotFound(str(study_id)) + if type(persisted) is not NonresponseAdjustmentAuthorityRecord: + raise NonresponseAdjustmentAuthorityIntegrityError( + "owner port returned non-canonical nonresponse-adjustment authority evidence" + ) + + record = NonresponseAdjustmentAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + nonresponse_receipt_reference=persisted.nonresponse_receipt_reference, + nonresponse_receipt_digest=persisted.nonresponse_receipt_digest, + evidence_version=persisted.evidence_version, + response_disposition_receipt_reference=persisted.response_disposition_receipt_reference, + response_disposition_receipt_version=persisted.response_disposition_receipt_version, + response_disposition_receipt_digest=persisted.response_disposition_receipt_digest, + response_disposition_receipt_released_at=persisted.response_disposition_receipt_released_at, + adjustment_population_digest=persisted.adjustment_population_digest, + method_reference=persisted.method_reference, + method_version=persisted.method_version, + configuration_digest=persisted.configuration_digest, + ineligible_treatment_code=persisted.ineligible_treatment_code, + unknown_treatment_code=persisted.unknown_treatment_code, + unavailable_treatment_code=persisted.unavailable_treatment_code, + input_weight_artifact_digest=persisted.input_weight_artifact_digest, + output_weight_artifact_digest=persisted.output_weight_artifact_digest, + constructed_at=persisted.constructed_at, + owner_contract_reference=persisted.owner_contract_reference, + owner_contract_version=persisted.owner_contract_version, + owner_contract_digest=persisted.owner_contract_digest, + released_at=persisted.released_at, + ) + if _coordinate_tuple(record) != _coordinate_tuple(requested): + raise NonresponseAdjustmentAuthorityIntegrityError( + "released nonresponse-adjustment authority does not match requested coordinates" + ) + if record.released_at > use_instant: + raise NonresponseAdjustmentAuthorityIntegrityError( + "nonresponse-adjustment evidence must be released before scientific use" + ) + + fields: tuple[tuple[str, object], ...] = ( + ("adjustment_population_digest", record.adjustment_population_digest), + ("configuration_digest", record.configuration_digest), + ("constructed_at", record.constructed_at), + ("evidence_version", record.evidence_version), + ("ineligible_treatment_code", record.ineligible_treatment_code), + ("input_weight_artifact_digest", record.input_weight_artifact_digest), + ("method_reference", record.method_reference), + ("method_version", record.method_version), + ("nonresponse_receipt_digest", record.nonresponse_receipt_digest), + ("nonresponse_receipt_reference", record.nonresponse_receipt_reference), + ("output_weight_artifact_digest", record.output_weight_artifact_digest), + ("owner_contract_digest", record.owner_contract_digest), + ("owner_contract_reference", record.owner_contract_reference), + ("owner_contract_version", record.owner_contract_version), + ("released_at", record.released_at), + ("response_disposition_receipt_digest", record.response_disposition_receipt_digest), + ("response_disposition_receipt_reference", record.response_disposition_receipt_reference), + ("response_disposition_receipt_released_at", record.response_disposition_receipt_released_at), + ("response_disposition_receipt_version", record.response_disposition_receipt_version), + ("unavailable_treatment_code", record.unavailable_treatment_code), + ("unknown_treatment_code", record.unknown_treatment_code), + ) + return tuple.__new__( + NonresponseAdjustmentAuthorityView, + ( + _store_operational_uuid("tenant_record_id", tenant_id), + _store_operational_uuid("validity_study_id", study_id), + fields, + ), + ) From a557d122f1a9de0af3b1f76e1ecccda5ed4dd2df Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 18:06:56 +0900 Subject: [PATCH 113/603] feat(workforce-validation): export nonresponse adjustment authority --- .../__init__.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index c3b10a938..824ab2640 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -16,6 +16,14 @@ CalibrationAdjustmentAuthorityView, resolve_calibration_adjustment_authority, ) +from orgmetra_workforce_validation_api.nonresponse_adjustment_authority import ( + NonresponseAdjustmentAuthorityIntegrityError, + NonresponseAdjustmentAuthorityNotFound, + NonresponseAdjustmentAuthorityReadPort, + NonresponseAdjustmentAuthorityRecord, + NonresponseAdjustmentAuthorityView, + resolve_nonresponse_adjustment_authority, +) from orgmetra_workforce_validation_api.registry import ( ValidationPrincipal, ValidityStudyIntegrityError, @@ -74,6 +82,11 @@ "CalibrationBenchmarkAuthorityReadPort", "CalibrationBenchmarkAuthorityRecord", "CalibrationBenchmarkAuthorityView", + "NonresponseAdjustmentAuthorityIntegrityError", + "NonresponseAdjustmentAuthorityNotFound", + "NonresponseAdjustmentAuthorityReadPort", + "NonresponseAdjustmentAuthorityRecord", + "NonresponseAdjustmentAuthorityView", "ValidationPrincipal", "ValidationResultAuthorityIntegrityError", "ValidationResultAuthorityNotFound", @@ -99,7 +112,8 @@ "resolve_calibration_adjustment_authority", "resolve_calibration_auxiliary_authority", "resolve_calibration_benchmark_authority", + "resolve_nonresponse_adjustment_authority", "resolve_validation_result_authority", "resolve_validation_result_nonverifiability", "resolve_weight_variance_authority", -] +] \ No newline at end of file From 52d1750b8cd3b59ba4972ab8c96f1d01cb956b5c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 18:07:36 +0900 Subject: [PATCH 114/603] docs(workforce-validation): document nonresponse authority boundary --- services/workforce-validation-api/README.md | 23 ++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index f2c7f5fcc..76e5d5fe8 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -52,6 +52,23 @@ For `termination_code="fallback_applied"`, owner evidence must additionally pres This closes the application-owner side of #407 RED #7 without importing mutable `validity-analysis` source. It does not make caller-supplied leaf evidence self-authenticating; the durable adapter must re-resolve released typed calibration evidence from its owner. +## Typed nonresponse-adjustment authority + +`resolve_nonresponse_adjustment_authority(...)` corroborates the exact released disposition-aware nonresponse receipt that produced a point-weight artifact. It binds: + +- nonresponse receipt reference/digest and evidence version; +- exact response/disposition receipt reference/version/digest; +- owner-resolved response/disposition receipt release instant; +- adjustment-population digest; +- controlled method reference/version and immutable configuration digest; +- explicit ineligible, unknown, and unavailable treatment codes; +- input/output weight-artifact digests and construction time; +- released owner-contract reference/version/digest and owner-resolved receipt release instant. + +The response/disposition input must already be released when the nonresponse receipt is constructed, the output artifact must differ from its input, and the nonresponse receipt cannot authorize scientific use before its owner-resolved release. Response values, source attributes, protected attributes, and row-level weights are excluded from the projection. + +This closes the application-owner corroboration gap for #407's versioned, disposition-aware nonresponse adjustment. The durable adapter must re-resolve the same exact receipt/version/digest and chronology from released owner evidence rather than treating a leaf adjustment digest or a missing join as authority. + ## Point-weight / variance authority `resolve_weight_variance_authority(...)` corroborates point-estimation and variance evidence without treating leaf-provided digests as owner authority. It binds: @@ -105,7 +122,7 @@ This is still application-boundary corroboration, not durable scientific authori The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, point-weight/variance, validation-result binding, and validation-result non-verifiability. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, point-weight/variance, validation-result binding, and validation-result non-verifiability. ## Test contract @@ -120,6 +137,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback generating-method provenance, point/variance evidence compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback generating-method provenance, typed nonresponse disposition/treatment provenance and input-release chronology, point/variance evidence compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. -These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. +These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. \ No newline at end of file From 759f0d961c845fd385bf21bc76b003d153831d4a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 18:08:06 +0900 Subject: [PATCH 115/603] test(workforce-validation): close nonresponse authority edge coverage --- ..._nonresponse_adjustment_authority_edges.py | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_edges.py diff --git a/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_edges.py b/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_edges.py new file mode 100644 index 000000000..611abe2c2 --- /dev/null +++ b/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_edges.py @@ -0,0 +1,51 @@ +"""Hostile edges for typed nonresponse-adjustment authority.""" + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.nonresponse_adjustment_authority import ( + NonresponseAdjustmentAuthorityRecord, +) + + +def _record(*, evidence_version: object = 1) -> NonresponseAdjustmentAuthorityRecord: + return NonresponseAdjustmentAuthorityRecord( + tenant_record_id=UUID("10000000-0000-7000-8000-000000000001"), + validity_study_id=UUID("00000000-0000-7000-8000-0000000000d1"), + nonresponse_receipt_reference=( + "nonresponse_adjustment_receipt:11111111-1111-4111-8111-111111111111" + ), + nonresponse_receipt_digest="1" * 64, + evidence_version=evidence_version, + response_disposition_receipt_reference=( + "response_disposition_receipt:22222222-2222-4222-8222-222222222222" + ), + response_disposition_receipt_version=4, + response_disposition_receipt_digest="2" * 64, + response_disposition_receipt_released_at=datetime( + 2026, 9, 16, 10, 0, tzinfo=timezone.utc + ), + adjustment_population_digest="3" * 64, + method_reference="weight_method:response_propensity_cells", + method_version=3, + configuration_digest="4" * 64, + ineligible_treatment_code="exclude_ineligible", + unknown_treatment_code="retain_unknown_class", + unavailable_treatment_code="retain_unavailable_class", + input_weight_artifact_digest="5" * 64, + output_weight_artifact_digest="6" * 64, + constructed_at=datetime(2026, 9, 16, 12, 0, tzinfo=timezone.utc), + owner_contract_reference=( + "released_owner_contract:33333333-3333-4333-8333-333333333333" + ), + owner_contract_version=5, + owner_contract_digest="7" * 64, + released_at=datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc), + ) + + +def test_evidence_version_cannot_advance_without_a_contract_revision() -> None: + with pytest.raises(ValueError, match="evidence_version must remain 1"): + _record(evidence_version=2) From 837b41b7308818aa596f5fd081793f713cf26fb1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 18:11:49 +0900 Subject: [PATCH 116/603] test(workforce-validation): require weight eligibility authority --- .../test_weight_eligibility_authority.py | 293 ++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_eligibility_authority.py diff --git a/services/workforce-validation-api/tests/test_weight_eligibility_authority.py b/services/workforce-validation-api/tests/test_weight_eligibility_authority.py new file mode 100644 index 000000000..1be518186 --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_eligibility_authority.py @@ -0,0 +1,293 @@ +"""Fail-closed contract for released cross-sectional/longitudinal weight eligibility.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.weight_eligibility_authority import ( + WeightEligibilityAuthorityIntegrityError, + WeightEligibilityAuthorityNotFound, + WeightEligibilityAuthorityReadPort, + WeightEligibilityAuthorityRecord, + WeightEligibilityAuthorityView, + resolve_weight_eligibility_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000d2") +RECEIPT_REFERENCE = "weight_eligibility_receipt:11111111-1111-4111-8111-111111111111" +TARGET_POPULATION_REFERENCE = "analysis_target_population:workers-2026q3" +REFERENCE_DURATION_REFERENCE = "analysis_reference_duration:2026q3" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +RECEIPT_DIGEST = "1" * 64 +TARGET_POPULATION_DIGEST = "2" * 64 +REFERENCE_DURATION_DIGEST = "3" * 64 +ELIGIBLE_CASE_SET_DIGEST = "4" * 64 +WEIGHT_ARTIFACT_DIGEST = "5" * 64 +OWNER_CONTRACT_DIGEST = "6" * 64 +CONSTRUCTED_AT = datetime(2026, 9, 16, 12, 0, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "eligibility_receipt_reference", + "eligibility_receipt_digest", + "evidence_version", + "weight_scope_code", + "target_population_reference", + "target_population_digest", + "reference_duration_reference", + "reference_duration_digest", + "eligible_case_set_digest", + "weight_artifact_digest", + "constructed_at", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "released_at", + } +) + + +class _ReadPort: + """Return configured eligibility authority and retain lookup coordinates.""" + + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[dict[str, object]] = [] + + def read_weight_eligibility_authority(self, **coordinates: object) -> object: + """Capture the owner lookup and return configured evidence.""" + self.calls.append(dict(coordinates)) + return self.result + + +class _NoReadMethod: + """Deliberately fail the owner-port protocol.""" + + +class _ProtocolOnly(WeightEligibilityAuthorityReadPort): + """Inherit only the Protocol placeholder, not a concrete owner capability.""" + + +class _DescriptorReadPort: + """Expose a descriptor that must be rejected without executing it.""" + + @property + def read_weight_eligibility_authority(self) -> object: + raise AssertionError("descriptor must not execute") + + +def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=tenant_record_id, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="weight-eligibility-authority-read-v1", + resource_kind="weight_eligibility_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record(**overrides: object) -> WeightEligibilityAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "eligibility_receipt_reference": RECEIPT_REFERENCE, + "eligibility_receipt_digest": RECEIPT_DIGEST, + "evidence_version": 1, + "weight_scope_code": "longitudinal", + "target_population_reference": TARGET_POPULATION_REFERENCE, + "target_population_digest": TARGET_POPULATION_DIGEST, + "reference_duration_reference": REFERENCE_DURATION_REFERENCE, + "reference_duration_digest": REFERENCE_DURATION_DIGEST, + "eligible_case_set_digest": ELIGIBLE_CASE_SET_DIGEST, + "weight_artifact_digest": WEIGHT_ARTIFACT_DIGEST, + "constructed_at": CONSTRUCTED_AT, + "owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "owner_contract_version": 3, + "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "released_at": RELEASED_AT, + } + values.update(overrides) + return WeightEligibilityAuthorityRecord(**values) + + +def _resolve(*, read_port: object, **overrides: object) -> WeightEligibilityAuthorityView: + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "eligibility_receipt_reference": RECEIPT_REFERENCE, + "eligibility_receipt_digest": RECEIPT_DIGEST, + "evidence_version": 1, + "weight_scope_code": "longitudinal", + "target_population_reference": TARGET_POPULATION_REFERENCE, + "target_population_digest": TARGET_POPULATION_DIGEST, + "reference_duration_reference": REFERENCE_DURATION_REFERENCE, + "reference_duration_digest": REFERENCE_DURATION_DIGEST, + "eligible_case_set_digest": ELIGIBLE_CASE_SET_DIGEST, + "weight_artifact_digest": WEIGHT_ARTIFACT_DIGEST, + "constructed_at": CONSTRUCTED_AT, + "owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "owner_contract_version": 3, + "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_weight_eligibility_authority(**values) + + +def test_longitudinal_resolution_binds_population_duration_case_set_and_artifact() -> None: + port = _ReadPort(_record()) + + view = _resolve(read_port=port) + + assert isinstance(port, WeightEligibilityAuthorityReadPort) + assert len(port.calls) == 1 + assert port.calls[0]["weight_scope_code"] == "longitudinal" + assert port.calls[0]["reference_duration_reference"] == REFERENCE_DURATION_REFERENCE + assert port.calls[0]["eligible_case_set_digest"] == ELIGIBLE_CASE_SET_DIGEST + assert port.calls[0]["weight_artifact_digest"] == WEIGHT_ARTIFACT_DIGEST + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + assert ("weight_scope_code", "longitudinal") in view.fields + assert ("target_population_reference", TARGET_POPULATION_REFERENCE) in view.fields + assert ("reference_duration_reference", REFERENCE_DURATION_REFERENCE) in view.fields + assert ("eligible_case_set_digest", ELIGIBLE_CASE_SET_DIGEST) in view.fields + assert ("weight_artifact_digest", WEIGHT_ARTIFACT_DIGEST) in view.fields + + +def test_cross_sectional_scope_is_distinct_released_authority() -> None: + record = _record(weight_scope_code="cross_sectional") + view = _resolve(read_port=_ReadPort(record), weight_scope_code="cross_sectional") + assert ("weight_scope_code", "cross_sectional") in view.fields + + +def test_authorization_denial_happens_before_owner_resolution() -> None: + port = _ReadPort(_record()) + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, policy=_policy(purpose_code="audit_review")) + assert port.calls == [] + + +def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: + with pytest.raises(WeightEligibilityAuthorityNotFound): + _resolve(read_port=_ReadPort(None)) + with pytest.raises(WeightEligibilityAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object())) + + +@pytest.mark.parametrize( + "record_overrides", + [ + {"tenant_record_id": OTHER_TENANT}, + {"validity_study_id": OTHER_STUDY}, + {"eligibility_receipt_digest": "a" * 64}, + {"weight_scope_code": "cross_sectional"}, + {"target_population_reference": "analysis_target_population:other"}, + {"target_population_digest": "b" * 64}, + {"reference_duration_reference": "analysis_reference_duration:other"}, + {"reference_duration_digest": "c" * 64}, + {"eligible_case_set_digest": "d" * 64}, + {"weight_artifact_digest": "e" * 64}, + {"constructed_at": CONSTRUCTED_AT + timedelta(seconds=1)}, + {"owner_contract_version": 4}, + {"owner_contract_digest": "f" * 64}, + ], +) +def test_owner_evidence_must_match_every_requested_coordinate( + record_overrides: dict[str, object] +) -> None: + with pytest.raises(WeightEligibilityAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(**record_overrides))) + + +def test_release_chronology_and_use_fail_closed() -> None: + with pytest.raises(ValueError): + _record(released_at=CONSTRUCTED_AT - timedelta(seconds=1)) + with pytest.raises(WeightEligibilityAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(released_at=USED_AT + timedelta(seconds=1)))) + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("eligibility_receipt_reference", "wrong:receipt", ValueError), + ("eligibility_receipt_digest", "ABC", ValueError), + ("evidence_version", False, ValueError), + ("weight_scope_code", "panel", ValueError), + ("target_population_reference", "wrong:population", ValueError), + ("target_population_digest", "2" * 63, ValueError), + ("reference_duration_reference", "wrong:duration", ValueError), + ("reference_duration_digest", "3" * 65, ValueError), + ("eligible_case_set_digest", "4" * 63, ValueError), + ("weight_artifact_digest", "5" * 65, ValueError), + ("constructed_at", datetime(2026, 9, 16, 12, 0), ValueError), + ("owner_contract_reference", "wrong:contract", ValueError), + ("owner_contract_version", 0, ValueError), + ("owner_contract_digest", "6" * 63, ValueError), + ("used_at", datetime(2026, 9, 17), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_or_dependency_fails_before_owner_resolution( + key: str, value: object, error: type[Exception] +) -> None: + port: object = _ReadPort(_record()) + overrides = {key: value} + if key == "read_port": + port = value + overrides = {} + with pytest.raises(error): + _resolve(read_port=port, **overrides) + if isinstance(port, _ReadPort): + assert port.calls == [] + + +def test_record_and_view_are_structurally_immutable_and_uuid_views_are_detached() -> None: + tenant = UUID(str(TENANT)) + record = _record(tenant_record_id=tenant) + object.__setattr__(tenant, "int", OTHER_TENANT.int) + assert record.tenant_record_id == TENANT + with pytest.raises(AttributeError): + object.__setattr__(record, "weight_scope_code", "cross_sectional") + + view = _resolve(read_port=_ReadPort(record)) + returned_tenant = view.tenant_record_id + object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) + assert view.tenant_record_id == TENANT + with pytest.raises(AttributeError): + object.__setattr__(view, "fields", ()) + with pytest.raises(TypeError): + WeightEligibilityAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) From cbe74990b8661fe0eb278129518e78fe00525c18 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 18:12:22 +0900 Subject: [PATCH 117/603] feat(workforce-validation): corroborate weight eligibility authority --- .../weight_eligibility_authority.py | 487 ++++++++++++++++++ 1 file changed, 487 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py new file mode 100644 index 000000000..5a99ce84c --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py @@ -0,0 +1,487 @@ +"""Corroborate released cross-sectional/longitudinal weight eligibility. + +The owner port binds one point-weight artifact to its governed population, +reference duration, eligible case set, and scope. It does not copy row-level +weights, person attributes, or foreign application data. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + +_RESOURCE_KIND = "weight_eligibility_authority" +_OPERATION = "read" +_WEIGHT_SCOPE_CODES = frozenset({"cross_sectional", "longitudinal"}) +_READ_FIELDS = frozenset( + { + "eligibility_receipt_reference", + "eligibility_receipt_digest", + "evidence_version", + "weight_scope_code", + "target_population_reference", + "target_population_digest", + "reference_duration_reference", + "reference_duration_digest", + "eligible_case_set_digest", + "weight_artifact_digest", + "constructed_at", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "released_at", + } +) + + +class WeightEligibilityAuthorityNotFound(LookupError): + """Indicate that no released owner evidence corroborates the eligibility receipt.""" + + +class WeightEligibilityAuthorityIntegrityError(RuntimeError): + """Indicate that owner evidence cannot corroborate the requested eligibility tuple.""" + + +def _require_weight_scope(value: object) -> str: + """Require explicit cross-sectional or longitudinal eligibility semantics.""" + if type(value) is not str or value not in _WEIGHT_SCOPE_CODES: + raise ValueError("weight_scope_code must be cross_sectional or longitudinal.") + return value + + +class WeightEligibilityAuthorityRecord(tuple): + """Immutable owner projection for one released weight-eligibility receipt.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + eligibility_receipt_reference: str, + eligibility_receipt_digest: str, + evidence_version: int, + weight_scope_code: str, + target_population_reference: str, + target_population_digest: str, + reference_duration_reference: str, + reference_duration_digest: str, + eligible_case_set_digest: str, + weight_artifact_digest: str, + constructed_at: datetime, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + released_at: datetime, + ) -> WeightEligibilityAuthorityRecord: + """Validate and detach the minimum immutable eligibility authority.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + receipt_ref = _require_reference( + "eligibility_receipt_reference", + eligibility_receipt_reference, + "weight_eligibility_receipt", + ) + receipt_digest = _require_digest( + "eligibility_receipt_digest", eligibility_receipt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + scope = _require_weight_scope(weight_scope_code) + target_ref = _require_reference( + "target_population_reference", + target_population_reference, + "analysis_target_population", + ) + target_digest = _require_digest( + "target_population_digest", target_population_digest + ) + duration_ref = _require_reference( + "reference_duration_reference", + reference_duration_reference, + "analysis_reference_duration", + ) + duration_digest = _require_digest( + "reference_duration_digest", reference_duration_digest + ) + case_digest = _require_digest( + "eligible_case_set_digest", eligible_case_set_digest + ) + artifact_digest = _require_digest( + "weight_artifact_digest", weight_artifact_digest + ) + constructed = _require_aware_datetime("constructed_at", constructed_at) + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + release_instant = _require_aware_datetime("released_at", released_at) + if release_instant < constructed: + raise ValueError("released_at cannot precede constructed_at.") + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + receipt_ref, + receipt_digest, + version, + scope, + target_ref, + target_digest, + duration_ref, + duration_digest, + case_digest, + artifact_digest, + constructed, + owner_ref, + owner_version, + owner_digest, + release_instant, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity for this released evidence.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity for this released evidence.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def eligibility_receipt_reference(self) -> str: + """Return the typed weight-eligibility receipt reference.""" + return self[2] + + @property + def eligibility_receipt_digest(self) -> str: + """Return the exact eligibility receipt digest.""" + return self[3] + + @property + def evidence_version(self) -> int: + """Return the eligibility receipt evidence version.""" + return self[4] + + @property + def weight_scope_code(self) -> str: + """Return cross-sectional or longitudinal eligibility semantics.""" + return self[5] + + @property + def target_population_reference(self) -> str: + """Return the governed analysis target-population reference.""" + return self[6] + + @property + def target_population_digest(self) -> str: + """Return the target-population evidence digest.""" + return self[7] + + @property + def reference_duration_reference(self) -> str: + """Return the governed analysis reference-duration reference.""" + return self[8] + + @property + def reference_duration_digest(self) -> str: + """Return the reference-duration evidence digest.""" + return self[9] + + @property + def eligible_case_set_digest(self) -> str: + """Return the exact eligible-case set digest.""" + return self[10] + + @property + def weight_artifact_digest(self) -> str: + """Return the point-weight artifact governed by this eligibility receipt.""" + return self[11] + + @property + def constructed_at(self) -> datetime: + """Return when the typed eligibility receipt was constructed.""" + return self[12] + + @property + def owner_contract_reference(self) -> str: + """Return the released owner-contract reference.""" + return self[13] + + @property + def owner_contract_version(self) -> int: + """Return the released owner-contract version.""" + return self[14] + + @property + def owner_contract_digest(self) -> str: + """Return the released owner-contract digest.""" + return self[15] + + @property + def released_at(self) -> datetime: + """Return when this eligibility evidence became released authority.""" + return self[16] + + +class WeightEligibilityAuthorityView(tuple): + """Field-minimized eligibility evidence issued only after authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> WeightEligibilityAuthorityView: + """Reject direct construction; only the resolver may issue this view.""" + raise TypeError( + "WeightEligibilityAuthorityView is issued only by " + "resolve_weight_eligibility_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable eligibility provenance without row-level values.""" + return self[2] + + +@runtime_checkable +class WeightEligibilityAuthorityReadPort(Protocol): + """Owner read contract for released typed weight-eligibility evidence.""" + + def read_weight_eligibility_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + eligibility_receipt_reference: str, + eligibility_receipt_digest: str, + evidence_version: int, + weight_scope_code: str, + target_population_reference: str, + target_population_digest: str, + reference_duration_reference: str, + reference_duration_digest: str, + eligible_case_set_digest: str, + weight_artifact_digest: str, + constructed_at: datetime, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> WeightEligibilityAuthorityRecord | None: + """Return matching released eligibility evidence or ``None``.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + WeightEligibilityAuthorityReadPort, "read_weight_eligibility_authority" +) + + +def resolve_weight_eligibility_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + eligibility_receipt_reference: str, + eligibility_receipt_digest: str, + evidence_version: int, + weight_scope_code: str, + target_population_reference: str, + target_population_digest: str, + reference_duration_reference: str, + reference_duration_digest: str, + eligible_case_set_digest: str, + weight_artifact_digest: str, + constructed_at: datetime, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: WeightEligibilityAuthorityReadPort, +) -> WeightEligibilityAuthorityView: + """Authorize then corroborate exact released weight-eligibility evidence.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static(type(read_port), "read_weight_eligibility_authority", None) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError( + "read_port must expose a statically callable read_weight_eligibility_authority." + ) + + requested = WeightEligibilityAuthorityRecord( + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + eligibility_receipt_reference=eligibility_receipt_reference, + eligibility_receipt_digest=eligibility_receipt_digest, + evidence_version=evidence_version, + weight_scope_code=weight_scope_code, + target_population_reference=target_population_reference, + target_population_digest=target_population_digest, + reference_duration_reference=reference_duration_reference, + reference_duration_digest=reference_duration_digest, + eligible_case_set_digest=eligible_case_set_digest, + weight_artifact_digest=weight_artifact_digest, + constructed_at=constructed_at, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + released_at=constructed_at, + ) + tenant_id = requested.tenant_record_id + study_id = requested.validity_study_id + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=requested.tenant_record_id, + validity_study_id=requested.validity_study_id, + eligibility_receipt_reference=requested.eligibility_receipt_reference, + eligibility_receipt_digest=requested.eligibility_receipt_digest, + evidence_version=requested.evidence_version, + weight_scope_code=requested.weight_scope_code, + target_population_reference=requested.target_population_reference, + target_population_digest=requested.target_population_digest, + reference_duration_reference=requested.reference_duration_reference, + reference_duration_digest=requested.reference_duration_digest, + eligible_case_set_digest=requested.eligible_case_set_digest, + weight_artifact_digest=requested.weight_artifact_digest, + constructed_at=requested.constructed_at, + owner_contract_reference=requested.owner_contract_reference, + owner_contract_version=requested.owner_contract_version, + owner_contract_digest=requested.owner_contract_digest, + ) + if persisted is None: + raise WeightEligibilityAuthorityNotFound(str(study_id)) + if type(persisted) is not WeightEligibilityAuthorityRecord: + raise WeightEligibilityAuthorityIntegrityError( + "owner port returned non-canonical weight-eligibility authority evidence" + ) + + record = WeightEligibilityAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + eligibility_receipt_reference=persisted.eligibility_receipt_reference, + eligibility_receipt_digest=persisted.eligibility_receipt_digest, + evidence_version=persisted.evidence_version, + weight_scope_code=persisted.weight_scope_code, + target_population_reference=persisted.target_population_reference, + target_population_digest=persisted.target_population_digest, + reference_duration_reference=persisted.reference_duration_reference, + reference_duration_digest=persisted.reference_duration_digest, + eligible_case_set_digest=persisted.eligible_case_set_digest, + weight_artifact_digest=persisted.weight_artifact_digest, + constructed_at=persisted.constructed_at, + owner_contract_reference=persisted.owner_contract_reference, + owner_contract_version=persisted.owner_contract_version, + owner_contract_digest=persisted.owner_contract_digest, + released_at=persisted.released_at, + ) + if record[:-1] != requested[:-1]: + raise WeightEligibilityAuthorityIntegrityError( + "released weight-eligibility authority does not match requested coordinates" + ) + if record.released_at > use_instant: + raise WeightEligibilityAuthorityIntegrityError( + "weight-eligibility evidence must be released before scientific use" + ) + + fields: tuple[tuple[str, object], ...] = ( + ("constructed_at", record.constructed_at), + ("eligibility_receipt_digest", record.eligibility_receipt_digest), + ("eligibility_receipt_reference", record.eligibility_receipt_reference), + ("eligible_case_set_digest", record.eligible_case_set_digest), + ("evidence_version", record.evidence_version), + ("owner_contract_digest", record.owner_contract_digest), + ("owner_contract_reference", record.owner_contract_reference), + ("owner_contract_version", record.owner_contract_version), + ("reference_duration_digest", record.reference_duration_digest), + ("reference_duration_reference", record.reference_duration_reference), + ("released_at", record.released_at), + ("target_population_digest", record.target_population_digest), + ("target_population_reference", record.target_population_reference), + ("weight_artifact_digest", record.weight_artifact_digest), + ("weight_scope_code", record.weight_scope_code), + ) + return tuple.__new__( + WeightEligibilityAuthorityView, + ( + _store_operational_uuid("tenant_record_id", tenant_id), + _store_operational_uuid("validity_study_id", study_id), + fields, + ), + ) From 8595e7998a169df0619e47dc00822bfb28126b6f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 18:12:39 +0900 Subject: [PATCH 118/603] feat(workforce-validation): export weight eligibility authority --- .../orgmetra_workforce_validation_api/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index 824ab2640..08984f912 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -65,6 +65,14 @@ WeightVarianceAuthorityView, resolve_weight_variance_authority, ) +from orgmetra_workforce_validation_api.weight_eligibility_authority import ( + WeightEligibilityAuthorityIntegrityError, + WeightEligibilityAuthorityNotFound, + WeightEligibilityAuthorityReadPort, + WeightEligibilityAuthorityRecord, + WeightEligibilityAuthorityView, + resolve_weight_eligibility_authority, +) __all__ = [ "CalibrationAdjustmentAuthorityIntegrityError", @@ -103,6 +111,11 @@ "ValidityStudyReadPort", "ValidityStudyRecord", "ValidityStudyView", + "WeightEligibilityAuthorityIntegrityError", + "WeightEligibilityAuthorityNotFound", + "WeightEligibilityAuthorityReadPort", + "WeightEligibilityAuthorityRecord", + "WeightEligibilityAuthorityView", "WeightVarianceAuthorityIntegrityError", "WeightVarianceAuthorityNotFound", "WeightVarianceAuthorityReadPort", @@ -115,5 +128,6 @@ "resolve_nonresponse_adjustment_authority", "resolve_validation_result_authority", "resolve_validation_result_nonverifiability", + "resolve_weight_eligibility_authority", "resolve_weight_variance_authority", ] \ No newline at end of file From c9f505207ca7e1a54c64c770a3ad85f064d9ed61 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 18:13:14 +0900 Subject: [PATCH 119/603] docs(workforce-validation): document weight eligibility authority --- services/workforce-validation-api/README.md | 94 +++++---------------- 1 file changed, 21 insertions(+), 73 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 76e5d5fe8..4dcf2a505 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -22,99 +22,47 @@ Foreign domain truth crosses this boundary only through released/versioned contr ## Calibration auxiliary authority -`resolve_calibration_auxiliary_authority(...)` corroborates #407's purpose-limited calibration input without copying protected source attributes. It binds: - -- auxiliary authority reference; -- auxiliary projection reference/version/digest; -- scientific-use purpose reference/digest; -- released owner-contract reference/version/digest; -- authorization receipt reference/digest and owner-resolved authorization interval; -- scientific-use receipt reference/digest and owner-resolved scientific-use instant. - -Caller `used_at` must equal the owner-resolved scientific-use instant, and that instant must fall inside the owner-resolved authorization interval. +`resolve_calibration_auxiliary_authority(...)` corroborates #407's purpose-limited calibration input without copying protected source attributes. It binds auxiliary authority and projection coordinates, scientific-use purpose, released owner contract, authorization receipt/interval, and scientific-use receipt/instant. Caller `used_at` must equal the owner-resolved scientific-use instant, and that instant must fall inside the owner-resolved authorization interval. ## Calibration benchmark authority -`resolve_calibration_benchmark_authority(...)` corroborates the benchmark tuple used by a calibration receipt: - -- benchmark receipt reference/version/digest; -- released benchmark-owner contract reference/version/digest; -- benchmark reference instant and owner-resolved release instants; -- append-only predecessor/successor correction lineage when a benchmark is superseded. - -The owner contract must already be released when the benchmark receipt becomes released evidence. A successor must advance the version, identify new evidence, be released after its predecessor, and exist no later than the predecessor's supersession instant. A predecessor is authoritative only on its owner-resolved half-open interval `[benchmark_receipt_released_at, benchmark_receipt_superseded_at)`. +`resolve_calibration_benchmark_authority(...)` corroborates benchmark receipt/version/digest, released benchmark-owner contract, reference/release chronology, and append-only predecessor/successor correction lineage. The owner contract must already be released when the benchmark receipt becomes released evidence; a predecessor is authoritative only on its owner-resolved half-open interval. ## Typed calibration-adjustment authority -`resolve_calibration_adjustment_authority(...)` corroborates the exact released calibration receipt that produced a point-weight artifact. It binds the receipt digest and evidence version to the purpose-limited auxiliary projection digest, benchmark receipt digest, primary algorithm/version, constraints, input/output weight artifact digests, construction time, and released owner-contract evidence. - -For `termination_code="fallback_applied"`, owner evidence must additionally preserve the primary failure reason, immutable fallback-rule reference/digest, and the actual fallback calibration algorithm/version/configuration that produced the output weights. `converged` rejects all fallback-only coordinates. The two weight-artifact digests must differ, release cannot precede construction, and the receipt cannot authorize scientific use before its owner-resolved release. Auxiliary values, benchmark totals, protected attributes, and row-level weights are excluded from the projection. - -This closes the application-owner side of #407 RED #7 without importing mutable `validity-analysis` source. It does not make caller-supplied leaf evidence self-authenticating; the durable adapter must re-resolve released typed calibration evidence from its owner. +`resolve_calibration_adjustment_authority(...)` corroborates the exact released calibration receipt that produced a point-weight artifact. It binds the receipt/evidence version to purpose-limited auxiliary and benchmark digests, primary method, constraints, artifacts, construction time, and released owner contract. `fallback_applied` additionally requires the primary failure reason, immutable fallback rule, and actual fallback algorithm/version/configuration; `converged` rejects fallback-only evidence. Raw auxiliary values, benchmark totals, protected attributes, and row-level weights are excluded. ## Typed nonresponse-adjustment authority -`resolve_nonresponse_adjustment_authority(...)` corroborates the exact released disposition-aware nonresponse receipt that produced a point-weight artifact. It binds: +`resolve_nonresponse_adjustment_authority(...)` corroborates the exact released disposition-aware nonresponse receipt. It binds receipt/evidence version, exact response/disposition receipt reference/version/digest, owner-resolved disposition release time, adjustment population, method/version/configuration, explicit ineligible/unknown/unavailable treatments, input/output weight artifacts, construction time, and released owner contract. The disposition input must already exist by adjustment construction and scientific use cannot precede the typed receipt's release. Response values, source attributes, protected attributes, and row-level weights are excluded. -- nonresponse receipt reference/digest and evidence version; -- exact response/disposition receipt reference/version/digest; -- owner-resolved response/disposition receipt release instant; -- adjustment-population digest; -- controlled method reference/version and immutable configuration digest; -- explicit ineligible, unknown, and unavailable treatment codes; -- input/output weight-artifact digests and construction time; -- released owner-contract reference/version/digest and owner-resolved receipt release instant. +## Weight-eligibility authority -The response/disposition input must already be released when the nonresponse receipt is constructed, the output artifact must differ from its input, and the nonresponse receipt cannot authorize scientific use before its owner-resolved release. Response values, source attributes, protected attributes, and row-level weights are excluded from the projection. +`resolve_weight_eligibility_authority(...)` corroborates #407 RED #9 instead of treating an eligibility digest as sufficient authority. It binds the exact `weight_eligibility_receipt` reference/digest/evidence version to: -This closes the application-owner corroboration gap for #407's versioned, disposition-aware nonresponse adjustment. The durable adapter must re-resolve the same exact receipt/version/digest and chronology from released owner evidence rather than treating a leaf adjustment digest or a missing join as authority. +- explicit `cross_sectional | longitudinal` scope; +- governed target-population reference/digest; +- governed reference-duration reference/digest; +- exact eligible-case set digest; +- exact point-weight artifact digest; +- construction time and released owner-contract reference/version/digest; +- owner-resolved eligibility-receipt release instant. -## Point-weight / variance authority +Every requested coordinate must match released owner evidence. Cross-sectional and longitudinal eligibility are distinct authority states; a different target population, reference duration, eligible-case set, or weight artifact cannot be silently reused. Release cannot precede receipt construction and scientific use cannot precede release. The projection carries no person attributes or row-level weights. -`resolve_weight_variance_authority(...)` corroborates point-estimation and variance evidence without treating leaf-provided digests as owner authority. It binds: +This is application-owner corroboration only. PR #248 or a verified successor must later re-resolve the same eligibility tuple from schema-qualified least-privilege released evidence after normal protected integration. -- released #405 sampling receipt reference/version/digest; -- final analysis-weight receipt digest; -- exact analytic-case occurrence set; -- weight-eligibility receipt digest; -- integer correction sequence; -- final point-weight artifact digest; -- distinct #406 variance-design receipt reference/version/digest; -- controlled variance method/version, evidence mode, and exact/approximate semantics; -- released owner-contract reference/version/digest and owner-resolved release instant. +## Point-weight / variance authority -A variance receipt cannot alias the point-weight receipt, and an approximation cannot be represented as exact evidence. +`resolve_weight_variance_authority(...)` corroborates released #405 sampling evidence, final analysis-weight receipt, analytic-case occurrence set, weight-eligibility receipt digest, correction sequence, final point-weight artifact, separate #406 variance-design evidence, variance method/evidence semantics, and released owner contract. A variance receipt cannot alias the point-weight receipt, and approximation evidence cannot be represented as exact. The newly separate weight-eligibility owner boundary supplies the durable scope/population/duration semantics behind the eligibility digest. ## Released validation-result authority -`resolve_validation_result_authority(...)` binds one immutable validation result to the exact weight/variance evidence it claims to use. It requires: - -- result reference/digest; -- exact `WeightVarianceCompatibilityReceipt` reference/digest; -- final analysis-weight receipt digest; -- separate variance-design receipt digest; -- non-authorizing `verification_pending | not_verifiable` state; -- released owner-contract reference/version/digest and owner-resolved release instant. - -Result, compatibility, point-weight, and variance digests must be pairwise distinct. Numerical convergence cannot be promoted to `verified` at this boundary. +`resolve_validation_result_authority(...)` binds one immutable validation result to the exact `WeightVarianceCompatibilityReceipt`, final analysis-weight receipt, separate variance-design receipt, non-authorizing `verification_pending | not_verifiable` state, and released owner contract. Numerical convergence is not promoted to `verified` at this boundary. ## Released non-verifiability outcome -`resolve_validation_result_nonverifiability(...)` is the application repair for #407 RED #12. The ordinary result-authority contract requires exact compatibility/point-weight/variance digests, so it cannot represent the case where required evidence itself is missing or cannot be reproduced. This separate contract makes that failure explicit and non-authorizing instead of allowing callers to treat lookup failure as scientific GREEN. - -`ValidationResultNonVerifiabilityRecord` fixes `verification_status` to `not_verifiable` and records exactly one failed evidence family: - -- `analysis_weight_receipt`; -- `weight_variance_compatibility_receipt`; or -- `variance_design_receipt`. - -`failure_mode` is `missing` or `non_reproducible`. - -For `missing`, failed-evidence reference/digest must both be absent; the service does not fabricate an opaque identity for evidence that does not exist. For `non_reproducible`, the exact typed failed-evidence reference and digest are required. Every released outcome additionally binds an immutable `validation_evidence_verification_attempt` reference/digest, released owner-contract reference/version/digest, `evaluated_at`, and `released_at`. Result, failed-evidence when present, verification-attempt, and owner-contract digests must be distinct. Evaluation may not occur after release, and the outcome cannot be consumed before release. - -Authorization occurs before `ValidationResultNonVerifiabilityReadPort` resolution. Returned `ValidationResultNonVerifiabilityView` contains only the minimized reason/provenance tuple; effect estimates, uncertainty values, row-level weights, replicate vectors, protected attributes, and foreign application data are excluded. - -This is still application-boundary corroboration, not durable scientific authority. A later owner persistence adapter must establish missing/non-reproducible evidence from released owner/verification-attempt evidence rather than from cross-context SQL, missing joins, or swallowed exceptions. +`resolve_validation_result_nonverifiability(...)` is the application repair for #407 RED #12. It represents required analysis-weight, weight/variance-compatibility, or variance-design evidence that is `missing | non_reproducible` without turning lookup failure into scientific GREEN. Missing evidence carries no fabricated identity; non-reproducible evidence retains the exact failed reference/digest. Every outcome binds a separate immutable verification-attempt receipt, released owner contract, and evaluation/release chronology. Effect estimates, row-level weights, replicate vectors, protected attributes, and foreign application data are excluded. ## Persistence state @@ -122,7 +70,7 @@ This is still application-boundary corroboration, not durable scientific authori The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, point-weight/variance, validation-result binding, and validation-result non-verifiability. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, weight eligibility, point-weight/variance, validation-result binding, and validation-result non-verifiability. ## Test contract @@ -137,6 +85,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback generating-method provenance, typed nonresponse disposition/treatment provenance and input-release chronology, point/variance evidence compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, cross-sectional/longitudinal weight eligibility, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. \ No newline at end of file From 9227d53ee7e0d304328447b7f489f60bdaf0aff6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 18:13:25 +0900 Subject: [PATCH 120/603] test(workforce-validation): close eligibility authority edge coverage --- ...test_weight_eligibility_authority_edges.py | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_eligibility_authority_edges.py diff --git a/services/workforce-validation-api/tests/test_weight_eligibility_authority_edges.py b/services/workforce-validation-api/tests/test_weight_eligibility_authority_edges.py new file mode 100644 index 000000000..c7a0f6483 --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_eligibility_authority_edges.py @@ -0,0 +1,41 @@ +"""Hostile edges for released weight-eligibility authority.""" + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.weight_eligibility_authority import ( + WeightEligibilityAuthorityRecord, +) + + +def _record(*, evidence_version: object = 1) -> WeightEligibilityAuthorityRecord: + return WeightEligibilityAuthorityRecord( + tenant_record_id=UUID("10000000-0000-7000-8000-000000000001"), + validity_study_id=UUID("00000000-0000-7000-8000-0000000000d1"), + eligibility_receipt_reference=( + "weight_eligibility_receipt:11111111-1111-4111-8111-111111111111" + ), + eligibility_receipt_digest="1" * 64, + evidence_version=evidence_version, + weight_scope_code="longitudinal", + target_population_reference="analysis_target_population:workers-2026q3", + target_population_digest="2" * 64, + reference_duration_reference="analysis_reference_duration:2026q3", + reference_duration_digest="3" * 64, + eligible_case_set_digest="4" * 64, + weight_artifact_digest="5" * 64, + constructed_at=datetime(2026, 9, 16, 12, 0, tzinfo=timezone.utc), + owner_contract_reference=( + "released_owner_contract:22222222-2222-4222-8222-222222222222" + ), + owner_contract_version=3, + owner_contract_digest="6" * 64, + released_at=datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc), + ) + + +def test_evidence_version_cannot_advance_without_contract_revision() -> None: + with pytest.raises(ValueError, match="evidence_version must remain 1"): + _record(evidence_version=2) From c3fca62759997b76aad2a59fc9b09f99ef7d9a17 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 18:15:33 +0900 Subject: [PATCH 121/603] test(workforce-validation): require trimming authority --- .../tests/test_trimming_bounding_authority.py | 286 ++++++++++++++++++ 1 file changed, 286 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_trimming_bounding_authority.py diff --git a/services/workforce-validation-api/tests/test_trimming_bounding_authority.py b/services/workforce-validation-api/tests/test_trimming_bounding_authority.py new file mode 100644 index 000000000..fb4bc82c9 --- /dev/null +++ b/services/workforce-validation-api/tests/test_trimming_bounding_authority.py @@ -0,0 +1,286 @@ +"""Fail-closed contract for released trimming/bounding adjustment authority.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.trimming_bounding_authority import ( + TrimmingBoundingAuthorityIntegrityError, + TrimmingBoundingAuthorityNotFound, + TrimmingBoundingAuthorityReadPort, + TrimmingBoundingAuthorityRecord, + TrimmingBoundingAuthorityView, + resolve_trimming_bounding_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000d2") +RECEIPT_REFERENCE = "trimming_bounding_adjustment_receipt:11111111-1111-4111-8111-111111111111" +RULE_REFERENCE = "weight_trimming_rule:winsor-p995-v1" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +RECEIPT_DIGEST = "1" * 64 +RULE_CONFIGURATION_DIGEST = "2" * 64 +AFFECTED_CASE_SET_DIGEST = "3" * 64 +INPUT_WEIGHT_DIGEST = "4" * 64 +OUTPUT_WEIGHT_DIGEST = "5" * 64 +OWNER_CONTRACT_DIGEST = "6" * 64 +CONSTRUCTED_AT = datetime(2026, 9, 16, 12, 0, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "adjustment_receipt_reference", + "adjustment_receipt_digest", + "evidence_version", + "rule_reference", + "rule_version", + "rule_configuration_digest", + "affected_case_occurrence_set_digest", + "affected_case_count", + "input_weight_artifact_digest", + "output_weight_artifact_digest", + "constructed_at", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "released_at", + } +) + + +class _ReadPort: + """Return configured trimming authority and retain lookup coordinates.""" + + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[dict[str, object]] = [] + + def read_trimming_bounding_authority(self, **coordinates: object) -> object: + """Capture the owner lookup and return configured evidence.""" + self.calls.append(dict(coordinates)) + return self.result + + +class _NoReadMethod: + """Deliberately fail the owner-port protocol.""" + + +class _ProtocolOnly(TrimmingBoundingAuthorityReadPort): + """Inherit only the Protocol placeholder, not a concrete owner capability.""" + + +class _DescriptorReadPort: + """Expose a descriptor that must be rejected without executing it.""" + + @property + def read_trimming_bounding_authority(self) -> object: + raise AssertionError("descriptor must not execute") + + +def _principal() -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="trimming-bounding-authority-read-v1", + resource_kind="trimming_bounding_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record(**overrides: object) -> TrimmingBoundingAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "adjustment_receipt_reference": RECEIPT_REFERENCE, + "adjustment_receipt_digest": RECEIPT_DIGEST, + "evidence_version": 1, + "rule_reference": RULE_REFERENCE, + "rule_version": 2, + "rule_configuration_digest": RULE_CONFIGURATION_DIGEST, + "affected_case_occurrence_set_digest": AFFECTED_CASE_SET_DIGEST, + "affected_case_count": 17, + "input_weight_artifact_digest": INPUT_WEIGHT_DIGEST, + "output_weight_artifact_digest": OUTPUT_WEIGHT_DIGEST, + "constructed_at": CONSTRUCTED_AT, + "owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "owner_contract_version": 3, + "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "released_at": RELEASED_AT, + } + values.update(overrides) + return TrimmingBoundingAuthorityRecord(**values) + + +def _resolve(*, read_port: object, **overrides: object) -> TrimmingBoundingAuthorityView: + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "adjustment_receipt_reference": RECEIPT_REFERENCE, + "adjustment_receipt_digest": RECEIPT_DIGEST, + "evidence_version": 1, + "rule_reference": RULE_REFERENCE, + "rule_version": 2, + "rule_configuration_digest": RULE_CONFIGURATION_DIGEST, + "affected_case_occurrence_set_digest": AFFECTED_CASE_SET_DIGEST, + "affected_case_count": 17, + "input_weight_artifact_digest": INPUT_WEIGHT_DIGEST, + "output_weight_artifact_digest": OUTPUT_WEIGHT_DIGEST, + "constructed_at": CONSTRUCTED_AT, + "owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "owner_contract_version": 3, + "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_trimming_bounding_authority(**values) + + +def test_resolution_binds_rule_affected_cases_and_artifact_lineage() -> None: + port = _ReadPort(_record()) + view = _resolve(read_port=port) + + assert isinstance(port, TrimmingBoundingAuthorityReadPort) + assert len(port.calls) == 1 + assert port.calls[0]["rule_reference"] == RULE_REFERENCE + assert port.calls[0]["affected_case_occurrence_set_digest"] == AFFECTED_CASE_SET_DIGEST + assert port.calls[0]["affected_case_count"] == 17 + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + assert ("rule_reference", RULE_REFERENCE) in view.fields + assert ("rule_version", 2) in view.fields + assert ("affected_case_count", 17) in view.fields + assert ("affected_case_occurrence_set_digest", AFFECTED_CASE_SET_DIGEST) in view.fields + assert ("output_weight_artifact_digest", OUTPUT_WEIGHT_DIGEST) in view.fields + + +def test_authorization_denial_happens_before_owner_resolution() -> None: + port = _ReadPort(_record()) + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, policy=_policy(purpose_code="audit_review")) + assert port.calls == [] + + +def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: + with pytest.raises(TrimmingBoundingAuthorityNotFound): + _resolve(read_port=_ReadPort(None)) + with pytest.raises(TrimmingBoundingAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object())) + + +@pytest.mark.parametrize( + "record_overrides", + [ + {"tenant_record_id": OTHER_TENANT}, + {"validity_study_id": OTHER_STUDY}, + {"adjustment_receipt_digest": "a" * 64}, + {"rule_reference": "weight_trimming_rule:other"}, + {"rule_version": 3}, + {"rule_configuration_digest": "b" * 64}, + {"affected_case_occurrence_set_digest": "c" * 64}, + {"affected_case_count": 18}, + {"input_weight_artifact_digest": "d" * 64}, + {"output_weight_artifact_digest": "e" * 64}, + {"constructed_at": CONSTRUCTED_AT + timedelta(seconds=1)}, + {"owner_contract_version": 4}, + {"owner_contract_digest": "f" * 64}, + ], +) +def test_owner_evidence_must_match_every_requested_coordinate( + record_overrides: dict[str, object] +) -> None: + with pytest.raises(TrimmingBoundingAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(**record_overrides))) + + +def test_artifact_alias_and_release_chronology_fail_closed() -> None: + with pytest.raises(ValueError): + _record(output_weight_artifact_digest=INPUT_WEIGHT_DIGEST) + with pytest.raises(ValueError): + _record(released_at=CONSTRUCTED_AT - timedelta(seconds=1)) + with pytest.raises(TrimmingBoundingAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(released_at=USED_AT + timedelta(seconds=1)))) + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("adjustment_receipt_reference", "wrong:receipt", ValueError), + ("adjustment_receipt_digest", "ABC", ValueError), + ("evidence_version", False, ValueError), + ("rule_reference", "wrong:rule", ValueError), + ("rule_version", 0, ValueError), + ("rule_configuration_digest", "2" * 63, ValueError), + ("affected_case_occurrence_set_digest", "3" * 65, ValueError), + ("affected_case_count", True, ValueError), + ("input_weight_artifact_digest", "4" * 63, ValueError), + ("output_weight_artifact_digest", "5" * 65, ValueError), + ("constructed_at", datetime(2026, 9, 16, 12, 0), ValueError), + ("owner_contract_reference", "wrong:contract", ValueError), + ("owner_contract_version", 0, ValueError), + ("owner_contract_digest", "6" * 63, ValueError), + ("used_at", datetime(2026, 9, 17), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_or_dependency_fails_before_owner_resolution( + key: str, value: object, error: type[Exception] +) -> None: + port: object = _ReadPort(_record()) + overrides = {key: value} + if key == "read_port": + port = value + overrides = {} + with pytest.raises(error): + _resolve(read_port=port, **overrides) + if isinstance(port, _ReadPort): + assert port.calls == [] + + +def test_record_and_view_are_structurally_immutable_and_uuid_views_are_detached() -> None: + tenant = UUID(str(TENANT)) + record = _record(tenant_record_id=tenant) + object.__setattr__(tenant, "int", OTHER_TENANT.int) + assert record.tenant_record_id == TENANT + with pytest.raises(AttributeError): + object.__setattr__(record, "affected_case_count", 18) + + view = _resolve(read_port=_ReadPort(record)) + returned_tenant = view.tenant_record_id + object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) + assert view.tenant_record_id == TENANT + with pytest.raises(AttributeError): + object.__setattr__(view, "fields", ()) + with pytest.raises(TypeError): + TrimmingBoundingAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) From a82d6c8db58ae3382b533a612545414013381be8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 18:16:08 +0900 Subject: [PATCH 122/603] feat(workforce-validation): corroborate trimming authority --- .../trimming_bounding_authority.py | 480 ++++++++++++++++++ 1 file changed, 480 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py new file mode 100644 index 000000000..d5dc58fe8 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py @@ -0,0 +1,480 @@ +"""Corroborate released trimming or bounding weight-adjustment evidence. + +This application boundary binds an exact governed trimming rule to the affected +case set and weight-artifact transition without copying case identities or +row-level weights. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + +_RESOURCE_KIND = "trimming_bounding_authority" +_OPERATION = "read" +_READ_FIELDS = frozenset( + { + "adjustment_receipt_reference", + "adjustment_receipt_digest", + "evidence_version", + "rule_reference", + "rule_version", + "rule_configuration_digest", + "affected_case_occurrence_set_digest", + "affected_case_count", + "input_weight_artifact_digest", + "output_weight_artifact_digest", + "constructed_at", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "released_at", + } +) + + +class TrimmingBoundingAuthorityNotFound(LookupError): + """Indicate that no released owner evidence corroborates the adjustment receipt.""" + + +class TrimmingBoundingAuthorityIntegrityError(RuntimeError): + """Indicate that owner evidence cannot corroborate the requested adjustment.""" + + +class TrimmingBoundingAuthorityRecord(tuple): + """Immutable owner projection for one released trimming/bounding adjustment.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + adjustment_receipt_reference: str, + adjustment_receipt_digest: str, + evidence_version: int, + rule_reference: str, + rule_version: int, + rule_configuration_digest: str, + affected_case_occurrence_set_digest: str, + affected_case_count: int, + input_weight_artifact_digest: str, + output_weight_artifact_digest: str, + constructed_at: datetime, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + released_at: datetime, + ) -> TrimmingBoundingAuthorityRecord: + """Validate and detach the minimum immutable trimming authority.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + receipt_ref = _require_reference( + "adjustment_receipt_reference", + adjustment_receipt_reference, + "trimming_bounding_adjustment_receipt", + ) + receipt_digest = _require_digest( + "adjustment_receipt_digest", adjustment_receipt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + rule_ref = _require_reference( + "rule_reference", rule_reference, "weight_trimming_rule" + ) + rule_ver = _require_positive_integer("rule_version", rule_version) + configuration = _require_digest( + "rule_configuration_digest", rule_configuration_digest + ) + affected_digest = _require_digest( + "affected_case_occurrence_set_digest", + affected_case_occurrence_set_digest, + ) + affected_count = _require_positive_integer( + "affected_case_count", affected_case_count + ) + input_digest = _require_digest( + "input_weight_artifact_digest", input_weight_artifact_digest + ) + output_digest = _require_digest( + "output_weight_artifact_digest", output_weight_artifact_digest + ) + if input_digest == output_digest: + raise ValueError( + "output_weight_artifact_digest must identify the adjusted weight artifact." + ) + constructed = _require_aware_datetime("constructed_at", constructed_at) + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + release_instant = _require_aware_datetime("released_at", released_at) + if release_instant < constructed: + raise ValueError("released_at cannot precede constructed_at.") + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + receipt_ref, + receipt_digest, + version, + rule_ref, + rule_ver, + configuration, + affected_digest, + affected_count, + input_digest, + output_digest, + constructed, + owner_ref, + owner_version, + owner_digest, + release_instant, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity for this released evidence.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity for this released evidence.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def adjustment_receipt_reference(self) -> str: + """Return the typed trimming/bounding receipt reference.""" + return self[2] + + @property + def adjustment_receipt_digest(self) -> str: + """Return the exact trimming/bounding receipt digest.""" + return self[3] + + @property + def evidence_version(self) -> int: + """Return the evidence version.""" + return self[4] + + @property + def rule_reference(self) -> str: + """Return the governed trimming-rule reference.""" + return self[5] + + @property + def rule_version(self) -> int: + """Return the governed trimming-rule version.""" + return self[6] + + @property + def rule_configuration_digest(self) -> str: + """Return the immutable trimming-rule configuration digest.""" + return self[7] + + @property + def affected_case_occurrence_set_digest(self) -> str: + """Return the exact affected-case occurrence-set digest.""" + return self[8] + + @property + def affected_case_count(self) -> int: + """Return the positive number of affected case occurrences.""" + return self[9] + + @property + def input_weight_artifact_digest(self) -> str: + """Return the input weight artifact digest.""" + return self[10] + + @property + def output_weight_artifact_digest(self) -> str: + """Return the adjusted output weight artifact digest.""" + return self[11] + + @property + def constructed_at(self) -> datetime: + """Return when the typed adjustment receipt was constructed.""" + return self[12] + + @property + def owner_contract_reference(self) -> str: + """Return the released owner-contract reference.""" + return self[13] + + @property + def owner_contract_version(self) -> int: + """Return the released owner-contract version.""" + return self[14] + + @property + def owner_contract_digest(self) -> str: + """Return the released owner-contract digest.""" + return self[15] + + @property + def released_at(self) -> datetime: + """Return when this adjustment became released authority.""" + return self[16] + + +class TrimmingBoundingAuthorityView(tuple): + """Field-minimized adjustment evidence issued only after authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> TrimmingBoundingAuthorityView: + """Reject direct construction; only the resolver may issue this view.""" + raise TypeError( + "TrimmingBoundingAuthorityView is issued only by " + "resolve_trimming_bounding_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable adjustment provenance without case identities.""" + return self[2] + + +@runtime_checkable +class TrimmingBoundingAuthorityReadPort(Protocol): + """Owner read contract for released trimming/bounding adjustment evidence.""" + + def read_trimming_bounding_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + adjustment_receipt_reference: str, + adjustment_receipt_digest: str, + evidence_version: int, + rule_reference: str, + rule_version: int, + rule_configuration_digest: str, + affected_case_occurrence_set_digest: str, + affected_case_count: int, + input_weight_artifact_digest: str, + output_weight_artifact_digest: str, + constructed_at: datetime, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> TrimmingBoundingAuthorityRecord | None: + """Return matching released adjustment evidence or ``None``.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + TrimmingBoundingAuthorityReadPort, "read_trimming_bounding_authority" +) + + +def resolve_trimming_bounding_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + adjustment_receipt_reference: str, + adjustment_receipt_digest: str, + evidence_version: int, + rule_reference: str, + rule_version: int, + rule_configuration_digest: str, + affected_case_occurrence_set_digest: str, + affected_case_count: int, + input_weight_artifact_digest: str, + output_weight_artifact_digest: str, + constructed_at: datetime, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: TrimmingBoundingAuthorityReadPort, +) -> TrimmingBoundingAuthorityView: + """Authorize then corroborate exact released trimming/bounding evidence.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static(type(read_port), "read_trimming_bounding_authority", None) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError( + "read_port must expose a statically callable read_trimming_bounding_authority." + ) + + requested = TrimmingBoundingAuthorityRecord( + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + adjustment_receipt_reference=adjustment_receipt_reference, + adjustment_receipt_digest=adjustment_receipt_digest, + evidence_version=evidence_version, + rule_reference=rule_reference, + rule_version=rule_version, + rule_configuration_digest=rule_configuration_digest, + affected_case_occurrence_set_digest=affected_case_occurrence_set_digest, + affected_case_count=affected_case_count, + input_weight_artifact_digest=input_weight_artifact_digest, + output_weight_artifact_digest=output_weight_artifact_digest, + constructed_at=constructed_at, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + released_at=constructed_at, + ) + tenant_id = requested.tenant_record_id + study_id = requested.validity_study_id + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=requested.tenant_record_id, + validity_study_id=requested.validity_study_id, + adjustment_receipt_reference=requested.adjustment_receipt_reference, + adjustment_receipt_digest=requested.adjustment_receipt_digest, + evidence_version=requested.evidence_version, + rule_reference=requested.rule_reference, + rule_version=requested.rule_version, + rule_configuration_digest=requested.rule_configuration_digest, + affected_case_occurrence_set_digest=requested.affected_case_occurrence_set_digest, + affected_case_count=requested.affected_case_count, + input_weight_artifact_digest=requested.input_weight_artifact_digest, + output_weight_artifact_digest=requested.output_weight_artifact_digest, + constructed_at=requested.constructed_at, + owner_contract_reference=requested.owner_contract_reference, + owner_contract_version=requested.owner_contract_version, + owner_contract_digest=requested.owner_contract_digest, + ) + if persisted is None: + raise TrimmingBoundingAuthorityNotFound(str(study_id)) + if type(persisted) is not TrimmingBoundingAuthorityRecord: + raise TrimmingBoundingAuthorityIntegrityError( + "owner port returned non-canonical trimming/bounding authority evidence" + ) + + record = TrimmingBoundingAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + adjustment_receipt_reference=persisted.adjustment_receipt_reference, + adjustment_receipt_digest=persisted.adjustment_receipt_digest, + evidence_version=persisted.evidence_version, + rule_reference=persisted.rule_reference, + rule_version=persisted.rule_version, + rule_configuration_digest=persisted.rule_configuration_digest, + affected_case_occurrence_set_digest=persisted.affected_case_occurrence_set_digest, + affected_case_count=persisted.affected_case_count, + input_weight_artifact_digest=persisted.input_weight_artifact_digest, + output_weight_artifact_digest=persisted.output_weight_artifact_digest, + constructed_at=persisted.constructed_at, + owner_contract_reference=persisted.owner_contract_reference, + owner_contract_version=persisted.owner_contract_version, + owner_contract_digest=persisted.owner_contract_digest, + released_at=persisted.released_at, + ) + if record[:-1] != requested[:-1]: + raise TrimmingBoundingAuthorityIntegrityError( + "released trimming/bounding authority does not match requested coordinates" + ) + if record.released_at > use_instant: + raise TrimmingBoundingAuthorityIntegrityError( + "trimming/bounding evidence must be released before scientific use" + ) + + fields: tuple[tuple[str, object], ...] = ( + ("adjustment_receipt_digest", record.adjustment_receipt_digest), + ("adjustment_receipt_reference", record.adjustment_receipt_reference), + ("affected_case_count", record.affected_case_count), + ("affected_case_occurrence_set_digest", record.affected_case_occurrence_set_digest), + ("constructed_at", record.constructed_at), + ("evidence_version", record.evidence_version), + ("input_weight_artifact_digest", record.input_weight_artifact_digest), + ("output_weight_artifact_digest", record.output_weight_artifact_digest), + ("owner_contract_digest", record.owner_contract_digest), + ("owner_contract_reference", record.owner_contract_reference), + ("owner_contract_version", record.owner_contract_version), + ("released_at", record.released_at), + ("rule_configuration_digest", record.rule_configuration_digest), + ("rule_reference", record.rule_reference), + ("rule_version", record.rule_version), + ) + return tuple.__new__( + TrimmingBoundingAuthorityView, + ( + _store_operational_uuid("tenant_record_id", tenant_id), + _store_operational_uuid("validity_study_id", study_id), + fields, + ), + ) From d414cb6d4638735a4beb4315a7e8b9e0daca610d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 18:16:28 +0900 Subject: [PATCH 123/603] feat(workforce-validation): export trimming authority --- .../orgmetra_workforce_validation_api/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index 08984f912..34d3203bc 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -57,6 +57,14 @@ CalibrationAuxiliaryAuthorityView, resolve_calibration_auxiliary_authority, ) +from orgmetra_workforce_validation_api.trimming_bounding_authority import ( + TrimmingBoundingAuthorityIntegrityError, + TrimmingBoundingAuthorityNotFound, + TrimmingBoundingAuthorityReadPort, + TrimmingBoundingAuthorityRecord, + TrimmingBoundingAuthorityView, + resolve_trimming_bounding_authority, +) from orgmetra_workforce_validation_api.variance_authority import ( WeightVarianceAuthorityIntegrityError, WeightVarianceAuthorityNotFound, @@ -95,6 +103,11 @@ "NonresponseAdjustmentAuthorityReadPort", "NonresponseAdjustmentAuthorityRecord", "NonresponseAdjustmentAuthorityView", + "TrimmingBoundingAuthorityIntegrityError", + "TrimmingBoundingAuthorityNotFound", + "TrimmingBoundingAuthorityReadPort", + "TrimmingBoundingAuthorityRecord", + "TrimmingBoundingAuthorityView", "ValidationPrincipal", "ValidationResultAuthorityIntegrityError", "ValidationResultAuthorityNotFound", @@ -126,6 +139,7 @@ "resolve_calibration_auxiliary_authority", "resolve_calibration_benchmark_authority", "resolve_nonresponse_adjustment_authority", + "resolve_trimming_bounding_authority", "resolve_validation_result_authority", "resolve_validation_result_nonverifiability", "resolve_weight_eligibility_authority", From a69b5711f24a0a030ce78775cc489b1e19b1a632 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 18:16:53 +0900 Subject: [PATCH 124/603] docs(workforce-validation): document trimming authority --- services/workforce-validation-api/README.md | 22 ++++++++------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 4dcf2a505..d15a4d85e 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -36,25 +36,19 @@ Foreign domain truth crosses this boundary only through released/versioned contr `resolve_nonresponse_adjustment_authority(...)` corroborates the exact released disposition-aware nonresponse receipt. It binds receipt/evidence version, exact response/disposition receipt reference/version/digest, owner-resolved disposition release time, adjustment population, method/version/configuration, explicit ineligible/unknown/unavailable treatments, input/output weight artifacts, construction time, and released owner contract. The disposition input must already exist by adjustment construction and scientific use cannot precede the typed receipt's release. Response values, source attributes, protected attributes, and row-level weights are excluded. -## Weight-eligibility authority +## Trimming/bounding adjustment authority -`resolve_weight_eligibility_authority(...)` corroborates #407 RED #9 instead of treating an eligibility digest as sufficient authority. It binds the exact `weight_eligibility_receipt` reference/digest/evidence version to: +`resolve_trimming_bounding_authority(...)` corroborates the exact released trimming or bounding receipt rather than trusting an adjustment-chain digest alone. It binds the typed receipt reference/digest/evidence version to the governed `weight_trimming_rule` reference/version, immutable rule configuration, exact affected-case occurrence-set digest and positive affected-case count, input/output weight-artifact transition, construction time and released owner-contract tuple. Input and output artifacts may not alias; release cannot precede construction or scientific use. Case identities and row-level weights are excluded from the projection. -- explicit `cross_sectional | longitudinal` scope; -- governed target-population reference/digest; -- governed reference-duration reference/digest; -- exact eligible-case set digest; -- exact point-weight artifact digest; -- construction time and released owner-contract reference/version/digest; -- owner-resolved eligibility-receipt release instant. +This preserves the evidence needed to reproduce which governed trimming/bounding rule changed which case occurrence set without copying those cases into `workforce_validation`. PR #248 or a verified successor must later re-resolve the same tuple from released owner evidence. -Every requested coordinate must match released owner evidence. Cross-sectional and longitudinal eligibility are distinct authority states; a different target population, reference duration, eligible-case set, or weight artifact cannot be silently reused. Release cannot precede receipt construction and scientific use cannot precede release. The projection carries no person attributes or row-level weights. +## Weight-eligibility authority -This is application-owner corroboration only. PR #248 or a verified successor must later re-resolve the same eligibility tuple from schema-qualified least-privilege released evidence after normal protected integration. +`resolve_weight_eligibility_authority(...)` corroborates #407 RED #9 instead of treating an eligibility digest as sufficient authority. It binds the exact `weight_eligibility_receipt` reference/digest/evidence version to explicit `cross_sectional | longitudinal` scope, governed target-population and reference-duration coordinates, exact eligible-case set, exact point-weight artifact, construction time, released owner-contract tuple, and owner-resolved receipt release time. Cross-sectional and longitudinal eligibility are distinct authority states; a different population, duration, case set, or artifact cannot be silently reused. Person attributes and row-level weights are excluded. ## Point-weight / variance authority -`resolve_weight_variance_authority(...)` corroborates released #405 sampling evidence, final analysis-weight receipt, analytic-case occurrence set, weight-eligibility receipt digest, correction sequence, final point-weight artifact, separate #406 variance-design evidence, variance method/evidence semantics, and released owner contract. A variance receipt cannot alias the point-weight receipt, and approximation evidence cannot be represented as exact. The newly separate weight-eligibility owner boundary supplies the durable scope/population/duration semantics behind the eligibility digest. +`resolve_weight_variance_authority(...)` corroborates released #405 sampling evidence, final analysis-weight receipt, analytic-case occurrence set, weight-eligibility receipt digest, correction sequence, final point-weight artifact, separate #406 variance-design evidence, variance method/evidence semantics, and released owner contract. A variance receipt cannot alias the point-weight receipt, and approximation evidence cannot be represented as exact. The separate eligibility authority supplies the durable scope/population/duration semantics behind the eligibility digest. ## Released validation-result authority @@ -70,7 +64,7 @@ This is application-owner corroboration only. PR #248 or a verified successor mu The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, weight eligibility, point-weight/variance, validation-result binding, and validation-result non-verifiability. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, point-weight/variance, validation-result binding, and validation-result non-verifiability. ## Test contract @@ -85,6 +79,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, cross-sectional/longitudinal weight eligibility, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. \ No newline at end of file From e852ba545357ffd3ce56b88145cffa893e0781f8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 18:17:01 +0900 Subject: [PATCH 125/603] test(workforce-validation): close trimming authority edge coverage --- .../test_trimming_bounding_authority_edges.py | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_trimming_bounding_authority_edges.py diff --git a/services/workforce-validation-api/tests/test_trimming_bounding_authority_edges.py b/services/workforce-validation-api/tests/test_trimming_bounding_authority_edges.py new file mode 100644 index 000000000..b215703c7 --- /dev/null +++ b/services/workforce-validation-api/tests/test_trimming_bounding_authority_edges.py @@ -0,0 +1,41 @@ +"""Hostile edges for released trimming/bounding authority.""" + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.trimming_bounding_authority import ( + TrimmingBoundingAuthorityRecord, +) + + +def _record(*, evidence_version: object = 1) -> TrimmingBoundingAuthorityRecord: + return TrimmingBoundingAuthorityRecord( + tenant_record_id=UUID("10000000-0000-7000-8000-000000000001"), + validity_study_id=UUID("00000000-0000-7000-8000-0000000000d1"), + adjustment_receipt_reference=( + "trimming_bounding_adjustment_receipt:11111111-1111-4111-8111-111111111111" + ), + adjustment_receipt_digest="1" * 64, + evidence_version=evidence_version, + rule_reference="weight_trimming_rule:winsor-p995-v1", + rule_version=2, + rule_configuration_digest="2" * 64, + affected_case_occurrence_set_digest="3" * 64, + affected_case_count=17, + input_weight_artifact_digest="4" * 64, + output_weight_artifact_digest="5" * 64, + constructed_at=datetime(2026, 9, 16, 12, 0, tzinfo=timezone.utc), + owner_contract_reference=( + "released_owner_contract:22222222-2222-4222-8222-222222222222" + ), + owner_contract_version=3, + owner_contract_digest="6" * 64, + released_at=datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc), + ) + + +def test_evidence_version_cannot_advance_without_contract_revision() -> None: + with pytest.raises(ValueError, match="evidence_version must remain 1"): + _record(evidence_version=2) From 86b18d52b7f898b99566836588e54b6ccf487e37 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 19:07:06 +0900 Subject: [PATCH 126/603] test(workforce-validation): add final weight authority RED --- .../test_final_analysis_weight_authority.py | 422 ++++++++++++++++++ 1 file changed, 422 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_analysis_weight_authority.py diff --git a/services/workforce-validation-api/tests/test_final_analysis_weight_authority.py b/services/workforce-validation-api/tests/test_final_analysis_weight_authority.py new file mode 100644 index 000000000..09f422045 --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_analysis_weight_authority.py @@ -0,0 +1,422 @@ +"""Fail-closed contract for complete released final analysis-weight provenance.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.final_weight_authority import ( + FinalAnalysisWeightAuthorityIntegrityError, + FinalAnalysisWeightAuthorityNotFound, + FinalAnalysisWeightAuthorityReadPort, + FinalAnalysisWeightAuthorityRecord, + FinalAnalysisWeightAuthorityView, + FinalWeightAdjustmentCoordinate, + resolve_final_analysis_weight_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000f2") +WEIGHT_RECEIPT_REFERENCE = "analysis_weight_receipt:11111111-1111-4111-8111-111111111111" +ESTIMAND_REFERENCE = "validation_estimand:criterion-validity-q3" +TARGET_REFERENCE = "analysis_target_population:workers-2026q3" +WINDOW_REFERENCE = "analysis_window:2026q3" +DURATION_REFERENCE = "analysis_reference_duration:2026q3" +SOURCE_REFERENCE = "source_universe_receipt:22222222-2222-4222-8222-222222222222" +SAMPLING_REFERENCE = "sampling_design_receipt:33333333-3333-4333-8333-333333333333" +ELIGIBILITY_REFERENCE = "weight_eligibility_receipt:44444444-4444-4444-8444-444444444444" +OWNER_REFERENCE = "released_owner_contract:55555555-5555-4555-8555-555555555555" +METHOD_REFERENCE = "weight_method:nonresponse-cell-adjustment" +WEIGHT_RECEIPT_DIGEST = "1" * 64 +ESTIMAND_DIGEST = "2" * 64 +TARGET_DIGEST = "3" * 64 +DURATION_DIGEST = "4" * 64 +ELIGIBLE_CASE_DIGEST = "5" * 64 +ANALYTIC_CASE_DIGEST = "6" * 64 +SOURCE_DIGEST = "7" * 64 +SAMPLING_DIGEST = "8" * 64 +BASE_EVIDENCE_DIGEST = "9" * 64 +BASE_ARTIFACT_DIGEST = "a" * 64 +ADJUSTED_ARTIFACT_DIGEST = "b" * 64 +ADJUSTMENT_CONFIG_DIGEST = "c" * 64 +ADJUSTMENT_RECEIPT_DIGEST = "d" * 64 +ELIGIBILITY_DIGEST = "e" * 64 +OWNER_DIGEST = "f" * 64 +SUPERSEDES_DIGEST = "0" * 64 +CONSTRUCTED_AT = datetime(2026, 9, 17, 8, 0, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 8, 30, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 9, 0, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "analysis_weight_receipt_reference", + "analysis_weight_receipt_digest", + "evidence_version", + "estimand_reference", + "estimand_digest", + "estimand_scope_code", + "target_population_reference", + "target_population_digest", + "analysis_unit_code", + "analysis_window_reference", + "reference_duration_reference", + "reference_duration_digest", + "eligible_case_set_digest", + "analytic_case_occurrence_set_digest", + "source_universe_receipt_reference", + "source_universe_receipt_version", + "source_universe_receipt_digest", + "sampling_design_receipt_reference", + "sampling_design_receipt_version", + "sampling_design_receipt_digest", + "base_weight_method_code", + "base_weight_method_version", + "base_weight_evidence_digest", + "base_weight_artifact_digest", + "adjustments", + "final_weight_artifact_digest", + "weight_eligibility_receipt_reference", + "weight_eligibility_receipt_digest", + "analytic_case_count", + "constructed_at", + "correction_sequence", + "supersedes_receipt_digest", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "released_at", + } +) + + +class _ReadPort: + """Return configured released final-weight authority and capture lookup coordinates.""" + + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[dict[str, object]] = [] + + def read_final_analysis_weight_authority(self, **coordinates: object) -> object: + self.calls.append(dict(coordinates)) + return self.result + + +class _ProtocolOnly(FinalAnalysisWeightAuthorityReadPort): + """Inherit only the Protocol placeholder.""" + + +class _DescriptorReadPort: + """Expose a descriptor that must not execute.""" + + @property + def read_final_analysis_weight_authority(self) -> object: + raise AssertionError("descriptor must not execute") + + +class _NoReadMethod: + """Deliberately omit the owner capability.""" + + +def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=tenant_record_id, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="final-analysis-weight-authority-read-v1", + resource_kind="final_analysis_weight_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _adjustment(**overrides: object) -> FinalWeightAdjustmentCoordinate: + values: dict[str, object] = { + "sequence_number": 1, + "adjustment_code": "nonresponse_adjustment", + "method_reference": METHOD_REFERENCE, + "method_version": 2, + "input_weight_artifact_digest": BASE_ARTIFACT_DIGEST, + "output_weight_artifact_digest": ADJUSTED_ARTIFACT_DIGEST, + "configuration_digest": ADJUSTMENT_CONFIG_DIGEST, + "evidence_receipt_digest": ADJUSTMENT_RECEIPT_DIGEST, + "evidence_kind": "nonresponse_adjustment_receipt", + } + values.update(overrides) + return FinalWeightAdjustmentCoordinate(**values) + + +def _record(**overrides: object) -> FinalAnalysisWeightAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "analysis_weight_receipt_reference": WEIGHT_RECEIPT_REFERENCE, + "analysis_weight_receipt_digest": WEIGHT_RECEIPT_DIGEST, + "evidence_version": 1, + "estimand_reference": ESTIMAND_REFERENCE, + "estimand_digest": ESTIMAND_DIGEST, + "estimand_scope_code": "longitudinal", + "target_population_reference": TARGET_REFERENCE, + "target_population_digest": TARGET_DIGEST, + "analysis_unit_code": "person_occurrence", + "analysis_window_reference": WINDOW_REFERENCE, + "reference_duration_reference": DURATION_REFERENCE, + "reference_duration_digest": DURATION_DIGEST, + "eligible_case_set_digest": ELIGIBLE_CASE_DIGEST, + "analytic_case_occurrence_set_digest": ANALYTIC_CASE_DIGEST, + "source_universe_receipt_reference": SOURCE_REFERENCE, + "source_universe_receipt_version": 4, + "source_universe_receipt_digest": SOURCE_DIGEST, + "sampling_design_receipt_reference": SAMPLING_REFERENCE, + "sampling_design_receipt_version": 3, + "sampling_design_receipt_digest": SAMPLING_DIGEST, + "base_weight_method_code": "inverse_inclusion_probability", + "base_weight_method_version": 1, + "base_weight_evidence_digest": BASE_EVIDENCE_DIGEST, + "base_weight_artifact_digest": BASE_ARTIFACT_DIGEST, + "adjustments": (_adjustment(),), + "final_weight_artifact_digest": ADJUSTED_ARTIFACT_DIGEST, + "weight_eligibility_receipt_reference": ELIGIBILITY_REFERENCE, + "weight_eligibility_receipt_digest": ELIGIBILITY_DIGEST, + "analytic_case_count": 1200, + "constructed_at": CONSTRUCTED_AT, + "correction_sequence": 1, + "supersedes_receipt_digest": None, + "owner_contract_reference": OWNER_REFERENCE, + "owner_contract_version": 7, + "owner_contract_digest": OWNER_DIGEST, + "released_at": RELEASED_AT, + } + values.update(overrides) + return FinalAnalysisWeightAuthorityRecord(**values) + + +def _resolve(*, read_port: object, **overrides: object) -> FinalAnalysisWeightAuthorityView: + values = dict(_record().fields) + values.update( + { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + ) + values.update(overrides) + return resolve_final_analysis_weight_authority(**values) + + +def test_resolution_binds_complete_estimand_source_base_adjustment_and_final_artifact() -> None: + port = _ReadPort(_record()) + + view = _resolve(read_port=port) + + assert isinstance(port, FinalAnalysisWeightAuthorityReadPort) + assert len(port.calls) == 1 + assert port.calls[0]["source_universe_receipt_reference"] == SOURCE_REFERENCE + assert port.calls[0]["sampling_design_receipt_version"] == 3 + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + assert ("estimand_reference", ESTIMAND_REFERENCE) in view.fields + assert ("source_universe_receipt_digest", SOURCE_DIGEST) in view.fields + assert ("base_weight_evidence_digest", BASE_EVIDENCE_DIGEST) in view.fields + assert ("final_weight_artifact_digest", ADJUSTED_ARTIFACT_DIGEST) in view.fields + assert ("released_at", RELEASED_AT) in view.fields + adjustment = dict(view.fields)["adjustments"][0] + assert tuple(adjustment) == tuple(_adjustment()) + assert adjustment.sequence_number == 1 + assert adjustment.adjustment_code == "nonresponse_adjustment" + assert adjustment.method_reference == METHOD_REFERENCE + assert adjustment.method_version == 2 + assert adjustment.input_weight_artifact_digest == BASE_ARTIFACT_DIGEST + assert adjustment.output_weight_artifact_digest == ADJUSTED_ARTIFACT_DIGEST + assert adjustment.configuration_digest == ADJUSTMENT_CONFIG_DIGEST + assert adjustment.evidence_receipt_digest == ADJUSTMENT_RECEIPT_DIGEST + assert adjustment.evidence_kind == "nonresponse_adjustment_receipt" + + +def test_authorization_denial_happens_before_owner_resolution() -> None: + port = _ReadPort(_record()) + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, policy=_policy(purpose_code="audit_review")) + assert port.calls == [] + + +def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: + with pytest.raises(FinalAnalysisWeightAuthorityNotFound): + _resolve(read_port=_ReadPort(None)) + with pytest.raises(FinalAnalysisWeightAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object())) + + +@pytest.mark.parametrize( + "record_overrides", + [ + {"tenant_record_id": OTHER_TENANT}, + {"validity_study_id": OTHER_STUDY}, + {"estimand_digest": "a" * 64}, + {"estimand_scope_code": "cross_sectional"}, + {"target_population_digest": "b" * 64}, + {"analysis_unit_code": "household"}, + {"analysis_window_reference": "analysis_window:other"}, + {"reference_duration_digest": "c" * 64}, + {"eligible_case_set_digest": "d" * 64}, + {"analytic_case_occurrence_set_digest": "e" * 64}, + {"source_universe_receipt_version": 5}, + {"source_universe_receipt_digest": "f" * 64}, + {"sampling_design_receipt_version": 4}, + {"sampling_design_receipt_digest": "0" * 64}, + {"base_weight_method_code": "equal_weight"}, + {"base_weight_method_version": 2}, + {"base_weight_evidence_digest": "a" * 64}, + {"weight_eligibility_receipt_digest": "b" * 64}, + {"analytic_case_count": 1199}, + {"constructed_at": CONSTRUCTED_AT + timedelta(seconds=1)}, + {"owner_contract_version": 8}, + {"owner_contract_digest": "c" * 64}, + ], +) +def test_owner_evidence_must_match_every_material_requested_coordinate( + record_overrides: dict[str, object], +) -> None: + with pytest.raises(FinalAnalysisWeightAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(**record_overrides))) + + +def test_chain_correction_and_release_chronology_fail_closed() -> None: + with pytest.raises(ValueError): + _record(adjustments=[]) + with pytest.raises(ValueError): + _record(adjustments=(_adjustment(sequence_number=2),)) + with pytest.raises(ValueError): + _record(adjustments=(_adjustment(input_weight_artifact_digest="0" * 64),)) + with pytest.raises(ValueError): + _record(final_weight_artifact_digest="0" * 64) + with pytest.raises(ValueError): + _record(correction_sequence=1, supersedes_receipt_digest=SUPERSEDES_DIGEST) + with pytest.raises(ValueError): + _record(correction_sequence=2, supersedes_receipt_digest=None) + with pytest.raises(ValueError): + _record(correction_sequence=2, supersedes_receipt_digest=WEIGHT_RECEIPT_DIGEST) + corrected = _record(correction_sequence=2, supersedes_receipt_digest=SUPERSEDES_DIGEST) + assert ("correction_sequence", 2) in corrected.fields + with pytest.raises(ValueError): + _record(released_at=CONSTRUCTED_AT - timedelta(seconds=1)) + with pytest.raises(FinalAnalysisWeightAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(released_at=USED_AT + timedelta(seconds=1)))) + + +def test_adjustment_semantics_are_typed_and_no_op_transform_is_rejected() -> None: + with pytest.raises(ValueError): + _adjustment(evidence_kind="generic_weight_evidence") + with pytest.raises(ValueError): + _adjustment(output_weight_artifact_digest=BASE_ARTIFACT_DIGEST) + generic = _adjustment( + adjustment_code="custom_transform", + evidence_kind="custom_transform_receipt", + ) + assert generic.evidence_kind == "custom_transform_receipt" + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("analysis_weight_receipt_reference", "wrong:receipt", ValueError), + ("analysis_weight_receipt_digest", "ABC", ValueError), + ("evidence_version", False, ValueError), + ("estimand_reference", "wrong:estimand", ValueError), + ("estimand_digest", "2" * 63, ValueError), + ("estimand_scope_code", "panel", ValueError), + ("target_population_reference", "wrong:population", ValueError), + ("target_population_digest", "3" * 63, ValueError), + ("analysis_unit_code", "Person Occurrence", ValueError), + ("analysis_window_reference", "wrong:window", ValueError), + ("reference_duration_reference", "wrong:duration", ValueError), + ("reference_duration_digest", "4" * 63, ValueError), + ("eligible_case_set_digest", "5" * 63, ValueError), + ("analytic_case_occurrence_set_digest", "6" * 63, ValueError), + ("source_universe_receipt_reference", "wrong:source", ValueError), + ("source_universe_receipt_version", 0, ValueError), + ("source_universe_receipt_digest", "7" * 63, ValueError), + ("sampling_design_receipt_reference", "wrong:sampling", ValueError), + ("sampling_design_receipt_version", 0, ValueError), + ("sampling_design_receipt_digest", "8" * 63, ValueError), + ("base_weight_method_code", "Inverse Probability", ValueError), + ("base_weight_method_version", False, ValueError), + ("base_weight_evidence_digest", "9" * 63, ValueError), + ("base_weight_artifact_digest", "a" * 63, ValueError), + ("adjustments", (_adjustment(), object()), ValueError), + ("final_weight_artifact_digest", "b" * 63, ValueError), + ("weight_eligibility_receipt_reference", "wrong:eligibility", ValueError), + ("weight_eligibility_receipt_digest", "e" * 63, ValueError), + ("analytic_case_count", 0, ValueError), + ("constructed_at", datetime(2026, 9, 17, 8, 0), ValueError), + ("correction_sequence", False, ValueError), + ("owner_contract_reference", "wrong:contract", ValueError), + ("owner_contract_version", 0, ValueError), + ("owner_contract_digest", "f" * 63, ValueError), + ("used_at", datetime(2026, 9, 17, 9, 0), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_or_dependency_fails_before_owner_resolution( + key: str, value: object, error: type[Exception] +) -> None: + port: object = _ReadPort(_record()) + overrides = {key: value} + if key == "read_port": + port = value + overrides = {} + with pytest.raises(error): + _resolve(read_port=port, **overrides) + if isinstance(port, _ReadPort): + assert port.calls == [] + + +def test_record_adjustment_and_view_are_structurally_immutable() -> None: + adjustment = _adjustment() + with pytest.raises(AttributeError): + object.__setattr__(adjustment, "sequence_number", 2) + + tenant = UUID(str(TENANT)) + record = _record(tenant_record_id=tenant) + object.__setattr__(tenant, "int", OTHER_TENANT.int) + assert record.tenant_record_id == TENANT + assert record.validity_study_id == STUDY + assert record.released_at == RELEASED_AT + with pytest.raises(AttributeError): + object.__setattr__(record, "fields", ()) + + view = _resolve(read_port=_ReadPort(record)) + returned_tenant = view.tenant_record_id + object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) + assert view.tenant_record_id == TENANT + with pytest.raises(AttributeError): + object.__setattr__(view, "fields", ()) + with pytest.raises(TypeError): + FinalAnalysisWeightAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) From 7db64f8e2c3a5ebaca64605c0992088d2815be35 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 19:07:58 +0900 Subject: [PATCH 127/603] feat(workforce-validation): corroborate complete final weight lineage --- .../final_weight_authority.py | 731 ++++++++++++++++++ 1 file changed, 731 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py new file mode 100644 index 000000000..b445d18c4 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py @@ -0,0 +1,731 @@ +"""Corroborate the complete released final analysis-weight construction. + +This application boundary verifies the scientific coordinates needed to reproduce +one final point-estimation weight receipt without importing mutable validity- +analysis source, copying row-level weights, or querying foreign application +tables. Durable persistence remains the responsibility of the owner adapter. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + +_RESOURCE_KIND = "final_analysis_weight_authority" +_OPERATION = "read" +_WEIGHT_SCOPE_CODES = frozenset({"cross_sectional", "longitudinal"}) +_SPECIALIZED_EVIDENCE_KIND_BY_ADJUSTMENT_CODE = { + "nonresponse_adjustment": "nonresponse_adjustment_receipt", + "calibration_adjustment": "calibration_adjustment_receipt", + "raking_adjustment": "calibration_adjustment_receipt", + "poststratification_adjustment": "calibration_adjustment_receipt", + "weight_trimming_adjustment": "trimming_bounding_adjustment_receipt", + "weight_bounding_adjustment": "trimming_bounding_adjustment_receipt", + "weight_winsorization_adjustment": "trimming_bounding_adjustment_receipt", +} +_READ_FIELDS = frozenset( + { + "analysis_weight_receipt_reference", + "analysis_weight_receipt_digest", + "evidence_version", + "estimand_reference", + "estimand_digest", + "estimand_scope_code", + "target_population_reference", + "target_population_digest", + "analysis_unit_code", + "analysis_window_reference", + "reference_duration_reference", + "reference_duration_digest", + "eligible_case_set_digest", + "analytic_case_occurrence_set_digest", + "source_universe_receipt_reference", + "source_universe_receipt_version", + "source_universe_receipt_digest", + "sampling_design_receipt_reference", + "sampling_design_receipt_version", + "sampling_design_receipt_digest", + "base_weight_method_code", + "base_weight_method_version", + "base_weight_evidence_digest", + "base_weight_artifact_digest", + "adjustments", + "final_weight_artifact_digest", + "weight_eligibility_receipt_reference", + "weight_eligibility_receipt_digest", + "analytic_case_count", + "constructed_at", + "correction_sequence", + "supersedes_receipt_digest", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "released_at", + } +) + + +class FinalAnalysisWeightAuthorityNotFound(LookupError): + """Indicate that no released owner evidence corroborates the final-weight receipt.""" + + +class FinalAnalysisWeightAuthorityIntegrityError(RuntimeError): + """Indicate that owner evidence cannot corroborate the requested final-weight lineage.""" + + +def _require_weight_scope(value: object) -> str: + """Require explicit cross-sectional or longitudinal estimand semantics.""" + if type(value) is not str or value not in _WEIGHT_SCOPE_CODES: + raise ValueError("estimand_scope_code must be cross_sectional or longitudinal.") + return value + + +class FinalWeightAdjustmentCoordinate(tuple): + """Immutable, value-minimized coordinate for one ordered weight transform.""" + + __slots__ = () + + def __new__( + cls, + *, + sequence_number: int, + adjustment_code: str, + method_reference: str, + method_version: int, + input_weight_artifact_digest: str, + output_weight_artifact_digest: str, + configuration_digest: str, + evidence_receipt_digest: str, + evidence_kind: str, + ) -> FinalWeightAdjustmentCoordinate: + """Validate one transform without storing case-level weight values.""" + sequence = _require_positive_integer("sequence_number", sequence_number) + code = _require_code("adjustment_code", adjustment_code) + method_ref = _require_reference("method_reference", method_reference, "weight_method") + method_ver = _require_positive_integer("method_version", method_version) + input_digest = _require_digest( + "input_weight_artifact_digest", input_weight_artifact_digest + ) + output_digest = _require_digest( + "output_weight_artifact_digest", output_weight_artifact_digest + ) + config_digest = _require_digest("configuration_digest", configuration_digest) + evidence_digest = _require_digest("evidence_receipt_digest", evidence_receipt_digest) + kind = _require_code("evidence_kind", evidence_kind) + required_kind = _SPECIALIZED_EVIDENCE_KIND_BY_ADJUSTMENT_CODE.get(code) + if required_kind is not None and kind != required_kind: + raise ValueError(f"{code} requires evidence_kind {required_kind}.") + if input_digest == output_digest: + raise ValueError( + "output_weight_artifact_digest must identify the transformed weight artifact." + ) + return tuple.__new__( + cls, + ( + sequence, + code, + method_ref, + method_ver, + input_digest, + output_digest, + config_digest, + evidence_digest, + kind, + ), + ) + + @property + def sequence_number(self) -> int: + """Return the one-based transform order.""" + return self[0] + + @property + def adjustment_code(self) -> str: + """Return the controlled adjustment code.""" + return self[1] + + @property + def method_reference(self) -> str: + """Return the controlled weight-method reference.""" + return self[2] + + @property + def method_version(self) -> int: + """Return the positive weight-method version.""" + return self[3] + + @property + def input_weight_artifact_digest(self) -> str: + """Return the transform input artifact digest.""" + return self[4] + + @property + def output_weight_artifact_digest(self) -> str: + """Return the transform output artifact digest.""" + return self[5] + + @property + def configuration_digest(self) -> str: + """Return the immutable transform configuration digest.""" + return self[6] + + @property + def evidence_receipt_digest(self) -> str: + """Return the immutable supporting evidence-receipt digest.""" + return self[7] + + @property + def evidence_kind(self) -> str: + """Return the typed supporting evidence kind.""" + return self[8] + + +class FinalAnalysisWeightAuthorityRecord(tuple): + """Immutable owner projection for one complete released final-weight receipt.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + analysis_weight_receipt_reference: str, + analysis_weight_receipt_digest: str, + evidence_version: int, + estimand_reference: str, + estimand_digest: str, + estimand_scope_code: str, + target_population_reference: str, + target_population_digest: str, + analysis_unit_code: str, + analysis_window_reference: str, + reference_duration_reference: str, + reference_duration_digest: str, + eligible_case_set_digest: str, + analytic_case_occurrence_set_digest: str, + source_universe_receipt_reference: str, + source_universe_receipt_version: int, + source_universe_receipt_digest: str, + sampling_design_receipt_reference: str, + sampling_design_receipt_version: int, + sampling_design_receipt_digest: str, + base_weight_method_code: str, + base_weight_method_version: int, + base_weight_evidence_digest: str, + base_weight_artifact_digest: str, + adjustments: tuple[FinalWeightAdjustmentCoordinate, ...], + final_weight_artifact_digest: str, + weight_eligibility_receipt_reference: str, + weight_eligibility_receipt_digest: str, + analytic_case_count: int, + constructed_at: datetime, + correction_sequence: int, + supersedes_receipt_digest: str | None, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + released_at: datetime, + ) -> FinalAnalysisWeightAuthorityRecord: + """Validate and detach the complete scientific point-weight lineage.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + receipt_ref = _require_reference( + "analysis_weight_receipt_reference", + analysis_weight_receipt_reference, + "analysis_weight_receipt", + ) + receipt_digest = _require_digest( + "analysis_weight_receipt_digest", analysis_weight_receipt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + estimand_ref = _require_reference( + "estimand_reference", estimand_reference, "validation_estimand" + ) + estimand_evidence = _require_digest("estimand_digest", estimand_digest) + scope = _require_weight_scope(estimand_scope_code) + target_ref = _require_reference( + "target_population_reference", + target_population_reference, + "analysis_target_population", + ) + target_digest = _require_digest( + "target_population_digest", target_population_digest + ) + unit_code = _require_code("analysis_unit_code", analysis_unit_code) + window_ref = _require_reference( + "analysis_window_reference", analysis_window_reference, "analysis_window" + ) + duration_ref = _require_reference( + "reference_duration_reference", + reference_duration_reference, + "analysis_reference_duration", + ) + duration_digest = _require_digest( + "reference_duration_digest", reference_duration_digest + ) + eligible_digest = _require_digest( + "eligible_case_set_digest", eligible_case_set_digest + ) + analytic_digest = _require_digest( + "analytic_case_occurrence_set_digest", analytic_case_occurrence_set_digest + ) + source_ref = _require_reference( + "source_universe_receipt_reference", + source_universe_receipt_reference, + "source_universe_receipt", + ) + source_version = _require_positive_integer( + "source_universe_receipt_version", source_universe_receipt_version + ) + source_digest = _require_digest( + "source_universe_receipt_digest", source_universe_receipt_digest + ) + sampling_ref = _require_reference( + "sampling_design_receipt_reference", + sampling_design_receipt_reference, + "sampling_design_receipt", + ) + sampling_version = _require_positive_integer( + "sampling_design_receipt_version", sampling_design_receipt_version + ) + sampling_digest = _require_digest( + "sampling_design_receipt_digest", sampling_design_receipt_digest + ) + base_method = _require_code("base_weight_method_code", base_weight_method_code) + base_method_version_value = _require_positive_integer( + "base_weight_method_version", base_weight_method_version + ) + base_evidence = _require_digest( + "base_weight_evidence_digest", base_weight_evidence_digest + ) + base_artifact = _require_digest( + "base_weight_artifact_digest", base_weight_artifact_digest + ) + if type(adjustments) is not tuple: + raise ValueError("adjustments must be an immutable tuple.") + detached_adjustments: list[FinalWeightAdjustmentCoordinate] = [] + expected_input = base_artifact + for expected_sequence, adjustment in enumerate(adjustments, start=1): + if type(adjustment) is not FinalWeightAdjustmentCoordinate: + raise ValueError( + "adjustments must contain exact FinalWeightAdjustmentCoordinate values." + ) + if adjustment.sequence_number != expected_sequence: + raise ValueError("adjustments must have contiguous sequence_number values.") + if adjustment.input_weight_artifact_digest != expected_input: + raise ValueError( + "adjustment input_weight_artifact_digest breaks the weight chain." + ) + detached = FinalWeightAdjustmentCoordinate( + sequence_number=adjustment.sequence_number, + adjustment_code=adjustment.adjustment_code, + method_reference=adjustment.method_reference, + method_version=adjustment.method_version, + input_weight_artifact_digest=adjustment.input_weight_artifact_digest, + output_weight_artifact_digest=adjustment.output_weight_artifact_digest, + configuration_digest=adjustment.configuration_digest, + evidence_receipt_digest=adjustment.evidence_receipt_digest, + evidence_kind=adjustment.evidence_kind, + ) + detached_adjustments.append(detached) + expected_input = detached.output_weight_artifact_digest + final_artifact = _require_digest( + "final_weight_artifact_digest", final_weight_artifact_digest + ) + if expected_input != final_artifact: + raise ValueError( + "final_weight_artifact_digest must equal the ordered adjustment chain output." + ) + eligibility_ref = _require_reference( + "weight_eligibility_receipt_reference", + weight_eligibility_receipt_reference, + "weight_eligibility_receipt", + ) + eligibility_digest = _require_digest( + "weight_eligibility_receipt_digest", weight_eligibility_receipt_digest + ) + case_count = _require_positive_integer("analytic_case_count", analytic_case_count) + constructed = _require_aware_datetime("constructed_at", constructed_at) + correction = _require_positive_integer("correction_sequence", correction_sequence) + supersedes_digest: str | None + if correction == 1: + if supersedes_receipt_digest is not None: + raise ValueError( + "supersedes_receipt_digest must be absent for correction_sequence 1." + ) + supersedes_digest = None + else: + if supersedes_receipt_digest is None: + raise ValueError( + "supersedes_receipt_digest is required when correction_sequence exceeds 1." + ) + supersedes_digest = _require_digest( + "supersedes_receipt_digest", supersedes_receipt_digest + ) + if supersedes_digest == receipt_digest: + raise ValueError("a final analysis-weight receipt cannot supersede itself.") + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + release_instant = _require_aware_datetime("released_at", released_at) + if release_instant < constructed: + raise ValueError("released_at cannot precede constructed_at.") + + fields: tuple[tuple[str, object], ...] = ( + ("adjustments", tuple(detached_adjustments)), + ("analysis_unit_code", unit_code), + ("analysis_weight_receipt_digest", receipt_digest), + ("analysis_weight_receipt_reference", receipt_ref), + ("analysis_window_reference", window_ref), + ("analytic_case_count", case_count), + ("analytic_case_occurrence_set_digest", analytic_digest), + ("base_weight_artifact_digest", base_artifact), + ("base_weight_evidence_digest", base_evidence), + ("base_weight_method_code", base_method), + ("base_weight_method_version", base_method_version_value), + ("constructed_at", constructed), + ("correction_sequence", correction), + ("eligible_case_set_digest", eligible_digest), + ("estimand_digest", estimand_evidence), + ("estimand_reference", estimand_ref), + ("estimand_scope_code", scope), + ("evidence_version", version), + ("final_weight_artifact_digest", final_artifact), + ("owner_contract_digest", owner_digest), + ("owner_contract_reference", owner_ref), + ("owner_contract_version", owner_version), + ("reference_duration_digest", duration_digest), + ("reference_duration_reference", duration_ref), + ("sampling_design_receipt_digest", sampling_digest), + ("sampling_design_receipt_reference", sampling_ref), + ("sampling_design_receipt_version", sampling_version), + ("source_universe_receipt_digest", source_digest), + ("source_universe_receipt_reference", source_ref), + ("source_universe_receipt_version", source_version), + ("supersedes_receipt_digest", supersedes_digest), + ("target_population_digest", target_digest), + ("target_population_reference", target_ref), + ("weight_eligibility_receipt_digest", eligibility_digest), + ("weight_eligibility_receipt_reference", eligibility_ref), + ) + return tuple.__new__( + cls, + (tenant_identity, study_identity, fields, release_instant), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable scientific coordinates without row-level weights.""" + return self[2] + + @property + def released_at(self) -> datetime: + """Return the owner-resolved release instant.""" + return self[3] + + +class FinalAnalysisWeightAuthorityView(tuple): + """Field-minimized final-weight evidence issued only after authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> FinalAnalysisWeightAuthorityView: + """Reject public construction; the resolver is the only supported issuer.""" + raise TypeError( + "FinalAnalysisWeightAuthorityView is issued only by " + "resolve_final_analysis_weight_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable final-weight provenance.""" + return self[2] + + +@runtime_checkable +class FinalAnalysisWeightAuthorityReadPort(Protocol): + """Owner read contract for one released final analysis-weight receipt.""" + + def read_final_analysis_weight_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + analysis_weight_receipt_reference: str, + analysis_weight_receipt_digest: str, + evidence_version: int, + source_universe_receipt_reference: str, + source_universe_receipt_version: int, + source_universe_receipt_digest: str, + sampling_design_receipt_reference: str, + sampling_design_receipt_version: int, + sampling_design_receipt_digest: str, + owner_contract_reference: str, + owner_contract_version: int, + ) -> FinalAnalysisWeightAuthorityRecord | None: + """Return matching released final-weight evidence or ``None``.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + FinalAnalysisWeightAuthorityReadPort, "read_final_analysis_weight_authority" +) + + +def resolve_final_analysis_weight_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + analysis_weight_receipt_reference: str, + analysis_weight_receipt_digest: str, + evidence_version: int, + estimand_reference: str, + estimand_digest: str, + estimand_scope_code: str, + target_population_reference: str, + target_population_digest: str, + analysis_unit_code: str, + analysis_window_reference: str, + reference_duration_reference: str, + reference_duration_digest: str, + eligible_case_set_digest: str, + analytic_case_occurrence_set_digest: str, + source_universe_receipt_reference: str, + source_universe_receipt_version: int, + source_universe_receipt_digest: str, + sampling_design_receipt_reference: str, + sampling_design_receipt_version: int, + sampling_design_receipt_digest: str, + base_weight_method_code: str, + base_weight_method_version: int, + base_weight_evidence_digest: str, + base_weight_artifact_digest: str, + adjustments: tuple[FinalWeightAdjustmentCoordinate, ...], + final_weight_artifact_digest: str, + weight_eligibility_receipt_reference: str, + weight_eligibility_receipt_digest: str, + analytic_case_count: int, + constructed_at: datetime, + correction_sequence: int, + supersedes_receipt_digest: str | None, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: FinalAnalysisWeightAuthorityReadPort, +) -> FinalAnalysisWeightAuthorityView: + """Authorize then corroborate the complete released final-weight lineage.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static( + type(read_port), "read_final_analysis_weight_authority", None + ) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError( + "read_port must expose a statically callable " + "read_final_analysis_weight_authority." + ) + + requested = FinalAnalysisWeightAuthorityRecord( + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + analysis_weight_receipt_reference=analysis_weight_receipt_reference, + analysis_weight_receipt_digest=analysis_weight_receipt_digest, + evidence_version=evidence_version, + estimand_reference=estimand_reference, + estimand_digest=estimand_digest, + estimand_scope_code=estimand_scope_code, + target_population_reference=target_population_reference, + target_population_digest=target_population_digest, + analysis_unit_code=analysis_unit_code, + analysis_window_reference=analysis_window_reference, + reference_duration_reference=reference_duration_reference, + reference_duration_digest=reference_duration_digest, + eligible_case_set_digest=eligible_case_set_digest, + analytic_case_occurrence_set_digest=analytic_case_occurrence_set_digest, + source_universe_receipt_reference=source_universe_receipt_reference, + source_universe_receipt_version=source_universe_receipt_version, + source_universe_receipt_digest=source_universe_receipt_digest, + sampling_design_receipt_reference=sampling_design_receipt_reference, + sampling_design_receipt_version=sampling_design_receipt_version, + sampling_design_receipt_digest=sampling_design_receipt_digest, + base_weight_method_code=base_weight_method_code, + base_weight_method_version=base_weight_method_version, + base_weight_evidence_digest=base_weight_evidence_digest, + base_weight_artifact_digest=base_weight_artifact_digest, + adjustments=adjustments, + final_weight_artifact_digest=final_weight_artifact_digest, + weight_eligibility_receipt_reference=weight_eligibility_receipt_reference, + weight_eligibility_receipt_digest=weight_eligibility_receipt_digest, + analytic_case_count=analytic_case_count, + constructed_at=constructed_at, + correction_sequence=correction_sequence, + supersedes_receipt_digest=supersedes_receipt_digest, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + released_at=constructed_at, + ) + tenant_id = requested.tenant_record_id + study_id = requested.validity_study_id + requested_values = dict(requested.fields) + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=requested.tenant_record_id, + validity_study_id=requested.validity_study_id, + analysis_weight_receipt_reference=requested_values[ + "analysis_weight_receipt_reference" + ], + analysis_weight_receipt_digest=requested_values[ + "analysis_weight_receipt_digest" + ], + evidence_version=requested_values["evidence_version"], + source_universe_receipt_reference=requested_values[ + "source_universe_receipt_reference" + ], + source_universe_receipt_version=requested_values[ + "source_universe_receipt_version" + ], + source_universe_receipt_digest=requested_values[ + "source_universe_receipt_digest" + ], + sampling_design_receipt_reference=requested_values[ + "sampling_design_receipt_reference" + ], + sampling_design_receipt_version=requested_values[ + "sampling_design_receipt_version" + ], + sampling_design_receipt_digest=requested_values[ + "sampling_design_receipt_digest" + ], + owner_contract_reference=requested_values["owner_contract_reference"], + owner_contract_version=requested_values["owner_contract_version"], + ) + if persisted is None: + raise FinalAnalysisWeightAuthorityNotFound(str(study_id)) + if type(persisted) is not FinalAnalysisWeightAuthorityRecord: + raise FinalAnalysisWeightAuthorityIntegrityError( + "owner port returned non-canonical final analysis-weight authority evidence" + ) + + record = FinalAnalysisWeightAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + released_at=persisted.released_at, + **dict(persisted.fields), + ) + if ( + _store_operational_uuid("record tenant_record_id", record.tenant_record_id) + != _store_operational_uuid("requested tenant_record_id", requested.tenant_record_id) + or _store_operational_uuid("record validity_study_id", record.validity_study_id) + != _store_operational_uuid("requested validity_study_id", requested.validity_study_id) + or record.fields != requested.fields + ): + raise FinalAnalysisWeightAuthorityIntegrityError( + "released final analysis-weight authority does not match requested coordinates" + ) + if use_instant < record.released_at: + raise FinalAnalysisWeightAuthorityIntegrityError( + "final analysis-weight authority cannot be used before its release instant" + ) + + values = dict(record.fields) + values["released_at"] = record.released_at + fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) + return tuple.__new__( + FinalAnalysisWeightAuthorityView, + ( + _store_operational_uuid("tenant_record_id", record.tenant_record_id), + _store_operational_uuid("validity_study_id", record.validity_study_id), + fields, + ), + ) From ffe0d94d2849d215b0a798cb011af25e6e452c3e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 19:08:15 +0900 Subject: [PATCH 128/603] feat(workforce-validation): export final weight authority --- .../__init__.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index 34d3203bc..66b2f73fb 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -16,6 +16,15 @@ CalibrationAdjustmentAuthorityView, resolve_calibration_adjustment_authority, ) +from orgmetra_workforce_validation_api.final_weight_authority import ( + FinalAnalysisWeightAuthorityIntegrityError, + FinalAnalysisWeightAuthorityNotFound, + FinalAnalysisWeightAuthorityReadPort, + FinalAnalysisWeightAuthorityRecord, + FinalAnalysisWeightAuthorityView, + FinalWeightAdjustmentCoordinate, + resolve_final_analysis_weight_authority, +) from orgmetra_workforce_validation_api.nonresponse_adjustment_authority import ( NonresponseAdjustmentAuthorityIntegrityError, NonresponseAdjustmentAuthorityNotFound, @@ -98,6 +107,12 @@ "CalibrationBenchmarkAuthorityReadPort", "CalibrationBenchmarkAuthorityRecord", "CalibrationBenchmarkAuthorityView", + "FinalAnalysisWeightAuthorityIntegrityError", + "FinalAnalysisWeightAuthorityNotFound", + "FinalAnalysisWeightAuthorityReadPort", + "FinalAnalysisWeightAuthorityRecord", + "FinalAnalysisWeightAuthorityView", + "FinalWeightAdjustmentCoordinate", "NonresponseAdjustmentAuthorityIntegrityError", "NonresponseAdjustmentAuthorityNotFound", "NonresponseAdjustmentAuthorityReadPort", @@ -138,6 +153,7 @@ "resolve_calibration_adjustment_authority", "resolve_calibration_auxiliary_authority", "resolve_calibration_benchmark_authority", + "resolve_final_analysis_weight_authority", "resolve_nonresponse_adjustment_authority", "resolve_trimming_bounding_authority", "resolve_validation_result_authority", From c651cda301d36e0111422e279e015ec211295b28 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 19:08:42 +0900 Subject: [PATCH 129/603] docs(workforce-validation): document final weight owner authority --- services/workforce-validation-api/README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index d15a4d85e..e8db57c5d 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -46,9 +46,15 @@ This preserves the evidence needed to reproduce which governed trimming/bounding `resolve_weight_eligibility_authority(...)` corroborates #407 RED #9 instead of treating an eligibility digest as sufficient authority. It binds the exact `weight_eligibility_receipt` reference/digest/evidence version to explicit `cross_sectional | longitudinal` scope, governed target-population and reference-duration coordinates, exact eligible-case set, exact point-weight artifact, construction time, released owner-contract tuple, and owner-resolved receipt release time. Cross-sectional and longitudinal eligibility are distinct authority states; a different population, duration, case set, or artifact cannot be silently reused. Person attributes and row-level weights are excluded. +## Final analysis-weight authority + +`resolve_final_analysis_weight_authority(...)` corroborates the complete #407 point-estimation lineage rather than trusting only the final receipt digest carried by the point-weight/variance compatibility boundary. It binds the exact final analysis-weight receipt to the estimand, target population, analysis unit/window/reference duration, eligible and analytic-case sets, owner-resolved source-universe and sampling-design receipt references/versions/digests, base-weight method/evidence/artifact, ordered typed adjustment chain, final point-weight artifact, weight-eligibility receipt, analytic-case count, append-only correction lineage, construction/release chronology, and released owner contract. + +The ordered adjustment chain is immutable and contiguous: each transform must consume the preceding artifact, material transforms may not be no-ops, and known nonresponse/calibration/raking/poststratification/trimming/bounding/winsorization codes require their specialized receipt kind. Source/sampling references are owner-corroborated coordinates layered over the digest-only scientific leaf, so a caller cannot turn an opaque digest into a floating source/design version. No row-level weights, case identities, protected calibration values, or foreign tables cross this boundary. + ## Point-weight / variance authority -`resolve_weight_variance_authority(...)` corroborates released #405 sampling evidence, final analysis-weight receipt, analytic-case occurrence set, weight-eligibility receipt digest, correction sequence, final point-weight artifact, separate #406 variance-design evidence, variance method/evidence semantics, and released owner contract. A variance receipt cannot alias the point-weight receipt, and approximation evidence cannot be represented as exact. The separate eligibility authority supplies the durable scope/population/duration semantics behind the eligibility digest. +`resolve_weight_variance_authority(...)` corroborates released #405 sampling evidence, final analysis-weight receipt, analytic-case occurrence set, weight-eligibility receipt digest, correction sequence, final point-weight artifact, separate #406 variance-design evidence, variance method/evidence semantics, and released owner contract. A variance receipt cannot alias the point-weight receipt, and approximation evidence cannot be represented as exact. The separate eligibility and final analysis-weight authorities supply the durable scope/population/duration and complete ordered point-weight lineage behind those compatibility coordinates. ## Released validation-result authority @@ -64,7 +70,7 @@ This preserves the evidence needed to reproduce which governed trimming/bounding The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, point-weight/variance, validation-result binding, and validation-result non-verifiability. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, complete final analysis-weight lineage, point-weight/variance compatibility, validation-result binding, and validation-result non-verifiability. ## Test contract @@ -79,6 +85,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. \ No newline at end of file From aeaee5f8b3d8453596ee1e9ccf7f5a6450cb0cab Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 19:10:20 +0900 Subject: [PATCH 130/603] test(workforce-validation): cover final weight evidence version edge --- .../tests/test_final_analysis_weight_authority.py | 1 + 1 file changed, 1 insertion(+) diff --git a/services/workforce-validation-api/tests/test_final_analysis_weight_authority.py b/services/workforce-validation-api/tests/test_final_analysis_weight_authority.py index 09f422045..2683e3e23 100644 --- a/services/workforce-validation-api/tests/test_final_analysis_weight_authority.py +++ b/services/workforce-validation-api/tests/test_final_analysis_weight_authority.py @@ -345,6 +345,7 @@ def test_adjustment_semantics_are_typed_and_no_op_transform_is_rejected() -> Non ("analysis_weight_receipt_reference", "wrong:receipt", ValueError), ("analysis_weight_receipt_digest", "ABC", ValueError), ("evidence_version", False, ValueError), + ("evidence_version", 2, ValueError), ("estimand_reference", "wrong:estimand", ValueError), ("estimand_digest", "2" * 63, ValueError), ("estimand_scope_code", "panel", ValueError), From 1a43d088f0f355d8b91de3fb2055c8e156693c0e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 20:03:42 +0900 Subject: [PATCH 131/603] test(workforce-validation): RED base-weight owner provenance --- .../tests/test_base_weight_authority.py | 256 ++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_base_weight_authority.py diff --git a/services/workforce-validation-api/tests/test_base_weight_authority.py b/services/workforce-validation-api/tests/test_base_weight_authority.py new file mode 100644 index 000000000..a8406def2 --- /dev/null +++ b/services/workforce-validation-api/tests/test_base_weight_authority.py @@ -0,0 +1,256 @@ +"""Fail-closed contract for released base/design-weight provenance.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.base_weight_authority import ( + BaseWeightAuthorityIntegrityError, + BaseWeightAuthorityNotFound, + BaseWeightAuthorityReadPort, + BaseWeightAuthorityRecord, + BaseWeightAuthorityView, + resolve_base_weight_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000f2") +BASE_RECEIPT_REFERENCE = "base_weight_evidence_receipt:11111111-1111-4111-8111-111111111111" +SOURCE_REFERENCE = "source_universe_receipt:22222222-2222-4222-8222-222222222222" +SAMPLING_REFERENCE = "sampling_design_receipt:33333333-3333-4333-8333-333333333333" +OWNER_REFERENCE = "released_owner_contract:44444444-4444-4444-8444-444444444444" +BASE_RECEIPT_DIGEST = "1" * 64 +SOURCE_DIGEST = "2" * 64 +SAMPLING_DIGEST = "3" * 64 +SAMPLED_SET_DIGEST = "4" * 64 +SELECTION_PROBABILITY_SET_DIGEST = "5" * 64 +BASE_ARTIFACT_DIGEST = "6" * 64 +OWNER_DIGEST = "7" * 64 +SOURCE_RELEASED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) +SAMPLING_RELEASED_AT = datetime(2026, 9, 17, 6, 30, tzinfo=timezone.utc) +CONSTRUCTED_AT = datetime(2026, 9, 17, 7, 0, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 7, 30, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 8, 0, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "base_weight_evidence_receipt_reference", + "base_weight_evidence_receipt_digest", + "evidence_version", + "source_universe_receipt_reference", + "source_universe_receipt_version", + "source_universe_receipt_digest", + "source_universe_released_at", + "sampling_design_receipt_reference", + "sampling_design_receipt_version", + "sampling_design_receipt_digest", + "sampling_design_released_at", + "sampled_occurrence_set_digest", + "selection_probability_set_digest", + "selection_stage_count", + "base_weight_method_code", + "base_weight_method_version", + "base_weight_artifact_digest", + "constructed_at", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "released_at", + } +) + + +class _ReadPort: + """Return configured owner evidence and capture lookup coordinates.""" + + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[dict[str, object]] = [] + + def read_base_weight_authority(self, **coordinates: object) -> object: + self.calls.append(dict(coordinates)) + return self.result + + +class _ProtocolOnly(BaseWeightAuthorityReadPort): + """Inherit only the Protocol placeholder.""" + + +class _DescriptorReadPort: + """Expose a descriptor that must never execute.""" + + @property + def read_base_weight_authority(self) -> object: + raise AssertionError("descriptor must not execute") + + +class _NoReadMethod: + """Deliberately omit the owner capability.""" + + +def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=tenant_record_id, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="base-weight-authority-read-v1", + resource_kind="base_weight_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record(**overrides: object) -> BaseWeightAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "base_weight_evidence_receipt_reference": BASE_RECEIPT_REFERENCE, + "base_weight_evidence_receipt_digest": BASE_RECEIPT_DIGEST, + "evidence_version": 1, + "source_universe_receipt_reference": SOURCE_REFERENCE, + "source_universe_receipt_version": 4, + "source_universe_receipt_digest": SOURCE_DIGEST, + "source_universe_released_at": SOURCE_RELEASED_AT, + "sampling_design_receipt_reference": SAMPLING_REFERENCE, + "sampling_design_receipt_version": 3, + "sampling_design_receipt_digest": SAMPLING_DIGEST, + "sampling_design_released_at": SAMPLING_RELEASED_AT, + "sampled_occurrence_set_digest": SAMPLED_SET_DIGEST, + "selection_probability_set_digest": SELECTION_PROBABILITY_SET_DIGEST, + "selection_stage_count": 2, + "base_weight_method_code": "inverse_inclusion_probability", + "base_weight_method_version": 1, + "base_weight_artifact_digest": BASE_ARTIFACT_DIGEST, + "constructed_at": CONSTRUCTED_AT, + "owner_contract_reference": OWNER_REFERENCE, + "owner_contract_version": 6, + "owner_contract_digest": OWNER_DIGEST, + "released_at": RELEASED_AT, + } + values.update(overrides) + return BaseWeightAuthorityRecord(**values) + + +def _resolve(*, read_port: object, **overrides: object) -> BaseWeightAuthorityView: + values = dict(_record().fields) + values.update( + { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + ) + values.update(overrides) + return resolve_base_weight_authority(**values) + + +def test_resolution_binds_sampling_stage_probabilities_to_base_weight_artifact() -> None: + port = _ReadPort(_record()) + + view = _resolve(read_port=port) + + assert isinstance(port, BaseWeightAuthorityReadPort) + assert len(port.calls) == 1 + assert port.calls[0]["source_universe_receipt_version"] == 4 + assert port.calls[0]["sampling_design_receipt_version"] == 3 + assert port.calls[0]["selection_probability_set_digest"] == SELECTION_PROBABILITY_SET_DIGEST + assert ("sampled_occurrence_set_digest", SAMPLED_SET_DIGEST) in view.fields + assert ("selection_stage_count", 2) in view.fields + assert ("base_weight_artifact_digest", BASE_ARTIFACT_DIGEST) in view.fields + assert ("released_at", RELEASED_AT) in view.fields + + +def test_authorization_denial_happens_before_owner_resolution() -> None: + port = _ReadPort(_record()) + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, policy=_policy(purpose_code="audit_review")) + assert port.calls == [] + + +def test_missing_noncanonical_or_mismatched_owner_evidence_fails_closed() -> None: + with pytest.raises(BaseWeightAuthorityNotFound): + _resolve(read_port=_ReadPort(None)) + with pytest.raises(BaseWeightAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object())) + with pytest.raises(BaseWeightAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(selection_stage_count=3))) + with pytest.raises(BaseWeightAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(base_weight_artifact_digest="8" * 64))) + with pytest.raises(BaseWeightAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(tenant_record_id=OTHER_TENANT))) + with pytest.raises(BaseWeightAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(validity_study_id=OTHER_STUDY))) + + +def test_source_sampling_and_release_chronology_fail_closed() -> None: + with pytest.raises(ValueError): + _record(source_universe_released_at=CONSTRUCTED_AT + timedelta(seconds=1)) + with pytest.raises(ValueError): + _record(sampling_design_released_at=CONSTRUCTED_AT + timedelta(seconds=1)) + with pytest.raises(ValueError): + _record(released_at=CONSTRUCTED_AT - timedelta(seconds=1)) + with pytest.raises(BaseWeightAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(released_at=USED_AT + timedelta(seconds=1)))) + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("base_weight_evidence_receipt_reference", "wrong:receipt", ValueError), + ("base_weight_evidence_receipt_digest", "ABC", ValueError), + ("evidence_version", False, ValueError), + ("evidence_version", 2, ValueError), + ("source_universe_receipt_reference", "wrong:source", ValueError), + ("source_universe_receipt_version", 0, ValueError), + ("source_universe_receipt_digest", "2" * 63, ValueError), + ("sampling_design_receipt_reference", "wrong:sampling", ValueError), + ("sampling_design_receipt_version", False, ValueError), + ("sampling_design_receipt_digest", "3" * 63, ValueError), + ("sampled_occurrence_set_digest", "4" * 63, ValueError), + ("selection_probability_set_digest", "5" * 63, ValueError), + ("selection_stage_count", 0, ValueError), + ("base_weight_method_code", "Inverse Probability", ValueError), + ("base_weight_method_version", False, ValueError), + ("base_weight_artifact_digest", "6" * 63, ValueError), + ("owner_contract_reference", "wrong:owner", ValueError), + ("owner_contract_version", 0, ValueError), + ("owner_contract_digest", "7" * 63, ValueError), + ], +) +def test_hostile_coordinates_fail_closed(key: str, value: object, error: type[Exception]) -> None: + with pytest.raises(error): + _resolve(read_port=_ReadPort(_record()), **{key: value}) + + +def test_view_cannot_be_constructed_directly() -> None: + with pytest.raises(TypeError): + BaseWeightAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) From e672dfb2010715f9b2712fa2b4627848cf11e877 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 20:04:26 +0900 Subject: [PATCH 132/603] feat(workforce-validation): corroborate base-weight owner evidence --- .../base_weight_authority.py | 470 ++++++++++++++++++ 1 file changed, 470 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py new file mode 100644 index 000000000..97cf510c1 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py @@ -0,0 +1,470 @@ +"""Corroborate released base/design-weight evidence without copying row-level weights. + +This boundary keeps stage-wise inclusion-probability evidence with its sampling +owner. Workforce validation receives only released references, versions, digests, +set identity, method identity, and the resulting base-weight artifact needed to +reproduce the scientific weight lineage. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + +_RESOURCE_KIND = "base_weight_authority" +_OPERATION = "read" +_READ_FIELDS = frozenset( + { + "base_weight_evidence_receipt_reference", + "base_weight_evidence_receipt_digest", + "evidence_version", + "source_universe_receipt_reference", + "source_universe_receipt_version", + "source_universe_receipt_digest", + "source_universe_released_at", + "sampling_design_receipt_reference", + "sampling_design_receipt_version", + "sampling_design_receipt_digest", + "sampling_design_released_at", + "sampled_occurrence_set_digest", + "selection_probability_set_digest", + "selection_stage_count", + "base_weight_method_code", + "base_weight_method_version", + "base_weight_artifact_digest", + "constructed_at", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "released_at", + } +) + + +class BaseWeightAuthorityNotFound(LookupError): + """Indicate that no released owner evidence corroborates the base weight.""" + + +class BaseWeightAuthorityIntegrityError(RuntimeError): + """Indicate that released owner evidence cannot corroborate the requested base weight.""" + + +class BaseWeightAuthorityRecord(tuple): + """Immutable owner projection for one released base/design-weight construction.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + base_weight_evidence_receipt_reference: str, + base_weight_evidence_receipt_digest: str, + evidence_version: int, + source_universe_receipt_reference: str, + source_universe_receipt_version: int, + source_universe_receipt_digest: str, + source_universe_released_at: datetime, + sampling_design_receipt_reference: str, + sampling_design_receipt_version: int, + sampling_design_receipt_digest: str, + sampling_design_released_at: datetime, + sampled_occurrence_set_digest: str, + selection_probability_set_digest: str, + selection_stage_count: int, + base_weight_method_code: str, + base_weight_method_version: int, + base_weight_artifact_digest: str, + constructed_at: datetime, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + released_at: datetime, + ) -> BaseWeightAuthorityRecord: + """Validate the minimum released provenance needed to reproduce a base weight.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + receipt_ref = _require_reference( + "base_weight_evidence_receipt_reference", + base_weight_evidence_receipt_reference, + "base_weight_evidence_receipt", + ) + receipt_digest = _require_digest( + "base_weight_evidence_receipt_digest", base_weight_evidence_receipt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + source_ref = _require_reference( + "source_universe_receipt_reference", + source_universe_receipt_reference, + "source_universe_receipt", + ) + source_version = _require_positive_integer( + "source_universe_receipt_version", source_universe_receipt_version + ) + source_digest = _require_digest( + "source_universe_receipt_digest", source_universe_receipt_digest + ) + source_released = _require_aware_datetime( + "source_universe_released_at", source_universe_released_at + ) + sampling_ref = _require_reference( + "sampling_design_receipt_reference", + sampling_design_receipt_reference, + "sampling_design_receipt", + ) + sampling_version = _require_positive_integer( + "sampling_design_receipt_version", sampling_design_receipt_version + ) + sampling_digest = _require_digest( + "sampling_design_receipt_digest", sampling_design_receipt_digest + ) + sampling_released = _require_aware_datetime( + "sampling_design_released_at", sampling_design_released_at + ) + sampled_digest = _require_digest( + "sampled_occurrence_set_digest", sampled_occurrence_set_digest + ) + probability_digest = _require_digest( + "selection_probability_set_digest", selection_probability_set_digest + ) + stage_count = _require_positive_integer("selection_stage_count", selection_stage_count) + method_code = _require_code("base_weight_method_code", base_weight_method_code) + method_version = _require_positive_integer( + "base_weight_method_version", base_weight_method_version + ) + artifact_digest = _require_digest( + "base_weight_artifact_digest", base_weight_artifact_digest + ) + constructed = _require_aware_datetime("constructed_at", constructed_at) + if source_released > constructed: + raise ValueError("source_universe_released_at cannot be later than constructed_at.") + if sampling_released > constructed: + raise ValueError("sampling_design_released_at cannot be later than constructed_at.") + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + release_instant = _require_aware_datetime("released_at", released_at) + if release_instant < constructed: + raise ValueError("released_at cannot precede constructed_at.") + + fields: tuple[tuple[str, object], ...] = ( + ("base_weight_artifact_digest", artifact_digest), + ("base_weight_evidence_receipt_digest", receipt_digest), + ("base_weight_evidence_receipt_reference", receipt_ref), + ("base_weight_method_code", method_code), + ("base_weight_method_version", method_version), + ("constructed_at", constructed), + ("evidence_version", version), + ("owner_contract_digest", owner_digest), + ("owner_contract_reference", owner_ref), + ("owner_contract_version", owner_version), + ("sampled_occurrence_set_digest", sampled_digest), + ("sampling_design_receipt_digest", sampling_digest), + ("sampling_design_receipt_reference", sampling_ref), + ("sampling_design_receipt_version", sampling_version), + ("sampling_design_released_at", sampling_released), + ("selection_probability_set_digest", probability_digest), + ("selection_stage_count", stage_count), + ("source_universe_receipt_digest", source_digest), + ("source_universe_receipt_reference", source_ref), + ("source_universe_receipt_version", source_version), + ("source_universe_released_at", source_released), + ) + return tuple.__new__(cls, (tenant_identity, study_identity, fields, release_instant)) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable, value-minimized base-weight provenance.""" + return self[2] + + @property + def released_at(self) -> datetime: + """Return when the base-weight evidence became released authority.""" + return self[3] + + +class BaseWeightAuthorityView(tuple): + """Field-minimized base-weight evidence issued only after authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> BaseWeightAuthorityView: + """Reject public construction; only the resolver may issue this view.""" + raise TypeError( + "BaseWeightAuthorityView is issued only by resolve_base_weight_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return released base-weight provenance without row-level probabilities.""" + return self[2] + + +@runtime_checkable +class BaseWeightAuthorityReadPort(Protocol): + """Owner read contract for one released base/design-weight receipt.""" + + def read_base_weight_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + base_weight_evidence_receipt_reference: str, + base_weight_evidence_receipt_digest: str, + evidence_version: int, + source_universe_receipt_reference: str, + source_universe_receipt_version: int, + source_universe_receipt_digest: str, + sampling_design_receipt_reference: str, + sampling_design_receipt_version: int, + sampling_design_receipt_digest: str, + selection_probability_set_digest: str, + owner_contract_reference: str, + owner_contract_version: int, + ) -> BaseWeightAuthorityRecord | None: + """Return matching released base-weight evidence or ``None``.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + BaseWeightAuthorityReadPort, "read_base_weight_authority" +) + + +def resolve_base_weight_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + base_weight_evidence_receipt_reference: str, + base_weight_evidence_receipt_digest: str, + evidence_version: int, + source_universe_receipt_reference: str, + source_universe_receipt_version: int, + source_universe_receipt_digest: str, + source_universe_released_at: datetime, + sampling_design_receipt_reference: str, + sampling_design_receipt_version: int, + sampling_design_receipt_digest: str, + sampling_design_released_at: datetime, + sampled_occurrence_set_digest: str, + selection_probability_set_digest: str, + selection_stage_count: int, + base_weight_method_code: str, + base_weight_method_version: int, + base_weight_artifact_digest: str, + constructed_at: datetime, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: BaseWeightAuthorityReadPort, +) -> BaseWeightAuthorityView: + """Authorize then corroborate released stage-wise base-weight evidence.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static(type(read_port), "read_base_weight_authority", None) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError("read_port must expose a statically callable read_base_weight_authority.") + + requested = BaseWeightAuthorityRecord( + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + base_weight_evidence_receipt_reference=base_weight_evidence_receipt_reference, + base_weight_evidence_receipt_digest=base_weight_evidence_receipt_digest, + evidence_version=evidence_version, + source_universe_receipt_reference=source_universe_receipt_reference, + source_universe_receipt_version=source_universe_receipt_version, + source_universe_receipt_digest=source_universe_receipt_digest, + source_universe_released_at=source_universe_released_at, + sampling_design_receipt_reference=sampling_design_receipt_reference, + sampling_design_receipt_version=sampling_design_receipt_version, + sampling_design_receipt_digest=sampling_design_receipt_digest, + sampling_design_released_at=sampling_design_released_at, + sampled_occurrence_set_digest=sampled_occurrence_set_digest, + selection_probability_set_digest=selection_probability_set_digest, + selection_stage_count=selection_stage_count, + base_weight_method_code=base_weight_method_code, + base_weight_method_version=base_weight_method_version, + base_weight_artifact_digest=base_weight_artifact_digest, + constructed_at=constructed_at, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + released_at=constructed_at, + ) + tenant_id = requested.tenant_record_id + study_id = requested.validity_study_id + requested_values = dict(requested.fields) + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=requested.tenant_record_id, + validity_study_id=requested.validity_study_id, + base_weight_evidence_receipt_reference=requested_values[ + "base_weight_evidence_receipt_reference" + ], + base_weight_evidence_receipt_digest=requested_values[ + "base_weight_evidence_receipt_digest" + ], + evidence_version=requested_values["evidence_version"], + source_universe_receipt_reference=requested_values[ + "source_universe_receipt_reference" + ], + source_universe_receipt_version=requested_values[ + "source_universe_receipt_version" + ], + source_universe_receipt_digest=requested_values[ + "source_universe_receipt_digest" + ], + sampling_design_receipt_reference=requested_values[ + "sampling_design_receipt_reference" + ], + sampling_design_receipt_version=requested_values[ + "sampling_design_receipt_version" + ], + sampling_design_receipt_digest=requested_values[ + "sampling_design_receipt_digest" + ], + selection_probability_set_digest=requested_values[ + "selection_probability_set_digest" + ], + owner_contract_reference=requested_values["owner_contract_reference"], + owner_contract_version=requested_values["owner_contract_version"], + ) + if persisted is None: + raise BaseWeightAuthorityNotFound(str(study_id)) + if type(persisted) is not BaseWeightAuthorityRecord: + raise BaseWeightAuthorityIntegrityError( + "owner port returned non-canonical base-weight authority evidence" + ) + + record = BaseWeightAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + released_at=persisted.released_at, + **dict(persisted.fields), + ) + if ( + _store_operational_uuid("record tenant_record_id", record.tenant_record_id) + != _store_operational_uuid("requested tenant_record_id", requested.tenant_record_id) + or _store_operational_uuid("record validity_study_id", record.validity_study_id) + != _store_operational_uuid("requested validity_study_id", requested.validity_study_id) + or record.fields != requested.fields + ): + raise BaseWeightAuthorityIntegrityError( + "released base-weight authority does not match requested coordinates" + ) + if use_instant < record.released_at: + raise BaseWeightAuthorityIntegrityError( + "base-weight authority cannot be used before its release instant" + ) + + values = dict(record.fields) + values["released_at"] = record.released_at + fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) + return tuple.__new__( + BaseWeightAuthorityView, + ( + _store_operational_uuid("tenant_record_id", record.tenant_record_id), + _store_operational_uuid("validity_study_id", record.validity_study_id), + fields, + ), + ) + + +__all__ = [ + "BaseWeightAuthorityIntegrityError", + "BaseWeightAuthorityNotFound", + "BaseWeightAuthorityReadPort", + "BaseWeightAuthorityRecord", + "BaseWeightAuthorityView", + "resolve_base_weight_authority", +] From fa4bfa496428b1dfc94e3af77ccb8c5ae3cee3c0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 20:04:53 +0900 Subject: [PATCH 133/603] feat(workforce-validation): export base-weight authority --- .../__init__.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index 66b2f73fb..3063504cf 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -1,5 +1,13 @@ """Canonical workforce-validation application contracts for Orgmetra.""" +from orgmetra_workforce_validation_api.base_weight_authority import ( + BaseWeightAuthorityIntegrityError, + BaseWeightAuthorityNotFound, + BaseWeightAuthorityReadPort, + BaseWeightAuthorityRecord, + BaseWeightAuthorityView, + resolve_base_weight_authority, +) from orgmetra_workforce_validation_api.benchmark_authority import ( CalibrationBenchmarkAuthorityIntegrityError, CalibrationBenchmarkAuthorityNotFound, @@ -92,6 +100,11 @@ ) __all__ = [ + "BaseWeightAuthorityIntegrityError", + "BaseWeightAuthorityNotFound", + "BaseWeightAuthorityReadPort", + "BaseWeightAuthorityRecord", + "BaseWeightAuthorityView", "CalibrationAdjustmentAuthorityIntegrityError", "CalibrationAdjustmentAuthorityNotFound", "CalibrationAdjustmentAuthorityReadPort", @@ -150,6 +163,7 @@ "WeightVarianceAuthorityRecord", "WeightVarianceAuthorityView", "read_validity_study", + "resolve_base_weight_authority", "resolve_calibration_adjustment_authority", "resolve_calibration_auxiliary_authority", "resolve_calibration_benchmark_authority", @@ -160,4 +174,4 @@ "resolve_validation_result_nonverifiability", "resolve_weight_eligibility_authority", "resolve_weight_variance_authority", -] \ No newline at end of file +] From 20a80f0b0d5291d0e9bc9670f6f933c77191e96b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 20:05:25 +0900 Subject: [PATCH 134/603] docs(workforce-validation): document base-weight owner evidence --- services/workforce-validation-api/README.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index e8db57c5d..1d82370ce 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -46,15 +46,21 @@ This preserves the evidence needed to reproduce which governed trimming/bounding `resolve_weight_eligibility_authority(...)` corroborates #407 RED #9 instead of treating an eligibility digest as sufficient authority. It binds the exact `weight_eligibility_receipt` reference/digest/evidence version to explicit `cross_sectional | longitudinal` scope, governed target-population and reference-duration coordinates, exact eligible-case set, exact point-weight artifact, construction time, released owner-contract tuple, and owner-resolved receipt release time. Cross-sectional and longitudinal eligibility are distinct authority states; a different population, duration, case set, or artifact cannot be silently reused. Person attributes and row-level weights are excluded. +## Base/design-weight authority + +`resolve_base_weight_authority(...)` corroborates the base/design-weight derivation instead of accepting `base_weight_evidence_digest` as an opaque caller label. It binds an exact released base-weight evidence receipt to the source-universe and sampling-design receipt references/versions/digests, their release chronology, the sampled occurrence set, an immutable digest of the stage-wise selection-probability evidence, the positive selection-stage count, base-weight method/version, resulting base-weight artifact, construction time, and released owner contract. + +The stage-wise probability values themselves stay with the sampling owner. `workforce_validation` receives only the evidence identity needed to prove which selection-probability set and sampled occurrence set produced the base artifact. Source and sampling evidence must already be released when the base weight is constructed, and scientific use cannot precede release of the base-weight evidence. This closes the remaining #407 gap where the final-weight receipt carried only a base-evidence digest and artifact identity without independently corroborating the sampling evidence needed to verify `1/π` or another controlled base-weight derivation. + ## Final analysis-weight authority `resolve_final_analysis_weight_authority(...)` corroborates the complete #407 point-estimation lineage rather than trusting only the final receipt digest carried by the point-weight/variance compatibility boundary. It binds the exact final analysis-weight receipt to the estimand, target population, analysis unit/window/reference duration, eligible and analytic-case sets, owner-resolved source-universe and sampling-design receipt references/versions/digests, base-weight method/evidence/artifact, ordered typed adjustment chain, final point-weight artifact, weight-eligibility receipt, analytic-case count, append-only correction lineage, construction/release chronology, and released owner contract. -The ordered adjustment chain is immutable and contiguous: each transform must consume the preceding artifact, material transforms may not be no-ops, and known nonresponse/calibration/raking/poststratification/trimming/bounding/winsorization codes require their specialized receipt kind. Source/sampling references are owner-corroborated coordinates layered over the digest-only scientific leaf, so a caller cannot turn an opaque digest into a floating source/design version. No row-level weights, case identities, protected calibration values, or foreign tables cross this boundary. +The ordered adjustment chain is immutable and contiguous: each transform must consume the preceding artifact, material transforms may not be no-ops, and known nonresponse/calibration/raking/poststratification/trimming/bounding/winsorization codes require their specialized receipt kind. Source/sampling references are owner-corroborated coordinates layered over the digest-only scientific leaf, so a caller cannot turn an opaque digest into a floating source/design version. The separate base-weight authority additionally resolves the stage-wise selection-probability evidence behind the base artifact. No row-level weights, case identities, protected calibration values, or foreign tables cross this boundary. ## Point-weight / variance authority -`resolve_weight_variance_authority(...)` corroborates released #405 sampling evidence, final analysis-weight receipt, analytic-case occurrence set, weight-eligibility receipt digest, correction sequence, final point-weight artifact, separate #406 variance-design evidence, variance method/evidence semantics, and released owner contract. A variance receipt cannot alias the point-weight receipt, and approximation evidence cannot be represented as exact. The separate eligibility and final analysis-weight authorities supply the durable scope/population/duration and complete ordered point-weight lineage behind those compatibility coordinates. +`resolve_weight_variance_authority(...)` corroborates released #405 sampling evidence, final analysis-weight receipt, analytic-case occurrence set, weight-eligibility receipt digest, correction sequence, final point-weight artifact, separate #406 variance-design evidence, variance method/evidence semantics, and released owner contract. A variance receipt cannot alias the point-weight receipt, and approximation evidence cannot be represented as exact. The separate eligibility, base-weight, and final analysis-weight authorities supply the durable population/duration, selection-probability provenance, and complete ordered point-weight lineage behind those compatibility coordinates. ## Released validation-result authority @@ -70,7 +76,7 @@ The ordered adjustment chain is immutable and contiguous: each transform must co The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, complete final analysis-weight lineage, point-weight/variance compatibility, validation-result binding, and validation-result non-verifiability. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, point-weight/variance compatibility, validation-result binding, and validation-result non-verifiability. ## Test contract @@ -85,6 +91,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, stage-wise base/design-weight provenance, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. -These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. \ No newline at end of file +These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From c34d7420078e65f388870839ed296ce1eaa5e35e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 20:07:32 +0900 Subject: [PATCH 135/603] test(workforce-validation): preserve benchmark release invariant --- .../tests/test_calibration_benchmark_authority.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_calibration_benchmark_authority.py b/services/workforce-validation-api/tests/test_calibration_benchmark_authority.py index 20c07d0e7..9382c9940 100644 --- a/services/workforce-validation-api/tests/test_calibration_benchmark_authority.py +++ b/services/workforce-validation-api/tests/test_calibration_benchmark_authority.py @@ -240,7 +240,10 @@ def test_owner_evidence_must_match_every_leaf_benchmark_coordinate( def test_owner_evidence_must_have_existed_before_scientific_use() -> None: for overrides in ( {"benchmark_receipt_released_at": USED_AT + timedelta(seconds=1)}, - {"owner_contract_released_at": USED_AT + timedelta(seconds=1)}, + { + "benchmark_receipt_released_at": USED_AT + timedelta(seconds=1), + "owner_contract_released_at": USED_AT + timedelta(seconds=1), + }, {"benchmark_reference_at": USED_AT + timedelta(seconds=1)}, ): port = _ReadPort(_record(**overrides)) From 62bdad83a9e452290effee89a2f3eb325df06ec8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 20:17:20 +0900 Subject: [PATCH 136/603] test(workforce-validation): require base-weight owner contract chronology --- ...t_base_weight_owner_contract_chronology.py | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_base_weight_owner_contract_chronology.py diff --git a/services/workforce-validation-api/tests/test_base_weight_owner_contract_chronology.py b/services/workforce-validation-api/tests/test_base_weight_owner_contract_chronology.py new file mode 100644 index 000000000..c982dd407 --- /dev/null +++ b/services/workforce-validation-api/tests/test_base_weight_owner_contract_chronology.py @@ -0,0 +1,69 @@ +"""Fail closed when base-weight evidence predates its released owner contract.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.base_weight_authority import BaseWeightAuthorityRecord + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") +SOURCE_RELEASED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) +SAMPLING_RELEASED_AT = datetime(2026, 9, 17, 6, 30, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 17, 6, 45, tzinfo=timezone.utc) +CONSTRUCTED_AT = datetime(2026, 9, 17, 7, 0, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 7, 30, tzinfo=timezone.utc) + + +def _record(**overrides: object) -> BaseWeightAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "base_weight_evidence_receipt_reference": ( + "base_weight_evidence_receipt:11111111-1111-4111-8111-111111111111" + ), + "base_weight_evidence_receipt_digest": "1" * 64, + "evidence_version": 1, + "source_universe_receipt_reference": ( + "source_universe_receipt:22222222-2222-4222-8222-222222222222" + ), + "source_universe_receipt_version": 4, + "source_universe_receipt_digest": "2" * 64, + "source_universe_released_at": SOURCE_RELEASED_AT, + "sampling_design_receipt_reference": ( + "sampling_design_receipt:33333333-3333-4333-8333-333333333333" + ), + "sampling_design_receipt_version": 3, + "sampling_design_receipt_digest": "3" * 64, + "sampling_design_released_at": SAMPLING_RELEASED_AT, + "sampled_occurrence_set_digest": "4" * 64, + "selection_probability_set_digest": "5" * 64, + "selection_stage_count": 2, + "base_weight_method_code": "inverse_inclusion_probability", + "base_weight_method_version": 1, + "base_weight_artifact_digest": "6" * 64, + "constructed_at": CONSTRUCTED_AT, + "owner_contract_reference": ( + "released_owner_contract:44444444-4444-4444-8444-444444444444" + ), + "owner_contract_version": 6, + "owner_contract_digest": "7" * 64, + "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, + "released_at": RELEASED_AT, + } + values.update(overrides) + return BaseWeightAuthorityRecord(**values) + + +def test_owner_contract_release_is_preserved_as_authority_provenance() -> None: + record = _record() + + assert dict(record.fields)["owner_contract_released_at"] == OWNER_CONTRACT_RELEASED_AT + + +def test_owner_contract_cannot_postdate_base_weight_receipt_release() -> None: + with pytest.raises(ValueError, match="owner contract"): + _record(owner_contract_released_at=RELEASED_AT + timedelta(seconds=1)) From a6477d42ab89a7cceacb5edcafb2c9e206f97bfe Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 20:18:46 +0900 Subject: [PATCH 137/603] fix(workforce-validation): enforce base-weight owner contract chronology --- .../base_weight_authority.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py index 97cf510c1..5167c5534 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py @@ -59,6 +59,7 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "released_at", } ) @@ -103,6 +104,7 @@ def __new__( owner_contract_reference: str, owner_contract_version: int, owner_contract_digest: str, + owner_contract_released_at: datetime, released_at: datetime, ) -> BaseWeightAuthorityRecord: """Validate the minimum released provenance needed to reproduce a base weight.""" @@ -173,9 +175,16 @@ def __new__( "owner_contract_version", owner_contract_version ) owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + contract_released_at = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) release_instant = _require_aware_datetime("released_at", released_at) if release_instant < constructed: raise ValueError("released_at cannot precede constructed_at.") + if contract_released_at > release_instant: + raise ValueError( + "owner contract must be released no later than base-weight evidence receipt." + ) fields: tuple[tuple[str, object], ...] = ( ("base_weight_artifact_digest", artifact_digest), @@ -187,6 +196,7 @@ def __new__( ("evidence_version", version), ("owner_contract_digest", owner_digest), ("owner_contract_reference", owner_ref), + ("owner_contract_released_at", contract_released_at), ("owner_contract_version", owner_version), ("sampled_occurrence_set_digest", sampled_digest), ("sampling_design_receipt_digest", sampling_digest), @@ -313,6 +323,7 @@ def resolve_base_weight_authority( owner_contract_reference: str, owner_contract_version: int, owner_contract_digest: str, + owner_contract_released_at: datetime, used_at: datetime, purpose_code: str, policy: PurposeBoundAccessPolicy, @@ -354,6 +365,7 @@ def resolve_base_weight_authority( owner_contract_reference=owner_contract_reference, owner_contract_version=owner_contract_version, owner_contract_digest=owner_contract_digest, + owner_contract_released_at=owner_contract_released_at, released_at=constructed_at, ) tenant_id = requested.tenant_record_id @@ -467,4 +479,4 @@ def resolve_base_weight_authority( "BaseWeightAuthorityRecord", "BaseWeightAuthorityView", "resolve_base_weight_authority", -] +] \ No newline at end of file From ca51d184eae12c40650f39a0cefdd5f61231186a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 20:19:13 +0900 Subject: [PATCH 138/603] test(workforce-validation): cover base-weight owner contract release --- .../tests/test_base_weight_authority.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_base_weight_authority.py b/services/workforce-validation-api/tests/test_base_weight_authority.py index a8406def2..402b1665b 100644 --- a/services/workforce-validation-api/tests/test_base_weight_authority.py +++ b/services/workforce-validation-api/tests/test_base_weight_authority.py @@ -35,6 +35,7 @@ OWNER_DIGEST = "7" * 64 SOURCE_RELEASED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) SAMPLING_RELEASED_AT = datetime(2026, 9, 17, 6, 30, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 17, 6, 45, tzinfo=timezone.utc) CONSTRUCTED_AT = datetime(2026, 9, 17, 7, 0, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 17, 7, 30, tzinfo=timezone.utc) USED_AT = datetime(2026, 9, 17, 8, 0, tzinfo=timezone.utc) @@ -61,6 +62,7 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "released_at", } ) @@ -139,6 +141,7 @@ def _record(**overrides: object) -> BaseWeightAuthorityRecord: "owner_contract_reference": OWNER_REFERENCE, "owner_contract_version": 6, "owner_contract_digest": OWNER_DIGEST, + "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, "released_at": RELEASED_AT, } values.update(overrides) @@ -175,6 +178,7 @@ def test_resolution_binds_sampling_stage_probabilities_to_base_weight_artifact() assert ("sampled_occurrence_set_digest", SAMPLED_SET_DIGEST) in view.fields assert ("selection_stage_count", 2) in view.fields assert ("base_weight_artifact_digest", BASE_ARTIFACT_DIGEST) in view.fields + assert ("owner_contract_released_at", OWNER_CONTRACT_RELEASED_AT) in view.fields assert ("released_at", RELEASED_AT) in view.fields @@ -198,6 +202,12 @@ def test_missing_noncanonical_or_mismatched_owner_evidence_fails_closed() -> Non _resolve(read_port=_ReadPort(_record(tenant_record_id=OTHER_TENANT))) with pytest.raises(BaseWeightAuthorityIntegrityError): _resolve(read_port=_ReadPort(_record(validity_study_id=OTHER_STUDY))) + with pytest.raises(BaseWeightAuthorityIntegrityError): + _resolve( + read_port=_ReadPort( + _record(owner_contract_released_at=OWNER_CONTRACT_RELEASED_AT + timedelta(seconds=1)) + ) + ) def test_source_sampling_and_release_chronology_fail_closed() -> None: @@ -207,6 +217,8 @@ def test_source_sampling_and_release_chronology_fail_closed() -> None: _record(sampling_design_released_at=CONSTRUCTED_AT + timedelta(seconds=1)) with pytest.raises(ValueError): _record(released_at=CONSTRUCTED_AT - timedelta(seconds=1)) + with pytest.raises(ValueError, match="owner contract"): + _record(owner_contract_released_at=RELEASED_AT + timedelta(seconds=1)) with pytest.raises(BaseWeightAuthorityIntegrityError): _resolve(read_port=_ReadPort(_record(released_at=USED_AT + timedelta(seconds=1)))) @@ -240,6 +252,7 @@ def test_source_sampling_and_release_chronology_fail_closed() -> None: ("owner_contract_reference", "wrong:owner", ValueError), ("owner_contract_version", 0, ValueError), ("owner_contract_digest", "7" * 63, ValueError), + ("owner_contract_released_at", datetime(2026, 9, 17, 6, 45), ValueError), ], ) def test_hostile_coordinates_fail_closed(key: str, value: object, error: type[Exception]) -> None: @@ -253,4 +266,4 @@ def test_view_cannot_be_constructed_directly() -> None: tenant_record_id=TENANT, validity_study_id=STUDY, fields=(), - ) + ) \ No newline at end of file From 8f95d59c72eb887370ec0a4a94afbca96936594f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 20:19:45 +0900 Subject: [PATCH 139/603] docs(workforce-validation): record base-weight contract chronology --- services/workforce-validation-api/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 1d82370ce..de3e6d713 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -50,7 +50,7 @@ This preserves the evidence needed to reproduce which governed trimming/bounding `resolve_base_weight_authority(...)` corroborates the base/design-weight derivation instead of accepting `base_weight_evidence_digest` as an opaque caller label. It binds an exact released base-weight evidence receipt to the source-universe and sampling-design receipt references/versions/digests, their release chronology, the sampled occurrence set, an immutable digest of the stage-wise selection-probability evidence, the positive selection-stage count, base-weight method/version, resulting base-weight artifact, construction time, and released owner contract. -The stage-wise probability values themselves stay with the sampling owner. `workforce_validation` receives only the evidence identity needed to prove which selection-probability set and sampled occurrence set produced the base artifact. Source and sampling evidence must already be released when the base weight is constructed, and scientific use cannot precede release of the base-weight evidence. This closes the remaining #407 gap where the final-weight receipt carried only a base-evidence digest and artifact identity without independently corroborating the sampling evidence needed to verify `1/π` or another controlled base-weight derivation. +The stage-wise probability values themselves stay with the sampling owner. `workforce_validation` receives only the evidence identity needed to prove which selection-probability set and sampled occurrence set produced the base artifact. Source and sampling evidence must already be released when the base weight is constructed, the referenced owner contract must be released no later than the base-weight evidence receipt itself, and scientific use cannot precede release of that receipt. A contract released later cannot retroactively authorize an earlier base-weight receipt. This closes the remaining #407 gap where the final-weight receipt carried only a base-evidence digest and artifact identity without independently corroborating the sampling evidence needed to verify `1/π` or another controlled base-weight derivation. ## Final analysis-weight authority @@ -91,6 +91,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, stage-wise base/design-weight provenance, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, stage-wise base/design-weight provenance including owner-contract-before-receipt chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. -These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. +These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. \ No newline at end of file From 9aaa50528e410710d84ff68e9bbeec133c1748ec Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 20:24:03 +0900 Subject: [PATCH 140/603] test(workforce-validation): keep base owner release owner-resolved --- .../test_base_weight_owner_contract_chronology.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_base_weight_owner_contract_chronology.py b/services/workforce-validation-api/tests/test_base_weight_owner_contract_chronology.py index c982dd407..17232bab8 100644 --- a/services/workforce-validation-api/tests/test_base_weight_owner_contract_chronology.py +++ b/services/workforce-validation-api/tests/test_base_weight_owner_contract_chronology.py @@ -3,11 +3,15 @@ from __future__ import annotations from datetime import datetime, timedelta, timezone +from inspect import signature from uuid import UUID import pytest -from orgmetra_workforce_validation_api.base_weight_authority import BaseWeightAuthorityRecord +from orgmetra_workforce_validation_api.base_weight_authority import ( + BaseWeightAuthorityRecord, + resolve_base_weight_authority, +) TENANT = UUID("10000000-0000-7000-8000-000000000001") STUDY = UUID("00000000-0000-7000-8000-0000000000f1") @@ -64,6 +68,10 @@ def test_owner_contract_release_is_preserved_as_authority_provenance() -> None: assert dict(record.fields)["owner_contract_released_at"] == OWNER_CONTRACT_RELEASED_AT +def test_owner_contract_release_is_not_a_caller_asserted_resolver_coordinate() -> None: + assert "owner_contract_released_at" not in signature(resolve_base_weight_authority).parameters + + def test_owner_contract_cannot_postdate_base_weight_receipt_release() -> None: with pytest.raises(ValueError, match="owner contract"): _record(owner_contract_released_at=RELEASED_AT + timedelta(seconds=1)) From 97cc3e11d8dfc7110c22d5050e56f8245e06a995 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 20:24:45 +0900 Subject: [PATCH 141/603] fix(workforce-validation): resolve base owner release from owner evidence --- .../base_weight_authority.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py index 5167c5534..a0d1c7d74 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py @@ -65,7 +65,7 @@ ) -class BaseWeightAuthorityNotFound(LookupError): +class BaseWeightAuthorityNotFound(LookError := LookupError): """Indicate that no released owner evidence corroborates the base weight.""" @@ -323,7 +323,6 @@ def resolve_base_weight_authority( owner_contract_reference: str, owner_contract_version: int, owner_contract_digest: str, - owner_contract_released_at: datetime, used_at: datetime, purpose_code: str, policy: PurposeBoundAccessPolicy, @@ -365,7 +364,7 @@ def resolve_base_weight_authority( owner_contract_reference=owner_contract_reference, owner_contract_version=owner_contract_version, owner_contract_digest=owner_contract_digest, - owner_contract_released_at=owner_contract_released_at, + owner_contract_released_at=constructed_at, released_at=constructed_at, ) tenant_id = requested.tenant_record_id @@ -444,12 +443,22 @@ def resolve_base_weight_authority( released_at=persisted.released_at, **dict(persisted.fields), ) + record_values = dict(record.fields) + requested_match = tuple( + (field_name, field_value) + for field_name, field_value in requested.fields + if field_name != "owner_contract_released_at" + ) + record_match = tuple( + (field_name, record_values[field_name]) + for field_name, _ in requested_match + ) if ( _store_operational_uuid("record tenant_record_id", record.tenant_record_id) != _store_operational_uuid("requested tenant_record_id", requested.tenant_record_id) or _store_operational_uuid("record validity_study_id", record.validity_study_id) != _store_operational_uuid("requested validity_study_id", requested.validity_study_id) - or record.fields != requested.fields + or record_match != requested_match ): raise BaseWeightAuthorityIntegrityError( "released base-weight authority does not match requested coordinates" From 0b9137c7e5ab09069a5cf0422dae7ad0f9082bce Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 20:25:39 +0900 Subject: [PATCH 142/603] fix(workforce-validation): restore base authority exception type --- .../orgmetra_workforce_validation_api/base_weight_authority.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py index a0d1c7d74..0e846679e 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py @@ -65,7 +65,7 @@ ) -class BaseWeightAuthorityNotFound(LookError := LookupError): +class BaseWeightAuthorityNotFound(LookupError): """Indicate that no released owner evidence corroborates the base weight.""" From 7fb16ba6c9037b1d717def9cf9f10eaef3958d0c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 20:26:15 +0900 Subject: [PATCH 143/603] test(workforce-validation): verify owner-resolved base contract release --- .../tests/test_base_weight_authority.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/services/workforce-validation-api/tests/test_base_weight_authority.py b/services/workforce-validation-api/tests/test_base_weight_authority.py index 402b1665b..0d1930458 100644 --- a/services/workforce-validation-api/tests/test_base_weight_authority.py +++ b/services/workforce-validation-api/tests/test_base_weight_authority.py @@ -150,6 +150,7 @@ def _record(**overrides: object) -> BaseWeightAuthorityRecord: def _resolve(*, read_port: object, **overrides: object) -> BaseWeightAuthorityView: values = dict(_record().fields) + values.pop("owner_contract_released_at") values.update( { "principal": _principal(), @@ -175,6 +176,7 @@ def test_resolution_binds_sampling_stage_probabilities_to_base_weight_artifact() assert port.calls[0]["source_universe_receipt_version"] == 4 assert port.calls[0]["sampling_design_receipt_version"] == 3 assert port.calls[0]["selection_probability_set_digest"] == SELECTION_PROBABILITY_SET_DIGEST + assert "owner_contract_released_at" not in port.calls[0] assert ("sampled_occurrence_set_digest", SAMPLED_SET_DIGEST) in view.fields assert ("selection_stage_count", 2) in view.fields assert ("base_weight_artifact_digest", BASE_ARTIFACT_DIGEST) in view.fields @@ -182,6 +184,15 @@ def test_resolution_binds_sampling_stage_probabilities_to_base_weight_artifact() assert ("released_at", RELEASED_AT) in view.fields +def test_owner_contract_release_is_resolved_from_owner_evidence() -> None: + owner_release = OWNER_CONTRACT_RELEASED_AT + timedelta(seconds=1) + view = _resolve( + read_port=_ReadPort(_record(owner_contract_released_at=owner_release)) + ) + + assert ("owner_contract_released_at", owner_release) in view.fields + + def test_authorization_denial_happens_before_owner_resolution() -> None: port = _ReadPort(_record()) with pytest.raises(AuthorizationDeniedError): @@ -202,12 +213,6 @@ def test_missing_noncanonical_or_mismatched_owner_evidence_fails_closed() -> Non _resolve(read_port=_ReadPort(_record(tenant_record_id=OTHER_TENANT))) with pytest.raises(BaseWeightAuthorityIntegrityError): _resolve(read_port=_ReadPort(_record(validity_study_id=OTHER_STUDY))) - with pytest.raises(BaseWeightAuthorityIntegrityError): - _resolve( - read_port=_ReadPort( - _record(owner_contract_released_at=OWNER_CONTRACT_RELEASED_AT + timedelta(seconds=1)) - ) - ) def test_source_sampling_and_release_chronology_fail_closed() -> None: @@ -252,7 +257,6 @@ def test_source_sampling_and_release_chronology_fail_closed() -> None: ("owner_contract_reference", "wrong:owner", ValueError), ("owner_contract_version", 0, ValueError), ("owner_contract_digest", "7" * 63, ValueError), - ("owner_contract_released_at", datetime(2026, 9, 17, 6, 45), ValueError), ], ) def test_hostile_coordinates_fail_closed(key: str, value: object, error: type[Exception]) -> None: From eaa9ea3af85c8547ea9b040d0e1b3924bf403473 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 20:26:42 +0900 Subject: [PATCH 144/603] test(workforce-validation): cover owner release timestamp boundary --- .../tests/test_base_weight_owner_contract_chronology.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_base_weight_owner_contract_chronology.py b/services/workforce-validation-api/tests/test_base_weight_owner_contract_chronology.py index 17232bab8..083a5cef1 100644 --- a/services/workforce-validation-api/tests/test_base_weight_owner_contract_chronology.py +++ b/services/workforce-validation-api/tests/test_base_weight_owner_contract_chronology.py @@ -72,6 +72,8 @@ def test_owner_contract_release_is_not_a_caller_asserted_resolver_coordinate() - assert "owner_contract_released_at" not in signature(resolve_base_weight_authority).parameters -def test_owner_contract_cannot_postdate_base_weight_receipt_release() -> None: +def test_owner_contract_release_timestamp_and_chronology_fail_closed() -> None: + with pytest.raises(ValueError): + _record(owner_contract_released_at=datetime(2026, 9, 17, 6, 45)) with pytest.raises(ValueError, match="owner contract"): _record(owner_contract_released_at=RELEASED_AT + timedelta(seconds=1)) From 91b76dc2f046229c5c7fb17eeca272634c850e15 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 20:27:32 +0900 Subject: [PATCH 145/603] docs(workforce-validation): keep base owner release owner-resolved --- services/workforce-validation-api/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index de3e6d713..1db718d7e 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -50,7 +50,7 @@ This preserves the evidence needed to reproduce which governed trimming/bounding `resolve_base_weight_authority(...)` corroborates the base/design-weight derivation instead of accepting `base_weight_evidence_digest` as an opaque caller label. It binds an exact released base-weight evidence receipt to the source-universe and sampling-design receipt references/versions/digests, their release chronology, the sampled occurrence set, an immutable digest of the stage-wise selection-probability evidence, the positive selection-stage count, base-weight method/version, resulting base-weight artifact, construction time, and released owner contract. -The stage-wise probability values themselves stay with the sampling owner. `workforce_validation` receives only the evidence identity needed to prove which selection-probability set and sampled occurrence set produced the base artifact. Source and sampling evidence must already be released when the base weight is constructed, the referenced owner contract must be released no later than the base-weight evidence receipt itself, and scientific use cannot precede release of that receipt. A contract released later cannot retroactively authorize an earlier base-weight receipt. This closes the remaining #407 gap where the final-weight receipt carried only a base-evidence digest and artifact identity without independently corroborating the sampling evidence needed to verify `1/π` or another controlled base-weight derivation. +The stage-wise probability values themselves stay with the sampling owner. `workforce_validation` receives only the evidence identity needed to prove which selection-probability set and sampled occurrence set produced the base artifact. Source and sampling evidence must already be released when the base weight is constructed. The owner-contract release instant is **not** caller asserted: it is returned only by the owner record, must be timezone-aware, and must be no later than the released base-weight evidence receipt. A contract released later cannot retroactively authorize an earlier receipt. Scientific use cannot precede release of the base-weight evidence. This closes the #407 gap where the final-weight receipt carried only a base-evidence digest and artifact identity without independently corroborating the sampling evidence needed to verify `1/π` or another controlled base-weight derivation. ## Final analysis-weight authority @@ -76,7 +76,7 @@ The ordered adjustment chain is immutable and contiguous: each transform must co The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, point-weight/variance compatibility, validation-result binding, and validation-result non-verifiability. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, point-weight/variance compatibility, validation-result binding, and validation-result non-verifiability. Owner-resolved release instants such as base-weight `owner_contract_released_at` must come from those durable owner records rather than caller-supplied request coordinates. ## Test contract @@ -91,6 +91,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, stage-wise base/design-weight provenance including owner-contract-before-receipt chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, stage-wise base/design-weight provenance including owner-contract-before-receipt chronology and owner-resolved release time, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. \ No newline at end of file From 3872dbc4af5b0cdfff5055842ab5a8ffc501471f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 20:31:04 +0900 Subject: [PATCH 146/603] test(workforce-validation): keep base release chronology owner-resolved --- ...t_base_weight_owner_contract_chronology.py | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/services/workforce-validation-api/tests/test_base_weight_owner_contract_chronology.py b/services/workforce-validation-api/tests/test_base_weight_owner_contract_chronology.py index 083a5cef1..442cebc11 100644 --- a/services/workforce-validation-api/tests/test_base_weight_owner_contract_chronology.py +++ b/services/workforce-validation-api/tests/test_base_weight_owner_contract_chronology.py @@ -1,4 +1,4 @@ -"""Fail closed when base-weight evidence predates its released owner contract.""" +"""Fail closed when base-weight evidence predates its released prerequisites.""" from __future__ import annotations @@ -62,18 +62,32 @@ def _record(**overrides: object) -> BaseWeightAuthorityRecord: return BaseWeightAuthorityRecord(**values) -def test_owner_contract_release_is_preserved_as_authority_provenance() -> None: - record = _record() +def test_release_instants_are_preserved_as_authority_provenance() -> None: + fields = dict(_record().fields) - assert dict(record.fields)["owner_contract_released_at"] == OWNER_CONTRACT_RELEASED_AT + assert fields["source_universe_released_at"] == SOURCE_RELEASED_AT + assert fields["sampling_design_released_at"] == SAMPLING_RELEASED_AT + assert fields["owner_contract_released_at"] == OWNER_CONTRACT_RELEASED_AT -def test_owner_contract_release_is_not_a_caller_asserted_resolver_coordinate() -> None: - assert "owner_contract_released_at" not in signature(resolve_base_weight_authority).parameters +def test_release_instants_are_not_caller_asserted_resolver_coordinates() -> None: + parameters = signature(resolve_base_weight_authority).parameters + assert "source_universe_released_at" not in parameters + assert "sampling_design_released_at" not in parameters + assert "owner_contract_released_at" not in parameters -def test_owner_contract_release_timestamp_and_chronology_fail_closed() -> None: + +def test_released_prerequisite_timestamp_and_chronology_fail_closed() -> None: + with pytest.raises(ValueError): + _record(source_universe_released_at=datetime(2026, 9, 17, 6, 0)) + with pytest.raises(ValueError): + _record(sampling_design_released_at=datetime(2026, 9, 17, 6, 30)) with pytest.raises(ValueError): _record(owner_contract_released_at=datetime(2026, 9, 17, 6, 45)) + with pytest.raises(ValueError): + _record(source_universe_released_at=CONSTRUCTED_AT + timedelta(seconds=1)) + with pytest.raises(ValueError): + _record(sampling_design_released_at=CONSTRUCTED_AT + timedelta(seconds=1)) with pytest.raises(ValueError, match="owner contract"): _record(owner_contract_released_at=RELEASED_AT + timedelta(seconds=1)) From 037d2a42a45716b6c7fe11a47ea4327a8410211a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 20:32:23 +0900 Subject: [PATCH 147/603] fix(workforce-validation): resolve prerequisite releases from owner evidence --- .../base_weight_authority.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py index 0e846679e..35ff4cd67 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py @@ -64,6 +64,14 @@ } ) +_OWNER_RESOLVED_RELEASE_FIELDS = frozenset( + { + "source_universe_released_at", + "sampling_design_released_at", + "owner_contract_released_at", + } +) + class BaseWeightAuthorityNotFound(LookupError): """Indicate that no released owner evidence corroborates the base weight.""" @@ -308,11 +316,9 @@ def resolve_base_weight_authority( source_universe_receipt_reference: str, source_universe_receipt_version: int, source_universe_receipt_digest: str, - source_universe_released_at: datetime, sampling_design_receipt_reference: str, sampling_design_receipt_version: int, sampling_design_receipt_digest: str, - sampling_design_released_at: datetime, sampled_occurrence_set_digest: str, selection_probability_set_digest: str, selection_stage_count: int, @@ -349,11 +355,11 @@ def resolve_base_weight_authority( source_universe_receipt_reference=source_universe_receipt_reference, source_universe_receipt_version=source_universe_receipt_version, source_universe_receipt_digest=source_universe_receipt_digest, - source_universe_released_at=source_universe_released_at, + source_universe_released_at=constructed_at, sampling_design_receipt_reference=sampling_design_receipt_reference, sampling_design_receipt_version=sampling_design_receipt_version, sampling_design_receipt_digest=sampling_design_receipt_digest, - sampling_design_released_at=sampling_design_released_at, + sampling_design_released_at=constructed_at, sampled_occurrence_set_digest=sampled_occurrence_set_digest, selection_probability_set_digest=selection_probability_set_digest, selection_stage_count=selection_stage_count, @@ -447,7 +453,7 @@ def resolve_base_weight_authority( requested_match = tuple( (field_name, field_value) for field_name, field_value in requested.fields - if field_name != "owner_contract_released_at" + if field_name not in _OWNER_RESOLVED_RELEASE_FIELDS ) record_match = tuple( (field_name, record_values[field_name]) From 5f85e6dfa559f51534b8b1a7bef2e72644d525c7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 20:33:05 +0900 Subject: [PATCH 148/603] test(workforce-validation): verify owner-resolved prerequisite releases --- .../tests/test_base_weight_authority.py | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/tests/test_base_weight_authority.py b/services/workforce-validation-api/tests/test_base_weight_authority.py index 0d1930458..4a23e40c2 100644 --- a/services/workforce-validation-api/tests/test_base_weight_authority.py +++ b/services/workforce-validation-api/tests/test_base_weight_authority.py @@ -150,7 +150,12 @@ def _record(**overrides: object) -> BaseWeightAuthorityRecord: def _resolve(*, read_port: object, **overrides: object) -> BaseWeightAuthorityView: values = dict(_record().fields) - values.pop("owner_contract_released_at") + for owner_resolved_field in ( + "source_universe_released_at", + "sampling_design_released_at", + "owner_contract_released_at", + ): + values.pop(owner_resolved_field) values.update( { "principal": _principal(), @@ -176,20 +181,34 @@ def test_resolution_binds_sampling_stage_probabilities_to_base_weight_artifact() assert port.calls[0]["source_universe_receipt_version"] == 4 assert port.calls[0]["sampling_design_receipt_version"] == 3 assert port.calls[0]["selection_probability_set_digest"] == SELECTION_PROBABILITY_SET_DIGEST + assert "source_universe_released_at" not in port.calls[0] + assert "sampling_design_released_at" not in port.calls[0] assert "owner_contract_released_at" not in port.calls[0] assert ("sampled_occurrence_set_digest", SAMPLED_SET_DIGEST) in view.fields assert ("selection_stage_count", 2) in view.fields assert ("base_weight_artifact_digest", BASE_ARTIFACT_DIGEST) in view.fields + assert ("source_universe_released_at", SOURCE_RELEASED_AT) in view.fields + assert ("sampling_design_released_at", SAMPLING_RELEASED_AT) in view.fields assert ("owner_contract_released_at", OWNER_CONTRACT_RELEASED_AT) in view.fields assert ("released_at", RELEASED_AT) in view.fields -def test_owner_contract_release_is_resolved_from_owner_evidence() -> None: +def test_prerequisite_releases_are_resolved_from_owner_evidence() -> None: + source_release = SOURCE_RELEASED_AT + timedelta(seconds=1) + sampling_release = SAMPLING_RELEASED_AT + timedelta(seconds=1) owner_release = OWNER_CONTRACT_RELEASED_AT + timedelta(seconds=1) view = _resolve( - read_port=_ReadPort(_record(owner_contract_released_at=owner_release)) + read_port=_ReadPort( + _record( + source_universe_released_at=source_release, + sampling_design_released_at=sampling_release, + owner_contract_released_at=owner_release, + ) + ) ) + assert ("source_universe_released_at", source_release) in view.fields + assert ("sampling_design_released_at", sampling_release) in view.fields assert ("owner_contract_released_at", owner_release) in view.fields From f38ee5852ef2b5722d4724aff5bd4b5a0a1fb704 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 20:33:48 +0900 Subject: [PATCH 149/603] docs(workforce-validation): keep prerequisite chronology owner-resolved --- services/workforce-validation-api/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 1db718d7e..a96838cc8 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -50,7 +50,7 @@ This preserves the evidence needed to reproduce which governed trimming/bounding `resolve_base_weight_authority(...)` corroborates the base/design-weight derivation instead of accepting `base_weight_evidence_digest` as an opaque caller label. It binds an exact released base-weight evidence receipt to the source-universe and sampling-design receipt references/versions/digests, their release chronology, the sampled occurrence set, an immutable digest of the stage-wise selection-probability evidence, the positive selection-stage count, base-weight method/version, resulting base-weight artifact, construction time, and released owner contract. -The stage-wise probability values themselves stay with the sampling owner. `workforce_validation` receives only the evidence identity needed to prove which selection-probability set and sampled occurrence set produced the base artifact. Source and sampling evidence must already be released when the base weight is constructed. The owner-contract release instant is **not** caller asserted: it is returned only by the owner record, must be timezone-aware, and must be no later than the released base-weight evidence receipt. A contract released later cannot retroactively authorize an earlier receipt. Scientific use cannot precede release of the base-weight evidence. This closes the #407 gap where the final-weight receipt carried only a base-evidence digest and artifact identity without independently corroborating the sampling evidence needed to verify `1/π` or another controlled base-weight derivation. +The stage-wise probability values themselves stay with the sampling owner. `workforce_validation` receives only the evidence identity needed to prove which selection-probability set and sampled occurrence set produced the base artifact. The source-universe release instant, sampling-design release instant, and owner-contract release instant are all **owner-resolved evidence**, not caller request coordinates. Source and sampling evidence must already be released when the base weight is constructed; the owner contract must be released no later than the base-weight evidence receipt. All three instants must be timezone-aware. A caller therefore cannot manufacture favorable chronology by supplying release timestamps, and a later owner contract cannot retroactively authorize an earlier receipt. Scientific use cannot precede release of the base-weight evidence. This closes the #407 gap where the final-weight receipt carried only a base-evidence digest and artifact identity without independently corroborating the sampling evidence needed to verify `1/π` or another controlled base-weight derivation. ## Final analysis-weight authority @@ -76,7 +76,7 @@ The ordered adjustment chain is immutable and contiguous: each transform must co The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, point-weight/variance compatibility, validation-result binding, and validation-result non-verifiability. Owner-resolved release instants such as base-weight `owner_contract_released_at` must come from those durable owner records rather than caller-supplied request coordinates. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, point-weight/variance compatibility, validation-result binding, and validation-result non-verifiability. Base-weight source-universe, sampling-design, and owner-contract release instants must come from those durable owner records rather than caller-supplied request coordinates. ## Test contract @@ -91,6 +91,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, stage-wise base/design-weight provenance including owner-contract-before-receipt chronology and owner-resolved release time, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. \ No newline at end of file From 8fa816ba191b0005f9fa3ac0c68f2ce6b243e799 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 21:01:07 +0900 Subject: [PATCH 150/603] test(workforce-validation): RED final-weight supersession authority --- ...est_final_weight_supersession_authority.py | 239 ++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_supersession_authority.py diff --git a/services/workforce-validation-api/tests/test_final_weight_supersession_authority.py b/services/workforce-validation-api/tests/test_final_weight_supersession_authority.py new file mode 100644 index 000000000..f84a4c8e9 --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_supersession_authority.py @@ -0,0 +1,239 @@ +"""Fail closed when released final analysis-weight evidence has been superseded.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.final_weight_supersession_authority import ( + FinalWeightSupersessionAuthorityIntegrityError, + FinalWeightSupersessionAuthorityRecord, + resolve_final_weight_supersession_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RECEIPT_REFERENCE = "analysis_weight_receipt:11111111-1111-4111-8111-111111111111" +SUCCESSOR_REFERENCE = "analysis_weight_receipt:33333333-3333-4333-8333-333333333333" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +RECEIPT_DIGEST = "1" * 64 +SUCCESSOR_DIGEST = "3" * 64 +OWNER_CONTRACT_DIGEST = "2" * 64 +RELEASED_AT = datetime(2026, 7, 15, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 7, 1, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "analysis_weight_receipt_reference", + "analysis_weight_receipt_digest", + "evidence_version", + "correction_sequence", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + } +) + + +class _ReadPort: + """Return one configured owner record through the canonical supersession read shape.""" + + def __init__(self, record: FinalWeightSupersessionAuthorityRecord) -> None: + self.record = record + + def read_final_weight_supersession_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + analysis_weight_receipt_reference: str, + analysis_weight_receipt_digest: str, + evidence_version: int, + correction_sequence: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> FinalWeightSupersessionAuthorityRecord: + """Return owner evidence; resolver verifies every request coordinate.""" + return self.record + + +def _principal() -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy() -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="final-weight-supersession-authority-read-v1", + resource_kind="final_weight_supersession_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record( + *, + superseded_at: datetime | None, + successor_reference: str | None, + successor_correction_sequence: int | None, + successor_digest: str | None, + successor_released_at: datetime | None, +) -> FinalWeightSupersessionAuthorityRecord: + return FinalWeightSupersessionAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + analysis_weight_receipt_reference=RECEIPT_REFERENCE, + analysis_weight_receipt_digest=RECEIPT_DIGEST, + evidence_version=1, + correction_sequence=2, + owner_contract_reference=OWNER_CONTRACT_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_CONTRACT_DIGEST, + owner_contract_released_at=OWNER_CONTRACT_RELEASED_AT, + released_at=RELEASED_AT, + superseded_at=superseded_at, + successor_analysis_weight_receipt_reference=successor_reference, + successor_correction_sequence=successor_correction_sequence, + successor_analysis_weight_receipt_digest=successor_digest, + successor_released_at=successor_released_at, + ) + + +def _resolve( + record: FinalWeightSupersessionAuthorityRecord, + *, + used_at: datetime = USED_AT, +): + return resolve_final_weight_supersession_authority( + principal=_principal(), + tenant_record_id=TENANT, + validity_study_id=STUDY, + analysis_weight_receipt_reference=RECEIPT_REFERENCE, + analysis_weight_receipt_digest=RECEIPT_DIGEST, + evidence_version=1, + correction_sequence=2, + owner_contract_reference=OWNER_CONTRACT_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_CONTRACT_DIGEST, + used_at=used_at, + purpose_code="selection_validity_analysis", + policy=_policy(), + read_port=_ReadPort(record), + ) + + +def test_historical_use_before_supersession_remains_verifiable_without_leaking_successor() -> None: + superseded_at = USED_AT + timedelta(days=1) + view = _resolve( + _record( + superseded_at=superseded_at, + successor_reference=SUCCESSOR_REFERENCE, + successor_correction_sequence=3, + successor_digest=SUCCESSOR_DIGEST, + successor_released_at=USED_AT + timedelta(hours=12), + ) + ) + + fields = dict(view.fields) + assert fields["analysis_weight_receipt_reference"] == RECEIPT_REFERENCE + assert fields["correction_sequence"] == 2 + assert "superseded_at" not in fields + assert "successor_analysis_weight_receipt_reference" not in fields + assert "successor_released_at" not in fields + + +def test_superseded_final_weight_is_not_authoritative_at_or_after_cutover() -> None: + record = _record( + superseded_at=USED_AT, + successor_reference=SUCCESSOR_REFERENCE, + successor_correction_sequence=3, + successor_digest=SUCCESSOR_DIGEST, + successor_released_at=USED_AT - timedelta(hours=1), + ) + + with pytest.raises(FinalWeightSupersessionAuthorityIntegrityError): + _resolve(record) + + +def test_owner_contract_cannot_be_released_after_final_weight_receipt() -> None: + with pytest.raises(ValueError, match="owner contract must be released no later than final-weight receipt"): + FinalWeightSupersessionAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + analysis_weight_receipt_reference=RECEIPT_REFERENCE, + analysis_weight_receipt_digest=RECEIPT_DIGEST, + evidence_version=1, + correction_sequence=2, + owner_contract_reference=OWNER_CONTRACT_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_CONTRACT_DIGEST, + owner_contract_released_at=RELEASED_AT + timedelta(seconds=1), + released_at=RELEASED_AT, + ) + + +@pytest.mark.parametrize( + ( + "superseded_at", + "successor_reference", + "successor_correction_sequence", + "successor_digest", + "successor_released_at", + ), + [ + (USED_AT, None, 3, SUCCESSOR_DIGEST, USED_AT), + (None, SUCCESSOR_REFERENCE, 3, SUCCESSOR_DIGEST, USED_AT), + (USED_AT, RECEIPT_REFERENCE, 3, SUCCESSOR_DIGEST, USED_AT), + (USED_AT, SUCCESSOR_REFERENCE, 2, SUCCESSOR_DIGEST, USED_AT), + (USED_AT, SUCCESSOR_REFERENCE, 3, RECEIPT_DIGEST, USED_AT), + ( + RELEASED_AT - timedelta(seconds=1), + SUCCESSOR_REFERENCE, + 3, + SUCCESSOR_DIGEST, + RELEASED_AT - timedelta(seconds=1), + ), + ( + USED_AT, + SUCCESSOR_REFERENCE, + 3, + SUCCESSOR_DIGEST, + USED_AT + timedelta(seconds=1), + ), + ( + USED_AT, + SUCCESSOR_REFERENCE, + 3, + SUCCESSOR_DIGEST, + RELEASED_AT, + ), + ], +) +def test_owner_record_rejects_incomplete_or_non_append_only_supersession_lineage( + superseded_at: datetime | None, + successor_reference: str | None, + successor_correction_sequence: int | None, + successor_digest: str | None, + successor_released_at: datetime | None, +) -> None: + with pytest.raises(ValueError): + _record( + superseded_at=superseded_at, + successor_reference=successor_reference, + successor_correction_sequence=successor_correction_sequence, + successor_digest=successor_digest, + successor_released_at=successor_released_at, + ) From 21f1580518b863a30dc88effd0918a567481fb05 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 21:02:00 +0900 Subject: [PATCH 151/603] feat(workforce-validation): enforce final-weight supersession authority --- .../final_weight_supersession_authority.py | 493 ++++++++++++++++++ 1 file changed, 493 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py new file mode 100644 index 000000000..5eee6984f --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py @@ -0,0 +1,493 @@ +"""Corroborate append-only final analysis-weight correction authority. + +The complete final-weight projection proves what one point-weight construction +contains. This boundary proves *when* that released receipt remained authoritative +and which released successor ended its half-open authority interval. It keeps +row-level weights and case identities with their scientific owners. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + +_RESOURCE_KIND = "final_weight_supersession_authority" +_OPERATION = "read" +_READ_FIELDS = frozenset( + { + "analysis_weight_receipt_reference", + "analysis_weight_receipt_digest", + "evidence_version", + "correction_sequence", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_analysis_weight_receipt_reference", + "successor_correction_sequence", + "successor_analysis_weight_receipt_digest", + "successor_released_at", + } +) +_VIEW_FIELDS = frozenset( + { + "analysis_weight_receipt_reference", + "analysis_weight_receipt_digest", + "evidence_version", + "correction_sequence", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + } +) + + +class FinalWeightSupersessionAuthorityNotFound(LookupError): + """Indicate that no released owner evidence corroborates the weight receipt.""" + + +class FinalWeightSupersessionAuthorityIntegrityError(RuntimeError): + """Indicate that released correction evidence cannot authorize scientific use.""" + + +class FinalWeightSupersessionAuthorityRecord(tuple): + """Immutable owner projection for one final-weight receipt authority interval.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + analysis_weight_receipt_reference: str, + analysis_weight_receipt_digest: str, + evidence_version: int, + correction_sequence: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + owner_contract_released_at: datetime, + released_at: datetime, + superseded_at: datetime | None = None, + successor_analysis_weight_receipt_reference: str | None = None, + successor_correction_sequence: int | None = None, + successor_analysis_weight_receipt_digest: str | None = None, + successor_released_at: datetime | None = None, + ) -> FinalWeightSupersessionAuthorityRecord: + """Validate released predecessor/successor chronology without weight values.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + receipt_ref = _require_reference( + "analysis_weight_receipt_reference", + analysis_weight_receipt_reference, + "analysis_weight_receipt", + ) + receipt_digest = _require_digest( + "analysis_weight_receipt_digest", analysis_weight_receipt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + correction = _require_positive_integer("correction_sequence", correction_sequence) + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + contract_released_at = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) + release_instant = _require_aware_datetime("released_at", released_at) + if contract_released_at > release_instant: + raise ValueError( + "owner contract must be released no later than final-weight receipt." + ) + + supersession_values = ( + superseded_at, + successor_analysis_weight_receipt_reference, + successor_correction_sequence, + successor_analysis_weight_receipt_digest, + successor_released_at, + ) + if all(value is None for value in supersession_values): + cutover = None + successor_ref = None + successor_correction = None + successor_digest = None + successor_release = None + elif any(value is None for value in supersession_values): + raise ValueError( + "final-weight supersession requires time and complete released successor coordinates." + ) + else: + cutover = _require_aware_datetime("superseded_at", superseded_at) + successor_ref = _require_reference( + "successor_analysis_weight_receipt_reference", + successor_analysis_weight_receipt_reference, + "analysis_weight_receipt", + ) + successor_correction = _require_positive_integer( + "successor_correction_sequence", successor_correction_sequence + ) + successor_digest = _require_digest( + "successor_analysis_weight_receipt_digest", + successor_analysis_weight_receipt_digest, + ) + successor_release = _require_aware_datetime( + "successor_released_at", successor_released_at + ) + if cutover < release_instant: + raise ValueError("superseded_at cannot precede final-weight receipt release.") + if successor_ref == receipt_ref: + raise ValueError("successor final-weight receipt must have a new reference.") + if successor_correction != correction + 1: + raise ValueError( + "successor correction_sequence must advance exactly by one." + ) + if successor_digest == receipt_digest: + raise ValueError("successor final-weight receipt must identify new evidence.") + if successor_release <= release_instant: + raise ValueError( + "successor final-weight receipt must be released after its predecessor." + ) + if successor_release > cutover: + raise ValueError( + "successor final-weight receipt must be released no later than supersession." + ) + + current_fields: tuple[tuple[str, object], ...] = ( + ("analysis_weight_receipt_digest", receipt_digest), + ("analysis_weight_receipt_reference", receipt_ref), + ("correction_sequence", correction), + ("evidence_version", version), + ("owner_contract_digest", owner_digest), + ("owner_contract_reference", owner_ref), + ("owner_contract_released_at", contract_released_at), + ("owner_contract_version", owner_version), + ) + successor_fields: tuple[tuple[str, object], ...] | None + if cutover is None: + successor_fields = None + else: + successor_fields = ( + ("successor_analysis_weight_receipt_digest", successor_digest), + ("successor_analysis_weight_receipt_reference", successor_ref), + ("successor_correction_sequence", successor_correction), + ("successor_released_at", successor_release), + ) + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + current_fields, + release_instant, + cutover, + successor_fields, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable current-receipt authority coordinates.""" + return self[2] + + @property + def released_at(self) -> datetime: + """Return when this final-weight receipt became released authority.""" + return self[3] + + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive end of this receipt's authority interval.""" + return self[4] + + @property + def successor_fields(self) -> tuple[tuple[str, object], ...] | None: + """Return internal released successor coordinates, if any.""" + return self[5] + + +class FinalWeightSupersessionAuthorityView(tuple): + """Minimized current-receipt authority issued only after purpose authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> FinalWeightSupersessionAuthorityView: + """Reject public construction; only the resolver may issue this view.""" + raise TypeError( + "FinalWeightSupersessionAuthorityView is issued only by " + "resolve_final_weight_supersession_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return released current-receipt provenance without successor disclosure.""" + return self[2] + + +@runtime_checkable +class FinalWeightSupersessionAuthorityReadPort(Protocol): + """Owner read contract for one released final-weight correction state.""" + + def read_final_weight_supersession_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + analysis_weight_receipt_reference: str, + analysis_weight_receipt_digest: str, + evidence_version: int, + correction_sequence: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> FinalWeightSupersessionAuthorityRecord | None: + """Return matching released supersession evidence or ``None``.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + FinalWeightSupersessionAuthorityReadPort, + "read_final_weight_supersession_authority", +) + + +def resolve_final_weight_supersession_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + analysis_weight_receipt_reference: str, + analysis_weight_receipt_digest: str, + evidence_version: int, + correction_sequence: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: FinalWeightSupersessionAuthorityReadPort, +) -> FinalWeightSupersessionAuthorityView: + """Authorize then resolve the receipt's half-open append-only authority interval.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static( + type(read_port), "read_final_weight_supersession_authority", None + ) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError( + "read_port must expose a statically callable " + "read_final_weight_supersession_authority." + ) + + tenant_id = _restore_operational_uuid( + "tenant_record_id", _store_operational_uuid("tenant_record_id", tenant_record_id) + ) + study_id = _restore_operational_uuid( + "validity_study_id", _store_operational_uuid("validity_study_id", validity_study_id) + ) + receipt_ref = _require_reference( + "analysis_weight_receipt_reference", + analysis_weight_receipt_reference, + "analysis_weight_receipt", + ) + receipt_digest = _require_digest( + "analysis_weight_receipt_digest", analysis_weight_receipt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + correction = _require_positive_integer("correction_sequence", correction_sequence) + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=tenant_id, + validity_study_id=study_id, + analysis_weight_receipt_reference=receipt_ref, + analysis_weight_receipt_digest=receipt_digest, + evidence_version=version, + correction_sequence=correction, + owner_contract_reference=owner_ref, + owner_contract_version=owner_version, + owner_contract_digest=owner_digest, + ) + if persisted is None: + raise FinalWeightSupersessionAuthorityNotFound(str(study_id)) + if type(persisted) is not FinalWeightSupersessionAuthorityRecord: + raise FinalWeightSupersessionAuthorityIntegrityError( + "owner port returned non-canonical final-weight supersession evidence" + ) + + record = FinalWeightSupersessionAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + successor_analysis_weight_receipt_reference=( + None + if persisted.successor_fields is None + else dict(persisted.successor_fields)[ + "successor_analysis_weight_receipt_reference" + ] + ), + successor_correction_sequence=( + None + if persisted.successor_fields is None + else dict(persisted.successor_fields)["successor_correction_sequence"] + ), + successor_analysis_weight_receipt_digest=( + None + if persisted.successor_fields is None + else dict(persisted.successor_fields)[ + "successor_analysis_weight_receipt_digest" + ] + ), + successor_released_at=( + None + if persisted.successor_fields is None + else dict(persisted.successor_fields)["successor_released_at"] + ), + **dict(persisted.fields), + ) + record_values = dict(record.fields) + if ( + _store_operational_uuid("record tenant_record_id", record.tenant_record_id) + != _store_operational_uuid("requested tenant_record_id", tenant_id) + or _store_operational_uuid("record validity_study_id", record.validity_study_id) + != _store_operational_uuid("requested validity_study_id", study_id) + or record_values["analysis_weight_receipt_reference"] != receipt_ref + or record_values["analysis_weight_receipt_digest"] != receipt_digest + or record_values["evidence_version"] != version + or record_values["correction_sequence"] != correction + or record_values["owner_contract_reference"] != owner_ref + or record_values["owner_contract_version"] != owner_version + or record_values["owner_contract_digest"] != owner_digest + ): + raise FinalWeightSupersessionAuthorityIntegrityError( + "released final-weight supersession authority does not match requested coordinates" + ) + if use_instant < record.released_at: + raise FinalWeightSupersessionAuthorityIntegrityError( + "final-weight authority cannot be used before its release instant" + ) + if record.superseded_at is not None and use_instant >= record.superseded_at: + raise FinalWeightSupersessionAuthorityIntegrityError( + "superseded final-weight receipt is not authoritative at scientific use" + ) + + values = dict(record.fields) + values["released_at"] = record.released_at + fields = tuple((field_name, values[field_name]) for field_name in sorted(_VIEW_FIELDS)) + return tuple.__new__( + FinalWeightSupersessionAuthorityView, + ( + _store_operational_uuid("tenant_record_id", record.tenant_record_id), + _store_operational_uuid("validity_study_id", record.validity_study_id), + fields, + ), + ) + + +__all__ = [ + "FinalWeightSupersessionAuthorityIntegrityError", + "FinalWeightSupersessionAuthorityNotFound", + "FinalWeightSupersessionAuthorityReadPort", + "FinalWeightSupersessionAuthorityRecord", + "FinalWeightSupersessionAuthorityView", + "resolve_final_weight_supersession_authority", +] From 327b8819650356499b91f8942e758d0fef463dcc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 21:02:26 +0900 Subject: [PATCH 152/603] test(workforce-validation): align supersession policy coverage --- .../tests/test_final_weight_supersession_authority.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/services/workforce-validation-api/tests/test_final_weight_supersession_authority.py b/services/workforce-validation-api/tests/test_final_weight_supersession_authority.py index f84a4c8e9..de5fe6e91 100644 --- a/services/workforce-validation-api/tests/test_final_weight_supersession_authority.py +++ b/services/workforce-validation-api/tests/test_final_weight_supersession_authority.py @@ -37,6 +37,11 @@ "owner_contract_digest", "owner_contract_released_at", "released_at", + "superseded_at", + "successor_analysis_weight_receipt_reference", + "successor_correction_sequence", + "successor_analysis_weight_receipt_digest", + "successor_released_at", } ) From 79533c89d02240a437c3a268ed17813c03ab4748 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 21:02:42 +0900 Subject: [PATCH 153/603] feat(workforce-validation): export final-weight supersession authority --- .../orgmetra_workforce_validation_api/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index 3063504cf..36056d271 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -33,6 +33,14 @@ FinalWeightAdjustmentCoordinate, resolve_final_analysis_weight_authority, ) +from orgmetra_workforce_validation_api.final_weight_supersession_authority import ( + FinalWeightSupersessionAuthorityIntegrityError, + FinalWeightSupersessionAuthorityNotFound, + FinalWeightSupersessionAuthorityReadPort, + FinalWeightSupersessionAuthorityRecord, + FinalWeightSupersessionAuthorityView, + resolve_final_weight_supersession_authority, +) from orgmetra_workforce_validation_api.nonresponse_adjustment_authority import ( NonresponseAdjustmentAuthorityIntegrityError, NonresponseAdjustmentAuthorityNotFound, @@ -126,6 +134,11 @@ "FinalAnalysisWeightAuthorityRecord", "FinalAnalysisWeightAuthorityView", "FinalWeightAdjustmentCoordinate", + "FinalWeightSupersessionAuthorityIntegrityError", + "FinalWeightSupersessionAuthorityNotFound", + "FinalWeightSupersessionAuthorityReadPort", + "FinalWeightSupersessionAuthorityRecord", + "FinalWeightSupersessionAuthorityView", "NonresponseAdjustmentAuthorityIntegrityError", "NonresponseAdjustmentAuthorityNotFound", "NonresponseAdjustmentAuthorityReadPort", @@ -168,6 +181,7 @@ "resolve_calibration_auxiliary_authority", "resolve_calibration_benchmark_authority", "resolve_final_analysis_weight_authority", + "resolve_final_weight_supersession_authority", "resolve_nonresponse_adjustment_authority", "resolve_trimming_bounding_authority", "resolve_validation_result_authority", From 9067d6111d68ba9f8cede8e42f10c7af70817683 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 21:03:11 +0900 Subject: [PATCH 154/603] docs(workforce-validation): document final-weight supersession authority --- services/workforce-validation-api/README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index a96838cc8..30f5d3488 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -58,9 +58,15 @@ The stage-wise probability values themselves stay with the sampling owner. `work The ordered adjustment chain is immutable and contiguous: each transform must consume the preceding artifact, material transforms may not be no-ops, and known nonresponse/calibration/raking/poststratification/trimming/bounding/winsorization codes require their specialized receipt kind. Source/sampling references are owner-corroborated coordinates layered over the digest-only scientific leaf, so a caller cannot turn an opaque digest into a floating source/design version. The separate base-weight authority additionally resolves the stage-wise selection-probability evidence behind the base artifact. No row-level weights, case identities, protected calibration values, or foreign tables cross this boundary. +## Final analysis-weight supersession authority + +`resolve_final_weight_supersession_authority(...)` closes #407 RED #10 at the application-owner boundary. A `correction_sequence` plus predecessor digest is not enough to prove that a previously released final-weight receipt stopped being authoritative without in-place mutation. The owner record therefore preserves the predecessor release instant, exclusive supersession instant, and complete released successor coordinates. The successor must have a new receipt reference and digest, advance the correction sequence exactly by one, be released after its predecessor, and already exist no later than the cutover. The released owner contract must predate the predecessor receipt. + +Scientific use is evaluated against the owner-resolved half-open interval `[released_at, superseded_at)`. Historical use inside that interval remains reproducible, while use at or after the cutover fails closed. Successor coordinates are deliberately omitted from the returned view so downstream callers receive only the currently requested receipt authority, not a reusable correction graph. Row-level weights and case identities remain outside this boundary. + ## Point-weight / variance authority -`resolve_weight_variance_authority(...)` corroborates released #405 sampling evidence, final analysis-weight receipt, analytic-case occurrence set, weight-eligibility receipt digest, correction sequence, final point-weight artifact, separate #406 variance-design evidence, variance method/evidence semantics, and released owner contract. A variance receipt cannot alias the point-weight receipt, and approximation evidence cannot be represented as exact. The separate eligibility, base-weight, and final analysis-weight authorities supply the durable population/duration, selection-probability provenance, and complete ordered point-weight lineage behind those compatibility coordinates. +`resolve_weight_variance_authority(...)` corroborates released #405 sampling evidence, final analysis-weight receipt, analytic-case occurrence set, weight-eligibility receipt digest, correction sequence, final point-weight artifact, separate #406 variance-design evidence, variance method/evidence semantics, and released owner contract. A variance receipt cannot alias the point-weight receipt, and approximation evidence cannot be represented as exact. The separate eligibility, base-weight, final analysis-weight, and final-weight supersession authorities supply the durable population/duration, selection-probability provenance, complete ordered point-weight lineage, and correction authority interval behind those compatibility coordinates. ## Released validation-result authority @@ -76,7 +82,7 @@ The ordered adjustment chain is immutable and contiguous: each transform must co The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, point-weight/variance compatibility, validation-result binding, and validation-result non-verifiability. Base-weight source-universe, sampling-design, and owner-contract release instants must come from those durable owner records rather than caller-supplied request coordinates. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, and validation-result non-verifiability. Base-weight source-universe, sampling-design, and owner-contract release instants must come from those durable owner records rather than caller-supplied request coordinates. Final-weight correction cutovers and successor coordinates likewise come only from released owner records, never caller timestamps or mutable result rows. ## Test contract @@ -91,6 +97,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage, final-weight predecessor/successor correction intervals, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. -These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. \ No newline at end of file +These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From 441fe0731b8edb642fff96e2779cc29a3b06a400 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 21:04:07 +0900 Subject: [PATCH 155/603] test(workforce-validation): cover final-weight supersession hostile edges --- ...nal_weight_supersession_authority_edges.py | 282 ++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_supersession_authority_edges.py diff --git a/services/workforce-validation-api/tests/test_final_weight_supersession_authority_edges.py b/services/workforce-validation-api/tests/test_final_weight_supersession_authority_edges.py new file mode 100644 index 000000000..ea8f7f989 --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_supersession_authority_edges.py @@ -0,0 +1,282 @@ +"""Hostile edges for append-only final analysis-weight correction authority.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.final_weight_supersession_authority import ( + FinalWeightSupersessionAuthorityIntegrityError, + FinalWeightSupersessionAuthorityNotFound, + FinalWeightSupersessionAuthorityReadPort, + FinalWeightSupersessionAuthorityRecord, + FinalWeightSupersessionAuthorityView, + resolve_final_weight_supersession_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000d2") +RECEIPT_REFERENCE = "analysis_weight_receipt:11111111-1111-4111-8111-111111111111" +OTHER_RECEIPT_REFERENCE = "analysis_weight_receipt:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" +SUCCESSOR_REFERENCE = "analysis_weight_receipt:33333333-3333-4333-8333-333333333333" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +OTHER_OWNER_CONTRACT_REFERENCE = "released_owner_contract:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" +RECEIPT_DIGEST = "1" * 64 +SUCCESSOR_DIGEST = "3" * 64 +OWNER_CONTRACT_DIGEST = "2" * 64 +RELEASED_AT = datetime(2026, 7, 15, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 7, 1, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "analysis_weight_receipt_reference", + "analysis_weight_receipt_digest", + "evidence_version", + "correction_sequence", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_analysis_weight_receipt_reference", + "successor_correction_sequence", + "successor_analysis_weight_receipt_digest", + "successor_released_at", + } +) + + +class _ReadPort: + """Return configured authority and retain lookup coordinates.""" + + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[dict[str, object]] = [] + + def read_final_weight_supersession_authority(self, **coordinates: object) -> object: + """Capture the owner lookup and return configured evidence.""" + self.calls.append(dict(coordinates)) + return self.result + + +class _NoReadMethod: + """Deliberately fail the owner-port protocol.""" + + +class _ProtocolOnly(FinalWeightSupersessionAuthorityReadPort): + """Inherit only the Protocol placeholder, not a concrete owner capability.""" + + +class _DescriptorReadPort: + """Expose a descriptor that static capability validation must reject.""" + + @property + def read_final_weight_supersession_authority(self) -> object: + raise AssertionError("descriptor must not execute") + + +def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=tenant_record_id, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="final-weight-supersession-authority-read-v1", + resource_kind="final_weight_supersession_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record(**overrides: object) -> FinalWeightSupersessionAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "analysis_weight_receipt_reference": RECEIPT_REFERENCE, + "analysis_weight_receipt_digest": RECEIPT_DIGEST, + "evidence_version": 1, + "correction_sequence": 2, + "owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "owner_contract_version": 3, + "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, + "released_at": RELEASED_AT, + "superseded_at": None, + "successor_analysis_weight_receipt_reference": None, + "successor_correction_sequence": None, + "successor_analysis_weight_receipt_digest": None, + "successor_released_at": None, + } + values.update(overrides) + return FinalWeightSupersessionAuthorityRecord(**values) + + +def _resolve(*, read_port: object, **overrides: object) -> FinalWeightSupersessionAuthorityView: + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "analysis_weight_receipt_reference": RECEIPT_REFERENCE, + "analysis_weight_receipt_digest": RECEIPT_DIGEST, + "evidence_version": 1, + "correction_sequence": 2, + "owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "owner_contract_version": 3, + "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_final_weight_supersession_authority(**values) + + +def test_current_receipt_resolution_uses_owner_release_chronology_without_successor() -> None: + port = _ReadPort(_record()) + + view = _resolve(read_port=port) + + assert isinstance(port, FinalWeightSupersessionAuthorityReadPort) + assert len(port.calls) == 1 + assert port.calls[0]["analysis_weight_receipt_reference"] == RECEIPT_REFERENCE + assert "owner_contract_released_at" not in port.calls[0] + assert "released_at" not in port.calls[0] + assert "superseded_at" not in port.calls[0] + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + fields = dict(view.fields) + assert fields["owner_contract_released_at"] == OWNER_CONTRACT_RELEASED_AT + assert fields["released_at"] == RELEASED_AT + assert "superseded_at" not in fields + + +def test_authorization_denial_happens_before_owner_resolution() -> None: + port = _ReadPort(_record()) + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, policy=_policy(purpose_code="audit_review")) + assert port.calls == [] + + +def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: + with pytest.raises(FinalWeightSupersessionAuthorityNotFound): + _resolve(read_port=_ReadPort(None)) + with pytest.raises(FinalWeightSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object())) + + +@pytest.mark.parametrize( + "record_overrides", + [ + {"tenant_record_id": OTHER_TENANT}, + {"validity_study_id": OTHER_STUDY}, + {"analysis_weight_receipt_reference": OTHER_RECEIPT_REFERENCE}, + {"analysis_weight_receipt_digest": "a" * 64}, + {"correction_sequence": 3}, + {"owner_contract_reference": OTHER_OWNER_CONTRACT_REFERENCE}, + {"owner_contract_version": 4}, + {"owner_contract_digest": "b" * 64}, + ], +) +def test_owner_evidence_must_match_every_requested_coordinate( + record_overrides: dict[str, object] +) -> None: + with pytest.raises(FinalWeightSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(**record_overrides))) + + +def test_release_chronology_and_use_fail_closed() -> None: + with pytest.raises(FinalWeightSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(released_at=USED_AT + timedelta(seconds=1)))) + + record = _record( + superseded_at=USED_AT + timedelta(seconds=1), + successor_analysis_weight_receipt_reference=SUCCESSOR_REFERENCE, + successor_correction_sequence=3, + successor_analysis_weight_receipt_digest=SUCCESSOR_DIGEST, + successor_released_at=USED_AT, + ) + view = _resolve(read_port=_ReadPort(record)) + assert dict(view.fields)["analysis_weight_receipt_digest"] == RECEIPT_DIGEST + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("analysis_weight_receipt_reference", "wrong:receipt", ValueError), + ("analysis_weight_receipt_digest", "ABC", ValueError), + ("evidence_version", False, ValueError), + ("evidence_version", 2, ValueError), + ("correction_sequence", 0, ValueError), + ("owner_contract_reference", "wrong:contract", ValueError), + ("owner_contract_version", 0, ValueError), + ("owner_contract_digest", "2" * 63, ValueError), + ("used_at", datetime(2026, 9, 17), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_or_dependency_fails_before_owner_resolution( + key: str, value: object, error: type[Exception] +) -> None: + port: object = _ReadPort(_record()) + overrides = {key: value} + if key == "read_port": + port = value + overrides = {} + with pytest.raises(error): + _resolve(read_port=port, **overrides) + if isinstance(port, _ReadPort): + assert port.calls == [] + + +def test_record_rejects_non_v1_evidence_and_public_view_construction() -> None: + with pytest.raises(ValueError, match="evidence_version must remain 1"): + _record(evidence_version=2) + with pytest.raises(TypeError, match="issued only by"): + FinalWeightSupersessionAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) + + +def test_record_and_view_are_structurally_immutable_and_uuid_views_are_detached() -> None: + tenant = UUID(str(TENANT)) + record = _record(tenant_record_id=tenant) + object.__setattr__(tenant, "int", OTHER_TENANT.int) + assert record.tenant_record_id == TENANT + assert record.validity_study_id == STUDY + assert record.released_at == RELEASED_AT + assert record.superseded_at is None + assert record.successor_fields is None + assert dict(record.fields)["correction_sequence"] == 2 + with pytest.raises(AttributeError): + object.__setattr__(record, "correction_sequence", 3) + + view = _resolve(read_port=_ReadPort(record)) + returned_tenant = view.tenant_record_id + object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) + assert view.tenant_record_id == TENANT + with pytest.raises(AttributeError): + object.__setattr__(view, "fields", ()) From 0b2b85564925d98a1ca7b20feadd2b9c9657ad36 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 21:08:31 +0900 Subject: [PATCH 156/603] test(workforce-validation): cover supersession record hostile edges --- ...ght_supersession_authority_record_edges.py | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_supersession_authority_record_edges.py diff --git a/services/workforce-validation-api/tests/test_final_weight_supersession_authority_record_edges.py b/services/workforce-validation-api/tests/test_final_weight_supersession_authority_record_edges.py new file mode 100644 index 000000000..243412603 --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_supersession_authority_record_edges.py @@ -0,0 +1,65 @@ +"""Record-level hostile edges for final analysis-weight correction authority.""" + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.final_weight_supersession_authority import ( + FinalWeightSupersessionAuthorityRecord, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RECEIPT_REFERENCE = "analysis_weight_receipt:11111111-1111-4111-8111-111111111111" +SUCCESSOR_REFERENCE = "analysis_weight_receipt:33333333-3333-4333-8333-333333333333" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +RECEIPT_DIGEST = "1" * 64 +SUCCESSOR_DIGEST = "3" * 64 +OWNER_CONTRACT_DIGEST = "2" * 64 +RELEASED_AT = datetime(2026, 7, 15, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 7, 1, tzinfo=timezone.utc) +SUPERSEDED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) +SUCCESSOR_RELEASED_AT = SUPERSEDED_AT - timedelta(hours=1) + + +def _record(**overrides: object) -> FinalWeightSupersessionAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "analysis_weight_receipt_reference": RECEIPT_REFERENCE, + "analysis_weight_receipt_digest": RECEIPT_DIGEST, + "evidence_version": 1, + "correction_sequence": 2, + "owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "owner_contract_version": 3, + "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, + "released_at": RELEASED_AT, + "superseded_at": SUPERSEDED_AT, + "successor_analysis_weight_receipt_reference": SUCCESSOR_REFERENCE, + "successor_correction_sequence": 3, + "successor_analysis_weight_receipt_digest": SUCCESSOR_DIGEST, + "successor_released_at": SUCCESSOR_RELEASED_AT, + } + values.update(overrides) + return FinalWeightSupersessionAuthorityRecord(**values) + + +@pytest.mark.parametrize( + "overrides", + [ + {"owner_contract_released_at": datetime(2026, 7, 1)}, + {"released_at": datetime(2026, 7, 15)}, + {"superseded_at": datetime(2026, 9, 17)}, + {"successor_analysis_weight_receipt_reference": "wrong:receipt"}, + {"successor_correction_sequence": False}, + {"successor_analysis_weight_receipt_digest": "ABC"}, + {"successor_released_at": datetime(2026, 9, 16, 23, 0)}, + ], +) +def test_record_rejects_malformed_owner_resolved_chronology_or_successor_coordinates( + overrides: dict[str, object], +) -> None: + with pytest.raises(ValueError): + _record(**overrides) From f691699f99fa9163db9537247528ef05d1239412 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 22:03:13 +0900 Subject: [PATCH 157/603] test(workforce-validation): require result supersession authority --- .../test_result_supersession_authority.py | 243 ++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_result_supersession_authority.py diff --git a/services/workforce-validation-api/tests/test_result_supersession_authority.py b/services/workforce-validation-api/tests/test_result_supersession_authority.py new file mode 100644 index 000000000..897b85b2c --- /dev/null +++ b/services/workforce-validation-api/tests/test_result_supersession_authority.py @@ -0,0 +1,243 @@ +"""Fail closed when a released validation result has been superseded.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.result_supersession_authority import ( + ValidationResultSupersessionAuthorityIntegrityError, + ValidationResultSupersessionAuthorityRecord, + resolve_validation_result_supersession_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +SUCCESSOR_REFERENCE = "validation_analysis_result:33333333-3333-4333-8333-333333333333" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +RESULT_DIGEST = "1" * 64 +SUCCESSOR_DIGEST = "3" * 64 +OWNER_CONTRACT_DIGEST = "2" * 64 +RELEASED_AT = datetime(2026, 9, 17, 10, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 1, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 12, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "result_reference", + "result_digest", + "evidence_version", + "correction_sequence", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_result_reference", + "successor_correction_sequence", + "successor_result_digest", + "successor_released_at", + } +) + + +class _ReadPort: + """Return one configured owner record through the result supersession read shape.""" + + def __init__(self, record: ValidationResultSupersessionAuthorityRecord) -> None: + self.record = record + + def read_validation_result_supersession_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + evidence_version: int, + correction_sequence: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> ValidationResultSupersessionAuthorityRecord: + """Return owner evidence; resolver verifies every request coordinate.""" + return self.record + + +def _principal() -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy() -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="validation-result-supersession-authority-read-v1", + resource_kind="validation_result_supersession_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record( + *, + superseded_at: datetime | None, + successor_reference: str | None, + successor_correction_sequence: int | None, + successor_digest: str | None, + successor_released_at: datetime | None, +) -> ValidationResultSupersessionAuthorityRecord: + return ValidationResultSupersessionAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + evidence_version=1, + correction_sequence=2, + owner_contract_reference=OWNER_CONTRACT_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_CONTRACT_DIGEST, + owner_contract_released_at=OWNER_CONTRACT_RELEASED_AT, + released_at=RELEASED_AT, + superseded_at=superseded_at, + successor_result_reference=successor_reference, + successor_correction_sequence=successor_correction_sequence, + successor_result_digest=successor_digest, + successor_released_at=successor_released_at, + ) + + +def _resolve( + record: ValidationResultSupersessionAuthorityRecord, + *, + used_at: datetime = USED_AT, +): + return resolve_validation_result_supersession_authority( + principal=_principal(), + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + evidence_version=1, + correction_sequence=2, + owner_contract_reference=OWNER_CONTRACT_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_CONTRACT_DIGEST, + used_at=used_at, + purpose_code="selection_validity_analysis", + policy=_policy(), + read_port=_ReadPort(record), + ) + + +def test_historical_result_use_before_supersession_remains_verifiable_without_leaking_successor() -> None: + view = _resolve( + _record( + superseded_at=USED_AT + timedelta(days=1), + successor_reference=SUCCESSOR_REFERENCE, + successor_correction_sequence=3, + successor_digest=SUCCESSOR_DIGEST, + successor_released_at=USED_AT + timedelta(hours=12), + ) + ) + + fields = dict(view.fields) + assert fields["result_reference"] == RESULT_REFERENCE + assert fields["correction_sequence"] == 2 + assert "superseded_at" not in fields + assert "successor_result_reference" not in fields + assert "successor_released_at" not in fields + + +def test_superseded_result_is_not_authoritative_at_or_after_cutover() -> None: + record = _record( + superseded_at=USED_AT, + successor_reference=SUCCESSOR_REFERENCE, + successor_correction_sequence=3, + successor_digest=SUCCESSOR_DIGEST, + successor_released_at=USED_AT - timedelta(minutes=1), + ) + + with pytest.raises(ValidationResultSupersessionAuthorityIntegrityError): + _resolve(record) + + +def test_owner_contract_cannot_be_released_after_result() -> None: + with pytest.raises(ValueError, match="owner contract must be released no later than validation result"): + ValidationResultSupersessionAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + evidence_version=1, + correction_sequence=2, + owner_contract_reference=OWNER_CONTRACT_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_CONTRACT_DIGEST, + owner_contract_released_at=RELEASED_AT + timedelta(seconds=1), + released_at=RELEASED_AT, + ) + + +@pytest.mark.parametrize( + ( + "superseded_at", + "successor_reference", + "successor_correction_sequence", + "successor_digest", + "successor_released_at", + ), + [ + (USED_AT, None, 3, SUCCESSOR_DIGEST, USED_AT), + (None, SUCCESSOR_REFERENCE, 3, SUCCESSOR_DIGEST, USED_AT), + (USED_AT, RESULT_REFERENCE, 3, SUCCESSOR_DIGEST, USED_AT), + (USED_AT, SUCCESSOR_REFERENCE, 2, SUCCESSOR_DIGEST, USED_AT), + (USED_AT, SUCCESSOR_REFERENCE, 3, RESULT_DIGEST, USED_AT), + ( + RELEASED_AT - timedelta(seconds=1), + SUCCESSOR_REFERENCE, + 3, + SUCCESSOR_DIGEST, + RELEASED_AT - timedelta(seconds=1), + ), + ( + USED_AT, + SUCCESSOR_REFERENCE, + 3, + SUCCESSOR_DIGEST, + USED_AT + timedelta(seconds=1), + ), + ( + USED_AT, + SUCCESSOR_REFERENCE, + 3, + SUCCESSOR_DIGEST, + RELEASED_AT, + ), + ], +) +def test_owner_record_rejects_incomplete_or_non_append_only_result_supersession( + superseded_at: datetime | None, + successor_reference: str | None, + successor_correction_sequence: int | None, + successor_digest: str | None, + successor_released_at: datetime | None, +) -> None: + with pytest.raises(ValueError): + _record( + superseded_at=superseded_at, + successor_reference=successor_reference, + successor_correction_sequence=successor_correction_sequence, + successor_digest=successor_digest, + successor_released_at=successor_released_at, + ) From 02df69e6c1792f04bee72f64e7e6ba876a853c85 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 22:03:58 +0900 Subject: [PATCH 158/603] feat(workforce-validation): corroborate result supersession --- .../result_supersession_authority.py | 493 ++++++++++++++++++ 1 file changed, 493 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py new file mode 100644 index 000000000..5052faa49 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py @@ -0,0 +1,493 @@ +"""Corroborate append-only validation-result correction authority. + +One validation-result record proves what immutable scientific evidence was +released. This application boundary proves when that released result remained +authoritative and which complete released successor ended its half-open +authority interval. Successor coordinates stay internal to the owner boundary. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + +_RESOURCE_KIND = "validation_result_supersession_authority" +_OPERATION = "read" +_READ_FIELDS = frozenset( + { + "result_reference", + "result_digest", + "evidence_version", + "correction_sequence", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_result_reference", + "successor_correction_sequence", + "successor_result_digest", + "successor_released_at", + } +) +_VIEW_FIELDS = frozenset( + { + "result_reference", + "result_digest", + "evidence_version", + "correction_sequence", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + } +) + + +class ValidationResultSupersessionAuthorityNotFound(LookupError): + """Indicate that no released owner evidence corroborates the result version.""" + + +class ValidationResultSupersessionAuthorityIntegrityError(RuntimeError): + """Indicate that released correction evidence cannot authorize result use.""" + + +class ValidationResultSupersessionAuthorityRecord(tuple): + """Immutable owner projection for one released result authority interval.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + evidence_version: int, + correction_sequence: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + owner_contract_released_at: datetime, + released_at: datetime, + superseded_at: datetime | None = None, + successor_result_reference: str | None = None, + successor_correction_sequence: int | None = None, + successor_result_digest: str | None = None, + successor_released_at: datetime | None = None, + ) -> ValidationResultSupersessionAuthorityRecord: + """Validate released predecessor/successor chronology without result values.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + result_ref = _require_reference( + "result_reference", result_reference, "validation_analysis_result" + ) + result_evidence_digest = _require_digest("result_digest", result_digest) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + correction = _require_positive_integer("correction_sequence", correction_sequence) + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + contract_released_at = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) + release_instant = _require_aware_datetime("released_at", released_at) + if contract_released_at > release_instant: + raise ValueError( + "owner contract must be released no later than validation result." + ) + + supersession_values = ( + superseded_at, + successor_result_reference, + successor_correction_sequence, + successor_result_digest, + successor_released_at, + ) + if all(value is None for value in supersession_values): + cutover = None + successor_ref = None + successor_correction = None + successor_digest = None + successor_release = None + elif any(value is None for value in supersession_values): + raise ValueError( + "result supersession requires time and complete released successor coordinates." + ) + else: + cutover = _require_aware_datetime("superseded_at", superseded_at) + successor_ref = _require_reference( + "successor_result_reference", + successor_result_reference, + "validation_analysis_result", + ) + successor_correction = _require_positive_integer( + "successor_correction_sequence", successor_correction_sequence + ) + successor_digest = _require_digest( + "successor_result_digest", successor_result_digest + ) + successor_release = _require_aware_datetime( + "successor_released_at", successor_released_at + ) + if cutover < release_instant: + raise ValueError("superseded_at cannot precede validation-result release.") + if successor_ref == result_ref: + raise ValueError("successor validation result must use a new reference.") + if successor_correction != correction + 1: + raise ValueError( + "successor correction_sequence must advance exactly by one." + ) + if successor_digest == result_evidence_digest: + raise ValueError("successor validation result must identify new evidence.") + if successor_release <= release_instant: + raise ValueError( + "successor validation result must be released after its predecessor." + ) + if successor_release > cutover: + raise ValueError( + "successor validation result must be released no later than supersession." + ) + + current_fields: tuple[tuple[str, object], ...] = ( + ("correction_sequence", correction), + ("evidence_version", version), + ("owner_contract_digest", owner_digest), + ("owner_contract_reference", owner_ref), + ("owner_contract_released_at", contract_released_at), + ("owner_contract_version", owner_version), + ("result_digest", result_evidence_digest), + ("result_reference", result_ref), + ) + successor_fields: tuple[tuple[str, object], ...] | None + if cutover is None: + successor_fields = None + else: + successor_fields = ( + ("successor_correction_sequence", successor_correction), + ("successor_released_at", successor_release), + ("successor_result_digest", successor_digest), + ("successor_result_reference", successor_ref), + ) + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + current_fields, + release_instant, + cutover, + successor_fields, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable current-result authority coordinates.""" + return self[2] + + @property + def released_at(self) -> datetime: + """Return when this validation result became released authority.""" + return self[3] + + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive end of this result's authority interval.""" + return self[4] + + @property + def successor_fields(self) -> tuple[tuple[str, object], ...] | None: + """Return internal released successor coordinates, if any.""" + return self[5] + + +class ValidationResultSupersessionAuthorityView(tuple): + """Minimized current-result authority issued only after purpose authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> ValidationResultSupersessionAuthorityView: + """Reject public construction; only the resolver may issue this view.""" + raise TypeError( + "ValidationResultSupersessionAuthorityView is issued only by " + "resolve_validation_result_supersession_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return released current-result provenance without successor disclosure.""" + return self[2] + + +@runtime_checkable +class ValidationResultSupersessionAuthorityReadPort(Protocol): + """Owner read contract for one released validation-result correction state.""" + + def read_validation_result_supersession_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + evidence_version: int, + correction_sequence: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> ValidationResultSupersessionAuthorityRecord | None: + """Return matching released supersession evidence or ``None``.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + ValidationResultSupersessionAuthorityReadPort, + "read_validation_result_supersession_authority", +) + + +def resolve_validation_result_supersession_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + evidence_version: int, + correction_sequence: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: ValidationResultSupersessionAuthorityReadPort, +) -> ValidationResultSupersessionAuthorityView: + """Authorize then resolve the result's half-open append-only authority interval.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static( + type(read_port), "read_validation_result_supersession_authority", None + ) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError( + "read_port must expose a statically callable " + "read_validation_result_supersession_authority." + ) + + tenant_id = _restore_operational_uuid( + "tenant_record_id", _store_operational_uuid("tenant_record_id", tenant_record_id) + ) + study_id = _restore_operational_uuid( + "validity_study_id", _store_operational_uuid("validity_study_id", validity_study_id) + ) + result_ref = _require_reference( + "result_reference", result_reference, "validation_analysis_result" + ) + result_evidence_digest = _require_digest("result_digest", result_digest) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + correction = _require_positive_integer("correction_sequence", correction_sequence) + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=tenant_id, + validity_study_id=study_id, + result_reference=result_ref, + result_digest=result_evidence_digest, + evidence_version=version, + correction_sequence=correction, + owner_contract_reference=owner_ref, + owner_contract_version=owner_version, + owner_contract_digest=owner_digest, + ) + if persisted is None: + raise ValidationResultSupersessionAuthorityNotFound(str(study_id)) + if type(persisted) is not ValidationResultSupersessionAuthorityRecord: + raise ValidationResultSupersessionAuthorityIntegrityError( + "owner port returned non-canonical validation-result supersession evidence" + ) + + persisted_fields = dict(persisted.fields) + persisted_successor = ( + None if persisted.successor_fields is None else dict(persisted.successor_fields) + ) + record = ValidationResultSupersessionAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + result_reference=persisted_fields["result_reference"], + result_digest=persisted_fields["result_digest"], + evidence_version=persisted_fields["evidence_version"], + correction_sequence=persisted_fields["correction_sequence"], + owner_contract_reference=persisted_fields["owner_contract_reference"], + owner_contract_version=persisted_fields["owner_contract_version"], + owner_contract_digest=persisted_fields["owner_contract_digest"], + owner_contract_released_at=persisted_fields["owner_contract_released_at"], + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + successor_result_reference=( + None + if persisted_successor is None + else persisted_successor["successor_result_reference"] + ), + successor_correction_sequence=( + None + if persisted_successor is None + else persisted_successor["successor_correction_sequence"] + ), + successor_result_digest=( + None + if persisted_successor is None + else persisted_successor["successor_result_digest"] + ), + successor_released_at=( + None + if persisted_successor is None + else persisted_successor["successor_released_at"] + ), + ) + record_values = dict(record.fields) + if ( + _store_operational_uuid("record tenant_record_id", record.tenant_record_id) + != _store_operational_uuid("requested tenant_record_id", tenant_id) + or _store_operational_uuid("record validity_study_id", record.validity_study_id) + != _store_operational_uuid("requested validity_study_id", study_id) + or record_values["result_reference"] != result_ref + or record_values["result_digest"] != result_evidence_digest + or record_values["evidence_version"] != version + or record_values["correction_sequence"] != correction + or record_values["owner_contract_reference"] != owner_ref + or record_values["owner_contract_version"] != owner_version + or record_values["owner_contract_digest"] != owner_digest + ): + raise ValidationResultSupersessionAuthorityIntegrityError( + "owner evidence does not match requested validation-result correction coordinates" + ) + if use_instant < record.released_at: + raise ValidationResultSupersessionAuthorityIntegrityError( + "validation-result authority cannot be used before its release instant" + ) + if record.superseded_at is not None and use_instant >= record.superseded_at: + raise ValidationResultSupersessionAuthorityIntegrityError( + "validation-result authority ended at its owner-resolved supersession instant" + ) + + values = { + **record_values, + "released_at": record.released_at, + } + fields = tuple((field_name, values[field_name]) for field_name in sorted(_VIEW_FIELDS)) + return tuple.__new__( + ValidationResultSupersessionAuthorityView, + ( + _store_operational_uuid("tenant_record_id", tenant_id), + _store_operational_uuid("validity_study_id", study_id), + fields, + ), + ) + + +__all__ = [ + "ValidationResultSupersessionAuthorityIntegrityError", + "ValidationResultSupersessionAuthorityNotFound", + "ValidationResultSupersessionAuthorityReadPort", + "ValidationResultSupersessionAuthorityRecord", + "ValidationResultSupersessionAuthorityView", + "resolve_validation_result_supersession_authority", +] From c950af56baef9a16b2065d5ab8521af2dd5b2000 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 22:04:22 +0900 Subject: [PATCH 159/603] feat(workforce-validation): export result supersession authority --- .../orgmetra_workforce_validation_api/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index 36056d271..d3b28338d 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -74,6 +74,14 @@ ValidationResultNonVerifiabilityView, resolve_validation_result_nonverifiability, ) +from orgmetra_workforce_validation_api.result_supersession_authority import ( + ValidationResultSupersessionAuthorityIntegrityError, + ValidationResultSupersessionAuthorityNotFound, + ValidationResultSupersessionAuthorityReadPort, + ValidationResultSupersessionAuthorityRecord, + ValidationResultSupersessionAuthorityView, + resolve_validation_result_supersession_authority, +) from orgmetra_workforce_validation_api.scientific_authority import ( CalibrationAuxiliaryAuthorityIntegrityError, CalibrationAuxiliaryAuthorityNotFound, @@ -160,6 +168,11 @@ "ValidationResultNonVerifiabilityReadPort", "ValidationResultNonVerifiabilityRecord", "ValidationResultNonVerifiabilityView", + "ValidationResultSupersessionAuthorityIntegrityError", + "ValidationResultSupersessionAuthorityNotFound", + "ValidationResultSupersessionAuthorityReadPort", + "ValidationResultSupersessionAuthorityRecord", + "ValidationResultSupersessionAuthorityView", "ValidityStudyIntegrityError", "ValidityStudyNotFound", "ValidityStudyReadPort", @@ -186,6 +199,7 @@ "resolve_trimming_bounding_authority", "resolve_validation_result_authority", "resolve_validation_result_nonverifiability", + "resolve_validation_result_supersession_authority", "resolve_weight_eligibility_authority", "resolve_weight_variance_authority", ] From 8e051aabdef920f8378c66e7bc0b12777d2b1321 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 22:06:22 +0900 Subject: [PATCH 160/603] test(workforce-validation): harden result supersession authority --- ...est_result_supersession_authority_edges.py | 321 ++++++++++++++++++ 1 file changed, 321 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_result_supersession_authority_edges.py diff --git a/services/workforce-validation-api/tests/test_result_supersession_authority_edges.py b/services/workforce-validation-api/tests/test_result_supersession_authority_edges.py new file mode 100644 index 000000000..ad154836e --- /dev/null +++ b/services/workforce-validation-api/tests/test_result_supersession_authority_edges.py @@ -0,0 +1,321 @@ +"""Hostile edges for append-only validation-result correction authority.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.result_supersession_authority import ( + ValidationResultSupersessionAuthorityIntegrityError, + ValidationResultSupersessionAuthorityNotFound, + ValidationResultSupersessionAuthorityReadPort, + ValidationResultSupersessionAuthorityRecord, + ValidationResultSupersessionAuthorityView, + resolve_validation_result_supersession_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000d2") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +OTHER_RESULT_REFERENCE = "validation_analysis_result:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" +SUCCESSOR_REFERENCE = "validation_analysis_result:33333333-3333-4333-8333-333333333333" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +OTHER_OWNER_CONTRACT_REFERENCE = "released_owner_contract:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" +RESULT_DIGEST = "1" * 64 +SUCCESSOR_DIGEST = "3" * 64 +OWNER_CONTRACT_DIGEST = "2" * 64 +RELEASED_AT = datetime(2026, 9, 17, 10, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 1, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 12, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "result_reference", + "result_digest", + "evidence_version", + "correction_sequence", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_result_reference", + "successor_correction_sequence", + "successor_result_digest", + "successor_released_at", + } +) + + +class _ReadPort: + """Return configured authority and retain lookup coordinates.""" + + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[dict[str, object]] = [] + + def read_validation_result_supersession_authority(self, **coordinates: object) -> object: + """Capture the owner lookup and return configured evidence.""" + self.calls.append(dict(coordinates)) + return self.result + + +class _NoReadMethod: + """Deliberately fail the owner-port protocol.""" + + +class _ProtocolOnly(ValidationResultSupersessionAuthorityReadPort): + """Inherit only the Protocol placeholder, not a concrete owner capability.""" + + +class _DescriptorReadPort: + """Expose a descriptor that static capability validation must reject.""" + + @property + def read_validation_result_supersession_authority(self) -> object: + raise AssertionError("descriptor must not execute") + + +def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=tenant_record_id, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="validation-result-supersession-authority-read-v1", + resource_kind="validation_result_supersession_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record(**overrides: object) -> ValidationResultSupersessionAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "result_reference": RESULT_REFERENCE, + "result_digest": RESULT_DIGEST, + "evidence_version": 1, + "correction_sequence": 2, + "owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "owner_contract_version": 3, + "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, + "released_at": RELEASED_AT, + "superseded_at": None, + "successor_result_reference": None, + "successor_correction_sequence": None, + "successor_result_digest": None, + "successor_released_at": None, + } + values.update(overrides) + return ValidationResultSupersessionAuthorityRecord(**values) + + +def _resolve(*, read_port: object, **overrides: object) -> ValidationResultSupersessionAuthorityView: + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "result_reference": RESULT_REFERENCE, + "result_digest": RESULT_DIGEST, + "evidence_version": 1, + "correction_sequence": 2, + "owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "owner_contract_version": 3, + "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_validation_result_supersession_authority(**values) + + +def test_current_result_resolution_uses_owner_release_chronology_without_successor() -> None: + port = _ReadPort(_record()) + view = _resolve(read_port=port) + + assert isinstance(port, ValidationResultSupersessionAuthorityReadPort) + assert len(port.calls) == 1 + assert port.calls[0]["result_reference"] == RESULT_REFERENCE + assert "owner_contract_released_at" not in port.calls[0] + assert "released_at" not in port.calls[0] + assert "superseded_at" not in port.calls[0] + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + fields = dict(view.fields) + assert fields["owner_contract_released_at"] == OWNER_CONTRACT_RELEASED_AT + assert fields["released_at"] == RELEASED_AT + assert "superseded_at" not in fields + assert "successor_result_reference" not in fields + + +def test_authorization_denial_happens_before_owner_resolution() -> None: + port = _ReadPort(_record()) + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, policy=_policy(purpose_code="audit_review")) + assert port.calls == [] + + +def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: + with pytest.raises(ValidationResultSupersessionAuthorityNotFound): + _resolve(read_port=_ReadPort(None)) + with pytest.raises(ValidationResultSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object())) + + +@pytest.mark.parametrize( + "record_overrides", + [ + {"tenant_record_id": OTHER_TENANT}, + {"validity_study_id": OTHER_STUDY}, + {"result_reference": OTHER_RESULT_REFERENCE}, + {"result_digest": "a" * 64}, + {"correction_sequence": 3}, + {"owner_contract_reference": OTHER_OWNER_CONTRACT_REFERENCE}, + {"owner_contract_version": 4}, + {"owner_contract_digest": "b" * 64}, + ], +) +def test_owner_evidence_must_match_every_requested_coordinate( + record_overrides: dict[str, object] +) -> None: + with pytest.raises(ValidationResultSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(**record_overrides))) + + +def test_release_chronology_and_historical_use_fail_closed_or_remain_reproducible() -> None: + with pytest.raises(ValidationResultSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(released_at=USED_AT + timedelta(seconds=1)))) + + record = _record( + superseded_at=USED_AT + timedelta(seconds=1), + successor_result_reference=SUCCESSOR_REFERENCE, + successor_correction_sequence=3, + successor_result_digest=SUCCESSOR_DIGEST, + successor_released_at=USED_AT, + ) + view = _resolve(read_port=_ReadPort(record)) + assert dict(view.fields)["result_digest"] == RESULT_DIGEST + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("result_reference", "wrong:result", ValueError), + ("result_digest", "ABC", ValueError), + ("evidence_version", False, ValueError), + ("evidence_version", 2, ValueError), + ("correction_sequence", 0, ValueError), + ("owner_contract_reference", "wrong:contract", ValueError), + ("owner_contract_version", 0, ValueError), + ("owner_contract_digest", "2" * 63, ValueError), + ("used_at", datetime(2026, 9, 17), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_or_dependency_fails_before_owner_resolution( + key: str, value: object, error: type[Exception] +) -> None: + port: object = _ReadPort(_record()) + overrides = {key: value} + if key == "read_port": + port = value + overrides = {} + with pytest.raises(error): + _resolve(read_port=port, **overrides) + if isinstance(port, _ReadPort): + assert port.calls == [] + + +def test_record_rejects_non_v1_evidence_and_public_view_construction() -> None: + with pytest.raises(ValueError, match="evidence_version must remain 1"): + _record(evidence_version=2) + with pytest.raises(TypeError, match="issued only by"): + ValidationResultSupersessionAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) + + +def test_record_rejects_naive_owner_resolved_timestamps_and_malformed_successor() -> None: + with pytest.raises(ValueError): + _record(owner_contract_released_at=datetime(2026, 9, 1)) + with pytest.raises(ValueError): + _record(released_at=datetime(2026, 9, 17, 10)) + with pytest.raises(ValueError): + _record( + superseded_at=datetime(2026, 9, 17, 13), + successor_result_reference=SUCCESSOR_REFERENCE, + successor_correction_sequence=3, + successor_result_digest=SUCCESSOR_DIGEST, + successor_released_at=USED_AT, + ) + with pytest.raises(ValueError): + _record( + superseded_at=USED_AT + timedelta(hours=1), + successor_result_reference="analysis_weight_receipt:33333333-3333-4333-8333-333333333333", + successor_correction_sequence=3, + successor_result_digest=SUCCESSOR_DIGEST, + successor_released_at=USED_AT, + ) + with pytest.raises(ValueError): + _record( + superseded_at=USED_AT + timedelta(hours=1), + successor_result_reference=SUCCESSOR_REFERENCE, + successor_correction_sequence=True, + successor_result_digest=SUCCESSOR_DIGEST, + successor_released_at=USED_AT, + ) + with pytest.raises(ValueError): + _record( + superseded_at=USED_AT + timedelta(hours=1), + successor_result_reference=SUCCESSOR_REFERENCE, + successor_correction_sequence=3, + successor_result_digest="not-a-digest", + successor_released_at=USED_AT, + ) + + +def test_record_and_view_are_structurally_immutable_and_uuid_views_are_detached() -> None: + tenant = UUID(str(TENANT)) + record = _record(tenant_record_id=tenant) + object.__setattr__(tenant, "int", OTHER_TENANT.int) + assert record.tenant_record_id == TENANT + assert record.validity_study_id == STUDY + assert record.released_at == RELEASED_AT + assert record.superseded_at is None + assert record.successor_fields is None + assert dict(record.fields)["correction_sequence"] == 2 + with pytest.raises(AttributeError): + object.__setattr__(record, "correction_sequence", 3) + + view = _resolve(read_port=_ReadPort(record)) + returned_tenant = view.tenant_record_id + object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) + assert view.tenant_record_id == TENANT + with pytest.raises(AttributeError): + object.__setattr__(view, "fields", ()) From e9a13f7a46ea91d47785bfe17a4f9dcc1f6e62f6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 22:07:09 +0900 Subject: [PATCH 161/603] docs(workforce-validation): add result supersession handoff --- services/workforce-validation-api/README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 30f5d3488..4aed3fea6 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -60,7 +60,7 @@ The ordered adjustment chain is immutable and contiguous: each transform must co ## Final analysis-weight supersession authority -`resolve_final_weight_supersession_authority(...)` closes #407 RED #10 at the application-owner boundary. A `correction_sequence` plus predecessor digest is not enough to prove that a previously released final-weight receipt stopped being authoritative without in-place mutation. The owner record therefore preserves the predecessor release instant, exclusive supersession instant, and complete released successor coordinates. The successor must have a new receipt reference and digest, advance the correction sequence exactly by one, be released after its predecessor, and already exist no later than the cutover. The released owner contract must predate the predecessor receipt. +`resolve_final_weight_supersession_authority(...)` closes the point-weight side of #407 RED #10 at the application-owner boundary. A `correction_sequence` plus predecessor digest is not enough to prove that a previously released final-weight receipt stopped being authoritative without in-place mutation. The owner record therefore preserves the predecessor release instant, exclusive supersession instant, and complete released successor coordinates. The successor must have a new receipt reference and digest, advance the correction sequence exactly by one, be released after its predecessor, and already exist no later than the cutover. The released owner contract must predate the predecessor receipt. Scientific use is evaluated against the owner-resolved half-open interval `[released_at, superseded_at)`. Historical use inside that interval remains reproducible, while use at or after the cutover fails closed. Successor coordinates are deliberately omitted from the returned view so downstream callers receive only the currently requested receipt authority, not a reusable correction graph. Row-level weights and case identities remain outside this boundary. @@ -72,6 +72,12 @@ Scientific use is evaluated against the owner-resolved half-open interval `[rele `resolve_validation_result_authority(...)` binds one immutable validation result to the exact `WeightVarianceCompatibilityReceipt`, final analysis-weight receipt, separate variance-design receipt, non-authorizing `verification_pending | not_verifiable` state, and released owner contract. Numerical convergence is not promoted to `verified` at this boundary. +## Validation-result supersession authority + +`resolve_validation_result_supersession_authority(...)` closes the released-result side of #407 RED #10. A corrected final weight or recomputed estimate must not leave an earlier released `ValidationAnalysisResult` looking current. The owner record therefore resolves the result release instant, optional exclusive supersession instant, and complete released successor result reference/correction-sequence/digest/release instant. The successor must use a new `validation_analysis_result` reference and digest, advance correction sequence exactly by one, be released after its predecessor, and exist no later than cutover. The released owner contract must already exist when the predecessor result is released. + +Result authority is the half-open owner-resolved interval `[released_at, superseded_at)`: historical use remains reproducible before cutover and use at or after cutover fails closed. Caller timestamps and mutable result rows do not establish correction authority. Successor coordinates remain internal and are not projected to downstream callers. + ## Released non-verifiability outcome `resolve_validation_result_nonverifiability(...)` is the application repair for #407 RED #12. It represents required analysis-weight, weight/variance-compatibility, or variance-design evidence that is `missing | non_reproducible` without turning lookup failure into scientific GREEN. Missing evidence carries no fabricated identity; non-reproducible evidence retains the exact failed reference/digest. Every outcome binds a separate immutable verification-attempt receipt, released owner contract, and evaluation/release chronology. Effect estimates, row-level weights, replicate vectors, protected attributes, and foreign application data are excluded. @@ -82,7 +88,7 @@ Scientific use is evaluated against the owner-resolved half-open interval `[rele The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, and validation-result non-verifiability. Base-weight source-universe, sampling-design, and owner-contract release instants must come from those durable owner records rather than caller-supplied request coordinates. Final-weight correction cutovers and successor coordinates likewise come only from released owner records, never caller timestamps or mutable result rows. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Base-weight source-universe, sampling-design, and owner-contract release instants must come from those durable owner records rather than caller-supplied request coordinates. Final-weight and validation-result correction cutovers plus successor coordinates likewise come only from released owner records, never caller timestamps or mutable current rows. ## Test contract @@ -97,6 +103,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage, final-weight predecessor/successor correction intervals, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage, final-weight predecessor/successor correction intervals, validation-result predecessor/successor correction intervals, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From 9d6cb0bf07de47d484ea99ef953677919b4fa944 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 23:09:04 +0900 Subject: [PATCH 162/603] test(workforce-validation): RED result authority chronology --- ..._validation_result_authority_chronology.py | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_authority_chronology.py diff --git a/services/workforce-validation-api/tests/test_validation_result_authority_chronology.py b/services/workforce-validation-api/tests/test_validation_result_authority_chronology.py new file mode 100644 index 000000000..ef4dcc6fb --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_authority_chronology.py @@ -0,0 +1,139 @@ +"""Reject retroactive owner contracts and stale validation-result use.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from inspect import signature +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.result_authority import ( + ValidationResultAuthorityIntegrityError, + ValidationResultAuthorityRecord, + resolve_validation_result_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +COMPATIBILITY_REFERENCE = ( + "weight_variance_compatibility_receipt:22222222-2222-4222-8222-222222222222" +) +OWNER_REFERENCE = "released_owner_contract:33333333-3333-4333-8333-333333333333" +RESULT_DIGEST = "1" * 64 +COMPATIBILITY_DIGEST = "2" * 64 +ANALYSIS_WEIGHT_DIGEST = "3" * 64 +VARIANCE_DIGEST = "4" * 64 +OWNER_DIGEST = "5" * 64 +OWNER_RELEASED_AT = datetime(2026, 9, 17, 4, 0, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 5, 0, tzinfo=timezone.utc) +SUPERSEDED_AT = datetime(2026, 9, 17, 7, 0, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "result_reference", + "result_digest", + "compatibility_receipt_reference", + "compatibility_receipt_digest", + "analysis_weight_receipt_digest", + "variance_design_receipt_digest", + "verification_status", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + } +) + + +class _ReadPort: + def __init__(self, record: ValidationResultAuthorityRecord) -> None: + self.record = record + + def read_validation_result_authority(self, **_: object) -> ValidationResultAuthorityRecord: + return self.record + + +def _record(**overrides: object) -> ValidationResultAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "result_reference": RESULT_REFERENCE, + "result_digest": RESULT_DIGEST, + "compatibility_receipt_reference": COMPATIBILITY_REFERENCE, + "compatibility_receipt_digest": COMPATIBILITY_DIGEST, + "analysis_weight_receipt_digest": ANALYSIS_WEIGHT_DIGEST, + "variance_design_receipt_digest": VARIANCE_DIGEST, + "verification_status": "verification_pending", + "owner_contract_reference": OWNER_REFERENCE, + "owner_contract_version": 7, + "owner_contract_digest": OWNER_DIGEST, + "owner_contract_released_at": OWNER_RELEASED_AT, + "released_at": RELEASED_AT, + "superseded_at": SUPERSEDED_AT, + } + values.update(overrides) + return ValidationResultAuthorityRecord(**values) + + +def _resolve(*, used_at: datetime) -> object: + return resolve_validation_result_authority( + principal=ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ), + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + compatibility_receipt_reference=COMPATIBILITY_REFERENCE, + compatibility_receipt_digest=COMPATIBILITY_DIGEST, + analysis_weight_receipt_digest=ANALYSIS_WEIGHT_DIGEST, + variance_design_receipt_digest=VARIANCE_DIGEST, + verification_status="verification_pending", + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=7, + owner_contract_digest=OWNER_DIGEST, + used_at=used_at, + purpose_code="selection_validity_analysis", + policy=PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="validation-result-authority-read-v2", + resource_kind="validation_result_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ), + read_port=_ReadPort(_record()), + ) + + +def test_chronology_is_owner_evidence_not_caller_input() -> None: + parameters = signature(resolve_validation_result_authority).parameters + assert "owner_contract_released_at" not in parameters + assert "superseded_at" not in parameters + + +def test_owner_contract_cannot_retroactively_authorize_released_result() -> None: + with pytest.raises(ValueError, match="owner contract"): + _record( + owner_contract_released_at=datetime( + 2026, 9, 17, 5, 1, tzinfo=timezone.utc + ) + ) + + +def test_result_binding_uses_same_half_open_authority_interval_as_supersession() -> None: + historical = _resolve(used_at=datetime(2026, 9, 17, 6, 59, tzinfo=timezone.utc)) + fields = dict(historical.fields) + assert fields["owner_contract_released_at"] == OWNER_RELEASED_AT + assert fields["superseded_at"] == SUPERSEDED_AT + + with pytest.raises(ValidationResultAuthorityIntegrityError, match="supersession"): + _resolve(used_at=SUPERSEDED_AT) From 5a64e97a8196ae67d077f6f0432fd030cf372a13 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 23:15:20 +0900 Subject: [PATCH 163/603] fix(workforce-validation): enforce result authority chronology --- .../result_authority.py | 48 +++++++++++++++++-- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py index 54d425d3e..ee88f2728 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py @@ -3,8 +3,8 @@ This application boundary binds one immutable validation result to the exact point-weight/variance compatibility evidence it claims to use. It keeps the scientific leaf non-authorizing: only ``verification_pending`` or -``not_verifiable`` may cross this owner boundary, and durable PostgreSQL/release -resolution remains a child persistence responsibility after this service lands. +``not_verifiable`` may cross this owner boundary. Release and supersession +instants are owner evidence, never caller assertions. """ from __future__ import annotations @@ -50,7 +50,9 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "released_at", + "superseded_at", } ) @@ -73,7 +75,7 @@ def _require_verification_status(value: object) -> str: class ValidationResultAuthorityRecord(tuple): - """Immutable owner projection binding result, weight, and variance evidence.""" + """Immutable owner projection binding result, weight, variance, and chronology.""" __slots__ = () @@ -92,9 +94,11 @@ def __new__( owner_contract_reference: str, owner_contract_version: int, owner_contract_digest: str, + owner_contract_released_at: datetime, released_at: datetime, + superseded_at: datetime | None = None, ) -> ValidationResultAuthorityRecord: - """Validate and detach the minimum released result-provenance coordinates.""" + """Validate the released binding and its owner-resolved authority interval.""" tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) study_identity = _store_operational_uuid("validity_study_id", validity_study_id) result_ref = _require_reference( @@ -134,7 +138,21 @@ def __new__( "owner_contract_version", owner_contract_version ) owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + contract_release = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) release_instant = _require_aware_datetime("released_at", released_at) + if contract_release > release_instant: + raise ValueError( + "owner contract must be released no later than validation result." + ) + cutover = ( + None + if superseded_at is None + else _require_aware_datetime("superseded_at", superseded_at) + ) + if cutover is not None and cutover <= release_instant: + raise ValueError("superseded_at must be later than validation-result release.") return tuple.__new__( cls, ( @@ -150,7 +168,9 @@ def __new__( owner_ref, owner_version, owner_digest, + contract_release, release_instant, + cutover, ), ) @@ -214,10 +234,20 @@ def owner_contract_digest(self) -> str: """Return the immutable released owner-contract digest.""" return self[11] + @property + def owner_contract_released_at(self) -> datetime: + """Return when the owner contract became released authority.""" + return self[12] + @property def released_at(self) -> datetime: """Return when this result-authority evidence became released.""" - return self[12] + return self[13] + + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive end of this result binding's authority interval.""" + return self[14] class ValidationResultAuthorityView(tuple): @@ -416,7 +446,9 @@ def resolve_validation_result_authority( owner_contract_reference=persisted.owner_contract_reference, owner_contract_version=persisted.owner_contract_version, owner_contract_digest=persisted.owner_contract_digest, + owner_contract_released_at=persisted.owner_contract_released_at, released_at=persisted.released_at, + superseded_at=persisted.superseded_at, ) requested_identity = ( tenant_identity, @@ -454,6 +486,10 @@ def resolve_validation_result_authority( raise ValidationResultAuthorityIntegrityError( "validation-result authority cannot be used before its release instant" ) + if record.superseded_at is not None and use_instant >= record.superseded_at: + raise ValidationResultAuthorityIntegrityError( + "validation-result authority ended at its owner-resolved supersession instant" + ) values = { "result_reference": record.result_reference, @@ -466,7 +502,9 @@ def resolve_validation_result_authority( "owner_contract_reference": record.owner_contract_reference, "owner_contract_version": record.owner_contract_version, "owner_contract_digest": record.owner_contract_digest, + "owner_contract_released_at": record.owner_contract_released_at, "released_at": record.released_at, + "superseded_at": record.superseded_at, } fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) return tuple.__new__( From 89e42077436c747d30df383b4d2fac99fd28e401 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 23:15:46 +0900 Subject: [PATCH 164/603] test(workforce-validation): align result chronology fixtures --- .../tests/test_validation_result_authority.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_validation_result_authority.py b/services/workforce-validation-api/tests/test_validation_result_authority.py index 9b3c8bca1..cb2ce6c62 100644 --- a/services/workforce-validation-api/tests/test_validation_result_authority.py +++ b/services/workforce-validation-api/tests/test_validation_result_authority.py @@ -31,6 +31,7 @@ ANALYSIS_WEIGHT_DIGEST = "3" * 64 VARIANCE_DIGEST = "4" * 64 OWNER_DIGEST = "5" * 64 +OWNER_RELEASED_AT = datetime(2026, 9, 17, 4, 0, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 17, 5, 0, tzinfo=timezone.utc) USED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) READ_FIELDS = frozenset( @@ -45,7 +46,9 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "released_at", + "superseded_at", } ) @@ -107,7 +110,7 @@ def _principal() -> ValidationPrincipal: def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: return PurposeBoundAccessPolicy( tenant_record_id=TENANT, - policy_version_code="validation-result-authority-read-v1", + policy_version_code="validation-result-authority-read-v2", resource_kind="validation_result_authority", purpose_code=purpose_code, operation_code="read", @@ -130,6 +133,7 @@ def _record(**overrides: object) -> ValidationResultAuthorityRecord: "owner_contract_reference": OWNER_REFERENCE, "owner_contract_version": 7, "owner_contract_digest": OWNER_DIGEST, + "owner_contract_released_at": OWNER_RELEASED_AT, "released_at": RELEASED_AT, } values.update(overrides) @@ -191,7 +195,9 @@ def test_resolution_binds_result_to_exact_compatibility_and_owner_evidence() -> assert fields["variance_design_receipt_digest"] == VARIANCE_DIGEST assert fields["verification_status"] == "verification_pending" assert fields["owner_contract_digest"] == OWNER_DIGEST + assert fields["owner_contract_released_at"] == OWNER_RELEASED_AT assert fields["released_at"] == RELEASED_AT + assert fields["superseded_at"] is None def test_not_verifiable_result_remains_released_non_authorizing_evidence() -> None: From c767c5c1fafbd015de01b26ad50ec4e3254749cf Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 17 Sep 2026 23:16:42 +0900 Subject: [PATCH 165/603] docs(workforce-validation): document result binding currentness --- services/workforce-validation-api/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 4aed3fea6..862718727 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -72,11 +72,13 @@ Scientific use is evaluated against the owner-resolved half-open interval `[rele `resolve_validation_result_authority(...)` binds one immutable validation result to the exact `WeightVarianceCompatibilityReceipt`, final analysis-weight receipt, separate variance-design receipt, non-authorizing `verification_pending | not_verifiable` state, and released owner contract. Numerical convergence is not promoted to `verified` at this boundary. +The binding now also resolves `owner_contract_released_at` and the optional exclusive `superseded_at` from canonical owner evidence. Neither timestamp is a caller request coordinate. A later owner contract cannot retroactively authorize an earlier released result, and the ordinary result-binding resolver itself honors the same half-open `[released_at, superseded_at)` authority interval as the correction graph. Historical reads before cutover remain reproducible; use at or after cutover fails closed. This prevents a consumer from bypassing currentness simply by calling the result-binding resolver without separately traversing the successor graph. + ## Validation-result supersession authority `resolve_validation_result_supersession_authority(...)` closes the released-result side of #407 RED #10. A corrected final weight or recomputed estimate must not leave an earlier released `ValidationAnalysisResult` looking current. The owner record therefore resolves the result release instant, optional exclusive supersession instant, and complete released successor result reference/correction-sequence/digest/release instant. The successor must use a new `validation_analysis_result` reference and digest, advance correction sequence exactly by one, be released after its predecessor, and exist no later than cutover. The released owner contract must already exist when the predecessor result is released. -Result authority is the half-open owner-resolved interval `[released_at, superseded_at)`: historical use remains reproducible before cutover and use at or after cutover fails closed. Caller timestamps and mutable result rows do not establish correction authority. Successor coordinates remain internal and are not projected to downstream callers. +Result authority is the half-open owner-resolved interval `[released_at, superseded_at)`: historical use remains reproducible before cutover and use at or after cutover fails closed. Caller timestamps and mutable result rows do not establish correction authority. Successor coordinates remain internal and are not projected to downstream callers. This family proves the complete append-only successor edge; the ordinary result-binding authority consumes only the owner-resolved release/cutover needed to reject stale use. ## Released non-verifiability outcome @@ -88,7 +90,7 @@ Result authority is the half-open owner-resolved interval `[released_at, superse The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Base-weight source-universe, sampling-design, and owner-contract release instants must come from those durable owner records rather than caller-supplied request coordinates. Final-weight and validation-result correction cutovers plus successor coordinates likewise come only from released owner records, never caller timestamps or mutable current rows. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Base-weight source-universe, sampling-design, and owner-contract release instants must come from those durable owner records rather than caller-supplied request coordinates. Final-weight and validation-result correction cutovers plus successor coordinates likewise come only from released owner records, never caller timestamps or mutable current rows. The durable validation-result binding adapter must populate owner-contract release and result supersession cutover from the same canonical chronology so the low-level binding path cannot serve stale evidence. ## Test contract @@ -103,6 +105,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage, final-weight predecessor/successor correction intervals, validation-result predecessor/successor correction intervals, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage, final-weight predecessor/successor correction intervals, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From a0556627f03e615fa4a7c0dd26aae1e1c5e4a048 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 00:00:53 +0900 Subject: [PATCH 166/603] test(workforce-validation): red weight variance authority chronology --- ...st_weight_variance_authority_chronology.py | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_variance_authority_chronology.py diff --git a/services/workforce-validation-api/tests/test_weight_variance_authority_chronology.py b/services/workforce-validation-api/tests/test_weight_variance_authority_chronology.py new file mode 100644 index 000000000..628fe8458 --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_variance_authority_chronology.py @@ -0,0 +1,166 @@ +"""Reject retroactive owner contracts and stale weight/variance compatibility use.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from inspect import signature +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.variance_authority import ( + WeightVarianceAuthorityIntegrityError, + WeightVarianceAuthorityRecord, + resolve_weight_variance_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +AUTHORITY_REFERENCE = "variance_compatibility_authority:11111111-1111-4111-8111-111111111111" +SAMPLING_REFERENCE = "sampling_design_receipt:22222222-2222-4222-8222-222222222222" +VARIANCE_REFERENCE = "variance_design_receipt:33333333-3333-4333-8333-333333333333" +METHOD_REFERENCE = "variance_method:44444444-4444-4444-8444-444444444444" +OWNER_REFERENCE = "released_owner_contract:55555555-5555-4555-8555-555555555555" +SAMPLING_DIGEST = "1" * 64 +ANALYSIS_WEIGHT_DIGEST = "2" * 64 +CASE_SET_DIGEST = "3" * 64 +ELIGIBILITY_DIGEST = "4" * 64 +FINAL_WEIGHT_DIGEST = "6" * 64 +VARIANCE_DIGEST = "7" * 64 +OWNER_DIGEST = "8" * 64 +OWNER_RELEASED_AT = datetime(2026, 9, 17, 0, 30, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 1, 0, tzinfo=timezone.utc) +SUPERSEDED_AT = datetime(2026, 9, 17, 3, 0, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "authority_reference", + "sampling_receipt_reference", + "sampling_receipt_version", + "sampling_receipt_digest", + "analysis_weight_receipt_digest", + "analytic_case_occurrence_set_digest", + "weight_eligibility_receipt_digest", + "weight_correction_sequence", + "final_weight_artifact_digest", + "variance_design_receipt_reference", + "variance_design_receipt_version", + "variance_design_receipt_digest", + "variance_method_reference", + "variance_method_version", + "variance_evidence_mode", + "variance_semantics", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + } +) + + +class _ReadPort: + def __init__(self, record: WeightVarianceAuthorityRecord) -> None: + self.record = record + + def read_weight_variance_authority(self, **_: object) -> WeightVarianceAuthorityRecord: + return self.record + + +def _record(**overrides: object) -> WeightVarianceAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "authority_reference": AUTHORITY_REFERENCE, + "sampling_receipt_reference": SAMPLING_REFERENCE, + "sampling_receipt_version": 3, + "sampling_receipt_digest": SAMPLING_DIGEST, + "analysis_weight_receipt_digest": ANALYSIS_WEIGHT_DIGEST, + "analytic_case_occurrence_set_digest": CASE_SET_DIGEST, + "weight_eligibility_receipt_digest": ELIGIBILITY_DIGEST, + "weight_correction_sequence": 9, + "final_weight_artifact_digest": FINAL_WEIGHT_DIGEST, + "variance_design_receipt_reference": VARIANCE_REFERENCE, + "variance_design_receipt_version": 5, + "variance_design_receipt_digest": VARIANCE_DIGEST, + "variance_method_reference": METHOD_REFERENCE, + "variance_method_version": 2, + "variance_evidence_mode": "replicate_weights", + "variance_semantics": "exact", + "owner_contract_reference": OWNER_REFERENCE, + "owner_contract_version": 4, + "owner_contract_digest": OWNER_DIGEST, + "owner_contract_released_at": OWNER_RELEASED_AT, + "released_at": RELEASED_AT, + "superseded_at": SUPERSEDED_AT, + } + values.update(overrides) + return WeightVarianceAuthorityRecord(**values) + + +def _resolve(*, used_at: datetime) -> object: + return resolve_weight_variance_authority( + principal=ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ), + tenant_record_id=TENANT, + validity_study_id=STUDY, + sampling_receipt_reference=SAMPLING_REFERENCE, + sampling_receipt_version=3, + sampling_receipt_digest=SAMPLING_DIGEST, + analysis_weight_receipt_digest=ANALYSIS_WEIGHT_DIGEST, + analytic_case_occurrence_set_digest=CASE_SET_DIGEST, + weight_eligibility_receipt_digest=ELIGIBILITY_DIGEST, + weight_correction_sequence=9, + final_weight_artifact_digest=FINAL_WEIGHT_DIGEST, + variance_design_receipt_reference=VARIANCE_REFERENCE, + variance_design_receipt_version=5, + variance_design_receipt_digest=VARIANCE_DIGEST, + variance_method_reference=METHOD_REFERENCE, + variance_method_version=2, + variance_evidence_mode="replicate_weights", + variance_semantics="exact", + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=4, + used_at=used_at, + purpose_code="selection_validity_analysis", + policy=PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="weight-variance-authority-read-v2", + resource_kind="weight_variance_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ), + read_port=_ReadPort(_record()), + ) + + +def test_chronology_is_owner_evidence_not_caller_input() -> None: + parameters = signature(resolve_weight_variance_authority).parameters + assert "owner_contract_released_at" not in parameters + assert "superseded_at" not in parameters + + +def test_owner_contract_cannot_retroactively_authorize_compatibility() -> None: + with pytest.raises(ValueError, match="owner contract"): + _record( + owner_contract_released_at=datetime( + 2026, 9, 17, 1, 1, tzinfo=timezone.utc + ) + ) + + +def test_compatibility_uses_owner_resolved_half_open_authority_interval() -> None: + historical = _resolve(used_at=datetime(2026, 9, 17, 2, 59, tzinfo=timezone.utc)) + fields = dict(historical.fields) + assert fields["owner_contract_released_at"] == OWNER_RELEASED_AT + assert fields["superseded_at"] == SUPERSEDED_AT + + with pytest.raises(WeightVarianceAuthorityIntegrityError, match="supersession"): + _resolve(used_at=SUPERSEDED_AT) From 1eb059afa1f94a211e5d9a87a144c7597bd77eba Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 00:02:17 +0900 Subject: [PATCH 167/603] fix(workforce-validation): enforce variance authority chronology --- .../variance_authority.py | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py index 4a1d02c8f..adf46f63e 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py @@ -65,7 +65,9 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "released_at", + "superseded_at", } ) @@ -146,7 +148,9 @@ def __new__( owner_contract_reference: str, owner_contract_version: int, owner_contract_digest: str, + owner_contract_released_at: datetime, released_at: datetime, + superseded_at: datetime | None = None, ) -> WeightVarianceAuthorityRecord: """Validate and detach the minimum immutable compatibility coordinates.""" tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) @@ -202,7 +206,19 @@ def __new__( ) owner_version = _require_positive_integer("owner_contract_version", owner_contract_version) owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + owner_release_instant = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) release_instant = _require_aware_datetime("released_at", released_at) + if owner_release_instant > release_instant: + raise ValueError( + "owner contract must be released no later than the compatibility authority" + ) + supersession_instant = None + if superseded_at is not None: + supersession_instant = _require_aware_datetime("superseded_at", superseded_at) + if supersession_instant <= release_instant: + raise ValueError("superseded_at must be later than released_at") return tuple.__new__( cls, ( @@ -228,6 +244,8 @@ def __new__( owner_version, owner_digest, release_instant, + owner_release_instant, + supersession_instant, ), ) @@ -341,6 +359,16 @@ def released_at(self) -> datetime: """Return the owner-resolved release instant for this authority evidence.""" return self[21] + @property + def owner_contract_released_at(self) -> datetime: + """Return the owner-resolved release instant for the governing owner contract.""" + return self[22] + + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive owner-resolved cutover instant, when one exists.""" + return self[23] + class WeightVarianceAuthorityView(tuple): """Field-minimized compatibility evidence issued only after authorization.""" @@ -558,7 +586,9 @@ def resolve_weight_variance_authority( owner_contract_reference=persisted.owner_contract_reference, owner_contract_version=persisted.owner_contract_version, owner_contract_digest=persisted.owner_contract_digest, + owner_contract_released_at=persisted.owner_contract_released_at, released_at=persisted.released_at, + superseded_at=persisted.superseded_at, ) if ( _store_operational_uuid("record tenant_record_id", record.tenant_record_id) @@ -590,6 +620,10 @@ def resolve_weight_variance_authority( raise WeightVarianceAuthorityIntegrityError( "weight/variance authority cannot be used before its owner-resolved release instant" ) + if record.superseded_at is not None and use_instant >= record.superseded_at: + raise WeightVarianceAuthorityIntegrityError( + "weight/variance authority cannot be used at or after owner-resolved supersession" + ) values = { "authority_reference": record.authority_reference, @@ -611,7 +645,9 @@ def resolve_weight_variance_authority( "owner_contract_reference": record.owner_contract_reference, "owner_contract_version": record.owner_contract_version, "owner_contract_digest": record.owner_contract_digest, + "owner_contract_released_at": record.owner_contract_released_at, "released_at": record.released_at, + "superseded_at": record.superseded_at, } fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) return tuple.__new__(WeightVarianceAuthorityView, (tenant_identity, study_identity, fields)) From f374463d9de61285c5c62d692a6526064afac51c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 00:02:45 +0900 Subject: [PATCH 168/603] test(workforce-validation): cover variance authority chronology --- .../tests/test_weight_variance_authority.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_weight_variance_authority.py b/services/workforce-validation-api/tests/test_weight_variance_authority.py index ff547ea2d..761aa7fee 100644 --- a/services/workforce-validation-api/tests/test_weight_variance_authority.py +++ b/services/workforce-validation-api/tests/test_weight_variance_authority.py @@ -34,6 +34,7 @@ FINAL_WEIGHT_DIGEST = "6" * 64 VARIANCE_DIGEST = "7" * 64 OWNER_DIGEST = "8" * 64 +OWNER_RELEASED_AT = datetime(2026, 9, 17, 0, 30, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 17, 1, 0, tzinfo=timezone.utc) USED_AT = datetime(2026, 9, 17, 2, 0, tzinfo=timezone.utc) READ_FIELDS = frozenset( @@ -57,7 +58,9 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "released_at", + "superseded_at", } ) @@ -118,7 +121,7 @@ def _principal() -> ValidationPrincipal: def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: return PurposeBoundAccessPolicy( tenant_record_id=TENANT, - policy_version_code="weight-variance-authority-read-v1", + policy_version_code="weight-variance-authority-read-v2", resource_kind="weight_variance_authority", purpose_code=purpose_code, operation_code="read", @@ -150,7 +153,9 @@ def _record(**overrides: object) -> WeightVarianceAuthorityRecord: "owner_contract_reference": OWNER_REFERENCE, "owner_contract_version": 4, "owner_contract_digest": OWNER_DIGEST, + "owner_contract_released_at": OWNER_RELEASED_AT, "released_at": RELEASED_AT, + "superseded_at": None, } values.update(overrides) return WeightVarianceAuthorityRecord(**values) @@ -215,7 +220,9 @@ def test_resolution_authorizes_then_returns_owner_corroborated_compatibility() - assert fields["weight_correction_sequence"] == CORRECTION_SEQUENCE assert fields["variance_design_receipt_digest"] == VARIANCE_DIGEST assert fields["owner_contract_digest"] == OWNER_DIGEST + assert fields["owner_contract_released_at"] == OWNER_RELEASED_AT assert fields["released_at"] == RELEASED_AT + assert fields["superseded_at"] is None def test_authorization_denial_happens_before_owner_resolution() -> None: From 828220db3ebbda17d4d264237070c1a6a160d31f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 00:03:17 +0900 Subject: [PATCH 169/603] test(workforce-validation): harden variance chronology edges --- .../tests/test_weight_variance_authority_edges.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_weight_variance_authority_edges.py b/services/workforce-validation-api/tests/test_weight_variance_authority_edges.py index b27f49a29..cd1700f01 100644 --- a/services/workforce-validation-api/tests/test_weight_variance_authority_edges.py +++ b/services/workforce-validation-api/tests/test_weight_variance_authority_edges.py @@ -33,6 +33,7 @@ FINAL_WEIGHT_DIGEST = "6" * 64 VARIANCE_DIGEST = "7" * 64 OWNER_DIGEST = "8" * 64 +OWNER_RELEASED_AT = datetime(2026, 9, 17, 0, 30, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 17, 1, 0, tzinfo=timezone.utc) USED_AT = datetime(2026, 9, 17, 2, 0, tzinfo=timezone.utc) READ_FIELDS = frozenset( @@ -56,7 +57,9 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "released_at", + "superseded_at", } ) @@ -96,7 +99,7 @@ def _principal() -> ValidationPrincipal: def _policy() -> PurposeBoundAccessPolicy: return PurposeBoundAccessPolicy( tenant_record_id=TENANT, - policy_version_code="weight-variance-authority-read-v1", + policy_version_code="weight-variance-authority-read-v2", resource_kind="weight_variance_authority", purpose_code="selection_validity_analysis", operation_code="read", @@ -128,7 +131,9 @@ def _record(**overrides: object) -> WeightVarianceAuthorityRecord: "owner_contract_reference": OWNER_REFERENCE, "owner_contract_version": 4, "owner_contract_digest": OWNER_DIGEST, + "owner_contract_released_at": OWNER_RELEASED_AT, "released_at": RELEASED_AT, + "superseded_at": None, } values.update(overrides) return WeightVarianceAuthorityRecord(**values) @@ -197,7 +202,10 @@ def _resolve(*, result: object | None = None, read_port: object | None = None, * ("owner_contract_reference", "wrong:owner"), ("owner_contract_version", 0), ("owner_contract_digest", "8" * 63), + ("owner_contract_released_at", datetime(2026, 9, 17, 0, 30)), ("released_at", datetime(2026, 9, 17, 1, 0)), + ("superseded_at", datetime(2026, 9, 17, 3, 0)), + ("superseded_at", RELEASED_AT), ], ) def test_record_rejects_malformed_authority_evidence(key: str, value: object) -> None: From bbafafb404705855fd4ac27b086e98aefa45c832 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 00:04:02 +0900 Subject: [PATCH 170/603] docs(workforce-validation): document variance authority currentness --- services/workforce-validation-api/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 862718727..f00f1fc42 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -68,6 +68,8 @@ Scientific use is evaluated against the owner-resolved half-open interval `[rele `resolve_weight_variance_authority(...)` corroborates released #405 sampling evidence, final analysis-weight receipt, analytic-case occurrence set, weight-eligibility receipt digest, correction sequence, final point-weight artifact, separate #406 variance-design evidence, variance method/evidence semantics, and released owner contract. A variance receipt cannot alias the point-weight receipt, and approximation evidence cannot be represented as exact. The separate eligibility, base-weight, final analysis-weight, and final-weight supersession authorities supply the durable population/duration, selection-probability provenance, complete ordered point-weight lineage, and correction authority interval behind those compatibility coordinates. +The compatibility binding itself now resolves the governing owner-contract release instant and an optional exclusive supersession cutover from canonical owner evidence. Neither is a caller request coordinate. The owner contract must already exist when the compatibility authority is released, and the ordinary resolver enforces the owner-resolved half-open interval `[released_at, superseded_at)`. Historical use before cutover remains reproducible; use at or after cutover fails closed. This prevents a corrected point-weight or variance-design lineage from leaving an older compatibility binding apparently current merely because a consumer bypassed a higher-level correction path. + ## Released validation-result authority `resolve_validation_result_authority(...)` binds one immutable validation result to the exact `WeightVarianceCompatibilityReceipt`, final analysis-weight receipt, separate variance-design receipt, non-authorizing `verification_pending | not_verifiable` state, and released owner contract. Numerical convergence is not promoted to `verified` at this boundary. @@ -90,7 +92,7 @@ Result authority is the half-open owner-resolved interval `[released_at, superse The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Base-weight source-universe, sampling-design, and owner-contract release instants must come from those durable owner records rather than caller-supplied request coordinates. Final-weight and validation-result correction cutovers plus successor coordinates likewise come only from released owner records, never caller timestamps or mutable current rows. The durable validation-result binding adapter must populate owner-contract release and result supersession cutover from the same canonical chronology so the low-level binding path cannot serve stale evidence. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Base-weight source-universe, sampling-design, and owner-contract release instants must come from those durable owner records rather than caller-supplied request coordinates. Final-weight, point-weight/variance compatibility, and validation-result correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. The durable point-weight/variance adapter must populate owner-contract release and compatibility supersession cutover from canonical released chronology, and the durable validation-result binding adapter must do the same for result chronology, so low-level binding paths cannot serve stale evidence. ## Test contract @@ -105,6 +107,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage, final-weight predecessor/successor correction intervals, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage, final-weight predecessor/successor correction intervals, point/variance owner-contract chronology and binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From 5f7d3e3ae9ec184ce250e3ef80d60aa1a2b4369d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 01:04:04 +0900 Subject: [PATCH 171/603] test(workforce-validation): expose stale weight eligibility after cutover --- ...weight_eligibility_authority_chronology.py | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_eligibility_authority_chronology.py diff --git a/services/workforce-validation-api/tests/test_weight_eligibility_authority_chronology.py b/services/workforce-validation-api/tests/test_weight_eligibility_authority_chronology.py new file mode 100644 index 000000000..87494ecef --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_eligibility_authority_chronology.py @@ -0,0 +1,150 @@ +"""Chronology contract for released weight-eligibility authority.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from inspect import signature +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.weight_eligibility_authority import ( + WeightEligibilityAuthorityIntegrityError, + WeightEligibilityAuthorityRecord, + resolve_weight_eligibility_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000c1") +RECEIPT_REFERENCE = "weight_eligibility_receipt:eligibility-chronology-1" +TARGET_REFERENCE = "analysis_target_population:population-1" +DURATION_REFERENCE = "analysis_reference_duration:duration-1" +OWNER_REFERENCE = "released_owner_contract:weight-eligibility-v1" +RECEIPT_DIGEST = "1" * 64 +TARGET_DIGEST = "2" * 64 +DURATION_DIGEST = "3" * 64 +CASE_SET_DIGEST = "4" * 64 +ARTIFACT_DIGEST = "5" * 64 +OWNER_DIGEST = "6" * 64 +CONSTRUCTED_AT = datetime(2026, 9, 16, 12, 0, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc) +SUPERSEDED_AT = datetime(2026, 9, 17, 13, 0, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "eligibility_receipt_reference", + "eligibility_receipt_digest", + "evidence_version", + "weight_scope_code", + "target_population_reference", + "target_population_digest", + "reference_duration_reference", + "reference_duration_digest", + "eligible_case_set_digest", + "weight_artifact_digest", + "constructed_at", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "released_at", + } +) + + +class _ReadPort: + def __init__(self, record: WeightEligibilityAuthorityRecord) -> None: + self.record = record + + def read_weight_eligibility_authority(self, **_: object) -> WeightEligibilityAuthorityRecord: + return self.record + + +def _record(*, superseded_at: datetime | None = SUPERSEDED_AT) -> WeightEligibilityAuthorityRecord: + return WeightEligibilityAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + eligibility_receipt_reference=RECEIPT_REFERENCE, + eligibility_receipt_digest=RECEIPT_DIGEST, + evidence_version=1, + weight_scope_code="longitudinal", + target_population_reference=TARGET_REFERENCE, + target_population_digest=TARGET_DIGEST, + reference_duration_reference=DURATION_REFERENCE, + reference_duration_digest=DURATION_DIGEST, + eligible_case_set_digest=CASE_SET_DIGEST, + weight_artifact_digest=ARTIFACT_DIGEST, + constructed_at=CONSTRUCTED_AT, + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=1, + owner_contract_digest=OWNER_DIGEST, + released_at=RELEASED_AT, + superseded_at=superseded_at, + ) + + +def _policy() -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="weight-eligibility-chronology-v1", + resource_kind="weight_eligibility_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _resolve(*, used_at: datetime, record: WeightEligibilityAuthorityRecord) -> object: + return resolve_weight_eligibility_authority( + principal=ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ), + tenant_record_id=TENANT, + validity_study_id=STUDY, + eligibility_receipt_reference=RECEIPT_REFERENCE, + eligibility_receipt_digest=RECEIPT_DIGEST, + evidence_version=1, + weight_scope_code="longitudinal", + target_population_reference=TARGET_REFERENCE, + target_population_digest=TARGET_DIGEST, + reference_duration_reference=DURATION_REFERENCE, + reference_duration_digest=DURATION_DIGEST, + eligible_case_set_digest=CASE_SET_DIGEST, + weight_artifact_digest=ARTIFACT_DIGEST, + constructed_at=CONSTRUCTED_AT, + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=1, + owner_contract_digest=OWNER_DIGEST, + used_at=used_at, + purpose_code="selection_validity_analysis", + policy=_policy(), + read_port=_ReadPort(record), + ) + + +def test_supersession_cutover_is_owner_evidence_not_caller_input() -> None: + assert "superseded_at" not in signature(resolve_weight_eligibility_authority).parameters + + +def test_historical_use_before_cutover_remains_reproducible() -> None: + view = _resolve(used_at=SUPERSEDED_AT - timedelta(microseconds=1), record=_record()) + assert dict(view.fields)["released_at"] == RELEASED_AT + + +def test_use_at_or_after_owner_cutover_fails_closed() -> None: + for used_at in (SUPERSEDED_AT, SUPERSEDED_AT + timedelta(seconds=1)): + with pytest.raises(WeightEligibilityAuthorityIntegrityError): + _resolve(used_at=used_at, record=_record()) + + +def test_non_positive_owner_authority_interval_is_rejected() -> None: + for superseded_at in (RELEASED_AT, RELEASED_AT - timedelta(microseconds=1)): + with pytest.raises(ValueError): + _record(superseded_at=superseded_at) + + +def test_unsuperseded_owner_evidence_remains_current() -> None: + _resolve(used_at=SUPERSEDED_AT + timedelta(days=30), record=_record(superseded_at=None)) From 858568fc955e5c04a871b1f25be5148ed05de25c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 01:04:46 +0900 Subject: [PATCH 172/603] fix(workforce-validation): enforce eligibility authority cutover --- .../weight_eligibility_authority.py | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py index 5a99ce84c..0f21d9f68 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py @@ -97,6 +97,7 @@ def __new__( owner_contract_version: int, owner_contract_digest: str, released_at: datetime, + superseded_at: datetime | None = None, ) -> WeightEligibilityAuthorityRecord: """Validate and detach the minimum immutable eligibility authority.""" tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) @@ -144,8 +145,15 @@ def __new__( ) owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) release_instant = _require_aware_datetime("released_at", released_at) + supersession_instant = ( + None + if superseded_at is None + else _require_aware_datetime("superseded_at", superseded_at) + ) if release_instant < constructed: raise ValueError("released_at cannot precede constructed_at.") + if supersession_instant is not None and supersession_instant <= release_instant: + raise ValueError("superseded_at must be later than released_at.") return tuple.__new__( cls, ( @@ -166,6 +174,7 @@ def __new__( owner_version, owner_digest, release_instant, + supersession_instant, ), ) @@ -254,6 +263,11 @@ def released_at(self) -> datetime: """Return when this eligibility evidence became released authority.""" return self[16] + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive owner-resolved cutover when this authority is superseded.""" + return self[17] + class WeightEligibilityAuthorityView(tuple): """Field-minimized eligibility evidence issued only after authorization.""" @@ -450,8 +464,9 @@ def resolve_weight_eligibility_authority( owner_contract_version=persisted.owner_contract_version, owner_contract_digest=persisted.owner_contract_digest, released_at=persisted.released_at, + superseded_at=persisted.superseded_at, ) - if record[:-1] != requested[:-1]: + if record[:-2] != requested[:-2]: raise WeightEligibilityAuthorityIntegrityError( "released weight-eligibility authority does not match requested coordinates" ) @@ -459,6 +474,10 @@ def resolve_weight_eligibility_authority( raise WeightEligibilityAuthorityIntegrityError( "weight-eligibility evidence must be released before scientific use" ) + if record.superseded_at is not None and use_instant >= record.superseded_at: + raise WeightEligibilityAuthorityIntegrityError( + "weight-eligibility evidence is superseded for this scientific-use instant" + ) fields: tuple[tuple[str, object], ...] = ( ("constructed_at", record.constructed_at), From 66dbcac4fcb6053415c55b825524a775487d846f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 01:10:47 +0900 Subject: [PATCH 173/603] test(workforce-validation): expose stale final-weight authority after cutover --- ...al_analysis_weight_authority_chronology.py | 248 ++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_analysis_weight_authority_chronology.py diff --git a/services/workforce-validation-api/tests/test_final_analysis_weight_authority_chronology.py b/services/workforce-validation-api/tests/test_final_analysis_weight_authority_chronology.py new file mode 100644 index 000000000..115b04f75 --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_analysis_weight_authority_chronology.py @@ -0,0 +1,248 @@ +"""Reject retroactive owner contracts and stale final analysis-weight use.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from inspect import signature +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.final_weight_authority import ( + FinalAnalysisWeightAuthorityIntegrityError, + FinalAnalysisWeightAuthorityRecord, + FinalWeightAdjustmentCoordinate, + resolve_final_analysis_weight_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") +WEIGHT_RECEIPT_REFERENCE = "analysis_weight_receipt:11111111-1111-4111-8111-111111111111" +ESTIMAND_REFERENCE = "validation_estimand:criterion-validity-q3" +TARGET_REFERENCE = "analysis_target_population:workers-2026q3" +WINDOW_REFERENCE = "analysis_window:2026q3" +DURATION_REFERENCE = "analysis_reference_duration:2026q3" +SOURCE_REFERENCE = "source_universe_receipt:22222222-2222-4222-8222-222222222222" +SAMPLING_REFERENCE = "sampling_design_receipt:33333333-3333-4333-8333-333333333333" +ELIGIBILITY_REFERENCE = "weight_eligibility_receipt:44444444-4444-4444-8444-444444444444" +OWNER_REFERENCE = "released_owner_contract:55555555-5555-4555-8555-555555555555" +METHOD_REFERENCE = "weight_method:nonresponse-cell-adjustment" +WEIGHT_RECEIPT_DIGEST = "1" * 64 +ESTIMAND_DIGEST = "2" * 64 +TARGET_DIGEST = "3" * 64 +DURATION_DIGEST = "4" * 64 +ELIGIBLE_CASE_DIGEST = "5" * 64 +ANALYTIC_CASE_DIGEST = "6" * 64 +SOURCE_DIGEST = "7" * 64 +SAMPLING_DIGEST = "8" * 64 +BASE_EVIDENCE_DIGEST = "9" * 64 +BASE_ARTIFACT_DIGEST = "a" * 64 +ADJUSTED_ARTIFACT_DIGEST = "b" * 64 +ADJUSTMENT_CONFIG_DIGEST = "c" * 64 +ADJUSTMENT_RECEIPT_DIGEST = "d" * 64 +ELIGIBILITY_DIGEST = "e" * 64 +OWNER_DIGEST = "f" * 64 +CONSTRUCTED_AT = datetime(2026, 9, 17, 8, 0, tzinfo=timezone.utc) +OWNER_RELEASED_AT = datetime(2026, 9, 17, 8, 10, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 8, 30, tzinfo=timezone.utc) +SUPERSEDED_AT = datetime(2026, 9, 17, 10, 0, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "analysis_weight_receipt_reference", + "analysis_weight_receipt_digest", + "evidence_version", + "estimand_reference", + "estimand_digest", + "estimand_scope_code", + "target_population_reference", + "target_population_digest", + "analysis_unit_code", + "analysis_window_reference", + "reference_duration_reference", + "reference_duration_digest", + "eligible_case_set_digest", + "analytic_case_occurrence_set_digest", + "source_universe_receipt_reference", + "source_universe_receipt_version", + "source_universe_receipt_digest", + "sampling_design_receipt_reference", + "sampling_design_receipt_version", + "sampling_design_receipt_digest", + "base_weight_method_code", + "base_weight_method_version", + "base_weight_evidence_digest", + "base_weight_artifact_digest", + "adjustments", + "final_weight_artifact_digest", + "weight_eligibility_receipt_reference", + "weight_eligibility_receipt_digest", + "analytic_case_count", + "constructed_at", + "correction_sequence", + "supersedes_receipt_digest", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + } +) + + +class _ReadPort: + def __init__(self, record: FinalAnalysisWeightAuthorityRecord) -> None: + self.record = record + + def read_final_analysis_weight_authority(self, **_: object) -> FinalAnalysisWeightAuthorityRecord: + return self.record + + +def _adjustment() -> FinalWeightAdjustmentCoordinate: + return FinalWeightAdjustmentCoordinate( + sequence_number=1, + adjustment_code="nonresponse_adjustment", + method_reference=METHOD_REFERENCE, + method_version=2, + input_weight_artifact_digest=BASE_ARTIFACT_DIGEST, + output_weight_artifact_digest=ADJUSTED_ARTIFACT_DIGEST, + configuration_digest=ADJUSTMENT_CONFIG_DIGEST, + evidence_receipt_digest=ADJUSTMENT_RECEIPT_DIGEST, + evidence_kind="nonresponse_adjustment_receipt", + ) + + +def _record(**overrides: object) -> FinalAnalysisWeightAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "analysis_weight_receipt_reference": WEIGHT_RECEIPT_REFERENCE, + "analysis_weight_receipt_digest": WEIGHT_RECEIPT_DIGEST, + "evidence_version": 1, + "estimand_reference": ESTIMAND_REFERENCE, + "estimand_digest": ESTIMAND_DIGEST, + "estimand_scope_code": "longitudinal", + "target_population_reference": TARGET_REFERENCE, + "target_population_digest": TARGET_DIGEST, + "analysis_unit_code": "person_occurrence", + "analysis_window_reference": WINDOW_REFERENCE, + "reference_duration_reference": DURATION_REFERENCE, + "reference_duration_digest": DURATION_DIGEST, + "eligible_case_set_digest": ELIGIBLE_CASE_DIGEST, + "analytic_case_occurrence_set_digest": ANALYTIC_CASE_DIGEST, + "source_universe_receipt_reference": SOURCE_REFERENCE, + "source_universe_receipt_version": 4, + "source_universe_receipt_digest": SOURCE_DIGEST, + "sampling_design_receipt_reference": SAMPLING_REFERENCE, + "sampling_design_receipt_version": 3, + "sampling_design_receipt_digest": SAMPLING_DIGEST, + "base_weight_method_code": "inverse_inclusion_probability", + "base_weight_method_version": 1, + "base_weight_evidence_digest": BASE_EVIDENCE_DIGEST, + "base_weight_artifact_digest": BASE_ARTIFACT_DIGEST, + "adjustments": (_adjustment(),), + "final_weight_artifact_digest": ADJUSTED_ARTIFACT_DIGEST, + "weight_eligibility_receipt_reference": ELIGIBILITY_REFERENCE, + "weight_eligibility_receipt_digest": ELIGIBILITY_DIGEST, + "analytic_case_count": 1200, + "constructed_at": CONSTRUCTED_AT, + "correction_sequence": 1, + "supersedes_receipt_digest": None, + "owner_contract_reference": OWNER_REFERENCE, + "owner_contract_version": 7, + "owner_contract_digest": OWNER_DIGEST, + "owner_contract_released_at": OWNER_RELEASED_AT, + "released_at": RELEASED_AT, + "superseded_at": SUPERSEDED_AT, + } + values.update(overrides) + return FinalAnalysisWeightAuthorityRecord(**values) + + +def _resolve(*, used_at: datetime, record: FinalAnalysisWeightAuthorityRecord) -> object: + return resolve_final_analysis_weight_authority( + principal=ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ), + tenant_record_id=TENANT, + validity_study_id=STUDY, + analysis_weight_receipt_reference=WEIGHT_RECEIPT_REFERENCE, + analysis_weight_receipt_digest=WEIGHT_RECEIPT_DIGEST, + evidence_version=1, + estimand_reference=ESTIMAND_REFERENCE, + estimand_digest=ESTIMAND_DIGEST, + estimand_scope_code="longitudinal", + target_population_reference=TARGET_REFERENCE, + target_population_digest=TARGET_DIGEST, + analysis_unit_code="person_occurrence", + analysis_window_reference=WINDOW_REFERENCE, + reference_duration_reference=DURATION_REFERENCE, + reference_duration_digest=DURATION_DIGEST, + eligible_case_set_digest=ELIGIBLE_CASE_DIGEST, + analytic_case_occurrence_set_digest=ANALYTIC_CASE_DIGEST, + source_universe_receipt_reference=SOURCE_REFERENCE, + source_universe_receipt_version=4, + source_universe_receipt_digest=SOURCE_DIGEST, + sampling_design_receipt_reference=SAMPLING_REFERENCE, + sampling_design_receipt_version=3, + sampling_design_receipt_digest=SAMPLING_DIGEST, + base_weight_method_code="inverse_inclusion_probability", + base_weight_method_version=1, + base_weight_evidence_digest=BASE_EVIDENCE_DIGEST, + base_weight_artifact_digest=BASE_ARTIFACT_DIGEST, + adjustments=(_adjustment(),), + final_weight_artifact_digest=ADJUSTED_ARTIFACT_DIGEST, + weight_eligibility_receipt_reference=ELIGIBILITY_REFERENCE, + weight_eligibility_receipt_digest=ELIGIBILITY_DIGEST, + analytic_case_count=1200, + constructed_at=CONSTRUCTED_AT, + correction_sequence=1, + supersedes_receipt_digest=None, + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=7, + owner_contract_digest=OWNER_DIGEST, + used_at=used_at, + purpose_code="selection_validity_analysis", + policy=PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="final-analysis-weight-authority-read-v2", + resource_kind="final_analysis_weight_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ), + read_port=_ReadPort(record), + ) + + +def test_chronology_is_owner_evidence_not_caller_input() -> None: + parameters = signature(resolve_final_analysis_weight_authority).parameters + assert "owner_contract_released_at" not in parameters + assert "superseded_at" not in parameters + + +def test_owner_contract_cannot_retroactively_authorize_final_weight() -> None: + with pytest.raises(ValueError, match="owner contract"): + _record(owner_contract_released_at=RELEASED_AT + timedelta(microseconds=1)) + + +def test_final_weight_uses_owner_resolved_half_open_authority_interval() -> None: + historical = _resolve( + used_at=SUPERSEDED_AT - timedelta(microseconds=1), record=_record() + ) + fields = dict(historical.fields) + assert fields["owner_contract_released_at"] == OWNER_RELEASED_AT + assert fields["superseded_at"] == SUPERSEDED_AT + + with pytest.raises(FinalAnalysisWeightAuthorityIntegrityError, match="supersession"): + _resolve(used_at=SUPERSEDED_AT, record=_record()) + + +def test_non_positive_owner_authority_interval_is_rejected() -> None: + with pytest.raises(ValueError, match="superseded_at"): + _record(superseded_at=RELEASED_AT) From 0a586324a7f6da7bf76a9c9947be23fae53257b0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 01:12:56 +0900 Subject: [PATCH 174/603] fix(workforce-validation): enforce final-weight authority cutover --- .../final_weight_authority.py | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py index b445d18c4..fab3fa710 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py @@ -83,7 +83,9 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "released_at", + "superseded_at", } ) @@ -248,7 +250,9 @@ def __new__( owner_contract_reference: str, owner_contract_version: int, owner_contract_digest: str, + owner_contract_released_at: datetime, released_at: datetime, + superseded_at: datetime | None = None, ) -> FinalAnalysisWeightAuthorityRecord: """Validate and detach the complete scientific point-weight lineage.""" tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) @@ -397,9 +401,21 @@ def __new__( "owner_contract_version", owner_contract_version ) owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + owner_release_instant = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) release_instant = _require_aware_datetime("released_at", released_at) if release_instant < constructed: raise ValueError("released_at cannot precede constructed_at.") + if owner_release_instant > release_instant: + raise ValueError( + "owner contract must be released no later than the final analysis-weight authority" + ) + supersession_instant = None + if superseded_at is not None: + supersession_instant = _require_aware_datetime("superseded_at", superseded_at) + if supersession_instant <= release_instant: + raise ValueError("superseded_at must be later than released_at") fields: tuple[tuple[str, object], ...] = ( ("adjustments", tuple(detached_adjustments)), @@ -440,7 +456,14 @@ def __new__( ) return tuple.__new__( cls, - (tenant_identity, study_identity, fields, release_instant), + ( + tenant_identity, + study_identity, + fields, + release_instant, + owner_release_instant, + supersession_instant, + ), ) @property @@ -463,6 +486,16 @@ def released_at(self) -> datetime: """Return the owner-resolved release instant.""" return self[3] + @property + def owner_contract_released_at(self) -> datetime: + """Return when the governing owner contract became released authority.""" + return self[4] + + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive owner-resolved cutover instant, when one exists.""" + return self[5] + class FinalAnalysisWeightAuthorityView(tuple): """Field-minimized final-weight evidence issued only after authorization.""" @@ -628,7 +661,9 @@ def resolve_final_analysis_weight_authority( owner_contract_reference=owner_contract_reference, owner_contract_version=owner_contract_version, owner_contract_digest=owner_contract_digest, + owner_contract_released_at=constructed_at, released_at=constructed_at, + superseded_at=None, ) tenant_id = requested.tenant_record_id study_id = requested.validity_study_id @@ -700,7 +735,9 @@ def resolve_final_analysis_weight_authority( record = FinalAnalysisWeightAuthorityRecord( tenant_record_id=persisted.tenant_record_id, validity_study_id=persisted.validity_study_id, + owner_contract_released_at=persisted.owner_contract_released_at, released_at=persisted.released_at, + superseded_at=persisted.superseded_at, **dict(persisted.fields), ) if ( @@ -717,9 +754,15 @@ def resolve_final_analysis_weight_authority( raise FinalAnalysisWeightAuthorityIntegrityError( "final analysis-weight authority cannot be used before its release instant" ) + if record.superseded_at is not None and use_instant >= record.superseded_at: + raise FinalAnalysisWeightAuthorityIntegrityError( + "final analysis-weight authority cannot be used at or after supersession" + ) values = dict(record.fields) + values["owner_contract_released_at"] = record.owner_contract_released_at values["released_at"] = record.released_at + values["superseded_at"] = record.superseded_at fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) return tuple.__new__( FinalAnalysisWeightAuthorityView, From 44e44425bffca4341393ebbce52ce984faecf877 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 01:13:40 +0900 Subject: [PATCH 175/603] test(workforce-validation): align final-weight chronology fixtures --- .../tests/test_final_analysis_weight_authority.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/services/workforce-validation-api/tests/test_final_analysis_weight_authority.py b/services/workforce-validation-api/tests/test_final_analysis_weight_authority.py index 2683e3e23..c3f674f81 100644 --- a/services/workforce-validation-api/tests/test_final_analysis_weight_authority.py +++ b/services/workforce-validation-api/tests/test_final_analysis_weight_authority.py @@ -50,6 +50,7 @@ OWNER_DIGEST = "f" * 64 SUPERSEDES_DIGEST = "0" * 64 CONSTRUCTED_AT = datetime(2026, 9, 17, 8, 0, tzinfo=timezone.utc) +OWNER_RELEASED_AT = datetime(2026, 9, 17, 8, 10, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 17, 8, 30, tzinfo=timezone.utc) USED_AT = datetime(2026, 9, 17, 9, 0, tzinfo=timezone.utc) READ_FIELDS = frozenset( @@ -89,7 +90,9 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "released_at", + "superseded_at", } ) @@ -197,7 +200,9 @@ def _record(**overrides: object) -> FinalAnalysisWeightAuthorityRecord: "owner_contract_reference": OWNER_REFERENCE, "owner_contract_version": 7, "owner_contract_digest": OWNER_DIGEST, + "owner_contract_released_at": OWNER_RELEASED_AT, "released_at": RELEASED_AT, + "superseded_at": None, } values.update(overrides) return FinalAnalysisWeightAuthorityRecord(**values) @@ -235,7 +240,9 @@ def test_resolution_binds_complete_estimand_source_base_adjustment_and_final_art assert ("source_universe_receipt_digest", SOURCE_DIGEST) in view.fields assert ("base_weight_evidence_digest", BASE_EVIDENCE_DIGEST) in view.fields assert ("final_weight_artifact_digest", ADJUSTED_ARTIFACT_DIGEST) in view.fields + assert ("owner_contract_released_at", OWNER_RELEASED_AT) in view.fields assert ("released_at", RELEASED_AT) in view.fields + assert ("superseded_at", None) in view.fields adjustment = dict(view.fields)["adjustments"][0] assert tuple(adjustment) == tuple(_adjustment()) assert adjustment.sequence_number == 1 @@ -405,7 +412,9 @@ def test_record_adjustment_and_view_are_structurally_immutable() -> None: object.__setattr__(tenant, "int", OTHER_TENANT.int) assert record.tenant_record_id == TENANT assert record.validity_study_id == STUDY + assert record.owner_contract_released_at == OWNER_RELEASED_AT assert record.released_at == RELEASED_AT + assert record.superseded_at is None with pytest.raises(AttributeError): object.__setattr__(record, "fields", ()) From 887b05ee5fcd114d224529fa1c751d6a9304b1a4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 01:14:15 +0900 Subject: [PATCH 176/603] test(workforce-validation): expose retroactive eligibility owner contract --- ...weight_eligibility_authority_chronology.py | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/services/workforce-validation-api/tests/test_weight_eligibility_authority_chronology.py b/services/workforce-validation-api/tests/test_weight_eligibility_authority_chronology.py index 87494ecef..f9cebdaa0 100644 --- a/services/workforce-validation-api/tests/test_weight_eligibility_authority_chronology.py +++ b/services/workforce-validation-api/tests/test_weight_eligibility_authority_chronology.py @@ -29,6 +29,7 @@ ARTIFACT_DIGEST = "5" * 64 OWNER_DIGEST = "6" * 64 CONSTRUCTED_AT = datetime(2026, 9, 16, 12, 0, tzinfo=timezone.utc) +OWNER_RELEASED_AT = datetime(2026, 9, 16, 12, 30, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc) SUPERSEDED_AT = datetime(2026, 9, 17, 13, 0, tzinfo=timezone.utc) READ_FIELDS = frozenset( @@ -47,7 +48,9 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "released_at", + "superseded_at", } ) @@ -60,7 +63,11 @@ def read_weight_eligibility_authority(self, **_: object) -> WeightEligibilityAut return self.record -def _record(*, superseded_at: datetime | None = SUPERSEDED_AT) -> WeightEligibilityAuthorityRecord: +def _record( + *, + owner_contract_released_at: datetime = OWNER_RELEASED_AT, + superseded_at: datetime | None = SUPERSEDED_AT, +) -> WeightEligibilityAuthorityRecord: return WeightEligibilityAuthorityRecord( tenant_record_id=TENANT, validity_study_id=STUDY, @@ -78,6 +85,7 @@ def _record(*, superseded_at: datetime | None = SUPERSEDED_AT) -> WeightEligibil owner_contract_reference=OWNER_REFERENCE, owner_contract_version=1, owner_contract_digest=OWNER_DIGEST, + owner_contract_released_at=owner_contract_released_at, released_at=RELEASED_AT, superseded_at=superseded_at, ) @@ -86,7 +94,7 @@ def _record(*, superseded_at: datetime | None = SUPERSEDED_AT) -> WeightEligibil def _policy() -> PurposeBoundAccessPolicy: return PurposeBoundAccessPolicy( tenant_record_id=TENANT, - policy_version_code="weight-eligibility-chronology-v1", + policy_version_code="weight-eligibility-chronology-v2", resource_kind="weight_eligibility_authority", purpose_code="selection_validity_analysis", operation_code="read", @@ -125,13 +133,23 @@ def _resolve(*, used_at: datetime, record: WeightEligibilityAuthorityRecord) -> ) -def test_supersession_cutover_is_owner_evidence_not_caller_input() -> None: - assert "superseded_at" not in signature(resolve_weight_eligibility_authority).parameters +def test_chronology_is_owner_evidence_not_caller_input() -> None: + parameters = signature(resolve_weight_eligibility_authority).parameters + assert "owner_contract_released_at" not in parameters + assert "superseded_at" not in parameters + + +def test_owner_contract_cannot_retroactively_authorize_eligibility() -> None: + with pytest.raises(ValueError, match="owner contract"): + _record(owner_contract_released_at=RELEASED_AT + timedelta(microseconds=1)) def test_historical_use_before_cutover_remains_reproducible() -> None: view = _resolve(used_at=SUPERSEDED_AT - timedelta(microseconds=1), record=_record()) - assert dict(view.fields)["released_at"] == RELEASED_AT + fields = dict(view.fields) + assert fields["owner_contract_released_at"] == OWNER_RELEASED_AT + assert fields["released_at"] == RELEASED_AT + assert fields["superseded_at"] == SUPERSEDED_AT def test_use_at_or_after_owner_cutover_fails_closed() -> None: From a4795dc11c30779e02e3639afe73710c83b430a9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 01:14:53 +0900 Subject: [PATCH 177/603] fix(workforce-validation): bind eligibility owner-contract chronology --- .../weight_eligibility_authority.py | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py index 0f21d9f68..bdec01e47 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py @@ -52,7 +52,9 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "released_at", + "superseded_at", } ) @@ -96,6 +98,7 @@ def __new__( owner_contract_reference: str, owner_contract_version: int, owner_contract_digest: str, + owner_contract_released_at: datetime, released_at: datetime, superseded_at: datetime | None = None, ) -> WeightEligibilityAuthorityRecord: @@ -144,6 +147,9 @@ def __new__( "owner_contract_version", owner_contract_version ) owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + owner_release_instant = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) release_instant = _require_aware_datetime("released_at", released_at) supersession_instant = ( None @@ -152,6 +158,10 @@ def __new__( ) if release_instant < constructed: raise ValueError("released_at cannot precede constructed_at.") + if owner_release_instant > release_instant: + raise ValueError( + "owner contract must be released no later than the weight-eligibility authority" + ) if supersession_instant is not None and supersession_instant <= release_instant: raise ValueError("superseded_at must be later than released_at.") return tuple.__new__( @@ -174,6 +184,7 @@ def __new__( owner_version, owner_digest, release_instant, + owner_release_instant, supersession_instant, ), ) @@ -263,10 +274,15 @@ def released_at(self) -> datetime: """Return when this eligibility evidence became released authority.""" return self[16] + @property + def owner_contract_released_at(self) -> datetime: + """Return when the governing owner contract became released authority.""" + return self[17] + @property def superseded_at(self) -> datetime | None: """Return the exclusive owner-resolved cutover when this authority is superseded.""" - return self[17] + return self[18] class WeightEligibilityAuthorityView(tuple): @@ -391,7 +407,9 @@ def resolve_weight_eligibility_authority( owner_contract_reference=owner_contract_reference, owner_contract_version=owner_contract_version, owner_contract_digest=owner_contract_digest, + owner_contract_released_at=constructed_at, released_at=constructed_at, + superseded_at=None, ) tenant_id = requested.tenant_record_id study_id = requested.validity_study_id @@ -463,10 +481,11 @@ def resolve_weight_eligibility_authority( owner_contract_reference=persisted.owner_contract_reference, owner_contract_version=persisted.owner_contract_version, owner_contract_digest=persisted.owner_contract_digest, + owner_contract_released_at=persisted.owner_contract_released_at, released_at=persisted.released_at, superseded_at=persisted.superseded_at, ) - if record[:-2] != requested[:-2]: + if record[:-3] != requested[:-3]: raise WeightEligibilityAuthorityIntegrityError( "released weight-eligibility authority does not match requested coordinates" ) @@ -487,10 +506,12 @@ def resolve_weight_eligibility_authority( ("evidence_version", record.evidence_version), ("owner_contract_digest", record.owner_contract_digest), ("owner_contract_reference", record.owner_contract_reference), + ("owner_contract_released_at", record.owner_contract_released_at), ("owner_contract_version", record.owner_contract_version), ("reference_duration_digest", record.reference_duration_digest), ("reference_duration_reference", record.reference_duration_reference), ("released_at", record.released_at), + ("superseded_at", record.superseded_at), ("target_population_digest", record.target_population_digest), ("target_population_reference", record.target_population_reference), ("weight_artifact_digest", record.weight_artifact_digest), From 94b6c0801960f12b8451c3c9eff69f5a959b51ed Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 01:16:24 +0900 Subject: [PATCH 178/603] test(workforce-validation): align eligibility chronology fixtures --- .../tests/test_weight_eligibility_authority.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_weight_eligibility_authority.py b/services/workforce-validation-api/tests/test_weight_eligibility_authority.py index 1be518186..805e63dd2 100644 --- a/services/workforce-validation-api/tests/test_weight_eligibility_authority.py +++ b/services/workforce-validation-api/tests/test_weight_eligibility_authority.py @@ -33,6 +33,7 @@ WEIGHT_ARTIFACT_DIGEST = "5" * 64 OWNER_CONTRACT_DIGEST = "6" * 64 CONSTRUCTED_AT = datetime(2026, 9, 16, 12, 0, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 16, 12, 30, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc) USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) READ_FIELDS = frozenset( @@ -51,7 +52,9 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "released_at", + "superseded_at", } ) @@ -96,7 +99,7 @@ def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: return PurposeBoundAccessPolicy( tenant_record_id=TENANT, - policy_version_code="weight-eligibility-authority-read-v1", + policy_version_code="weight-eligibility-authority-read-v2", resource_kind="weight_eligibility_authority", purpose_code=purpose_code, operation_code="read", @@ -123,7 +126,9 @@ def _record(**overrides: object) -> WeightEligibilityAuthorityRecord: "owner_contract_reference": OWNER_CONTRACT_REFERENCE, "owner_contract_version": 3, "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, "released_at": RELEASED_AT, + "superseded_at": None, } values.update(overrides) return WeightEligibilityAuthorityRecord(**values) @@ -175,6 +180,9 @@ def test_longitudinal_resolution_binds_population_duration_case_set_and_artifact assert ("reference_duration_reference", REFERENCE_DURATION_REFERENCE) in view.fields assert ("eligible_case_set_digest", ELIGIBLE_CASE_SET_DIGEST) in view.fields assert ("weight_artifact_digest", WEIGHT_ARTIFACT_DIGEST) in view.fields + assert ("owner_contract_released_at", OWNER_CONTRACT_RELEASED_AT) in view.fields + assert ("released_at", RELEASED_AT) in view.fields + assert ("superseded_at", None) in view.fields def test_cross_sectional_scope_is_distinct_released_authority() -> None: @@ -276,6 +284,8 @@ def test_record_and_view_are_structurally_immutable_and_uuid_views_are_detached( record = _record(tenant_record_id=tenant) object.__setattr__(tenant, "int", OTHER_TENANT.int) assert record.tenant_record_id == TENANT + assert record.owner_contract_released_at == OWNER_CONTRACT_RELEASED_AT + assert record.superseded_at is None with pytest.raises(AttributeError): object.__setattr__(record, "weight_scope_code", "cross_sectional") From a700f141a4f5cfddcf118bd8170cbb1d875db38a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 01:16:33 +0900 Subject: [PATCH 179/603] test(workforce-validation): cover eligibility chronology edges --- .../test_weight_eligibility_authority_edges.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_weight_eligibility_authority_edges.py b/services/workforce-validation-api/tests/test_weight_eligibility_authority_edges.py index c7a0f6483..a749514ca 100644 --- a/services/workforce-validation-api/tests/test_weight_eligibility_authority_edges.py +++ b/services/workforce-validation-api/tests/test_weight_eligibility_authority_edges.py @@ -10,7 +10,14 @@ ) -def _record(*, evidence_version: object = 1) -> WeightEligibilityAuthorityRecord: +def _record( + *, + evidence_version: object = 1, + owner_contract_released_at: object = datetime( + 2026, 9, 16, 12, 30, tzinfo=timezone.utc + ), + superseded_at: object = None, +) -> WeightEligibilityAuthorityRecord: return WeightEligibilityAuthorityRecord( tenant_record_id=UUID("10000000-0000-7000-8000-000000000001"), validity_study_id=UUID("00000000-0000-7000-8000-0000000000d1"), @@ -32,10 +39,19 @@ def _record(*, evidence_version: object = 1) -> WeightEligibilityAuthorityRecord ), owner_contract_version=3, owner_contract_digest="6" * 64, + owner_contract_released_at=owner_contract_released_at, released_at=datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc), + superseded_at=superseded_at, ) def test_evidence_version_cannot_advance_without_contract_revision() -> None: with pytest.raises(ValueError, match="evidence_version must remain 1"): _record(evidence_version=2) + + +def test_owner_chronology_requires_timezone_aware_instants() -> None: + with pytest.raises(ValueError): + _record(owner_contract_released_at=datetime(2026, 9, 16, 12, 30)) + with pytest.raises(ValueError): + _record(superseded_at=datetime(2026, 9, 17, 13, 0)) From f23e10ed9d18269f89054372acc0b049117e0168 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 01:17:31 +0900 Subject: [PATCH 180/603] docs(workforce-validation): document owner-resolved weight currentness --- services/workforce-validation-api/README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index f00f1fc42..adcd1ed02 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -46,6 +46,8 @@ This preserves the evidence needed to reproduce which governed trimming/bounding `resolve_weight_eligibility_authority(...)` corroborates #407 RED #9 instead of treating an eligibility digest as sufficient authority. It binds the exact `weight_eligibility_receipt` reference/digest/evidence version to explicit `cross_sectional | longitudinal` scope, governed target-population and reference-duration coordinates, exact eligible-case set, exact point-weight artifact, construction time, released owner-contract tuple, and owner-resolved receipt release time. Cross-sectional and longitudinal eligibility are distinct authority states; a different population, duration, case set, or artifact cannot be silently reused. Person attributes and row-level weights are excluded. +The governing owner-contract release instant and optional exclusive eligibility cutover are also owner-resolved evidence, not caller coordinates. The owner contract must exist no later than the eligibility receipt release, and the ordinary resolver enforces `[released_at, superseded_at)`. Historical scientific use before cutover remains reproducible; use at or after cutover fails closed. This prevents a corrected population, duration, eligible-case set, or point-weight artifact from leaving an older eligibility receipt apparently current merely because a consumer bypasses a higher-level correction path. + ## Base/design-weight authority `resolve_base_weight_authority(...)` corroborates the base/design-weight derivation instead of accepting `base_weight_evidence_digest` as an opaque caller label. It binds an exact released base-weight evidence receipt to the source-universe and sampling-design receipt references/versions/digests, their release chronology, the sampled occurrence set, an immutable digest of the stage-wise selection-probability evidence, the positive selection-stage count, base-weight method/version, resulting base-weight artifact, construction time, and released owner contract. @@ -58,6 +60,8 @@ The stage-wise probability values themselves stay with the sampling owner. `work The ordered adjustment chain is immutable and contiguous: each transform must consume the preceding artifact, material transforms may not be no-ops, and known nonresponse/calibration/raking/poststratification/trimming/bounding/winsorization codes require their specialized receipt kind. Source/sampling references are owner-corroborated coordinates layered over the digest-only scientific leaf, so a caller cannot turn an opaque digest into a floating source/design version. The separate base-weight authority additionally resolves the stage-wise selection-probability evidence behind the base artifact. No row-level weights, case identities, protected calibration values, or foreign tables cross this boundary. +The ordinary final-weight resolver itself now resolves the governing owner-contract release instant and optional exclusive supersession cutover from canonical owner evidence. Neither is a caller request coordinate. A later owner contract cannot retroactively authorize an earlier final-weight receipt, and scientific use is valid only on `[released_at, superseded_at)`. The separate supersession authority still proves the complete predecessor/successor edge; this lower-level resolver consumes only the owner-resolved chronology needed to prevent stale final-weight evidence from remaining usable when callers do not traverse that graph. + ## Final analysis-weight supersession authority `resolve_final_weight_supersession_authority(...)` closes the point-weight side of #407 RED #10 at the application-owner boundary. A `correction_sequence` plus predecessor digest is not enough to prove that a previously released final-weight receipt stopped being authoritative without in-place mutation. The owner record therefore preserves the predecessor release instant, exclusive supersession instant, and complete released successor coordinates. The successor must have a new receipt reference and digest, advance the correction sequence exactly by one, be released after its predecessor, and already exist no later than the cutover. The released owner contract must predate the predecessor receipt. @@ -92,7 +96,7 @@ Result authority is the half-open owner-resolved interval `[released_at, superse The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Base-weight source-universe, sampling-design, and owner-contract release instants must come from those durable owner records rather than caller-supplied request coordinates. Final-weight, point-weight/variance compatibility, and validation-result correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. The durable point-weight/variance adapter must populate owner-contract release and compatibility supersession cutover from canonical released chronology, and the durable validation-result binding adapter must do the same for result chronology, so low-level binding paths cannot serve stale evidence. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Base-weight source-universe, sampling-design, and owner-contract release instants must come from those durable owner records rather than caller-supplied request coordinates. Eligibility, final-weight, point-weight/variance compatibility, and validation-result owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Low-level eligibility/final-weight/binding adapters must therefore recover the same canonical chronology used by their corresponding correction graph rather than independently infer currentness. ## Test contract @@ -107,6 +111,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage, final-weight predecessor/successor correction intervals, point/variance owner-contract chronology and binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology and low-level final-weight currentness, final-weight predecessor/successor correction intervals, point/variance owner-contract chronology and binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From 0870fb79b699093a0c6019476b7e6fbbdbae01a8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 02:01:52 +0900 Subject: [PATCH 181/603] test(workforce-validation): require complete variance lookup key --- ...ght_variance_read_port_key_completeness.py | 162 ++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_variance_read_port_key_completeness.py diff --git a/services/workforce-validation-api/tests/test_weight_variance_read_port_key_completeness.py b/services/workforce-validation-api/tests/test_weight_variance_read_port_key_completeness.py new file mode 100644 index 000000000..78545d5a4 --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_variance_read_port_key_completeness.py @@ -0,0 +1,162 @@ +"""Require the owner read to key the complete point-weight/variance compatibility tuple.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.variance_authority import ( + WeightVarianceAuthorityRecord, + resolve_weight_variance_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +SAMPLING_REFERENCE = "sampling_design_receipt:22222222-2222-4222-8222-222222222222" +VARIANCE_REFERENCE = "variance_design_receipt:33333333-3333-4333-8333-333333333333" +METHOD_REFERENCE = "variance_method:44444444-4444-4444-8444-444444444444" +OWNER_REFERENCE = "released_owner_contract:55555555-5555-4555-8555-555555555555" +AUTHORITY_REFERENCE = "variance_compatibility_authority:11111111-1111-4111-8111-111111111111" +SAMPLING_DIGEST = "1" * 64 +ANALYSIS_WEIGHT_DIGEST = "2" * 64 +CASE_SET_DIGEST = "3" * 64 +ELIGIBILITY_DIGEST = "4" * 64 +FINAL_WEIGHT_DIGEST = "6" * 64 +VARIANCE_DIGEST = "7" * 64 +OWNER_DIGEST = "8" * 64 +RELEASED_AT = datetime(2026, 9, 17, 1, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 2, tzinfo=timezone.utc) + + +class _StrictReadPort: + """Require every coordinate needed to select one compatibility record.""" + + def read_weight_variance_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + sampling_receipt_reference: str, + sampling_receipt_version: int, + sampling_receipt_digest: str, + analysis_weight_receipt_digest: str, + analytic_case_occurrence_set_digest: str, + weight_eligibility_receipt_digest: str, + weight_correction_sequence: int, + final_weight_artifact_digest: str, + variance_design_receipt_reference: str, + variance_design_receipt_version: int, + variance_design_receipt_digest: str, + variance_method_reference: str, + variance_method_version: int, + variance_evidence_mode: str, + variance_semantics: str, + owner_contract_reference: str, + owner_contract_version: int, + ) -> WeightVarianceAuthorityRecord: + assert analytic_case_occurrence_set_digest == CASE_SET_DIGEST + assert weight_eligibility_receipt_digest == ELIGIBILITY_DIGEST + assert weight_correction_sequence == 9 + assert final_weight_artifact_digest == FINAL_WEIGHT_DIGEST + assert variance_method_reference == METHOD_REFERENCE + assert variance_method_version == 2 + assert variance_evidence_mode == "replicate_weights" + assert variance_semantics == "exact" + return WeightVarianceAuthorityRecord( + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + authority_reference=AUTHORITY_REFERENCE, + sampling_receipt_reference=sampling_receipt_reference, + sampling_receipt_version=sampling_receipt_version, + sampling_receipt_digest=sampling_receipt_digest, + analysis_weight_receipt_digest=analysis_weight_receipt_digest, + analytic_case_occurrence_set_digest=analytic_case_occurrence_set_digest, + weight_eligibility_receipt_digest=weight_eligibility_receipt_digest, + weight_correction_sequence=weight_correction_sequence, + final_weight_artifact_digest=final_weight_artifact_digest, + variance_design_receipt_reference=variance_design_receipt_reference, + variance_design_receipt_version=variance_design_receipt_version, + variance_design_receipt_digest=variance_design_receipt_digest, + variance_method_reference=variance_method_reference, + variance_method_version=variance_method_version, + variance_evidence_mode=variance_evidence_mode, + variance_semantics=variance_semantics, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=OWNER_DIGEST, + owner_contract_released_at=RELEASED_AT, + released_at=RELEASED_AT, + ) + + +def test_owner_read_receives_complete_compatibility_tuple() -> None: + principal = ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + policy = PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="weight-variance-authority-read-v2", + resource_kind="weight_variance_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=frozenset( + { + "authority_reference", + "sampling_receipt_reference", + "sampling_receipt_version", + "sampling_receipt_digest", + "analysis_weight_receipt_digest", + "analytic_case_occurrence_set_digest", + "weight_eligibility_receipt_digest", + "weight_correction_sequence", + "final_weight_artifact_digest", + "variance_design_receipt_reference", + "variance_design_receipt_version", + "variance_design_receipt_digest", + "variance_method_reference", + "variance_method_version", + "variance_evidence_mode", + "variance_semantics", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + } + ), + ) + + view = resolve_weight_variance_authority( + principal=principal, + tenant_record_id=TENANT, + validity_study_id=STUDY, + sampling_receipt_reference=SAMPLING_REFERENCE, + sampling_receipt_version=3, + sampling_receipt_digest=SAMPLING_DIGEST, + analysis_weight_receipt_digest=ANALYSIS_WEIGHT_DIGEST, + analytic_case_occurrence_set_digest=CASE_SET_DIGEST, + weight_eligibility_receipt_digest=ELIGIBILITY_DIGEST, + weight_correction_sequence=9, + final_weight_artifact_digest=FINAL_WEIGHT_DIGEST, + variance_design_receipt_reference=VARIANCE_REFERENCE, + variance_design_receipt_version=5, + variance_design_receipt_digest=VARIANCE_DIGEST, + variance_method_reference=METHOD_REFERENCE, + variance_method_version=2, + variance_evidence_mode="replicate_weights", + variance_semantics="exact", + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=4, + used_at=USED_AT, + purpose_code="selection_validity_analysis", + policy=policy, + read_port=_StrictReadPort(), + ) + + assert dict(view.fields)["variance_method_reference"] == METHOD_REFERENCE From c9c313a8847c54dfc001bda1af4cc1a13547bfd1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 02:02:00 +0900 Subject: [PATCH 182/603] test(workforce-validation): align result release with cutover --- ...t_result_supersession_cutover_alignment.py | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_result_supersession_cutover_alignment.py diff --git a/services/workforce-validation-api/tests/test_result_supersession_cutover_alignment.py b/services/workforce-validation-api/tests/test_result_supersession_cutover_alignment.py new file mode 100644 index 000000000..47aeb0013 --- /dev/null +++ b/services/workforce-validation-api/tests/test_result_supersession_cutover_alignment.py @@ -0,0 +1,55 @@ +"""Require a released successor to become authoritative exactly at predecessor cutover.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.result_supersession_authority import ( + ValidationResultSupersessionAuthorityRecord, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +SUCCESSOR_REFERENCE = "validation_analysis_result:33333333-3333-4333-8333-333333333333" +OWNER_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +RESULT_DIGEST = "1" * 64 +SUCCESSOR_DIGEST = "3" * 64 +OWNER_DIGEST = "2" * 64 +RELEASED_AT = datetime(2026, 9, 17, 10, tzinfo=timezone.utc) +CUTOVER = datetime(2026, 9, 17, 12, tzinfo=timezone.utc) + + +def _record(*, successor_released_at: datetime) -> ValidationResultSupersessionAuthorityRecord: + return ValidationResultSupersessionAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + evidence_version=1, + correction_sequence=2, + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_DIGEST, + owner_contract_released_at=datetime(2026, 9, 1, tzinfo=timezone.utc), + released_at=RELEASED_AT, + superseded_at=CUTOVER, + successor_result_reference=SUCCESSOR_REFERENCE, + successor_correction_sequence=3, + successor_result_digest=SUCCESSOR_DIGEST, + successor_released_at=successor_released_at, + ) + + +def test_successor_release_cannot_precede_cutover() -> None: + with pytest.raises(ValueError, match="exactly at supersession"): + _record(successor_released_at=CUTOVER - timedelta(seconds=1)) + + +def test_successor_release_matches_cutover() -> None: + record = _record(successor_released_at=CUTOVER) + assert record.superseded_at == CUTOVER + assert dict(record.successor_fields or ())["successor_released_at"] == CUTOVER From 02edde822f508cd162e79eee4ff0abccbf1215e6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 02:02:42 +0900 Subject: [PATCH 183/603] fix(workforce-validation): align result cutover with successor release --- .../result_supersession_authority.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py index 5052faa49..dcc4c0ade 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py @@ -176,9 +176,9 @@ def __new__( raise ValueError( "successor validation result must be released after its predecessor." ) - if successor_release > cutover: + if successor_release != cutover: raise ValueError( - "successor validation result must be released no later than supersession." + "successor validation result must be released exactly at supersession." ) current_fields: tuple[tuple[str, object], ...] = ( From a5f4c189befc3bc8fa5527c4c96a0702e8c915b2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 02:03:49 +0900 Subject: [PATCH 184/603] fix(workforce-validation): key complete variance compatibility tuple --- .../variance_authority.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py index adf46f63e..f8f5b7520 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py @@ -416,9 +416,17 @@ def read_weight_variance_authority( sampling_receipt_version: int, sampling_receipt_digest: str, analysis_weight_receipt_digest: str, + analytic_case_occurrence_set_digest: str, + weight_eligibility_receipt_digest: str, + weight_correction_sequence: int, + final_weight_artifact_digest: str, variance_design_receipt_reference: str, variance_design_receipt_version: int, variance_design_receipt_digest: str, + variance_method_reference: str, + variance_method_version: int, + variance_evidence_mode: str, + variance_semantics: str, owner_contract_reference: str, owner_contract_version: int, ) -> WeightVarianceAuthorityRecord | None: @@ -551,9 +559,17 @@ def resolve_weight_variance_authority( sampling_receipt_version=sampling_version, sampling_receipt_digest=sampling_digest, analysis_weight_receipt_digest=point_digest, + analytic_case_occurrence_set_digest=case_digest, + weight_eligibility_receipt_digest=eligibility_digest, + weight_correction_sequence=correction_sequence, + final_weight_artifact_digest=final_digest, variance_design_receipt_reference=variance_ref, variance_design_receipt_version=variance_version, variance_design_receipt_digest=variance_digest, + variance_method_reference=method_ref, + variance_method_version=method_version, + variance_evidence_mode=evidence_mode, + variance_semantics=semantics, owner_contract_reference=owner_ref, owner_contract_version=owner_version, ) @@ -650,4 +666,4 @@ def resolve_weight_variance_authority( "superseded_at": record.superseded_at, } fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) - return tuple.__new__(WeightVarianceAuthorityView, (tenant_identity, study_identity, fields)) + return tuple.__new__(WeightVarianceAuthorityView, (tenant_identity, study_identity, fields)) \ No newline at end of file From 95b640d8638d899a9779889856fb387a5debaabe Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 02:04:15 +0900 Subject: [PATCH 185/603] test(workforce-validation): capture complete variance lookup tuple --- .../tests/test_weight_variance_authority.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/services/workforce-validation-api/tests/test_weight_variance_authority.py b/services/workforce-validation-api/tests/test_weight_variance_authority.py index 761aa7fee..d2a4d657f 100644 --- a/services/workforce-validation-api/tests/test_weight_variance_authority.py +++ b/services/workforce-validation-api/tests/test_weight_variance_authority.py @@ -81,9 +81,17 @@ def read_weight_variance_authority( sampling_receipt_version: int, sampling_receipt_digest: str, analysis_weight_receipt_digest: str, + analytic_case_occurrence_set_digest: str, + weight_eligibility_receipt_digest: str, + weight_correction_sequence: int, + final_weight_artifact_digest: str, variance_design_receipt_reference: str, variance_design_receipt_version: int, variance_design_receipt_digest: str, + variance_method_reference: str, + variance_method_version: int, + variance_evidence_mode: str, + variance_semantics: str, owner_contract_reference: str, owner_contract_version: int, ) -> object: @@ -96,9 +104,17 @@ def read_weight_variance_authority( sampling_receipt_version, sampling_receipt_digest, analysis_weight_receipt_digest, + analytic_case_occurrence_set_digest, + weight_eligibility_receipt_digest, + weight_correction_sequence, + final_weight_artifact_digest, variance_design_receipt_reference, variance_design_receipt_version, variance_design_receipt_digest, + variance_method_reference, + variance_method_version, + variance_evidence_mode, + variance_semantics, owner_contract_reference, owner_contract_version, ) @@ -206,9 +222,17 @@ def test_resolution_authorizes_then_returns_owner_corroborated_compatibility() - 3, SAMPLING_DIGEST, ANALYSIS_WEIGHT_DIGEST, + CASE_SET_DIGEST, + ELIGIBILITY_DIGEST, + CORRECTION_SEQUENCE, + FINAL_WEIGHT_DIGEST, VARIANCE_REFERENCE, 5, VARIANCE_DIGEST, + METHOD_REFERENCE, + 2, + "replicate_weights", + "exact", OWNER_REFERENCE, 4, ) From 4a539e36f345c6ac1efc8be4f2fc3156967c5f12 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 02:10:04 +0900 Subject: [PATCH 186/603] test(workforce-validation): require exact final-weight cutover --- ...l_weight_supersession_cutover_alignment.py | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_supersession_cutover_alignment.py diff --git a/services/workforce-validation-api/tests/test_final_weight_supersession_cutover_alignment.py b/services/workforce-validation-api/tests/test_final_weight_supersession_cutover_alignment.py new file mode 100644 index 000000000..9be62aafa --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_supersession_cutover_alignment.py @@ -0,0 +1,46 @@ +"""Require final-weight successor release to be the exact supersession cutover.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.final_weight_supersession_authority import ( + FinalWeightSupersessionAuthorityRecord, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RECEIPT_REFERENCE = "analysis_weight_receipt:11111111-1111-4111-8111-111111111111" +SUCCESSOR_REFERENCE = "analysis_weight_receipt:33333333-3333-4333-8333-333333333333" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +RELEASED_AT = datetime(2026, 7, 15, tzinfo=timezone.utc) +SUPERSEDED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) + + +def test_successor_release_must_equal_final_weight_cutover() -> None: + """Reject an overlap where successor evidence exists before predecessor cutover.""" + with pytest.raises( + ValueError, + match="successor final-weight receipt must be released exactly at supersession", + ): + FinalWeightSupersessionAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + analysis_weight_receipt_reference=RECEIPT_REFERENCE, + analysis_weight_receipt_digest="1" * 64, + evidence_version=1, + correction_sequence=2, + owner_contract_reference=OWNER_CONTRACT_REFERENCE, + owner_contract_version=3, + owner_contract_digest="2" * 64, + owner_contract_released_at=RELEASED_AT - timedelta(days=1), + released_at=RELEASED_AT, + superseded_at=SUPERSEDED_AT, + successor_analysis_weight_receipt_reference=SUCCESSOR_REFERENCE, + successor_correction_sequence=3, + successor_analysis_weight_receipt_digest="3" * 64, + successor_released_at=SUPERSEDED_AT - timedelta(seconds=1), + ) From 7fa44243be9c0e4c0ff40470e011e776d6c03ec9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 02:11:38 +0900 Subject: [PATCH 187/603] fix(workforce-validation): align final-weight cutover with successor release --- .../final_weight_supersession_authority.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py index 5eee6984f..c73ac568a 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py @@ -181,9 +181,9 @@ def __new__( raise ValueError( "successor final-weight receipt must be released after its predecessor." ) - if successor_release > cutover: + if successor_release != cutover: raise ValueError( - "successor final-weight receipt must be released no later than supersession." + "successor final-weight receipt must be released exactly at supersession." ) current_fields: tuple[tuple[str, object], ...] = ( From 3e030d9856aa8ada27a6cb36d539f57a353e9268 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 02:12:03 +0900 Subject: [PATCH 188/603] test(workforce-validation): align final-weight supersession fixtures --- .../tests/test_final_weight_supersession_authority.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/tests/test_final_weight_supersession_authority.py b/services/workforce-validation-api/tests/test_final_weight_supersession_authority.py index de5fe6e91..a85dcba8a 100644 --- a/services/workforce-validation-api/tests/test_final_weight_supersession_authority.py +++ b/services/workforce-validation-api/tests/test_final_weight_supersession_authority.py @@ -148,7 +148,7 @@ def test_historical_use_before_supersession_remains_verifiable_without_leaking_s successor_reference=SUCCESSOR_REFERENCE, successor_correction_sequence=3, successor_digest=SUCCESSOR_DIGEST, - successor_released_at=USED_AT + timedelta(hours=12), + successor_released_at=superseded_at, ) ) @@ -166,7 +166,7 @@ def test_superseded_final_weight_is_not_authoritative_at_or_after_cutover() -> N successor_reference=SUCCESSOR_REFERENCE, successor_correction_sequence=3, successor_digest=SUCCESSOR_DIGEST, - successor_released_at=USED_AT - timedelta(hours=1), + successor_released_at=USED_AT, ) with pytest.raises(FinalWeightSupersessionAuthorityIntegrityError): From 230fa84bab5698af3684c27fe12c35dfc4927304 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 02:15:32 +0900 Subject: [PATCH 189/603] docs(workforce-validation): align correction cutover semantics --- services/workforce-validation-api/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index adcd1ed02..fd32efc28 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -64,13 +64,13 @@ The ordinary final-weight resolver itself now resolves the governing owner-contr ## Final analysis-weight supersession authority -`resolve_final_weight_supersession_authority(...)` closes the point-weight side of #407 RED #10 at the application-owner boundary. A `correction_sequence` plus predecessor digest is not enough to prove that a previously released final-weight receipt stopped being authoritative without in-place mutation. The owner record therefore preserves the predecessor release instant, exclusive supersession instant, and complete released successor coordinates. The successor must have a new receipt reference and digest, advance the correction sequence exactly by one, be released after its predecessor, and already exist no later than the cutover. The released owner contract must predate the predecessor receipt. +`resolve_final_weight_supersession_authority(...)` closes the point-weight side of #407 RED #10 at the application-owner boundary. A `correction_sequence` plus predecessor digest is not enough to prove that a previously released final-weight receipt stopped being authoritative without in-place mutation. The owner record therefore preserves the predecessor release instant, exclusive supersession instant, and complete released successor coordinates. The successor must have a new receipt reference and digest, advance the correction sequence exactly by one, be released after its predecessor, and be released exactly at the predecessor's cutover. The released owner contract must predate the predecessor receipt. -Scientific use is evaluated against the owner-resolved half-open interval `[released_at, superseded_at)`. Historical use inside that interval remains reproducible, while use at or after the cutover fails closed. Successor coordinates are deliberately omitted from the returned view so downstream callers receive only the currently requested receipt authority, not a reusable correction graph. Row-level weights and case identities remain outside this boundary. +Scientific use is evaluated against the owner-resolved half-open interval `[released_at, superseded_at)`. Historical use inside that interval remains reproducible, while use at or after the cutover fails closed. Exact release-at-cutover prevents an overlap or gap in released final-weight authority: predecessor authority ends at the same instant successor authority begins. Successor coordinates are deliberately omitted from the returned view so downstream callers receive only the currently requested receipt authority, not a reusable correction graph. Row-level weights and case identities remain outside this boundary. ## Point-weight / variance authority -`resolve_weight_variance_authority(...)` corroborates released #405 sampling evidence, final analysis-weight receipt, analytic-case occurrence set, weight-eligibility receipt digest, correction sequence, final point-weight artifact, separate #406 variance-design evidence, variance method/evidence semantics, and released owner contract. A variance receipt cannot alias the point-weight receipt, and approximation evidence cannot be represented as exact. The separate eligibility, base-weight, final analysis-weight, and final-weight supersession authorities supply the durable population/duration, selection-probability provenance, complete ordered point-weight lineage, and correction authority interval behind those compatibility coordinates. +`resolve_weight_variance_authority(...)` corroborates released #405 sampling evidence, final analysis-weight receipt, analytic-case occurrence set, weight-eligibility receipt digest, correction sequence, final point-weight artifact, separate #406 variance-design evidence, variance method/evidence semantics, and released owner contract. A variance receipt cannot alias the point-weight receipt, and approximation evidence cannot be represented as exact. The owner read is keyed by this complete compatibility tuple rather than an incomplete prefix, so multiple released bindings that share sampling or receipt identifiers cannot be ambiguously selected. The separate eligibility, base-weight, final analysis-weight, and final-weight supersession authorities supply the durable population/duration, selection-probability provenance, complete ordered point-weight lineage, and correction authority interval behind those compatibility coordinates. The compatibility binding itself now resolves the governing owner-contract release instant and an optional exclusive supersession cutover from canonical owner evidence. Neither is a caller request coordinate. The owner contract must already exist when the compatibility authority is released, and the ordinary resolver enforces the owner-resolved half-open interval `[released_at, superseded_at)`. Historical use before cutover remains reproducible; use at or after cutover fails closed. This prevents a corrected point-weight or variance-design lineage from leaving an older compatibility binding apparently current merely because a consumer bypassed a higher-level correction path. @@ -82,9 +82,9 @@ The binding now also resolves `owner_contract_released_at` and the optional excl ## Validation-result supersession authority -`resolve_validation_result_supersession_authority(...)` closes the released-result side of #407 RED #10. A corrected final weight or recomputed estimate must not leave an earlier released `ValidationAnalysisResult` looking current. The owner record therefore resolves the result release instant, optional exclusive supersession instant, and complete released successor result reference/correction-sequence/digest/release instant. The successor must use a new `validation_analysis_result` reference and digest, advance correction sequence exactly by one, be released after its predecessor, and exist no later than cutover. The released owner contract must already exist when the predecessor result is released. +`resolve_validation_result_supersession_authority(...)` closes the released-result side of #407 RED #10. A corrected final weight or recomputed estimate must not leave an earlier released `ValidationAnalysisResult` looking current. The owner record therefore resolves the result release instant, optional exclusive supersession instant, and complete released successor result reference/correction-sequence/digest/release instant. The successor must use a new `validation_analysis_result` reference and digest, advance correction sequence exactly by one, be released after its predecessor, and be released exactly at the predecessor's cutover. The released owner contract must already exist when the predecessor result is released. -Result authority is the half-open owner-resolved interval `[released_at, superseded_at)`: historical use remains reproducible before cutover and use at or after cutover fails closed. Caller timestamps and mutable result rows do not establish correction authority. Successor coordinates remain internal and are not projected to downstream callers. This family proves the complete append-only successor edge; the ordinary result-binding authority consumes only the owner-resolved release/cutover needed to reject stale use. +Result authority is the half-open owner-resolved interval `[released_at, superseded_at)`: historical use remains reproducible before cutover and use at or after cutover fails closed. Exact release-at-cutover prevents overlap or gap between corrected result authorities. Caller timestamps and mutable result rows do not establish correction authority. Successor coordinates remain internal and are not projected to downstream callers. This family proves the complete append-only successor edge; the ordinary result-binding authority consumes only the owner-resolved release/cutover needed to reject stale use. ## Released non-verifiability outcome @@ -96,7 +96,7 @@ Result authority is the half-open owner-resolved interval `[released_at, superse The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Base-weight source-universe, sampling-design, and owner-contract release instants must come from those durable owner records rather than caller-supplied request coordinates. Eligibility, final-weight, point-weight/variance compatibility, and validation-result owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Low-level eligibility/final-weight/binding adapters must therefore recover the same canonical chronology used by their corresponding correction graph rather than independently infer currentness. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Base-weight source-universe, sampling-design, and owner-contract release instants must come from those durable owner records rather than caller-supplied request coordinates. Eligibility, final-weight, point-weight/variance compatibility, and validation-result owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Low-level eligibility/final-weight/binding adapters must therefore recover the same canonical chronology used by their corresponding correction graph rather than independently infer currentness. Final-weight and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`. ## Test contract @@ -111,6 +111,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology and low-level final-weight currentness, final-weight predecessor/successor correction intervals, point/variance owner-contract chronology and binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology and low-level final-weight currentness, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From b9d76a95e9fac84f4f9a1bc1fb7c8981a9ec6b67 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 03:02:03 +0900 Subject: [PATCH 190/603] test(workforce-validation): require benchmark release at cutover --- .../test_calibration_benchmark_supersession.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py b/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py index 179a80880..28b3fc081 100644 --- a/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py +++ b/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py @@ -151,6 +151,21 @@ def test_historical_use_before_supersession_remains_verifiable_without_leaking_l assert "successor_benchmark_receipt_released_at" not in fields +def test_successor_benchmark_release_must_equal_predecessor_cutover() -> None: + superseded_at = USED_AT + timedelta(days=1) + with pytest.raises( + ValueError, + match="successor benchmark receipt must be released exactly at supersession", + ): + _record( + superseded_at=superseded_at, + successor_reference=SUCCESSOR_REFERENCE, + successor_version=5, + successor_digest=SUCCESSOR_DIGEST, + successor_released_at=superseded_at - timedelta(seconds=1), + ) + + def test_benchmark_receipt_cannot_predate_its_released_owner_contract() -> None: with pytest.raises(ValueError, match="owner contract must be released no later than benchmark receipt"): CalibrationBenchmarkAuthorityRecord( From 884182d704fe4f488c4011ff0e397a1bac3ae375 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 03:03:56 +0900 Subject: [PATCH 191/603] fix(workforce-validation): align benchmark successor release with cutover --- .../orgmetra_workforce_validation_api/benchmark_authority.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py index f994c7072..ac088811e 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py @@ -205,9 +205,9 @@ def __new__( raise ValueError( "successor benchmark receipt must be released after its predecessor." ) - if successor_released_at > superseded_at: + if successor_released_at != superseded_at: raise ValueError( - "successor benchmark receipt must be released no later than supersession." + "successor benchmark receipt must be released exactly at supersession." ) return tuple.__new__( From f68a688cea419d24002d3b5c3e98daa022c123a6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 03:04:30 +0900 Subject: [PATCH 192/603] test(workforce-validation): align benchmark supersession fixtures --- .../tests/test_calibration_benchmark_supersession.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py b/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py index 28b3fc081..72592c977 100644 --- a/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py +++ b/services/workforce-validation-api/tests/test_calibration_benchmark_supersession.py @@ -140,7 +140,7 @@ def test_historical_use_before_supersession_remains_verifiable_without_leaking_l successor_reference=SUCCESSOR_REFERENCE, successor_version=5, successor_digest=SUCCESSOR_DIGEST, - successor_released_at=USED_AT + timedelta(hours=12), + successor_released_at=superseded_at, ) ) @@ -189,7 +189,7 @@ def test_benchmark_superseded_by_scientific_use_is_not_authoritative() -> None: successor_reference=SUCCESSOR_REFERENCE, successor_version=5, successor_digest=SUCCESSOR_DIGEST, - successor_released_at=USED_AT - timedelta(hours=1), + successor_released_at=USED_AT, ) with pytest.raises(CalibrationBenchmarkAuthorityIntegrityError): From 6d3da8903029a325c59d33be009c8422b74cfd8d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 03:05:21 +0900 Subject: [PATCH 193/603] docs(workforce-validation): make benchmark cutover chronology explicit --- services/workforce-validation-api/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index fd32efc28..8e4c67cad 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -26,7 +26,7 @@ Foreign domain truth crosses this boundary only through released/versioned contr ## Calibration benchmark authority -`resolve_calibration_benchmark_authority(...)` corroborates benchmark receipt/version/digest, released benchmark-owner contract, reference/release chronology, and append-only predecessor/successor correction lineage. The owner contract must already be released when the benchmark receipt becomes released evidence; a predecessor is authoritative only on its owner-resolved half-open interval. +`resolve_calibration_benchmark_authority(...)` corroborates benchmark receipt/version/digest, released benchmark-owner contract, reference/release chronology, and append-only predecessor/successor correction lineage. The owner contract must already be released when the benchmark receipt becomes released evidence; a predecessor is authoritative only on its owner-resolved half-open interval `[released_at, superseded_at)`. When a successor exists, its released instant must equal the predecessor cutover exactly, so two released benchmark receipts cannot overlap in authority and no authority gap can appear between them. ## Typed calibration-adjustment authority @@ -96,7 +96,7 @@ Result authority is the half-open owner-resolved interval `[released_at, superse The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Base-weight source-universe, sampling-design, and owner-contract release instants must come from those durable owner records rather than caller-supplied request coordinates. Eligibility, final-weight, point-weight/variance compatibility, and validation-result owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Low-level eligibility/final-weight/binding adapters must therefore recover the same canonical chronology used by their corresponding correction graph rather than independently infer currentness. Final-weight and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Base-weight source-universe, sampling-design, and owner-contract release instants must come from those durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; eligibility, final-weight, point-weight/variance compatibility, and validation-result owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Low-level eligibility/final-weight/binding adapters must therefore recover the same canonical chronology used by their corresponding correction graph rather than independently infer currentness. ## Test contract @@ -111,6 +111,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology and low-level final-weight currentness, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology including exact successor release-at-cutover, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology and low-level final-weight currentness, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From cc8f4108deb1cb0621bd8e5f60c4a39b443edf9a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 03:59:53 +0900 Subject: [PATCH 194/603] test(workforce-validation): expose auxiliary contract chronology RED --- ...ibration_auxiliary_authority_chronology.py | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_auxiliary_authority_chronology.py diff --git a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority_chronology.py b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority_chronology.py new file mode 100644 index 000000000..3855910d9 --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority_chronology.py @@ -0,0 +1,76 @@ +"""Chronology contract for calibration auxiliary-use authority.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from inspect import signature +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.scientific_authority import ( + CalibrationAuxiliaryAuthorityRecord, + resolve_calibration_auxiliary_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000c1") +AUTHORIZED_FROM = datetime(2026, 9, 1, tzinfo=timezone.utc) +AUTHORIZED_TO = datetime(2026, 10, 1, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = AUTHORIZED_FROM - timedelta(days=1) + + +def _record(*, owner_contract_released_at: object) -> CalibrationAuxiliaryAuthorityRecord: + return CalibrationAuxiliaryAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + authority_reference=( + "scientific_auxiliary_authority:11111111-1111-4111-8111-111111111111" + ), + auxiliary_projection_reference=( + "calibration_auxiliary_projection:22222222-2222-4222-8222-222222222222" + ), + auxiliary_projection_version=4, + auxiliary_projection_digest="1" * 64, + scientific_purpose_reference=( + "scientific_data_use_purpose:33333333-3333-4333-8333-333333333333" + ), + scientific_purpose_digest="2" * 64, + owner_contract_reference=( + "released_owner_contract:44444444-4444-4444-8444-444444444444" + ), + owner_contract_version=7, + owner_contract_digest="3" * 64, + owner_contract_released_at=owner_contract_released_at, + authorization_receipt_reference=( + "scientific_data_authorization:55555555-5555-4555-8555-555555555555" + ), + authorization_receipt_digest="4" * 64, + scientific_use_receipt_reference=( + "scientific_use_receipt:66666666-6666-4666-8666-666666666666" + ), + scientific_use_receipt_digest="5" * 64, + scientific_use_at=USED_AT, + authorized_from=AUTHORIZED_FROM, + authorized_to=AUTHORIZED_TO, + ) + + +def test_owner_contract_release_is_owner_evidence_not_a_caller_coordinate() -> None: + assert "owner_contract_released_at" not in signature( + resolve_calibration_auxiliary_authority + ).parameters + + record = _record(owner_contract_released_at=OWNER_CONTRACT_RELEASED_AT) + assert record.owner_contract_released_at == OWNER_CONTRACT_RELEASED_AT + + +def test_owner_contract_cannot_retroactively_authorize_the_interval() -> None: + with pytest.raises(ValueError, match="owner contract must be released no later"): + _record(owner_contract_released_at=AUTHORIZED_FROM + timedelta(seconds=1)) + + +def test_owner_contract_release_requires_timezone_aware_evidence() -> None: + with pytest.raises(ValueError): + _record(owner_contract_released_at=datetime(2026, 8, 31)) From 63fe18bb28c4d22d66b0e669316568c39467fc8f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 04:00:42 +0900 Subject: [PATCH 195/603] fix(workforce-validation): owner-resolve auxiliary contract chronology --- .../scientific_authority.py | 37 ++++++++++++++----- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py index 4845b6528..f0c52e881 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py @@ -46,6 +46,7 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "authorization_receipt_reference", "authorization_receipt_digest", "scientific_use_receipt_reference", @@ -115,6 +116,7 @@ def __new__( owner_contract_reference: str, owner_contract_version: int, owner_contract_digest: str, + owner_contract_released_at: datetime, authorization_receipt_reference: str, authorization_receipt_digest: str, scientific_use_receipt_reference: str, @@ -153,6 +155,9 @@ def __new__( "owner_contract_version", owner_contract_version ) owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + owner_contract_release = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) authorization_ref = _require_reference( "authorization_receipt_reference", authorization_receipt_reference, @@ -176,6 +181,10 @@ def __new__( if authorized_to is None else _require_aware_datetime("authorized_to", authorized_to) ) + if owner_contract_release > authorization_start: + raise ValueError( + "owner contract must be released no later than authorized_from." + ) if authorization_end is not None and authorization_end <= authorization_start: raise ValueError("authorized_to must be later than authorized_from.") if use_instant < authorization_start or ( @@ -198,6 +207,7 @@ def __new__( owner_ref, owner_version, owner_digest, + owner_contract_release, authorization_ref, authorization_digest, scientific_use_ref, @@ -263,40 +273,45 @@ def owner_contract_digest(self) -> str: """Return the immutable bytes digest for the released owner contract.""" return self[10] + @property + def owner_contract_released_at(self) -> datetime: + """Return the owner-resolved contract release instant.""" + return self[11] + @property def authorization_receipt_reference(self) -> str: """Return the authoritative scientific-use authorization receipt reference.""" - return self[11] + return self[12] @property def authorization_receipt_digest(self) -> str: """Return the authorization receipt digest used for exact correlation.""" - return self[12] + return self[13] @property def scientific_use_receipt_reference(self) -> str: """Return the immutable scientific-use receipt reference.""" - return self[13] + return self[14] @property def scientific_use_receipt_digest(self) -> str: """Return the immutable scientific-use receipt digest.""" - return self[14] + return self[15] @property def scientific_use_at(self) -> datetime: """Return the owner-resolved UTC instant for the exact scientific use.""" - return self[15] + return self[16] @property def authorized_from(self) -> datetime: """Return the UTC instant when this scientific use became authorized.""" - return self[16] + return self[17] @property def authorized_to(self) -> datetime | None: """Return the exclusive UTC authorization end when one exists.""" - return self[17] + return self[18] class CalibrationAuxiliaryAuthorityView(tuple): @@ -394,8 +409,10 @@ def resolve_calibration_auxiliary_authority( same function is invoked afterward. The request carries no protected source values. Owner evidence must reproduce every caller-supplied leaf coordinate, including the projection reference/version/digest, receipt references and the - released owner-contract digest, and independently bind the scientific-use - receipt to the same use instant before any corroborating fields are returned. + released owner-contract digest. The owner contract release instant is resolved + only from owner evidence and must not postdate the authorization interval start. + The scientific-use receipt is independently bound to the same use instant + before any corroborating fields are returned. """ if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") @@ -520,6 +537,7 @@ def resolve_calibration_auxiliary_authority( owner_contract_reference=persisted.owner_contract_reference, owner_contract_version=persisted.owner_contract_version, owner_contract_digest=persisted.owner_contract_digest, + owner_contract_released_at=persisted.owner_contract_released_at, authorization_receipt_reference=persisted.authorization_receipt_reference, authorization_receipt_digest=persisted.authorization_receipt_digest, scientific_use_receipt_reference=persisted.scientific_use_receipt_reference, @@ -562,6 +580,7 @@ def resolve_calibration_auxiliary_authority( "owner_contract_reference": record.owner_contract_reference, "owner_contract_version": record.owner_contract_version, "owner_contract_digest": record.owner_contract_digest, + "owner_contract_released_at": record.owner_contract_released_at, "authorization_receipt_reference": record.authorization_receipt_reference, "authorization_receipt_digest": record.authorization_receipt_digest, "scientific_use_receipt_reference": record.scientific_use_receipt_reference, From 8474826ccf19078b23a9cb0886e0594e019f51ef Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 04:01:16 +0900 Subject: [PATCH 196/603] test(workforce-validation): cover auxiliary contract release evidence --- .../tests/test_calibration_auxiliary_authority.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py index d87909eb2..dbafd1b9b 100644 --- a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py +++ b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py @@ -46,6 +46,7 @@ OWNER_CONTRACT_DIGEST = "3" * 64 AUTHORIZATION_DIGEST = "4" * 64 SCIENTIFIC_USE_DIGEST = "5" * 64 +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 8, 31, tzinfo=timezone.utc) AUTHORIZED_FROM = datetime(2026, 9, 1, tzinfo=timezone.utc) AUTHORIZED_TO = datetime(2026, 10, 1, tzinfo=timezone.utc) USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) @@ -60,6 +61,7 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "authorization_receipt_reference", "authorization_receipt_digest", "scientific_use_receipt_reference", @@ -169,6 +171,7 @@ def _record(**overrides: object) -> CalibrationAuxiliaryAuthorityRecord: "owner_contract_reference": OWNER_CONTRACT_REFERENCE, "owner_contract_version": 7, "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, "authorization_receipt_reference": AUTHORIZATION_REFERENCE, "authorization_receipt_digest": AUTHORIZATION_DIGEST, "scientific_use_receipt_reference": SCIENTIFIC_USE_REFERENCE, @@ -246,6 +249,7 @@ def test_resolution_authorizes_then_returns_minimized_corroborated_evidence() -> ("auxiliary_projection_version", PROJECTION_VERSION), ("owner_contract_digest", OWNER_CONTRACT_DIGEST), ("owner_contract_reference", OWNER_CONTRACT_REFERENCE), + ("owner_contract_released_at", OWNER_CONTRACT_RELEASED_AT), ("owner_contract_version", 7), ("scientific_purpose_digest", PURPOSE_DIGEST), ("scientific_purpose_reference", PURPOSE_REFERENCE), @@ -423,6 +427,7 @@ def test_invalid_request_or_dependency_fails_before_owner_resolution( ("owner_contract_reference", "wrong:contract"), ("owner_contract_version", 0), ("owner_contract_digest", "3" * 63), + ("owner_contract_released_at", datetime(2026, 8, 31)), ("authorization_receipt_reference", "wrong:authorization"), ("authorization_receipt_digest", "4" * 63), ("scientific_use_receipt_reference", "wrong:use"), From 601a15d7214f8b7a80116ad94d12f2b8bd9baf7d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 04:01:52 +0900 Subject: [PATCH 197/603] docs(workforce-validation): record auxiliary contract chronology --- services/workforce-validation-api/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 8e4c67cad..d12ae5a48 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -22,7 +22,7 @@ Foreign domain truth crosses this boundary only through released/versioned contr ## Calibration auxiliary authority -`resolve_calibration_auxiliary_authority(...)` corroborates #407's purpose-limited calibration input without copying protected source attributes. It binds auxiliary authority and projection coordinates, scientific-use purpose, released owner contract, authorization receipt/interval, and scientific-use receipt/instant. Caller `used_at` must equal the owner-resolved scientific-use instant, and that instant must fall inside the owner-resolved authorization interval. +`resolve_calibration_auxiliary_authority(...)` corroborates #407's purpose-limited calibration input without copying protected source attributes. It binds auxiliary authority and projection coordinates, scientific-use purpose, released owner contract, authorization receipt/interval, and scientific-use receipt/instant. The governing owner-contract release instant is owner-resolved evidence rather than a caller coordinate, must be timezone-aware, and must be no later than `authorized_from`; this prevents a later contract from retroactively creating an earlier scientific-use authorization interval. Caller `used_at` must equal the owner-resolved scientific-use instant, and that instant must fall inside the owner-resolved authorization interval. ## Calibration benchmark authority @@ -96,7 +96,7 @@ Result authority is the half-open owner-resolved interval `[released_at, superse The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Base-weight source-universe, sampling-design, and owner-contract release instants must come from those durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; eligibility, final-weight, point-weight/variance compatibility, and validation-result owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Low-level eligibility/final-weight/binding adapters must therefore recover the same canonical chronology used by their corresponding correction graph rather than independently infer currentness. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; eligibility, final-weight, point-weight/variance compatibility, and validation-result owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Low-level eligibility/final-weight/binding adapters must therefore recover the same canonical chronology used by their corresponding correction graph rather than independently infer currentness. ## Test contract @@ -111,6 +111,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, benchmark correction chronology including exact successor release-at-cutover, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology and low-level final-weight currentness, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology and low-level final-weight currentness, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From 56b0e112373ec9f0f16357c3fecaa7079e5dba50 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:00:36 +0900 Subject: [PATCH 198/603] test(workforce-validation): expose calibration contract chronology gap --- ...on_adjustment_owner_contract_chronology.py | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_adjustment_owner_contract_chronology.py diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_owner_contract_chronology.py b/services/workforce-validation-api/tests/test_calibration_adjustment_owner_contract_chronology.py new file mode 100644 index 000000000..6e6167dd7 --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_owner_contract_chronology.py @@ -0,0 +1,82 @@ +"""Fail closed when calibration-adjustment owner contracts are retroactive.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from inspect import signature +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.calibration_adjustment_authority import ( + CalibrationAdjustmentAuthorityRecord, + resolve_calibration_adjustment_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +CONSTRUCTED_AT = datetime(2026, 9, 16, 12, 0, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 16, 12, 30, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc) + + +def _record(**overrides: object) -> CalibrationAdjustmentAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "calibration_receipt_reference": ( + "calibration_adjustment_receipt:11111111-1111-4111-8111-111111111111" + ), + "calibration_receipt_digest": "1" * 64, + "evidence_version": 1, + "auxiliary_projection_digest": "2" * 64, + "benchmark_receipt_digest": "3" * 64, + "algorithm_reference": "calibration_algorithm:raking", + "algorithm_version": 2, + "constraints_digest": "4" * 64, + "termination_code": "converged", + "input_weight_artifact_digest": "5" * 64, + "output_weight_artifact_digest": "6" * 64, + "constructed_at": CONSTRUCTED_AT, + "fallback_reason_code": None, + "fallback_rule_reference": None, + "fallback_rule_digest": None, + "fallback_algorithm_reference": None, + "fallback_algorithm_version": None, + "fallback_configuration_digest": None, + "owner_contract_reference": ( + "released_owner_contract:33333333-3333-4333-8333-333333333333" + ), + "owner_contract_version": 5, + "owner_contract_digest": "7" * 64, + "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, + "released_at": RELEASED_AT, + } + values.update(overrides) + return CalibrationAdjustmentAuthorityRecord(**values) + + +def test_owner_contract_release_is_owner_resolved_not_a_request_coordinate() -> None: + assert "owner_contract_released_at" not in signature( + resolve_calibration_adjustment_authority + ).parameters + + +def test_owner_contract_must_exist_before_calibration_receipt_release() -> None: + with pytest.raises(ValueError, match="owner_contract_released_at"): + _record( + owner_contract_released_at=datetime( + 2026, 9, 16, 13, 0, 1, tzinfo=timezone.utc + ) + ) + + +def test_owner_contract_release_requires_timezone_aware_evidence() -> None: + with pytest.raises(ValueError): + _record(owner_contract_released_at=datetime(2026, 9, 16, 12, 30)) + + +def test_contract_released_after_construction_but_before_receipt_release_is_valid() -> None: + record = _record() + assert record.owner_contract_released_at == OWNER_CONTRACT_RELEASED_AT + assert record.released_at == RELEASED_AT From 211d10e60189fb770e893c563875994c81ec82d7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:01:24 +0900 Subject: [PATCH 199/603] fix(workforce-validation): bind calibration contract chronology --- .../calibration_adjustment_authority.py | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py index bc6773e45..310bf48d5 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py @@ -61,6 +61,7 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "released_at", } ) @@ -112,6 +113,7 @@ def __new__( owner_contract_reference: str, owner_contract_version: int, owner_contract_digest: str, + owner_contract_released_at: datetime, released_at: datetime, ) -> CalibrationAdjustmentAuthorityRecord: """Validate and detach the minimum receipt-level scientific authority.""" @@ -203,9 +205,16 @@ def __new__( "owner_contract_version", owner_contract_version ) owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + owner_released = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) release_instant = _require_aware_datetime("released_at", released_at) if release_instant < constructed: raise ValueError("released_at cannot precede constructed_at.") + if owner_released > release_instant: + raise ValueError( + "owner_contract_released_at cannot be later than released_at." + ) return tuple.__new__( cls, @@ -233,6 +242,7 @@ def __new__( owner_ref, owner_version, owner_digest, + owner_released, release_instant, ), ) @@ -352,10 +362,15 @@ def owner_contract_digest(self) -> str: """Return the released owner-contract digest.""" return self[22] + @property + def owner_contract_released_at(self) -> datetime: + """Return when the governing owner contract became released authority.""" + return self[23] + @property def released_at(self) -> datetime: """Return when this typed calibration evidence became released authority.""" - return self[23] + return self[24] class CalibrationAdjustmentAuthorityView(tuple): @@ -432,6 +447,11 @@ def read_calibration_adjustment_authority( ) +def _coordinate_tuple(record: CalibrationAdjustmentAuthorityRecord) -> tuple[object, ...]: + """Return caller-known coordinates, excluding owner-resolved release instants.""" + return record[:23] + + def resolve_calibration_adjustment_authority( *, principal: ValidationPrincipal, @@ -509,6 +529,7 @@ def resolve_calibration_adjustment_authority( owner_contract_reference=owner_contract_reference, owner_contract_version=owner_contract_version, owner_contract_digest=owner_contract_digest, + owner_contract_released_at=constructed_at, released_at=constructed_at, ) tenant_id = requested.tenant_record_id @@ -590,11 +611,10 @@ def resolve_calibration_adjustment_authority( owner_contract_reference=persisted.owner_contract_reference, owner_contract_version=persisted.owner_contract_version, owner_contract_digest=persisted.owner_contract_digest, + owner_contract_released_at=persisted.owner_contract_released_at, released_at=persisted.released_at, ) - expected = requested[:-1] - observed = record[:-1] - if observed != expected: + if _coordinate_tuple(record) != _coordinate_tuple(requested): raise CalibrationAdjustmentAuthorityIntegrityError( "released calibration-adjustment authority does not match requested coordinates" ) @@ -617,6 +637,7 @@ def resolve_calibration_adjustment_authority( ("output_weight_artifact_digest", record.output_weight_artifact_digest), ("owner_contract_digest", record.owner_contract_digest), ("owner_contract_reference", record.owner_contract_reference), + ("owner_contract_released_at", record.owner_contract_released_at), ("owner_contract_version", record.owner_contract_version), ("released_at", record.released_at), ("termination_code", record.termination_code), From 94421747d833c2c5e6c429d6d0808053c38d77fc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:02:16 +0900 Subject: [PATCH 200/603] test(workforce-validation): align calibration chronology fixtures --- .../tests/test_calibration_adjustment_authority.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py b/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py index 78995a6e2..29bc0f56a 100644 --- a/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py @@ -34,6 +34,7 @@ FALLBACK_CONFIGURATION_DIGEST = "8" * 64 OWNER_CONTRACT_DIGEST = "9" * 64 CONSTRUCTED_AT = datetime(2026, 9, 16, 12, 0, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 16, 12, 30, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc) USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) READ_FIELDS = frozenset( @@ -59,6 +60,7 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "released_at", } ) @@ -150,6 +152,7 @@ def _record(**overrides: object) -> CalibrationAdjustmentAuthorityRecord: "owner_contract_reference": OWNER_CONTRACT_REFERENCE, "owner_contract_version": 6, "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, "released_at": RELEASED_AT, } values.update(overrides) @@ -210,6 +213,7 @@ def test_fallback_resolution_binds_actual_generating_method() -> None: assert ("fallback_algorithm_reference", "calibration_algorithm:raking") in view.fields assert ("fallback_algorithm_version", 4) in view.fields assert ("fallback_configuration_digest", FALLBACK_CONFIGURATION_DIGEST) in view.fields + assert ("owner_contract_released_at", OWNER_CONTRACT_RELEASED_AT) in view.fields def test_converged_resolution_omits_fallback_only_projection() -> None: From cf86f9ba13f214eaa611c041f6e7b19c30f1b6c6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:08:06 +0900 Subject: [PATCH 201/603] test(workforce-validation): expose nonresponse contract chronology gap --- ...se_adjustment_owner_contract_chronology.py | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_nonresponse_adjustment_owner_contract_chronology.py diff --git a/services/workforce-validation-api/tests/test_nonresponse_adjustment_owner_contract_chronology.py b/services/workforce-validation-api/tests/test_nonresponse_adjustment_owner_contract_chronology.py new file mode 100644 index 000000000..de72f9820 --- /dev/null +++ b/services/workforce-validation-api/tests/test_nonresponse_adjustment_owner_contract_chronology.py @@ -0,0 +1,84 @@ +"""Fail closed when nonresponse-adjustment owner contracts are retroactive.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from inspect import signature +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.nonresponse_adjustment_authority import ( + NonresponseAdjustmentAuthorityRecord, + resolve_nonresponse_adjustment_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +DISPOSITION_RELEASED_AT = datetime(2026, 9, 16, 10, 0, tzinfo=timezone.utc) +CONSTRUCTED_AT = datetime(2026, 9, 16, 12, 0, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 16, 12, 30, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc) + + +def _record(**overrides: object) -> NonresponseAdjustmentAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "nonresponse_receipt_reference": ( + "nonresponse_adjustment_receipt:11111111-1111-4111-8111-111111111111" + ), + "nonresponse_receipt_digest": "1" * 64, + "evidence_version": 1, + "response_disposition_receipt_reference": ( + "response_disposition_receipt:22222222-2222-4222-8222-222222222222" + ), + "response_disposition_receipt_version": 4, + "response_disposition_receipt_digest": "2" * 64, + "response_disposition_receipt_released_at": DISPOSITION_RELEASED_AT, + "adjustment_population_digest": "3" * 64, + "method_reference": "weight_method:response_propensity_cells", + "method_version": 3, + "configuration_digest": "4" * 64, + "ineligible_treatment_code": "exclude_ineligible", + "unknown_treatment_code": "retain_unknown_class", + "unavailable_treatment_code": "retain_unavailable_class", + "input_weight_artifact_digest": "5" * 64, + "output_weight_artifact_digest": "6" * 64, + "constructed_at": CONSTRUCTED_AT, + "owner_contract_reference": ( + "released_owner_contract:33333333-3333-4333-8333-333333333333" + ), + "owner_contract_version": 5, + "owner_contract_digest": "7" * 64, + "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, + "released_at": RELEASED_AT, + } + values.update(overrides) + return NonresponseAdjustmentAuthorityRecord(**values) + + +def test_owner_contract_release_is_owner_resolved_not_a_request_coordinate() -> None: + assert "owner_contract_released_at" not in signature( + resolve_nonresponse_adjustment_authority + ).parameters + + +def test_owner_contract_must_exist_before_nonresponse_receipt_release() -> None: + with pytest.raises(ValueError, match="owner_contract_released_at"): + _record( + owner_contract_released_at=datetime( + 2026, 9, 16, 13, 0, 1, tzinfo=timezone.utc + ) + ) + + +def test_owner_contract_release_requires_timezone_aware_evidence() -> None: + with pytest.raises(ValueError): + _record(owner_contract_released_at=datetime(2026, 9, 16, 12, 30)) + + +def test_contract_released_after_construction_but_before_receipt_release_is_valid() -> None: + record = _record() + assert record.owner_contract_released_at == OWNER_CONTRACT_RELEASED_AT + assert record.released_at == RELEASED_AT From 08d4698cd12c4f9d2daaddb21ab79e82a02c07f4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:08:51 +0900 Subject: [PATCH 202/603] fix(workforce-validation): bind nonresponse contract chronology --- .../nonresponse_adjustment_authority.py | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py index dc9dc2204..07ef9542d 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py @@ -59,6 +59,7 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "released_at", } ) @@ -102,6 +103,7 @@ def __new__( owner_contract_reference: str, owner_contract_version: int, owner_contract_digest: str, + owner_contract_released_at: datetime, released_at: datetime, ) -> NonresponseAdjustmentAuthorityRecord: """Validate and detach the minimum disposition-aware scientific authority.""" @@ -170,9 +172,16 @@ def __new__( "owner_contract_version", owner_contract_version ) owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + owner_released = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) release_instant = _require_aware_datetime("released_at", released_at) if release_instant < constructed: raise ValueError("released_at cannot precede constructed_at.") + if owner_released > release_instant: + raise ValueError( + "owner_contract_released_at cannot be later than released_at." + ) return tuple.__new__( cls, @@ -199,6 +208,7 @@ def __new__( owner_ref, owner_version, owner_digest, + owner_released, release_instant, ), ) @@ -313,10 +323,15 @@ def owner_contract_digest(self) -> str: """Return the released owner-contract digest.""" return self[21] + @property + def owner_contract_released_at(self) -> datetime: + """Return when the governing owner contract became released authority.""" + return self[22] + @property def released_at(self) -> datetime: """Return when this typed nonresponse evidence became released authority.""" - return self[22] + return self[23] class NonresponseAdjustmentAuthorityView(tuple): @@ -466,6 +481,7 @@ def resolve_nonresponse_adjustment_authority( owner_contract_reference=owner_contract_reference, owner_contract_version=owner_contract_version, owner_contract_digest=owner_contract_digest, + owner_contract_released_at=constructed, released_at=constructed, ) tenant_id = requested.tenant_record_id @@ -549,6 +565,7 @@ def resolve_nonresponse_adjustment_authority( owner_contract_reference=persisted.owner_contract_reference, owner_contract_version=persisted.owner_contract_version, owner_contract_digest=persisted.owner_contract_digest, + owner_contract_released_at=persisted.owner_contract_released_at, released_at=persisted.released_at, ) if _coordinate_tuple(record) != _coordinate_tuple(requested): @@ -574,6 +591,7 @@ def resolve_nonresponse_adjustment_authority( ("output_weight_artifact_digest", record.output_weight_artifact_digest), ("owner_contract_digest", record.owner_contract_digest), ("owner_contract_reference", record.owner_contract_reference), + ("owner_contract_released_at", record.owner_contract_released_at), ("owner_contract_version", record.owner_contract_version), ("released_at", record.released_at), ("response_disposition_receipt_digest", record.response_disposition_receipt_digest), From 7a02a58706cbac11beaedad1ddea89b5c5071453 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:13:31 +0900 Subject: [PATCH 203/603] test(workforce-validation): align nonresponse chronology fixtures --- .../tests/test_nonresponse_adjustment_authority.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority.py b/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority.py index f413ec0a6..644ba659b 100644 --- a/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority.py +++ b/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority.py @@ -34,6 +34,7 @@ OWNER_CONTRACT_DIGEST = "7" * 64 DISPOSITION_RELEASED_AT = datetime(2026, 9, 16, 10, 0, tzinfo=timezone.utc) CONSTRUCTED_AT = datetime(2026, 9, 16, 12, 0, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 16, 12, 30, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc) USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) READ_FIELDS = frozenset( @@ -58,6 +59,7 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "released_at", } ) @@ -136,6 +138,7 @@ def _record(**overrides: object) -> NonresponseAdjustmentAuthorityRecord: "owner_contract_reference": OWNER_CONTRACT_REFERENCE, "owner_contract_version": 5, "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, "released_at": RELEASED_AT, } values.update(overrides) @@ -192,6 +195,7 @@ def test_resolution_binds_versioned_disposition_and_treatment_evidence() -> None assert ("unknown_treatment_code", "retain_unknown_class") in view.fields assert ("unavailable_treatment_code", "retain_unavailable_class") in view.fields assert ("response_disposition_receipt_released_at", DISPOSITION_RELEASED_AT) in view.fields + assert ("owner_contract_released_at", OWNER_CONTRACT_RELEASED_AT) in view.fields def test_authorization_denial_happens_before_owner_resolution() -> None: From ddfb3d823746027e764d7dd5092dc2efc2f0d557 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:19:45 +0900 Subject: [PATCH 204/603] test(workforce-validation): expose trimming contract chronology gap --- ...ming_bounding_owner_contract_chronology.py | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_trimming_bounding_owner_contract_chronology.py diff --git a/services/workforce-validation-api/tests/test_trimming_bounding_owner_contract_chronology.py b/services/workforce-validation-api/tests/test_trimming_bounding_owner_contract_chronology.py new file mode 100644 index 000000000..ba18edb4a --- /dev/null +++ b/services/workforce-validation-api/tests/test_trimming_bounding_owner_contract_chronology.py @@ -0,0 +1,75 @@ +"""Fail closed when trimming/bounding owner contracts are retroactive.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from inspect import signature +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.trimming_bounding_authority import ( + TrimmingBoundingAuthorityRecord, + resolve_trimming_bounding_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +CONSTRUCTED_AT = datetime(2026, 9, 16, 12, 0, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 16, 12, 30, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc) + + +def _record(**overrides: object) -> TrimmingBoundingAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "adjustment_receipt_reference": ( + "trimming_bounding_adjustment_receipt:11111111-1111-4111-8111-111111111111" + ), + "adjustment_receipt_digest": "1" * 64, + "evidence_version": 1, + "rule_reference": "weight_trimming_rule:winsor-p995-v1", + "rule_version": 2, + "rule_configuration_digest": "2" * 64, + "affected_case_occurrence_set_digest": "3" * 64, + "affected_case_count": 17, + "input_weight_artifact_digest": "4" * 64, + "output_weight_artifact_digest": "5" * 64, + "constructed_at": CONSTRUCTED_AT, + "owner_contract_reference": ( + "released_owner_contract:22222222-2222-4222-8222-222222222222" + ), + "owner_contract_version": 3, + "owner_contract_digest": "6" * 64, + "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, + "released_at": RELEASED_AT, + } + values.update(overrides) + return TrimmingBoundingAuthorityRecord(**values) + + +def test_owner_contract_release_is_owner_resolved_not_a_request_coordinate() -> None: + assert "owner_contract_released_at" not in signature( + resolve_trimming_bounding_authority + ).parameters + + +def test_owner_contract_must_exist_before_adjustment_receipt_release() -> None: + with pytest.raises(ValueError, match="owner_contract_released_at"): + _record( + owner_contract_released_at=datetime( + 2026, 9, 16, 13, 0, 1, tzinfo=timezone.utc + ) + ) + + +def test_owner_contract_release_requires_timezone_aware_evidence() -> None: + with pytest.raises(ValueError): + _record(owner_contract_released_at=datetime(2026, 9, 16, 12, 30)) + + +def test_contract_released_after_construction_but_before_receipt_release_is_valid() -> None: + record = _record() + assert record.owner_contract_released_at == OWNER_CONTRACT_RELEASED_AT + assert record.released_at == RELEASED_AT From 0290d9b0d4930159c7baf60491adc764ef526cb1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:20:20 +0900 Subject: [PATCH 205/603] fix(workforce-validation): bind trimming contract chronology --- .../trimming_bounding_authority.py | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py index d5dc58fe8..57376d986 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py @@ -51,6 +51,7 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "released_at", } ) @@ -88,6 +89,7 @@ def __new__( owner_contract_reference: str, owner_contract_version: int, owner_contract_digest: str, + owner_contract_released_at: datetime, released_at: datetime, ) -> TrimmingBoundingAuthorityRecord: """Validate and detach the minimum immutable trimming authority.""" @@ -136,9 +138,16 @@ def __new__( "owner_contract_version", owner_contract_version ) owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + owner_released = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) release_instant = _require_aware_datetime("released_at", released_at) if release_instant < constructed: raise ValueError("released_at cannot precede constructed_at.") + if owner_released > release_instant: + raise ValueError( + "owner_contract_released_at cannot be later than released_at." + ) return tuple.__new__( cls, ( @@ -158,6 +167,7 @@ def __new__( owner_ref, owner_version, owner_digest, + owner_released, release_instant, ), ) @@ -242,10 +252,15 @@ def owner_contract_digest(self) -> str: """Return the released owner-contract digest.""" return self[15] + @property + def owner_contract_released_at(self) -> datetime: + """Return when the governing owner contract became released authority.""" + return self[16] + @property def released_at(self) -> datetime: """Return when this adjustment became released authority.""" - return self[16] + return self[17] class TrimmingBoundingAuthorityView(tuple): @@ -315,6 +330,11 @@ def read_trimming_bounding_authority( ) +def _coordinate_tuple(record: TrimmingBoundingAuthorityRecord) -> tuple[object, ...]: + """Return caller-known coordinates, excluding owner-resolved release instants.""" + return record[:16] + + def resolve_trimming_bounding_authority( *, principal: ValidationPrincipal, @@ -370,6 +390,7 @@ def resolve_trimming_bounding_authority( owner_contract_reference=owner_contract_reference, owner_contract_version=owner_contract_version, owner_contract_digest=owner_contract_digest, + owner_contract_released_at=constructed_at, released_at=constructed_at, ) tenant_id = requested.tenant_record_id @@ -442,9 +463,10 @@ def resolve_trimming_bounding_authority( owner_contract_reference=persisted.owner_contract_reference, owner_contract_version=persisted.owner_contract_version, owner_contract_digest=persisted.owner_contract_digest, + owner_contract_released_at=persisted.owner_contract_released_at, released_at=persisted.released_at, ) - if record[:-1] != requested[:-1]: + if _coordinate_tuple(record) != _coordinate_tuple(requested): raise TrimmingBoundingAuthorityIntegrityError( "released trimming/bounding authority does not match requested coordinates" ) @@ -464,6 +486,7 @@ def resolve_trimming_bounding_authority( ("output_weight_artifact_digest", record.output_weight_artifact_digest), ("owner_contract_digest", record.owner_contract_digest), ("owner_contract_reference", record.owner_contract_reference), + ("owner_contract_released_at", record.owner_contract_released_at), ("owner_contract_version", record.owner_contract_version), ("released_at", record.released_at), ("rule_configuration_digest", record.rule_configuration_digest), From 9a90d5b4c38300bfd0bf4c2132f63eb351ba84aa Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:20:46 +0900 Subject: [PATCH 206/603] test(workforce-validation): align trimming chronology fixtures --- .../tests/test_trimming_bounding_authority.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/services/workforce-validation-api/tests/test_trimming_bounding_authority.py b/services/workforce-validation-api/tests/test_trimming_bounding_authority.py index fb4bc82c9..af71f3b8d 100644 --- a/services/workforce-validation-api/tests/test_trimming_bounding_authority.py +++ b/services/workforce-validation-api/tests/test_trimming_bounding_authority.py @@ -32,6 +32,7 @@ OUTPUT_WEIGHT_DIGEST = "5" * 64 OWNER_CONTRACT_DIGEST = "6" * 64 CONSTRUCTED_AT = datetime(2026, 9, 16, 12, 0, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 16, 12, 30, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc) USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) READ_FIELDS = frozenset( @@ -50,6 +51,7 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "released_at", } ) @@ -122,6 +124,7 @@ def _record(**overrides: object) -> TrimmingBoundingAuthorityRecord: "owner_contract_reference": OWNER_CONTRACT_REFERENCE, "owner_contract_version": 3, "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, "released_at": RELEASED_AT, } values.update(overrides) @@ -172,6 +175,7 @@ def test_resolution_binds_rule_affected_cases_and_artifact_lineage() -> None: assert ("affected_case_count", 17) in view.fields assert ("affected_case_occurrence_set_digest", AFFECTED_CASE_SET_DIGEST) in view.fields assert ("output_weight_artifact_digest", OUTPUT_WEIGHT_DIGEST) in view.fields + assert ("owner_contract_released_at", OWNER_CONTRACT_RELEASED_AT) in view.fields def test_authorization_denial_happens_before_owner_resolution() -> None: From e14fe6271780065fe2f52cec512ef29d51d400b0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:21:02 +0900 Subject: [PATCH 207/603] test(workforce-validation): cover trimming owner chronology edge --- .../tests/test_trimming_bounding_authority_edges.py | 1 + 1 file changed, 1 insertion(+) diff --git a/services/workforce-validation-api/tests/test_trimming_bounding_authority_edges.py b/services/workforce-validation-api/tests/test_trimming_bounding_authority_edges.py index b215703c7..2ec9a17fe 100644 --- a/services/workforce-validation-api/tests/test_trimming_bounding_authority_edges.py +++ b/services/workforce-validation-api/tests/test_trimming_bounding_authority_edges.py @@ -32,6 +32,7 @@ def _record(*, evidence_version: object = 1) -> TrimmingBoundingAuthorityRecord: ), owner_contract_version=3, owner_contract_digest="6" * 64, + owner_contract_released_at=datetime(2026, 9, 16, 12, 30, tzinfo=timezone.utc), released_at=datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc), ) From 3439e765460ccd406a0b0a83afef49f80fdbae09 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:21:21 +0900 Subject: [PATCH 208/603] test(workforce-validation): expose nonverifiability contract chronology gap --- ...verifiability_owner_contract_chronology.py | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_owner_contract_chronology.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_owner_contract_chronology.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_owner_contract_chronology.py new file mode 100644 index 000000000..874c8bef5 --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_owner_contract_chronology.py @@ -0,0 +1,76 @@ +"""Fail closed when non-verifiability owner contracts are retroactive.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from inspect import signature +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.result_nonverifiability import ( + ValidationResultNonVerifiabilityRecord, + resolve_validation_result_nonverifiability, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 17, 5, 55, tzinfo=timezone.utc) +EVALUATED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 6, 5, tzinfo=timezone.utc) + + +def _record(**overrides: object) -> ValidationResultNonVerifiabilityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "result_reference": ( + "validation_analysis_result:11111111-1111-4111-8111-111111111111" + ), + "result_digest": "1" * 64, + "failed_evidence_kind": "analysis_weight_receipt", + "failure_mode": "missing", + "failed_evidence_reference": None, + "failed_evidence_digest": None, + "verification_attempt_reference": ( + "validation_evidence_verification_attempt:" + "33333333-3333-4333-8333-333333333333" + ), + "verification_attempt_digest": "3" * 64, + "owner_contract_reference": ( + "released_owner_contract:44444444-4444-4444-8444-444444444444" + ), + "owner_contract_version": 7, + "owner_contract_digest": "4" * 64, + "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, + "evaluated_at": EVALUATED_AT, + "released_at": RELEASED_AT, + } + values.update(overrides) + return ValidationResultNonVerifiabilityRecord(**values) + + +def test_owner_contract_release_is_owner_resolved_not_a_request_coordinate() -> None: + assert "owner_contract_released_at" not in signature( + resolve_validation_result_nonverifiability + ).parameters + + +def test_owner_contract_must_exist_before_verification_evaluation() -> None: + with pytest.raises(ValueError, match="owner_contract_released_at"): + _record( + owner_contract_released_at=datetime( + 2026, 9, 17, 6, 0, 1, tzinfo=timezone.utc + ) + ) + + +def test_owner_contract_release_requires_timezone_aware_evidence() -> None: + with pytest.raises(ValueError): + _record(owner_contract_released_at=datetime(2026, 9, 17, 5, 55)) + + +def test_owner_contract_can_be_released_immediately_before_evaluation() -> None: + record = _record() + assert record.owner_contract_released_at == OWNER_CONTRACT_RELEASED_AT + assert record.evaluated_at == EVALUATED_AT From 9a4df1018e6949ad3af40ef5746de425557144ff Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:21:57 +0900 Subject: [PATCH 209/603] fix(workforce-validation): bind nonverifiability contract chronology --- .../result_nonverifiability.py | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py index 705eea960..5732a11df 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py @@ -58,6 +58,7 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "evaluated_at", "released_at", } @@ -110,6 +111,7 @@ def __new__( owner_contract_reference: str, owner_contract_version: int, owner_contract_digest: str, + owner_contract_released_at: datetime, evaluated_at: datetime, released_at: datetime, ) -> ValidationResultNonVerifiabilityRecord: @@ -163,6 +165,9 @@ def __new__( "owner_contract_version", owner_contract_version ) owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + owner_released = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) digests = [result_evidence_digest, attempt_digest, owner_digest] if failed_digest is not None: @@ -175,6 +180,10 @@ def __new__( evaluation_instant = _require_aware_datetime("evaluated_at", evaluated_at) release_instant = _require_aware_datetime("released_at", released_at) + if owner_released > evaluation_instant: + raise ValueError( + "owner_contract_released_at cannot be later than evaluated_at." + ) if evaluation_instant > release_instant: raise ValueError("evaluated_at cannot be later than released_at.") @@ -194,6 +203,7 @@ def __new__( owner_ref, owner_version, owner_digest, + owner_released, evaluation_instant, release_instant, ), @@ -269,15 +279,20 @@ def owner_contract_digest(self) -> str: """Return the immutable released owner-contract digest.""" return self[12] + @property + def owner_contract_released_at(self) -> datetime: + """Return when the governing owner contract became released authority.""" + return self[13] + @property def evaluated_at(self) -> datetime: """Return when the evidence-verification attempt was evaluated.""" - return self[13] + return self[14] @property def released_at(self) -> datetime: """Return when this non-verifiability outcome became released evidence.""" - return self[14] + return self[15] class ValidationResultNonVerifiabilityView(tuple): @@ -450,6 +465,7 @@ def resolve_validation_result_nonverifiability( owner_contract_reference=persisted.owner_contract_reference, owner_contract_version=persisted.owner_contract_version, owner_contract_digest=persisted.owner_contract_digest, + owner_contract_released_at=persisted.owner_contract_released_at, evaluated_at=persisted.evaluated_at, released_at=persisted.released_at, ) @@ -497,6 +513,7 @@ def resolve_validation_result_nonverifiability( "owner_contract_reference": record.owner_contract_reference, "owner_contract_version": record.owner_contract_version, "owner_contract_digest": record.owner_contract_digest, + "owner_contract_released_at": record.owner_contract_released_at, "evaluated_at": record.evaluated_at, "released_at": record.released_at, } From f4dd6b5b4d39cefd3d3b679dd46ae98d0d894c5f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:22:26 +0900 Subject: [PATCH 210/603] test(workforce-validation): align nonverifiability chronology fixtures --- .../tests/test_validation_result_nonverifiability.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py index 53a41b49c..9289e8dba 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py @@ -31,6 +31,7 @@ FAILED_WEIGHT_DIGEST = "2" * 64 ATTEMPT_DIGEST = "3" * 64 OWNER_DIGEST = "4" * 64 +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 17, 5, 55, tzinfo=timezone.utc) EVALUATED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 17, 6, 5, tzinfo=timezone.utc) USED_AT = datetime(2026, 9, 17, 6, 10, tzinfo=timezone.utc) @@ -48,6 +49,7 @@ "owner_contract_reference", "owner_contract_version", "owner_contract_digest", + "owner_contract_released_at", "evaluated_at", "released_at", } @@ -129,6 +131,7 @@ def _record(**overrides: object) -> ValidationResultNonVerifiabilityRecord: "owner_contract_reference": OWNER_REFERENCE, "owner_contract_version": 7, "owner_contract_digest": OWNER_DIGEST, + "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, "evaluated_at": EVALUATED_AT, "released_at": RELEASED_AT, } @@ -188,6 +191,7 @@ def test_missing_final_weight_evidence_is_released_as_not_verifiable() -> None: assert fields["failed_evidence_digest"] is None assert fields["verification_attempt_reference"] == ATTEMPT_REFERENCE assert fields["verification_attempt_digest"] == ATTEMPT_DIGEST + assert fields["owner_contract_released_at"] == OWNER_CONTRACT_RELEASED_AT assert fields["evaluated_at"] == EVALUATED_AT assert fields["released_at"] == RELEASED_AT From 905146754a5be3148c5f689f3e5b5c249539baeb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:28:41 +0900 Subject: [PATCH 211/603] test(workforce-validation): expose stale nonverifiability authority --- ...ion_result_nonverifiability_currentness.py | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py new file mode 100644 index 000000000..45550b235 --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py @@ -0,0 +1,161 @@ +"""RED contract for owner-resolved non-verifiability currentness.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from inspect import signature +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.result_nonverifiability import ( + ValidationResultNonVerifiabilityIntegrityError, + ValidationResultNonVerifiabilityReadPort, + ValidationResultNonVerifiabilityRecord, + resolve_validation_result_nonverifiability, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +ATTEMPT_REFERENCE = ( + "validation_evidence_verification_attempt:33333333-3333-4333-8333-333333333333" +) +OWNER_REFERENCE = "released_owner_contract:44444444-4444-4444-8444-444444444444" +RESULT_DIGEST = "1" * 64 +ATTEMPT_DIGEST = "3" * 64 +OWNER_DIGEST = "4" * 64 +OWNER_RELEASED_AT = datetime(2026, 9, 17, 5, 55, tzinfo=timezone.utc) +EVALUATED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 6, 5, tzinfo=timezone.utc) +SUPERSEDED_AT = datetime(2026, 9, 17, 6, 20, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "result_reference", + "result_digest", + "verification_status", + "failed_evidence_kind", + "failure_mode", + "failed_evidence_reference", + "failed_evidence_digest", + "verification_attempt_reference", + "verification_attempt_digest", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "evaluated_at", + "released_at", + "superseded_at", + } +) + + +class _ReadPort: + """Return one canonical owner record.""" + + def __init__(self, record: ValidationResultNonVerifiabilityRecord) -> None: + self.record = record + + def read_validation_result_nonverifiability( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + failed_evidence_kind: str, + failure_mode: str, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> ValidationResultNonVerifiabilityRecord: + return self.record + + +def _record(*, superseded_at: datetime | None = SUPERSEDED_AT) -> ValidationResultNonVerifiabilityRecord: + return ValidationResultNonVerifiabilityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + failed_evidence_kind="analysis_weight_receipt", + failure_mode="missing", + failed_evidence_reference=None, + failed_evidence_digest=None, + verification_attempt_reference=ATTEMPT_REFERENCE, + verification_attempt_digest=ATTEMPT_DIGEST, + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=7, + owner_contract_digest=OWNER_DIGEST, + owner_contract_released_at=OWNER_RELEASED_AT, + evaluated_at=EVALUATED_AT, + released_at=RELEASED_AT, + superseded_at=superseded_at, + ) + + +def _resolve(*, record: ValidationResultNonVerifiabilityRecord, used_at: datetime): + return resolve_validation_result_nonverifiability( + principal=ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ), + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + failed_evidence_kind="analysis_weight_receipt", + failure_mode="missing", + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=7, + owner_contract_digest=OWNER_DIGEST, + used_at=used_at, + purpose_code="selection_validity_analysis", + policy=PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="validation-result-nonverifiability-read-v1", + resource_kind="validation_result_nonverifiability", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ), + read_port=_ReadPort(record), + ) + + +def test_nonverifiability_cutover_is_owner_evidence_not_caller_coordinate() -> None: + assert "superseded_at" not in signature(resolve_validation_result_nonverifiability).parameters + assert ( + "superseded_at" + not in signature( + ValidationResultNonVerifiabilityReadPort.read_validation_result_nonverifiability + ).parameters + ) + + +def test_nonverifiability_is_valid_only_before_owner_resolved_cutover() -> None: + record = _record() + + historical = _resolve( + record=record, + used_at=datetime(2026, 9, 17, 6, 19, 59, tzinfo=timezone.utc), + ) + assert dict(historical.fields)["superseded_at"] == SUPERSEDED_AT + + with pytest.raises( + ValidationResultNonVerifiabilityIntegrityError, + match="supersession instant", + ): + _resolve(record=record, used_at=SUPERSEDED_AT) + + +def test_nonverifiability_cutover_must_follow_release_and_be_timezone_aware() -> None: + with pytest.raises(ValueError, match="later than"): + _record(superseded_at=RELEASED_AT) + with pytest.raises(ValueError, match="timezone-aware"): + _record(superseded_at=datetime(2026, 9, 17, 6, 20)) From 028566a03e9ec84d9c5b23fe98584e6315c230db Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:29:38 +0900 Subject: [PATCH 212/603] fix(workforce-validation): bound nonverifiability currentness --- .../result_nonverifiability.py | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py index 5732a11df..c458b984d 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py @@ -61,6 +61,7 @@ "owner_contract_released_at", "evaluated_at", "released_at", + "superseded_at", } ) @@ -114,8 +115,9 @@ def __new__( owner_contract_released_at: datetime, evaluated_at: datetime, released_at: datetime, + superseded_at: datetime | None = None, ) -> ValidationResultNonVerifiabilityRecord: - """Validate a minimal, reproducible explanation for non-verifiability.""" + """Validate a minimal, reproducible explanation and its authority interval.""" tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) study_identity = _store_operational_uuid("validity_study_id", validity_study_id) result_ref = _require_reference( @@ -186,6 +188,15 @@ def __new__( ) if evaluation_instant > release_instant: raise ValueError("evaluated_at cannot be later than released_at.") + cutover = ( + None + if superseded_at is None + else _require_aware_datetime("superseded_at", superseded_at) + ) + if cutover is not None and cutover <= release_instant: + raise ValueError( + "superseded_at must be later than non-verifiability release." + ) return tuple.__new__( cls, @@ -206,6 +217,7 @@ def __new__( owner_released, evaluation_instant, release_instant, + cutover, ), ) @@ -294,6 +306,11 @@ def released_at(self) -> datetime: """Return when this non-verifiability outcome became released evidence.""" return self[15] + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive end of this outcome's owner-resolved authority.""" + return self[16] + class ValidationResultNonVerifiabilityView(tuple): """Field-minimized non-authorizing outcome issued only after authorization.""" @@ -468,6 +485,7 @@ def resolve_validation_result_nonverifiability( owner_contract_released_at=persisted.owner_contract_released_at, evaluated_at=persisted.evaluated_at, released_at=persisted.released_at, + superseded_at=persisted.superseded_at, ) requested_identity = ( tenant_identity, @@ -499,6 +517,10 @@ def resolve_validation_result_nonverifiability( raise ValidationResultNonVerifiabilityIntegrityError( "validation-result non-verifiability cannot be used before its release instant" ) + if record.superseded_at is not None and use_instant >= record.superseded_at: + raise ValidationResultNonVerifiabilityIntegrityError( + "validation-result non-verifiability ended at its owner-resolved supersession instant" + ) values = { "result_reference": record.result_reference, @@ -516,6 +538,7 @@ def resolve_validation_result_nonverifiability( "owner_contract_released_at": record.owner_contract_released_at, "evaluated_at": record.evaluated_at, "released_at": record.released_at, + "superseded_at": record.superseded_at, } fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) return tuple.__new__( From a5cff6e2e2063e0cf3adae237ca0a2b1c1357467 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:30:18 +0900 Subject: [PATCH 213/603] test(workforce-validation): align nonverifiability currentness fixtures --- .../tests/test_validation_result_nonverifiability.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py index 9289e8dba..230ada81c 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py @@ -52,6 +52,7 @@ "owner_contract_released_at", "evaluated_at", "released_at", + "superseded_at", } ) @@ -194,6 +195,7 @@ def test_missing_final_weight_evidence_is_released_as_not_verifiable() -> None: assert fields["owner_contract_released_at"] == OWNER_CONTRACT_RELEASED_AT assert fields["evaluated_at"] == EVALUATED_AT assert fields["released_at"] == RELEASED_AT + assert fields["superseded_at"] is None def test_non_reproducible_weight_evidence_keeps_exact_failed_receipt() -> None: From b101e989d12ed9cb0c51bb748d92b173a091f63b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:31:22 +0900 Subject: [PATCH 214/603] docs(workforce-validation): align released authority chronology --- services/workforce-validation-api/README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index d12ae5a48..ec490145b 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -32,15 +32,19 @@ Foreign domain truth crosses this boundary only through released/versioned contr `resolve_calibration_adjustment_authority(...)` corroborates the exact released calibration receipt that produced a point-weight artifact. It binds the receipt/evidence version to purpose-limited auxiliary and benchmark digests, primary method, constraints, artifacts, construction time, and released owner contract. `fallback_applied` additionally requires the primary failure reason, immutable fallback rule, and actual fallback algorithm/version/configuration; `converged` rejects fallback-only evidence. Raw auxiliary values, benchmark totals, protected attributes, and row-level weights are excluded. +The governing owner-contract release instant is canonical owner evidence, not a resolver request coordinate. It must be timezone-aware and no later than the calibration receipt release. A contract may legitimately be released after adjustment construction but before receipt release, while a later contract cannot retroactively authorize an already released calibration receipt. + ## Typed nonresponse-adjustment authority `resolve_nonresponse_adjustment_authority(...)` corroborates the exact released disposition-aware nonresponse receipt. It binds receipt/evidence version, exact response/disposition receipt reference/version/digest, owner-resolved disposition release time, adjustment population, method/version/configuration, explicit ineligible/unknown/unavailable treatments, input/output weight artifacts, construction time, and released owner contract. The disposition input must already exist by adjustment construction and scientific use cannot precede the typed receipt's release. Response values, source attributes, protected attributes, and row-level weights are excluded. +The owner-contract release instant is resolved only from canonical owner evidence and must be timezone-aware and no later than the nonresponse receipt release. It is deliberately absent from caller lookup coordinates, preventing a later owner contract from being used to retroactively corroborate an earlier released adjustment. + ## Trimming/bounding adjustment authority `resolve_trimming_bounding_authority(...)` corroborates the exact released trimming or bounding receipt rather than trusting an adjustment-chain digest alone. It binds the typed receipt reference/digest/evidence version to the governed `weight_trimming_rule` reference/version, immutable rule configuration, exact affected-case occurrence-set digest and positive affected-case count, input/output weight-artifact transition, construction time and released owner-contract tuple. Input and output artifacts may not alias; release cannot precede construction or scientific use. Case identities and row-level weights are excluded from the projection. -This preserves the evidence needed to reproduce which governed trimming/bounding rule changed which case occurrence set without copying those cases into `workforce_validation`. PR #248 or a verified successor must later re-resolve the same tuple from released owner evidence. +The governing owner-contract release instant is also owner-resolved evidence and must exist no later than the adjustment receipt release. The resolver never accepts that instant from the caller. This preserves the evidence needed to reproduce which governed trimming/bounding rule changed which case occurrence set without copying those cases into `workforce_validation`. PR #248 or a verified successor must later re-resolve the same tuple and chronology from released owner evidence. ## Weight-eligibility authority @@ -90,13 +94,15 @@ Result authority is the half-open owner-resolved interval `[released_at, superse `resolve_validation_result_nonverifiability(...)` is the application repair for #407 RED #12. It represents required analysis-weight, weight/variance-compatibility, or variance-design evidence that is `missing | non_reproducible` without turning lookup failure into scientific GREEN. Missing evidence carries no fabricated identity; non-reproducible evidence retains the exact failed reference/digest. Every outcome binds a separate immutable verification-attempt receipt, released owner contract, and evaluation/release chronology. Effect estimates, row-level weights, replicate vectors, protected attributes, and foreign application data are excluded. +The governing owner-contract release instant and optional exclusive `superseded_at` are owner-resolved evidence, never caller lookup coordinates. The contract must already exist when verification is evaluated, and the ordinary resolver accepts the released negative outcome only on `[released_at, superseded_at)`. This prevents an earlier `not_verifiable` outcome from remaining apparently current after later released evidence makes the same immutable validation result corroboratable; use at or after the owner cutover fails closed while historical use before cutover remains reproducible. + ## Persistence state `services/workforce-validation-api/database/migrations/0001_owner_schema.sql` starts this bounded context's migration history. It creates the `workforce_validation` schema and a deny-default `workforce_validation_role`, revokes public schema access, and intentionally creates or moves no application table yet. The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; eligibility, final-weight, point-weight/variance compatibility, and validation-result owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Low-level eligibility/final-weight/binding adapters must therefore recover the same canonical chronology used by their corresponding correction graph rather than independently infer currentness. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; calibration-adjustment, nonresponse-adjustment, and trimming/bounding owner-contract release instants likewise come from durable owner records and must not postdate their released receipts. Base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; eligibility, final-weight, point-weight/variance compatibility, validation-result, and non-verifiability owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Low-level eligibility/final-weight/binding/non-verifiability adapters must therefore recover canonical chronology rather than independently infer currentness. ## Test contract @@ -111,6 +117,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration fallback provenance, typed nonresponse disposition/treatment provenance and chronology, trimming/bounding rule and affected-case provenance, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology and low-level final-weight currentness, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, point/variance compatibility, validation-result binding, and explicit missing/non-reproducible result evidence. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration fallback provenance and owner-contract chronology, typed nonresponse disposition/treatment provenance and owner-contract chronology, trimming/bounding rule/affected-case provenance and owner-contract chronology, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology and low-level final-weight currentness, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, and explicit missing/non-reproducible result evidence including owner-contract chronology and owner-resolved negative-outcome cutover. -These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. +These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. \ No newline at end of file From a1093aba019c5b4dacb16f6ed21324e635dfb6fd Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:34:08 +0900 Subject: [PATCH 215/603] test(workforce-validation): expose failed-evidence chronology gap --- ...erifiability_failed_evidence_chronology.py | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_failed_evidence_chronology.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_failed_evidence_chronology.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_failed_evidence_chronology.py new file mode 100644 index 000000000..5bea199aa --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_failed_evidence_chronology.py @@ -0,0 +1,98 @@ +"""RED contract for chronology of non-reproducible validation evidence.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from inspect import signature +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.result_nonverifiability import ( + ValidationResultNonVerifiabilityReadPort, + ValidationResultNonVerifiabilityRecord, + resolve_validation_result_nonverifiability, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +OWNER_RELEASED_AT = datetime(2026, 9, 17, 5, 45, tzinfo=timezone.utc) +FAILED_EVIDENCE_RELEASED_AT = datetime(2026, 9, 17, 5, 50, tzinfo=timezone.utc) +EVALUATED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 6, 5, tzinfo=timezone.utc) + + +def _record(**overrides: object) -> ValidationResultNonVerifiabilityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "result_reference": ( + "validation_analysis_result:11111111-1111-4111-8111-111111111111" + ), + "result_digest": "1" * 64, + "failed_evidence_kind": "analysis_weight_receipt", + "failure_mode": "non_reproducible", + "failed_evidence_reference": ( + "analysis_weight_receipt:22222222-2222-4222-8222-222222222222" + ), + "failed_evidence_digest": "2" * 64, + "verification_attempt_reference": ( + "validation_evidence_verification_attempt:" + "33333333-3333-4333-8333-333333333333" + ), + "verification_attempt_digest": "3" * 64, + "owner_contract_reference": ( + "released_owner_contract:44444444-4444-4444-8444-444444444444" + ), + "owner_contract_version": 7, + "owner_contract_digest": "4" * 64, + "owner_contract_released_at": OWNER_RELEASED_AT, + "evaluated_at": EVALUATED_AT, + "released_at": RELEASED_AT, + "failed_evidence_released_at": FAILED_EVIDENCE_RELEASED_AT, + } + values.update(overrides) + return ValidationResultNonVerifiabilityRecord(**values) + + +def test_failed_evidence_release_is_owner_evidence_not_lookup_coordinate() -> None: + assert "failed_evidence_released_at" not in signature( + resolve_validation_result_nonverifiability + ).parameters + assert ( + "failed_evidence_released_at" + not in signature( + ValidationResultNonVerifiabilityReadPort.read_validation_result_nonverifiability + ).parameters + ) + + +def test_non_reproducible_evidence_must_exist_before_verification_evaluation() -> None: + with pytest.raises(ValueError, match="failed_evidence_released_at"): + _record( + failed_evidence_released_at=datetime( + 2026, 9, 17, 6, 0, 1, tzinfo=timezone.utc + ) + ) + + +def test_non_reproducible_evidence_requires_release_chronology() -> None: + with pytest.raises(ValueError, match="failed_evidence_released_at"): + _record(failed_evidence_released_at=None) + with pytest.raises(ValueError, match="timezone-aware"): + _record(failed_evidence_released_at=datetime(2026, 9, 17, 5, 50)) + + +def test_missing_evidence_cannot_fabricate_release_chronology() -> None: + with pytest.raises(ValueError, match="must be absent"): + _record( + failure_mode="missing", + failed_evidence_reference=None, + failed_evidence_digest=None, + failed_evidence_released_at=FAILED_EVIDENCE_RELEASED_AT, + ) + + +def test_non_reproducible_release_chronology_is_retained() -> None: + record = _record() + assert record.failed_evidence_released_at == FAILED_EVIDENCE_RELEASED_AT From f19aa64d54ab012d84d45a60de1938893fda01d9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:34:46 +0900 Subject: [PATCH 216/603] fix(workforce-validation): bind failed-evidence chronology --- .../result_nonverifiability.py | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py index c458b984d..d79d65a49 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py @@ -53,6 +53,7 @@ "failure_mode", "failed_evidence_reference", "failed_evidence_digest", + "failed_evidence_released_at", "verification_attempt_reference", "verification_attempt_digest", "owner_contract_reference", @@ -116,8 +117,9 @@ def __new__( evaluated_at: datetime, released_at: datetime, superseded_at: datetime | None = None, + failed_evidence_released_at: datetime | None = None, ) -> ValidationResultNonVerifiabilityRecord: - """Validate a minimal, reproducible explanation and its authority interval.""" + """Validate a reproducible failure explanation and its authority chronology.""" tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) study_identity = _store_operational_uuid("validity_study_id", validity_study_id) result_ref = _require_reference( @@ -129,18 +131,29 @@ def __new__( failed_reference: str | None failed_digest: str | None + failed_release: datetime | None if mode == "missing": - if failed_evidence_reference is not None or failed_evidence_digest is not None: + if ( + failed_evidence_reference is not None + or failed_evidence_digest is not None + or failed_evidence_released_at is not None + ): raise ValueError( - "failed evidence reference and digest must be absent when evidence is missing." + "failed evidence reference, digest, and release chronology must be absent " + "when evidence is missing." ) failed_reference = None failed_digest = None + failed_release = None else: if failed_evidence_reference is None or failed_evidence_digest is None: raise ValueError( "failed evidence reference and digest are required for non_reproducible evidence." ) + if failed_evidence_released_at is None: + raise ValueError( + "failed_evidence_released_at is required for non_reproducible evidence." + ) failed_reference = _require_reference( "failed_evidence_reference", failed_evidence_reference, @@ -149,6 +162,9 @@ def __new__( failed_digest = _require_digest( "failed_evidence_digest", failed_evidence_digest ) + failed_release = _require_aware_datetime( + "failed_evidence_released_at", failed_evidence_released_at + ) attempt_ref = _require_reference( "verification_attempt_reference", @@ -186,6 +202,10 @@ def __new__( raise ValueError( "owner_contract_released_at cannot be later than evaluated_at." ) + if failed_release is not None and failed_release > evaluation_instant: + raise ValueError( + "failed_evidence_released_at cannot be later than evaluated_at." + ) if evaluation_instant > release_instant: raise ValueError("evaluated_at cannot be later than released_at.") cutover = ( @@ -218,6 +238,7 @@ def __new__( evaluation_instant, release_instant, cutover, + failed_release, ), ) @@ -311,6 +332,11 @@ def superseded_at(self) -> datetime | None: """Return the exclusive end of this outcome's owner-resolved authority.""" return self[16] + @property + def failed_evidence_released_at(self) -> datetime | None: + """Return when non-reproducible evidence became available for verification.""" + return self[17] + class ValidationResultNonVerifiabilityView(tuple): """Field-minimized non-authorizing outcome issued only after authorization.""" @@ -486,6 +512,7 @@ def resolve_validation_result_nonverifiability( evaluated_at=persisted.evaluated_at, released_at=persisted.released_at, superseded_at=persisted.superseded_at, + failed_evidence_released_at=persisted.failed_evidence_released_at, ) requested_identity = ( tenant_identity, @@ -530,6 +557,7 @@ def resolve_validation_result_nonverifiability( "failure_mode": record.failure_mode, "failed_evidence_reference": record.failed_evidence_reference, "failed_evidence_digest": record.failed_evidence_digest, + "failed_evidence_released_at": record.failed_evidence_released_at, "verification_attempt_reference": record.verification_attempt_reference, "verification_attempt_digest": record.verification_attempt_digest, "owner_contract_reference": record.owner_contract_reference, From d18828d138f2169b47ff7547b1dbcc942600eadb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:35:15 +0900 Subject: [PATCH 217/603] test(workforce-validation): align failed-evidence chronology fixtures --- .../tests/test_validation_result_nonverifiability.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py index 230ada81c..4e9eb9af4 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py @@ -32,6 +32,7 @@ ATTEMPT_DIGEST = "3" * 64 OWNER_DIGEST = "4" * 64 OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 17, 5, 55, tzinfo=timezone.utc) +FAILED_EVIDENCE_RELEASED_AT = datetime(2026, 9, 17, 5, 59, tzinfo=timezone.utc) EVALUATED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 17, 6, 5, tzinfo=timezone.utc) USED_AT = datetime(2026, 9, 17, 6, 10, tzinfo=timezone.utc) @@ -44,6 +45,7 @@ "failure_mode", "failed_evidence_reference", "failed_evidence_digest", + "failed_evidence_released_at", "verification_attempt_reference", "verification_attempt_digest", "owner_contract_reference", @@ -127,6 +129,7 @@ def _record(**overrides: object) -> ValidationResultNonVerifiabilityRecord: "failure_mode": "missing", "failed_evidence_reference": None, "failed_evidence_digest": None, + "failed_evidence_released_at": None, "verification_attempt_reference": ATTEMPT_REFERENCE, "verification_attempt_digest": ATTEMPT_DIGEST, "owner_contract_reference": OWNER_REFERENCE, @@ -190,6 +193,7 @@ def test_missing_final_weight_evidence_is_released_as_not_verifiable() -> None: assert fields["failure_mode"] == "missing" assert fields["failed_evidence_reference"] is None assert fields["failed_evidence_digest"] is None + assert fields["failed_evidence_released_at"] is None assert fields["verification_attempt_reference"] == ATTEMPT_REFERENCE assert fields["verification_attempt_digest"] == ATTEMPT_DIGEST assert fields["owner_contract_released_at"] == OWNER_CONTRACT_RELEASED_AT @@ -203,6 +207,7 @@ def test_non_reproducible_weight_evidence_keeps_exact_failed_receipt() -> None: failure_mode="non_reproducible", failed_evidence_reference=FAILED_WEIGHT_REFERENCE, failed_evidence_digest=FAILED_WEIGHT_DIGEST, + failed_evidence_released_at=FAILED_EVIDENCE_RELEASED_AT, ) view = _resolve( @@ -214,6 +219,7 @@ def test_non_reproducible_weight_evidence_keeps_exact_failed_receipt() -> None: assert fields["verification_status"] == "not_verifiable" assert fields["failed_evidence_reference"] == FAILED_WEIGHT_REFERENCE assert fields["failed_evidence_digest"] == FAILED_WEIGHT_DIGEST + assert fields["failed_evidence_released_at"] == FAILED_EVIDENCE_RELEASED_AT @pytest.mark.parametrize( @@ -239,6 +245,7 @@ def test_non_reproducible_evidence_kind_uses_its_typed_reference( failure_mode="non_reproducible", failed_evidence_reference=failed_reference, failed_evidence_digest=FAILED_WEIGHT_DIGEST, + failed_evidence_released_at=FAILED_EVIDENCE_RELEASED_AT, ) view = _resolve( read_port=_ReadPort(record), @@ -263,6 +270,7 @@ def test_missing_and_non_reproducible_modes_fail_closed_on_incoherent_evidence() "variance_design_receipt:22222222-2222-4222-8222-222222222222" ), failed_evidence_digest=FAILED_WEIGHT_DIGEST, + failed_evidence_released_at=FAILED_EVIDENCE_RELEASED_AT, ) From c76927bca1da889362fe22c963bcfb1cf6c0c6cc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 05:35:56 +0900 Subject: [PATCH 218/603] docs(workforce-validation): bind nonverifiability evidence chronology --- services/workforce-validation-api/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index ec490145b..24f465048 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -92,9 +92,9 @@ Result authority is the half-open owner-resolved interval `[released_at, superse ## Released non-verifiability outcome -`resolve_validation_result_nonverifiability(...)` is the application repair for #407 RED #12. It represents required analysis-weight, weight/variance-compatibility, or variance-design evidence that is `missing | non_reproducible` without turning lookup failure into scientific GREEN. Missing evidence carries no fabricated identity; non-reproducible evidence retains the exact failed reference/digest. Every outcome binds a separate immutable verification-attempt receipt, released owner contract, and evaluation/release chronology. Effect estimates, row-level weights, replicate vectors, protected attributes, and foreign application data are excluded. +`resolve_validation_result_nonverifiability(...)` is the application repair for #407 RED #12. It represents required analysis-weight, weight/variance-compatibility, or variance-design evidence that is `missing | non_reproducible` without turning lookup failure into scientific GREEN. Missing evidence carries no fabricated reference, digest, or release timestamp. Non-reproducible evidence retains the exact failed reference/digest **and the owner-resolved release instant of that failed evidence**; the evidence must already have been released when the verification attempt is evaluated. Every outcome also binds a separate immutable verification-attempt receipt, released owner contract, and evaluation/release chronology. Effect estimates, row-level weights, replicate vectors, protected attributes, and foreign application data are excluded. -The governing owner-contract release instant and optional exclusive `superseded_at` are owner-resolved evidence, never caller lookup coordinates. The contract must already exist when verification is evaluated, and the ordinary resolver accepts the released negative outcome only on `[released_at, superseded_at)`. This prevents an earlier `not_verifiable` outcome from remaining apparently current after later released evidence makes the same immutable validation result corroboratable; use at or after the owner cutover fails closed while historical use before cutover remains reproducible. +The failed-evidence release instant, governing owner-contract release instant, and optional exclusive `superseded_at` are owner-resolved evidence, never caller/read-port lookup coordinates. For `non_reproducible`, `failed_evidence_released_at <= evaluated_at` is mandatory; for `missing`, failed-evidence release chronology must be absent rather than fabricated. The contract must already exist when verification is evaluated, and the ordinary resolver accepts the released negative outcome only on `[released_at, superseded_at)`. This prevents both time-travel reproducibility claims and an earlier `not_verifiable` outcome from remaining apparently current after later released evidence makes the same immutable validation result corroboratable. ## Persistence state @@ -102,7 +102,7 @@ The governing owner-contract release instant and optional exclusive `superseded_ The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; calibration-adjustment, nonresponse-adjustment, and trimming/bounding owner-contract release instants likewise come from durable owner records and must not postdate their released receipts. Base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; eligibility, final-weight, point-weight/variance compatibility, validation-result, and non-verifiability owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Low-level eligibility/final-weight/binding/non-verifiability adapters must therefore recover canonical chronology rather than independently infer currentness. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; calibration-adjustment, nonresponse-adjustment, and trimming/bounding owner-contract release instants likewise come from durable owner records and must not postdate their released receipts. Base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; eligibility, final-weight, point-weight/variance compatibility, validation-result, and non-verifiability owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Non-verifiability persistence must additionally preserve `failed_evidence_released_at` for non-reproducible evidence and prove it does not postdate verification evaluation, while missing evidence stores no fabricated release time. Low-level eligibility/final-weight/binding/non-verifiability adapters must therefore recover canonical chronology rather than independently infer currentness. ## Test contract @@ -117,6 +117,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration fallback provenance and owner-contract chronology, typed nonresponse disposition/treatment provenance and owner-contract chronology, trimming/bounding rule/affected-case provenance and owner-contract chronology, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology and low-level final-weight currentness, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, and explicit missing/non-reproducible result evidence including owner-contract chronology and owner-resolved negative-outcome cutover. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration fallback provenance and owner-contract chronology, typed nonresponse disposition/treatment provenance and owner-contract chronology, trimming/bounding rule/affected-case provenance and owner-contract chronology, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology and low-level final-weight currentness, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, and explicit missing/non-reproducible result evidence including owner-contract chronology, failed-evidence release chronology, and owner-resolved negative-outcome cutover. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. \ No newline at end of file From 1764c9c34003cf38ca5567921f13d1dd0b9c832e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 06:05:05 +0900 Subject: [PATCH 219/603] test(workforce-validation): require verification-attempt release chronology --- ...ult_nonverifiability_attempt_chronology.py | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_attempt_chronology.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_attempt_chronology.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_attempt_chronology.py new file mode 100644 index 000000000..dbb69f305 --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_attempt_chronology.py @@ -0,0 +1,97 @@ +"""RED contract for immutable verification-attempt release chronology.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from inspect import signature +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.result_nonverifiability import ( + ValidationResultNonVerifiabilityReadPort, + ValidationResultNonVerifiabilityRecord, + resolve_validation_result_nonverifiability, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +OWNER_RELEASED_AT = datetime(2026, 9, 17, 5, 45, tzinfo=timezone.utc) +FAILED_EVIDENCE_RELEASED_AT = datetime(2026, 9, 17, 5, 50, tzinfo=timezone.utc) +EVALUATED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) +ATTEMPT_RELEASED_AT = datetime(2026, 9, 17, 6, 2, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 6, 5, tzinfo=timezone.utc) + + +def _record(**overrides: object) -> ValidationResultNonVerifiabilityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "result_reference": ( + "validation_analysis_result:11111111-1111-4111-8111-111111111111" + ), + "result_digest": "1" * 64, + "failed_evidence_kind": "analysis_weight_receipt", + "failure_mode": "non_reproducible", + "failed_evidence_reference": ( + "analysis_weight_receipt:22222222-2222-4222-8222-222222222222" + ), + "failed_evidence_digest": "2" * 64, + "failed_evidence_released_at": FAILED_EVIDENCE_RELEASED_AT, + "verification_attempt_reference": ( + "validation_evidence_verification_attempt:" + "33333333-3333-4333-8333-333333333333" + ), + "verification_attempt_digest": "3" * 64, + "verification_attempt_released_at": ATTEMPT_RELEASED_AT, + "owner_contract_reference": ( + "released_owner_contract:44444444-4444-4444-8444-444444444444" + ), + "owner_contract_version": 7, + "owner_contract_digest": "4" * 64, + "owner_contract_released_at": OWNER_RELEASED_AT, + "evaluated_at": EVALUATED_AT, + "released_at": RELEASED_AT, + } + values.update(overrides) + return ValidationResultNonVerifiabilityRecord(**values) + + +def test_attempt_release_is_owner_evidence_not_lookup_coordinate() -> None: + assert "verification_attempt_released_at" not in signature( + resolve_validation_result_nonverifiability + ).parameters + assert ( + "verification_attempt_released_at" + not in signature( + ValidationResultNonVerifiabilityReadPort.read_validation_result_nonverifiability + ).parameters + ) + + +def test_verification_attempt_release_is_retained() -> None: + record = _record() + assert record.verification_attempt_released_at == ATTEMPT_RELEASED_AT + + +def test_verification_attempt_cannot_be_released_before_evaluation() -> None: + with pytest.raises(ValueError, match="verification_attempt_released_at"): + _record( + verification_attempt_released_at=datetime( + 2026, 9, 17, 5, 59, 59, tzinfo=timezone.utc + ) + ) + + +def test_verification_attempt_must_exist_before_outcome_release() -> None: + with pytest.raises(ValueError, match="verification_attempt_released_at"): + _record( + verification_attempt_released_at=datetime( + 2026, 9, 17, 6, 5, 1, tzinfo=timezone.utc + ) + ) + + +def test_verification_attempt_release_requires_timezone() -> None: + with pytest.raises(ValueError, match="timezone-aware"): + _record(verification_attempt_released_at=datetime(2026, 9, 17, 6, 2)) From 4327475452a260f0751cc1519e36e2f458ae0995 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 06:06:46 +0900 Subject: [PATCH 220/603] fix(workforce-validation): bind verification-attempt release chronology --- .../result_nonverifiability.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py index d79d65a49..6b75359b6 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py @@ -56,6 +56,7 @@ "failed_evidence_released_at", "verification_attempt_reference", "verification_attempt_digest", + "verification_attempt_released_at", "owner_contract_reference", "owner_contract_version", "owner_contract_digest", @@ -110,6 +111,7 @@ def __new__( failed_evidence_digest: str | None, verification_attempt_reference: str, verification_attempt_digest: str, + verification_attempt_released_at: datetime, owner_contract_reference: str, owner_contract_version: int, owner_contract_digest: str, @@ -174,6 +176,9 @@ def __new__( attempt_digest = _require_digest( "verification_attempt_digest", verification_attempt_digest ) + attempt_release = _require_aware_datetime( + "verification_attempt_released_at", verification_attempt_released_at + ) owner_ref = _require_reference( "owner_contract_reference", owner_contract_reference, @@ -206,6 +211,14 @@ def __new__( raise ValueError( "failed_evidence_released_at cannot be later than evaluated_at." ) + if attempt_release < evaluation_instant: + raise ValueError( + "verification_attempt_released_at cannot precede evaluated_at." + ) + if attempt_release > release_instant: + raise ValueError( + "verification_attempt_released_at cannot be later than released_at." + ) if evaluation_instant > release_instant: raise ValueError("evaluated_at cannot be later than released_at.") cutover = ( @@ -239,6 +252,7 @@ def __new__( release_instant, cutover, failed_release, + attempt_release, ), ) @@ -337,6 +351,11 @@ def failed_evidence_released_at(self) -> datetime | None: """Return when non-reproducible evidence became available for verification.""" return self[17] + @property + def verification_attempt_released_at(self) -> datetime: + """Return when the immutable verification-attempt receipt became released evidence.""" + return self[18] + class ValidationResultNonVerifiabilityView(tuple): """Field-minimized non-authorizing outcome issued only after authorization.""" @@ -505,6 +524,7 @@ def resolve_validation_result_nonverifiability( failed_evidence_digest=persisted.failed_evidence_digest, verification_attempt_reference=persisted.verification_attempt_reference, verification_attempt_digest=persisted.verification_attempt_digest, + verification_attempt_released_at=persisted.verification_attempt_released_at, owner_contract_reference=persisted.owner_contract_reference, owner_contract_version=persisted.owner_contract_version, owner_contract_digest=persisted.owner_contract_digest, @@ -560,6 +580,7 @@ def resolve_validation_result_nonverifiability( "failed_evidence_released_at": record.failed_evidence_released_at, "verification_attempt_reference": record.verification_attempt_reference, "verification_attempt_digest": record.verification_attempt_digest, + "verification_attempt_released_at": record.verification_attempt_released_at, "owner_contract_reference": record.owner_contract_reference, "owner_contract_version": record.owner_contract_version, "owner_contract_digest": record.owner_contract_digest, From 80a70220167833c787143c0f2fa2b7c9f40655b7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 06:07:17 +0900 Subject: [PATCH 221/603] test(workforce-validation): align nonverifiability attempt chronology --- .../tests/test_validation_result_nonverifiability.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py index 4e9eb9af4..ea5ea9304 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py @@ -34,6 +34,7 @@ OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 17, 5, 55, tzinfo=timezone.utc) FAILED_EVIDENCE_RELEASED_AT = datetime(2026, 9, 17, 5, 59, tzinfo=timezone.utc) EVALUATED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) +ATTEMPT_RELEASED_AT = datetime(2026, 9, 17, 6, 2, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 17, 6, 5, tzinfo=timezone.utc) USED_AT = datetime(2026, 9, 17, 6, 10, tzinfo=timezone.utc) READ_FIELDS = frozenset( @@ -48,6 +49,7 @@ "failed_evidence_released_at", "verification_attempt_reference", "verification_attempt_digest", + "verification_attempt_released_at", "owner_contract_reference", "owner_contract_version", "owner_contract_digest", @@ -132,6 +134,7 @@ def _record(**overrides: object) -> ValidationResultNonVerifiabilityRecord: "failed_evidence_released_at": None, "verification_attempt_reference": ATTEMPT_REFERENCE, "verification_attempt_digest": ATTEMPT_DIGEST, + "verification_attempt_released_at": ATTEMPT_RELEASED_AT, "owner_contract_reference": OWNER_REFERENCE, "owner_contract_version": 7, "owner_contract_digest": OWNER_DIGEST, @@ -196,6 +199,7 @@ def test_missing_final_weight_evidence_is_released_as_not_verifiable() -> None: assert fields["failed_evidence_released_at"] is None assert fields["verification_attempt_reference"] == ATTEMPT_REFERENCE assert fields["verification_attempt_digest"] == ATTEMPT_DIGEST + assert fields["verification_attempt_released_at"] == ATTEMPT_RELEASED_AT assert fields["owner_contract_released_at"] == OWNER_CONTRACT_RELEASED_AT assert fields["evaluated_at"] == EVALUATED_AT assert fields["released_at"] == RELEASED_AT @@ -291,6 +295,9 @@ def test_evaluation_must_precede_release() -> None: with pytest.raises(ValueError, match="evaluated_at"): _record( evaluated_at=datetime(2026, 9, 17, 6, 6, tzinfo=timezone.utc), + verification_attempt_released_at=datetime( + 2026, 9, 17, 6, 6, tzinfo=timezone.utc + ), released_at=RELEASED_AT, ) From 18f5c906ad3693cdb497d1f6dc6597c3144a7b48 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 06:09:02 +0900 Subject: [PATCH 222/603] fix(workforce-validation): order nonverifiability chronology checks causally --- .../result_nonverifiability.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py index 6b75359b6..f1d54dc5c 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py @@ -211,6 +211,8 @@ def __new__( raise ValueError( "failed_evidence_released_at cannot be later than evaluated_at." ) + if evaluation_instant > release_instant: + raise ValueError("evaluated_at cannot be later than released_at.") if attempt_release < evaluation_instant: raise ValueError( "verification_attempt_released_at cannot precede evaluated_at." @@ -219,8 +221,6 @@ def __new__( raise ValueError( "verification_attempt_released_at cannot be later than released_at." ) - if evaluation_instant > release_instant: - raise ValueError("evaluated_at cannot be later than released_at.") cutover = ( None if superseded_at is None From 712a114951582796e7c18bf96478e9518b8914c1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 06:09:19 +0900 Subject: [PATCH 223/603] test(workforce-validation): align currentness with attempt chronology --- .../test_validation_result_nonverifiability_currentness.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py index 45550b235..99497641f 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py @@ -29,6 +29,7 @@ OWNER_DIGEST = "4" * 64 OWNER_RELEASED_AT = datetime(2026, 9, 17, 5, 55, tzinfo=timezone.utc) EVALUATED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) +ATTEMPT_RELEASED_AT = datetime(2026, 9, 17, 6, 2, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 17, 6, 5, tzinfo=timezone.utc) SUPERSEDED_AT = datetime(2026, 9, 17, 6, 20, tzinfo=timezone.utc) READ_FIELDS = frozenset( @@ -40,8 +41,10 @@ "failure_mode", "failed_evidence_reference", "failed_evidence_digest", + "failed_evidence_released_at", "verification_attempt_reference", "verification_attempt_digest", + "verification_attempt_released_at", "owner_contract_reference", "owner_contract_version", "owner_contract_digest", @@ -87,6 +90,7 @@ def _record(*, superseded_at: datetime | None = SUPERSEDED_AT) -> ValidationResu failed_evidence_digest=None, verification_attempt_reference=ATTEMPT_REFERENCE, verification_attempt_digest=ATTEMPT_DIGEST, + verification_attempt_released_at=ATTEMPT_RELEASED_AT, owner_contract_reference=OWNER_REFERENCE, owner_contract_version=7, owner_contract_digest=OWNER_DIGEST, From dede2a2c885404aa7b309b60545e9f1a8a03b766 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 06:09:46 +0900 Subject: [PATCH 224/603] test(workforce-validation): align owner chronology with attempt release --- ...idation_result_nonverifiability_owner_contract_chronology.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_owner_contract_chronology.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_owner_contract_chronology.py index 874c8bef5..4ce0683e0 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_owner_contract_chronology.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_owner_contract_chronology.py @@ -17,6 +17,7 @@ STUDY = UUID("00000000-0000-7000-8000-0000000000d1") OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 17, 5, 55, tzinfo=timezone.utc) EVALUATED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) +ATTEMPT_RELEASED_AT = datetime(2026, 9, 17, 6, 2, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 17, 6, 5, tzinfo=timezone.utc) @@ -37,6 +38,7 @@ def _record(**overrides: object) -> ValidationResultNonVerifiabilityRecord: "33333333-3333-4333-8333-333333333333" ), "verification_attempt_digest": "3" * 64, + "verification_attempt_released_at": ATTEMPT_RELEASED_AT, "owner_contract_reference": ( "released_owner_contract:44444444-4444-4444-8444-444444444444" ), From f6b849f77bb1de785636b89075bd612c558ca4eb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 06:10:00 +0900 Subject: [PATCH 225/603] test(workforce-validation): align failed-evidence chronology with attempt release --- ...dation_result_nonverifiability_failed_evidence_chronology.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_failed_evidence_chronology.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_failed_evidence_chronology.py index 5bea199aa..8c9223e06 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_failed_evidence_chronology.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_failed_evidence_chronology.py @@ -19,6 +19,7 @@ OWNER_RELEASED_AT = datetime(2026, 9, 17, 5, 45, tzinfo=timezone.utc) FAILED_EVIDENCE_RELEASED_AT = datetime(2026, 9, 17, 5, 50, tzinfo=timezone.utc) EVALUATED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) +ATTEMPT_RELEASED_AT = datetime(2026, 9, 17, 6, 2, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 17, 6, 5, tzinfo=timezone.utc) @@ -41,6 +42,7 @@ def _record(**overrides: object) -> ValidationResultNonVerifiabilityRecord: "33333333-3333-4333-8333-333333333333" ), "verification_attempt_digest": "3" * 64, + "verification_attempt_released_at": ATTEMPT_RELEASED_AT, "owner_contract_reference": ( "released_owner_contract:44444444-4444-4444-8444-444444444444" ), From 4208af1913b07d0f1b79162c097e001ca81c37a7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 06:10:48 +0900 Subject: [PATCH 226/603] docs(workforce-validation): document verification-attempt release chronology --- services/workforce-validation-api/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 24f465048..40cf6463b 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -92,9 +92,9 @@ Result authority is the half-open owner-resolved interval `[released_at, superse ## Released non-verifiability outcome -`resolve_validation_result_nonverifiability(...)` is the application repair for #407 RED #12. It represents required analysis-weight, weight/variance-compatibility, or variance-design evidence that is `missing | non_reproducible` without turning lookup failure into scientific GREEN. Missing evidence carries no fabricated reference, digest, or release timestamp. Non-reproducible evidence retains the exact failed reference/digest **and the owner-resolved release instant of that failed evidence**; the evidence must already have been released when the verification attempt is evaluated. Every outcome also binds a separate immutable verification-attempt receipt, released owner contract, and evaluation/release chronology. Effect estimates, row-level weights, replicate vectors, protected attributes, and foreign application data are excluded. +`resolve_validation_result_nonverifiability(...)` is the application repair for #407 RED #12. It represents required analysis-weight, weight/variance-compatibility, or variance-design evidence that is `missing | non_reproducible` without turning lookup failure into scientific GREEN. Missing evidence carries no fabricated reference, digest, or release timestamp. Non-reproducible evidence retains the exact failed reference/digest **and the owner-resolved release instant of that failed evidence**; the evidence must already have been released when the verification attempt is evaluated. Every outcome also binds a separate immutable verification-attempt receipt, its owner-resolved release instant, released owner contract, and outcome evaluation/release chronology. Effect estimates, row-level weights, replicate vectors, protected attributes, and foreign application data are excluded. -The failed-evidence release instant, governing owner-contract release instant, and optional exclusive `superseded_at` are owner-resolved evidence, never caller/read-port lookup coordinates. For `non_reproducible`, `failed_evidence_released_at <= evaluated_at` is mandatory; for `missing`, failed-evidence release chronology must be absent rather than fabricated. The contract must already exist when verification is evaluated, and the ordinary resolver accepts the released negative outcome only on `[released_at, superseded_at)`. This prevents both time-travel reproducibility claims and an earlier `not_verifiable` outcome from remaining apparently current after later released evidence makes the same immutable validation result corroboratable. +The failed-evidence release instant, verification-attempt release instant, governing owner-contract release instant, and optional exclusive `superseded_at` are owner-resolved evidence, never caller/read-port lookup coordinates. For `non_reproducible`, `failed_evidence_released_at <= evaluated_at` is mandatory; for `missing`, failed-evidence release chronology must be absent rather than fabricated. The contract must already exist when verification is evaluated. The immutable verification-attempt receipt must be released on the causal interval `evaluated_at <= verification_attempt_released_at <= released_at`, so a later-created attempt receipt cannot be backdated into an earlier negative outcome and a receipt cannot predate the evaluation it records. The ordinary resolver accepts the released negative outcome only on `[released_at, superseded_at)`. This prevents time-travel reproducibility/verification claims and an earlier `not_verifiable` outcome from remaining apparently current after later released evidence makes the same immutable validation result corroboratable. ## Persistence state @@ -102,7 +102,7 @@ The failed-evidence release instant, governing owner-contract release instant, a The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; calibration-adjustment, nonresponse-adjustment, and trimming/bounding owner-contract release instants likewise come from durable owner records and must not postdate their released receipts. Base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; eligibility, final-weight, point-weight/variance compatibility, validation-result, and non-verifiability owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Non-verifiability persistence must additionally preserve `failed_evidence_released_at` for non-reproducible evidence and prove it does not postdate verification evaluation, while missing evidence stores no fabricated release time. Low-level eligibility/final-weight/binding/non-verifiability adapters must therefore recover canonical chronology rather than independently infer currentness. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; calibration-adjustment, nonresponse-adjustment, and trimming/bounding owner-contract release instants likewise come from durable owner records and must not postdate their released receipts. Base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; eligibility, final-weight, point-weight/variance compatibility, validation-result, and non-verifiability owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Non-verifiability persistence must additionally preserve `failed_evidence_released_at` for non-reproducible evidence, preserve `verification_attempt_released_at` for every verification attempt, prove `failed_evidence_released_at <= evaluated_at` when applicable, and prove `evaluated_at <= verification_attempt_released_at <= released_at`; missing evidence stores no fabricated failed-evidence release time. Low-level eligibility/final-weight/binding/non-verifiability adapters must therefore recover canonical chronology rather than independently infer currentness. ## Test contract @@ -117,6 +117,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration fallback provenance and owner-contract chronology, typed nonresponse disposition/treatment provenance and owner-contract chronology, trimming/bounding rule/affected-case provenance and owner-contract chronology, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology and low-level final-weight currentness, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, and explicit missing/non-reproducible result evidence including owner-contract chronology, failed-evidence release chronology, and owner-resolved negative-outcome cutover. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration fallback provenance and owner-contract chronology, typed nonresponse disposition/treatment provenance and owner-contract chronology, trimming/bounding rule/affected-case provenance and owner-contract chronology, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology and low-level final-weight currentness, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, and explicit missing/non-reproducible result evidence including owner-contract chronology, failed-evidence release chronology, verification-attempt release chronology, and owner-resolved negative-outcome cutover. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. \ No newline at end of file From 6dd8e55744fb4ab7caf1bfacbcb2246d736b2bc9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 06:22:58 +0900 Subject: [PATCH 227/603] test(workforce-validation): RED exact nonverifiability attempt lookup --- ...onverifiability_lookup_key_completeness.py | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_lookup_key_completeness.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_lookup_key_completeness.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_lookup_key_completeness.py new file mode 100644 index 000000000..0157ca2ee --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_lookup_key_completeness.py @@ -0,0 +1,42 @@ +"""Fail closed on ambiguous lookup of immutable verification attempts.""" + +from __future__ import annotations + +from inspect import signature + +from orgmetra_workforce_validation_api.result_nonverifiability import ( + ValidationResultNonVerifiabilityReadPort, + resolve_validation_result_nonverifiability, +) + + +_REQUIRED_ATTEMPT_COORDINATES = ( + "verification_attempt_reference", + "verification_attempt_digest", +) + + +def test_resolver_requires_exact_verification_attempt_coordinates() -> None: + """Bind callers to one immutable attempt instead of an arbitrary matching outcome.""" + parameters = signature(resolve_validation_result_nonverifiability).parameters + for coordinate in _REQUIRED_ATTEMPT_COORDINATES: + assert coordinate in parameters + + +def test_owner_read_port_keys_exact_verification_attempt_coordinates() -> None: + """Prevent repeated attempts for one result from sharing an ambiguous lookup prefix.""" + parameters = signature( + ValidationResultNonVerifiabilityReadPort.read_validation_result_nonverifiability + ).parameters + for coordinate in _REQUIRED_ATTEMPT_COORDINATES: + assert coordinate in parameters + + +def test_attempt_release_time_remains_owner_evidence_not_lookup_authority() -> None: + """Keep release chronology owner-resolved while the immutable attempt identity is exact.""" + resolver_parameters = signature(resolve_validation_result_nonverifiability).parameters + port_parameters = signature( + ValidationResultNonVerifiabilityReadPort.read_validation_result_nonverifiability + ).parameters + assert "verification_attempt_released_at" not in resolver_parameters + assert "verification_attempt_released_at" not in port_parameters From 7acef751c5b0d5a11f68029e6dfc646e07aee02b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 06:23:54 +0900 Subject: [PATCH 228/603] fix(workforce-validation): key nonverifiability by exact attempt --- .../result_nonverifiability.py | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py index f1d54dc5c..444ec3bae 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py @@ -404,6 +404,8 @@ def read_validation_result_nonverifiability( result_digest: str, failed_evidence_kind: str, failure_mode: str, + verification_attempt_reference: str, + verification_attempt_digest: str, owner_contract_reference: str, owner_contract_version: int, owner_contract_digest: str, @@ -427,6 +429,8 @@ def resolve_validation_result_nonverifiability( result_digest: str, failed_evidence_kind: str, failure_mode: str, + verification_attempt_reference: str, + verification_attempt_digest: str, owner_contract_reference: str, owner_contract_version: int, owner_contract_digest: str, @@ -435,7 +439,7 @@ def resolve_validation_result_nonverifiability( policy: PurposeBoundAccessPolicy, read_port: ValidationResultNonVerifiabilityReadPort, ) -> ValidationResultNonVerifiabilityView: - """Authorize then corroborate one released, explicitly non-authorizing outcome.""" + """Authorize then corroborate one exact released, non-authorizing verification attempt.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") if type(policy) is not PurposeBoundAccessPolicy: @@ -467,6 +471,14 @@ def resolve_validation_result_nonverifiability( result_evidence_digest = _require_digest("result_digest", result_digest) evidence_kind = _require_failed_evidence_kind(failed_evidence_kind) mode = _require_failure_mode(failure_mode) + attempt_ref = _require_reference( + "verification_attempt_reference", + verification_attempt_reference, + "validation_evidence_verification_attempt", + ) + attempt_digest = _require_digest( + "verification_attempt_digest", verification_attempt_digest + ) owner_ref = _require_reference( "owner_contract_reference", owner_contract_reference, "released_owner_contract" ) @@ -502,6 +514,8 @@ def resolve_validation_result_nonverifiability( result_digest=result_evidence_digest, failed_evidence_kind=evidence_kind, failure_mode=mode, + verification_attempt_reference=attempt_ref, + verification_attempt_digest=attempt_digest, owner_contract_reference=owner_ref, owner_contract_version=owner_version, owner_contract_digest=owner_digest, @@ -541,6 +555,8 @@ def resolve_validation_result_nonverifiability( result_evidence_digest, evidence_kind, mode, + attempt_ref, + attempt_digest, owner_ref, owner_version, owner_digest, @@ -552,13 +568,15 @@ def resolve_validation_result_nonverifiability( record.result_digest, record.failed_evidence_kind, record.failure_mode, + record.verification_attempt_reference, + record.verification_attempt_digest, record.owner_contract_reference, record.owner_contract_version, record.owner_contract_digest, ) if record_identity != requested_identity: raise ValidationResultNonVerifiabilityIntegrityError( - "owner evidence does not match the requested non-verifiability outcome" + "owner evidence does not match the requested non-verifiability attempt" ) if use_instant < record.released_at: raise ValidationResultNonVerifiabilityIntegrityError( From 3638c820b3f17666df52b0dbd3a4b76f81b45c9b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 06:25:44 +0900 Subject: [PATCH 229/603] test(workforce-validation): align nonverifiability currentness lookup --- .../test_validation_result_nonverifiability_currentness.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py index 99497641f..18c062682 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py @@ -71,6 +71,8 @@ def read_validation_result_nonverifiability( result_digest: str, failed_evidence_kind: str, failure_mode: str, + verification_attempt_reference: str, + verification_attempt_digest: str, owner_contract_reference: str, owner_contract_version: int, owner_contract_digest: str, @@ -114,6 +116,8 @@ def _resolve(*, record: ValidationResultNonVerifiabilityRecord, used_at: datetim result_digest=RESULT_DIGEST, failed_evidence_kind="analysis_weight_receipt", failure_mode="missing", + verification_attempt_reference=ATTEMPT_REFERENCE, + verification_attempt_digest=ATTEMPT_DIGEST, owner_contract_reference=OWNER_REFERENCE, owner_contract_version=7, owner_contract_digest=OWNER_DIGEST, From 784770366cc04bc14ea6e49ea2147f864fbd7c3d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 06:26:16 +0900 Subject: [PATCH 230/603] test(workforce-validation): align exact attempt lookup fixtures --- .../tests/test_validation_result_nonverifiability.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py index ea5ea9304..ff5bfe7b8 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py @@ -77,6 +77,8 @@ def read_validation_result_nonverifiability( result_digest: str, failed_evidence_kind: str, failure_mode: str, + verification_attempt_reference: str, + verification_attempt_digest: str, owner_contract_reference: str, owner_contract_version: int, owner_contract_digest: str, @@ -89,6 +91,8 @@ def read_validation_result_nonverifiability( result_digest, failed_evidence_kind, failure_mode, + verification_attempt_reference, + verification_attempt_digest, owner_contract_reference, owner_contract_version, owner_contract_digest, @@ -157,6 +161,8 @@ def _resolve( "result_digest": RESULT_DIGEST, "failed_evidence_kind": "analysis_weight_receipt", "failure_mode": "missing", + "verification_attempt_reference": ATTEMPT_REFERENCE, + "verification_attempt_digest": ATTEMPT_DIGEST, "owner_contract_reference": OWNER_REFERENCE, "owner_contract_version": 7, "owner_contract_digest": OWNER_DIGEST, @@ -183,6 +189,8 @@ def test_missing_final_weight_evidence_is_released_as_not_verifiable() -> None: RESULT_DIGEST, "analysis_weight_receipt", "missing", + ATTEMPT_REFERENCE, + ATTEMPT_DIGEST, OWNER_REFERENCE, 7, OWNER_DIGEST, @@ -316,6 +324,8 @@ def test_missing_noncanonical_or_mismatched_owner_outcome_fails_closed() -> None _resolve(read_port=_ReadPort(object())) with pytest.raises(ValidationResultNonVerifiabilityIntegrityError): _resolve(read_port=_ReadPort(_record(result_digest="a" * 64))) + with pytest.raises(ValidationResultNonVerifiabilityIntegrityError): + _resolve(read_port=_ReadPort(_record(verification_attempt_digest="a" * 64))) def test_invalid_dependencies_and_pre_release_use_fail_closed() -> None: From a2ffa9e07497c43670f49a77ca2d94be93790f06 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 06:27:05 +0900 Subject: [PATCH 231/603] docs(workforce-validation): document exact attempt lookup authority --- services/workforce-validation-api/README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 40cf6463b..726049caf 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -94,7 +94,9 @@ Result authority is the half-open owner-resolved interval `[released_at, superse `resolve_validation_result_nonverifiability(...)` is the application repair for #407 RED #12. It represents required analysis-weight, weight/variance-compatibility, or variance-design evidence that is `missing | non_reproducible` without turning lookup failure into scientific GREEN. Missing evidence carries no fabricated reference, digest, or release timestamp. Non-reproducible evidence retains the exact failed reference/digest **and the owner-resolved release instant of that failed evidence**; the evidence must already have been released when the verification attempt is evaluated. Every outcome also binds a separate immutable verification-attempt receipt, its owner-resolved release instant, released owner contract, and outcome evaluation/release chronology. Effect estimates, row-level weights, replicate vectors, protected attributes, and foreign application data are excluded. -The failed-evidence release instant, verification-attempt release instant, governing owner-contract release instant, and optional exclusive `superseded_at` are owner-resolved evidence, never caller/read-port lookup coordinates. For `non_reproducible`, `failed_evidence_released_at <= evaluated_at` is mandatory; for `missing`, failed-evidence release chronology must be absent rather than fabricated. The contract must already exist when verification is evaluated. The immutable verification-attempt receipt must be released on the causal interval `evaluated_at <= verification_attempt_released_at <= released_at`, so a later-created attempt receipt cannot be backdated into an earlier negative outcome and a receipt cannot predate the evaluation it records. The ordinary resolver accepts the released negative outcome only on `[released_at, superseded_at)`. This prevents time-travel reproducibility/verification claims and an earlier `not_verifiable` outcome from remaining apparently current after later released evidence makes the same immutable validation result corroboratable. +The immutable `verification_attempt_reference` and `verification_attempt_digest` are part of the resolver and owner-read lookup identity. Repeated attempts for the same result, evidence kind, failure mode, and owner contract therefore cannot share an ambiguous lookup prefix or let persistence choose an arbitrary attempt. The attempt's `verification_attempt_released_at` remains owner-resolved chronology and is deliberately not a caller/read-port lookup coordinate. + +The failed-evidence release instant, verification-attempt release instant, governing owner-contract release instant, and optional exclusive `superseded_at` are owner-resolved evidence. For `non_reproducible`, `failed_evidence_released_at <= evaluated_at` is mandatory; for `missing`, failed-evidence release chronology must be absent rather than fabricated. The contract must already exist when verification is evaluated. The immutable verification-attempt receipt must be released on the causal interval `evaluated_at <= verification_attempt_released_at <= released_at`, so a later-created attempt receipt cannot be backdated into an earlier negative outcome and a receipt cannot predate the evaluation it records. The ordinary resolver accepts the released negative outcome only on `[released_at, superseded_at)`. This prevents time-travel reproducibility/verification claims and an earlier `not_verifiable` outcome from remaining apparently current after later released evidence makes the same immutable validation result corroboratable. ## Persistence state @@ -102,7 +104,7 @@ The failed-evidence release instant, verification-attempt release instant, gover The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; calibration-adjustment, nonresponse-adjustment, and trimming/bounding owner-contract release instants likewise come from durable owner records and must not postdate their released receipts. Base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; eligibility, final-weight, point-weight/variance compatibility, validation-result, and non-verifiability owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Non-verifiability persistence must additionally preserve `failed_evidence_released_at` for non-reproducible evidence, preserve `verification_attempt_released_at` for every verification attempt, prove `failed_evidence_released_at <= evaluated_at` when applicable, and prove `evaluated_at <= verification_attempt_released_at <= released_at`; missing evidence stores no fabricated failed-evidence release time. Low-level eligibility/final-weight/binding/non-verifiability adapters must therefore recover canonical chronology rather than independently infer currentness. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; calibration-adjustment, nonresponse-adjustment, and trimming/bounding owner-contract release instants likewise come from durable owner records and must not postdate their released receipts. Base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; eligibility, final-weight, point-weight/variance compatibility, validation-result, and non-verifiability owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Non-verifiability persistence must key the owner read by the exact immutable verification-attempt reference/digest, preserve `failed_evidence_released_at` for non-reproducible evidence, preserve owner-resolved `verification_attempt_released_at` for every verification attempt, prove `failed_evidence_released_at <= evaluated_at` when applicable, and prove `evaluated_at <= verification_attempt_released_at <= released_at`; missing evidence stores no fabricated failed-evidence release time. Low-level eligibility/final-weight/binding/non-verifiability adapters must therefore recover canonical chronology rather than independently infer currentness. ## Test contract @@ -117,6 +119,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration fallback provenance and owner-contract chronology, typed nonresponse disposition/treatment provenance and owner-contract chronology, trimming/bounding rule/affected-case provenance and owner-contract chronology, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology and low-level final-weight currentness, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, and explicit missing/non-reproducible result evidence including owner-contract chronology, failed-evidence release chronology, verification-attempt release chronology, and owner-resolved negative-outcome cutover. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration fallback provenance and owner-contract chronology, typed nonresponse disposition/treatment provenance and owner-contract chronology, trimming/bounding rule/affected-case provenance and owner-contract chronology, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology and low-level final-weight currentness, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, and explicit missing/non-reproducible result evidence including owner-contract chronology, failed-evidence release chronology, exact verification-attempt lookup-key completeness, verification-attempt release chronology, and owner-resolved negative-outcome cutover. -These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. \ No newline at end of file +These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From 493d3ac05c771e224d9b3fd5e2355cf889fe96aa Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 07:02:00 +0900 Subject: [PATCH 232/603] test(workforce-validation): RED complete base-weight owner lookup key --- ...t_base_weight_read_port_lookup_contract.py | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_base_weight_read_port_lookup_contract.py diff --git a/services/workforce-validation-api/tests/test_base_weight_read_port_lookup_contract.py b/services/workforce-validation-api/tests/test_base_weight_read_port_lookup_contract.py new file mode 100644 index 000000000..8e7f7e17c --- /dev/null +++ b/services/workforce-validation-api/tests/test_base_weight_read_port_lookup_contract.py @@ -0,0 +1,47 @@ +"""Guard the exact immutable lookup key for base-weight owner evidence.""" + +from __future__ import annotations + +from inspect import signature + +from orgmetra_workforce_validation_api.base_weight_authority import ( + BaseWeightAuthorityReadPort, +) + + +def test_base_weight_read_port_requires_complete_reproducibility_tuple() -> None: + """Require every caller-known coordinate needed to select one owner record.""" + parameters = set(signature(BaseWeightAuthorityReadPort.read_base_weight_authority).parameters) + + required_lookup_coordinates = { + "tenant_record_id", + "validity_study_id", + "base_weight_evidence_receipt_reference", + "base_weight_evidence_receipt_digest", + "evidence_version", + "source_universe_receipt_reference", + "source_universe_receipt_version", + "source_universe_receipt_digest", + "sampling_design_receipt_reference", + "sampling_design_receipt_version", + "sampling_design_receipt_digest", + "sampled_occurrence_set_digest", + "selection_probability_set_digest", + "selection_stage_count", + "base_weight_method_code", + "base_weight_method_version", + "base_weight_artifact_digest", + "constructed_at", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + } + assert required_lookup_coordinates <= parameters + + owner_resolved_chronology = { + "source_universe_released_at", + "sampling_design_released_at", + "owner_contract_released_at", + "released_at", + } + assert parameters.isdisjoint(owner_resolved_chronology) From 5f66626495b6b40d2799bb17e51a8598eb8c14f2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 07:02:36 +0900 Subject: [PATCH 233/603] fix(workforce-validation): complete base-weight owner lookup key --- .../base_weight_authority.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py index 35ff4cd67..c9f3b3619 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py @@ -292,9 +292,16 @@ def read_base_weight_authority( sampling_design_receipt_reference: str, sampling_design_receipt_version: int, sampling_design_receipt_digest: str, + sampled_occurrence_set_digest: str, selection_probability_set_digest: str, + selection_stage_count: int, + base_weight_method_code: str, + base_weight_method_version: int, + base_weight_artifact_digest: str, + constructed_at: datetime, owner_contract_reference: str, owner_contract_version: int, + owner_contract_digest: str, ) -> BaseWeightAuthorityRecord | None: """Return matching released base-weight evidence or ``None``.""" ... @@ -430,11 +437,18 @@ def resolve_base_weight_authority( sampling_design_receipt_digest=requested_values[ "sampling_design_receipt_digest" ], + sampled_occurrence_set_digest=requested_values["sampled_occurrence_set_digest"], selection_probability_set_digest=requested_values[ "selection_probability_set_digest" ], + selection_stage_count=requested_values["selection_stage_count"], + base_weight_method_code=requested_values["base_weight_method_code"], + base_weight_method_version=requested_values["base_weight_method_version"], + base_weight_artifact_digest=requested_values["base_weight_artifact_digest"], + constructed_at=requested_values["constructed_at"], owner_contract_reference=requested_values["owner_contract_reference"], owner_contract_version=requested_values["owner_contract_version"], + owner_contract_digest=requested_values["owner_contract_digest"], ) if persisted is None: raise BaseWeightAuthorityNotFound(str(study_id)) @@ -494,4 +508,4 @@ def resolve_base_weight_authority( "BaseWeightAuthorityRecord", "BaseWeightAuthorityView", "resolve_base_weight_authority", -] \ No newline at end of file +] From 9c4bd8c730e20e36810f8ba984ff8188639d5656 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 08:00:31 +0900 Subject: [PATCH 234/603] test(workforce-validation): require complete final-weight lookup key --- ...alysis_weight_read_port_lookup_contract.py | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_analysis_weight_read_port_lookup_contract.py diff --git a/services/workforce-validation-api/tests/test_final_analysis_weight_read_port_lookup_contract.py b/services/workforce-validation-api/tests/test_final_analysis_weight_read_port_lookup_contract.py new file mode 100644 index 000000000..5483d9e5c --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_analysis_weight_read_port_lookup_contract.py @@ -0,0 +1,66 @@ +"""Guard the exact immutable lookup key for final analysis-weight owner evidence.""" + +from __future__ import annotations + +from inspect import signature + +from orgmetra_workforce_validation_api.final_weight_authority import ( + FinalAnalysisWeightAuthorityReadPort, +) + + +def test_final_analysis_weight_read_port_requires_complete_reproducibility_tuple() -> None: + """Require every caller-known coordinate needed to select one owner record.""" + parameters = set( + signature( + FinalAnalysisWeightAuthorityReadPort.read_final_analysis_weight_authority + ).parameters + ) + + required_lookup_coordinates = { + "tenant_record_id", + "validity_study_id", + "analysis_weight_receipt_reference", + "analysis_weight_receipt_digest", + "evidence_version", + "estimand_reference", + "estimand_digest", + "estimand_scope_code", + "target_population_reference", + "target_population_digest", + "analysis_unit_code", + "analysis_window_reference", + "reference_duration_reference", + "reference_duration_digest", + "eligible_case_set_digest", + "analytic_case_occurrence_set_digest", + "source_universe_receipt_reference", + "source_universe_receipt_version", + "source_universe_receipt_digest", + "sampling_design_receipt_reference", + "sampling_design_receipt_version", + "sampling_design_receipt_digest", + "base_weight_method_code", + "base_weight_method_version", + "base_weight_evidence_digest", + "base_weight_artifact_digest", + "adjustments", + "final_weight_artifact_digest", + "weight_eligibility_receipt_reference", + "weight_eligibility_receipt_digest", + "analytic_case_count", + "constructed_at", + "correction_sequence", + "supersedes_receipt_digest", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + } + assert required_lookup_coordinates <= parameters + + owner_resolved_chronology = { + "owner_contract_released_at", + "released_at", + "superseded_at", + } + assert parameters.isdisjoint(owner_resolved_chronology) From a96c6c2ab037053036ba0f46c492103e720f21ff Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 08:02:14 +0900 Subject: [PATCH 235/603] fix(workforce-validation): complete final-weight owner lookup key --- .../final_weight_authority.py | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py index fab3fa710..568210678 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py @@ -543,14 +543,38 @@ def read_final_analysis_weight_authority( analysis_weight_receipt_reference: str, analysis_weight_receipt_digest: str, evidence_version: int, + estimand_reference: str, + estimand_digest: str, + estimand_scope_code: str, + target_population_reference: str, + target_population_digest: str, + analysis_unit_code: str, + analysis_window_reference: str, + reference_duration_reference: str, + reference_duration_digest: str, + eligible_case_set_digest: str, + analytic_case_occurrence_set_digest: str, source_universe_receipt_reference: str, source_universe_receipt_version: int, source_universe_receipt_digest: str, sampling_design_receipt_reference: str, sampling_design_receipt_version: int, sampling_design_receipt_digest: str, + base_weight_method_code: str, + base_weight_method_version: int, + base_weight_evidence_digest: str, + base_weight_artifact_digest: str, + adjustments: tuple[FinalWeightAdjustmentCoordinate, ...], + final_weight_artifact_digest: str, + weight_eligibility_receipt_reference: str, + weight_eligibility_receipt_digest: str, + analytic_case_count: int, + constructed_at: datetime, + correction_sequence: int, + supersedes_receipt_digest: str | None, owner_contract_reference: str, owner_contract_version: int, + owner_contract_digest: str, ) -> FinalAnalysisWeightAuthorityRecord | None: """Return matching released final-weight evidence or ``None``.""" ... @@ -704,6 +728,19 @@ def resolve_final_analysis_weight_authority( "analysis_weight_receipt_digest" ], evidence_version=requested_values["evidence_version"], + estimand_reference=requested_values["estimand_reference"], + estimand_digest=requested_values["estimand_digest"], + estimand_scope_code=requested_values["estimand_scope_code"], + target_population_reference=requested_values["target_population_reference"], + target_population_digest=requested_values["target_population_digest"], + analysis_unit_code=requested_values["analysis_unit_code"], + analysis_window_reference=requested_values["analysis_window_reference"], + reference_duration_reference=requested_values["reference_duration_reference"], + reference_duration_digest=requested_values["reference_duration_digest"], + eligible_case_set_digest=requested_values["eligible_case_set_digest"], + analytic_case_occurrence_set_digest=requested_values[ + "analytic_case_occurrence_set_digest" + ], source_universe_receipt_reference=requested_values[ "source_universe_receipt_reference" ], @@ -722,8 +759,25 @@ def resolve_final_analysis_weight_authority( sampling_design_receipt_digest=requested_values[ "sampling_design_receipt_digest" ], + base_weight_method_code=requested_values["base_weight_method_code"], + base_weight_method_version=requested_values["base_weight_method_version"], + base_weight_evidence_digest=requested_values["base_weight_evidence_digest"], + base_weight_artifact_digest=requested_values["base_weight_artifact_digest"], + adjustments=requested_values["adjustments"], + final_weight_artifact_digest=requested_values["final_weight_artifact_digest"], + weight_eligibility_receipt_reference=requested_values[ + "weight_eligibility_receipt_reference" + ], + weight_eligibility_receipt_digest=requested_values[ + "weight_eligibility_receipt_digest" + ], + analytic_case_count=requested_values["analytic_case_count"], + constructed_at=requested_values["constructed_at"], + correction_sequence=requested_values["correction_sequence"], + supersedes_receipt_digest=requested_values["supersedes_receipt_digest"], owner_contract_reference=requested_values["owner_contract_reference"], owner_contract_version=requested_values["owner_contract_version"], + owner_contract_digest=requested_values["owner_contract_digest"], ) if persisted is None: raise FinalAnalysisWeightAuthorityNotFound(str(study_id)) From dcbe1aac4e2020a6adacc1e940d8b24b3975a1a1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 08:03:07 +0900 Subject: [PATCH 236/603] docs(workforce-validation): document complete final-weight lookup key --- services/workforce-validation-api/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 726049caf..361db9610 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -62,6 +62,8 @@ The stage-wise probability values themselves stay with the sampling owner. `work `resolve_final_analysis_weight_authority(...)` corroborates the complete #407 point-estimation lineage rather than trusting only the final receipt digest carried by the point-weight/variance compatibility boundary. It binds the exact final analysis-weight receipt to the estimand, target population, analysis unit/window/reference duration, eligible and analytic-case sets, owner-resolved source-universe and sampling-design receipt references/versions/digests, base-weight method/evidence/artifact, ordered typed adjustment chain, final point-weight artifact, weight-eligibility receipt, analytic-case count, append-only correction lineage, construction/release chronology, and released owner contract. +The owner read is keyed by that complete caller-known reproducibility tuple rather than only receipt/source/design identifiers. Multiple released final-weight records that share the old prefix but differ in estimand, population, analytic-case set, base-weight evidence, ordered adjustments, final artifact, eligibility, construction, correction lineage, or owner-contract digest therefore cannot be selected ambiguously by persistence before integrity comparison. Owner-contract release, final-weight release, and supersession instants remain owner-resolved chronology and are not caller lookup coordinates. + The ordered adjustment chain is immutable and contiguous: each transform must consume the preceding artifact, material transforms may not be no-ops, and known nonresponse/calibration/raking/poststratification/trimming/bounding/winsorization codes require their specialized receipt kind. Source/sampling references are owner-corroborated coordinates layered over the digest-only scientific leaf, so a caller cannot turn an opaque digest into a floating source/design version. The separate base-weight authority additionally resolves the stage-wise selection-probability evidence behind the base artifact. No row-level weights, case identities, protected calibration values, or foreign tables cross this boundary. The ordinary final-weight resolver itself now resolves the governing owner-contract release instant and optional exclusive supersession cutover from canonical owner evidence. Neither is a caller request coordinate. A later owner contract cannot retroactively authorize an earlier final-weight receipt, and scientific use is valid only on `[released_at, superseded_at)`. The separate supersession authority still proves the complete predecessor/successor edge; this lower-level resolver consumes only the owner-resolved chronology needed to prevent stale final-weight evidence from remaining usable when callers do not traverse that graph. @@ -104,7 +106,7 @@ The failed-evidence release instant, verification-attempt release instant, gover The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; calibration-adjustment, nonresponse-adjustment, and trimming/bounding owner-contract release instants likewise come from durable owner records and must not postdate their released receipts. Base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; eligibility, final-weight, point-weight/variance compatibility, validation-result, and non-verifiability owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Non-verifiability persistence must key the owner read by the exact immutable verification-attempt reference/digest, preserve `failed_evidence_released_at` for non-reproducible evidence, preserve owner-resolved `verification_attempt_released_at` for every verification attempt, prove `failed_evidence_released_at <= evaluated_at` when applicable, and prove `evaluated_at <= verification_attempt_released_at <= released_at`; missing evidence stores no fabricated failed-evidence release time. Low-level eligibility/final-weight/binding/non-verifiability adapters must therefore recover canonical chronology rather than independently infer currentness. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; calibration-adjustment, nonresponse-adjustment, and trimming/bounding owner-contract release instants likewise come from durable owner records and must not postdate their released receipts. Base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; eligibility, final-weight, point-weight/variance compatibility, validation-result, and non-verifiability owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Base-weight and final-analysis-weight persistence must select released owner evidence by their complete caller-known reproducibility tuples; it may not select a partial receipt/source/design prefix and rely on a later in-memory mismatch check. Non-verifiability persistence must key the owner read by the exact immutable verification-attempt reference/digest, preserve `failed_evidence_released_at` for non-reproducible evidence, preserve owner-resolved `verification_attempt_released_at` for every verification attempt, prove `failed_evidence_released_at <= evaluated_at` when applicable, and prove `evaluated_at <= verification_attempt_released_at <= released_at`; missing evidence stores no fabricated failed-evidence release time. Low-level eligibility/final-weight/binding/non-verifiability adapters must therefore recover canonical chronology rather than independently infer currentness. ## Test contract @@ -119,6 +121,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration fallback provenance and owner-contract chronology, typed nonresponse disposition/treatment provenance and owner-contract chronology, trimming/bounding rule/affected-case provenance and owner-contract chronology, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology and low-level final-weight currentness, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, and explicit missing/non-reproducible result evidence including owner-contract chronology, failed-evidence release chronology, exact verification-attempt lookup-key completeness, verification-attempt release chronology, and owner-resolved negative-outcome cutover. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration fallback provenance and owner-contract chronology, typed nonresponse disposition/treatment provenance and owner-contract chronology, trimming/bounding rule/affected-case provenance and owner-contract chronology, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology and complete read-port lookup coordinates, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology, low-level final-weight currentness, and complete final-weight read-port lookup coordinates, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, and explicit missing/non-reproducible result evidence including owner-contract chronology, failed-evidence release chronology, exact verification-attempt lookup-key completeness, verification-attempt release chronology, and owner-resolved negative-outcome cutover. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From 5d0f09b9353991b8aefe90d5a835a301fb232a13 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 09:08:08 +0900 Subject: [PATCH 237/603] test(workforce-validation): bind calibration context coordinates --- ...alibration_adjustment_context_authority.py | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_adjustment_context_authority.py diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_context_authority.py b/services/workforce-validation-api/tests/test_calibration_adjustment_context_authority.py new file mode 100644 index 000000000..eac206556 --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_context_authority.py @@ -0,0 +1,78 @@ +"""Regression contract for calibration target-population and analysis-window authority.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from inspect import signature +from uuid import UUID + +from orgmetra_workforce_validation_api.calibration_adjustment_authority import ( + CalibrationAdjustmentAuthorityReadPort, + CalibrationAdjustmentAuthorityRecord, + resolve_calibration_adjustment_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") +CONSTRUCTED_AT = datetime(2026, 9, 17, 8, 0, tzinfo=timezone.utc) +OWNER_RELEASED_AT = datetime(2026, 9, 17, 8, 10, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 8, 30, tzinfo=timezone.utc) +TARGET_POPULATION_DIGEST = "a" * 64 +ANALYSIS_WINDOW_REFERENCE = "analysis_window:2026q3" + + +def _record() -> CalibrationAdjustmentAuthorityRecord: + """Build one released calibration authority with explicit analysis context.""" + return CalibrationAdjustmentAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + calibration_receipt_reference=( + "calibration_adjustment_receipt:11111111-1111-4111-8111-111111111111" + ), + calibration_receipt_digest="1" * 64, + evidence_version=1, + target_population_digest=TARGET_POPULATION_DIGEST, + analysis_window_reference=ANALYSIS_WINDOW_REFERENCE, + auxiliary_projection_digest="2" * 64, + benchmark_receipt_digest="3" * 64, + algorithm_reference="calibration_algorithm:linear-raking", + algorithm_version=1, + constraints_digest="4" * 64, + termination_code="converged", + input_weight_artifact_digest="5" * 64, + output_weight_artifact_digest="6" * 64, + constructed_at=CONSTRUCTED_AT, + fallback_reason_code=None, + fallback_rule_reference=None, + fallback_rule_digest=None, + fallback_algorithm_reference=None, + fallback_algorithm_version=None, + fallback_configuration_digest=None, + owner_contract_reference=( + "released_owner_contract:22222222-2222-4222-8222-222222222222" + ), + owner_contract_version=1, + owner_contract_digest="7" * 64, + owner_contract_released_at=OWNER_RELEASED_AT, + released_at=RELEASED_AT, + ) + + +def test_calibration_authority_binds_target_population_and_analysis_window() -> None: + """Keep the scientific leaf's population/window semantics in owner corroboration.""" + record = _record() + + assert record.target_population_digest == TARGET_POPULATION_DIGEST + assert record.analysis_window_reference == ANALYSIS_WINDOW_REFERENCE + + read_parameters = signature( + CalibrationAdjustmentAuthorityReadPort.read_calibration_adjustment_authority + ).parameters + resolver_parameters = signature(resolve_calibration_adjustment_authority).parameters + for field_name in ("target_population_digest", "analysis_window_reference"): + assert field_name in read_parameters + assert field_name in resolver_parameters + + for owner_resolved_field in ("owner_contract_released_at", "released_at"): + assert owner_resolved_field not in read_parameters + assert owner_resolved_field not in resolver_parameters From 2ca632c354d17652dbb8ead08fc1302ce7e88e48 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 09:10:10 +0900 Subject: [PATCH 238/603] fix(workforce-validation): bind calibration analysis context --- .../calibration_adjustment_authority.py | 46 +++++++++++++++++-- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py index 310bf48d5..53fab964d 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py @@ -1,10 +1,10 @@ """Corroborate released typed calibration-adjustment evidence through an owner port. This application boundary binds the exact calibration receipt that produced a -point-weight artifact to its primary or fallback generating method. It does not -copy auxiliary values, benchmark totals, protected attributes, or row-level -weights. Durable PostgreSQL/release resolution remains a persistence-owner task -after this service reaches protected truth. +point-weight artifact to its target population, analysis window, and primary or +fallback generating method. It does not copy auxiliary values, benchmark totals, +protected attributes, or row-level weights. Durable PostgreSQL/release resolution +remains a persistence-owner task after this service reaches protected truth. """ from __future__ import annotations @@ -43,6 +43,8 @@ "calibration_receipt_reference", "calibration_receipt_digest", "evidence_version", + "target_population_digest", + "analysis_window_reference", "auxiliary_projection_digest", "benchmark_receipt_digest", "algorithm_reference", @@ -95,6 +97,8 @@ def __new__( calibration_receipt_reference: str, calibration_receipt_digest: str, evidence_version: int, + target_population_digest: str, + analysis_window_reference: str, auxiliary_projection_digest: str, benchmark_receipt_digest: str, algorithm_reference: str, @@ -130,6 +134,14 @@ def __new__( version = _require_positive_integer("evidence_version", evidence_version) if version != 1: raise ValueError("evidence_version must remain 1.") + target_digest = _require_digest( + "target_population_digest", target_population_digest + ) + analysis_window_ref = _require_reference( + "analysis_window_reference", + analysis_window_reference, + "analysis_window", + ) projection_digest = _require_digest( "auxiliary_projection_digest", auxiliary_projection_digest ) @@ -244,6 +256,8 @@ def __new__( owner_digest, owner_released, release_instant, + target_digest, + analysis_window_ref, ), ) @@ -372,6 +386,16 @@ def released_at(self) -> datetime: """Return when this typed calibration evidence became released authority.""" return self[24] + @property + def target_population_digest(self) -> str: + """Return the exact target population governed by the calibration receipt.""" + return self[25] + + @property + def analysis_window_reference(self) -> str: + """Return the analysis window governed by the calibration receipt.""" + return self[26] + class CalibrationAdjustmentAuthorityView(tuple): """Field-minimized typed calibration evidence issued only after authorization.""" @@ -419,6 +443,8 @@ def read_calibration_adjustment_authority( calibration_receipt_reference: str, calibration_receipt_digest: str, evidence_version: int, + target_population_digest: str, + analysis_window_reference: str, auxiliary_projection_digest: str, benchmark_receipt_digest: str, algorithm_reference: str, @@ -449,7 +475,7 @@ def read_calibration_adjustment_authority( def _coordinate_tuple(record: CalibrationAdjustmentAuthorityRecord) -> tuple[object, ...]: """Return caller-known coordinates, excluding owner-resolved release instants.""" - return record[:23] + return record[:23] + record[25:27] def resolve_calibration_adjustment_authority( @@ -460,6 +486,8 @@ def resolve_calibration_adjustment_authority( calibration_receipt_reference: str, calibration_receipt_digest: str, evidence_version: int, + target_population_digest: str, + analysis_window_reference: str, auxiliary_projection_digest: str, benchmark_receipt_digest: str, algorithm_reference: str, @@ -511,6 +539,8 @@ def resolve_calibration_adjustment_authority( calibration_receipt_reference=calibration_receipt_reference, calibration_receipt_digest=calibration_receipt_digest, evidence_version=evidence_version, + target_population_digest=target_population_digest, + analysis_window_reference=analysis_window_reference, auxiliary_projection_digest=auxiliary_projection_digest, benchmark_receipt_digest=benchmark_receipt_digest, algorithm_reference=algorithm_reference, @@ -561,6 +591,8 @@ def resolve_calibration_adjustment_authority( calibration_receipt_reference=requested.calibration_receipt_reference, calibration_receipt_digest=requested.calibration_receipt_digest, evidence_version=requested.evidence_version, + target_population_digest=requested.target_population_digest, + analysis_window_reference=requested.analysis_window_reference, auxiliary_projection_digest=requested.auxiliary_projection_digest, benchmark_receipt_digest=requested.benchmark_receipt_digest, algorithm_reference=requested.algorithm_reference, @@ -593,6 +625,8 @@ def resolve_calibration_adjustment_authority( calibration_receipt_reference=persisted.calibration_receipt_reference, calibration_receipt_digest=persisted.calibration_receipt_digest, evidence_version=persisted.evidence_version, + target_population_digest=persisted.target_population_digest, + analysis_window_reference=persisted.analysis_window_reference, auxiliary_projection_digest=persisted.auxiliary_projection_digest, benchmark_receipt_digest=persisted.benchmark_receipt_digest, algorithm_reference=persisted.algorithm_reference, @@ -626,6 +660,7 @@ def resolve_calibration_adjustment_authority( fields: tuple[tuple[str, object], ...] = ( ("algorithm_reference", record.algorithm_reference), ("algorithm_version", record.algorithm_version), + ("analysis_window_reference", record.analysis_window_reference), ("auxiliary_projection_digest", record.auxiliary_projection_digest), ("benchmark_receipt_digest", record.benchmark_receipt_digest), ("calibration_receipt_digest", record.calibration_receipt_digest), @@ -640,6 +675,7 @@ def resolve_calibration_adjustment_authority( ("owner_contract_released_at", record.owner_contract_released_at), ("owner_contract_version", record.owner_contract_version), ("released_at", record.released_at), + ("target_population_digest", record.target_population_digest), ("termination_code", record.termination_code), ) if record.termination_code == "fallback_applied": From 417ee360902d16b02230b76f7a29c4c0d4021dee Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 09:10:47 +0900 Subject: [PATCH 239/603] test(workforce-validation): carry calibration context through owner resolution --- .../test_calibration_adjustment_authority.py | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py b/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py index 29bc0f56a..bb829f581 100644 --- a/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py @@ -25,6 +25,8 @@ RECEIPT_REFERENCE = "calibration_adjustment_receipt:11111111-1111-4111-8111-111111111111" OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" RECEIPT_DIGEST = "1" * 64 +TARGET_POPULATION_DIGEST = "a" * 64 +ANALYSIS_WINDOW_REFERENCE = "analysis_window:2026q3" AUXILIARY_PROJECTION_DIGEST = "2" * 64 BENCHMARK_RECEIPT_DIGEST = "3" * 64 CONSTRAINTS_DIGEST = "4" * 64 @@ -42,6 +44,8 @@ "calibration_receipt_reference", "calibration_receipt_digest", "evidence_version", + "target_population_digest", + "analysis_window_reference", "auxiliary_projection_digest", "benchmark_receipt_digest", "algorithm_reference", @@ -134,6 +138,8 @@ def _record(**overrides: object) -> CalibrationAdjustmentAuthorityRecord: "calibration_receipt_reference": RECEIPT_REFERENCE, "calibration_receipt_digest": RECEIPT_DIGEST, "evidence_version": 1, + "target_population_digest": TARGET_POPULATION_DIGEST, + "analysis_window_reference": ANALYSIS_WINDOW_REFERENCE, "auxiliary_projection_digest": AUXILIARY_PROJECTION_DIGEST, "benchmark_receipt_digest": BENCHMARK_RECEIPT_DIGEST, "algorithm_reference": "calibration_algorithm:generalized_regression", @@ -167,6 +173,8 @@ def _resolve(*, read_port: object, **overrides: object) -> CalibrationAdjustment "calibration_receipt_reference": RECEIPT_REFERENCE, "calibration_receipt_digest": RECEIPT_DIGEST, "evidence_version": 1, + "target_population_digest": TARGET_POPULATION_DIGEST, + "analysis_window_reference": ANALYSIS_WINDOW_REFERENCE, "auxiliary_projection_digest": AUXILIARY_PROJECTION_DIGEST, "benchmark_receipt_digest": BENCHMARK_RECEIPT_DIGEST, "algorithm_reference": "calibration_algorithm:generalized_regression", @@ -204,9 +212,13 @@ def test_fallback_resolution_binds_actual_generating_method() -> None: assert isinstance(port, CalibrationAdjustmentAuthorityReadPort) assert len(port.calls) == 1 assert port.calls[0]["calibration_receipt_digest"] == RECEIPT_DIGEST + assert port.calls[0]["target_population_digest"] == TARGET_POPULATION_DIGEST + assert port.calls[0]["analysis_window_reference"] == ANALYSIS_WINDOW_REFERENCE assert port.calls[0]["fallback_algorithm_reference"] == "calibration_algorithm:raking" assert view.tenant_record_id == TENANT assert view.validity_study_id == STUDY + assert ("target_population_digest", TARGET_POPULATION_DIGEST) in view.fields + assert ("analysis_window_reference", ANALYSIS_WINDOW_REFERENCE) in view.fields assert ("termination_code", "fallback_applied") in view.fields assert ("fallback_reason_code", "primary_nonconvergence") in view.fields assert ("fallback_rule_reference", "calibration_fallback_rule:cell-collapse-v2") in view.fields @@ -245,16 +257,18 @@ def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: [ {"tenant_record_id": OTHER_TENANT}, {"validity_study_id": OTHER_STUDY}, - {"calibration_receipt_digest": "a" * 64}, - {"auxiliary_projection_digest": "b" * 64}, - {"benchmark_receipt_digest": "c" * 64}, + {"calibration_receipt_digest": "b" * 64}, + {"target_population_digest": "c" * 64}, + {"analysis_window_reference": "analysis_window:2026q4"}, + {"auxiliary_projection_digest": "d" * 64}, + {"benchmark_receipt_digest": "e" * 64}, {"algorithm_reference": "calibration_algorithm:raking"}, {"algorithm_version": 9}, - {"constraints_digest": "d" * 64}, - {"input_weight_artifact_digest": "e" * 64}, - {"output_weight_artifact_digest": "f" * 64}, + {"constraints_digest": "f" * 64}, + {"input_weight_artifact_digest": "0" * 64}, + {"output_weight_artifact_digest": "a" * 64}, {"owner_contract_version": 7}, - {"owner_contract_digest": "0" * 64}, + {"owner_contract_digest": "b" * 64}, ], ) def test_owner_evidence_must_match_every_requested_coordinate( @@ -298,6 +312,8 @@ def test_converged_receipt_rejects_fallback_only_evidence() -> None: ("key", "value"), [ ("evidence_version", 2), + ("target_population_digest", "a" * 63), + ("analysis_window_reference", "wrong:window"), ("termination_code", "nonconverged"), ("algorithm_reference", "wrong:method"), ("algorithm_version", True), @@ -339,6 +355,8 @@ def test_weight_artifact_and_release_chronology_fail_closed() -> None: ("calibration_receipt_reference", "wrong:receipt", ValueError), ("calibration_receipt_digest", "ABC", ValueError), ("evidence_version", False, ValueError), + ("target_population_digest", "a" * 63, ValueError), + ("analysis_window_reference", "wrong:window", ValueError), ("auxiliary_projection_digest", "2" * 63, ValueError), ("benchmark_receipt_digest", "3" * 65, ValueError), ("algorithm_reference", "wrong:algorithm", ValueError), From da8e310d1c73b46b40d6798f560bedfc14b0c8e5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 09:13:43 +0900 Subject: [PATCH 240/603] test(workforce-validation): require exact calibration supporting authority --- ...djustment_supporting_authority_identity.py | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_adjustment_supporting_authority_identity.py diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_supporting_authority_identity.py b/services/workforce-validation-api/tests/test_calibration_adjustment_supporting_authority_identity.py new file mode 100644 index 000000000..72a6d3cd1 --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_supporting_authority_identity.py @@ -0,0 +1,131 @@ +"""Regression contract for exact auxiliary and benchmark identity in calibration evidence.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from inspect import signature +from uuid import UUID + +from orgmetra_workforce_validation_api.calibration_adjustment_authority import ( + CalibrationAdjustmentAuthorityReadPort, + CalibrationAdjustmentAuthorityRecord, + resolve_calibration_adjustment_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f2") +CONSTRUCTED_AT = datetime(2026, 9, 17, 9, 0, tzinfo=timezone.utc) +OWNER_RELEASED_AT = datetime(2026, 9, 17, 9, 10, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 9, 30, tzinfo=timezone.utc) +SUPPORTING_FIELDS = ( + "auxiliary_authority_reference", + "auxiliary_projection_reference", + "auxiliary_projection_version", + "auxiliary_purpose_reference", + "auxiliary_purpose_digest", + "auxiliary_owner_contract_reference", + "auxiliary_owner_contract_version", + "auxiliary_owner_contract_digest", + "auxiliary_authorization_receipt_reference", + "auxiliary_authorization_receipt_digest", + "auxiliary_scientific_use_receipt_reference", + "auxiliary_scientific_use_receipt_digest", + "auxiliary_scientific_use_at", + "benchmark_receipt_reference", + "benchmark_receipt_version", + "benchmark_owner_contract_reference", + "benchmark_owner_contract_version", + "benchmark_owner_contract_digest", + "benchmark_reference_at", +) + + +def _record() -> CalibrationAdjustmentAuthorityRecord: + """Build the complete leaf-semantic calibration authority projection.""" + return CalibrationAdjustmentAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + calibration_receipt_reference=( + "calibration_adjustment_receipt:11111111-1111-4111-8111-111111111111" + ), + calibration_receipt_digest="1" * 64, + evidence_version=1, + target_population_digest="2" * 64, + analysis_window_reference="analysis_window:2026q3", + auxiliary_authority_reference=( + "scientific_auxiliary_authority:22222222-2222-4222-8222-222222222222" + ), + auxiliary_projection_reference=( + "calibration_auxiliary_projection:33333333-3333-4333-8333-333333333333" + ), + auxiliary_projection_version=3, + auxiliary_projection_digest="3" * 64, + auxiliary_purpose_reference=( + "scientific_data_use_purpose:44444444-4444-4444-8444-444444444444" + ), + auxiliary_purpose_digest="4" * 64, + auxiliary_owner_contract_reference=( + "released_owner_contract:55555555-5555-4555-8555-555555555555" + ), + auxiliary_owner_contract_version=5, + auxiliary_owner_contract_digest="5" * 64, + auxiliary_authorization_receipt_reference=( + "scientific_data_authorization:66666666-6666-4666-8666-666666666666" + ), + auxiliary_authorization_receipt_digest="6" * 64, + auxiliary_scientific_use_receipt_reference=( + "scientific_use_receipt:77777777-7777-4777-8777-777777777777" + ), + auxiliary_scientific_use_receipt_digest="7" * 64, + auxiliary_scientific_use_at=datetime(2026, 9, 17, 8, 30, tzinfo=timezone.utc), + benchmark_receipt_reference=( + "calibration_benchmark_receipt:88888888-8888-4888-8888-888888888888" + ), + benchmark_receipt_version=8, + benchmark_receipt_digest="8" * 64, + benchmark_owner_contract_reference=( + "released_owner_contract:99999999-9999-4999-8999-999999999999" + ), + benchmark_owner_contract_version=9, + benchmark_owner_contract_digest="9" * 64, + benchmark_reference_at=datetime(2026, 9, 17, 8, 45, tzinfo=timezone.utc), + algorithm_reference="calibration_algorithm:generalized_regression", + algorithm_version=3, + constraints_digest="a" * 64, + termination_code="converged", + input_weight_artifact_digest="b" * 64, + output_weight_artifact_digest="c" * 64, + constructed_at=CONSTRUCTED_AT, + fallback_reason_code=None, + fallback_rule_reference=None, + fallback_rule_digest=None, + fallback_algorithm_reference=None, + fallback_algorithm_version=None, + fallback_configuration_digest=None, + owner_contract_reference=( + "released_owner_contract:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" + ), + owner_contract_version=10, + owner_contract_digest="d" * 64, + owner_contract_released_at=OWNER_RELEASED_AT, + released_at=RELEASED_AT, + ) + + +def test_calibration_authority_preserves_exact_supporting_evidence_identity() -> None: + """Do not collapse calibration auxiliary/benchmark provenance to digest-only labels.""" + record = _record() + read_parameters = signature( + CalibrationAdjustmentAuthorityReadPort.read_calibration_adjustment_authority + ).parameters + resolver_parameters = signature(resolve_calibration_adjustment_authority).parameters + + for field_name in SUPPORTING_FIELDS: + assert hasattr(record, field_name) + assert field_name in read_parameters + assert field_name in resolver_parameters + + assert record.auxiliary_projection_reference.startswith("calibration_auxiliary_projection:") + assert record.benchmark_receipt_reference.startswith("calibration_benchmark_receipt:") + assert record.auxiliary_scientific_use_at <= record.constructed_at + assert record.benchmark_reference_at <= record.constructed_at From 9db8d12e42d2eda65a33c3dd41d40fca77753cb1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 09:14:58 +0900 Subject: [PATCH 241/603] fix(workforce-validation): bind exact calibration support authority --- .../calibration_adjustment_authority.py | 370 +++++++++++++++++- 1 file changed, 359 insertions(+), 11 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py index 53fab964d..433332368 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py @@ -1,10 +1,11 @@ """Corroborate released typed calibration-adjustment evidence through an owner port. This application boundary binds the exact calibration receipt that produced a -point-weight artifact to its target population, analysis window, and primary or -fallback generating method. It does not copy auxiliary values, benchmark totals, -protected attributes, or row-level weights. Durable PostgreSQL/release resolution -remains a persistence-owner task after this service reaches protected truth. +point-weight artifact to its target population, analysis window, purpose-bound +auxiliary authority, benchmark authority, and primary or fallback generating +method. It does not copy auxiliary values, benchmark totals, protected +attributes, or row-level weights. Durable PostgreSQL/release resolution remains +a persistence-owner task after this service reaches protected truth. """ from __future__ import annotations @@ -45,8 +46,27 @@ "evidence_version", "target_population_digest", "analysis_window_reference", + "auxiliary_authority_reference", + "auxiliary_projection_reference", + "auxiliary_projection_version", "auxiliary_projection_digest", + "auxiliary_purpose_reference", + "auxiliary_purpose_digest", + "auxiliary_owner_contract_reference", + "auxiliary_owner_contract_version", + "auxiliary_owner_contract_digest", + "auxiliary_authorization_receipt_reference", + "auxiliary_authorization_receipt_digest", + "auxiliary_scientific_use_receipt_reference", + "auxiliary_scientific_use_receipt_digest", + "auxiliary_scientific_use_at", + "benchmark_receipt_reference", + "benchmark_receipt_version", "benchmark_receipt_digest", + "benchmark_owner_contract_reference", + "benchmark_owner_contract_version", + "benchmark_owner_contract_digest", + "benchmark_reference_at", "algorithm_reference", "algorithm_version", "constraints_digest", @@ -99,8 +119,27 @@ def __new__( evidence_version: int, target_population_digest: str, analysis_window_reference: str, + auxiliary_authority_reference: str, + auxiliary_projection_reference: str, + auxiliary_projection_version: int, auxiliary_projection_digest: str, + auxiliary_purpose_reference: str, + auxiliary_purpose_digest: str, + auxiliary_owner_contract_reference: str, + auxiliary_owner_contract_version: int, + auxiliary_owner_contract_digest: str, + auxiliary_authorization_receipt_reference: str, + auxiliary_authorization_receipt_digest: str, + auxiliary_scientific_use_receipt_reference: str, + auxiliary_scientific_use_receipt_digest: str, + auxiliary_scientific_use_at: datetime, + benchmark_receipt_reference: str, + benchmark_receipt_version: int, benchmark_receipt_digest: str, + benchmark_owner_contract_reference: str, + benchmark_owner_contract_version: int, + benchmark_owner_contract_digest: str, + benchmark_reference_at: datetime, algorithm_reference: str, algorithm_version: int, constraints_digest: str, @@ -120,7 +159,7 @@ def __new__( owner_contract_released_at: datetime, released_at: datetime, ) -> CalibrationAdjustmentAuthorityRecord: - """Validate and detach the minimum receipt-level scientific authority.""" + """Validate and detach the receipt-level scientific authority.""" tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) study_identity = _store_operational_uuid("validity_study_id", validity_study_id) receipt_ref = _require_reference( @@ -142,12 +181,87 @@ def __new__( analysis_window_reference, "analysis_window", ) + auxiliary_authority_ref = _require_reference( + "auxiliary_authority_reference", + auxiliary_authority_reference, + "scientific_auxiliary_authority", + ) + auxiliary_projection_ref = _require_reference( + "auxiliary_projection_reference", + auxiliary_projection_reference, + "calibration_auxiliary_projection", + ) + auxiliary_projection_ver = _require_positive_integer( + "auxiliary_projection_version", auxiliary_projection_version + ) projection_digest = _require_digest( "auxiliary_projection_digest", auxiliary_projection_digest ) + auxiliary_purpose_ref = _require_reference( + "auxiliary_purpose_reference", + auxiliary_purpose_reference, + "scientific_data_use_purpose", + ) + auxiliary_purpose_evidence = _require_digest( + "auxiliary_purpose_digest", auxiliary_purpose_digest + ) + auxiliary_owner_ref = _require_reference( + "auxiliary_owner_contract_reference", + auxiliary_owner_contract_reference, + "released_owner_contract", + ) + auxiliary_owner_ver = _require_positive_integer( + "auxiliary_owner_contract_version", auxiliary_owner_contract_version + ) + auxiliary_owner_evidence = _require_digest( + "auxiliary_owner_contract_digest", auxiliary_owner_contract_digest + ) + auxiliary_authorization_ref = _require_reference( + "auxiliary_authorization_receipt_reference", + auxiliary_authorization_receipt_reference, + "scientific_data_authorization", + ) + auxiliary_authorization_evidence = _require_digest( + "auxiliary_authorization_receipt_digest", + auxiliary_authorization_receipt_digest, + ) + auxiliary_use_ref = _require_reference( + "auxiliary_scientific_use_receipt_reference", + auxiliary_scientific_use_receipt_reference, + "scientific_use_receipt", + ) + auxiliary_use_evidence = _require_digest( + "auxiliary_scientific_use_receipt_digest", + auxiliary_scientific_use_receipt_digest, + ) + auxiliary_use_at = _require_aware_datetime( + "auxiliary_scientific_use_at", auxiliary_scientific_use_at + ) + benchmark_ref = _require_reference( + "benchmark_receipt_reference", + benchmark_receipt_reference, + "calibration_benchmark_receipt", + ) + benchmark_version = _require_positive_integer( + "benchmark_receipt_version", benchmark_receipt_version + ) benchmark_digest = _require_digest( "benchmark_receipt_digest", benchmark_receipt_digest ) + benchmark_owner_ref = _require_reference( + "benchmark_owner_contract_reference", + benchmark_owner_contract_reference, + "released_owner_contract", + ) + benchmark_owner_ver = _require_positive_integer( + "benchmark_owner_contract_version", benchmark_owner_contract_version + ) + benchmark_owner_evidence = _require_digest( + "benchmark_owner_contract_digest", benchmark_owner_contract_digest + ) + benchmark_at = _require_aware_datetime( + "benchmark_reference_at", benchmark_reference_at + ) algorithm_ref = _require_reference( "algorithm_reference", algorithm_reference, "calibration_algorithm" ) @@ -165,6 +279,12 @@ def __new__( "output_weight_artifact_digest must identify the calibrated weight artifact." ) constructed = _require_aware_datetime("constructed_at", constructed_at) + if auxiliary_use_at > constructed: + raise ValueError( + "auxiliary_scientific_use_at cannot be later than constructed_at." + ) + if benchmark_at > constructed: + raise ValueError("benchmark_reference_at cannot be later than constructed_at.") fallback_values = ( fallback_reason_code, @@ -258,6 +378,25 @@ def __new__( release_instant, target_digest, analysis_window_ref, + auxiliary_authority_ref, + auxiliary_projection_ref, + auxiliary_projection_ver, + auxiliary_purpose_ref, + auxiliary_purpose_evidence, + auxiliary_owner_ref, + auxiliary_owner_ver, + auxiliary_owner_evidence, + auxiliary_authorization_ref, + auxiliary_authorization_evidence, + auxiliary_use_ref, + auxiliary_use_evidence, + auxiliary_use_at, + benchmark_ref, + benchmark_version, + benchmark_owner_ref, + benchmark_owner_ver, + benchmark_owner_evidence, + benchmark_at, ), ) @@ -358,27 +497,27 @@ def fallback_algorithm_version(self) -> int | None: @property def fallback_configuration_digest(self) -> str | None: - """Return the actual fallback configuration digest.""" + """Return the actual fallback configuration digest when fallback was applied.""" return self[19] @property def owner_contract_reference(self) -> str: - """Return the released owner-contract reference.""" + """Return the released application owner-contract reference.""" return self[20] @property def owner_contract_version(self) -> int: - """Return the released owner-contract version.""" + """Return the released application owner-contract version.""" return self[21] @property def owner_contract_digest(self) -> str: - """Return the released owner-contract digest.""" + """Return the released application owner-contract digest.""" return self[22] @property def owner_contract_released_at(self) -> datetime: - """Return when the governing owner contract became released authority.""" + """Return when the governing application owner contract became authority.""" return self[23] @property @@ -396,6 +535,101 @@ def analysis_window_reference(self) -> str: """Return the analysis window governed by the calibration receipt.""" return self[26] + @property + def auxiliary_authority_reference(self) -> str: + """Return the scientific auxiliary-authority reference.""" + return self[27] + + @property + def auxiliary_projection_reference(self) -> str: + """Return the exact purpose-limited auxiliary projection reference.""" + return self[28] + + @property + def auxiliary_projection_version(self) -> int: + """Return the exact purpose-limited auxiliary projection version.""" + return self[29] + + @property + def auxiliary_purpose_reference(self) -> str: + """Return the scientific data-use purpose reference.""" + return self[30] + + @property + def auxiliary_purpose_digest(self) -> str: + """Return the scientific data-use purpose digest.""" + return self[31] + + @property + def auxiliary_owner_contract_reference(self) -> str: + """Return the auxiliary owner's released contract reference.""" + return self[32] + + @property + def auxiliary_owner_contract_version(self) -> int: + """Return the auxiliary owner's released contract version.""" + return self[33] + + @property + def auxiliary_owner_contract_digest(self) -> str: + """Return the auxiliary owner's released contract digest.""" + return self[34] + + @property + def auxiliary_authorization_receipt_reference(self) -> str: + """Return the purpose-bound auxiliary authorization receipt reference.""" + return self[35] + + @property + def auxiliary_authorization_receipt_digest(self) -> str: + """Return the purpose-bound auxiliary authorization receipt digest.""" + return self[36] + + @property + def auxiliary_scientific_use_receipt_reference(self) -> str: + """Return the scientific-use receipt reference.""" + return self[37] + + @property + def auxiliary_scientific_use_receipt_digest(self) -> str: + """Return the scientific-use receipt digest.""" + return self[38] + + @property + def auxiliary_scientific_use_at(self) -> datetime: + """Return the exact scientific-use instant committed by the receipt.""" + return self[39] + + @property + def benchmark_receipt_reference(self) -> str: + """Return the exact calibration benchmark receipt reference.""" + return self[40] + + @property + def benchmark_receipt_version(self) -> int: + """Return the exact calibration benchmark receipt version.""" + return self[41] + + @property + def benchmark_owner_contract_reference(self) -> str: + """Return the benchmark owner's released contract reference.""" + return self[42] + + @property + def benchmark_owner_contract_version(self) -> int: + """Return the benchmark owner's released contract version.""" + return self[43] + + @property + def benchmark_owner_contract_digest(self) -> str: + """Return the benchmark owner's released contract digest.""" + return self[44] + + @property + def benchmark_reference_at(self) -> datetime: + """Return the exact benchmark reference instant committed by the receipt.""" + return self[45] + class CalibrationAdjustmentAuthorityView(tuple): """Field-minimized typed calibration evidence issued only after authorization.""" @@ -445,8 +679,27 @@ def read_calibration_adjustment_authority( evidence_version: int, target_population_digest: str, analysis_window_reference: str, + auxiliary_authority_reference: str, + auxiliary_projection_reference: str, + auxiliary_projection_version: int, auxiliary_projection_digest: str, + auxiliary_purpose_reference: str, + auxiliary_purpose_digest: str, + auxiliary_owner_contract_reference: str, + auxiliary_owner_contract_version: int, + auxiliary_owner_contract_digest: str, + auxiliary_authorization_receipt_reference: str, + auxiliary_authorization_receipt_digest: str, + auxiliary_scientific_use_receipt_reference: str, + auxiliary_scientific_use_receipt_digest: str, + auxiliary_scientific_use_at: datetime, + benchmark_receipt_reference: str, + benchmark_receipt_version: int, benchmark_receipt_digest: str, + benchmark_owner_contract_reference: str, + benchmark_owner_contract_version: int, + benchmark_owner_contract_digest: str, + benchmark_reference_at: datetime, algorithm_reference: str, algorithm_version: int, constraints_digest: str, @@ -475,7 +728,7 @@ def read_calibration_adjustment_authority( def _coordinate_tuple(record: CalibrationAdjustmentAuthorityRecord) -> tuple[object, ...]: """Return caller-known coordinates, excluding owner-resolved release instants.""" - return record[:23] + record[25:27] + return record[:23] + record[25:46] def resolve_calibration_adjustment_authority( @@ -488,8 +741,27 @@ def resolve_calibration_adjustment_authority( evidence_version: int, target_population_digest: str, analysis_window_reference: str, + auxiliary_authority_reference: str, + auxiliary_projection_reference: str, + auxiliary_projection_version: int, auxiliary_projection_digest: str, + auxiliary_purpose_reference: str, + auxiliary_purpose_digest: str, + auxiliary_owner_contract_reference: str, + auxiliary_owner_contract_version: int, + auxiliary_owner_contract_digest: str, + auxiliary_authorization_receipt_reference: str, + auxiliary_authorization_receipt_digest: str, + auxiliary_scientific_use_receipt_reference: str, + auxiliary_scientific_use_receipt_digest: str, + auxiliary_scientific_use_at: datetime, + benchmark_receipt_reference: str, + benchmark_receipt_version: int, benchmark_receipt_digest: str, + benchmark_owner_contract_reference: str, + benchmark_owner_contract_version: int, + benchmark_owner_contract_digest: str, + benchmark_reference_at: datetime, algorithm_reference: str, algorithm_version: int, constraints_digest: str, @@ -541,8 +813,27 @@ def resolve_calibration_adjustment_authority( evidence_version=evidence_version, target_population_digest=target_population_digest, analysis_window_reference=analysis_window_reference, + auxiliary_authority_reference=auxiliary_authority_reference, + auxiliary_projection_reference=auxiliary_projection_reference, + auxiliary_projection_version=auxiliary_projection_version, auxiliary_projection_digest=auxiliary_projection_digest, + auxiliary_purpose_reference=auxiliary_purpose_reference, + auxiliary_purpose_digest=auxiliary_purpose_digest, + auxiliary_owner_contract_reference=auxiliary_owner_contract_reference, + auxiliary_owner_contract_version=auxiliary_owner_contract_version, + auxiliary_owner_contract_digest=auxiliary_owner_contract_digest, + auxiliary_authorization_receipt_reference=auxiliary_authorization_receipt_reference, + auxiliary_authorization_receipt_digest=auxiliary_authorization_receipt_digest, + auxiliary_scientific_use_receipt_reference=auxiliary_scientific_use_receipt_reference, + auxiliary_scientific_use_receipt_digest=auxiliary_scientific_use_receipt_digest, + auxiliary_scientific_use_at=auxiliary_scientific_use_at, + benchmark_receipt_reference=benchmark_receipt_reference, + benchmark_receipt_version=benchmark_receipt_version, benchmark_receipt_digest=benchmark_receipt_digest, + benchmark_owner_contract_reference=benchmark_owner_contract_reference, + benchmark_owner_contract_version=benchmark_owner_contract_version, + benchmark_owner_contract_digest=benchmark_owner_contract_digest, + benchmark_reference_at=benchmark_reference_at, algorithm_reference=algorithm_reference, algorithm_version=algorithm_version, constraints_digest=constraints_digest, @@ -593,8 +884,27 @@ def resolve_calibration_adjustment_authority( evidence_version=requested.evidence_version, target_population_digest=requested.target_population_digest, analysis_window_reference=requested.analysis_window_reference, + auxiliary_authority_reference=requested.auxiliary_authority_reference, + auxiliary_projection_reference=requested.auxiliary_projection_reference, + auxiliary_projection_version=requested.auxiliary_projection_version, auxiliary_projection_digest=requested.auxiliary_projection_digest, + auxiliary_purpose_reference=requested.auxiliary_purpose_reference, + auxiliary_purpose_digest=requested.auxiliary_purpose_digest, + auxiliary_owner_contract_reference=requested.auxiliary_owner_contract_reference, + auxiliary_owner_contract_version=requested.auxiliary_owner_contract_version, + auxiliary_owner_contract_digest=requested.auxiliary_owner_contract_digest, + auxiliary_authorization_receipt_reference=requested.auxiliary_authorization_receipt_reference, + auxiliary_authorization_receipt_digest=requested.auxiliary_authorization_receipt_digest, + auxiliary_scientific_use_receipt_reference=requested.auxiliary_scientific_use_receipt_reference, + auxiliary_scientific_use_receipt_digest=requested.auxiliary_scientific_use_receipt_digest, + auxiliary_scientific_use_at=requested.auxiliary_scientific_use_at, + benchmark_receipt_reference=requested.benchmark_receipt_reference, + benchmark_receipt_version=requested.benchmark_receipt_version, benchmark_receipt_digest=requested.benchmark_receipt_digest, + benchmark_owner_contract_reference=requested.benchmark_owner_contract_reference, + benchmark_owner_contract_version=requested.benchmark_owner_contract_version, + benchmark_owner_contract_digest=requested.benchmark_owner_contract_digest, + benchmark_reference_at=requested.benchmark_reference_at, algorithm_reference=requested.algorithm_reference, algorithm_version=requested.algorithm_version, constraints_digest=requested.constraints_digest, @@ -627,8 +937,27 @@ def resolve_calibration_adjustment_authority( evidence_version=persisted.evidence_version, target_population_digest=persisted.target_population_digest, analysis_window_reference=persisted.analysis_window_reference, + auxiliary_authority_reference=persisted.auxiliary_authority_reference, + auxiliary_projection_reference=persisted.auxiliary_projection_reference, + auxiliary_projection_version=persisted.auxiliary_projection_version, auxiliary_projection_digest=persisted.auxiliary_projection_digest, + auxiliary_purpose_reference=persisted.auxiliary_purpose_reference, + auxiliary_purpose_digest=persisted.auxiliary_purpose_digest, + auxiliary_owner_contract_reference=persisted.auxiliary_owner_contract_reference, + auxiliary_owner_contract_version=persisted.auxiliary_owner_contract_version, + auxiliary_owner_contract_digest=persisted.auxiliary_owner_contract_digest, + auxiliary_authorization_receipt_reference=persisted.auxiliary_authorization_receipt_reference, + auxiliary_authorization_receipt_digest=persisted.auxiliary_authorization_receipt_digest, + auxiliary_scientific_use_receipt_reference=persisted.auxiliary_scientific_use_receipt_reference, + auxiliary_scientific_use_receipt_digest=persisted.auxiliary_scientific_use_receipt_digest, + auxiliary_scientific_use_at=persisted.auxiliary_scientific_use_at, + benchmark_receipt_reference=persisted.benchmark_receipt_reference, + benchmark_receipt_version=persisted.benchmark_receipt_version, benchmark_receipt_digest=persisted.benchmark_receipt_digest, + benchmark_owner_contract_reference=persisted.benchmark_owner_contract_reference, + benchmark_owner_contract_version=persisted.benchmark_owner_contract_version, + benchmark_owner_contract_digest=persisted.benchmark_owner_contract_digest, + benchmark_reference_at=persisted.benchmark_reference_at, algorithm_reference=persisted.algorithm_reference, algorithm_version=persisted.algorithm_version, constraints_digest=persisted.constraints_digest, @@ -661,8 +990,27 @@ def resolve_calibration_adjustment_authority( ("algorithm_reference", record.algorithm_reference), ("algorithm_version", record.algorithm_version), ("analysis_window_reference", record.analysis_window_reference), + ("auxiliary_authority_reference", record.auxiliary_authority_reference), + ("auxiliary_authorization_receipt_digest", record.auxiliary_authorization_receipt_digest), + ("auxiliary_authorization_receipt_reference", record.auxiliary_authorization_receipt_reference), + ("auxiliary_owner_contract_digest", record.auxiliary_owner_contract_digest), + ("auxiliary_owner_contract_reference", record.auxiliary_owner_contract_reference), + ("auxiliary_owner_contract_version", record.auxiliary_owner_contract_version), ("auxiliary_projection_digest", record.auxiliary_projection_digest), + ("auxiliary_projection_reference", record.auxiliary_projection_reference), + ("auxiliary_projection_version", record.auxiliary_projection_version), + ("auxiliary_purpose_digest", record.auxiliary_purpose_digest), + ("auxiliary_purpose_reference", record.auxiliary_purpose_reference), + ("auxiliary_scientific_use_at", record.auxiliary_scientific_use_at), + ("auxiliary_scientific_use_receipt_digest", record.auxiliary_scientific_use_receipt_digest), + ("auxiliary_scientific_use_receipt_reference", record.auxiliary_scientific_use_receipt_reference), + ("benchmark_owner_contract_digest", record.benchmark_owner_contract_digest), + ("benchmark_owner_contract_reference", record.benchmark_owner_contract_reference), + ("benchmark_owner_contract_version", record.benchmark_owner_contract_version), ("benchmark_receipt_digest", record.benchmark_receipt_digest), + ("benchmark_receipt_reference", record.benchmark_receipt_reference), + ("benchmark_receipt_version", record.benchmark_receipt_version), + ("benchmark_reference_at", record.benchmark_reference_at), ("calibration_receipt_digest", record.calibration_receipt_digest), ("calibration_receipt_reference", record.calibration_receipt_reference), ("constraints_digest", record.constraints_digest), From e998575620e4c2ac17b3c111612c59a711dab5dd Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 09:15:27 +0900 Subject: [PATCH 242/603] test(workforce-validation): align calibration context fixture with support authority --- ...alibration_adjustment_context_authority.py | 45 ++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_context_authority.py b/services/workforce-validation-api/tests/test_calibration_adjustment_context_authority.py index eac206556..9afda410e 100644 --- a/services/workforce-validation-api/tests/test_calibration_adjustment_context_authority.py +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_context_authority.py @@ -33,14 +33,49 @@ def _record() -> CalibrationAdjustmentAuthorityRecord: evidence_version=1, target_population_digest=TARGET_POPULATION_DIGEST, analysis_window_reference=ANALYSIS_WINDOW_REFERENCE, + auxiliary_authority_reference=( + "scientific_auxiliary_authority:33333333-3333-4333-8333-333333333333" + ), + auxiliary_projection_reference=( + "calibration_auxiliary_projection:44444444-4444-4444-8444-444444444444" + ), + auxiliary_projection_version=2, auxiliary_projection_digest="2" * 64, - benchmark_receipt_digest="3" * 64, + auxiliary_purpose_reference=( + "scientific_data_use_purpose:55555555-5555-4555-8555-555555555555" + ), + auxiliary_purpose_digest="3" * 64, + auxiliary_owner_contract_reference=( + "released_owner_contract:66666666-6666-4666-8666-666666666666" + ), + auxiliary_owner_contract_version=3, + auxiliary_owner_contract_digest="4" * 64, + auxiliary_authorization_receipt_reference=( + "scientific_data_authorization:77777777-7777-4777-8777-777777777777" + ), + auxiliary_authorization_receipt_digest="5" * 64, + auxiliary_scientific_use_receipt_reference=( + "scientific_use_receipt:88888888-8888-4888-8888-888888888888" + ), + auxiliary_scientific_use_receipt_digest="6" * 64, + auxiliary_scientific_use_at=datetime(2026, 9, 17, 7, 30, tzinfo=timezone.utc), + benchmark_receipt_reference=( + "calibration_benchmark_receipt:99999999-9999-4999-8999-999999999999" + ), + benchmark_receipt_version=4, + benchmark_receipt_digest="7" * 64, + benchmark_owner_contract_reference=( + "released_owner_contract:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" + ), + benchmark_owner_contract_version=5, + benchmark_owner_contract_digest="8" * 64, + benchmark_reference_at=datetime(2026, 9, 17, 7, 45, tzinfo=timezone.utc), algorithm_reference="calibration_algorithm:linear-raking", algorithm_version=1, - constraints_digest="4" * 64, + constraints_digest="9" * 64, termination_code="converged", - input_weight_artifact_digest="5" * 64, - output_weight_artifact_digest="6" * 64, + input_weight_artifact_digest="b" * 64, + output_weight_artifact_digest="c" * 64, constructed_at=CONSTRUCTED_AT, fallback_reason_code=None, fallback_rule_reference=None, @@ -52,7 +87,7 @@ def _record() -> CalibrationAdjustmentAuthorityRecord: "released_owner_contract:22222222-2222-4222-8222-222222222222" ), owner_contract_version=1, - owner_contract_digest="7" * 64, + owner_contract_digest="d" * 64, owner_contract_released_at=OWNER_RELEASED_AT, released_at=RELEASED_AT, ) From da365a4fb716a8cf621b78fa71f5b2ddd6419617 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 09:15:43 +0900 Subject: [PATCH 243/603] test(workforce-validation): align calibration chronology fixture --- ...on_adjustment_owner_contract_chronology.py | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_owner_contract_chronology.py b/services/workforce-validation-api/tests/test_calibration_adjustment_owner_contract_chronology.py index 6e6167dd7..85a923215 100644 --- a/services/workforce-validation-api/tests/test_calibration_adjustment_owner_contract_chronology.py +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_owner_contract_chronology.py @@ -29,8 +29,47 @@ def _record(**overrides: object) -> CalibrationAdjustmentAuthorityRecord: ), "calibration_receipt_digest": "1" * 64, "evidence_version": 1, + "target_population_digest": "a" * 64, + "analysis_window_reference": "analysis_window:2026q3", + "auxiliary_authority_reference": ( + "scientific_auxiliary_authority:44444444-4444-4444-8444-444444444444" + ), + "auxiliary_projection_reference": ( + "calibration_auxiliary_projection:55555555-5555-4555-8555-555555555555" + ), + "auxiliary_projection_version": 2, "auxiliary_projection_digest": "2" * 64, + "auxiliary_purpose_reference": ( + "scientific_data_use_purpose:66666666-6666-4666-8666-666666666666" + ), + "auxiliary_purpose_digest": "8" * 64, + "auxiliary_owner_contract_reference": ( + "released_owner_contract:77777777-7777-4777-8777-777777777777" + ), + "auxiliary_owner_contract_version": 3, + "auxiliary_owner_contract_digest": "9" * 64, + "auxiliary_authorization_receipt_reference": ( + "scientific_data_authorization:88888888-8888-4888-8888-888888888888" + ), + "auxiliary_authorization_receipt_digest": "a" * 64, + "auxiliary_scientific_use_receipt_reference": ( + "scientific_use_receipt:99999999-9999-4999-8999-999999999999" + ), + "auxiliary_scientific_use_receipt_digest": "b" * 64, + "auxiliary_scientific_use_at": datetime( + 2026, 9, 16, 11, 0, tzinfo=timezone.utc + ), + "benchmark_receipt_reference": ( + "calibration_benchmark_receipt:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" + ), + "benchmark_receipt_version": 4, "benchmark_receipt_digest": "3" * 64, + "benchmark_owner_contract_reference": ( + "released_owner_contract:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" + ), + "benchmark_owner_contract_version": 4, + "benchmark_owner_contract_digest": "c" * 64, + "benchmark_reference_at": datetime(2026, 9, 16, 11, 30, tzinfo=timezone.utc), "algorithm_reference": "calibration_algorithm:raking", "algorithm_version": 2, "constraints_digest": "4" * 64, From 2ff76247322795f098be6afdbb962ebc750ba672 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 09:16:32 +0900 Subject: [PATCH 244/603] test(workforce-validation): verify complete calibration support provenance --- .../test_calibration_adjustment_authority.py | 156 +++++++++++++++--- 1 file changed, 135 insertions(+), 21 deletions(-) diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py b/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py index bb829f581..4b375b771 100644 --- a/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py @@ -24,17 +24,32 @@ OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000d2") RECEIPT_REFERENCE = "calibration_adjustment_receipt:11111111-1111-4111-8111-111111111111" OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +AUXILIARY_AUTHORITY_REFERENCE = "scientific_auxiliary_authority:33333333-3333-4333-8333-333333333333" +AUXILIARY_PROJECTION_REFERENCE = "calibration_auxiliary_projection:44444444-4444-4444-8444-444444444444" +AUXILIARY_PURPOSE_REFERENCE = "scientific_data_use_purpose:55555555-5555-4555-8555-555555555555" +AUXILIARY_OWNER_CONTRACT_REFERENCE = "released_owner_contract:66666666-6666-4666-8666-666666666666" +AUXILIARY_AUTHORIZATION_REFERENCE = "scientific_data_authorization:77777777-7777-4777-8777-777777777777" +AUXILIARY_USE_REFERENCE = "scientific_use_receipt:88888888-8888-4888-8888-888888888888" +BENCHMARK_RECEIPT_REFERENCE = "calibration_benchmark_receipt:99999999-9999-4999-8999-999999999999" +BENCHMARK_OWNER_CONTRACT_REFERENCE = "released_owner_contract:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" RECEIPT_DIGEST = "1" * 64 TARGET_POPULATION_DIGEST = "a" * 64 -ANALYSIS_WINDOW_REFERENCE = "analysis_window:2026q3" AUXILIARY_PROJECTION_DIGEST = "2" * 64 -BENCHMARK_RECEIPT_DIGEST = "3" * 64 -CONSTRAINTS_DIGEST = "4" * 64 -INPUT_WEIGHT_DIGEST = "5" * 64 -OUTPUT_WEIGHT_DIGEST = "6" * 64 -FALLBACK_RULE_DIGEST = "7" * 64 -FALLBACK_CONFIGURATION_DIGEST = "8" * 64 -OWNER_CONTRACT_DIGEST = "9" * 64 +AUXILIARY_PURPOSE_DIGEST = "3" * 64 +AUXILIARY_OWNER_CONTRACT_DIGEST = "4" * 64 +AUXILIARY_AUTHORIZATION_DIGEST = "5" * 64 +AUXILIARY_USE_DIGEST = "6" * 64 +BENCHMARK_RECEIPT_DIGEST = "7" * 64 +BENCHMARK_OWNER_CONTRACT_DIGEST = "8" * 64 +CONSTRAINTS_DIGEST = "9" * 64 +INPUT_WEIGHT_DIGEST = "b" * 64 +OUTPUT_WEIGHT_DIGEST = "c" * 64 +FALLBACK_RULE_DIGEST = "d" * 64 +FALLBACK_CONFIGURATION_DIGEST = "e" * 64 +OWNER_CONTRACT_DIGEST = "f" * 64 +ANALYSIS_WINDOW_REFERENCE = "analysis_window:2026q3" +AUXILIARY_USE_AT = datetime(2026, 9, 16, 11, 0, tzinfo=timezone.utc) +BENCHMARK_REFERENCE_AT = datetime(2026, 9, 16, 11, 30, tzinfo=timezone.utc) CONSTRUCTED_AT = datetime(2026, 9, 16, 12, 0, tzinfo=timezone.utc) OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 16, 12, 30, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc) @@ -46,8 +61,27 @@ "evidence_version", "target_population_digest", "analysis_window_reference", + "auxiliary_authority_reference", + "auxiliary_projection_reference", + "auxiliary_projection_version", "auxiliary_projection_digest", + "auxiliary_purpose_reference", + "auxiliary_purpose_digest", + "auxiliary_owner_contract_reference", + "auxiliary_owner_contract_version", + "auxiliary_owner_contract_digest", + "auxiliary_authorization_receipt_reference", + "auxiliary_authorization_receipt_digest", + "auxiliary_scientific_use_receipt_reference", + "auxiliary_scientific_use_receipt_digest", + "auxiliary_scientific_use_at", + "benchmark_receipt_reference", + "benchmark_receipt_version", "benchmark_receipt_digest", + "benchmark_owner_contract_reference", + "benchmark_owner_contract_version", + "benchmark_owner_contract_digest", + "benchmark_reference_at", "algorithm_reference", "algorithm_version", "constraints_digest", @@ -140,8 +174,27 @@ def _record(**overrides: object) -> CalibrationAdjustmentAuthorityRecord: "evidence_version": 1, "target_population_digest": TARGET_POPULATION_DIGEST, "analysis_window_reference": ANALYSIS_WINDOW_REFERENCE, + "auxiliary_authority_reference": AUXILIARY_AUTHORITY_REFERENCE, + "auxiliary_projection_reference": AUXILIARY_PROJECTION_REFERENCE, + "auxiliary_projection_version": 2, "auxiliary_projection_digest": AUXILIARY_PROJECTION_DIGEST, + "auxiliary_purpose_reference": AUXILIARY_PURPOSE_REFERENCE, + "auxiliary_purpose_digest": AUXILIARY_PURPOSE_DIGEST, + "auxiliary_owner_contract_reference": AUXILIARY_OWNER_CONTRACT_REFERENCE, + "auxiliary_owner_contract_version": 3, + "auxiliary_owner_contract_digest": AUXILIARY_OWNER_CONTRACT_DIGEST, + "auxiliary_authorization_receipt_reference": AUXILIARY_AUTHORIZATION_REFERENCE, + "auxiliary_authorization_receipt_digest": AUXILIARY_AUTHORIZATION_DIGEST, + "auxiliary_scientific_use_receipt_reference": AUXILIARY_USE_REFERENCE, + "auxiliary_scientific_use_receipt_digest": AUXILIARY_USE_DIGEST, + "auxiliary_scientific_use_at": AUXILIARY_USE_AT, + "benchmark_receipt_reference": BENCHMARK_RECEIPT_REFERENCE, + "benchmark_receipt_version": 4, "benchmark_receipt_digest": BENCHMARK_RECEIPT_DIGEST, + "benchmark_owner_contract_reference": BENCHMARK_OWNER_CONTRACT_REFERENCE, + "benchmark_owner_contract_version": 5, + "benchmark_owner_contract_digest": BENCHMARK_OWNER_CONTRACT_DIGEST, + "benchmark_reference_at": BENCHMARK_REFERENCE_AT, "algorithm_reference": "calibration_algorithm:generalized_regression", "algorithm_version": 3, "constraints_digest": CONSTRAINTS_DIGEST, @@ -175,8 +228,27 @@ def _resolve(*, read_port: object, **overrides: object) -> CalibrationAdjustment "evidence_version": 1, "target_population_digest": TARGET_POPULATION_DIGEST, "analysis_window_reference": ANALYSIS_WINDOW_REFERENCE, + "auxiliary_authority_reference": AUXILIARY_AUTHORITY_REFERENCE, + "auxiliary_projection_reference": AUXILIARY_PROJECTION_REFERENCE, + "auxiliary_projection_version": 2, "auxiliary_projection_digest": AUXILIARY_PROJECTION_DIGEST, + "auxiliary_purpose_reference": AUXILIARY_PURPOSE_REFERENCE, + "auxiliary_purpose_digest": AUXILIARY_PURPOSE_DIGEST, + "auxiliary_owner_contract_reference": AUXILIARY_OWNER_CONTRACT_REFERENCE, + "auxiliary_owner_contract_version": 3, + "auxiliary_owner_contract_digest": AUXILIARY_OWNER_CONTRACT_DIGEST, + "auxiliary_authorization_receipt_reference": AUXILIARY_AUTHORIZATION_REFERENCE, + "auxiliary_authorization_receipt_digest": AUXILIARY_AUTHORIZATION_DIGEST, + "auxiliary_scientific_use_receipt_reference": AUXILIARY_USE_REFERENCE, + "auxiliary_scientific_use_receipt_digest": AUXILIARY_USE_DIGEST, + "auxiliary_scientific_use_at": AUXILIARY_USE_AT, + "benchmark_receipt_reference": BENCHMARK_RECEIPT_REFERENCE, + "benchmark_receipt_version": 4, "benchmark_receipt_digest": BENCHMARK_RECEIPT_DIGEST, + "benchmark_owner_contract_reference": BENCHMARK_OWNER_CONTRACT_REFERENCE, + "benchmark_owner_contract_version": 5, + "benchmark_owner_contract_digest": BENCHMARK_OWNER_CONTRACT_DIGEST, + "benchmark_reference_at": BENCHMARK_REFERENCE_AT, "algorithm_reference": "calibration_algorithm:generalized_regression", "algorithm_version": 3, "constraints_digest": CONSTRAINTS_DIGEST, @@ -214,11 +286,15 @@ def test_fallback_resolution_binds_actual_generating_method() -> None: assert port.calls[0]["calibration_receipt_digest"] == RECEIPT_DIGEST assert port.calls[0]["target_population_digest"] == TARGET_POPULATION_DIGEST assert port.calls[0]["analysis_window_reference"] == ANALYSIS_WINDOW_REFERENCE + assert port.calls[0]["auxiliary_projection_reference"] == AUXILIARY_PROJECTION_REFERENCE + assert port.calls[0]["benchmark_receipt_reference"] == BENCHMARK_RECEIPT_REFERENCE assert port.calls[0]["fallback_algorithm_reference"] == "calibration_algorithm:raking" assert view.tenant_record_id == TENANT assert view.validity_study_id == STUDY assert ("target_population_digest", TARGET_POPULATION_DIGEST) in view.fields assert ("analysis_window_reference", ANALYSIS_WINDOW_REFERENCE) in view.fields + assert ("auxiliary_projection_reference", AUXILIARY_PROJECTION_REFERENCE) in view.fields + assert ("benchmark_receipt_reference", BENCHMARK_RECEIPT_REFERENCE) in view.fields assert ("termination_code", "fallback_applied") in view.fields assert ("fallback_reason_code", "primary_nonconvergence") in view.fields assert ("fallback_rule_reference", "calibration_fallback_rule:cell-collapse-v2") in view.fields @@ -257,18 +333,30 @@ def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: [ {"tenant_record_id": OTHER_TENANT}, {"validity_study_id": OTHER_STUDY}, - {"calibration_receipt_digest": "b" * 64}, - {"target_population_digest": "c" * 64}, + {"calibration_receipt_digest": "0" * 64}, + {"target_population_digest": "1" * 64}, {"analysis_window_reference": "analysis_window:2026q4"}, - {"auxiliary_projection_digest": "d" * 64}, - {"benchmark_receipt_digest": "e" * 64}, + {"auxiliary_authority_reference": "scientific_auxiliary_authority:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb"}, + {"auxiliary_projection_reference": "calibration_auxiliary_projection:cccccccc-cccc-4ccc-8ccc-cccccccccccc"}, + {"auxiliary_projection_version": 8}, + {"auxiliary_projection_digest": "3" * 64}, + {"auxiliary_purpose_digest": "4" * 64}, + {"auxiliary_owner_contract_digest": "5" * 64}, + {"auxiliary_authorization_receipt_digest": "6" * 64}, + {"auxiliary_scientific_use_receipt_digest": "7" * 64}, + {"auxiliary_scientific_use_at": AUXILIARY_USE_AT - timedelta(seconds=1)}, + {"benchmark_receipt_reference": "calibration_benchmark_receipt:dddddddd-dddd-4ddd-8ddd-dddddddddddd"}, + {"benchmark_receipt_version": 9}, + {"benchmark_receipt_digest": "8" * 64}, + {"benchmark_owner_contract_digest": "9" * 64}, + {"benchmark_reference_at": BENCHMARK_REFERENCE_AT - timedelta(seconds=1)}, {"algorithm_reference": "calibration_algorithm:raking"}, {"algorithm_version": 9}, - {"constraints_digest": "f" * 64}, - {"input_weight_artifact_digest": "0" * 64}, - {"output_weight_artifact_digest": "a" * 64}, + {"constraints_digest": "0" * 64}, + {"input_weight_artifact_digest": "1" * 64}, + {"output_weight_artifact_digest": "2" * 64}, {"owner_contract_version": 7}, - {"owner_contract_digest": "b" * 64}, + {"owner_contract_digest": "3" * 64}, ], ) def test_owner_evidence_must_match_every_requested_coordinate( @@ -314,15 +402,34 @@ def test_converged_receipt_rejects_fallback_only_evidence() -> None: ("evidence_version", 2), ("target_population_digest", "a" * 63), ("analysis_window_reference", "wrong:window"), + ("auxiliary_authority_reference", "wrong:authority"), + ("auxiliary_projection_reference", "wrong:projection"), + ("auxiliary_projection_version", 0), + ("auxiliary_purpose_reference", "wrong:purpose"), + ("auxiliary_purpose_digest", "3" * 63), + ("auxiliary_owner_contract_reference", "wrong:contract"), + ("auxiliary_owner_contract_version", 0), + ("auxiliary_owner_contract_digest", "4" * 63), + ("auxiliary_authorization_receipt_reference", "wrong:authorization"), + ("auxiliary_authorization_receipt_digest", "5" * 63), + ("auxiliary_scientific_use_receipt_reference", "wrong:use"), + ("auxiliary_scientific_use_receipt_digest", "6" * 63), + ("auxiliary_scientific_use_at", datetime(2026, 9, 16, 11, 0)), + ("benchmark_receipt_reference", "wrong:benchmark"), + ("benchmark_receipt_version", 0), + ("benchmark_owner_contract_reference", "wrong:contract"), + ("benchmark_owner_contract_version", 0), + ("benchmark_owner_contract_digest", "8" * 63), + ("benchmark_reference_at", datetime(2026, 9, 16, 11, 30)), ("termination_code", "nonconverged"), ("algorithm_reference", "wrong:method"), ("algorithm_version", True), ("fallback_reason_code", "Primary Failure"), ("fallback_rule_reference", "wrong:rule"), - ("fallback_rule_digest", "7" * 63), + ("fallback_rule_digest", "d" * 63), ("fallback_algorithm_reference", "wrong:algorithm"), ("fallback_algorithm_version", 0), - ("fallback_configuration_digest", "8" * 65), + ("fallback_configuration_digest", "e" * 65), ], ) def test_malformed_calibration_or_fallback_evidence_fails_closed( @@ -334,6 +441,13 @@ def test_malformed_calibration_or_fallback_evidence_fails_closed( _record(**overrides) +def test_supporting_evidence_cannot_postdate_calibration_construction() -> None: + with pytest.raises(ValueError): + _record(auxiliary_scientific_use_at=CONSTRUCTED_AT + timedelta(seconds=1)) + with pytest.raises(ValueError): + _record(benchmark_reference_at=CONSTRUCTED_AT + timedelta(seconds=1)) + + def test_weight_artifact_and_release_chronology_fail_closed() -> None: with pytest.raises(ValueError): _record(output_weight_artifact_digest=INPUT_WEIGHT_DIGEST) @@ -358,15 +472,15 @@ def test_weight_artifact_and_release_chronology_fail_closed() -> None: ("target_population_digest", "a" * 63, ValueError), ("analysis_window_reference", "wrong:window", ValueError), ("auxiliary_projection_digest", "2" * 63, ValueError), - ("benchmark_receipt_digest", "3" * 65, ValueError), + ("benchmark_receipt_digest", "7" * 65, ValueError), ("algorithm_reference", "wrong:algorithm", ValueError), ("algorithm_version", 0, ValueError), - ("constraints_digest", "4" * 63, ValueError), + ("constraints_digest", "9" * 63, ValueError), ("termination_code", "failed", ValueError), ("constructed_at", datetime(2026, 9, 16, 12, 0), ValueError), ("owner_contract_reference", "wrong:contract", ValueError), ("owner_contract_version", 0, ValueError), - ("owner_contract_digest", "9" * 63, ValueError), + ("owner_contract_digest", "f" * 63, ValueError), ("used_at", datetime(2026, 9, 17), ValueError), ("purpose_code", "Selection Validity Analysis", ValueError), ], From 1266286ed8fa3f0fe164772b66f58bec0ee737ba Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 09:19:09 +0900 Subject: [PATCH 245/603] docs(workforce-validation): document complete calibration authority --- services/workforce-validation-api/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 361db9610..ca6757826 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -30,9 +30,9 @@ Foreign domain truth crosses this boundary only through released/versioned contr ## Typed calibration-adjustment authority -`resolve_calibration_adjustment_authority(...)` corroborates the exact released calibration receipt that produced a point-weight artifact. It binds the receipt/evidence version to purpose-limited auxiliary and benchmark digests, primary method, constraints, artifacts, construction time, and released owner contract. `fallback_applied` additionally requires the primary failure reason, immutable fallback rule, and actual fallback algorithm/version/configuration; `converged` rejects fallback-only evidence. Raw auxiliary values, benchmark totals, protected attributes, and row-level weights are excluded. +`resolve_calibration_adjustment_authority(...)` corroborates the exact released calibration receipt that produced a point-weight artifact. It binds the receipt/evidence version to the exact target-population digest and analysis-window reference, scientific auxiliary-authority reference, auxiliary projection reference/version/digest, scientific-use purpose reference/digest, auxiliary owner-contract reference/version/digest, authorization and scientific-use receipt references/digests plus scientific-use instant, benchmark receipt reference/version/digest, benchmark owner-contract reference/version/digest plus benchmark reference instant, primary method, constraints, artifacts, construction time, and the released application owner contract. `fallback_applied` additionally requires the primary failure reason, immutable fallback rule, and actual fallback algorithm/version/configuration; `converged` rejects fallback-only evidence. Raw auxiliary values, benchmark totals, protected attributes, and row-level weights are excluded. -The governing owner-contract release instant is canonical owner evidence, not a resolver request coordinate. It must be timezone-aware and no later than the calibration receipt release. A contract may legitimately be released after adjustment construction but before receipt release, while a later contract cannot retroactively authorize an already released calibration receipt. +The supporting auxiliary-use and benchmark-reference instants are caller-known receipt coordinates committed by the scientific calibration receipt and may not postdate calibration construction. The application owner-contract release instant is different: it is canonical owner evidence, not a resolver request coordinate. It must be timezone-aware and no later than the calibration receipt release. A contract may legitimately be released after adjustment construction but before receipt release, while a later contract cannot retroactively authorize an already released calibration receipt. Exact supporting references/versions/digests prevent the application owner from collapsing auxiliary or benchmark provenance to floating digest-only labels. ## Typed nonresponse-adjustment authority @@ -106,7 +106,7 @@ The failed-evidence release instant, verification-attempt release instant, gover The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; calibration-adjustment, nonresponse-adjustment, and trimming/bounding owner-contract release instants likewise come from durable owner records and must not postdate their released receipts. Base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; eligibility, final-weight, point-weight/variance compatibility, validation-result, and non-verifiability owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Base-weight and final-analysis-weight persistence must select released owner evidence by their complete caller-known reproducibility tuples; it may not select a partial receipt/source/design prefix and rely on a later in-memory mismatch check. Non-verifiability persistence must key the owner read by the exact immutable verification-attempt reference/digest, preserve `failed_evidence_released_at` for non-reproducible evidence, preserve owner-resolved `verification_attempt_released_at` for every verification attempt, prove `failed_evidence_released_at <= evaluated_at` when applicable, and prove `evaluated_at <= verification_attempt_released_at <= released_at`; missing evidence stores no fabricated failed-evidence release time. Low-level eligibility/final-weight/binding/non-verifiability adapters must therefore recover canonical chronology rather than independently infer currentness. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. The typed-calibration adapter must persist and exact-key the target-population digest, analysis-window reference, scientific auxiliary-authority reference, auxiliary projection reference/version/digest, purpose reference/digest, auxiliary owner-contract reference/version/digest, authorization and scientific-use receipts, scientific-use instant, benchmark receipt reference/version/digest, benchmark owner-contract reference/version/digest, and benchmark-reference instant together with method/artifact/fallback/application-owner coordinates. It may not reconstruct these from a mutable current row or trust only the opaque calibration receipt digest. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; calibration-adjustment, nonresponse-adjustment, and trimming/bounding owner-contract release instants likewise come from durable owner records and must not postdate their released receipts. Base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; eligibility, final-weight, point-weight/variance compatibility, validation-result, and non-verifiability owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Base-weight and final-analysis-weight persistence must select released owner evidence by their complete caller-known reproducibility tuples; it may not select a partial receipt/source/design prefix and rely on a later in-memory mismatch check. Non-verifiability persistence must key the owner read by the exact immutable verification-attempt reference/digest, preserve `failed_evidence_released_at` for non-reproducible evidence, preserve owner-resolved `verification_attempt_released_at` for every verification attempt, prove `failed_evidence_released_at <= evaluated_at` when applicable, and prove `evaluated_at <= verification_attempt_released_at <= released_at`; missing evidence stores no fabricated failed-evidence release time. Low-level eligibility/final-weight/binding/non-verifiability adapters must therefore recover canonical chronology rather than independently infer currentness. ## Test contract @@ -121,6 +121,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration fallback provenance and owner-contract chronology, typed nonresponse disposition/treatment provenance and owner-contract chronology, trimming/bounding rule/affected-case provenance and owner-contract chronology, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology and complete read-port lookup coordinates, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology, low-level final-weight currentness, and complete final-weight read-port lookup coordinates, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, and explicit missing/non-reproducible result evidence including owner-contract chronology, failed-evidence release chronology, exact verification-attempt lookup-key completeness, verification-attempt release chronology, and owner-resolved negative-outcome cutover. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration target-population/analysis-window binding, complete auxiliary/benchmark supporting-authority identity and reference-time chronology, fallback provenance and owner-contract chronology, typed nonresponse disposition/treatment provenance and owner-contract chronology, trimming/bounding rule/affected-case provenance and owner-contract chronology, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology and complete read-port lookup coordinates, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology, low-level final-weight currentness, and complete final-weight read-port lookup coordinates, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, and explicit missing/non-reproducible result evidence including owner-contract chronology, failed-evidence release chronology, exact verification-attempt lookup-key completeness, verification-attempt release chronology, and owner-resolved negative-outcome cutover. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From c5d12e82d57e3269cb3104503d7697af83bf7577 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 10:02:26 +0900 Subject: [PATCH 246/603] test(workforce-validation): require eligibility successor authority --- ...ight_eligibility_supersession_authority.py | 257 ++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority.py diff --git a/services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority.py b/services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority.py new file mode 100644 index 000000000..15413b2d1 --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority.py @@ -0,0 +1,257 @@ +"""Fail closed when released weight-eligibility evidence has a successor.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from inspect import signature +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.weight_eligibility_supersession_authority import ( + WeightEligibilitySupersessionAuthorityIntegrityError, + WeightEligibilitySupersessionAuthorityRecord, + resolve_weight_eligibility_supersession_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RECEIPT_REFERENCE = "weight_eligibility_receipt:11111111-1111-4111-8111-111111111111" +SUCCESSOR_REFERENCE = "weight_eligibility_receipt:33333333-3333-4333-8333-333333333333" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +RECEIPT_DIGEST = "1" * 64 +SUCCESSOR_DIGEST = "3" * 64 +OWNER_CONTRACT_DIGEST = "2" * 64 +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 7, 1, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 7, 15, tzinfo=timezone.utc) +CUTOVER_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "eligibility_receipt_reference", + "eligibility_receipt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_eligibility_receipt_reference", + "successor_eligibility_receipt_digest", + "successor_evidence_version", + "successor_released_at", + } +) + + +class _ReadPort: + """Return one configured correction state through the owner read shape.""" + + def __init__(self, record: WeightEligibilitySupersessionAuthorityRecord) -> None: + self.record = record + + def read_weight_eligibility_supersession_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + eligibility_receipt_reference: str, + eligibility_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> WeightEligibilitySupersessionAuthorityRecord: + """Return owner evidence; the resolver verifies every current coordinate.""" + del ( + tenant_record_id, + validity_study_id, + eligibility_receipt_reference, + eligibility_receipt_digest, + evidence_version, + owner_contract_reference, + owner_contract_version, + owner_contract_digest, + ) + return self.record + + +def _principal() -> ValidationPrincipal: + """Return one exact workforce-validation principal.""" + return ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy() -> PurposeBoundAccessPolicy: + """Authorize the full internal correction evidence while minimizing the view.""" + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="weight-eligibility-supersession-read-v1", + resource_kind="weight_eligibility_supersession_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record( + *, + superseded_at: datetime | None = CUTOVER_AT, + successor_reference: str | None = SUCCESSOR_REFERENCE, + successor_digest: str | None = SUCCESSOR_DIGEST, + successor_evidence_version: int | None = 1, + successor_released_at: datetime | None = CUTOVER_AT, + owner_contract_released_at: datetime = OWNER_CONTRACT_RELEASED_AT, +) -> WeightEligibilitySupersessionAuthorityRecord: + """Build one canonical current or superseded eligibility authority record.""" + return WeightEligibilitySupersessionAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + eligibility_receipt_reference=RECEIPT_REFERENCE, + eligibility_receipt_digest=RECEIPT_DIGEST, + evidence_version=1, + owner_contract_reference=OWNER_CONTRACT_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_CONTRACT_DIGEST, + owner_contract_released_at=owner_contract_released_at, + released_at=RELEASED_AT, + superseded_at=superseded_at, + successor_eligibility_receipt_reference=successor_reference, + successor_eligibility_receipt_digest=successor_digest, + successor_evidence_version=successor_evidence_version, + successor_released_at=successor_released_at, + ) + + +def _resolve( + record: WeightEligibilitySupersessionAuthorityRecord, + *, + used_at: datetime, +): + """Resolve one historical eligibility authority instant.""" + return resolve_weight_eligibility_supersession_authority( + principal=_principal(), + tenant_record_id=TENANT, + validity_study_id=STUDY, + eligibility_receipt_reference=RECEIPT_REFERENCE, + eligibility_receipt_digest=RECEIPT_DIGEST, + evidence_version=1, + owner_contract_reference=OWNER_CONTRACT_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_CONTRACT_DIGEST, + used_at=used_at, + purpose_code="selection_validity_analysis", + policy=_policy(), + read_port=_ReadPort(record), + ) + + +def test_successor_chronology_is_owner_evidence_not_caller_input() -> None: + """Keep cutover and successor coordinates out of caller-controlled resolution.""" + parameters = signature(resolve_weight_eligibility_supersession_authority).parameters + assert "owner_contract_released_at" not in parameters + assert "released_at" not in parameters + assert "superseded_at" not in parameters + assert "successor_eligibility_receipt_reference" not in parameters + assert "successor_eligibility_receipt_digest" not in parameters + assert "successor_evidence_version" not in parameters + assert "successor_released_at" not in parameters + + +def test_historical_use_before_cutover_remains_verifiable_without_successor_disclosure() -> None: + """Allow predecessor reconstruction before cutover without leaking successor evidence.""" + view = _resolve(_record(), used_at=CUTOVER_AT - timedelta(microseconds=1)) + fields = dict(view.fields) + assert fields["eligibility_receipt_reference"] == RECEIPT_REFERENCE + assert fields["eligibility_receipt_digest"] == RECEIPT_DIGEST + assert fields["released_at"] == RELEASED_AT + assert "superseded_at" not in fields + assert "successor_eligibility_receipt_reference" not in fields + assert "successor_released_at" not in fields + + +def test_use_at_or_after_cutover_fails_closed() -> None: + """Reject stale eligibility evidence at the exact successor cutover and later.""" + record = _record() + for used_at in (CUTOVER_AT, CUTOVER_AT + timedelta(seconds=1)): + with pytest.raises(WeightEligibilitySupersessionAuthorityIntegrityError): + _resolve(record, used_at=used_at) + + +def test_owner_contract_cannot_retroactively_authorize_receipt() -> None: + """Require the governing contract to exist before eligibility release.""" + with pytest.raises(ValueError, match="owner contract"): + _record(owner_contract_released_at=RELEASED_AT + timedelta(microseconds=1)) + + +def test_unsuperseded_receipt_remains_current() -> None: + """Keep a released receipt current when no complete successor edge exists.""" + record = _record( + superseded_at=None, + successor_reference=None, + successor_digest=None, + successor_evidence_version=None, + successor_released_at=None, + ) + _resolve(record, used_at=CUTOVER_AT + timedelta(days=30)) + + +@pytest.mark.parametrize( + ( + "superseded_at", + "successor_reference", + "successor_digest", + "successor_evidence_version", + "successor_released_at", + ), + [ + (CUTOVER_AT, None, SUCCESSOR_DIGEST, 1, CUTOVER_AT), + (None, SUCCESSOR_REFERENCE, SUCCESSOR_DIGEST, 1, CUTOVER_AT), + (CUTOVER_AT, RECEIPT_REFERENCE, SUCCESSOR_DIGEST, 1, CUTOVER_AT), + (CUTOVER_AT, SUCCESSOR_REFERENCE, RECEIPT_DIGEST, 1, CUTOVER_AT), + (CUTOVER_AT, SUCCESSOR_REFERENCE, SUCCESSOR_DIGEST, 2, CUTOVER_AT), + ( + RELEASED_AT, + SUCCESSOR_REFERENCE, + SUCCESSOR_DIGEST, + 1, + RELEASED_AT, + ), + ( + CUTOVER_AT, + SUCCESSOR_REFERENCE, + SUCCESSOR_DIGEST, + 1, + CUTOVER_AT - timedelta(microseconds=1), + ), + ( + CUTOVER_AT, + SUCCESSOR_REFERENCE, + SUCCESSOR_DIGEST, + 1, + CUTOVER_AT + timedelta(microseconds=1), + ), + ], +) +def test_supersession_requires_one_complete_atomic_successor_edge( + superseded_at: datetime | None, + successor_reference: str | None, + successor_digest: str | None, + successor_evidence_version: int | None, + successor_released_at: datetime | None, +) -> None: + """Reject partial, self-referential, schema-floating, or non-atomic successor evidence.""" + with pytest.raises(ValueError): + _record( + superseded_at=superseded_at, + successor_reference=successor_reference, + successor_digest=successor_digest, + successor_evidence_version=successor_evidence_version, + successor_released_at=successor_released_at, + ) From 118ae855eed48a4a7dc923141420036eea9a4255 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 10:03:05 +0900 Subject: [PATCH 247/603] fix(workforce-validation): bind eligibility supersession successor --- ...ight_eligibility_supersession_authority.py | 475 ++++++++++++++++++ 1 file changed, 475 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_supersession_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_supersession_authority.py new file mode 100644 index 000000000..4c0b0b4da --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_supersession_authority.py @@ -0,0 +1,475 @@ +"""Corroborate append-only weight-eligibility correction authority. + +The ordinary eligibility projection proves which population, reference duration, +case set, and point-weight artifact one receipt governs. This boundary proves +when that released receipt remained authoritative and which released successor +ended its half-open authority interval. It keeps row-level weights and person +attributes behind their scientific owners. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + +_RESOURCE_KIND = "weight_eligibility_supersession_authority" +_OPERATION = "read" +_READ_FIELDS = frozenset( + { + "eligibility_receipt_reference", + "eligibility_receipt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_eligibility_receipt_reference", + "successor_eligibility_receipt_digest", + "successor_evidence_version", + "successor_released_at", + } +) +_VIEW_FIELDS = frozenset( + { + "eligibility_receipt_reference", + "eligibility_receipt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + } +) + + +class WeightEligibilitySupersessionAuthorityNotFound(LookupError): + """Indicate that no released owner evidence corroborates the eligibility receipt.""" + + +class WeightEligibilitySupersessionAuthorityIntegrityError(RuntimeError): + """Indicate that released eligibility correction evidence cannot authorize use.""" + + +class WeightEligibilitySupersessionAuthorityRecord(tuple): + """Immutable owner projection for one eligibility receipt authority interval.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + eligibility_receipt_reference: str, + eligibility_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + owner_contract_released_at: datetime, + released_at: datetime, + superseded_at: datetime | None = None, + successor_eligibility_receipt_reference: str | None = None, + successor_eligibility_receipt_digest: str | None = None, + successor_evidence_version: int | None = None, + successor_released_at: datetime | None = None, + ) -> WeightEligibilitySupersessionAuthorityRecord: + """Validate one released predecessor and its optional atomic successor edge.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + receipt_ref = _require_reference( + "eligibility_receipt_reference", + eligibility_receipt_reference, + "weight_eligibility_receipt", + ) + receipt_digest = _require_digest( + "eligibility_receipt_digest", eligibility_receipt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + owner_release = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) + release_instant = _require_aware_datetime("released_at", released_at) + if owner_release > release_instant: + raise ValueError( + "owner contract must be released no later than weight-eligibility receipt." + ) + + successor_values = ( + superseded_at, + successor_eligibility_receipt_reference, + successor_eligibility_receipt_digest, + successor_evidence_version, + successor_released_at, + ) + if all(value is None for value in successor_values): + cutover = None + successor_ref = None + successor_digest = None + successor_version = None + successor_release = None + elif any(value is None for value in successor_values): + raise ValueError( + "eligibility supersession requires cutover and complete released successor coordinates." + ) + else: + cutover = _require_aware_datetime("superseded_at", superseded_at) + successor_ref = _require_reference( + "successor_eligibility_receipt_reference", + successor_eligibility_receipt_reference, + "weight_eligibility_receipt", + ) + successor_digest = _require_digest( + "successor_eligibility_receipt_digest", + successor_eligibility_receipt_digest, + ) + successor_version = _require_positive_integer( + "successor_evidence_version", successor_evidence_version + ) + successor_release = _require_aware_datetime( + "successor_released_at", successor_released_at + ) + if cutover <= release_instant: + raise ValueError("superseded_at must be later than eligibility receipt release.") + if successor_ref == receipt_ref: + raise ValueError("successor eligibility receipt must have a new reference.") + if successor_digest == receipt_digest: + raise ValueError("successor eligibility receipt must identify new evidence.") + if successor_version != 1: + raise ValueError("successor_evidence_version must remain 1.") + if successor_release <= release_instant: + raise ValueError( + "successor eligibility receipt must be released after its predecessor." + ) + if successor_release != cutover: + raise ValueError( + "successor eligibility receipt must be released exactly at supersession." + ) + + current_fields: tuple[tuple[str, object], ...] = ( + ("eligibility_receipt_digest", receipt_digest), + ("eligibility_receipt_reference", receipt_ref), + ("evidence_version", version), + ("owner_contract_digest", owner_digest), + ("owner_contract_reference", owner_ref), + ("owner_contract_released_at", owner_release), + ("owner_contract_version", owner_version), + ) + successor_fields: tuple[tuple[str, object], ...] | None + if cutover is None: + successor_fields = None + else: + successor_fields = ( + ("successor_eligibility_receipt_digest", successor_digest), + ("successor_eligibility_receipt_reference", successor_ref), + ("successor_evidence_version", successor_version), + ("successor_released_at", successor_release), + ) + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + current_fields, + release_instant, + cutover, + successor_fields, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable current-receipt authority coordinates.""" + return self[2] + + @property + def released_at(self) -> datetime: + """Return when this eligibility receipt became released authority.""" + return self[3] + + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive end of this receipt's authority interval.""" + return self[4] + + @property + def successor_fields(self) -> tuple[tuple[str, object], ...] | None: + """Return internal released successor coordinates, if any.""" + return self[5] + + +class WeightEligibilitySupersessionAuthorityView(tuple): + """Minimized current-receipt authority issued only after authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> WeightEligibilitySupersessionAuthorityView: + """Reject public construction; only the resolver may issue this view.""" + raise TypeError( + "WeightEligibilitySupersessionAuthorityView is issued only by " + "resolve_weight_eligibility_supersession_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return current eligibility authority without successor disclosure.""" + return self[2] + + +@runtime_checkable +class WeightEligibilitySupersessionAuthorityReadPort(Protocol): + """Owner read contract for one released eligibility correction state.""" + + def read_weight_eligibility_supersession_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + eligibility_receipt_reference: str, + eligibility_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> WeightEligibilitySupersessionAuthorityRecord | None: + """Return matching released eligibility supersession evidence or ``None``.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + WeightEligibilitySupersessionAuthorityReadPort, + "read_weight_eligibility_supersession_authority", +) + + +def resolve_weight_eligibility_supersession_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + eligibility_receipt_reference: str, + eligibility_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: WeightEligibilitySupersessionAuthorityReadPort, +) -> WeightEligibilitySupersessionAuthorityView: + """Authorize then resolve the receipt's half-open append-only authority interval.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static( + type(read_port), "read_weight_eligibility_supersession_authority", None + ) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError( + "read_port must expose a statically callable " + "read_weight_eligibility_supersession_authority." + ) + + tenant_id = _restore_operational_uuid( + "tenant_record_id", _store_operational_uuid("tenant_record_id", tenant_record_id) + ) + study_id = _restore_operational_uuid( + "validity_study_id", _store_operational_uuid("validity_study_id", validity_study_id) + ) + receipt_ref = _require_reference( + "eligibility_receipt_reference", + eligibility_receipt_reference, + "weight_eligibility_receipt", + ) + receipt_digest = _require_digest( + "eligibility_receipt_digest", eligibility_receipt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer("owner_contract_version", owner_contract_version) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=tenant_id, + validity_study_id=study_id, + eligibility_receipt_reference=receipt_ref, + eligibility_receipt_digest=receipt_digest, + evidence_version=version, + owner_contract_reference=owner_ref, + owner_contract_version=owner_version, + owner_contract_digest=owner_digest, + ) + if persisted is None: + raise WeightEligibilitySupersessionAuthorityNotFound(str(study_id)) + if type(persisted) is not WeightEligibilitySupersessionAuthorityRecord: + raise WeightEligibilitySupersessionAuthorityIntegrityError( + "owner port returned non-canonical weight-eligibility supersession evidence" + ) + + successor_values = None if persisted.successor_fields is None else dict(persisted.successor_fields) + record = WeightEligibilitySupersessionAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + successor_eligibility_receipt_reference=( + None + if successor_values is None + else successor_values["successor_eligibility_receipt_reference"] + ), + successor_eligibility_receipt_digest=( + None + if successor_values is None + else successor_values["successor_eligibility_receipt_digest"] + ), + successor_evidence_version=( + None + if successor_values is None + else successor_values["successor_evidence_version"] + ), + successor_released_at=( + None if successor_values is None else successor_values["successor_released_at"] + ), + **dict(persisted.fields), + ) + record_values = dict(record.fields) + if ( + _store_operational_uuid("record tenant_record_id", record.tenant_record_id) + != _store_operational_uuid("requested tenant_record_id", tenant_id) + or _store_operational_uuid("record validity_study_id", record.validity_study_id) + != _store_operational_uuid("requested validity_study_id", study_id) + or record_values["eligibility_receipt_reference"] != receipt_ref + or record_values["eligibility_receipt_digest"] != receipt_digest + or record_values["evidence_version"] != version + or record_values["owner_contract_reference"] != owner_ref + or record_values["owner_contract_version"] != owner_version + or record_values["owner_contract_digest"] != owner_digest + ): + raise WeightEligibilitySupersessionAuthorityIntegrityError( + "released eligibility supersession authority does not match requested coordinates" + ) + if use_instant < record.released_at: + raise WeightEligibilitySupersessionAuthorityIntegrityError( + "weight-eligibility authority cannot be used before its release instant" + ) + if record.superseded_at is not None and use_instant >= record.superseded_at: + raise WeightEligibilitySupersessionAuthorityIntegrityError( + "weight-eligibility authority cannot be used at or after supersession" + ) + + values = dict(record.fields) + values["released_at"] = record.released_at + fields = tuple((field_name, values[field_name]) for field_name in sorted(_VIEW_FIELDS)) + return tuple.__new__( + WeightEligibilitySupersessionAuthorityView, + ( + _store_operational_uuid("tenant_record_id", record.tenant_record_id), + _store_operational_uuid("validity_study_id", record.validity_study_id), + fields, + ), + ) + + +__all__ = [ + "WeightEligibilitySupersessionAuthorityIntegrityError", + "WeightEligibilitySupersessionAuthorityNotFound", + "WeightEligibilitySupersessionAuthorityReadPort", + "WeightEligibilitySupersessionAuthorityRecord", + "WeightEligibilitySupersessionAuthorityView", + "resolve_weight_eligibility_supersession_authority", +] From 27ba6efd982ca66490551707d8ac75c14023fafd Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 10:03:34 +0900 Subject: [PATCH 248/603] feat(workforce-validation): export eligibility supersession authority --- .../orgmetra_workforce_validation_api/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index d3b28338d..523a8c74b 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -114,6 +114,14 @@ WeightEligibilityAuthorityView, resolve_weight_eligibility_authority, ) +from orgmetra_workforce_validation_api.weight_eligibility_supersession_authority import ( + WeightEligibilitySupersessionAuthorityIntegrityError, + WeightEligibilitySupersessionAuthorityNotFound, + WeightEligibilitySupersessionAuthorityReadPort, + WeightEligibilitySupersessionAuthorityRecord, + WeightEligibilitySupersessionAuthorityView, + resolve_weight_eligibility_supersession_authority, +) __all__ = [ "BaseWeightAuthorityIntegrityError", @@ -183,6 +191,11 @@ "WeightEligibilityAuthorityReadPort", "WeightEligibilityAuthorityRecord", "WeightEligibilityAuthorityView", + "WeightEligibilitySupersessionAuthorityIntegrityError", + "WeightEligibilitySupersessionAuthorityNotFound", + "WeightEligibilitySupersessionAuthorityReadPort", + "WeightEligibilitySupersessionAuthorityRecord", + "WeightEligibilitySupersessionAuthorityView", "WeightVarianceAuthorityIntegrityError", "WeightVarianceAuthorityNotFound", "WeightVarianceAuthorityReadPort", @@ -201,5 +214,6 @@ "resolve_validation_result_nonverifiability", "resolve_validation_result_supersession_authority", "resolve_weight_eligibility_authority", + "resolve_weight_eligibility_supersession_authority", "resolve_weight_variance_authority", ] From 7c0516ed23d4f09e605464df10ba76b3e1c9d2d9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 10:04:29 +0900 Subject: [PATCH 249/603] test(workforce-validation): cover eligibility supersession edges --- ...ligibility_supersession_authority_edges.py | 309 ++++++++++++++++++ 1 file changed, 309 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority_edges.py diff --git a/services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority_edges.py b/services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority_edges.py new file mode 100644 index 000000000..a7d6607a1 --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority_edges.py @@ -0,0 +1,309 @@ +"""Hostile edges for append-only weight-eligibility correction authority.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.weight_eligibility_supersession_authority import ( + WeightEligibilitySupersessionAuthorityIntegrityError, + WeightEligibilitySupersessionAuthorityNotFound, + WeightEligibilitySupersessionAuthorityReadPort, + WeightEligibilitySupersessionAuthorityRecord, + WeightEligibilitySupersessionAuthorityView, + resolve_weight_eligibility_supersession_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000d2") +RECEIPT_REFERENCE = "weight_eligibility_receipt:11111111-1111-4111-8111-111111111111" +OTHER_RECEIPT_REFERENCE = "weight_eligibility_receipt:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" +SUCCESSOR_REFERENCE = "weight_eligibility_receipt:33333333-3333-4333-8333-333333333333" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +OTHER_OWNER_CONTRACT_REFERENCE = "released_owner_contract:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" +RECEIPT_DIGEST = "1" * 64 +SUCCESSOR_DIGEST = "3" * 64 +OWNER_CONTRACT_DIGEST = "2" * 64 +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 7, 1, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 7, 15, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "eligibility_receipt_reference", + "eligibility_receipt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_eligibility_receipt_reference", + "successor_eligibility_receipt_digest", + "successor_evidence_version", + "successor_released_at", + } +) + + +class _ReadPort: + """Return configured authority and retain lookup coordinates.""" + + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[dict[str, object]] = [] + + def read_weight_eligibility_supersession_authority(self, **coordinates: object) -> object: + """Capture the owner lookup and return configured evidence.""" + self.calls.append(dict(coordinates)) + return self.result + + +class _NoReadMethod: + """Deliberately fail the owner-port protocol.""" + + +class _ProtocolOnly(WeightEligibilitySupersessionAuthorityReadPort): + """Inherit only the Protocol placeholder, not a concrete owner capability.""" + + +class _DescriptorReadPort: + """Expose a descriptor that static capability validation must reject.""" + + @property + def read_weight_eligibility_supersession_authority(self) -> object: + """Trip if dependency validation executes the descriptor.""" + raise AssertionError("descriptor must not execute") + + +def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: + """Return one exact workforce-validation principal.""" + return ValidationPrincipal( + tenant_record_id=tenant_record_id, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + """Return the purpose-bound policy for correction evidence.""" + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="weight-eligibility-supersession-authority-read-v1", + resource_kind="weight_eligibility_supersession_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record(**overrides: object) -> WeightEligibilitySupersessionAuthorityRecord: + """Build one current eligibility correction state.""" + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "eligibility_receipt_reference": RECEIPT_REFERENCE, + "eligibility_receipt_digest": RECEIPT_DIGEST, + "evidence_version": 1, + "owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "owner_contract_version": 3, + "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, + "released_at": RELEASED_AT, + "superseded_at": None, + "successor_eligibility_receipt_reference": None, + "successor_eligibility_receipt_digest": None, + "successor_evidence_version": None, + "successor_released_at": None, + } + values.update(overrides) + return WeightEligibilitySupersessionAuthorityRecord(**values) + + +def _resolve(*, read_port: object, **overrides: object) -> WeightEligibilitySupersessionAuthorityView: + """Resolve current eligibility authority with caller-known coordinates only.""" + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "eligibility_receipt_reference": RECEIPT_REFERENCE, + "eligibility_receipt_digest": RECEIPT_DIGEST, + "evidence_version": 1, + "owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "owner_contract_version": 3, + "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_weight_eligibility_supersession_authority(**values) + + +def test_current_receipt_resolution_uses_owner_chronology_without_successor() -> None: + """Resolve a current receipt and keep chronology out of the lookup key.""" + port = _ReadPort(_record()) + view = _resolve(read_port=port) + + assert isinstance(port, WeightEligibilitySupersessionAuthorityReadPort) + assert len(port.calls) == 1 + assert port.calls[0]["eligibility_receipt_reference"] == RECEIPT_REFERENCE + assert "owner_contract_released_at" not in port.calls[0] + assert "released_at" not in port.calls[0] + assert "superseded_at" not in port.calls[0] + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + fields = dict(view.fields) + assert fields["owner_contract_released_at"] == OWNER_CONTRACT_RELEASED_AT + assert fields["released_at"] == RELEASED_AT + assert "superseded_at" not in fields + + +def test_authorization_denial_happens_before_owner_resolution() -> None: + """Do not consult owner evidence when purpose authorization fails.""" + port = _ReadPort(_record()) + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, policy=_policy(purpose_code="audit_review")) + assert port.calls == [] + + +def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: + """Reject absent and non-canonical owner evidence.""" + with pytest.raises(WeightEligibilitySupersessionAuthorityNotFound): + _resolve(read_port=_ReadPort(None)) + with pytest.raises(WeightEligibilitySupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object())) + + +@pytest.mark.parametrize( + "record_overrides", + [ + {"tenant_record_id": OTHER_TENANT}, + {"validity_study_id": OTHER_STUDY}, + {"eligibility_receipt_reference": OTHER_RECEIPT_REFERENCE}, + {"eligibility_receipt_digest": "a" * 64}, + {"owner_contract_reference": OTHER_OWNER_CONTRACT_REFERENCE}, + {"owner_contract_version": 4}, + {"owner_contract_digest": "b" * 64}, + ], +) +def test_owner_evidence_must_match_every_requested_coordinate( + record_overrides: dict[str, object] +) -> None: + """Fail closed if the owner returns a different current receipt coordinate.""" + with pytest.raises(WeightEligibilitySupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(**record_overrides))) + + +def test_release_chronology_and_historical_use_are_distinct() -> None: + """Reject pre-release use while preserving history before a later cutover.""" + with pytest.raises(WeightEligibilitySupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(released_at=USED_AT + timedelta(seconds=1)))) + + cutover = USED_AT + timedelta(seconds=2) + record = _record( + superseded_at=cutover, + successor_eligibility_receipt_reference=SUCCESSOR_REFERENCE, + successor_eligibility_receipt_digest=SUCCESSOR_DIGEST, + successor_evidence_version=1, + successor_released_at=cutover, + ) + view = _resolve(read_port=_ReadPort(record)) + assert dict(view.fields)["eligibility_receipt_digest"] == RECEIPT_DIGEST + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("eligibility_receipt_reference", "wrong:receipt", ValueError), + ("eligibility_receipt_digest", "ABC", ValueError), + ("evidence_version", False, ValueError), + ("evidence_version", 2, ValueError), + ("owner_contract_reference", "wrong:contract", ValueError), + ("owner_contract_version", 0, ValueError), + ("owner_contract_digest", "2" * 63, ValueError), + ("used_at", datetime(2026, 9, 17), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_or_dependency_fails_before_owner_resolution( + key: str, value: object, error: type[Exception] +) -> None: + """Validate caller-controlled coordinates before touching the owner port.""" + port: object = _ReadPort(_record()) + overrides = {key: value} + if key == "read_port": + port = value + overrides = {} + with pytest.raises(error): + _resolve(read_port=port, **overrides) + if isinstance(port, _ReadPort): + assert port.calls == [] + + +def test_record_rejects_non_v1_evidence_and_public_view_construction() -> None: + """Keep receipt schema fixed and prevent forged minimized views.""" + with pytest.raises(ValueError, match="evidence_version must remain 1"): + _record(evidence_version=2) + with pytest.raises(TypeError, match="issued only by"): + WeightEligibilitySupersessionAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) + + +def test_successor_chronology_rejects_naive_or_predecessor_time() -> None: + """Require aware, post-predecessor, cutover-aligned successor release evidence.""" + with pytest.raises(ValueError): + _record( + superseded_at=datetime(2026, 9, 17), + successor_eligibility_receipt_reference=SUCCESSOR_REFERENCE, + successor_eligibility_receipt_digest=SUCCESSOR_DIGEST, + successor_evidence_version=1, + successor_released_at=datetime(2026, 9, 17, tzinfo=timezone.utc), + ) + with pytest.raises(ValueError): + _record( + superseded_at=USED_AT + timedelta(seconds=1), + successor_eligibility_receipt_reference=SUCCESSOR_REFERENCE, + successor_eligibility_receipt_digest=SUCCESSOR_DIGEST, + successor_evidence_version=1, + successor_released_at=RELEASED_AT, + ) + + +def test_record_and_view_are_structurally_immutable_and_uuid_views_are_detached() -> None: + """Detach UUIDs and reject mutation of owner records and minimized views.""" + tenant = UUID(str(TENANT)) + record = _record(tenant_record_id=tenant) + object.__setattr__(tenant, "int", OTHER_TENANT.int) + assert record.tenant_record_id == TENANT + assert record.validity_study_id == STUDY + assert record.released_at == RELEASED_AT + assert record.superseded_at is None + assert record.successor_fields is None + with pytest.raises(AttributeError): + object.__setattr__(record, "released_at", USED_AT) + + view = _resolve(read_port=_ReadPort(record)) + returned_tenant = view.tenant_record_id + object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) + assert view.tenant_record_id == TENANT + with pytest.raises(AttributeError): + object.__setattr__(view, "fields", ()) From b3abca1f32c3c0ae1108935341688915e1bdc62d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 10:05:32 +0900 Subject: [PATCH 250/603] docs(workforce-validation): document eligibility successor graph --- services/workforce-validation-api/README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index ca6757826..c221e1c38 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -52,6 +52,12 @@ The governing owner-contract release instant is also owner-resolved evidence and The governing owner-contract release instant and optional exclusive eligibility cutover are also owner-resolved evidence, not caller coordinates. The owner contract must exist no later than the eligibility receipt release, and the ordinary resolver enforces `[released_at, superseded_at)`. Historical scientific use before cutover remains reproducible; use at or after cutover fails closed. This prevents a corrected population, duration, eligible-case set, or point-weight artifact from leaving an older eligibility receipt apparently current merely because a consumer bypasses a higher-level correction path. +## Weight-eligibility supersession authority + +`resolve_weight_eligibility_supersession_authority(...)` closes the eligibility-specific part of #407 RED #10. An owner-resolved `superseded_at` on the ordinary eligibility projection is not by itself enough to prove which immutable released successor ended the predecessor's authority. The correction record therefore binds the current eligibility receipt reference/digest/evidence version to its release chronology and, when corrected, requires one complete successor receipt reference/digest/evidence version and successor release instant. + +The successor must identify new receipt evidence, remain on the governed v1 receipt contract, be released after its predecessor, and be released exactly at the predecessor cutover. The predecessor is authoritative only on `[released_at, superseded_at)`. Historical reconstruction before cutover remains valid; use at or after cutover fails closed. Successor coordinates are internal owner evidence and are omitted from the returned view. The durable adapter must make the ordinary eligibility projection's cutover agree with this graph rather than derive currentness from a mutable row or caller timestamp. + ## Base/design-weight authority `resolve_base_weight_authority(...)` corroborates the base/design-weight derivation instead of accepting `base_weight_evidence_digest` as an opaque caller label. It binds an exact released base-weight evidence receipt to the source-universe and sampling-design receipt references/versions/digests, their release chronology, the sampled occurrence set, an immutable digest of the stage-wise selection-probability evidence, the positive selection-stage count, base-weight method/version, resulting base-weight artifact, construction time, and released owner contract. @@ -76,7 +82,7 @@ Scientific use is evaluated against the owner-resolved half-open interval `[rele ## Point-weight / variance authority -`resolve_weight_variance_authority(...)` corroborates released #405 sampling evidence, final analysis-weight receipt, analytic-case occurrence set, weight-eligibility receipt digest, correction sequence, final point-weight artifact, separate #406 variance-design evidence, variance method/evidence semantics, and released owner contract. A variance receipt cannot alias the point-weight receipt, and approximation evidence cannot be represented as exact. The owner read is keyed by this complete compatibility tuple rather than an incomplete prefix, so multiple released bindings that share sampling or receipt identifiers cannot be ambiguously selected. The separate eligibility, base-weight, final analysis-weight, and final-weight supersession authorities supply the durable population/duration, selection-probability provenance, complete ordered point-weight lineage, and correction authority interval behind those compatibility coordinates. +`resolve_weight_variance_authority(...)` corroborates released #405 sampling evidence, final analysis-weight receipt, analytic-case occurrence set, weight-eligibility receipt digest, correction sequence, final point-weight artifact, separate #406 variance-design evidence, variance method/evidence semantics, and released owner contract. A variance receipt cannot alias the point-weight receipt, and approximation evidence cannot be represented as exact. The owner read is keyed by this complete compatibility tuple rather than an incomplete prefix, so multiple released bindings that share sampling or receipt identifiers cannot be ambiguously selected. The separate eligibility, eligibility-supersession, base-weight, final analysis-weight, and final-weight-supersession authorities supply the durable population/duration, append-only eligibility correction, selection-probability provenance, complete ordered point-weight lineage, and correction authority interval behind those compatibility coordinates. The compatibility binding itself now resolves the governing owner-contract release instant and an optional exclusive supersession cutover from canonical owner evidence. Neither is a caller request coordinate. The owner contract must already exist when the compatibility authority is released, and the ordinary resolver enforces the owner-resolved half-open interval `[released_at, superseded_at)`. Historical use before cutover remains reproducible; use at or after cutover fails closed. This prevents a corrected point-weight or variance-design lineage from leaving an older compatibility binding apparently current merely because a consumer bypassed a higher-level correction path. @@ -106,7 +112,7 @@ The failed-evidence release instant, verification-attempt release instant, gover The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. The typed-calibration adapter must persist and exact-key the target-population digest, analysis-window reference, scientific auxiliary-authority reference, auxiliary projection reference/version/digest, purpose reference/digest, auxiliary owner-contract reference/version/digest, authorization and scientific-use receipts, scientific-use instant, benchmark receipt reference/version/digest, benchmark owner-contract reference/version/digest, and benchmark-reference instant together with method/artifact/fallback/application-owner coordinates. It may not reconstruct these from a mutable current row or trust only the opaque calibration receipt digest. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; calibration-adjustment, nonresponse-adjustment, and trimming/bounding owner-contract release instants likewise come from durable owner records and must not postdate their released receipts. Base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; eligibility, final-weight, point-weight/variance compatibility, validation-result, and non-verifiability owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Base-weight and final-analysis-weight persistence must select released owner evidence by their complete caller-known reproducibility tuples; it may not select a partial receipt/source/design prefix and rely on a later in-memory mismatch check. Non-verifiability persistence must key the owner read by the exact immutable verification-attempt reference/digest, preserve `failed_evidence_released_at` for non-reproducible evidence, preserve owner-resolved `verification_attempt_released_at` for every verification attempt, prove `failed_evidence_released_at <= evaluated_at` when applicable, and prove `evaluated_at <= verification_attempt_released_at <= released_at`; missing evidence stores no fabricated failed-evidence release time. Low-level eligibility/final-weight/binding/non-verifiability adapters must therefore recover canonical chronology rather than independently infer currentness. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, weight-eligibility supersession, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. The typed-calibration adapter must persist and exact-key the target-population digest, analysis-window reference, scientific auxiliary-authority reference, auxiliary projection reference/version/digest, purpose reference/digest, auxiliary owner-contract reference/version/digest, authorization and scientific-use receipts, scientific-use instant, benchmark receipt reference/version/digest, benchmark owner-contract reference/version/digest, and benchmark-reference instant together with method/artifact/fallback/application-owner coordinates. It may not reconstruct these from a mutable current row or trust only the opaque calibration receipt digest. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; calibration-adjustment, nonresponse-adjustment, and trimming/bounding owner-contract release instants likewise come from durable owner records and must not postdate their released receipts. Base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, weight-eligibility, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; the ordinary eligibility projection's cutover must agree with the eligibility-supersession graph. Final-weight, point-weight/variance compatibility, validation-result, and non-verifiability owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Base-weight and final-analysis-weight persistence must select released owner evidence by their complete caller-known reproducibility tuples; it may not select a partial receipt/source/design prefix and rely on a later in-memory mismatch check. Non-verifiability persistence must key the owner read by the exact immutable verification-attempt reference/digest, preserve `failed_evidence_released_at` for non-reproducible evidence, preserve owner-resolved `verification_attempt_released_at` for every verification attempt, prove `failed_evidence_released_at <= evaluated_at` when applicable, and prove `evaluated_at <= verification_attempt_released_at <= released_at`; missing evidence stores no fabricated failed-evidence release time. Low-level eligibility/final-weight/binding/non-verifiability adapters must therefore recover canonical chronology rather than independently infer currentness. ## Test contract @@ -121,6 +127,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration target-population/analysis-window binding, complete auxiliary/benchmark supporting-authority identity and reference-time chronology, fallback provenance and owner-contract chronology, typed nonresponse disposition/treatment provenance and owner-contract chronology, trimming/bounding rule/affected-case provenance and owner-contract chronology, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology and complete read-port lookup coordinates, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology, low-level final-weight currentness, and complete final-weight read-port lookup coordinates, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, and explicit missing/non-reproducible result evidence including owner-contract chronology, failed-evidence release chronology, exact verification-attempt lookup-key completeness, verification-attempt release chronology, and owner-resolved negative-outcome cutover. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration target-population/analysis-window binding, complete auxiliary/benchmark supporting-authority identity and reference-time chronology, fallback provenance and owner-contract chronology, typed nonresponse disposition/treatment provenance and owner-contract chronology, trimming/bounding rule/affected-case provenance and owner-contract chronology, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, explicit eligibility predecessor/successor correction authority with exact release-at-cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology and complete read-port lookup coordinates, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology, low-level final-weight currentness and complete final-weight read-port lookup coordinates, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, and explicit missing/non-reproducible result evidence including owner-contract chronology, failed-evidence release chronology, exact verification-attempt lookup-key completeness, verification-attempt release chronology, and owner-resolved negative-outcome cutover. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From 77dc24adf38178947a28078b39a012a37dd28408 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 11:03:59 +0900 Subject: [PATCH 251/603] test(workforce-validation): establish nonresponse supersession RED --- ...sponse_adjustment_supersession_contract.py | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_contract.py diff --git a/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_contract.py b/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_contract.py new file mode 100644 index 000000000..93633841a --- /dev/null +++ b/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_contract.py @@ -0,0 +1,70 @@ +"""Regression contract for append-only nonresponse-adjustment corrections.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from inspect import signature +from uuid import uuid4 + +import pytest + +from orgmetra_workforce_validation_api.nonresponse_adjustment_authority import ( + NonresponseAdjustmentAuthorityRecord, +) +from orgmetra_workforce_validation_api.nonresponse_adjustment_supersession_authority import ( + NonresponseAdjustmentSupersessionAuthorityRecord, +) + + +def _released_at() -> datetime: + """Return a stable aware instant for chronology assertions.""" + return datetime(2026, 9, 18, 1, 0, tzinfo=timezone.utc) + + +def _supersession_record(**overrides: object) -> NonresponseAdjustmentSupersessionAuthorityRecord: + """Build one predecessor/successor edge with an atomic correction instant.""" + released_at = _released_at() + values: dict[str, object] = { + "tenant_record_id": uuid4(), + "validity_study_id": uuid4(), + "nonresponse_receipt_reference": "nonresponse_adjustment_receipt:old", + "nonresponse_receipt_digest": "a" * 64, + "evidence_version": 1, + "owner_contract_reference": "released_owner_contract:weighting-v1", + "owner_contract_version": 1, + "owner_contract_digest": "b" * 64, + "owner_contract_released_at": released_at - timedelta(minutes=5), + "released_at": released_at, + "superseded_at": released_at + timedelta(minutes=10), + "successor_nonresponse_receipt_reference": "nonresponse_adjustment_receipt:new", + "successor_nonresponse_receipt_digest": "c" * 64, + "successor_evidence_version": 1, + "successor_released_at": released_at + timedelta(minutes=10), + } + values.update(overrides) + return NonresponseAdjustmentSupersessionAuthorityRecord(**values) + + +def test_ordinary_nonresponse_authority_keeps_cutover_owner_resolved() -> None: + """Ordinary currentness accepts a cutover but never makes it a lookup coordinate.""" + record_parameters = signature(NonresponseAdjustmentAuthorityRecord).parameters + assert "superseded_at" in record_parameters + + +def test_nonresponse_supersession_requires_atomic_successor_release() -> None: + """A correction edge cannot leave an overlap or gap around the cutover.""" + _supersession_record() + with pytest.raises(ValueError, match="exactly at supersession"): + _supersession_record( + successor_released_at=_released_at() + timedelta(minutes=11) + ) + + +def test_nonresponse_supersession_requires_new_immutable_evidence() -> None: + """A predecessor cannot supersede itself or reuse its evidence digest.""" + with pytest.raises(ValueError, match="new reference"): + _supersession_record( + successor_nonresponse_receipt_reference="nonresponse_adjustment_receipt:old" + ) + with pytest.raises(ValueError, match="new evidence"): + _supersession_record(successor_nonresponse_receipt_digest="a" * 64) From a814294cb2c27b5abe3cdb9c0d4392b0517fd014 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 11:05:26 +0900 Subject: [PATCH 252/603] fix(workforce-validation): enforce nonresponse authority cutover --- .../nonresponse_adjustment_authority.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py index 07ef9542d..14575c359 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py @@ -61,6 +61,7 @@ "owner_contract_digest", "owner_contract_released_at", "released_at", + "superseded_at", } ) @@ -105,6 +106,7 @@ def __new__( owner_contract_digest: str, owner_contract_released_at: datetime, released_at: datetime, + superseded_at: datetime | None = None, ) -> NonresponseAdjustmentAuthorityRecord: """Validate and detach the minimum disposition-aware scientific authority.""" tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) @@ -176,12 +178,19 @@ def __new__( "owner_contract_released_at", owner_contract_released_at ) release_instant = _require_aware_datetime("released_at", released_at) + supersession_instant = ( + None + if superseded_at is None + else _require_aware_datetime("superseded_at", superseded_at) + ) if release_instant < constructed: raise ValueError("released_at cannot precede constructed_at.") if owner_released > release_instant: raise ValueError( "owner_contract_released_at cannot be later than released_at." ) + if supersession_instant is not None and supersession_instant <= release_instant: + raise ValueError("superseded_at must be later than released_at.") return tuple.__new__( cls, @@ -210,6 +219,7 @@ def __new__( owner_digest, owner_released, release_instant, + supersession_instant, ), ) @@ -333,6 +343,11 @@ def released_at(self) -> datetime: """Return when this typed nonresponse evidence became released authority.""" return self[23] + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive owner-resolved cutover for this receipt.""" + return self[24] + class NonresponseAdjustmentAuthorityView(tuple): """Field-minimized nonresponse evidence issued only after authorization.""" @@ -483,6 +498,7 @@ def resolve_nonresponse_adjustment_authority( owner_contract_digest=owner_contract_digest, owner_contract_released_at=constructed, released_at=constructed, + superseded_at=None, ) tenant_id = requested.tenant_record_id study_id = requested.validity_study_id @@ -567,6 +583,7 @@ def resolve_nonresponse_adjustment_authority( owner_contract_digest=persisted.owner_contract_digest, owner_contract_released_at=persisted.owner_contract_released_at, released_at=persisted.released_at, + superseded_at=persisted.superseded_at, ) if _coordinate_tuple(record) != _coordinate_tuple(requested): raise NonresponseAdjustmentAuthorityIntegrityError( @@ -576,6 +593,10 @@ def resolve_nonresponse_adjustment_authority( raise NonresponseAdjustmentAuthorityIntegrityError( "nonresponse-adjustment evidence must be released before scientific use" ) + if record.superseded_at is not None and use_instant >= record.superseded_at: + raise NonresponseAdjustmentAuthorityIntegrityError( + "nonresponse-adjustment evidence is superseded for this scientific-use instant" + ) fields: tuple[tuple[str, object], ...] = ( ("adjustment_population_digest", record.adjustment_population_digest), @@ -598,6 +619,7 @@ def resolve_nonresponse_adjustment_authority( ("response_disposition_receipt_reference", record.response_disposition_receipt_reference), ("response_disposition_receipt_released_at", record.response_disposition_receipt_released_at), ("response_disposition_receipt_version", record.response_disposition_receipt_version), + ("superseded_at", record.superseded_at), ("unavailable_treatment_code", record.unavailable_treatment_code), ("unknown_treatment_code", record.unknown_treatment_code), ) From 5e3bea2b78722c445b54ed0f5a41f1842aa45768 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 11:06:17 +0900 Subject: [PATCH 253/603] feat(workforce-validation): add nonresponse successor authority --- ...ponse_adjustment_supersession_authority.py | 467 ++++++++++++++++++ 1 file changed, 467 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_supersession_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_supersession_authority.py new file mode 100644 index 000000000..551ffc0be --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_supersession_authority.py @@ -0,0 +1,467 @@ +"""Corroborate append-only nonresponse-adjustment correction authority. + +The ordinary nonresponse projection proves which disposition-aware adjustment +receipt produced a released point-weight artifact. This boundary proves when +that immutable receipt remained authoritative and which released successor +ended its half-open authority interval. Successor chronology stays owner-resolved +instead of becoming a caller-selected lookup coordinate. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + +_RESOURCE_KIND = "nonresponse_adjustment_supersession_authority" +_OPERATION = "read" +_READ_FIELDS = frozenset( + { + "nonresponse_receipt_reference", + "nonresponse_receipt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_nonresponse_receipt_reference", + "successor_nonresponse_receipt_digest", + "successor_evidence_version", + "successor_released_at", + } +) + + +class NonresponseAdjustmentSupersessionAuthorityNotFound(LookupError): + """Indicate that no released owner evidence corroborates the receipt.""" + + +class NonresponseAdjustmentSupersessionAuthorityIntegrityError(RuntimeError): + """Indicate that released correction evidence cannot authorize use.""" + + +class NonresponseAdjustmentSupersessionAuthorityRecord(tuple): + """Immutable owner projection for one nonresponse receipt authority interval.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + nonresponse_receipt_reference: str, + nonresponse_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + owner_contract_released_at: datetime, + released_at: datetime, + superseded_at: datetime | None = None, + successor_nonresponse_receipt_reference: str | None = None, + successor_nonresponse_receipt_digest: str | None = None, + successor_evidence_version: int | None = None, + successor_released_at: datetime | None = None, + ) -> NonresponseAdjustmentSupersessionAuthorityRecord: + """Validate one released predecessor and its optional atomic successor edge.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + receipt_ref = _require_reference( + "nonresponse_receipt_reference", + nonresponse_receipt_reference, + "nonresponse_adjustment_receipt", + ) + receipt_digest = _require_digest( + "nonresponse_receipt_digest", nonresponse_receipt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + owner_release = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) + release_instant = _require_aware_datetime("released_at", released_at) + if owner_release > release_instant: + raise ValueError( + "owner contract must be released no later than nonresponse receipt." + ) + + successor_values = ( + superseded_at, + successor_nonresponse_receipt_reference, + successor_nonresponse_receipt_digest, + successor_evidence_version, + successor_released_at, + ) + if all(value is None for value in successor_values): + cutover = None + successor_ref = None + successor_digest = None + successor_version = None + successor_release = None + elif any(value is None for value in successor_values): + raise ValueError( + "nonresponse supersession requires cutover and complete released successor coordinates." + ) + else: + cutover = _require_aware_datetime("superseded_at", superseded_at) + successor_ref = _require_reference( + "successor_nonresponse_receipt_reference", + successor_nonresponse_receipt_reference, + "nonresponse_adjustment_receipt", + ) + successor_digest = _require_digest( + "successor_nonresponse_receipt_digest", + successor_nonresponse_receipt_digest, + ) + successor_version = _require_positive_integer( + "successor_evidence_version", successor_evidence_version + ) + successor_release = _require_aware_datetime( + "successor_released_at", successor_released_at + ) + if cutover <= release_instant: + raise ValueError("superseded_at must be later than nonresponse receipt release.") + if successor_ref == receipt_ref: + raise ValueError("successor nonresponse receipt must have a new reference.") + if successor_digest == receipt_digest: + raise ValueError("successor nonresponse receipt must identify new evidence.") + if successor_version != 1: + raise ValueError("successor_evidence_version must remain 1.") + if successor_release <= release_instant: + raise ValueError( + "successor nonresponse receipt must be released after its predecessor." + ) + if successor_release != cutover: + raise ValueError( + "successor nonresponse receipt must be released exactly at supersession." + ) + + current_fields: tuple[tuple[str, object], ...] = ( + ("evidence_version", version), + ("nonresponse_receipt_digest", receipt_digest), + ("nonresponse_receipt_reference", receipt_ref), + ("owner_contract_digest", owner_digest), + ("owner_contract_reference", owner_ref), + ("owner_contract_released_at", owner_release), + ("owner_contract_version", owner_version), + ) + successor_fields: tuple[tuple[str, object], ...] | None + if cutover is None: + successor_fields = None + else: + successor_fields = ( + ("successor_evidence_version", successor_version), + ("successor_nonresponse_receipt_digest", successor_digest), + ("successor_nonresponse_receipt_reference", successor_ref), + ("successor_released_at", successor_release), + ) + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + current_fields, + release_instant, + cutover, + successor_fields, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable current-receipt authority coordinates.""" + return self[2] + + @property + def released_at(self) -> datetime: + """Return when this nonresponse receipt became released authority.""" + return self[3] + + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive end of this receipt's authority interval.""" + return self[4] + + @property + def successor_fields(self) -> tuple[tuple[str, object], ...] | None: + """Return internal released successor coordinates, if any.""" + return self[5] + + +class NonresponseAdjustmentSupersessionAuthorityView(tuple): + """Minimized current-receipt authority issued only after authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> NonresponseAdjustmentSupersessionAuthorityView: + """Reject public construction; only the resolver may issue this view.""" + raise TypeError( + "NonresponseAdjustmentSupersessionAuthorityView is issued only by " + "resolve_nonresponse_adjustment_supersession_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return current receipt authority without successor disclosure.""" + return self[2] + + +@runtime_checkable +class NonresponseAdjustmentSupersessionAuthorityReadPort(Protocol): + """Owner read contract for one released nonresponse correction state.""" + + def read_nonresponse_adjustment_supersession_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + nonresponse_receipt_reference: str, + nonresponse_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> NonresponseAdjustmentSupersessionAuthorityRecord | None: + """Return matching released nonresponse supersession evidence or ``None``.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + NonresponseAdjustmentSupersessionAuthorityReadPort, + "read_nonresponse_adjustment_supersession_authority", +) + + +def resolve_nonresponse_adjustment_supersession_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + nonresponse_receipt_reference: str, + nonresponse_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: NonresponseAdjustmentSupersessionAuthorityReadPort, +) -> NonresponseAdjustmentSupersessionAuthorityView: + """Authorize then resolve the receipt's half-open append-only authority interval.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static( + type(read_port), "read_nonresponse_adjustment_supersession_authority", None + ) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError( + "read_port must expose a statically callable " + "read_nonresponse_adjustment_supersession_authority." + ) + + tenant_id = _restore_operational_uuid( + "tenant_record_id", _store_operational_uuid("tenant_record_id", tenant_record_id) + ) + study_id = _restore_operational_uuid( + "validity_study_id", _store_operational_uuid("validity_study_id", validity_study_id) + ) + receipt_ref = _require_reference( + "nonresponse_receipt_reference", + nonresponse_receipt_reference, + "nonresponse_adjustment_receipt", + ) + receipt_digest = _require_digest( + "nonresponse_receipt_digest", nonresponse_receipt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer("owner_contract_version", owner_contract_version) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=tenant_id, + validity_study_id=study_id, + nonresponse_receipt_reference=receipt_ref, + nonresponse_receipt_digest=receipt_digest, + evidence_version=version, + owner_contract_reference=owner_ref, + owner_contract_version=owner_version, + owner_contract_digest=owner_digest, + ) + if persisted is None: + raise NonresponseAdjustmentSupersessionAuthorityNotFound(str(study_id)) + if type(persisted) is not NonresponseAdjustmentSupersessionAuthorityRecord: + raise NonresponseAdjustmentSupersessionAuthorityIntegrityError( + "owner port returned non-canonical nonresponse supersession evidence" + ) + + successor_values = ( + None if persisted.successor_fields is None else dict(persisted.successor_fields) + ) + record = NonresponseAdjustmentSupersessionAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + successor_nonresponse_receipt_reference=( + None + if successor_values is None + else successor_values["successor_nonresponse_receipt_reference"] + ), + successor_nonresponse_receipt_digest=( + None + if successor_values is None + else successor_values["successor_nonresponse_receipt_digest"] + ), + successor_evidence_version=( + None + if successor_values is None + else successor_values["successor_evidence_version"] + ), + successor_released_at=( + None if successor_values is None else successor_values["successor_released_at"] + ), + **dict(persisted.fields), + ) + record_values = dict(record.fields) + if ( + _store_operational_uuid("record tenant_record_id", record.tenant_record_id) + != _store_operational_uuid("requested tenant_record_id", tenant_id) + or _store_operational_uuid("record validity_study_id", record.validity_study_id) + != _store_operational_uuid("requested validity_study_id", study_id) + or record_values["nonresponse_receipt_reference"] != receipt_ref + or record_values["nonresponse_receipt_digest"] != receipt_digest + or record_values["evidence_version"] != version + or record_values["owner_contract_reference"] != owner_ref + or record_values["owner_contract_version"] != owner_version + or record_values["owner_contract_digest"] != owner_digest + ): + raise NonresponseAdjustmentSupersessionAuthorityIntegrityError( + "released nonresponse supersession authority does not match requested coordinates" + ) + if use_instant < record.released_at: + raise NonresponseAdjustmentSupersessionAuthorityIntegrityError( + "nonresponse receipt must be released before scientific use" + ) + if record.superseded_at is not None and use_instant >= record.superseded_at: + raise NonresponseAdjustmentSupersessionAuthorityIntegrityError( + "nonresponse receipt is superseded for this scientific-use instant" + ) + + view_values = dict(record.fields) + view_values["released_at"] = record.released_at + fields = tuple( + (name, view_values[name]) + for name in ( + "evidence_version", + "nonresponse_receipt_digest", + "nonresponse_receipt_reference", + "owner_contract_digest", + "owner_contract_reference", + "owner_contract_released_at", + "owner_contract_version", + "released_at", + ) + ) + return tuple.__new__( + NonresponseAdjustmentSupersessionAuthorityView, + ( + _store_operational_uuid("tenant_record_id", tenant_id), + _store_operational_uuid("validity_study_id", study_id), + fields, + ), + ) From 3371d1978aecddbd297db852ca977905d54965ba Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 11:06:45 +0900 Subject: [PATCH 254/603] chore(workforce-validation): export nonresponse supersession authority --- .../orgmetra_workforce_validation_api/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index 523a8c74b..5e895a68b 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -49,6 +49,14 @@ NonresponseAdjustmentAuthorityView, resolve_nonresponse_adjustment_authority, ) +from orgmetra_workforce_validation_api.nonresponse_adjustment_supersession_authority import ( + NonresponseAdjustmentSupersessionAuthorityIntegrityError, + NonresponseAdjustmentSupersessionAuthorityNotFound, + NonresponseAdjustmentSupersessionAuthorityReadPort, + NonresponseAdjustmentSupersessionAuthorityRecord, + NonresponseAdjustmentSupersessionAuthorityView, + resolve_nonresponse_adjustment_supersession_authority, +) from orgmetra_workforce_validation_api.registry import ( ValidationPrincipal, ValidityStudyIntegrityError, @@ -160,6 +168,11 @@ "NonresponseAdjustmentAuthorityReadPort", "NonresponseAdjustmentAuthorityRecord", "NonresponseAdjustmentAuthorityView", + "NonresponseAdjustmentSupersessionAuthorityIntegrityError", + "NonresponseAdjustmentSupersessionAuthorityNotFound", + "NonresponseAdjustmentSupersessionAuthorityReadPort", + "NonresponseAdjustmentSupersessionAuthorityRecord", + "NonresponseAdjustmentSupersessionAuthorityView", "TrimmingBoundingAuthorityIntegrityError", "TrimmingBoundingAuthorityNotFound", "TrimmingBoundingAuthorityReadPort", @@ -209,6 +222,7 @@ "resolve_final_analysis_weight_authority", "resolve_final_weight_supersession_authority", "resolve_nonresponse_adjustment_authority", + "resolve_nonresponse_adjustment_supersession_authority", "resolve_trimming_bounding_authority", "resolve_validation_result_authority", "resolve_validation_result_nonverifiability", From d94fba32e8267bc040738a8ddf0dee6653da90d0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 11:07:38 +0900 Subject: [PATCH 255/603] test(workforce-validation): harden nonresponse successor edges --- ...sponse_adjustment_supersession_contract.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_contract.py b/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_contract.py index 93633841a..75b48961a 100644 --- a/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_contract.py +++ b/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_contract.py @@ -9,6 +9,7 @@ import pytest from orgmetra_workforce_validation_api.nonresponse_adjustment_authority import ( + NonresponseAdjustmentAuthorityReadPort, NonresponseAdjustmentAuthorityRecord, ) from orgmetra_workforce_validation_api.nonresponse_adjustment_supersession_authority import ( @@ -48,7 +49,13 @@ def _supersession_record(**overrides: object) -> NonresponseAdjustmentSupersessi def test_ordinary_nonresponse_authority_keeps_cutover_owner_resolved() -> None: """Ordinary currentness accepts a cutover but never makes it a lookup coordinate.""" record_parameters = signature(NonresponseAdjustmentAuthorityRecord).parameters + read_parameters = signature( + NonresponseAdjustmentAuthorityReadPort.read_nonresponse_adjustment_authority + ).parameters assert "superseded_at" in record_parameters + assert "superseded_at" not in read_parameters + assert "owner_contract_released_at" not in read_parameters + assert "released_at" not in read_parameters def test_nonresponse_supersession_requires_atomic_successor_release() -> None: @@ -60,6 +67,12 @@ def test_nonresponse_supersession_requires_atomic_successor_release() -> None: ) +def test_nonresponse_supersession_requires_complete_successor_coordinates() -> None: + """A cutover without a complete released successor is not correction authority.""" + with pytest.raises(ValueError, match="complete released successor"): + _supersession_record(successor_released_at=None) + + def test_nonresponse_supersession_requires_new_immutable_evidence() -> None: """A predecessor cannot supersede itself or reuse its evidence digest.""" with pytest.raises(ValueError, match="new reference"): @@ -68,3 +81,9 @@ def test_nonresponse_supersession_requires_new_immutable_evidence() -> None: ) with pytest.raises(ValueError, match="new evidence"): _supersession_record(successor_nonresponse_receipt_digest="a" * 64) + + +def test_nonresponse_supersession_rejects_naive_cutover() -> None: + """Correction chronology must remain timezone-aware owner evidence.""" + with pytest.raises(ValueError, match="timezone-aware"): + _supersession_record(superseded_at=datetime(2026, 9, 18, 1, 10)) From f4b9b16b2d6aaba635ec966891bea7b476ca2c2e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 11:08:22 +0900 Subject: [PATCH 256/603] test(workforce-validation): verify nonresponse currentness interval --- .../test_nonresponse_adjustment_authority.py | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority.py b/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority.py index 644ba659b..221bf4d36 100644 --- a/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority.py +++ b/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority.py @@ -61,6 +61,7 @@ "owner_contract_digest", "owner_contract_released_at", "released_at", + "superseded_at", } ) @@ -196,6 +197,7 @@ def test_resolution_binds_versioned_disposition_and_treatment_evidence() -> None assert ("unavailable_treatment_code", "retain_unavailable_class") in view.fields assert ("response_disposition_receipt_released_at", DISPOSITION_RELEASED_AT) in view.fields assert ("owner_contract_released_at", OWNER_CONTRACT_RELEASED_AT) in view.fields + assert ("superseded_at", None) in view.fields def test_authorization_denial_happens_before_owner_resolution() -> None: @@ -242,16 +244,38 @@ def test_owner_evidence_must_match_every_requested_coordinate( _resolve(read_port=_ReadPort(_record(**record_overrides))) -def test_owner_resolved_input_and_release_chronology_fail_closed() -> None: +def test_owner_resolved_input_release_and_currentness_chronology_fail_closed() -> None: with pytest.raises(ValueError): _record(response_disposition_receipt_released_at=CONSTRUCTED_AT + timedelta(seconds=1)) with pytest.raises(ValueError): _record(released_at=CONSTRUCTED_AT - timedelta(seconds=1)) + with pytest.raises(ValueError, match="superseded_at must be later"): + _record(superseded_at=RELEASED_AT) + + with pytest.raises(ValueError, match="timezone-aware"): + _record(superseded_at=datetime(2026, 9, 16, 14, 0)) + with pytest.raises(NonresponseAdjustmentAuthorityIntegrityError): _resolve(read_port=_ReadPort(_record(released_at=USED_AT + timedelta(seconds=1)))) + cutover = RELEASED_AT + timedelta(hours=1) + historical = _resolve( + read_port=_ReadPort(_record(superseded_at=cutover)), + used_at=cutover - timedelta(seconds=1), + ) + assert ("superseded_at", cutover) in historical.fields + + with pytest.raises( + NonresponseAdjustmentAuthorityIntegrityError, + match="superseded for this scientific-use instant", + ): + _resolve( + read_port=_ReadPort(_record(superseded_at=cutover)), + used_at=cutover, + ) + def test_weight_artifact_aliasing_fails_closed() -> None: with pytest.raises(ValueError): From 5bb9d62310923ebb394f787265e374d26e10b92e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 11:10:13 +0900 Subject: [PATCH 257/603] docs(workforce-validation): document nonresponse correction authority --- services/workforce-validation-api/README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index c221e1c38..d06a2b22e 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -38,7 +38,13 @@ The supporting auxiliary-use and benchmark-reference instants are caller-known r `resolve_nonresponse_adjustment_authority(...)` corroborates the exact released disposition-aware nonresponse receipt. It binds receipt/evidence version, exact response/disposition receipt reference/version/digest, owner-resolved disposition release time, adjustment population, method/version/configuration, explicit ineligible/unknown/unavailable treatments, input/output weight artifacts, construction time, and released owner contract. The disposition input must already exist by adjustment construction and scientific use cannot precede the typed receipt's release. Response values, source attributes, protected attributes, and row-level weights are excluded. -The owner-contract release instant is resolved only from canonical owner evidence and must be timezone-aware and no later than the nonresponse receipt release. It is deliberately absent from caller lookup coordinates, preventing a later owner contract from being used to retroactively corroborate an earlier released adjustment. +The owner-contract release instant and optional exclusive nonresponse cutover are resolved only from canonical owner evidence. Neither is a caller lookup coordinate. The contract must be timezone-aware and exist no later than the nonresponse receipt release, while the ordinary resolver enforces `[released_at, superseded_at)`. Historical use before cutover remains reproducible and use at or after cutover fails closed, so a corrected disposition, adjustment population, treatment rule, or weight-artifact transition cannot leave an older nonresponse receipt apparently current. + +## Nonresponse-adjustment supersession authority + +`resolve_nonresponse_adjustment_supersession_authority(...)` supplies the append-only correction edge required by #407 RED #10 for typed nonresponse weighting. An owner-resolved `superseded_at` on the ordinary projection is not enough to prove which immutable released receipt ended the predecessor interval. The supersession record therefore binds the current nonresponse receipt reference/digest/evidence version and released owner contract to release chronology and, when corrected, requires one complete successor receipt reference/digest/evidence version/release tuple. + +The successor must identify new immutable receipt evidence, remain on the governed v1 contract, be released after its predecessor, and satisfy `successor_released_at == superseded_at`. The predecessor is authoritative only on `[released_at, superseded_at)`. Successor coordinates remain owner-resolved evidence and are deliberately omitted from the minimized downstream view. Durable persistence must make the ordinary nonresponse projection's cutover and the explicit successor edge agree on the same atomic correction instant; currentness may not be inferred from a mutable current row or caller timestamp. ## Trimming/bounding adjustment authority @@ -112,7 +118,7 @@ The failed-evidence release instant, verification-attempt release instant, gover The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, trimming/bounding adjustment, weight eligibility, weight-eligibility supersession, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. The typed-calibration adapter must persist and exact-key the target-population digest, analysis-window reference, scientific auxiliary-authority reference, auxiliary projection reference/version/digest, purpose reference/digest, auxiliary owner-contract reference/version/digest, authorization and scientific-use receipts, scientific-use instant, benchmark receipt reference/version/digest, benchmark owner-contract reference/version/digest, and benchmark-reference instant together with method/artifact/fallback/application-owner coordinates. It may not reconstruct these from a mutable current row or trust only the opaque calibration receipt digest. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; calibration-adjustment, nonresponse-adjustment, and trimming/bounding owner-contract release instants likewise come from durable owner records and must not postdate their released receipts. Base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, weight-eligibility, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; the ordinary eligibility projection's cutover must agree with the eligibility-supersession graph. Final-weight, point-weight/variance compatibility, validation-result, and non-verifiability owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Base-weight and final-analysis-weight persistence must select released owner evidence by their complete caller-known reproducibility tuples; it may not select a partial receipt/source/design prefix and rely on a later in-memory mismatch check. Non-verifiability persistence must key the owner read by the exact immutable verification-attempt reference/digest, preserve `failed_evidence_released_at` for non-reproducible evidence, preserve owner-resolved `verification_attempt_released_at` for every verification attempt, prove `failed_evidence_released_at <= evaluated_at` when applicable, and prove `evaluated_at <= verification_attempt_released_at <= released_at`; missing evidence stores no fabricated failed-evidence release time. Low-level eligibility/final-weight/binding/non-verifiability adapters must therefore recover canonical chronology rather than independently infer currentness. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, weight eligibility, weight-eligibility supersession, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. The typed-calibration adapter must persist and exact-key the target-population digest, analysis-window reference, scientific auxiliary-authority reference, auxiliary projection reference/version/digest, purpose reference/digest, auxiliary owner-contract reference/version/digest, authorization and scientific-use receipts, scientific-use instant, benchmark receipt reference/version/digest, benchmark owner-contract reference/version/digest, and benchmark-reference instant together with method/artifact/fallback/application-owner coordinates. It may not reconstruct these from a mutable current row or trust only the opaque calibration receipt digest. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; calibration-adjustment, nonresponse-adjustment, and trimming/bounding owner-contract release instants likewise come from durable owner records and must not postdate their released receipts. Base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, weight-eligibility, nonresponse-adjustment, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; the ordinary eligibility and nonresponse projections' cutovers must agree with their explicit supersession graphs. Final-weight, point-weight/variance compatibility, validation-result, and non-verifiability owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Base-weight and final-analysis-weight persistence must select released owner evidence by their complete caller-known reproducibility tuples; it may not select a partial receipt/source/design prefix and rely on a later in-memory mismatch check. Non-verifiability persistence must key the owner read by the exact immutable verification-attempt reference/digest, preserve `failed_evidence_released_at` for non-reproducible evidence, preserve owner-resolved `verification_attempt_released_at` for every verification attempt, prove `failed_evidence_released_at <= evaluated_at` when applicable, and prove `evaluated_at <= verification_attempt_released_at <= released_at`; missing evidence stores no fabricated failed-evidence release time. Low-level eligibility/nonresponse/final-weight/binding/non-verifiability adapters must therefore recover canonical chronology rather than independently infer currentness. ## Test contract @@ -127,6 +133,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration target-population/analysis-window binding, complete auxiliary/benchmark supporting-authority identity and reference-time chronology, fallback provenance and owner-contract chronology, typed nonresponse disposition/treatment provenance and owner-contract chronology, trimming/bounding rule/affected-case provenance and owner-contract chronology, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, explicit eligibility predecessor/successor correction authority with exact release-at-cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology and complete read-port lookup coordinates, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology, low-level final-weight currentness and complete final-weight read-port lookup coordinates, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, and explicit missing/non-reproducible result evidence including owner-contract chronology, failed-evidence release chronology, exact verification-attempt lookup-key completeness, verification-attempt release chronology, and owner-resolved negative-outcome cutover. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration target-population/analysis-window binding, complete auxiliary/benchmark supporting-authority identity and reference-time chronology, fallback provenance and owner-contract chronology, typed nonresponse disposition/treatment provenance, owner-contract chronology and owner-resolved currentness, explicit nonresponse predecessor/successor correction authority with complete immutable successor coordinates and exact release-at-cutover, trimming/bounding rule/affected-case provenance and owner-contract chronology, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, explicit eligibility predecessor/successor correction authority with exact release-at-cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology and complete read-port lookup coordinates, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology, low-level final-weight currentness and complete final-weight read-port lookup coordinates, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, and explicit missing/non-reproducible result evidence including owner-contract chronology, failed-evidence release chronology, exact verification-attempt lookup-key completeness, verification-attempt release chronology, and owner-resolved negative-outcome cutover. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From 934caa54b0cb5d5f6ea11c41f7c9fec839c46a3c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 11:10:53 +0900 Subject: [PATCH 258/603] test(workforce-validation): establish trimming supersession RED --- ...trimming_bounding_supersession_contract.py | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_trimming_bounding_supersession_contract.py diff --git a/services/workforce-validation-api/tests/test_trimming_bounding_supersession_contract.py b/services/workforce-validation-api/tests/test_trimming_bounding_supersession_contract.py new file mode 100644 index 000000000..37c9c8285 --- /dev/null +++ b/services/workforce-validation-api/tests/test_trimming_bounding_supersession_contract.py @@ -0,0 +1,76 @@ +"""Regression contract for append-only trimming/bounding corrections.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from inspect import signature +from uuid import uuid4 + +import pytest + +from orgmetra_workforce_validation_api.trimming_bounding_authority import ( + TrimmingBoundingAuthorityReadPort, + TrimmingBoundingAuthorityRecord, +) +from orgmetra_workforce_validation_api.trimming_bounding_supersession_authority import ( + TrimmingBoundingSupersessionAuthorityRecord, +) + + +def _released_at() -> datetime: + """Return a stable aware instant for correction chronology.""" + return datetime(2026, 9, 18, 1, 30, tzinfo=timezone.utc) + + +def _record(**overrides: object) -> TrimmingBoundingSupersessionAuthorityRecord: + """Build one predecessor/successor edge with an atomic cutover.""" + released_at = _released_at() + values: dict[str, object] = { + "tenant_record_id": uuid4(), + "validity_study_id": uuid4(), + "adjustment_receipt_reference": "trimming_bounding_adjustment_receipt:old", + "adjustment_receipt_digest": "a" * 64, + "evidence_version": 1, + "owner_contract_reference": "released_owner_contract:weighting-v1", + "owner_contract_version": 1, + "owner_contract_digest": "b" * 64, + "owner_contract_released_at": released_at - timedelta(minutes=5), + "released_at": released_at, + "superseded_at": released_at + timedelta(minutes=10), + "successor_adjustment_receipt_reference": "trimming_bounding_adjustment_receipt:new", + "successor_adjustment_receipt_digest": "c" * 64, + "successor_evidence_version": 1, + "successor_released_at": released_at + timedelta(minutes=10), + } + values.update(overrides) + return TrimmingBoundingSupersessionAuthorityRecord(**values) + + +def test_ordinary_trimming_authority_keeps_cutover_owner_resolved() -> None: + """Currentness has a cutover without turning chronology into lookup identity.""" + assert "superseded_at" in signature(TrimmingBoundingAuthorityRecord).parameters + read_parameters = signature( + TrimmingBoundingAuthorityReadPort.read_trimming_bounding_authority + ).parameters + assert "superseded_at" not in read_parameters + assert "owner_contract_released_at" not in read_parameters + assert "released_at" not in read_parameters + + +def test_trimming_supersession_requires_atomic_successor_release() -> None: + """A correction edge cannot create an overlap or gap around cutover.""" + _record() + with pytest.raises(ValueError, match="exactly at supersession"): + _record(successor_released_at=_released_at() + timedelta(minutes=11)) + + +def test_trimming_supersession_requires_complete_new_successor() -> None: + """A cutover must identify one complete new immutable successor receipt.""" + with pytest.raises(ValueError, match="complete released successor"): + _record(successor_released_at=None) + with pytest.raises(ValueError, match="new reference"): + _record( + successor_adjustment_receipt_reference="trimming_bounding_adjustment_receipt:old" + ) + with pytest.raises(ValueError, match="new evidence"): + _record(successor_adjustment_receipt_digest="a" * 64) From 84f70f21c34b8b358d06bdd87aa4926c051d9010 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 11:11:30 +0900 Subject: [PATCH 259/603] fix(workforce-validation): enforce trimming authority cutover --- .../trimming_bounding_authority.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py index 57376d986..cbf125e9c 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py @@ -53,6 +53,7 @@ "owner_contract_digest", "owner_contract_released_at", "released_at", + "superseded_at", } ) @@ -91,6 +92,7 @@ def __new__( owner_contract_digest: str, owner_contract_released_at: datetime, released_at: datetime, + superseded_at: datetime | None = None, ) -> TrimmingBoundingAuthorityRecord: """Validate and detach the minimum immutable trimming authority.""" tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) @@ -142,12 +144,19 @@ def __new__( "owner_contract_released_at", owner_contract_released_at ) release_instant = _require_aware_datetime("released_at", released_at) + supersession_instant = ( + None + if superseded_at is None + else _require_aware_datetime("superseded_at", superseded_at) + ) if release_instant < constructed: raise ValueError("released_at cannot precede constructed_at.") if owner_released > release_instant: raise ValueError( "owner_contract_released_at cannot be later than released_at." ) + if supersession_instant is not None and supersession_instant <= release_instant: + raise ValueError("superseded_at must be later than released_at.") return tuple.__new__( cls, ( @@ -169,6 +178,7 @@ def __new__( owner_digest, owner_released, release_instant, + supersession_instant, ), ) @@ -262,6 +272,11 @@ def released_at(self) -> datetime: """Return when this adjustment became released authority.""" return self[17] + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive owner-resolved cutover for this receipt.""" + return self[18] + class TrimmingBoundingAuthorityView(tuple): """Field-minimized adjustment evidence issued only after authorization.""" @@ -392,6 +407,7 @@ def resolve_trimming_bounding_authority( owner_contract_digest=owner_contract_digest, owner_contract_released_at=constructed_at, released_at=constructed_at, + superseded_at=None, ) tenant_id = requested.tenant_record_id study_id = requested.validity_study_id @@ -465,6 +481,7 @@ def resolve_trimming_bounding_authority( owner_contract_digest=persisted.owner_contract_digest, owner_contract_released_at=persisted.owner_contract_released_at, released_at=persisted.released_at, + superseded_at=persisted.superseded_at, ) if _coordinate_tuple(record) != _coordinate_tuple(requested): raise TrimmingBoundingAuthorityIntegrityError( @@ -474,6 +491,10 @@ def resolve_trimming_bounding_authority( raise TrimmingBoundingAuthorityIntegrityError( "trimming/bounding evidence must be released before scientific use" ) + if record.superseded_at is not None and use_instant >= record.superseded_at: + raise TrimmingBoundingAuthorityIntegrityError( + "trimming/bounding evidence is superseded for this scientific-use instant" + ) fields: tuple[tuple[str, object], ...] = ( ("adjustment_receipt_digest", record.adjustment_receipt_digest), @@ -492,6 +513,7 @@ def resolve_trimming_bounding_authority( ("rule_configuration_digest", record.rule_configuration_digest), ("rule_reference", record.rule_reference), ("rule_version", record.rule_version), + ("superseded_at", record.superseded_at), ) return tuple.__new__( TrimmingBoundingAuthorityView, From 3436f6601d00e72a369387698fa4561a63fa6a07 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 11:12:05 +0900 Subject: [PATCH 260/603] feat(workforce-validation): add trimming successor authority --- ...rimming_bounding_supersession_authority.py | 466 ++++++++++++++++++ 1 file changed, 466 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_supersession_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_supersession_authority.py new file mode 100644 index 000000000..f1bfcecd4 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_supersession_authority.py @@ -0,0 +1,466 @@ +"""Corroborate append-only trimming/bounding correction authority. + +The ordinary trimming/bounding projection proves which governed adjustment +receipt produced a released weight artifact. This boundary proves when that +receipt remained authoritative and which released successor ended its half-open +authority interval without exposing case identities or row-level weights. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + +_RESOURCE_KIND = "trimming_bounding_supersession_authority" +_OPERATION = "read" +_READ_FIELDS = frozenset( + { + "adjustment_receipt_reference", + "adjustment_receipt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_adjustment_receipt_reference", + "successor_adjustment_receipt_digest", + "successor_evidence_version", + "successor_released_at", + } +) + + +class TrimmingBoundingSupersessionAuthorityNotFound(LookupError): + """Indicate that no released owner evidence corroborates the adjustment receipt.""" + + +class TrimmingBoundingSupersessionAuthorityIntegrityError(RuntimeError): + """Indicate that released trimming correction evidence cannot authorize use.""" + + +class TrimmingBoundingSupersessionAuthorityRecord(tuple): + """Immutable owner projection for one trimming receipt authority interval.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + adjustment_receipt_reference: str, + adjustment_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + owner_contract_released_at: datetime, + released_at: datetime, + superseded_at: datetime | None = None, + successor_adjustment_receipt_reference: str | None = None, + successor_adjustment_receipt_digest: str | None = None, + successor_evidence_version: int | None = None, + successor_released_at: datetime | None = None, + ) -> TrimmingBoundingSupersessionAuthorityRecord: + """Validate one released predecessor and its optional atomic successor edge.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + receipt_ref = _require_reference( + "adjustment_receipt_reference", + adjustment_receipt_reference, + "trimming_bounding_adjustment_receipt", + ) + receipt_digest = _require_digest( + "adjustment_receipt_digest", adjustment_receipt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + owner_release = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) + release_instant = _require_aware_datetime("released_at", released_at) + if owner_release > release_instant: + raise ValueError( + "owner contract must be released no later than trimming/bounding receipt." + ) + + successor_values = ( + superseded_at, + successor_adjustment_receipt_reference, + successor_adjustment_receipt_digest, + successor_evidence_version, + successor_released_at, + ) + if all(value is None for value in successor_values): + cutover = None + successor_ref = None + successor_digest = None + successor_version = None + successor_release = None + elif any(value is None for value in successor_values): + raise ValueError( + "trimming supersession requires cutover and complete released successor coordinates." + ) + else: + cutover = _require_aware_datetime("superseded_at", superseded_at) + successor_ref = _require_reference( + "successor_adjustment_receipt_reference", + successor_adjustment_receipt_reference, + "trimming_bounding_adjustment_receipt", + ) + successor_digest = _require_digest( + "successor_adjustment_receipt_digest", + successor_adjustment_receipt_digest, + ) + successor_version = _require_positive_integer( + "successor_evidence_version", successor_evidence_version + ) + successor_release = _require_aware_datetime( + "successor_released_at", successor_released_at + ) + if cutover <= release_instant: + raise ValueError("superseded_at must be later than trimming receipt release.") + if successor_ref == receipt_ref: + raise ValueError("successor trimming receipt must have a new reference.") + if successor_digest == receipt_digest: + raise ValueError("successor trimming receipt must identify new evidence.") + if successor_version != 1: + raise ValueError("successor_evidence_version must remain 1.") + if successor_release <= release_instant: + raise ValueError( + "successor trimming receipt must be released after its predecessor." + ) + if successor_release != cutover: + raise ValueError( + "successor trimming receipt must be released exactly at supersession." + ) + + current_fields: tuple[tuple[str, object], ...] = ( + ("adjustment_receipt_digest", receipt_digest), + ("adjustment_receipt_reference", receipt_ref), + ("evidence_version", version), + ("owner_contract_digest", owner_digest), + ("owner_contract_reference", owner_ref), + ("owner_contract_released_at", owner_release), + ("owner_contract_version", owner_version), + ) + successor_fields: tuple[tuple[str, object], ...] | None + if cutover is None: + successor_fields = None + else: + successor_fields = ( + ("successor_adjustment_receipt_digest", successor_digest), + ("successor_adjustment_receipt_reference", successor_ref), + ("successor_evidence_version", successor_version), + ("successor_released_at", successor_release), + ) + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + current_fields, + release_instant, + cutover, + successor_fields, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable current-receipt authority coordinates.""" + return self[2] + + @property + def released_at(self) -> datetime: + """Return when this trimming receipt became released authority.""" + return self[3] + + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive end of this receipt's authority interval.""" + return self[4] + + @property + def successor_fields(self) -> tuple[tuple[str, object], ...] | None: + """Return internal released successor coordinates, if any.""" + return self[5] + + +class TrimmingBoundingSupersessionAuthorityView(tuple): + """Minimized current-receipt authority issued only after authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> TrimmingBoundingSupersessionAuthorityView: + """Reject public construction; only the resolver may issue this view.""" + raise TypeError( + "TrimmingBoundingSupersessionAuthorityView is issued only by " + "resolve_trimming_bounding_supersession_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return current receipt authority without successor disclosure.""" + return self[2] + + +@runtime_checkable +class TrimmingBoundingSupersessionAuthorityReadPort(Protocol): + """Owner read contract for one released trimming correction state.""" + + def read_trimming_bounding_supersession_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + adjustment_receipt_reference: str, + adjustment_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> TrimmingBoundingSupersessionAuthorityRecord | None: + """Return matching released trimming supersession evidence or ``None``.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + TrimmingBoundingSupersessionAuthorityReadPort, + "read_trimming_bounding_supersession_authority", +) + + +def resolve_trimming_bounding_supersession_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + adjustment_receipt_reference: str, + adjustment_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: TrimmingBoundingSupersessionAuthorityReadPort, +) -> TrimmingBoundingSupersessionAuthorityView: + """Authorize then resolve the receipt's half-open append-only authority interval.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static( + type(read_port), "read_trimming_bounding_supersession_authority", None + ) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError( + "read_port must expose a statically callable " + "read_trimming_bounding_supersession_authority." + ) + + tenant_id = _restore_operational_uuid( + "tenant_record_id", _store_operational_uuid("tenant_record_id", tenant_record_id) + ) + study_id = _restore_operational_uuid( + "validity_study_id", _store_operational_uuid("validity_study_id", validity_study_id) + ) + receipt_ref = _require_reference( + "adjustment_receipt_reference", + adjustment_receipt_reference, + "trimming_bounding_adjustment_receipt", + ) + receipt_digest = _require_digest( + "adjustment_receipt_digest", adjustment_receipt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer("owner_contract_version", owner_contract_version) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=tenant_id, + validity_study_id=study_id, + adjustment_receipt_reference=receipt_ref, + adjustment_receipt_digest=receipt_digest, + evidence_version=version, + owner_contract_reference=owner_ref, + owner_contract_version=owner_version, + owner_contract_digest=owner_digest, + ) + if persisted is None: + raise TrimmingBoundingSupersessionAuthorityNotFound(str(study_id)) + if type(persisted) is not TrimmingBoundingSupersessionAuthorityRecord: + raise TrimmingBoundingSupersessionAuthorityIntegrityError( + "owner port returned non-canonical trimming supersession evidence" + ) + + successor_values = ( + None if persisted.successor_fields is None else dict(persisted.successor_fields) + ) + record = TrimmingBoundingSupersessionAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + successor_adjustment_receipt_reference=( + None + if successor_values is None + else successor_values["successor_adjustment_receipt_reference"] + ), + successor_adjustment_receipt_digest=( + None + if successor_values is None + else successor_values["successor_adjustment_receipt_digest"] + ), + successor_evidence_version=( + None + if successor_values is None + else successor_values["successor_evidence_version"] + ), + successor_released_at=( + None if successor_values is None else successor_values["successor_released_at"] + ), + **dict(persisted.fields), + ) + record_values = dict(record.fields) + if ( + _store_operational_uuid("record tenant_record_id", record.tenant_record_id) + != _store_operational_uuid("requested tenant_record_id", tenant_id) + or _store_operational_uuid("record validity_study_id", record.validity_study_id) + != _store_operational_uuid("requested validity_study_id", study_id) + or record_values["adjustment_receipt_reference"] != receipt_ref + or record_values["adjustment_receipt_digest"] != receipt_digest + or record_values["evidence_version"] != version + or record_values["owner_contract_reference"] != owner_ref + or record_values["owner_contract_version"] != owner_version + or record_values["owner_contract_digest"] != owner_digest + ): + raise TrimmingBoundingSupersessionAuthorityIntegrityError( + "released trimming supersession authority does not match requested coordinates" + ) + if use_instant < record.released_at: + raise TrimmingBoundingSupersessionAuthorityIntegrityError( + "trimming receipt must be released before scientific use" + ) + if record.superseded_at is not None and use_instant >= record.superseded_at: + raise TrimmingBoundingSupersessionAuthorityIntegrityError( + "trimming receipt is superseded for this scientific-use instant" + ) + + view_values = dict(record.fields) + view_values["released_at"] = record.released_at + fields = tuple( + (name, view_values[name]) + for name in ( + "adjustment_receipt_digest", + "adjustment_receipt_reference", + "evidence_version", + "owner_contract_digest", + "owner_contract_reference", + "owner_contract_released_at", + "owner_contract_version", + "released_at", + ) + ) + return tuple.__new__( + TrimmingBoundingSupersessionAuthorityView, + ( + _store_operational_uuid("tenant_record_id", tenant_id), + _store_operational_uuid("validity_study_id", study_id), + fields, + ), + ) From 47137f0336dbf8bd55e1a66854079360532a3309 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 11:12:28 +0900 Subject: [PATCH 261/603] chore(workforce-validation): export trimming supersession authority --- .../orgmetra_workforce_validation_api/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index 5e895a68b..76b638cd3 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -106,6 +106,14 @@ TrimmingBoundingAuthorityView, resolve_trimming_bounding_authority, ) +from orgmetra_workforce_validation_api.trimming_bounding_supersession_authority import ( + TrimmingBoundingSupersessionAuthorityIntegrityError, + TrimmingBoundingSupersessionAuthorityNotFound, + TrimmingBoundingSupersessionAuthorityReadPort, + TrimmingBoundingSupersessionAuthorityRecord, + TrimmingBoundingSupersessionAuthorityView, + resolve_trimming_bounding_supersession_authority, +) from orgmetra_workforce_validation_api.variance_authority import ( WeightVarianceAuthorityIntegrityError, WeightVarianceAuthorityNotFound, @@ -178,6 +186,11 @@ "TrimmingBoundingAuthorityReadPort", "TrimmingBoundingAuthorityRecord", "TrimmingBoundingAuthorityView", + "TrimmingBoundingSupersessionAuthorityIntegrityError", + "TrimmingBoundingSupersessionAuthorityNotFound", + "TrimmingBoundingSupersessionAuthorityReadPort", + "TrimmingBoundingSupersessionAuthorityRecord", + "TrimmingBoundingSupersessionAuthorityView", "ValidationPrincipal", "ValidationResultAuthorityIntegrityError", "ValidationResultAuthorityNotFound", @@ -224,6 +237,7 @@ "resolve_nonresponse_adjustment_authority", "resolve_nonresponse_adjustment_supersession_authority", "resolve_trimming_bounding_authority", + "resolve_trimming_bounding_supersession_authority", "resolve_validation_result_authority", "resolve_validation_result_nonverifiability", "resolve_validation_result_supersession_authority", From 5c99f63523e109b904cdcb042800067fba423721 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 11:13:00 +0900 Subject: [PATCH 262/603] test(workforce-validation): verify trimming currentness interval --- .../tests/test_trimming_bounding_authority.py | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_trimming_bounding_authority.py b/services/workforce-validation-api/tests/test_trimming_bounding_authority.py index af71f3b8d..6d2c0b84f 100644 --- a/services/workforce-validation-api/tests/test_trimming_bounding_authority.py +++ b/services/workforce-validation-api/tests/test_trimming_bounding_authority.py @@ -53,6 +53,7 @@ "owner_contract_digest", "owner_contract_released_at", "released_at", + "superseded_at", } ) @@ -176,6 +177,7 @@ def test_resolution_binds_rule_affected_cases_and_artifact_lineage() -> None: assert ("affected_case_occurrence_set_digest", AFFECTED_CASE_SET_DIGEST) in view.fields assert ("output_weight_artifact_digest", OUTPUT_WEIGHT_DIGEST) in view.fields assert ("owner_contract_released_at", OWNER_CONTRACT_RELEASED_AT) in view.fields + assert ("superseded_at", None) in view.fields def test_authorization_denial_happens_before_owner_resolution() -> None: @@ -217,14 +219,33 @@ def test_owner_evidence_must_match_every_requested_coordinate( _resolve(read_port=_ReadPort(_record(**record_overrides))) -def test_artifact_alias_and_release_chronology_fail_closed() -> None: +def test_artifact_release_and_currentness_chronology_fail_closed() -> None: with pytest.raises(ValueError): _record(output_weight_artifact_digest=INPUT_WEIGHT_DIGEST) with pytest.raises(ValueError): _record(released_at=CONSTRUCTED_AT - timedelta(seconds=1)) + with pytest.raises(ValueError, match="superseded_at must be later"): + _record(superseded_at=RELEASED_AT) + with pytest.raises(ValueError, match="timezone-aware"): + _record(superseded_at=datetime(2026, 9, 16, 14, 0)) with pytest.raises(TrimmingBoundingAuthorityIntegrityError): _resolve(read_port=_ReadPort(_record(released_at=USED_AT + timedelta(seconds=1)))) + cutover = RELEASED_AT + timedelta(hours=1) + historical = _resolve( + read_port=_ReadPort(_record(superseded_at=cutover)), + used_at=cutover - timedelta(seconds=1), + ) + assert ("superseded_at", cutover) in historical.fields + with pytest.raises( + TrimmingBoundingAuthorityIntegrityError, + match="superseded for this scientific-use instant", + ): + _resolve( + read_port=_ReadPort(_record(superseded_at=cutover)), + used_at=cutover, + ) + @pytest.mark.parametrize( ("key", "value", "error"), From a6bc9d6e295633a10e4444d27a1c1623a6e1787e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 11:13:46 +0900 Subject: [PATCH 263/603] docs(workforce-validation): document trimming correction authority --- services/workforce-validation-api/README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index d06a2b22e..907bd6f6a 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -50,7 +50,13 @@ The successor must identify new immutable receipt evidence, remain on the govern `resolve_trimming_bounding_authority(...)` corroborates the exact released trimming or bounding receipt rather than trusting an adjustment-chain digest alone. It binds the typed receipt reference/digest/evidence version to the governed `weight_trimming_rule` reference/version, immutable rule configuration, exact affected-case occurrence-set digest and positive affected-case count, input/output weight-artifact transition, construction time and released owner-contract tuple. Input and output artifacts may not alias; release cannot precede construction or scientific use. Case identities and row-level weights are excluded from the projection. -The governing owner-contract release instant is also owner-resolved evidence and must exist no later than the adjustment receipt release. The resolver never accepts that instant from the caller. This preserves the evidence needed to reproduce which governed trimming/bounding rule changed which case occurrence set without copying those cases into `workforce_validation`. PR #248 or a verified successor must later re-resolve the same tuple and chronology from released owner evidence. +The governing owner-contract release instant and optional exclusive trimming/bounding cutover are owner-resolved evidence and never caller lookup coordinates. The contract must exist no later than the adjustment receipt release and the ordinary resolver enforces `[released_at, superseded_at)`. Historical use before cutover remains reproducible; use at or after cutover fails closed. This preserves which governed rule changed which case occurrence set without copying cases into `workforce_validation` while preventing a corrected rule, affected set, or weight transition from leaving an older receipt apparently current. + +## Trimming/bounding supersession authority + +`resolve_trimming_bounding_supersession_authority(...)` supplies the explicit correction edge for typed trimming/bounding receipts. When a predecessor is superseded, owner evidence must identify one complete successor receipt reference/digest/evidence-version/release tuple. The successor must be new immutable evidence on the governed v1 receipt contract, be released after its predecessor, and be released exactly at the predecessor's `superseded_at` cutover. + +Successor coordinates remain internal owner evidence and are omitted from the minimized current-receipt view. Durable persistence must cross-check the ordinary trimming/bounding projection's `superseded_at` against the successor receipt release rather than infer currentness from mutable current rows, caller timestamps, or a floating rule pointer. ## Weight-eligibility authority @@ -118,7 +124,7 @@ The failed-evidence release instant, verification-attempt release instant, gover The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, weight eligibility, weight-eligibility supersession, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. The typed-calibration adapter must persist and exact-key the target-population digest, analysis-window reference, scientific auxiliary-authority reference, auxiliary projection reference/version/digest, purpose reference/digest, auxiliary owner-contract reference/version/digest, authorization and scientific-use receipts, scientific-use instant, benchmark receipt reference/version/digest, benchmark owner-contract reference/version/digest, and benchmark-reference instant together with method/artifact/fallback/application-owner coordinates. It may not reconstruct these from a mutable current row or trust only the opaque calibration receipt digest. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; calibration-adjustment, nonresponse-adjustment, and trimming/bounding owner-contract release instants likewise come from durable owner records and must not postdate their released receipts. Base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, weight-eligibility, nonresponse-adjustment, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; the ordinary eligibility and nonresponse projections' cutovers must agree with their explicit supersession graphs. Final-weight, point-weight/variance compatibility, validation-result, and non-verifiability owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Base-weight and final-analysis-weight persistence must select released owner evidence by their complete caller-known reproducibility tuples; it may not select a partial receipt/source/design prefix and rely on a later in-memory mismatch check. Non-verifiability persistence must key the owner read by the exact immutable verification-attempt reference/digest, preserve `failed_evidence_released_at` for non-reproducible evidence, preserve owner-resolved `verification_attempt_released_at` for every verification attempt, prove `failed_evidence_released_at <= evaluated_at` when applicable, and prove `evaluated_at <= verification_attempt_released_at <= released_at`; missing evidence stores no fabricated failed-evidence release time. Low-level eligibility/nonresponse/final-weight/binding/non-verifiability adapters must therefore recover canonical chronology rather than independently infer currentness. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. The typed-calibration adapter must persist and exact-key the target-population digest, analysis-window reference, scientific auxiliary-authority reference, auxiliary projection reference/version/digest, purpose reference/digest, auxiliary owner-contract reference/version/digest, authorization and scientific-use receipts, scientific-use instant, benchmark receipt reference/version/digest, benchmark owner-contract reference/version/digest, and benchmark-reference instant together with method/artifact/fallback/application-owner coordinates. It may not reconstruct these from a mutable current row or trust only the opaque calibration receipt digest. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; calibration-adjustment, nonresponse-adjustment, and trimming/bounding owner-contract release instants likewise come from durable owner records and must not postdate their released receipts. Base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, weight-eligibility, nonresponse-adjustment, trimming/bounding, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; ordinary eligibility, nonresponse and trimming/bounding projections must agree with their explicit supersession graphs. Final-weight, point-weight/variance compatibility, validation-result, and non-verifiability owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Base-weight and final-analysis-weight persistence must select released owner evidence by their complete caller-known reproducibility tuples; it may not select a partial receipt/source/design prefix and rely on a later in-memory mismatch check. Non-verifiability persistence must key the owner read by the exact immutable verification-attempt reference/digest, preserve `failed_evidence_released_at` for non-reproducible evidence, preserve owner-resolved `verification_attempt_released_at` for every verification attempt, prove `failed_evidence_released_at <= evaluated_at` when applicable, and prove `evaluated_at <= verification_attempt_released_at <= released_at`; missing evidence stores no fabricated failed-evidence release time. Low-level eligibility/nonresponse/trimming/final-weight/binding/non-verifiability adapters must therefore recover canonical chronology rather than independently infer currentness. ## Test contract @@ -133,6 +139,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration target-population/analysis-window binding, complete auxiliary/benchmark supporting-authority identity and reference-time chronology, fallback provenance and owner-contract chronology, typed nonresponse disposition/treatment provenance, owner-contract chronology and owner-resolved currentness, explicit nonresponse predecessor/successor correction authority with complete immutable successor coordinates and exact release-at-cutover, trimming/bounding rule/affected-case provenance and owner-contract chronology, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, explicit eligibility predecessor/successor correction authority with exact release-at-cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology and complete read-port lookup coordinates, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology, low-level final-weight currentness and complete final-weight read-port lookup coordinates, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, and explicit missing/non-reproducible result evidence including owner-contract chronology, failed-evidence release chronology, exact verification-attempt lookup-key completeness, verification-attempt release chronology, and owner-resolved negative-outcome cutover. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration target-population/analysis-window binding, complete auxiliary/benchmark supporting-authority identity and reference-time chronology, fallback provenance and owner-contract chronology, typed nonresponse disposition/treatment provenance, owner-contract chronology and owner-resolved currentness, explicit nonresponse predecessor/successor correction authority with complete immutable successor coordinates and exact release-at-cutover, trimming/bounding rule/affected-case provenance with owner-contract chronology and owner-resolved currentness, explicit trimming/bounding predecessor/successor correction authority with complete immutable successor coordinates and exact release-at-cutover, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, explicit eligibility predecessor/successor correction authority with exact release-at-cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology and complete read-port lookup coordinates, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology, low-level final-weight currentness and complete final-weight read-port lookup coordinates, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, and explicit missing/non-reproducible result evidence including owner-contract chronology, failed-evidence release chronology, exact verification-attempt lookup-key completeness, verification-attempt release chronology, and owner-resolved negative-outcome cutover. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From 86bd55a5541113a940ab3350f564cdf3737e9bf0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 12:04:21 +0900 Subject: [PATCH 264/603] test(workforce-validation): require calibration correction authority --- ...ration_adjustment_supersession_contract.py | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py b/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py new file mode 100644 index 000000000..a0a3f5e04 --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py @@ -0,0 +1,165 @@ +"""Append-only correction contract for typed calibration-adjustment authority.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.calibration_adjustment_supersession_authority import ( + CalibrationAdjustmentSupersessionAuthorityIntegrityError, + CalibrationAdjustmentSupersessionAuthorityReadPort, + CalibrationAdjustmentSupersessionAuthorityRecord, + resolve_calibration_adjustment_supersession_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RECEIPT = "calibration_adjustment_receipt:11111111-1111-4111-8111-111111111111" +SUCCESSOR = "calibration_adjustment_receipt:22222222-2222-4222-8222-222222222222" +OWNER = "released_owner_contract:33333333-3333-4333-8333-333333333333" +DIGEST = "1" * 64 +SUCCESSOR_DIGEST = "2" * 64 +OWNER_DIGEST = "3" * 64 +OWNER_RELEASED = datetime(2026, 9, 16, 12, 30, tzinfo=timezone.utc) +RELEASED = datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc) +CUTOVER = datetime(2026, 9, 17, 13, 0, tzinfo=timezone.utc) + + +class _ReadPort: + def __init__(self, record: CalibrationAdjustmentSupersessionAuthorityRecord) -> None: + self.record = record + self.calls: list[dict[str, object]] = [] + + def read_calibration_adjustment_supersession_authority( + self, **coordinates: object + ) -> CalibrationAdjustmentSupersessionAuthorityRecord: + self.calls.append(dict(coordinates)) + return self.record + + +def _principal() -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy() -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="calibration-adjustment-supersession-read-v1", + resource_kind="calibration_adjustment_supersession_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=frozenset( + { + "calibration_receipt_reference", + "calibration_receipt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_calibration_receipt_reference", + "successor_calibration_receipt_digest", + "successor_evidence_version", + "successor_released_at", + } + ), + ) + + +def _record(**overrides: object) -> CalibrationAdjustmentSupersessionAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "calibration_receipt_reference": RECEIPT, + "calibration_receipt_digest": DIGEST, + "evidence_version": 1, + "owner_contract_reference": OWNER, + "owner_contract_version": 1, + "owner_contract_digest": OWNER_DIGEST, + "owner_contract_released_at": OWNER_RELEASED, + "released_at": RELEASED, + "superseded_at": CUTOVER, + "successor_calibration_receipt_reference": SUCCESSOR, + "successor_calibration_receipt_digest": SUCCESSOR_DIGEST, + "successor_evidence_version": 1, + "successor_released_at": CUTOVER, + } + values.update(overrides) + return CalibrationAdjustmentSupersessionAuthorityRecord(**values) + + +def _resolve( + record: CalibrationAdjustmentSupersessionAuthorityRecord, *, used_at: datetime +): + return resolve_calibration_adjustment_supersession_authority( + principal=_principal(), + tenant_record_id=TENANT, + validity_study_id=STUDY, + calibration_receipt_reference=RECEIPT, + calibration_receipt_digest=DIGEST, + evidence_version=1, + owner_contract_reference=OWNER, + owner_contract_version=1, + owner_contract_digest=OWNER_DIGEST, + used_at=used_at, + purpose_code="selection_validity_analysis", + policy=_policy(), + read_port=_ReadPort(record), + ) + + +def test_successor_edge_requires_complete_atomic_released_coordinates() -> None: + with pytest.raises(ValueError, match="complete released successor coordinates"): + _record(successor_released_at=None) + + with pytest.raises(ValueError, match="exactly at supersession"): + _record(successor_released_at=CUTOVER - timedelta(seconds=1)) + + with pytest.raises(ValueError, match="exactly at supersession"): + _record(successor_released_at=CUTOVER + timedelta(seconds=1)) + + with pytest.raises(ValueError, match="new reference"): + _record(successor_calibration_receipt_reference=RECEIPT) + + with pytest.raises(ValueError, match="new evidence"): + _record(successor_calibration_receipt_digest=DIGEST) + + +def test_historical_use_is_allowed_but_cutover_use_fails_closed() -> None: + record = _record() + view = _resolve(record, used_at=CUTOVER - timedelta(microseconds=1)) + + assert isinstance(_ReadPort(record), CalibrationAdjustmentSupersessionAuthorityReadPort) + assert ("calibration_receipt_reference", RECEIPT) in view.fields + assert all(not name.startswith("successor_") for name, _ in view.fields) + + with pytest.raises( + CalibrationAdjustmentSupersessionAuthorityIntegrityError, + match="superseded", + ): + _resolve(record, used_at=CUTOVER) + + +def test_open_interval_without_successor_remains_current() -> None: + record = _record( + superseded_at=None, + successor_calibration_receipt_reference=None, + successor_calibration_receipt_digest=None, + successor_evidence_version=None, + successor_released_at=None, + ) + + view = _resolve(record, used_at=CUTOVER + timedelta(days=30)) + assert ("released_at", RELEASED) in view.fields + assert ("superseded_at", None) in view.fields From 4af8260065d15fed481d81a90d4cf45f4af74693 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 12:05:01 +0900 Subject: [PATCH 265/603] feat(workforce-validation): add calibration supersession authority --- ...ation_adjustment_supersession_authority.py | 456 ++++++++++++++++++ 1 file changed, 456 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_supersession_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_supersession_authority.py new file mode 100644 index 000000000..f00325ee3 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_supersession_authority.py @@ -0,0 +1,456 @@ +"""Corroborate append-only typed calibration-adjustment correction authority. + +The ordinary calibration projection proves which released calibration receipt +produced a point-weight artifact. This boundary proves the half-open authority +interval for that immutable receipt and, when corrected, the exact released +successor that ends the interval. Successor chronology is owner-resolved and is +never accepted as a caller-selected lookup coordinate. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + +_RESOURCE_KIND = "calibration_adjustment_supersession_authority" +_OPERATION = "read" +_READ_FIELDS = frozenset( + { + "calibration_receipt_reference", + "calibration_receipt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_calibration_receipt_reference", + "successor_calibration_receipt_digest", + "successor_evidence_version", + "successor_released_at", + } +) + + +class CalibrationAdjustmentSupersessionAuthorityNotFound(LookupError): + """Indicate that no released owner evidence corroborates the calibration receipt.""" + + +class CalibrationAdjustmentSupersessionAuthorityIntegrityError(RuntimeError): + """Indicate that released calibration correction evidence cannot authorize use.""" + + +class CalibrationAdjustmentSupersessionAuthorityRecord(tuple): + """Immutable owner projection for one calibration receipt authority interval.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + calibration_receipt_reference: str, + calibration_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + owner_contract_released_at: datetime, + released_at: datetime, + superseded_at: datetime | None = None, + successor_calibration_receipt_reference: str | None = None, + successor_calibration_receipt_digest: str | None = None, + successor_evidence_version: int | None = None, + successor_released_at: datetime | None = None, + ) -> CalibrationAdjustmentSupersessionAuthorityRecord: + """Validate one released predecessor and its optional atomic successor edge.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + receipt_ref = _require_reference( + "calibration_receipt_reference", + calibration_receipt_reference, + "calibration_adjustment_receipt", + ) + receipt_digest = _require_digest( + "calibration_receipt_digest", calibration_receipt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + owner_release = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) + release_instant = _require_aware_datetime("released_at", released_at) + if owner_release > release_instant: + raise ValueError( + "owner contract must be released no later than calibration receipt." + ) + + successor_values = ( + superseded_at, + successor_calibration_receipt_reference, + successor_calibration_receipt_digest, + successor_evidence_version, + successor_released_at, + ) + if all(value is None for value in successor_values): + cutover = None + successor_ref = None + successor_digest = None + successor_version = None + successor_release = None + elif any(value is None for value in successor_values): + raise ValueError( + "calibration supersession requires cutover and complete released successor coordinates." + ) + else: + cutover = _require_aware_datetime("superseded_at", superseded_at) + successor_ref = _require_reference( + "successor_calibration_receipt_reference", + successor_calibration_receipt_reference, + "calibration_adjustment_receipt", + ) + successor_digest = _require_digest( + "successor_calibration_receipt_digest", + successor_calibration_receipt_digest, + ) + successor_version = _require_positive_integer( + "successor_evidence_version", successor_evidence_version + ) + successor_release = _require_aware_datetime( + "successor_released_at", successor_released_at + ) + if cutover <= release_instant: + raise ValueError("superseded_at must be later than calibration receipt release.") + if successor_ref == receipt_ref: + raise ValueError("successor calibration receipt must have a new reference.") + if successor_digest == receipt_digest: + raise ValueError("successor calibration receipt must identify new evidence.") + if successor_version != 1: + raise ValueError("successor_evidence_version must remain 1.") + if successor_release <= release_instant: + raise ValueError( + "successor calibration receipt must be released after its predecessor." + ) + if successor_release != cutover: + raise ValueError( + "successor calibration receipt must be released exactly at supersession." + ) + + current_fields: tuple[tuple[str, object], ...] = ( + ("calibration_receipt_digest", receipt_digest), + ("calibration_receipt_reference", receipt_ref), + ("evidence_version", version), + ("owner_contract_digest", owner_digest), + ("owner_contract_reference", owner_ref), + ("owner_contract_released_at", owner_release), + ("owner_contract_version", owner_version), + ) + successor_fields: tuple[tuple[str, object], ...] | None + if cutover is None: + successor_fields = None + else: + successor_fields = ( + ("successor_calibration_receipt_digest", successor_digest), + ("successor_calibration_receipt_reference", successor_ref), + ("successor_evidence_version", successor_version), + ("successor_released_at", successor_release), + ) + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + current_fields, + release_instant, + cutover, + successor_fields, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable current-receipt authority coordinates.""" + return self[2] + + @property + def released_at(self) -> datetime: + """Return when this calibration receipt became released authority.""" + return self[3] + + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive end of this receipt's authority interval.""" + return self[4] + + @property + def successor_fields(self) -> tuple[tuple[str, object], ...] | None: + """Return internal released successor coordinates, if any.""" + return self[5] + + +class CalibrationAdjustmentSupersessionAuthorityView(tuple): + """Minimized current-receipt authority issued only after authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> CalibrationAdjustmentSupersessionAuthorityView: + """Reject public construction; only the resolver may issue this view.""" + raise TypeError( + "CalibrationAdjustmentSupersessionAuthorityView is issued only by " + "resolve_calibration_adjustment_supersession_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return current receipt authority without successor disclosure.""" + return self[2] + + +@runtime_checkable +class CalibrationAdjustmentSupersessionAuthorityReadPort(Protocol): + """Owner read contract for one released calibration correction state.""" + + def read_calibration_adjustment_supersession_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + calibration_receipt_reference: str, + calibration_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> CalibrationAdjustmentSupersessionAuthorityRecord | None: + """Return matching released calibration supersession evidence or ``None``.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + CalibrationAdjustmentSupersessionAuthorityReadPort, + "read_calibration_adjustment_supersession_authority", +) + + +def resolve_calibration_adjustment_supersession_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + calibration_receipt_reference: str, + calibration_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: CalibrationAdjustmentSupersessionAuthorityReadPort, +) -> CalibrationAdjustmentSupersessionAuthorityView: + """Authorize then resolve the receipt's half-open append-only authority interval.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static( + type(read_port), "read_calibration_adjustment_supersession_authority", None + ) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError( + "read_port must expose a statically callable " + "read_calibration_adjustment_supersession_authority." + ) + + tenant_id = _restore_operational_uuid( + "tenant_record_id", _store_operational_uuid("tenant_record_id", tenant_record_id) + ) + study_id = _restore_operational_uuid( + "validity_study_id", _store_operational_uuid("validity_study_id", validity_study_id) + ) + receipt_ref = _require_reference( + "calibration_receipt_reference", + calibration_receipt_reference, + "calibration_adjustment_receipt", + ) + receipt_digest = _require_digest( + "calibration_receipt_digest", calibration_receipt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer("owner_contract_version", owner_contract_version) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=tenant_id, + validity_study_id=study_id, + calibration_receipt_reference=receipt_ref, + calibration_receipt_digest=receipt_digest, + evidence_version=version, + owner_contract_reference=owner_ref, + owner_contract_version=owner_version, + owner_contract_digest=owner_digest, + ) + if persisted is None: + raise CalibrationAdjustmentSupersessionAuthorityNotFound(str(study_id)) + if type(persisted) is not CalibrationAdjustmentSupersessionAuthorityRecord: + raise CalibrationAdjustmentSupersessionAuthorityIntegrityError( + "owner port returned non-canonical calibration supersession evidence" + ) + + successor_values = ( + None if persisted.successor_fields is None else dict(persisted.successor_fields) + ) + record = CalibrationAdjustmentSupersessionAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + successor_calibration_receipt_reference=( + None + if successor_values is None + else successor_values["successor_calibration_receipt_reference"] + ), + successor_calibration_receipt_digest=( + None + if successor_values is None + else successor_values["successor_calibration_receipt_digest"] + ), + successor_evidence_version=( + None + if successor_values is None + else successor_values["successor_evidence_version"] + ), + successor_released_at=( + None if successor_values is None else successor_values["successor_released_at"] + ), + **dict(persisted.fields), + ) + record_values = dict(record.fields) + if ( + _store_operational_uuid("record tenant_record_id", record.tenant_record_id) + != _store_operational_uuid("requested tenant_record_id", tenant_id) + or _store_operational_uuid("record validity_study_id", record.validity_study_id) + != _store_operational_uuid("requested validity_study_id", study_id) + or record_values["calibration_receipt_reference"] != receipt_ref + or record_values["calibration_receipt_digest"] != receipt_digest + or record_values["evidence_version"] != version + or record_values["owner_contract_reference"] != owner_ref + or record_values["owner_contract_version"] != owner_version + or record_values["owner_contract_digest"] != owner_digest + ): + raise CalibrationAdjustmentSupersessionAuthorityIntegrityError( + "released calibration supersession authority does not match requested coordinates" + ) + if use_instant < record.released_at: + raise CalibrationAdjustmentSupersessionAuthorityIntegrityError( + "calibration receipt must be released before scientific use" + ) + if record.superseded_at is not None and use_instant >= record.superseded_at: + raise CalibrationAdjustmentSupersessionAuthorityIntegrityError( + "calibration receipt is superseded for this scientific-use instant" + ) + + fields = record.fields + ( + ("released_at", record.released_at), + ("superseded_at", record.superseded_at), + ) + return tuple.__new__( + CalibrationAdjustmentSupersessionAuthorityView, + ( + _store_operational_uuid("tenant_record_id", tenant_id), + _store_operational_uuid("validity_study_id", study_id), + fields, + ), + ) From d6ec049ee6357bf825ccda7fd1db4805d5133a76 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 12:06:43 +0900 Subject: [PATCH 266/603] fix(workforce-validation): enforce calibration authority cutover --- .../calibration_adjustment_authority.py | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py index 433332368..78a7c09e2 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py @@ -158,6 +158,7 @@ def __new__( owner_contract_digest: str, owner_contract_released_at: datetime, released_at: datetime, + superseded_at: datetime | None = None, ) -> CalibrationAdjustmentAuthorityRecord: """Validate and detach the receipt-level scientific authority.""" tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) @@ -177,9 +178,7 @@ def __new__( "target_population_digest", target_population_digest ) analysis_window_ref = _require_reference( - "analysis_window_reference", - analysis_window_reference, - "analysis_window", + "analysis_window_reference", analysis_window_reference, "analysis_window" ) auxiliary_authority_ref = _require_reference( "auxiliary_authority_reference", @@ -341,12 +340,19 @@ def __new__( "owner_contract_released_at", owner_contract_released_at ) release_instant = _require_aware_datetime("released_at", released_at) + supersession_instant = ( + None + if superseded_at is None + else _require_aware_datetime("superseded_at", superseded_at) + ) if release_instant < constructed: raise ValueError("released_at cannot precede constructed_at.") if owner_released > release_instant: raise ValueError( "owner_contract_released_at cannot be later than released_at." ) + if supersession_instant is not None and supersession_instant <= release_instant: + raise ValueError("superseded_at must be later than released_at.") return tuple.__new__( cls, @@ -397,6 +403,7 @@ def __new__( benchmark_owner_ver, benchmark_owner_evidence, benchmark_at, + supersession_instant, ), ) @@ -630,6 +637,11 @@ def benchmark_reference_at(self) -> datetime: """Return the exact benchmark reference instant committed by the receipt.""" return self[45] + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive owner-resolved cutover for this calibration receipt.""" + return self[46] + class CalibrationAdjustmentAuthorityView(tuple): """Field-minimized typed calibration evidence issued only after authorization.""" @@ -727,7 +739,7 @@ def read_calibration_adjustment_authority( def _coordinate_tuple(record: CalibrationAdjustmentAuthorityRecord) -> tuple[object, ...]: - """Return caller-known coordinates, excluding owner-resolved release instants.""" + """Return caller-known coordinates, excluding owner-resolved chronology.""" return record[:23] + record[25:46] @@ -852,6 +864,7 @@ def resolve_calibration_adjustment_authority( owner_contract_digest=owner_contract_digest, owner_contract_released_at=constructed_at, released_at=constructed_at, + superseded_at=None, ) tenant_id = requested.tenant_record_id study_id = requested.validity_study_id @@ -976,6 +989,7 @@ def resolve_calibration_adjustment_authority( owner_contract_digest=persisted.owner_contract_digest, owner_contract_released_at=persisted.owner_contract_released_at, released_at=persisted.released_at, + superseded_at=persisted.superseded_at, ) if _coordinate_tuple(record) != _coordinate_tuple(requested): raise CalibrationAdjustmentAuthorityIntegrityError( @@ -985,6 +999,10 @@ def resolve_calibration_adjustment_authority( raise CalibrationAdjustmentAuthorityIntegrityError( "calibration-adjustment evidence must be released before scientific use" ) + if record.superseded_at is not None and use_instant >= record.superseded_at: + raise CalibrationAdjustmentAuthorityIntegrityError( + "calibration-adjustment evidence is superseded for this scientific-use instant" + ) fields: tuple[tuple[str, object], ...] = ( ("algorithm_reference", record.algorithm_reference), From ed9043a089f593e3c1f2e92713ae200d861b8e3c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 12:07:15 +0900 Subject: [PATCH 267/603] feat(workforce-validation): export calibration supersession authority --- .../orgmetra_workforce_validation_api/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index 76b638cd3..6ec7bb04d 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -24,6 +24,14 @@ CalibrationAdjustmentAuthorityView, resolve_calibration_adjustment_authority, ) +from orgmetra_workforce_validation_api.calibration_adjustment_supersession_authority import ( + CalibrationAdjustmentSupersessionAuthorityIntegrityError, + CalibrationAdjustmentSupersessionAuthorityNotFound, + CalibrationAdjustmentSupersessionAuthorityReadPort, + CalibrationAdjustmentSupersessionAuthorityRecord, + CalibrationAdjustmentSupersessionAuthorityView, + resolve_calibration_adjustment_supersession_authority, +) from orgmetra_workforce_validation_api.final_weight_authority import ( FinalAnalysisWeightAuthorityIntegrityError, FinalAnalysisWeightAuthorityNotFound, @@ -150,6 +158,11 @@ "CalibrationAdjustmentAuthorityReadPort", "CalibrationAdjustmentAuthorityRecord", "CalibrationAdjustmentAuthorityView", + "CalibrationAdjustmentSupersessionAuthorityIntegrityError", + "CalibrationAdjustmentSupersessionAuthorityNotFound", + "CalibrationAdjustmentSupersessionAuthorityReadPort", + "CalibrationAdjustmentSupersessionAuthorityRecord", + "CalibrationAdjustmentSupersessionAuthorityView", "CalibrationAuxiliaryAuthorityIntegrityError", "CalibrationAuxiliaryAuthorityNotFound", "CalibrationAuxiliaryAuthorityReadPort", @@ -230,6 +243,7 @@ "read_validity_study", "resolve_base_weight_authority", "resolve_calibration_adjustment_authority", + "resolve_calibration_adjustment_supersession_authority", "resolve_calibration_auxiliary_authority", "resolve_calibration_benchmark_authority", "resolve_final_analysis_weight_authority", From 089163e979b9ab087cded6cd750140b9acfbac03 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 12:07:45 +0900 Subject: [PATCH 268/603] test(workforce-validation): cover calibration currentness cutover --- ...test_calibration_adjustment_currentness.py | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_adjustment_currentness.py diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_currentness.py b/services/workforce-validation-api/tests/test_calibration_adjustment_currentness.py new file mode 100644 index 000000000..d54e02791 --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_currentness.py @@ -0,0 +1,168 @@ +"""Currentness contract for released typed calibration-adjustment evidence.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.calibration_adjustment_authority import ( + CalibrationAdjustmentAuthorityIntegrityError, + CalibrationAdjustmentAuthorityRecord, + _READ_FIELDS, + resolve_calibration_adjustment_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RELEASED = datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc) +CUTOVER = datetime(2026, 9, 17, 13, 0, tzinfo=timezone.utc) + + +class _ReadPort: + def __init__(self, record: CalibrationAdjustmentAuthorityRecord) -> None: + self.record = record + + def read_calibration_adjustment_authority( + self, **_: object + ) -> CalibrationAdjustmentAuthorityRecord: + return self.record + + +def _record(**overrides: object) -> CalibrationAdjustmentAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "calibration_receipt_reference": "calibration_adjustment_receipt:11111111-1111-4111-8111-111111111111", + "calibration_receipt_digest": "1" * 64, + "evidence_version": 1, + "target_population_digest": "2" * 64, + "analysis_window_reference": "analysis_window:2026q3", + "auxiliary_authority_reference": "scientific_auxiliary_authority:33333333-3333-4333-8333-333333333333", + "auxiliary_projection_reference": "calibration_auxiliary_projection:44444444-4444-4444-8444-444444444444", + "auxiliary_projection_version": 1, + "auxiliary_projection_digest": "3" * 64, + "auxiliary_purpose_reference": "scientific_data_use_purpose:55555555-5555-4555-8555-555555555555", + "auxiliary_purpose_digest": "4" * 64, + "auxiliary_owner_contract_reference": "released_owner_contract:66666666-6666-4666-8666-666666666666", + "auxiliary_owner_contract_version": 1, + "auxiliary_owner_contract_digest": "5" * 64, + "auxiliary_authorization_receipt_reference": "scientific_data_authorization:77777777-7777-4777-8777-777777777777", + "auxiliary_authorization_receipt_digest": "6" * 64, + "auxiliary_scientific_use_receipt_reference": "scientific_use_receipt:88888888-8888-4888-8888-888888888888", + "auxiliary_scientific_use_receipt_digest": "7" * 64, + "auxiliary_scientific_use_at": datetime(2026, 9, 16, 11, 0, tzinfo=timezone.utc), + "benchmark_receipt_reference": "calibration_benchmark_receipt:99999999-9999-4999-8999-999999999999", + "benchmark_receipt_version": 1, + "benchmark_receipt_digest": "8" * 64, + "benchmark_owner_contract_reference": "released_owner_contract:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", + "benchmark_owner_contract_version": 1, + "benchmark_owner_contract_digest": "9" * 64, + "benchmark_reference_at": datetime(2026, 9, 16, 11, 30, tzinfo=timezone.utc), + "algorithm_reference": "calibration_algorithm:generalized_regression", + "algorithm_version": 1, + "constraints_digest": "a" * 64, + "termination_code": "converged", + "input_weight_artifact_digest": "b" * 64, + "output_weight_artifact_digest": "c" * 64, + "constructed_at": datetime(2026, 9, 16, 12, 0, tzinfo=timezone.utc), + "fallback_reason_code": None, + "fallback_rule_reference": None, + "fallback_rule_digest": None, + "fallback_algorithm_reference": None, + "fallback_algorithm_version": None, + "fallback_configuration_digest": None, + "owner_contract_reference": "released_owner_contract:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb", + "owner_contract_version": 1, + "owner_contract_digest": "d" * 64, + "owner_contract_released_at": datetime(2026, 9, 16, 12, 30, tzinfo=timezone.utc), + "released_at": RELEASED, + "superseded_at": CUTOVER, + } + values.update(overrides) + return CalibrationAdjustmentAuthorityRecord(**values) + + +def _resolve(record: CalibrationAdjustmentAuthorityRecord, *, used_at: datetime) -> None: + resolve_calibration_adjustment_authority( + principal=ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ), + tenant_record_id=TENANT, + validity_study_id=STUDY, + calibration_receipt_reference=record.calibration_receipt_reference, + calibration_receipt_digest=record.calibration_receipt_digest, + evidence_version=record.evidence_version, + target_population_digest=record.target_population_digest, + analysis_window_reference=record.analysis_window_reference, + auxiliary_authority_reference=record.auxiliary_authority_reference, + auxiliary_projection_reference=record.auxiliary_projection_reference, + auxiliary_projection_version=record.auxiliary_projection_version, + auxiliary_projection_digest=record.auxiliary_projection_digest, + auxiliary_purpose_reference=record.auxiliary_purpose_reference, + auxiliary_purpose_digest=record.auxiliary_purpose_digest, + auxiliary_owner_contract_reference=record.auxiliary_owner_contract_reference, + auxiliary_owner_contract_version=record.auxiliary_owner_contract_version, + auxiliary_owner_contract_digest=record.auxiliary_owner_contract_digest, + auxiliary_authorization_receipt_reference=record.auxiliary_authorization_receipt_reference, + auxiliary_authorization_receipt_digest=record.auxiliary_authorization_receipt_digest, + auxiliary_scientific_use_receipt_reference=record.auxiliary_scientific_use_receipt_reference, + auxiliary_scientific_use_receipt_digest=record.auxiliary_scientific_use_receipt_digest, + auxiliary_scientific_use_at=record.auxiliary_scientific_use_at, + benchmark_receipt_reference=record.benchmark_receipt_reference, + benchmark_receipt_version=record.benchmark_receipt_version, + benchmark_receipt_digest=record.benchmark_receipt_digest, + benchmark_owner_contract_reference=record.benchmark_owner_contract_reference, + benchmark_owner_contract_version=record.benchmark_owner_contract_version, + benchmark_owner_contract_digest=record.benchmark_owner_contract_digest, + benchmark_reference_at=record.benchmark_reference_at, + algorithm_reference=record.algorithm_reference, + algorithm_version=record.algorithm_version, + constraints_digest=record.constraints_digest, + termination_code=record.termination_code, + input_weight_artifact_digest=record.input_weight_artifact_digest, + output_weight_artifact_digest=record.output_weight_artifact_digest, + constructed_at=record.constructed_at, + fallback_reason_code=record.fallback_reason_code, + fallback_rule_reference=record.fallback_rule_reference, + fallback_rule_digest=record.fallback_rule_digest, + fallback_algorithm_reference=record.fallback_algorithm_reference, + fallback_algorithm_version=record.fallback_algorithm_version, + fallback_configuration_digest=record.fallback_configuration_digest, + owner_contract_reference=record.owner_contract_reference, + owner_contract_version=record.owner_contract_version, + owner_contract_digest=record.owner_contract_digest, + used_at=used_at, + purpose_code="selection_validity_analysis", + policy=PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="calibration-adjustment-authority-read-v1", + resource_kind="calibration_adjustment_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=_READ_FIELDS, + ), + read_port=_ReadPort(record), + ) + + +def test_supersession_cutover_is_owner_resolved_and_half_open() -> None: + record = _record() + _resolve(record, used_at=CUTOVER - timedelta(microseconds=1)) + + with pytest.raises(CalibrationAdjustmentAuthorityIntegrityError, match="superseded"): + _resolve(record, used_at=CUTOVER) + + +def test_superseded_at_requires_timezone_and_post_release_cutover() -> None: + with pytest.raises(ValueError): + _record(superseded_at=datetime(2026, 9, 17, 13, 0)) + + with pytest.raises(ValueError, match="later than released_at"): + _record(superseded_at=RELEASED) From 6695690b3e3ab456144e37d9369db5bb3c2741ec Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 12:09:52 +0900 Subject: [PATCH 269/603] test(workforce-validation): cover calibration supersession edges --- ...ration_adjustment_supersession_contract.py | 265 ++++++++++++++---- 1 file changed, 211 insertions(+), 54 deletions(-) diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py b/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py index a0a3f5e04..bba28c42a 100644 --- a/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py @@ -7,17 +7,21 @@ import pytest -from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy from orgmetra_workforce_validation_api import ValidationPrincipal from orgmetra_workforce_validation_api.calibration_adjustment_supersession_authority import ( CalibrationAdjustmentSupersessionAuthorityIntegrityError, + CalibrationAdjustmentSupersessionAuthorityNotFound, CalibrationAdjustmentSupersessionAuthorityReadPort, CalibrationAdjustmentSupersessionAuthorityRecord, + CalibrationAdjustmentSupersessionAuthorityView, resolve_calibration_adjustment_supersession_authority, ) TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000d2") RECEIPT = "calibration_adjustment_receipt:11111111-1111-4111-8111-111111111111" SUCCESSOR = "calibration_adjustment_receipt:22222222-2222-4222-8222-222222222222" OWNER = "released_owner_contract:33333333-3333-4333-8333-333333333333" @@ -27,53 +31,72 @@ OWNER_RELEASED = datetime(2026, 9, 16, 12, 30, tzinfo=timezone.utc) RELEASED = datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc) CUTOVER = datetime(2026, 9, 17, 13, 0, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "calibration_receipt_reference", + "calibration_receipt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_calibration_receipt_reference", + "successor_calibration_receipt_digest", + "successor_evidence_version", + "successor_released_at", + } +) class _ReadPort: - def __init__(self, record: CalibrationAdjustmentSupersessionAuthorityRecord) -> None: - self.record = record + """Return configured correction evidence and retain exact lookup coordinates.""" + + def __init__(self, result: object) -> None: + self.result = result self.calls: list[dict[str, object]] = [] def read_calibration_adjustment_supersession_authority( self, **coordinates: object - ) -> CalibrationAdjustmentSupersessionAuthorityRecord: + ) -> object: self.calls.append(dict(coordinates)) - return self.record + return self.result + + +class _NoReadMethod: + """Deliberately omit the owner read capability.""" + + +class _ProtocolOnly(CalibrationAdjustmentSupersessionAuthorityReadPort): + """Inherit only the Protocol placeholder, not a concrete owner capability.""" -def _principal() -> ValidationPrincipal: +class _DescriptorReadPort: + """Expose a descriptor that must be rejected without execution.""" + + @property + def read_calibration_adjustment_supersession_authority(self) -> object: + raise AssertionError("descriptor must not execute") + + +def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: return ValidationPrincipal( - tenant_record_id=TENANT, + tenant_record_id=tenant_record_id, actor_reference="person:validation-analyst-1", granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), ) -def _policy() -> PurposeBoundAccessPolicy: +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: return PurposeBoundAccessPolicy( tenant_record_id=TENANT, policy_version_code="calibration-adjustment-supersession-read-v1", resource_kind="calibration_adjustment_supersession_authority", - purpose_code="selection_validity_analysis", + purpose_code=purpose_code, operation_code="read", required_scope_code="orgmetra.workforce_validation.read", - permitted_fields=frozenset( - { - "calibration_receipt_reference", - "calibration_receipt_digest", - "evidence_version", - "owner_contract_reference", - "owner_contract_version", - "owner_contract_digest", - "owner_contract_released_at", - "released_at", - "superseded_at", - "successor_calibration_receipt_reference", - "successor_calibration_receipt_digest", - "successor_evidence_version", - "successor_released_at", - } - ), + permitted_fields=READ_FIELDS, ) @@ -99,56 +122,86 @@ def _record(**overrides: object) -> CalibrationAdjustmentSupersessionAuthorityRe return CalibrationAdjustmentSupersessionAuthorityRecord(**values) -def _resolve( - record: CalibrationAdjustmentSupersessionAuthorityRecord, *, used_at: datetime -): - return resolve_calibration_adjustment_supersession_authority( - principal=_principal(), - tenant_record_id=TENANT, - validity_study_id=STUDY, - calibration_receipt_reference=RECEIPT, - calibration_receipt_digest=DIGEST, - evidence_version=1, - owner_contract_reference=OWNER, - owner_contract_version=1, - owner_contract_digest=OWNER_DIGEST, - used_at=used_at, - purpose_code="selection_validity_analysis", - policy=_policy(), - read_port=_ReadPort(record), - ) +def _resolve(*, read_port: object, used_at: datetime, **overrides: object): + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "calibration_receipt_reference": RECEIPT, + "calibration_receipt_digest": DIGEST, + "evidence_version": 1, + "owner_contract_reference": OWNER, + "owner_contract_version": 1, + "owner_contract_digest": OWNER_DIGEST, + "used_at": used_at, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_calibration_adjustment_supersession_authority(**values) def test_successor_edge_requires_complete_atomic_released_coordinates() -> None: with pytest.raises(ValueError, match="complete released successor coordinates"): _record(successor_released_at=None) - + with pytest.raises(ValueError, match="later than calibration receipt release"): + _record(superseded_at=RELEASED) + with pytest.raises(ValueError, match="new reference"): + _record(successor_calibration_receipt_reference=RECEIPT) + with pytest.raises(ValueError, match="new evidence"): + _record(successor_calibration_receipt_digest=DIGEST) + with pytest.raises(ValueError, match="successor_evidence_version must remain 1"): + _record(successor_evidence_version=2) + with pytest.raises(ValueError, match="released after its predecessor"): + _record(superseded_at=RELEASED + timedelta(seconds=1), successor_released_at=RELEASED) with pytest.raises(ValueError, match="exactly at supersession"): _record(successor_released_at=CUTOVER - timedelta(seconds=1)) - with pytest.raises(ValueError, match="exactly at supersession"): _record(successor_released_at=CUTOVER + timedelta(seconds=1)) - with pytest.raises(ValueError, match="new reference"): - _record(successor_calibration_receipt_reference=RECEIPT) - with pytest.raises(ValueError, match="new evidence"): - _record(successor_calibration_receipt_digest=DIGEST) +def test_chronology_requires_released_owner_and_timezone_aware_instants() -> None: + with pytest.raises(ValueError, match="owner contract"): + _record(owner_contract_released_at=RELEASED + timedelta(seconds=1)) + with pytest.raises(ValueError): + _record(owner_contract_released_at=datetime(2026, 9, 16, 12, 30)) + with pytest.raises(ValueError): + _record(released_at=datetime(2026, 9, 16, 13, 0)) + with pytest.raises(ValueError): + _record(superseded_at=datetime(2026, 9, 17, 13, 0)) + with pytest.raises(ValueError): + _record(successor_released_at=datetime(2026, 9, 17, 13, 0)) def test_historical_use_is_allowed_but_cutover_use_fails_closed() -> None: record = _record() - view = _resolve(record, used_at=CUTOVER - timedelta(microseconds=1)) + port = _ReadPort(record) + view = _resolve(read_port=port, used_at=CUTOVER - timedelta(microseconds=1)) - assert isinstance(_ReadPort(record), CalibrationAdjustmentSupersessionAuthorityReadPort) + assert isinstance(port, CalibrationAdjustmentSupersessionAuthorityReadPort) + assert port.calls == [ + { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "calibration_receipt_reference": RECEIPT, + "calibration_receipt_digest": DIGEST, + "evidence_version": 1, + "owner_contract_reference": OWNER, + "owner_contract_version": 1, + "owner_contract_digest": OWNER_DIGEST, + } + ] assert ("calibration_receipt_reference", RECEIPT) in view.fields + assert ("released_at", RELEASED) in view.fields + assert ("superseded_at", CUTOVER) in view.fields assert all(not name.startswith("successor_") for name, _ in view.fields) with pytest.raises( CalibrationAdjustmentSupersessionAuthorityIntegrityError, match="superseded", ): - _resolve(record, used_at=CUTOVER) + _resolve(read_port=_ReadPort(record), used_at=CUTOVER) def test_open_interval_without_successor_remains_current() -> None: @@ -160,6 +213,110 @@ def test_open_interval_without_successor_remains_current() -> None: successor_released_at=None, ) - view = _resolve(record, used_at=CUTOVER + timedelta(days=30)) + view = _resolve(read_port=_ReadPort(record), used_at=CUTOVER + timedelta(days=30)) assert ("released_at", RELEASED) in view.fields assert ("superseded_at", None) in view.fields + + +def test_missing_noncanonical_and_pre_release_owner_evidence_fail_closed() -> None: + with pytest.raises(CalibrationAdjustmentSupersessionAuthorityNotFound): + _resolve(read_port=_ReadPort(None), used_at=CUTOVER - timedelta(seconds=1)) + with pytest.raises(CalibrationAdjustmentSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object()), used_at=CUTOVER - timedelta(seconds=1)) + with pytest.raises( + CalibrationAdjustmentSupersessionAuthorityIntegrityError, + match="released before scientific use", + ): + _resolve(read_port=_ReadPort(_record()), used_at=RELEASED - timedelta(seconds=1)) + + +@pytest.mark.parametrize( + "record_overrides", + [ + {"tenant_record_id": OTHER_TENANT}, + {"validity_study_id": OTHER_STUDY}, + {"calibration_receipt_reference": SUCCESSOR}, + {"calibration_receipt_digest": "4" * 64}, + {"evidence_version": 2}, + {"owner_contract_reference": "released_owner_contract:44444444-4444-4444-8444-444444444444"}, + {"owner_contract_version": 2}, + {"owner_contract_digest": "5" * 64}, + ], +) +def test_owner_evidence_must_match_every_requested_coordinate( + record_overrides: dict[str, object] +) -> None: + record = _record(**record_overrides) + with pytest.raises(CalibrationAdjustmentSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(record), used_at=CUTOVER - timedelta(seconds=1)) + + +def test_authorization_denial_precedes_owner_read() -> None: + port = _ReadPort(_record()) + with pytest.raises(AuthorizationDeniedError): + _resolve( + read_port=port, + used_at=CUTOVER - timedelta(seconds=1), + policy=_policy(purpose_code="audit_review"), + ) + assert port.calls == [] + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("calibration_receipt_reference", "wrong:receipt", ValueError), + ("calibration_receipt_digest", "ABC", ValueError), + ("evidence_version", 2, ValueError), + ("owner_contract_reference", "wrong:contract", ValueError), + ("owner_contract_version", 0, ValueError), + ("owner_contract_digest", "3" * 63, ValueError), + ("used_at", datetime(2026, 9, 17, 12, 0), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_or_dependency_fails_before_owner_resolution( + key: str, value: object, error: type[Exception] +) -> None: + port: object = _ReadPort(_record()) + overrides = {key: value} + if key == "read_port": + port = value + overrides = {} + with pytest.raises(error): + _resolve( + read_port=port, + used_at=CUTOVER - timedelta(seconds=1), + **overrides, + ) + if isinstance(port, _ReadPort): + assert port.calls == [] + + +def test_record_and_view_are_immutable_and_uuid_views_detached() -> None: + tenant = UUID(str(TENANT)) + record = _record(tenant_record_id=tenant) + object.__setattr__(tenant, "int", OTHER_TENANT.int) + assert record.tenant_record_id == TENANT + + with pytest.raises(AttributeError): + object.__setattr__(record, "released_at", CUTOVER) + + view = _resolve(read_port=_ReadPort(record), used_at=CUTOVER - timedelta(seconds=1)) + returned_tenant = view.tenant_record_id + object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) + assert view.tenant_record_id == TENANT + + with pytest.raises(TypeError): + CalibrationAdjustmentSupersessionAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) From 2e9b7b55b1ab46f3794e0841a142ebd812df7951 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 12:13:13 +0900 Subject: [PATCH 270/603] docs(workforce-validation): document calibration correction authority --- services/workforce-validation-api/README.md | 70 +++++++++------------ 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 907bd6f6a..9f41461be 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -32,91 +32,79 @@ Foreign domain truth crosses this boundary only through released/versioned contr `resolve_calibration_adjustment_authority(...)` corroborates the exact released calibration receipt that produced a point-weight artifact. It binds the receipt/evidence version to the exact target-population digest and analysis-window reference, scientific auxiliary-authority reference, auxiliary projection reference/version/digest, scientific-use purpose reference/digest, auxiliary owner-contract reference/version/digest, authorization and scientific-use receipt references/digests plus scientific-use instant, benchmark receipt reference/version/digest, benchmark owner-contract reference/version/digest plus benchmark reference instant, primary method, constraints, artifacts, construction time, and the released application owner contract. `fallback_applied` additionally requires the primary failure reason, immutable fallback rule, and actual fallback algorithm/version/configuration; `converged` rejects fallback-only evidence. Raw auxiliary values, benchmark totals, protected attributes, and row-level weights are excluded. -The supporting auxiliary-use and benchmark-reference instants are caller-known receipt coordinates committed by the scientific calibration receipt and may not postdate calibration construction. The application owner-contract release instant is different: it is canonical owner evidence, not a resolver request coordinate. It must be timezone-aware and no later than the calibration receipt release. A contract may legitimately be released after adjustment construction but before receipt release, while a later contract cannot retroactively authorize an already released calibration receipt. Exact supporting references/versions/digests prevent the application owner from collapsing auxiliary or benchmark provenance to floating digest-only labels. +The supporting auxiliary-use and benchmark-reference instants are caller-known receipt coordinates committed by the scientific calibration receipt and may not postdate calibration construction. The application owner-contract release instant is canonical owner evidence, not a resolver request coordinate. It must be timezone-aware and no later than the calibration receipt release. A contract may legitimately be released after adjustment construction but before receipt release, while a later contract cannot retroactively authorize an already released calibration receipt. + +The ordinary typed-calibration record also carries an optional owner-resolved `superseded_at`. It is not a caller lookup coordinate and is not projected as reusable downstream authority. Scientific use is valid only on `[released_at, superseded_at)`: historical use before cutover remains reproducible and use at or after cutover fails closed. + +## Calibration-adjustment supersession authority + +`resolve_calibration_adjustment_supersession_authority(...)` proves the append-only correction edge behind typed-calibration currentness. An ordinary `superseded_at` alone is not enough to prove which immutable receipt ended the predecessor interval. A correction therefore requires one complete successor calibration receipt reference/digest/evidence-version/release tuple. + +The successor must identify new immutable receipt evidence, remain on the governed v1 contract, be released after its predecessor, and satisfy `successor_released_at == superseded_at`. Successor coordinates are owner-resolved and omitted from the minimized current-receipt view. Durable persistence must make the ordinary calibration projection's cutover and the explicit successor edge agree on the same atomic correction instant; mutable current rows and caller timestamps are not correction authority. ## Typed nonresponse-adjustment authority `resolve_nonresponse_adjustment_authority(...)` corroborates the exact released disposition-aware nonresponse receipt. It binds receipt/evidence version, exact response/disposition receipt reference/version/digest, owner-resolved disposition release time, adjustment population, method/version/configuration, explicit ineligible/unknown/unavailable treatments, input/output weight artifacts, construction time, and released owner contract. The disposition input must already exist by adjustment construction and scientific use cannot precede the typed receipt's release. Response values, source attributes, protected attributes, and row-level weights are excluded. -The owner-contract release instant and optional exclusive nonresponse cutover are resolved only from canonical owner evidence. Neither is a caller lookup coordinate. The contract must be timezone-aware and exist no later than the nonresponse receipt release, while the ordinary resolver enforces `[released_at, superseded_at)`. Historical use before cutover remains reproducible and use at or after cutover fails closed, so a corrected disposition, adjustment population, treatment rule, or weight-artifact transition cannot leave an older nonresponse receipt apparently current. +The owner-contract release instant and optional exclusive nonresponse cutover are canonical owner evidence rather than caller lookup coordinates. The ordinary resolver enforces `[released_at, superseded_at)`, so a corrected disposition, adjustment population, treatment rule, or weight-artifact transition cannot leave an older receipt apparently current. ## Nonresponse-adjustment supersession authority -`resolve_nonresponse_adjustment_supersession_authority(...)` supplies the append-only correction edge required by #407 RED #10 for typed nonresponse weighting. An owner-resolved `superseded_at` on the ordinary projection is not enough to prove which immutable released receipt ended the predecessor interval. The supersession record therefore binds the current nonresponse receipt reference/digest/evidence version and released owner contract to release chronology and, when corrected, requires one complete successor receipt reference/digest/evidence version/release tuple. - -The successor must identify new immutable receipt evidence, remain on the governed v1 contract, be released after its predecessor, and satisfy `successor_released_at == superseded_at`. The predecessor is authoritative only on `[released_at, superseded_at)`. Successor coordinates remain owner-resolved evidence and are deliberately omitted from the minimized downstream view. Durable persistence must make the ordinary nonresponse projection's cutover and the explicit successor edge agree on the same atomic correction instant; currentness may not be inferred from a mutable current row or caller timestamp. +`resolve_nonresponse_adjustment_supersession_authority(...)` binds the current nonresponse receipt and owner contract to release chronology and, when corrected, requires one complete successor receipt reference/digest/evidence-version/release tuple. The successor must identify new immutable evidence on the governed v1 contract, be released after its predecessor, and satisfy `successor_released_at == superseded_at`. Durable persistence must cross-check the ordinary nonresponse cutover against this explicit edge. ## Trimming/bounding adjustment authority `resolve_trimming_bounding_authority(...)` corroborates the exact released trimming or bounding receipt rather than trusting an adjustment-chain digest alone. It binds the typed receipt reference/digest/evidence version to the governed `weight_trimming_rule` reference/version, immutable rule configuration, exact affected-case occurrence-set digest and positive affected-case count, input/output weight-artifact transition, construction time and released owner-contract tuple. Input and output artifacts may not alias; release cannot precede construction or scientific use. Case identities and row-level weights are excluded from the projection. -The governing owner-contract release instant and optional exclusive trimming/bounding cutover are owner-resolved evidence and never caller lookup coordinates. The contract must exist no later than the adjustment receipt release and the ordinary resolver enforces `[released_at, superseded_at)`. Historical use before cutover remains reproducible; use at or after cutover fails closed. This preserves which governed rule changed which case occurrence set without copying cases into `workforce_validation` while preventing a corrected rule, affected set, or weight transition from leaving an older receipt apparently current. +The governing owner-contract release instant and optional exclusive trimming/bounding cutover are owner-resolved evidence and never caller lookup coordinates. The ordinary resolver enforces `[released_at, superseded_at)`. ## Trimming/bounding supersession authority -`resolve_trimming_bounding_supersession_authority(...)` supplies the explicit correction edge for typed trimming/bounding receipts. When a predecessor is superseded, owner evidence must identify one complete successor receipt reference/digest/evidence-version/release tuple. The successor must be new immutable evidence on the governed v1 receipt contract, be released after its predecessor, and be released exactly at the predecessor's `superseded_at` cutover. - -Successor coordinates remain internal owner evidence and are omitted from the minimized current-receipt view. Durable persistence must cross-check the ordinary trimming/bounding projection's `superseded_at` against the successor receipt release rather than infer currentness from mutable current rows, caller timestamps, or a floating rule pointer. +`resolve_trimming_bounding_supersession_authority(...)` supplies the explicit correction edge for typed trimming/bounding receipts. A corrected predecessor requires one complete new successor receipt reference/digest/evidence-version/release tuple, with successor release exactly at the predecessor's `superseded_at`. Successor coordinates remain internal owner evidence. ## Weight-eligibility authority -`resolve_weight_eligibility_authority(...)` corroborates #407 RED #9 instead of treating an eligibility digest as sufficient authority. It binds the exact `weight_eligibility_receipt` reference/digest/evidence version to explicit `cross_sectional | longitudinal` scope, governed target-population and reference-duration coordinates, exact eligible-case set, exact point-weight artifact, construction time, released owner-contract tuple, and owner-resolved receipt release time. Cross-sectional and longitudinal eligibility are distinct authority states; a different population, duration, case set, or artifact cannot be silently reused. Person attributes and row-level weights are excluded. - -The governing owner-contract release instant and optional exclusive eligibility cutover are also owner-resolved evidence, not caller coordinates. The owner contract must exist no later than the eligibility receipt release, and the ordinary resolver enforces `[released_at, superseded_at)`. Historical scientific use before cutover remains reproducible; use at or after cutover fails closed. This prevents a corrected population, duration, eligible-case set, or point-weight artifact from leaving an older eligibility receipt apparently current merely because a consumer bypasses a higher-level correction path. +`resolve_weight_eligibility_authority(...)` binds the exact `weight_eligibility_receipt` reference/digest/evidence version to explicit `cross_sectional | longitudinal` scope, governed target-population and reference-duration coordinates, exact eligible-case set, exact point-weight artifact, construction time, released owner-contract tuple, and owner-resolved receipt release time. The optional exclusive cutover is owner-resolved and the resolver enforces `[released_at, superseded_at)`. ## Weight-eligibility supersession authority -`resolve_weight_eligibility_supersession_authority(...)` closes the eligibility-specific part of #407 RED #10. An owner-resolved `superseded_at` on the ordinary eligibility projection is not by itself enough to prove which immutable released successor ended the predecessor's authority. The correction record therefore binds the current eligibility receipt reference/digest/evidence version to its release chronology and, when corrected, requires one complete successor receipt reference/digest/evidence version and successor release instant. - -The successor must identify new receipt evidence, remain on the governed v1 receipt contract, be released after its predecessor, and be released exactly at the predecessor cutover. The predecessor is authoritative only on `[released_at, superseded_at)`. Historical reconstruction before cutover remains valid; use at or after cutover fails closed. Successor coordinates are internal owner evidence and are omitted from the returned view. The durable adapter must make the ordinary eligibility projection's cutover agree with this graph rather than derive currentness from a mutable row or caller timestamp. +`resolve_weight_eligibility_supersession_authority(...)` proves which immutable successor ended an eligibility receipt's authority. A correction requires a complete successor receipt reference/digest/evidence version/release instant; it must identify new evidence and be released exactly at the predecessor cutover. The durable adapter must make the ordinary eligibility projection's cutover agree with this graph rather than derive currentness from a mutable row or caller timestamp. ## Base/design-weight authority -`resolve_base_weight_authority(...)` corroborates the base/design-weight derivation instead of accepting `base_weight_evidence_digest` as an opaque caller label. It binds an exact released base-weight evidence receipt to the source-universe and sampling-design receipt references/versions/digests, their release chronology, the sampled occurrence set, an immutable digest of the stage-wise selection-probability evidence, the positive selection-stage count, base-weight method/version, resulting base-weight artifact, construction time, and released owner contract. +`resolve_base_weight_authority(...)` corroborates the base/design-weight derivation instead of accepting `base_weight_evidence_digest` as an opaque caller label. It binds an exact released base-weight evidence receipt to source-universe and sampling-design receipt references/versions/digests, their release chronology, the sampled occurrence set, stage-wise selection-probability evidence digest and stage count, base-weight method/version, resulting artifact, construction time, and released owner contract. -The stage-wise probability values themselves stay with the sampling owner. `workforce_validation` receives only the evidence identity needed to prove which selection-probability set and sampled occurrence set produced the base artifact. The source-universe release instant, sampling-design release instant, and owner-contract release instant are all **owner-resolved evidence**, not caller request coordinates. Source and sampling evidence must already be released when the base weight is constructed; the owner contract must be released no later than the base-weight evidence receipt. All three instants must be timezone-aware. A caller therefore cannot manufacture favorable chronology by supplying release timestamps, and a later owner contract cannot retroactively authorize an earlier receipt. Scientific use cannot precede release of the base-weight evidence. This closes the #407 gap where the final-weight receipt carried only a base-evidence digest and artifact identity without independently corroborating the sampling evidence needed to verify `1/π` or another controlled base-weight derivation. +Stage-wise probability values stay with the sampling owner. Source-universe, sampling-design and owner-contract release instants are owner-resolved evidence rather than caller coordinates. Source and sampling evidence must already be released when the base weight is constructed; the owner contract must be released no later than the base-weight evidence receipt. The owner read is keyed by the complete caller-known reproducibility tuple rather than a partial receipt/source/design prefix. ## Final analysis-weight authority -`resolve_final_analysis_weight_authority(...)` corroborates the complete #407 point-estimation lineage rather than trusting only the final receipt digest carried by the point-weight/variance compatibility boundary. It binds the exact final analysis-weight receipt to the estimand, target population, analysis unit/window/reference duration, eligible and analytic-case sets, owner-resolved source-universe and sampling-design receipt references/versions/digests, base-weight method/evidence/artifact, ordered typed adjustment chain, final point-weight artifact, weight-eligibility receipt, analytic-case count, append-only correction lineage, construction/release chronology, and released owner contract. +`resolve_final_analysis_weight_authority(...)` corroborates the complete #407 point-estimation lineage. It binds the exact final analysis-weight receipt to the estimand, target population, analysis unit/window/reference duration, eligible and analytic-case sets, owner-resolved source-universe and sampling-design evidence, base-weight method/evidence/artifact, ordered typed adjustment chain, final point-weight artifact, weight-eligibility receipt, analytic-case count, append-only correction lineage, construction/release chronology, and released owner contract. -The owner read is keyed by that complete caller-known reproducibility tuple rather than only receipt/source/design identifiers. Multiple released final-weight records that share the old prefix but differ in estimand, population, analytic-case set, base-weight evidence, ordered adjustments, final artifact, eligibility, construction, correction lineage, or owner-contract digest therefore cannot be selected ambiguously by persistence before integrity comparison. Owner-contract release, final-weight release, and supersession instants remain owner-resolved chronology and are not caller lookup coordinates. - -The ordered adjustment chain is immutable and contiguous: each transform must consume the preceding artifact, material transforms may not be no-ops, and known nonresponse/calibration/raking/poststratification/trimming/bounding/winsorization codes require their specialized receipt kind. Source/sampling references are owner-corroborated coordinates layered over the digest-only scientific leaf, so a caller cannot turn an opaque digest into a floating source/design version. The separate base-weight authority additionally resolves the stage-wise selection-probability evidence behind the base artifact. No row-level weights, case identities, protected calibration values, or foreign tables cross this boundary. - -The ordinary final-weight resolver itself now resolves the governing owner-contract release instant and optional exclusive supersession cutover from canonical owner evidence. Neither is a caller request coordinate. A later owner contract cannot retroactively authorize an earlier final-weight receipt, and scientific use is valid only on `[released_at, superseded_at)`. The separate supersession authority still proves the complete predecessor/successor edge; this lower-level resolver consumes only the owner-resolved chronology needed to prevent stale final-weight evidence from remaining usable when callers do not traverse that graph. +The owner read is keyed by the complete caller-known reproducibility tuple. Owner-contract release, final-weight release and supersession instants remain owner-resolved chronology. The ordered adjustment chain is immutable and contiguous; known nonresponse/calibration/raking/poststratification/trimming/bounding/winsorization codes require their specialized receipt kind. Scientific use is valid only on `[released_at, superseded_at)`. ## Final analysis-weight supersession authority -`resolve_final_weight_supersession_authority(...)` closes the point-weight side of #407 RED #10 at the application-owner boundary. A `correction_sequence` plus predecessor digest is not enough to prove that a previously released final-weight receipt stopped being authoritative without in-place mutation. The owner record therefore preserves the predecessor release instant, exclusive supersession instant, and complete released successor coordinates. The successor must have a new receipt reference and digest, advance the correction sequence exactly by one, be released after its predecessor, and be released exactly at the predecessor's cutover. The released owner contract must predate the predecessor receipt. - -Scientific use is evaluated against the owner-resolved half-open interval `[released_at, superseded_at)`. Historical use inside that interval remains reproducible, while use at or after the cutover fails closed. Exact release-at-cutover prevents an overlap or gap in released final-weight authority: predecessor authority ends at the same instant successor authority begins. Successor coordinates are deliberately omitted from the returned view so downstream callers receive only the currently requested receipt authority, not a reusable correction graph. Row-level weights and case identities remain outside this boundary. +`resolve_final_weight_supersession_authority(...)` preserves predecessor release, exclusive supersession and complete released successor coordinates. The successor must have a new receipt reference and digest, advance correction sequence exactly by one, be released after its predecessor, and be released exactly at the predecessor cutover. Successor coordinates are omitted from the downstream view. ## Point-weight / variance authority -`resolve_weight_variance_authority(...)` corroborates released #405 sampling evidence, final analysis-weight receipt, analytic-case occurrence set, weight-eligibility receipt digest, correction sequence, final point-weight artifact, separate #406 variance-design evidence, variance method/evidence semantics, and released owner contract. A variance receipt cannot alias the point-weight receipt, and approximation evidence cannot be represented as exact. The owner read is keyed by this complete compatibility tuple rather than an incomplete prefix, so multiple released bindings that share sampling or receipt identifiers cannot be ambiguously selected. The separate eligibility, eligibility-supersession, base-weight, final analysis-weight, and final-weight-supersession authorities supply the durable population/duration, append-only eligibility correction, selection-probability provenance, complete ordered point-weight lineage, and correction authority interval behind those compatibility coordinates. +`resolve_weight_variance_authority(...)` corroborates released sampling evidence, final analysis-weight receipt, analytic-case occurrence set, weight-eligibility receipt, correction sequence, final point-weight artifact, separate variance-design evidence, variance method/evidence semantics, and released owner contract. A variance receipt cannot alias the point-weight receipt, and approximation evidence cannot be represented as exact. The owner read is keyed by the complete compatibility tuple. -The compatibility binding itself now resolves the governing owner-contract release instant and an optional exclusive supersession cutover from canonical owner evidence. Neither is a caller request coordinate. The owner contract must already exist when the compatibility authority is released, and the ordinary resolver enforces the owner-resolved half-open interval `[released_at, superseded_at)`. Historical use before cutover remains reproducible; use at or after cutover fails closed. This prevents a corrected point-weight or variance-design lineage from leaving an older compatibility binding apparently current merely because a consumer bypassed a higher-level correction path. +The binding resolves owner-contract release and optional exclusive supersession from canonical owner evidence and enforces `[released_at, superseded_at)`. This prevents corrected point-weight or variance-design lineage from leaving an older compatibility binding apparently current. ## Released validation-result authority -`resolve_validation_result_authority(...)` binds one immutable validation result to the exact `WeightVarianceCompatibilityReceipt`, final analysis-weight receipt, separate variance-design receipt, non-authorizing `verification_pending | not_verifiable` state, and released owner contract. Numerical convergence is not promoted to `verified` at this boundary. - -The binding now also resolves `owner_contract_released_at` and the optional exclusive `superseded_at` from canonical owner evidence. Neither timestamp is a caller request coordinate. A later owner contract cannot retroactively authorize an earlier released result, and the ordinary result-binding resolver itself honors the same half-open `[released_at, superseded_at)` authority interval as the correction graph. Historical reads before cutover remain reproducible; use at or after cutover fails closed. This prevents a consumer from bypassing currentness simply by calling the result-binding resolver without separately traversing the successor graph. +`resolve_validation_result_authority(...)` binds one immutable validation result to the exact point-weight/variance compatibility receipt, final analysis-weight receipt, separate variance-design receipt, non-authorizing `verification_pending | not_verifiable` state, and released owner contract. Owner-contract release and optional exclusive cutover are canonical owner chronology. Historical reads before cutover remain reproducible; use at or after cutover fails closed. ## Validation-result supersession authority -`resolve_validation_result_supersession_authority(...)` closes the released-result side of #407 RED #10. A corrected final weight or recomputed estimate must not leave an earlier released `ValidationAnalysisResult` looking current. The owner record therefore resolves the result release instant, optional exclusive supersession instant, and complete released successor result reference/correction-sequence/digest/release instant. The successor must use a new `validation_analysis_result` reference and digest, advance correction sequence exactly by one, be released after its predecessor, and be released exactly at the predecessor's cutover. The released owner contract must already exist when the predecessor result is released. - -Result authority is the half-open owner-resolved interval `[released_at, superseded_at)`: historical use remains reproducible before cutover and use at or after cutover fails closed. Exact release-at-cutover prevents overlap or gap between corrected result authorities. Caller timestamps and mutable result rows do not establish correction authority. Successor coordinates remain internal and are not projected to downstream callers. This family proves the complete append-only successor edge; the ordinary result-binding authority consumes only the owner-resolved release/cutover needed to reject stale use. +`resolve_validation_result_supersession_authority(...)` proves the released predecessor/successor result edge. A successor must use a new result reference and digest, advance correction sequence exactly by one, be released after its predecessor, and be released exactly at the predecessor cutover. Caller timestamps and mutable result rows do not establish correction authority. ## Released non-verifiability outcome -`resolve_validation_result_nonverifiability(...)` is the application repair for #407 RED #12. It represents required analysis-weight, weight/variance-compatibility, or variance-design evidence that is `missing | non_reproducible` without turning lookup failure into scientific GREEN. Missing evidence carries no fabricated reference, digest, or release timestamp. Non-reproducible evidence retains the exact failed reference/digest **and the owner-resolved release instant of that failed evidence**; the evidence must already have been released when the verification attempt is evaluated. Every outcome also binds a separate immutable verification-attempt receipt, its owner-resolved release instant, released owner contract, and outcome evaluation/release chronology. Effect estimates, row-level weights, replicate vectors, protected attributes, and foreign application data are excluded. - -The immutable `verification_attempt_reference` and `verification_attempt_digest` are part of the resolver and owner-read lookup identity. Repeated attempts for the same result, evidence kind, failure mode, and owner contract therefore cannot share an ambiguous lookup prefix or let persistence choose an arbitrary attempt. The attempt's `verification_attempt_released_at` remains owner-resolved chronology and is deliberately not a caller/read-port lookup coordinate. +`resolve_validation_result_nonverifiability(...)` represents required analysis-weight, weight/variance-compatibility, or variance-design evidence that is `missing | non_reproducible` without turning lookup failure into scientific GREEN. Missing evidence carries no fabricated reference, digest, or release timestamp. Non-reproducible evidence retains the exact failed reference/digest and owner-resolved release instant; the failed evidence must already have been released when the verification attempt is evaluated. -The failed-evidence release instant, verification-attempt release instant, governing owner-contract release instant, and optional exclusive `superseded_at` are owner-resolved evidence. For `non_reproducible`, `failed_evidence_released_at <= evaluated_at` is mandatory; for `missing`, failed-evidence release chronology must be absent rather than fabricated. The contract must already exist when verification is evaluated. The immutable verification-attempt receipt must be released on the causal interval `evaluated_at <= verification_attempt_released_at <= released_at`, so a later-created attempt receipt cannot be backdated into an earlier negative outcome and a receipt cannot predate the evaluation it records. The ordinary resolver accepts the released negative outcome only on `[released_at, superseded_at)`. This prevents time-travel reproducibility/verification claims and an earlier `not_verifiable` outcome from remaining apparently current after later released evidence makes the same immutable validation result corroboratable. +The immutable `verification_attempt_reference` and `verification_attempt_digest` are part of the resolver and owner-read lookup identity. Verification-attempt release, governing owner-contract release and optional exclusive `superseded_at` remain owner-resolved chronology. The immutable attempt receipt must satisfy `evaluated_at <= verification_attempt_released_at <= released_at`, and the ordinary resolver accepts the released negative outcome only on `[released_at, superseded_at)`. ## Persistence state @@ -124,7 +112,9 @@ The failed-evidence release instant, verification-attempt release instant, gover The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for calibration auxiliary, calibration benchmark, typed calibration adjustment, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession authority, point-weight/variance compatibility, validation-result binding, validation-result supersession authority, and validation-result non-verifiability. The typed-calibration adapter must persist and exact-key the target-population digest, analysis-window reference, scientific auxiliary-authority reference, auxiliary projection reference/version/digest, purpose reference/digest, auxiliary owner-contract reference/version/digest, authorization and scientific-use receipts, scientific-use instant, benchmark receipt reference/version/digest, benchmark owner-contract reference/version/digest, and benchmark-reference instant together with method/artifact/fallback/application-owner coordinates. It may not reconstruct these from a mutable current row or trust only the opaque calibration receipt digest. Calibration-auxiliary owner-contract release time must come from the durable owner record and must not postdate its authorization interval start; calibration-adjustment, nonresponse-adjustment, and trimming/bounding owner-contract release instants likewise come from durable owner records and must not postdate their released receipts. Base-weight source-universe, sampling-design, and owner-contract release instants likewise come from durable owner records rather than caller-supplied request coordinates. Calibration-benchmark, weight-eligibility, nonresponse-adjustment, trimming/bounding, final-weight, and validation-result supersession adapters must persist one atomic correction instant so each predecessor `superseded_at` equals its successor `released_at`; ordinary eligibility, nonresponse and trimming/bounding projections must agree with their explicit supersession graphs. Final-weight, point-weight/variance compatibility, validation-result, and non-verifiability owner-contract release/correction cutovers likewise come only from released owner records, never caller timestamps or mutable current rows. Base-weight and final-analysis-weight persistence must select released owner evidence by their complete caller-known reproducibility tuples; it may not select a partial receipt/source/design prefix and rely on a later in-memory mismatch check. Non-verifiability persistence must key the owner read by the exact immutable verification-attempt reference/digest, preserve `failed_evidence_released_at` for non-reproducible evidence, preserve owner-resolved `verification_attempt_released_at` for every verification attempt, prove `failed_evidence_released_at <= evaluated_at` when applicable, and prove `evaluated_at <= verification_attempt_released_at <= released_at`; missing evidence stores no fabricated failed-evidence release time. Low-level eligibility/nonresponse/trimming/final-weight/binding/non-verifiability adapters must therefore recover canonical chronology rather than independently infer currentness. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **seventeen** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession, point-weight/variance compatibility, validation-result binding, validation-result supersession, and validation-result non-verifiability. + +The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration, eligibility, nonresponse and trimming/bounding ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable verification-attempt reference/digest and preserve failed-evidence and attempt-release chronology. No durable adapter may infer currentness from mutable current rows or caller-supplied timestamps. ## Test contract @@ -139,6 +129,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology without caller-supplied release time, benchmark correction chronology including exact successor release-at-cutover, typed calibration target-population/analysis-window binding, complete auxiliary/benchmark supporting-authority identity and reference-time chronology, fallback provenance and owner-contract chronology, typed nonresponse disposition/treatment provenance, owner-contract chronology and owner-resolved currentness, explicit nonresponse predecessor/successor correction authority with complete immutable successor coordinates and exact release-at-cutover, trimming/bounding rule/affected-case provenance with owner-contract chronology and owner-resolved currentness, explicit trimming/bounding predecessor/successor correction authority with complete immutable successor coordinates and exact release-at-cutover, cross-sectional/longitudinal weight eligibility including owner-contract chronology and owner-resolved cutover, explicit eligibility predecessor/successor correction authority with exact release-at-cutover, stage-wise base/design-weight provenance including owner-resolved source/sampling/contract release chronology and complete read-port lookup coordinates, complete estimand/source/base-weight/ordered-adjustment/final-artifact lineage including owner-contract chronology, low-level final-weight currentness and complete final-weight read-port lookup coordinates, final-weight predecessor/successor correction intervals with exact release-at-cutover, point/variance owner-contract chronology and complete compatibility lookup/binding currentness, validation-result owner-contract chronology and binding currentness, validation-result predecessor/successor correction intervals with exact release-at-cutover, and explicit missing/non-reproducible result evidence including owner-contract chronology, failed-evidence release chronology, exact verification-attempt lookup-key completeness, verification-attempt release chronology, and owner-resolved negative-outcome cutover. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, **typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover**, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity and chronology. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From 27d84512ff79084c78d31bd19ebbd6fee3a50ded Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 12:32:09 +0900 Subject: [PATCH 271/603] test(workforce-validation): establish base-weight currentness RED --- .../tests/test_base_weight_currentness.py | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_base_weight_currentness.py diff --git a/services/workforce-validation-api/tests/test_base_weight_currentness.py b/services/workforce-validation-api/tests/test_base_weight_currentness.py new file mode 100644 index 000000000..d2c6a61d0 --- /dev/null +++ b/services/workforce-validation-api/tests/test_base_weight_currentness.py @@ -0,0 +1,111 @@ +"""Currentness contract for released base/design-weight evidence.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.base_weight_authority import ( + BaseWeightAuthorityIntegrityError, + BaseWeightAuthorityRecord, + _READ_FIELDS, + resolve_base_weight_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") +RELEASED = datetime(2026, 9, 17, 7, 30, tzinfo=timezone.utc) +CUTOVER = datetime(2026, 9, 18, 7, 30, tzinfo=timezone.utc) + + +class _ReadPort: + def __init__(self, record: BaseWeightAuthorityRecord) -> None: + self.record = record + + def read_base_weight_authority(self, **_: object) -> BaseWeightAuthorityRecord: + return self.record + + +def _record(**overrides: object) -> BaseWeightAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "base_weight_evidence_receipt_reference": "base_weight_evidence_receipt:11111111-1111-4111-8111-111111111111", + "base_weight_evidence_receipt_digest": "1" * 64, + "evidence_version": 1, + "source_universe_receipt_reference": "source_universe_receipt:22222222-2222-4222-8222-222222222222", + "source_universe_receipt_version": 4, + "source_universe_receipt_digest": "2" * 64, + "source_universe_released_at": datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc), + "sampling_design_receipt_reference": "sampling_design_receipt:33333333-3333-4333-8333-333333333333", + "sampling_design_receipt_version": 3, + "sampling_design_receipt_digest": "3" * 64, + "sampling_design_released_at": datetime(2026, 9, 17, 6, 30, tzinfo=timezone.utc), + "sampled_occurrence_set_digest": "4" * 64, + "selection_probability_set_digest": "5" * 64, + "selection_stage_count": 2, + "base_weight_method_code": "inverse_inclusion_probability", + "base_weight_method_version": 1, + "base_weight_artifact_digest": "6" * 64, + "constructed_at": datetime(2026, 9, 17, 7, 0, tzinfo=timezone.utc), + "owner_contract_reference": "released_owner_contract:44444444-4444-4444-8444-444444444444", + "owner_contract_version": 6, + "owner_contract_digest": "7" * 64, + "owner_contract_released_at": datetime(2026, 9, 17, 6, 45, tzinfo=timezone.utc), + "released_at": RELEASED, + "superseded_at": CUTOVER, + } + values.update(overrides) + return BaseWeightAuthorityRecord(**values) + + +def _resolve(record: BaseWeightAuthorityRecord, *, used_at: datetime) -> None: + values = dict(record.fields) + for owner_resolved_field in ( + "source_universe_released_at", + "sampling_design_released_at", + "owner_contract_released_at", + ): + values.pop(owner_resolved_field) + resolve_base_weight_authority( + principal=ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ), + tenant_record_id=TENANT, + validity_study_id=STUDY, + used_at=used_at, + purpose_code="selection_validity_analysis", + policy=PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="base-weight-authority-read-v1", + resource_kind="base_weight_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=_READ_FIELDS, + ), + read_port=_ReadPort(record), + **values, + ) + + +def test_supersession_cutover_is_owner_resolved_and_half_open() -> None: + record = _record() + _resolve(record, used_at=CUTOVER - timedelta(microseconds=1)) + + with pytest.raises(BaseWeightAuthorityIntegrityError, match="superseded"): + _resolve(record, used_at=CUTOVER) + + +def test_superseded_at_requires_timezone_and_post_release_cutover() -> None: + with pytest.raises(ValueError): + _record(superseded_at=datetime(2026, 9, 18, 7, 30)) + + with pytest.raises(ValueError, match="later than released_at"): + _record(superseded_at=RELEASED) From 6f57c6d7d80aff2ab7b69a1210068daa4c7a375b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 12:32:56 +0900 Subject: [PATCH 272/603] fix(workforce-validation): enforce base-weight currentness --- .../base_weight_authority.py | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py index c9f3b3619..79a1f8136 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py @@ -61,6 +61,7 @@ "owner_contract_digest", "owner_contract_released_at", "released_at", + "superseded_at", } ) @@ -114,6 +115,7 @@ def __new__( owner_contract_digest: str, owner_contract_released_at: datetime, released_at: datetime, + superseded_at: datetime | None = None, ) -> BaseWeightAuthorityRecord: """Validate the minimum released provenance needed to reproduce a base weight.""" tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) @@ -193,6 +195,11 @@ def __new__( raise ValueError( "owner contract must be released no later than base-weight evidence receipt." ) + cutover = None + if superseded_at is not None: + cutover = _require_aware_datetime("superseded_at", superseded_at) + if cutover <= release_instant: + raise ValueError("superseded_at must be later than released_at.") fields: tuple[tuple[str, object], ...] = ( ("base_weight_artifact_digest", artifact_digest), @@ -218,7 +225,9 @@ def __new__( ("source_universe_receipt_version", source_version), ("source_universe_released_at", source_released), ) - return tuple.__new__(cls, (tenant_identity, study_identity, fields, release_instant)) + return tuple.__new__( + cls, (tenant_identity, study_identity, fields, release_instant, cutover) + ) @property def tenant_record_id(self) -> UUID: @@ -240,6 +249,11 @@ def released_at(self) -> datetime: """Return when the base-weight evidence became released authority.""" return self[3] + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive end of this base-weight receipt's authority interval.""" + return self[4] + class BaseWeightAuthorityView(tuple): """Field-minimized base-weight evidence issued only after authorization.""" @@ -379,6 +393,7 @@ def resolve_base_weight_authority( owner_contract_digest=owner_contract_digest, owner_contract_released_at=constructed_at, released_at=constructed_at, + superseded_at=None, ) tenant_id = requested.tenant_record_id study_id = requested.validity_study_id @@ -461,6 +476,7 @@ def resolve_base_weight_authority( tenant_record_id=persisted.tenant_record_id, validity_study_id=persisted.validity_study_id, released_at=persisted.released_at, + superseded_at=persisted.superseded_at, **dict(persisted.fields), ) record_values = dict(record.fields) @@ -487,9 +503,14 @@ def resolve_base_weight_authority( raise BaseWeightAuthorityIntegrityError( "base-weight authority cannot be used before its release instant" ) + if record.superseded_at is not None and use_instant >= record.superseded_at: + raise BaseWeightAuthorityIntegrityError( + "base-weight authority is superseded for this scientific-use instant" + ) values = dict(record.fields) values["released_at"] = record.released_at + values["superseded_at"] = record.superseded_at fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) return tuple.__new__( BaseWeightAuthorityView, From be6e51738c5f2f6475f2ed1b962fa99c1569ea17 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 12:33:27 +0900 Subject: [PATCH 273/603] test(workforce-validation): establish base-weight supersession RED --- ...test_base_weight_supersession_authority.py | 297 ++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_base_weight_supersession_authority.py diff --git a/services/workforce-validation-api/tests/test_base_weight_supersession_authority.py b/services/workforce-validation-api/tests/test_base_weight_supersession_authority.py new file mode 100644 index 000000000..7512079bf --- /dev/null +++ b/services/workforce-validation-api/tests/test_base_weight_supersession_authority.py @@ -0,0 +1,297 @@ +"""Append-only correction contract for released base/design-weight authority.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.base_weight_supersession_authority import ( + BaseWeightSupersessionAuthorityIntegrityError, + BaseWeightSupersessionAuthorityNotFound, + BaseWeightSupersessionAuthorityReadPort, + BaseWeightSupersessionAuthorityRecord, + BaseWeightSupersessionAuthorityView, + resolve_base_weight_supersession_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000f2") +RECEIPT = "base_weight_evidence_receipt:11111111-1111-4111-8111-111111111111" +SUCCESSOR = "base_weight_evidence_receipt:22222222-2222-4222-8222-222222222222" +OWNER = "released_owner_contract:33333333-3333-4333-8333-333333333333" +DIGEST = "1" * 64 +SUCCESSOR_DIGEST = "2" * 64 +OWNER_DIGEST = "3" * 64 +OWNER_RELEASED = datetime(2026, 9, 17, 6, 45, tzinfo=timezone.utc) +RELEASED = datetime(2026, 9, 17, 7, 30, tzinfo=timezone.utc) +CUTOVER = datetime(2026, 9, 18, 7, 30, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "base_weight_evidence_receipt_reference", + "base_weight_evidence_receipt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_base_weight_evidence_receipt_reference", + "successor_base_weight_evidence_receipt_digest", + "successor_evidence_version", + "successor_released_at", + } +) + + +class _ReadPort: + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[dict[str, object]] = [] + + def read_base_weight_supersession_authority(self, **coordinates: object) -> object: + self.calls.append(dict(coordinates)) + return self.result + + +class _ProtocolOnly(BaseWeightSupersessionAuthorityReadPort): + pass + + +class _DescriptorReadPort: + @property + def read_base_weight_supersession_authority(self) -> object: + raise AssertionError("descriptor must not execute") + + +class _NoReadMethod: + pass + + +def _principal() -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="base-weight-supersession-read-v1", + resource_kind="base_weight_supersession_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record(**overrides: object) -> BaseWeightSupersessionAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "base_weight_evidence_receipt_reference": RECEIPT, + "base_weight_evidence_receipt_digest": DIGEST, + "evidence_version": 1, + "owner_contract_reference": OWNER, + "owner_contract_version": 1, + "owner_contract_digest": OWNER_DIGEST, + "owner_contract_released_at": OWNER_RELEASED, + "released_at": RELEASED, + "superseded_at": CUTOVER, + "successor_base_weight_evidence_receipt_reference": SUCCESSOR, + "successor_base_weight_evidence_receipt_digest": SUCCESSOR_DIGEST, + "successor_evidence_version": 1, + "successor_released_at": CUTOVER, + } + values.update(overrides) + return BaseWeightSupersessionAuthorityRecord(**values) + + +def _resolve(*, read_port: object, used_at: datetime, **overrides: object): + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "base_weight_evidence_receipt_reference": RECEIPT, + "base_weight_evidence_receipt_digest": DIGEST, + "evidence_version": 1, + "owner_contract_reference": OWNER, + "owner_contract_version": 1, + "owner_contract_digest": OWNER_DIGEST, + "used_at": used_at, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_base_weight_supersession_authority(**values) + + +def test_successor_edge_requires_complete_atomic_released_coordinates() -> None: + with pytest.raises(ValueError, match="complete released successor coordinates"): + _record(successor_released_at=None) + with pytest.raises(ValueError, match="later than base-weight receipt release"): + _record(superseded_at=RELEASED) + with pytest.raises(ValueError, match="new reference"): + _record(successor_base_weight_evidence_receipt_reference=RECEIPT) + with pytest.raises(ValueError, match="new evidence"): + _record(successor_base_weight_evidence_receipt_digest=DIGEST) + with pytest.raises(ValueError, match="successor_evidence_version must remain 1"): + _record(successor_evidence_version=2) + with pytest.raises(ValueError, match="released after its predecessor"): + _record(superseded_at=RELEASED + timedelta(seconds=1), successor_released_at=RELEASED) + with pytest.raises(ValueError, match="exactly at supersession"): + _record(successor_released_at=CUTOVER - timedelta(seconds=1)) + with pytest.raises(ValueError, match="exactly at supersession"): + _record(successor_released_at=CUTOVER + timedelta(seconds=1)) + + +def test_chronology_requires_released_owner_and_timezone_aware_instants() -> None: + with pytest.raises(ValueError, match="owner contract"): + _record(owner_contract_released_at=RELEASED + timedelta(seconds=1)) + with pytest.raises(ValueError): + _record(owner_contract_released_at=datetime(2026, 9, 17, 6, 45)) + with pytest.raises(ValueError): + _record(released_at=datetime(2026, 9, 17, 7, 30)) + with pytest.raises(ValueError): + _record(superseded_at=datetime(2026, 9, 18, 7, 30)) + with pytest.raises(ValueError): + _record(successor_released_at=datetime(2026, 9, 18, 7, 30)) + + +def test_historical_use_is_allowed_but_cutover_use_fails_closed() -> None: + record = _record() + port = _ReadPort(record) + view = _resolve(read_port=port, used_at=CUTOVER - timedelta(microseconds=1)) + + assert isinstance(port, BaseWeightSupersessionAuthorityReadPort) + assert port.calls == [ + { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "base_weight_evidence_receipt_reference": RECEIPT, + "base_weight_evidence_receipt_digest": DIGEST, + "evidence_version": 1, + "owner_contract_reference": OWNER, + "owner_contract_version": 1, + "owner_contract_digest": OWNER_DIGEST, + } + ] + assert ("base_weight_evidence_receipt_reference", RECEIPT) in view.fields + assert ("released_at", RELEASED) in view.fields + assert ("superseded_at", CUTOVER) in view.fields + assert all(not name.startswith("successor_") for name, _ in view.fields) + + with pytest.raises(BaseWeightSupersessionAuthorityIntegrityError, match="superseded"): + _resolve(read_port=_ReadPort(record), used_at=CUTOVER) + + +def test_open_interval_without_successor_remains_current() -> None: + record = _record( + superseded_at=None, + successor_base_weight_evidence_receipt_reference=None, + successor_base_weight_evidence_receipt_digest=None, + successor_evidence_version=None, + successor_released_at=None, + ) + view = _resolve(read_port=_ReadPort(record), used_at=CUTOVER + timedelta(days=30)) + assert ("superseded_at", None) in view.fields + + +def test_missing_noncanonical_and_pre_release_evidence_fail_closed() -> None: + with pytest.raises(BaseWeightSupersessionAuthorityNotFound): + _resolve(read_port=_ReadPort(None), used_at=RELEASED) + with pytest.raises(BaseWeightSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object()), used_at=RELEASED) + with pytest.raises(BaseWeightSupersessionAuthorityIntegrityError, match="released before scientific use"): + _resolve(read_port=_ReadPort(_record()), used_at=RELEASED - timedelta(seconds=1)) + + +@pytest.mark.parametrize( + "record_overrides", + [ + {"tenant_record_id": OTHER_TENANT}, + {"validity_study_id": OTHER_STUDY}, + {"base_weight_evidence_receipt_reference": SUCCESSOR}, + {"base_weight_evidence_receipt_digest": "4" * 64}, + {"evidence_version": 2}, + {"owner_contract_reference": "released_owner_contract:44444444-4444-4444-8444-444444444444"}, + {"owner_contract_version": 2}, + {"owner_contract_digest": "5" * 64}, + ], +) +def test_owner_evidence_must_match_every_requested_coordinate(record_overrides: dict[str, object]) -> None: + with pytest.raises(BaseWeightSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(**record_overrides)), used_at=RELEASED) + + +def test_authorization_denial_precedes_owner_read() -> None: + port = _ReadPort(_record()) + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, used_at=RELEASED, policy=_policy(purpose_code="audit_review")) + assert port.calls == [] + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("base_weight_evidence_receipt_reference", "wrong:receipt", ValueError), + ("base_weight_evidence_receipt_digest", "ABC", ValueError), + ("evidence_version", 2, ValueError), + ("owner_contract_reference", "wrong:contract", ValueError), + ("owner_contract_version", 0, ValueError), + ("owner_contract_digest", "3" * 63, ValueError), + ("used_at", datetime(2026, 9, 18, 7, 0), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_or_dependency_fails_before_owner_resolution( + key: str, value: object, error: type[Exception] +) -> None: + port: object = _ReadPort(_record()) + overrides = {key: value} + if key == "read_port": + port = value + overrides = {} + with pytest.raises(error): + _resolve(read_port=port, used_at=RELEASED, **overrides) + if isinstance(port, _ReadPort): + assert port.calls == [] + + +def test_record_and_view_are_immutable_and_uuid_views_detached() -> None: + tenant = UUID(str(TENANT)) + record = _record(tenant_record_id=tenant) + object.__setattr__(tenant, "int", OTHER_TENANT.int) + assert record.tenant_record_id == TENANT + + with pytest.raises(AttributeError): + object.__setattr__(record, "released_at", CUTOVER) + + view = _resolve(read_port=_ReadPort(record), used_at=RELEASED) + returned_tenant = view.tenant_record_id + object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) + assert view.tenant_record_id == TENANT + + with pytest.raises(TypeError): + BaseWeightSupersessionAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) From e1d9d881812561a7d982a77f6142a55556337163 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 12:34:05 +0900 Subject: [PATCH 274/603] feat(workforce-validation): add base-weight supersession authority --- .../base_weight_supersession_authority.py | 465 ++++++++++++++++++ 1 file changed, 465 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_supersession_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_supersession_authority.py new file mode 100644 index 000000000..07eebbb9d --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_supersession_authority.py @@ -0,0 +1,465 @@ +"""Corroborate append-only base/design-weight correction authority. + +The ordinary base-weight projection proves which released sampling evidence +produced a base-weight artifact. This boundary proves the half-open authority +interval for that immutable receipt and, when corrected, the exact released +successor that ends the interval. Successor chronology is owner-resolved and is +never accepted as a caller-selected lookup coordinate. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + +_RESOURCE_KIND = "base_weight_supersession_authority" +_OPERATION = "read" +_READ_FIELDS = frozenset( + { + "base_weight_evidence_receipt_reference", + "base_weight_evidence_receipt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_base_weight_evidence_receipt_reference", + "successor_base_weight_evidence_receipt_digest", + "successor_evidence_version", + "successor_released_at", + } +) + + +class BaseWeightSupersessionAuthorityNotFound(LookupError): + """Indicate that no released owner evidence corroborates the base-weight receipt.""" + + +class BaseWeightSupersessionAuthorityIntegrityError(RuntimeError): + """Indicate that released base-weight correction evidence cannot authorize use.""" + + +class BaseWeightSupersessionAuthorityRecord(tuple): + """Immutable owner projection for one base-weight receipt authority interval.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + base_weight_evidence_receipt_reference: str, + base_weight_evidence_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + owner_contract_released_at: datetime, + released_at: datetime, + superseded_at: datetime | None = None, + successor_base_weight_evidence_receipt_reference: str | None = None, + successor_base_weight_evidence_receipt_digest: str | None = None, + successor_evidence_version: int | None = None, + successor_released_at: datetime | None = None, + ) -> BaseWeightSupersessionAuthorityRecord: + """Validate one released predecessor and its optional atomic successor edge.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + receipt_ref = _require_reference( + "base_weight_evidence_receipt_reference", + base_weight_evidence_receipt_reference, + "base_weight_evidence_receipt", + ) + receipt_digest = _require_digest( + "base_weight_evidence_receipt_digest", base_weight_evidence_receipt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + owner_release = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) + release_instant = _require_aware_datetime("released_at", released_at) + if owner_release > release_instant: + raise ValueError( + "owner contract must be released no later than base-weight receipt." + ) + + successor_values = ( + superseded_at, + successor_base_weight_evidence_receipt_reference, + successor_base_weight_evidence_receipt_digest, + successor_evidence_version, + successor_released_at, + ) + if all(value is None for value in successor_values): + cutover = None + successor_ref = None + successor_digest = None + successor_version = None + successor_release = None + elif any(value is None for value in successor_values): + raise ValueError( + "base-weight supersession requires cutover and complete released successor coordinates." + ) + else: + cutover = _require_aware_datetime("superseded_at", superseded_at) + successor_ref = _require_reference( + "successor_base_weight_evidence_receipt_reference", + successor_base_weight_evidence_receipt_reference, + "base_weight_evidence_receipt", + ) + successor_digest = _require_digest( + "successor_base_weight_evidence_receipt_digest", + successor_base_weight_evidence_receipt_digest, + ) + successor_version = _require_positive_integer( + "successor_evidence_version", successor_evidence_version + ) + successor_release = _require_aware_datetime( + "successor_released_at", successor_released_at + ) + if cutover <= release_instant: + raise ValueError("superseded_at must be later than base-weight receipt release.") + if successor_ref == receipt_ref: + raise ValueError("successor base-weight receipt must have a new reference.") + if successor_digest == receipt_digest: + raise ValueError("successor base-weight receipt must identify new evidence.") + if successor_version != 1: + raise ValueError("successor_evidence_version must remain 1.") + if successor_release <= release_instant: + raise ValueError( + "successor base-weight receipt must be released after its predecessor." + ) + if successor_release != cutover: + raise ValueError( + "successor base-weight receipt must be released exactly at supersession." + ) + + current_fields: tuple[tuple[str, object], ...] = ( + ("base_weight_evidence_receipt_digest", receipt_digest), + ("base_weight_evidence_receipt_reference", receipt_ref), + ("evidence_version", version), + ("owner_contract_digest", owner_digest), + ("owner_contract_reference", owner_ref), + ("owner_contract_released_at", owner_release), + ("owner_contract_version", owner_version), + ) + successor_fields: tuple[tuple[str, object], ...] | None + if cutover is None: + successor_fields = None + else: + successor_fields = ( + ("successor_base_weight_evidence_receipt_digest", successor_digest), + ("successor_base_weight_evidence_receipt_reference", successor_ref), + ("successor_evidence_version", successor_version), + ("successor_released_at", successor_release), + ) + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + current_fields, + release_instant, + cutover, + successor_fields, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable current-receipt authority coordinates.""" + return self[2] + + @property + def released_at(self) -> datetime: + """Return when this base-weight receipt became released authority.""" + return self[3] + + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive end of this receipt's authority interval.""" + return self[4] + + @property + def successor_fields(self) -> tuple[tuple[str, object], ...] | None: + """Return internal released successor coordinates, if any.""" + return self[5] + + +class BaseWeightSupersessionAuthorityView(tuple): + """Minimized current-receipt authority issued only after authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> BaseWeightSupersessionAuthorityView: + """Reject public construction; only the resolver may issue this view.""" + raise TypeError( + "BaseWeightSupersessionAuthorityView is issued only by " + "resolve_base_weight_supersession_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return current receipt authority without successor disclosure.""" + return self[2] + + +@runtime_checkable +class BaseWeightSupersessionAuthorityReadPort(Protocol): + """Owner read contract for one released base-weight correction state.""" + + def read_base_weight_supersession_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + base_weight_evidence_receipt_reference: str, + base_weight_evidence_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> BaseWeightSupersessionAuthorityRecord | None: + """Return matching released base-weight supersession evidence or ``None``.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + BaseWeightSupersessionAuthorityReadPort, + "read_base_weight_supersession_authority", +) + + +def resolve_base_weight_supersession_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + base_weight_evidence_receipt_reference: str, + base_weight_evidence_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: BaseWeightSupersessionAuthorityReadPort, +) -> BaseWeightSupersessionAuthorityView: + """Authorize then resolve the base-weight receipt's append-only authority interval.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static( + type(read_port), "read_base_weight_supersession_authority", None + ) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError( + "read_port must expose a statically callable read_base_weight_supersession_authority." + ) + + tenant_id = _restore_operational_uuid( + "tenant_record_id", _store_operational_uuid("tenant_record_id", tenant_record_id) + ) + study_id = _restore_operational_uuid( + "validity_study_id", _store_operational_uuid("validity_study_id", validity_study_id) + ) + receipt_ref = _require_reference( + "base_weight_evidence_receipt_reference", + base_weight_evidence_receipt_reference, + "base_weight_evidence_receipt", + ) + receipt_digest = _require_digest( + "base_weight_evidence_receipt_digest", base_weight_evidence_receipt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer("owner_contract_version", owner_contract_version) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=tenant_id, + validity_study_id=study_id, + base_weight_evidence_receipt_reference=receipt_ref, + base_weight_evidence_receipt_digest=receipt_digest, + evidence_version=version, + owner_contract_reference=owner_ref, + owner_contract_version=owner_version, + owner_contract_digest=owner_digest, + ) + if persisted is None: + raise BaseWeightSupersessionAuthorityNotFound(str(study_id)) + if type(persisted) is not BaseWeightSupersessionAuthorityRecord: + raise BaseWeightSupersessionAuthorityIntegrityError( + "owner port returned non-canonical base-weight supersession evidence" + ) + + successor_values = ( + None if persisted.successor_fields is None else dict(persisted.successor_fields) + ) + record = BaseWeightSupersessionAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + successor_base_weight_evidence_receipt_reference=( + None + if successor_values is None + else successor_values["successor_base_weight_evidence_receipt_reference"] + ), + successor_base_weight_evidence_receipt_digest=( + None + if successor_values is None + else successor_values["successor_base_weight_evidence_receipt_digest"] + ), + successor_evidence_version=( + None + if successor_values is None + else successor_values["successor_evidence_version"] + ), + successor_released_at=( + None if successor_values is None else successor_values["successor_released_at"] + ), + **dict(persisted.fields), + ) + record_values = dict(record.fields) + if ( + _store_operational_uuid("record tenant_record_id", record.tenant_record_id) + != _store_operational_uuid("requested tenant_record_id", tenant_id) + or _store_operational_uuid("record validity_study_id", record.validity_study_id) + != _store_operational_uuid("requested validity_study_id", study_id) + or record_values["base_weight_evidence_receipt_reference"] != receipt_ref + or record_values["base_weight_evidence_receipt_digest"] != receipt_digest + or record_values["evidence_version"] != version + or record_values["owner_contract_reference"] != owner_ref + or record_values["owner_contract_version"] != owner_version + or record_values["owner_contract_digest"] != owner_digest + ): + raise BaseWeightSupersessionAuthorityIntegrityError( + "released base-weight supersession authority does not match requested coordinates" + ) + if use_instant < record.released_at: + raise BaseWeightSupersessionAuthorityIntegrityError( + "base-weight receipt must be released before scientific use" + ) + if record.superseded_at is not None and use_instant >= record.superseded_at: + raise BaseWeightSupersessionAuthorityIntegrityError( + "base-weight receipt is superseded for this scientific-use instant" + ) + + fields = record.fields + ( + ("released_at", record.released_at), + ("superseded_at", record.superseded_at), + ) + return tuple.__new__( + BaseWeightSupersessionAuthorityView, + ( + _store_operational_uuid("tenant_record_id", record.tenant_record_id), + _store_operational_uuid("validity_study_id", record.validity_study_id), + fields, + ), + ) + + +__all__ = [ + "BaseWeightSupersessionAuthorityIntegrityError", + "BaseWeightSupersessionAuthorityNotFound", + "BaseWeightSupersessionAuthorityReadPort", + "BaseWeightSupersessionAuthorityRecord", + "BaseWeightSupersessionAuthorityView", + "resolve_base_weight_supersession_authority", +] From 8561122832a2143994e4e44e2c0240aefcd9fce4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 12:34:58 +0900 Subject: [PATCH 275/603] feat(workforce-validation): export base-weight supersession authority --- .../orgmetra_workforce_validation_api/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index 6ec7bb04d..7d5ecd8f5 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -8,6 +8,14 @@ BaseWeightAuthorityView, resolve_base_weight_authority, ) +from orgmetra_workforce_validation_api.base_weight_supersession_authority import ( + BaseWeightSupersessionAuthorityIntegrityError, + BaseWeightSupersessionAuthorityNotFound, + BaseWeightSupersessionAuthorityReadPort, + BaseWeightSupersessionAuthorityRecord, + BaseWeightSupersessionAuthorityView, + resolve_base_weight_supersession_authority, +) from orgmetra_workforce_validation_api.benchmark_authority import ( CalibrationBenchmarkAuthorityIntegrityError, CalibrationBenchmarkAuthorityNotFound, @@ -153,6 +161,11 @@ "BaseWeightAuthorityReadPort", "BaseWeightAuthorityRecord", "BaseWeightAuthorityView", + "BaseWeightSupersessionAuthorityIntegrityError", + "BaseWeightSupersessionAuthorityNotFound", + "BaseWeightSupersessionAuthorityReadPort", + "BaseWeightSupersessionAuthorityRecord", + "BaseWeightSupersessionAuthorityView", "CalibrationAdjustmentAuthorityIntegrityError", "CalibrationAdjustmentAuthorityNotFound", "CalibrationAdjustmentAuthorityReadPort", @@ -242,6 +255,7 @@ "WeightVarianceAuthorityView", "read_validity_study", "resolve_base_weight_authority", + "resolve_base_weight_supersession_authority", "resolve_calibration_adjustment_authority", "resolve_calibration_adjustment_supersession_authority", "resolve_calibration_auxiliary_authority", From 0d067ac5a16cd88996039b6df67564651b933d86 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 12:35:37 +0900 Subject: [PATCH 276/603] test(workforce-validation): harden base-weight supersession edges --- .../tests/test_base_weight_supersession_authority.py | 1 - 1 file changed, 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_base_weight_supersession_authority.py b/services/workforce-validation-api/tests/test_base_weight_supersession_authority.py index 7512079bf..f33187563 100644 --- a/services/workforce-validation-api/tests/test_base_weight_supersession_authority.py +++ b/services/workforce-validation-api/tests/test_base_weight_supersession_authority.py @@ -223,7 +223,6 @@ def test_missing_noncanonical_and_pre_release_evidence_fail_closed() -> None: {"validity_study_id": OTHER_STUDY}, {"base_weight_evidence_receipt_reference": SUCCESSOR}, {"base_weight_evidence_receipt_digest": "4" * 64}, - {"evidence_version": 2}, {"owner_contract_reference": "released_owner_contract:44444444-4444-4444-8444-444444444444"}, {"owner_contract_version": 2}, {"owner_contract_digest": "5" * 64}, From b54db3b2ac29266b89bfde615c35547616107b77 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 12:36:23 +0900 Subject: [PATCH 277/603] docs(workforce-validation): document base-weight correction authority --- services/workforce-validation-api/README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 9f41461be..d1e556cbc 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -74,7 +74,11 @@ The governing owner-contract release instant and optional exclusive trimming/bou `resolve_base_weight_authority(...)` corroborates the base/design-weight derivation instead of accepting `base_weight_evidence_digest` as an opaque caller label. It binds an exact released base-weight evidence receipt to source-universe and sampling-design receipt references/versions/digests, their release chronology, the sampled occurrence set, stage-wise selection-probability evidence digest and stage count, base-weight method/version, resulting artifact, construction time, and released owner contract. -Stage-wise probability values stay with the sampling owner. Source-universe, sampling-design and owner-contract release instants are owner-resolved evidence rather than caller coordinates. Source and sampling evidence must already be released when the base weight is constructed; the owner contract must be released no later than the base-weight evidence receipt. The owner read is keyed by the complete caller-known reproducibility tuple rather than a partial receipt/source/design prefix. +Stage-wise probability values stay with the sampling owner. Source-universe, sampling-design and owner-contract release instants are owner-resolved evidence rather than caller coordinates. Source and sampling evidence must already be released when the base weight is constructed; the owner contract must be released no later than the base-weight evidence receipt. The owner read is keyed by the complete caller-known reproducibility tuple rather than a partial receipt/source/design prefix. The ordinary record also carries an owner-resolved optional `superseded_at` and scientific use is valid only on `[released_at, superseded_at)`. + +## Base/design-weight supersession authority + +`resolve_base_weight_supersession_authority(...)` proves the append-only correction edge behind base/design-weight currentness. A corrected predecessor requires one complete successor base-weight evidence receipt reference/digest/evidence-version/release tuple. The successor must identify new immutable receipt evidence, stay on the governed v1 contract, be released after its predecessor, and satisfy `successor_released_at == superseded_at`. Successor coordinates are owner-resolved and omitted from the minimized current-receipt view. Durable persistence must cross-check the ordinary base-weight projection's cutover and this explicit successor edge at one atomic correction instant. ## Final analysis-weight authority @@ -112,9 +116,9 @@ The immutable `verification_attempt_reference` and `verification_attempt_digest` The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **seventeen** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, complete final analysis-weight lineage, final-weight supersession, point-weight/variance compatibility, validation-result binding, validation-result supersession, and validation-result non-verifiability. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **eighteen** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, base/design-weight supersession, complete final analysis-weight lineage, final-weight supersession, point-weight/variance compatibility, validation-result binding, validation-result supersession, and validation-result non-verifiability. -The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration, eligibility, nonresponse and trimming/bounding ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable verification-attempt reference/digest and preserve failed-evidence and attempt-release chronology. No durable adapter may infer currentness from mutable current rows or caller-supplied timestamps. +The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration, eligibility, nonresponse, trimming/bounding and base-weight ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable verification-attempt reference/digest and preserve failed-evidence and attempt-release chronology. No durable adapter may infer currentness from mutable current rows or caller-supplied timestamps. ## Test contract @@ -129,6 +133,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, **typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover**, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity and chronology. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity and chronology. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From da6a2b6fbab96286bbcd8cfcf6f9b45596ae3ff5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 12:39:45 +0900 Subject: [PATCH 278/603] test(workforce-validation): establish weight-variance supersession RED --- ..._weight_variance_supersession_authority.py | 283 ++++++++++++++++++ 1 file changed, 283 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_variance_supersession_authority.py diff --git a/services/workforce-validation-api/tests/test_weight_variance_supersession_authority.py b/services/workforce-validation-api/tests/test_weight_variance_supersession_authority.py new file mode 100644 index 000000000..8aa9758df --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_variance_supersession_authority.py @@ -0,0 +1,283 @@ +"""Append-only correction contract for point-weight/variance compatibility authority.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.weight_variance_supersession_authority import ( + WeightVarianceSupersessionAuthorityIntegrityError, + WeightVarianceSupersessionAuthorityNotFound, + WeightVarianceSupersessionAuthorityReadPort, + WeightVarianceSupersessionAuthorityRecord, + WeightVarianceSupersessionAuthorityView, + resolve_weight_variance_supersession_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000d2") +AUTHORITY = "variance_compatibility_authority:11111111-1111-4111-8111-111111111111" +SUCCESSOR = "variance_compatibility_authority:22222222-2222-4222-8222-222222222222" +OWNER = "released_owner_contract:33333333-3333-4333-8333-333333333333" +OWNER_DIGEST = "3" * 64 +OWNER_RELEASED = datetime(2026, 9, 17, 0, 30, tzinfo=timezone.utc) +RELEASED = datetime(2026, 9, 17, 1, 0, tzinfo=timezone.utc) +CUTOVER = datetime(2026, 9, 18, 1, 0, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "authority_reference", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_authority_reference", + "successor_evidence_version", + "successor_released_at", + } +) + + +class _ReadPort: + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[dict[str, object]] = [] + + def read_weight_variance_supersession_authority(self, **coordinates: object) -> object: + self.calls.append(dict(coordinates)) + return self.result + + +class _ProtocolOnly(WeightVarianceSupersessionAuthorityReadPort): + pass + + +class _DescriptorReadPort: + @property + def read_weight_variance_supersession_authority(self) -> object: + raise AssertionError("descriptor must not execute") + + +class _NoReadMethod: + pass + + +def _principal() -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="weight-variance-supersession-read-v1", + resource_kind="weight_variance_supersession_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record(**overrides: object) -> WeightVarianceSupersessionAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "authority_reference": AUTHORITY, + "evidence_version": 1, + "owner_contract_reference": OWNER, + "owner_contract_version": 1, + "owner_contract_digest": OWNER_DIGEST, + "owner_contract_released_at": OWNER_RELEASED, + "released_at": RELEASED, + "superseded_at": CUTOVER, + "successor_authority_reference": SUCCESSOR, + "successor_evidence_version": 1, + "successor_released_at": CUTOVER, + } + values.update(overrides) + return WeightVarianceSupersessionAuthorityRecord(**values) + + +def _resolve(*, read_port: object, used_at: datetime, **overrides: object): + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "authority_reference": AUTHORITY, + "evidence_version": 1, + "owner_contract_reference": OWNER, + "owner_contract_version": 1, + "owner_contract_digest": OWNER_DIGEST, + "used_at": used_at, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_weight_variance_supersession_authority(**values) + + +def test_successor_edge_requires_complete_atomic_released_coordinates() -> None: + with pytest.raises(ValueError, match="complete released successor coordinates"): + _record(successor_released_at=None) + with pytest.raises(ValueError, match="later than compatibility authority release"): + _record(superseded_at=RELEASED) + with pytest.raises(ValueError, match="new reference"): + _record(successor_authority_reference=AUTHORITY) + with pytest.raises(ValueError, match="successor_evidence_version must remain 1"): + _record(successor_evidence_version=2) + with pytest.raises(ValueError, match="released after its predecessor"): + _record(superseded_at=RELEASED + timedelta(seconds=1), successor_released_at=RELEASED) + with pytest.raises(ValueError, match="exactly at supersession"): + _record(successor_released_at=CUTOVER - timedelta(seconds=1)) + with pytest.raises(ValueError, match="exactly at supersession"): + _record(successor_released_at=CUTOVER + timedelta(seconds=1)) + + +def test_chronology_requires_released_owner_and_timezone_aware_instants() -> None: + with pytest.raises(ValueError, match="owner contract"): + _record(owner_contract_released_at=RELEASED + timedelta(seconds=1)) + with pytest.raises(ValueError): + _record(owner_contract_released_at=datetime(2026, 9, 17, 0, 30)) + with pytest.raises(ValueError): + _record(released_at=datetime(2026, 9, 17, 1, 0)) + with pytest.raises(ValueError): + _record(superseded_at=datetime(2026, 9, 18, 1, 0)) + with pytest.raises(ValueError): + _record(successor_released_at=datetime(2026, 9, 18, 1, 0)) + + +def test_historical_use_is_allowed_but_cutover_use_fails_closed() -> None: + record = _record() + port = _ReadPort(record) + view = _resolve(read_port=port, used_at=CUTOVER - timedelta(microseconds=1)) + + assert isinstance(port, WeightVarianceSupersessionAuthorityReadPort) + assert port.calls == [ + { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "authority_reference": AUTHORITY, + "evidence_version": 1, + "owner_contract_reference": OWNER, + "owner_contract_version": 1, + "owner_contract_digest": OWNER_DIGEST, + } + ] + assert ("authority_reference", AUTHORITY) in view.fields + assert ("released_at", RELEASED) in view.fields + assert ("superseded_at", CUTOVER) in view.fields + assert all(not name.startswith("successor_") for name, _ in view.fields) + + with pytest.raises(WeightVarianceSupersessionAuthorityIntegrityError, match="superseded"): + _resolve(read_port=_ReadPort(record), used_at=CUTOVER) + + +def test_open_interval_without_successor_remains_current() -> None: + record = _record( + superseded_at=None, + successor_authority_reference=None, + successor_evidence_version=None, + successor_released_at=None, + ) + view = _resolve(read_port=_ReadPort(record), used_at=CUTOVER + timedelta(days=30)) + assert ("superseded_at", None) in view.fields + + +def test_missing_noncanonical_and_pre_release_evidence_fail_closed() -> None: + with pytest.raises(WeightVarianceSupersessionAuthorityNotFound): + _resolve(read_port=_ReadPort(None), used_at=RELEASED) + with pytest.raises(WeightVarianceSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object()), used_at=RELEASED) + with pytest.raises(WeightVarianceSupersessionAuthorityIntegrityError, match="released before scientific use"): + _resolve(read_port=_ReadPort(_record()), used_at=RELEASED - timedelta(seconds=1)) + + +@pytest.mark.parametrize( + "record_overrides", + [ + {"tenant_record_id": OTHER_TENANT}, + {"validity_study_id": OTHER_STUDY}, + {"authority_reference": SUCCESSOR}, + {"owner_contract_reference": "released_owner_contract:44444444-4444-4444-8444-444444444444"}, + {"owner_contract_version": 2}, + {"owner_contract_digest": "5" * 64}, + ], +) +def test_owner_evidence_must_match_every_requested_coordinate(record_overrides: dict[str, object]) -> None: + with pytest.raises(WeightVarianceSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(**record_overrides)), used_at=RELEASED) + + +def test_authorization_denial_precedes_owner_read() -> None: + port = _ReadPort(_record()) + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, used_at=RELEASED, policy=_policy(purpose_code="audit_review")) + assert port.calls == [] + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("authority_reference", "wrong:authority", ValueError), + ("evidence_version", 2, ValueError), + ("owner_contract_reference", "wrong:contract", ValueError), + ("owner_contract_version", 0, ValueError), + ("owner_contract_digest", "3" * 63, ValueError), + ("used_at", datetime(2026, 9, 18, 0, 30), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_or_dependency_fails_before_owner_resolution( + key: str, value: object, error: type[Exception] +) -> None: + port: object = _ReadPort(_record()) + overrides = {key: value} + if key == "read_port": + port = value + overrides = {} + with pytest.raises(error): + _resolve(read_port=port, used_at=RELEASED, **overrides) + if isinstance(port, _ReadPort): + assert port.calls == [] + + +def test_record_and_view_are_immutable_and_uuid_views_detached() -> None: + tenant = UUID(str(TENANT)) + record = _record(tenant_record_id=tenant) + object.__setattr__(tenant, "int", OTHER_TENANT.int) + assert record.tenant_record_id == TENANT + + with pytest.raises(AttributeError): + object.__setattr__(record, "released_at", CUTOVER) + + view = _resolve(read_port=_ReadPort(record), used_at=RELEASED) + returned_tenant = view.tenant_record_id + object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) + assert view.tenant_record_id == TENANT + + with pytest.raises(TypeError): + WeightVarianceSupersessionAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) From a9f7ed4aa8d29b3a31965e1c96f09fd8fe37400c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 12:40:32 +0900 Subject: [PATCH 279/603] feat(workforce-validation): add weight-variance supersession authority --- .../weight_variance_supersession_authority.py | 434 ++++++++++++++++++ 1 file changed, 434 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_variance_supersession_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_variance_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_variance_supersession_authority.py new file mode 100644 index 000000000..3addf3c22 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_variance_supersession_authority.py @@ -0,0 +1,434 @@ +"""Corroborate append-only point-weight/variance compatibility corrections. + +The ordinary compatibility projection proves which released sampling, point-weight, +and variance-design coordinates were used together. This boundary proves the +half-open authority interval for that immutable compatibility identity and, when +corrected, the exact released successor identity that ends the interval. +Successor chronology is owner-resolved rather than caller-selected. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + +_RESOURCE_KIND = "weight_variance_supersession_authority" +_OPERATION = "read" +_READ_FIELDS = frozenset( + { + "authority_reference", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_authority_reference", + "successor_evidence_version", + "successor_released_at", + } +) + + +class WeightVarianceSupersessionAuthorityNotFound(LookupError): + """Indicate that no released owner evidence corroborates the compatibility authority.""" + + +class WeightVarianceSupersessionAuthorityIntegrityError(RuntimeError): + """Indicate that released compatibility correction evidence cannot authorize use.""" + + +class WeightVarianceSupersessionAuthorityRecord(tuple): + """Immutable owner projection for one compatibility-authority interval.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + authority_reference: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + owner_contract_released_at: datetime, + released_at: datetime, + superseded_at: datetime | None = None, + successor_authority_reference: str | None = None, + successor_evidence_version: int | None = None, + successor_released_at: datetime | None = None, + ) -> WeightVarianceSupersessionAuthorityRecord: + """Validate one released predecessor and its optional atomic successor edge.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + authority_ref = _require_reference( + "authority_reference", authority_reference, "variance_compatibility_authority" + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + owner_release = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) + release_instant = _require_aware_datetime("released_at", released_at) + if owner_release > release_instant: + raise ValueError( + "owner contract must be released no later than compatibility authority release." + ) + + successor_values = ( + superseded_at, + successor_authority_reference, + successor_evidence_version, + successor_released_at, + ) + if all(value is None for value in successor_values): + cutover = None + successor_ref = None + successor_version = None + successor_release = None + elif any(value is None for value in successor_values): + raise ValueError( + "weight/variance supersession requires cutover and complete released successor coordinates." + ) + else: + cutover = _require_aware_datetime("superseded_at", superseded_at) + successor_ref = _require_reference( + "successor_authority_reference", + successor_authority_reference, + "variance_compatibility_authority", + ) + successor_version = _require_positive_integer( + "successor_evidence_version", successor_evidence_version + ) + successor_release = _require_aware_datetime( + "successor_released_at", successor_released_at + ) + if cutover <= release_instant: + raise ValueError( + "superseded_at must be later than compatibility authority release." + ) + if successor_ref == authority_ref: + raise ValueError("successor compatibility authority must have a new reference.") + if successor_version != 1: + raise ValueError("successor_evidence_version must remain 1.") + if successor_release <= release_instant: + raise ValueError( + "successor compatibility authority must be released after its predecessor." + ) + if successor_release != cutover: + raise ValueError( + "successor compatibility authority must be released exactly at supersession." + ) + + current_fields: tuple[tuple[str, object], ...] = ( + ("authority_reference", authority_ref), + ("evidence_version", version), + ("owner_contract_digest", owner_digest), + ("owner_contract_reference", owner_ref), + ("owner_contract_released_at", owner_release), + ("owner_contract_version", owner_version), + ) + successor_fields: tuple[tuple[str, object], ...] | None + if cutover is None: + successor_fields = None + else: + successor_fields = ( + ("successor_authority_reference", successor_ref), + ("successor_evidence_version", successor_version), + ("successor_released_at", successor_release), + ) + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + current_fields, + release_instant, + cutover, + successor_fields, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable current-authority coordinates.""" + return self[2] + + @property + def released_at(self) -> datetime: + """Return when this compatibility authority became released.""" + return self[3] + + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive end of this authority interval.""" + return self[4] + + @property + def successor_fields(self) -> tuple[tuple[str, object], ...] | None: + """Return internal released successor coordinates, if any.""" + return self[5] + + +class WeightVarianceSupersessionAuthorityView(tuple): + """Minimized current compatibility authority issued after authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> WeightVarianceSupersessionAuthorityView: + """Reject public construction; only the resolver may issue this view.""" + raise TypeError( + "WeightVarianceSupersessionAuthorityView is issued only by " + "resolve_weight_variance_supersession_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return current authority without successor disclosure.""" + return self[2] + + +@runtime_checkable +class WeightVarianceSupersessionAuthorityReadPort(Protocol): + """Owner read contract for one released compatibility correction state.""" + + def read_weight_variance_supersession_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + authority_reference: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> WeightVarianceSupersessionAuthorityRecord | None: + """Return matching released compatibility supersession evidence or ``None``.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + WeightVarianceSupersessionAuthorityReadPort, + "read_weight_variance_supersession_authority", +) + + +def resolve_weight_variance_supersession_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + authority_reference: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: WeightVarianceSupersessionAuthorityReadPort, +) -> WeightVarianceSupersessionAuthorityView: + """Authorize then resolve the compatibility authority's append-only interval.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static( + type(read_port), "read_weight_variance_supersession_authority", None + ) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError( + "read_port must expose a statically callable read_weight_variance_supersession_authority." + ) + + tenant_id = _restore_operational_uuid( + "tenant_record_id", _store_operational_uuid("tenant_record_id", tenant_record_id) + ) + study_id = _restore_operational_uuid( + "validity_study_id", _store_operational_uuid("validity_study_id", validity_study_id) + ) + authority_ref = _require_reference( + "authority_reference", authority_reference, "variance_compatibility_authority" + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer("owner_contract_version", owner_contract_version) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=tenant_id, + validity_study_id=study_id, + authority_reference=authority_ref, + evidence_version=version, + owner_contract_reference=owner_ref, + owner_contract_version=owner_version, + owner_contract_digest=owner_digest, + ) + if persisted is None: + raise WeightVarianceSupersessionAuthorityNotFound(str(study_id)) + if type(persisted) is not WeightVarianceSupersessionAuthorityRecord: + raise WeightVarianceSupersessionAuthorityIntegrityError( + "owner port returned non-canonical weight/variance supersession evidence" + ) + + successor_values = ( + None if persisted.successor_fields is None else dict(persisted.successor_fields) + ) + record = WeightVarianceSupersessionAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + successor_authority_reference=( + None + if successor_values is None + else successor_values["successor_authority_reference"] + ), + successor_evidence_version=( + None + if successor_values is None + else successor_values["successor_evidence_version"] + ), + successor_released_at=( + None if successor_values is None else successor_values["successor_released_at"] + ), + **dict(persisted.fields), + ) + record_values = dict(record.fields) + if ( + _store_operational_uuid("record tenant_record_id", record.tenant_record_id) + != _store_operational_uuid("requested tenant_record_id", tenant_id) + or _store_operational_uuid("record validity_study_id", record.validity_study_id) + != _store_operational_uuid("requested validity_study_id", study_id) + or record_values["authority_reference"] != authority_ref + or record_values["evidence_version"] != version + or record_values["owner_contract_reference"] != owner_ref + or record_values["owner_contract_version"] != owner_version + or record_values["owner_contract_digest"] != owner_digest + ): + raise WeightVarianceSupersessionAuthorityIntegrityError( + "released weight/variance supersession authority does not match requested coordinates" + ) + if use_instant < record.released_at: + raise WeightVarianceSupersessionAuthorityIntegrityError( + "compatibility authority must be released before scientific use" + ) + if record.superseded_at is not None and use_instant >= record.superseded_at: + raise WeightVarianceSupersessionAuthorityIntegrityError( + "compatibility authority is superseded for this scientific-use instant" + ) + + fields = record.fields + ( + ("released_at", record.released_at), + ("superseded_at", record.superseded_at), + ) + return tuple.__new__( + WeightVarianceSupersessionAuthorityView, + ( + _store_operational_uuid("tenant_record_id", record.tenant_record_id), + _store_operational_uuid("validity_study_id", record.validity_study_id), + fields, + ), + ) + + +__all__ = [ + "WeightVarianceSupersessionAuthorityIntegrityError", + "WeightVarianceSupersessionAuthorityNotFound", + "WeightVarianceSupersessionAuthorityReadPort", + "WeightVarianceSupersessionAuthorityRecord", + "WeightVarianceSupersessionAuthorityView", + "resolve_weight_variance_supersession_authority", +] From b5a7aee40aef1ac35105692225a556742fbb4305 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 12:41:02 +0900 Subject: [PATCH 280/603] feat(workforce-validation): export weight-variance supersession authority --- .../orgmetra_workforce_validation_api/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index 7d5ecd8f5..deb61f76e 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -138,6 +138,14 @@ WeightVarianceAuthorityView, resolve_weight_variance_authority, ) +from orgmetra_workforce_validation_api.weight_variance_supersession_authority import ( + WeightVarianceSupersessionAuthorityIntegrityError, + WeightVarianceSupersessionAuthorityNotFound, + WeightVarianceSupersessionAuthorityReadPort, + WeightVarianceSupersessionAuthorityRecord, + WeightVarianceSupersessionAuthorityView, + resolve_weight_variance_supersession_authority, +) from orgmetra_workforce_validation_api.weight_eligibility_authority import ( WeightEligibilityAuthorityIntegrityError, WeightEligibilityAuthorityNotFound, @@ -253,6 +261,11 @@ "WeightVarianceAuthorityReadPort", "WeightVarianceAuthorityRecord", "WeightVarianceAuthorityView", + "WeightVarianceSupersessionAuthorityIntegrityError", + "WeightVarianceSupersessionAuthorityNotFound", + "WeightVarianceSupersessionAuthorityReadPort", + "WeightVarianceSupersessionAuthorityRecord", + "WeightVarianceSupersessionAuthorityView", "read_validity_study", "resolve_base_weight_authority", "resolve_base_weight_supersession_authority", @@ -272,4 +285,5 @@ "resolve_weight_eligibility_authority", "resolve_weight_eligibility_supersession_authority", "resolve_weight_variance_authority", + "resolve_weight_variance_supersession_authority", ] From e9c6244e0a8417138556ed2a45dfdbf9798bf121 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 12:41:49 +0900 Subject: [PATCH 281/603] docs(workforce-validation): document weight-variance correction authority --- services/workforce-validation-api/README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index d1e556cbc..2f08d1f00 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -96,6 +96,10 @@ The owner read is keyed by the complete caller-known reproducibility tuple. Owne The binding resolves owner-contract release and optional exclusive supersession from canonical owner evidence and enforces `[released_at, superseded_at)`. This prevents corrected point-weight or variance-design lineage from leaving an older compatibility binding apparently current. +## Point-weight / variance supersession authority + +`resolve_weight_variance_supersession_authority(...)` proves which immutable `variance_compatibility_authority` identity ended a predecessor binding. A correction requires a complete successor authority reference/evidence-version/release tuple; the successor must use a new authority reference on the governed v1 contract, be released after the predecessor, and satisfy `successor_released_at == superseded_at`. Successor coordinates remain owner-resolved and are omitted from the minimized view. Durable persistence must cross-check the ordinary compatibility projection's `superseded_at` against this explicit successor edge rather than manufacture currentness from a mutable row or caller timestamp. + ## Released validation-result authority `resolve_validation_result_authority(...)` binds one immutable validation result to the exact point-weight/variance compatibility receipt, final analysis-weight receipt, separate variance-design receipt, non-authorizing `verification_pending | not_verifiable` state, and released owner contract. Owner-contract release and optional exclusive cutover are canonical owner chronology. Historical reads before cutover remain reproducible; use at or after cutover fails closed. @@ -116,9 +120,9 @@ The immutable `verification_attempt_reference` and `verification_attempt_digest` The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **eighteen** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, base/design-weight supersession, complete final analysis-weight lineage, final-weight supersession, point-weight/variance compatibility, validation-result binding, validation-result supersession, and validation-result non-verifiability. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **nineteen** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, base/design-weight supersession, complete final analysis-weight lineage, final-weight supersession, point-weight/variance compatibility, point-weight/variance supersession, validation-result binding, validation-result supersession, and validation-result non-verifiability. -The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration, eligibility, nonresponse, trimming/bounding and base-weight ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable verification-attempt reference/digest and preserve failed-evidence and attempt-release chronology. No durable adapter may infer currentness from mutable current rows or caller-supplied timestamps. +The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable verification-attempt reference/digest and preserve failed-evidence and attempt-release chronology. No durable adapter may infer currentness from mutable current rows or caller-supplied timestamps. ## Test contract @@ -133,6 +137,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity and chronology. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity and chronology. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From 290ea0bff57a93522e6d4d706ae4a88b569a609b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 13:59:09 +0900 Subject: [PATCH 282/603] test(workforce-validation): expose retroactive auxiliary authorization gap --- ...iliary_authorization_receipt_chronology.py | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_auxiliary_authorization_receipt_chronology.py diff --git a/services/workforce-validation-api/tests/test_calibration_auxiliary_authorization_receipt_chronology.py b/services/workforce-validation-api/tests/test_calibration_auxiliary_authorization_receipt_chronology.py new file mode 100644 index 000000000..0b61f91f1 --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_auxiliary_authorization_receipt_chronology.py @@ -0,0 +1,93 @@ +"""Chronology contract for calibration auxiliary authorization receipts.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from inspect import signature +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.scientific_authority import ( + CalibrationAuxiliaryAuthorityRecord, + resolve_calibration_auxiliary_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000c1") +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 8, 30, tzinfo=timezone.utc) +AUTHORIZATION_RECEIPT_RELEASED_AT = datetime(2026, 8, 31, tzinfo=timezone.utc) +AUTHORIZED_FROM = datetime(2026, 9, 1, tzinfo=timezone.utc) +AUTHORIZED_TO = datetime(2026, 10, 1, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) + + +def _record(*, authorization_receipt_released_at: object) -> CalibrationAuxiliaryAuthorityRecord: + return CalibrationAuxiliaryAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + authority_reference=( + "scientific_auxiliary_authority:11111111-1111-4111-8111-111111111111" + ), + auxiliary_projection_reference=( + "calibration_auxiliary_projection:22222222-2222-4222-8222-222222222222" + ), + auxiliary_projection_version=4, + auxiliary_projection_digest="1" * 64, + scientific_purpose_reference=( + "scientific_data_use_purpose:33333333-3333-4333-8333-333333333333" + ), + scientific_purpose_digest="2" * 64, + owner_contract_reference=( + "released_owner_contract:44444444-4444-4444-8444-444444444444" + ), + owner_contract_version=7, + owner_contract_digest="3" * 64, + owner_contract_released_at=OWNER_CONTRACT_RELEASED_AT, + authorization_receipt_reference=( + "scientific_data_authorization:55555555-5555-4555-8555-555555555555" + ), + authorization_receipt_digest="4" * 64, + authorization_receipt_released_at=authorization_receipt_released_at, + scientific_use_receipt_reference=( + "scientific_use_receipt:66666666-6666-4666-8666-666666666666" + ), + scientific_use_receipt_digest="5" * 64, + scientific_use_at=USED_AT, + authorized_from=AUTHORIZED_FROM, + authorized_to=AUTHORIZED_TO, + ) + + +def test_authorization_receipt_release_is_owner_evidence_not_a_caller_coordinate() -> None: + assert "authorization_receipt_released_at" not in signature( + resolve_calibration_auxiliary_authority + ).parameters + + record = _record( + authorization_receipt_released_at=AUTHORIZATION_RECEIPT_RELEASED_AT + ) + assert ( + record.authorization_receipt_released_at + == AUTHORIZATION_RECEIPT_RELEASED_AT + ) + + +def test_authorization_receipt_cannot_retroactively_authorize_interval() -> None: + with pytest.raises(ValueError, match="authorization receipt must be released no later"): + _record( + authorization_receipt_released_at=AUTHORIZED_FROM + timedelta(seconds=1) + ) + + +def test_authorization_receipt_cannot_predate_governing_owner_contract() -> None: + with pytest.raises(ValueError, match="authorization receipt cannot predate owner contract"): + _record( + authorization_receipt_released_at=OWNER_CONTRACT_RELEASED_AT + - timedelta(seconds=1) + ) + + +def test_authorization_receipt_release_requires_timezone_aware_evidence() -> None: + with pytest.raises(ValueError): + _record(authorization_receipt_released_at=datetime(2026, 8, 31)) From bb8fccaa4f5d1d2f10190d94ee235329341e7b2e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 14:01:27 +0900 Subject: [PATCH 283/603] fix(workforce-validation): bind auxiliary authorization release chronology --- .../scientific_authority.py | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py index f0c52e881..09eb42dbb 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py @@ -49,6 +49,7 @@ "owner_contract_released_at", "authorization_receipt_reference", "authorization_receipt_digest", + "authorization_receipt_released_at", "scientific_use_receipt_reference", "scientific_use_receipt_digest", "scientific_use_at", @@ -119,6 +120,7 @@ def __new__( owner_contract_released_at: datetime, authorization_receipt_reference: str, authorization_receipt_digest: str, + authorization_receipt_released_at: datetime, scientific_use_receipt_reference: str, scientific_use_receipt_digest: str, scientific_use_at: datetime, @@ -166,6 +168,9 @@ def __new__( authorization_digest = _require_digest( "authorization_receipt_digest", authorization_receipt_digest ) + authorization_release = _require_aware_datetime( + "authorization_receipt_released_at", authorization_receipt_released_at + ) scientific_use_ref = _require_reference( "scientific_use_receipt_reference", scientific_use_receipt_reference, @@ -185,6 +190,14 @@ def __new__( raise ValueError( "owner contract must be released no later than authorized_from." ) + if authorization_release < owner_contract_release: + raise ValueError( + "authorization receipt cannot predate owner contract release." + ) + if authorization_release > authorization_start: + raise ValueError( + "authorization receipt must be released no later than authorized_from." + ) if authorization_end is not None and authorization_end <= authorization_start: raise ValueError("authorized_to must be later than authorized_from.") if use_instant < authorization_start or ( @@ -210,6 +223,7 @@ def __new__( owner_contract_release, authorization_ref, authorization_digest, + authorization_release, scientific_use_ref, scientific_use_digest, use_instant, @@ -288,30 +302,35 @@ def authorization_receipt_digest(self) -> str: """Return the authorization receipt digest used for exact correlation.""" return self[13] + @property + def authorization_receipt_released_at(self) -> datetime: + """Return the owner-resolved release instant of the authorization receipt.""" + return self[14] + @property def scientific_use_receipt_reference(self) -> str: """Return the immutable scientific-use receipt reference.""" - return self[14] + return self[15] @property def scientific_use_receipt_digest(self) -> str: """Return the immutable scientific-use receipt digest.""" - return self[15] + return self[16] @property def scientific_use_at(self) -> datetime: """Return the owner-resolved UTC instant for the exact scientific use.""" - return self[16] + return self[17] @property def authorized_from(self) -> datetime: """Return the UTC instant when this scientific use became authorized.""" - return self[17] + return self[18] @property def authorized_to(self) -> datetime | None: """Return the exclusive UTC authorization end when one exists.""" - return self[18] + return self[19] class CalibrationAuxiliaryAuthorityView(tuple): @@ -409,8 +428,9 @@ def resolve_calibration_auxiliary_authority( same function is invoked afterward. The request carries no protected source values. Owner evidence must reproduce every caller-supplied leaf coordinate, including the projection reference/version/digest, receipt references and the - released owner-contract digest. The owner contract release instant is resolved - only from owner evidence and must not postdate the authorization interval start. + released owner-contract digest. Owner evidence must also prove that both the + governing contract and authorization receipt existed before the authorization + interval became effective; neither release instant is a caller coordinate. The scientific-use receipt is independently bound to the same use instant before any corroborating fields are returned. """ @@ -540,6 +560,7 @@ def resolve_calibration_auxiliary_authority( owner_contract_released_at=persisted.owner_contract_released_at, authorization_receipt_reference=persisted.authorization_receipt_reference, authorization_receipt_digest=persisted.authorization_receipt_digest, + authorization_receipt_released_at=persisted.authorization_receipt_released_at, scientific_use_receipt_reference=persisted.scientific_use_receipt_reference, scientific_use_receipt_digest=persisted.scientific_use_receipt_digest, scientific_use_at=persisted.scientific_use_at, @@ -583,6 +604,7 @@ def resolve_calibration_auxiliary_authority( "owner_contract_released_at": record.owner_contract_released_at, "authorization_receipt_reference": record.authorization_receipt_reference, "authorization_receipt_digest": record.authorization_receipt_digest, + "authorization_receipt_released_at": record.authorization_receipt_released_at, "scientific_use_receipt_reference": record.scientific_use_receipt_reference, "scientific_use_receipt_digest": record.scientific_use_receipt_digest, "scientific_use_at": record.scientific_use_at, From 8dc40f2a88ea1b87bef37b948075d62f58b86810 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 14:02:28 +0900 Subject: [PATCH 284/603] test(workforce-validation): align auxiliary authorization chronology fixtures --- .../tests/test_calibration_auxiliary_authority.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py index dbafd1b9b..df11b9ce2 100644 --- a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py +++ b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py @@ -47,6 +47,7 @@ AUTHORIZATION_DIGEST = "4" * 64 SCIENTIFIC_USE_DIGEST = "5" * 64 OWNER_CONTRACT_RELEASED_AT = datetime(2026, 8, 31, tzinfo=timezone.utc) +AUTHORIZATION_RECEIPT_RELEASED_AT = datetime(2026, 8, 31, 12, tzinfo=timezone.utc) AUTHORIZED_FROM = datetime(2026, 9, 1, tzinfo=timezone.utc) AUTHORIZED_TO = datetime(2026, 10, 1, tzinfo=timezone.utc) USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) @@ -64,6 +65,7 @@ "owner_contract_released_at", "authorization_receipt_reference", "authorization_receipt_digest", + "authorization_receipt_released_at", "scientific_use_receipt_reference", "scientific_use_receipt_digest", "scientific_use_at", @@ -174,6 +176,7 @@ def _record(**overrides: object) -> CalibrationAuxiliaryAuthorityRecord: "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, "authorization_receipt_reference": AUTHORIZATION_REFERENCE, "authorization_receipt_digest": AUTHORIZATION_DIGEST, + "authorization_receipt_released_at": AUTHORIZATION_RECEIPT_RELEASED_AT, "scientific_use_receipt_reference": SCIENTIFIC_USE_REFERENCE, "scientific_use_receipt_digest": SCIENTIFIC_USE_DIGEST, "scientific_use_at": USED_AT, @@ -242,6 +245,7 @@ def test_resolution_authorizes_then_returns_minimized_corroborated_evidence() -> ("authority_reference", AUTHORITY_REFERENCE), ("authorization_receipt_digest", AUTHORIZATION_DIGEST), ("authorization_receipt_reference", AUTHORIZATION_REFERENCE), + ("authorization_receipt_released_at", AUTHORIZATION_RECEIPT_RELEASED_AT), ("authorized_from", AUTHORIZED_FROM), ("authorized_to", AUTHORIZED_TO), ("auxiliary_projection_digest", PROJECTION_DIGEST), @@ -430,6 +434,7 @@ def test_invalid_request_or_dependency_fails_before_owner_resolution( ("owner_contract_released_at", datetime(2026, 8, 31)), ("authorization_receipt_reference", "wrong:authorization"), ("authorization_receipt_digest", "4" * 63), + ("authorization_receipt_released_at", datetime(2026, 8, 31)), ("scientific_use_receipt_reference", "wrong:use"), ("scientific_use_receipt_digest", "5" * 63), ("scientific_use_at", datetime(2026, 9, 17)), From b04370d6919c0b1567061fc15c120e9a66bf2f0c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 14:02:44 +0900 Subject: [PATCH 285/603] test(workforce-validation): keep auxiliary owner chronology fixtures current --- .../tests/test_calibration_auxiliary_authority_chronology.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority_chronology.py b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority_chronology.py index 3855910d9..d57fa72f0 100644 --- a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority_chronology.py +++ b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority_chronology.py @@ -19,6 +19,7 @@ AUTHORIZED_TO = datetime(2026, 10, 1, tzinfo=timezone.utc) USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) OWNER_CONTRACT_RELEASED_AT = AUTHORIZED_FROM - timedelta(days=1) +AUTHORIZATION_RECEIPT_RELEASED_AT = AUTHORIZED_FROM - timedelta(hours=12) def _record(*, owner_contract_released_at: object) -> CalibrationAuxiliaryAuthorityRecord: @@ -47,6 +48,7 @@ def _record(*, owner_contract_released_at: object) -> CalibrationAuxiliaryAuthor "scientific_data_authorization:55555555-5555-4555-8555-555555555555" ), authorization_receipt_digest="4" * 64, + authorization_receipt_released_at=AUTHORIZATION_RECEIPT_RELEASED_AT, scientific_use_receipt_reference=( "scientific_use_receipt:66666666-6666-4666-8666-666666666666" ), From 49c9d2048ac5ad358edafeb66c83205b7a0b73af Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 14:04:16 +0900 Subject: [PATCH 286/603] docs(workforce-validation): document authorization receipt chronology --- services/workforce-validation-api/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 2f08d1f00..c34be9440 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -22,9 +22,9 @@ Foreign domain truth crosses this boundary only through released/versioned contr ## Calibration auxiliary authority -`resolve_calibration_auxiliary_authority(...)` corroborates #407's purpose-limited calibration input without copying protected source attributes. It binds auxiliary authority and projection coordinates, scientific-use purpose, released owner contract, authorization receipt/interval, and scientific-use receipt/instant. The governing owner-contract release instant is owner-resolved evidence rather than a caller coordinate, must be timezone-aware, and must be no later than `authorized_from`; this prevents a later contract from retroactively creating an earlier scientific-use authorization interval. Caller `used_at` must equal the owner-resolved scientific-use instant, and that instant must fall inside the owner-resolved authorization interval. +`resolve_calibration_auxiliary_authority(...)` corroborates #407's purpose-limited calibration input without copying protected source attributes. It binds auxiliary authority and projection coordinates, scientific-use purpose, released owner contract, authorization receipt/interval, and scientific-use receipt/instant. The governing owner-contract release instant and authorization-receipt release instant are owner-resolved evidence rather than caller coordinates. Both must be timezone-aware; the owner contract may not be released after the authorization receipt, and the authorization receipt must already be released no later than `authorized_from`. This closes the retroactive-authority gap where an immutable authorization receipt created later could otherwise appear to authorize an earlier interval. Caller `used_at` must equal the owner-resolved scientific-use instant, and that instant must fall inside the owner-resolved authorization interval. -## Calibration benchmark authority +## calibration benchmark authority `resolve_calibration_benchmark_authority(...)` corroborates benchmark receipt/version/digest, released benchmark-owner contract, reference/release chronology, and append-only predecessor/successor correction lineage. The owner contract must already be released when the benchmark receipt becomes released evidence; a predecessor is authoritative only on its owner-resolved half-open interval `[released_at, superseded_at)`. When a successor exists, its released instant must equal the predecessor cutover exactly, so two released benchmark receipts cannot overlap in authority and no authority gap can appear between them. @@ -122,7 +122,7 @@ The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL r Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **nineteen** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, base/design-weight supersession, complete final analysis-weight lineage, final-weight supersession, point-weight/variance compatibility, point-weight/variance supersession, validation-result binding, validation-result supersession, and validation-result non-verifiability. -The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable verification-attempt reference/digest and preserve failed-evidence and attempt-release chronology. No durable adapter may infer currentness from mutable current rows or caller-supplied timestamps. +The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable verification-attempt reference/digest and preserve failed-evidence and attempt-release chronology. No durable adapter may infer currentness from mutable current rows or caller-supplied timestamps. ## Test contract @@ -137,6 +137,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity and chronology. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity and chronology. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From f4bcc09bc0945198cba80d6202cc52571ea71406 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 15:04:47 +0900 Subject: [PATCH 287/603] test(workforce-validation): require calibration support chronology authority --- .../test_calibration_support_authority.py | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_support_authority.py diff --git a/services/workforce-validation-api/tests/test_calibration_support_authority.py b/services/workforce-validation-api/tests/test_calibration_support_authority.py new file mode 100644 index 000000000..fd13b5c16 --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_support_authority.py @@ -0,0 +1,161 @@ +"""Regression contract for released calibration supporting-authority chronology.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from inspect import signature +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.calibration_support_authority import ( + CalibrationSupportAuthorityReadPort, + CalibrationSupportAuthorityRecord, + resolve_calibration_support_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f2") +AUX_OWNER_RELEASED_AT = datetime(2026, 9, 17, 7, 50, tzinfo=timezone.utc) +AUX_AUTH_RELEASED_AT = datetime(2026, 9, 17, 8, 0, tzinfo=timezone.utc) +AUX_AUTHORIZED_FROM = datetime(2026, 9, 17, 8, 10, tzinfo=timezone.utc) +AUX_USE_AT = datetime(2026, 9, 17, 8, 30, tzinfo=timezone.utc) +BENCHMARK_OWNER_RELEASED_AT = datetime(2026, 9, 17, 8, 0, tzinfo=timezone.utc) +BENCHMARK_RECEIPT_RELEASED_AT = datetime(2026, 9, 17, 8, 20, tzinfo=timezone.utc) +BENCHMARK_REFERENCE_AT = datetime(2026, 9, 17, 8, 15, tzinfo=timezone.utc) +CONSTRUCTED_AT = datetime(2026, 9, 17, 9, 0, tzinfo=timezone.utc) +OWNER_RELEASED_AT = datetime(2026, 9, 17, 9, 10, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 9, 20, tzinfo=timezone.utc) + + +def _record(**overrides: object) -> CalibrationSupportAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "support_authority_reference": ( + "calibration_support_authority:10101010-1010-4010-8010-101010101010" + ), + "support_authority_digest": "0" * 64, + "evidence_version": 1, + "calibration_receipt_reference": ( + "calibration_adjustment_receipt:11111111-1111-4111-8111-111111111111" + ), + "calibration_receipt_digest": "1" * 64, + "auxiliary_authority_reference": ( + "scientific_auxiliary_authority:22222222-2222-4222-8222-222222222222" + ), + "auxiliary_projection_reference": ( + "calibration_auxiliary_projection:33333333-3333-4333-8333-333333333333" + ), + "auxiliary_projection_version": 3, + "auxiliary_projection_digest": "2" * 64, + "auxiliary_purpose_reference": ( + "scientific_data_use_purpose:44444444-4444-4444-8444-444444444444" + ), + "auxiliary_purpose_digest": "3" * 64, + "auxiliary_owner_contract_reference": ( + "released_owner_contract:55555555-5555-4555-8555-555555555555" + ), + "auxiliary_owner_contract_version": 5, + "auxiliary_owner_contract_digest": "4" * 64, + "auxiliary_owner_contract_released_at": AUX_OWNER_RELEASED_AT, + "auxiliary_authorization_receipt_reference": ( + "scientific_data_authorization:66666666-6666-4666-8666-666666666666" + ), + "auxiliary_authorization_receipt_digest": "5" * 64, + "auxiliary_authorization_receipt_released_at": AUX_AUTH_RELEASED_AT, + "auxiliary_scientific_use_receipt_reference": ( + "scientific_use_receipt:77777777-7777-4777-8777-777777777777" + ), + "auxiliary_scientific_use_receipt_digest": "6" * 64, + "auxiliary_scientific_use_at": AUX_USE_AT, + "auxiliary_authorized_from": AUX_AUTHORIZED_FROM, + "auxiliary_authorized_to": datetime(2026, 10, 1, tzinfo=timezone.utc), + "benchmark_receipt_reference": ( + "calibration_benchmark_receipt:88888888-8888-4888-8888-888888888888" + ), + "benchmark_receipt_version": 8, + "benchmark_receipt_digest": "7" * 64, + "benchmark_owner_contract_reference": ( + "released_owner_contract:99999999-9999-4999-8999-999999999999" + ), + "benchmark_owner_contract_version": 9, + "benchmark_owner_contract_digest": "8" * 64, + "benchmark_owner_contract_released_at": BENCHMARK_OWNER_RELEASED_AT, + "benchmark_reference_at": BENCHMARK_REFERENCE_AT, + "benchmark_receipt_released_at": BENCHMARK_RECEIPT_RELEASED_AT, + "benchmark_receipt_superseded_at": None, + "constructed_at": CONSTRUCTED_AT, + "owner_contract_reference": ( + "released_owner_contract:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" + ), + "owner_contract_version": 10, + "owner_contract_digest": "9" * 64, + "owner_contract_released_at": OWNER_RELEASED_AT, + "released_at": RELEASED_AT, + } + values.update(overrides) + return CalibrationSupportAuthorityRecord(**values) # type: ignore[arg-type] + + +def test_support_chronology_is_owner_evidence_not_lookup_authority() -> None: + record = _record() + read_parameters = signature( + CalibrationSupportAuthorityReadPort.read_calibration_support_authority + ).parameters + resolver_parameters = signature(resolve_calibration_support_authority).parameters + + owner_resolved = { + "auxiliary_owner_contract_released_at", + "auxiliary_authorization_receipt_released_at", + "auxiliary_authorized_from", + "auxiliary_authorized_to", + "benchmark_owner_contract_released_at", + "benchmark_receipt_released_at", + "benchmark_receipt_superseded_at", + "owner_contract_released_at", + "released_at", + } + for field_name in owner_resolved: + assert hasattr(record, field_name) + assert field_name not in read_parameters + assert field_name not in resolver_parameters + + +def test_auxiliary_evidence_must_exist_before_the_committed_scientific_use() -> None: + with pytest.raises(ValueError, match="authorization receipt must be released no later"): + _record(auxiliary_authorization_receipt_released_at=AUX_USE_AT + timedelta(seconds=1)) + + with pytest.raises(ValueError, match="auxiliary owner contract cannot postdate authorization"): + _record(auxiliary_owner_contract_released_at=AUX_AUTH_RELEASED_AT + timedelta(seconds=1)) + + +def test_auxiliary_use_must_be_inside_owner_resolved_authorization_interval() -> None: + with pytest.raises(ValueError, match="auxiliary scientific use must fall inside"): + _record(auxiliary_authorized_from=AUX_USE_AT + timedelta(seconds=1)) + + with pytest.raises(ValueError, match="auxiliary scientific use must fall inside"): + _record(auxiliary_authorized_to=AUX_USE_AT) + + +def test_supporting_evidence_must_exist_before_calibration_construction() -> None: + with pytest.raises(ValueError, match="benchmark receipt must be released no later"): + _record(benchmark_receipt_released_at=CONSTRUCTED_AT + timedelta(seconds=1)) + + with pytest.raises(ValueError, match="auxiliary scientific use cannot be later"): + _record(auxiliary_scientific_use_at=CONSTRUCTED_AT + timedelta(seconds=1)) + + +def test_superseded_benchmark_cannot_support_later_calibration_construction() -> None: + with pytest.raises(ValueError, match="superseded benchmark cannot support calibration"): + _record(benchmark_receipt_superseded_at=CONSTRUCTED_AT) + + +def test_support_chronology_requires_timezone_aware_owner_evidence() -> None: + with pytest.raises(ValueError): + _record(benchmark_receipt_released_at=datetime(2026, 9, 17, 8, 20)) + + +def test_application_owner_contract_cannot_retroactively_authorize_support_binding() -> None: + with pytest.raises(ValueError, match="owner contract cannot be released after support evidence"): + _record(owner_contract_released_at=RELEASED_AT + timedelta(seconds=1)) From fb141a8df2a25acfa3483de85d619637c6d9d505 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 15:06:09 +0900 Subject: [PATCH 288/603] feat(workforce-validation): bind calibration support chronology --- .../calibration_support_authority.py | 778 ++++++++++++++++++ 1 file changed, 778 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py new file mode 100644 index 000000000..b2d051269 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py @@ -0,0 +1,778 @@ +"""Corroborate released auxiliary/benchmark chronology for one calibration receipt. + +The typed calibration receipt carries the identities of the auxiliary and benchmark +inputs used to construct weights. This boundary separately proves that those exact +supporting authorities were released and current when the calibration was +constructed. Owner-resolved release/cutover instants are evidence, never caller +lookup coordinates. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + +_RESOURCE_KIND = "calibration_support_authority" +_OPERATION = "read" +_READ_FIELDS = frozenset( + { + "support_authority_reference", + "support_authority_digest", + "evidence_version", + "calibration_receipt_reference", + "calibration_receipt_digest", + "auxiliary_authority_reference", + "auxiliary_projection_reference", + "auxiliary_projection_version", + "auxiliary_projection_digest", + "auxiliary_purpose_reference", + "auxiliary_purpose_digest", + "auxiliary_owner_contract_reference", + "auxiliary_owner_contract_version", + "auxiliary_owner_contract_digest", + "auxiliary_owner_contract_released_at", + "auxiliary_authorization_receipt_reference", + "auxiliary_authorization_receipt_digest", + "auxiliary_authorization_receipt_released_at", + "auxiliary_scientific_use_receipt_reference", + "auxiliary_scientific_use_receipt_digest", + "auxiliary_scientific_use_at", + "auxiliary_authorized_from", + "auxiliary_authorized_to", + "benchmark_receipt_reference", + "benchmark_receipt_version", + "benchmark_receipt_digest", + "benchmark_owner_contract_reference", + "benchmark_owner_contract_version", + "benchmark_owner_contract_digest", + "benchmark_owner_contract_released_at", + "benchmark_reference_at", + "benchmark_receipt_released_at", + "benchmark_receipt_superseded_at", + "constructed_at", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + } +) + + +class CalibrationSupportAuthorityNotFound(LookupError): + """Indicate that no released support binding matches the requested calibration.""" + + +class CalibrationSupportAuthorityIntegrityError(RuntimeError): + """Indicate that returned support evidence does not match the requested binding.""" + + +class CalibrationSupportAuthorityRecord(tuple): + """Immutable released proof that calibration support was valid at construction.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + support_authority_reference: str, + support_authority_digest: str, + evidence_version: int, + calibration_receipt_reference: str, + calibration_receipt_digest: str, + auxiliary_authority_reference: str, + auxiliary_projection_reference: str, + auxiliary_projection_version: int, + auxiliary_projection_digest: str, + auxiliary_purpose_reference: str, + auxiliary_purpose_digest: str, + auxiliary_owner_contract_reference: str, + auxiliary_owner_contract_version: int, + auxiliary_owner_contract_digest: str, + auxiliary_owner_contract_released_at: datetime, + auxiliary_authorization_receipt_reference: str, + auxiliary_authorization_receipt_digest: str, + auxiliary_authorization_receipt_released_at: datetime, + auxiliary_scientific_use_receipt_reference: str, + auxiliary_scientific_use_receipt_digest: str, + auxiliary_scientific_use_at: datetime, + auxiliary_authorized_from: datetime, + auxiliary_authorized_to: datetime | None, + benchmark_receipt_reference: str, + benchmark_receipt_version: int, + benchmark_receipt_digest: str, + benchmark_owner_contract_reference: str, + benchmark_owner_contract_version: int, + benchmark_owner_contract_digest: str, + benchmark_owner_contract_released_at: datetime, + benchmark_reference_at: datetime, + benchmark_receipt_released_at: datetime, + benchmark_receipt_superseded_at: datetime | None, + constructed_at: datetime, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + owner_contract_released_at: datetime, + released_at: datetime, + ) -> CalibrationSupportAuthorityRecord: + """Validate support identities and owner-resolved chronology before storage.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + support_ref = _require_reference( + "support_authority_reference", support_authority_reference, "calibration_support_authority" + ) + support_digest = _require_digest("support_authority_digest", support_authority_digest) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + calibration_ref = _require_reference( + "calibration_receipt_reference", + calibration_receipt_reference, + "calibration_adjustment_receipt", + ) + calibration_digest = _require_digest( + "calibration_receipt_digest", calibration_receipt_digest + ) + auxiliary_authority_ref = _require_reference( + "auxiliary_authority_reference", + auxiliary_authority_reference, + "scientific_auxiliary_authority", + ) + projection_ref = _require_reference( + "auxiliary_projection_reference", + auxiliary_projection_reference, + "calibration_auxiliary_projection", + ) + projection_version = _require_positive_integer( + "auxiliary_projection_version", auxiliary_projection_version + ) + projection_digest = _require_digest( + "auxiliary_projection_digest", auxiliary_projection_digest + ) + purpose_ref = _require_reference( + "auxiliary_purpose_reference", + auxiliary_purpose_reference, + "scientific_data_use_purpose", + ) + purpose_digest = _require_digest("auxiliary_purpose_digest", auxiliary_purpose_digest) + auxiliary_owner_ref = _require_reference( + "auxiliary_owner_contract_reference", + auxiliary_owner_contract_reference, + "released_owner_contract", + ) + auxiliary_owner_version = _require_positive_integer( + "auxiliary_owner_contract_version", auxiliary_owner_contract_version + ) + auxiliary_owner_digest = _require_digest( + "auxiliary_owner_contract_digest", auxiliary_owner_contract_digest + ) + auxiliary_owner_released = _require_aware_datetime( + "auxiliary_owner_contract_released_at", auxiliary_owner_contract_released_at + ) + authorization_ref = _require_reference( + "auxiliary_authorization_receipt_reference", + auxiliary_authorization_receipt_reference, + "scientific_data_authorization", + ) + authorization_digest = _require_digest( + "auxiliary_authorization_receipt_digest", auxiliary_authorization_receipt_digest + ) + authorization_released = _require_aware_datetime( + "auxiliary_authorization_receipt_released_at", + auxiliary_authorization_receipt_released_at, + ) + use_ref = _require_reference( + "auxiliary_scientific_use_receipt_reference", + auxiliary_scientific_use_receipt_reference, + "scientific_use_receipt", + ) + use_digest = _require_digest( + "auxiliary_scientific_use_receipt_digest", auxiliary_scientific_use_receipt_digest + ) + use_at = _require_aware_datetime( + "auxiliary_scientific_use_at", auxiliary_scientific_use_at + ) + authorized_from = _require_aware_datetime( + "auxiliary_authorized_from", auxiliary_authorized_from + ) + authorized_to = ( + None + if auxiliary_authorized_to is None + else _require_aware_datetime("auxiliary_authorized_to", auxiliary_authorized_to) + ) + if auxiliary_owner_released > authorization_released: + raise ValueError("auxiliary owner contract cannot postdate authorization receipt.") + if authorization_released > use_at: + raise ValueError( + "authorization receipt must be released no later than auxiliary scientific use." + ) + if authorized_to is not None and authorized_to <= authorized_from: + raise ValueError("auxiliary_authorized_to must be later than auxiliary_authorized_from.") + if use_at < authorized_from or (authorized_to is not None and use_at >= authorized_to): + raise ValueError("auxiliary scientific use must fall inside owner-resolved authorization interval.") + + benchmark_ref = _require_reference( + "benchmark_receipt_reference", + benchmark_receipt_reference, + "calibration_benchmark_receipt", + ) + benchmark_version = _require_positive_integer( + "benchmark_receipt_version", benchmark_receipt_version + ) + benchmark_digest = _require_digest("benchmark_receipt_digest", benchmark_receipt_digest) + benchmark_owner_ref = _require_reference( + "benchmark_owner_contract_reference", + benchmark_owner_contract_reference, + "released_owner_contract", + ) + benchmark_owner_version = _require_positive_integer( + "benchmark_owner_contract_version", benchmark_owner_contract_version + ) + benchmark_owner_digest = _require_digest( + "benchmark_owner_contract_digest", benchmark_owner_contract_digest + ) + benchmark_owner_released = _require_aware_datetime( + "benchmark_owner_contract_released_at", benchmark_owner_contract_released_at + ) + benchmark_reference = _require_aware_datetime( + "benchmark_reference_at", benchmark_reference_at + ) + benchmark_released = _require_aware_datetime( + "benchmark_receipt_released_at", benchmark_receipt_released_at + ) + benchmark_superseded = ( + None + if benchmark_receipt_superseded_at is None + else _require_aware_datetime( + "benchmark_receipt_superseded_at", benchmark_receipt_superseded_at + ) + ) + if benchmark_owner_released > benchmark_released: + raise ValueError("benchmark owner contract cannot postdate benchmark receipt release.") + if benchmark_superseded is not None and benchmark_superseded <= benchmark_released: + raise ValueError("benchmark supersession must be later than benchmark receipt release.") + + constructed = _require_aware_datetime("constructed_at", constructed_at) + if use_at > constructed: + raise ValueError("auxiliary scientific use cannot be later than calibration construction.") + if benchmark_reference > constructed: + raise ValueError("benchmark reference cannot be later than calibration construction.") + if benchmark_released > constructed: + raise ValueError("benchmark receipt must be released no later than calibration construction.") + if benchmark_superseded is not None and constructed >= benchmark_superseded: + raise ValueError("superseded benchmark cannot support calibration construction at or after cutover.") + + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer("owner_contract_version", owner_contract_version) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + owner_released = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) + released = _require_aware_datetime("released_at", released_at) + if owner_released > released: + raise ValueError("owner contract cannot be released after support evidence.") + if released < constructed: + raise ValueError("support evidence cannot be released before calibration construction.") + + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + support_ref, + support_digest, + version, + calibration_ref, + calibration_digest, + auxiliary_authority_ref, + projection_ref, + projection_version, + projection_digest, + purpose_ref, + purpose_digest, + auxiliary_owner_ref, + auxiliary_owner_version, + auxiliary_owner_digest, + auxiliary_owner_released, + authorization_ref, + authorization_digest, + authorization_released, + use_ref, + use_digest, + use_at, + authorized_from, + authorized_to, + benchmark_ref, + benchmark_version, + benchmark_digest, + benchmark_owner_ref, + benchmark_owner_version, + benchmark_owner_digest, + benchmark_owner_released, + benchmark_reference, + benchmark_released, + benchmark_superseded, + constructed, + owner_ref, + owner_version, + owner_digest, + owner_released, + released, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + return _restore_operational_uuid("validity_study_id", self[1]) + + support_authority_reference = property(lambda self: self[2]) + support_authority_digest = property(lambda self: self[3]) + evidence_version = property(lambda self: self[4]) + calibration_receipt_reference = property(lambda self: self[5]) + calibration_receipt_digest = property(lambda self: self[6]) + auxiliary_authority_reference = property(lambda self: self[7]) + auxiliary_projection_reference = property(lambda self: self[8]) + auxiliary_projection_version = property(lambda self: self[9]) + auxiliary_projection_digest = property(lambda self: self[10]) + auxiliary_purpose_reference = property(lambda self: self[11]) + auxiliary_purpose_digest = property(lambda self: self[12]) + auxiliary_owner_contract_reference = property(lambda self: self[13]) + auxiliary_owner_contract_version = property(lambda self: self[14]) + auxiliary_owner_contract_digest = property(lambda self: self[15]) + auxiliary_owner_contract_released_at = property(lambda self: self[16]) + auxiliary_authorization_receipt_reference = property(lambda self: self[17]) + auxiliary_authorization_receipt_digest = property(lambda self: self[18]) + auxiliary_authorization_receipt_released_at = property(lambda self: self[19]) + auxiliary_scientific_use_receipt_reference = property(lambda self: self[20]) + auxiliary_scientific_use_receipt_digest = property(lambda self: self[21]) + auxiliary_scientific_use_at = property(lambda self: self[22]) + auxiliary_authorized_from = property(lambda self: self[23]) + auxiliary_authorized_to = property(lambda self: self[24]) + benchmark_receipt_reference = property(lambda self: self[25]) + benchmark_receipt_version = property(lambda self: self[26]) + benchmark_receipt_digest = property(lambda self: self[27]) + benchmark_owner_contract_reference = property(lambda self: self[28]) + benchmark_owner_contract_version = property(lambda self: self[29]) + benchmark_owner_contract_digest = property(lambda self: self[30]) + benchmark_owner_contract_released_at = property(lambda self: self[31]) + benchmark_reference_at = property(lambda self: self[32]) + benchmark_receipt_released_at = property(lambda self: self[33]) + benchmark_receipt_superseded_at = property(lambda self: self[34]) + constructed_at = property(lambda self: self[35]) + owner_contract_reference = property(lambda self: self[36]) + owner_contract_version = property(lambda self: self[37]) + owner_contract_digest = property(lambda self: self[38]) + owner_contract_released_at = property(lambda self: self[39]) + released_at = property(lambda self: self[40]) + + +class CalibrationSupportAuthorityView(tuple): + """Field-minimized support evidence issued only after authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> CalibrationSupportAuthorityView: + raise TypeError( + "CalibrationSupportAuthorityView is issued only by resolve_calibration_support_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + return self[2] + + +@runtime_checkable +class CalibrationSupportAuthorityReadPort(Protocol): + """Owner read contract keyed only by caller-known immutable coordinates.""" + + def read_calibration_support_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + calibration_receipt_reference: str, + calibration_receipt_digest: str, + auxiliary_authority_reference: str, + auxiliary_projection_reference: str, + auxiliary_projection_version: int, + auxiliary_projection_digest: str, + auxiliary_purpose_reference: str, + auxiliary_purpose_digest: str, + auxiliary_owner_contract_reference: str, + auxiliary_owner_contract_version: int, + auxiliary_owner_contract_digest: str, + auxiliary_authorization_receipt_reference: str, + auxiliary_authorization_receipt_digest: str, + auxiliary_scientific_use_receipt_reference: str, + auxiliary_scientific_use_receipt_digest: str, + auxiliary_scientific_use_at: datetime, + benchmark_receipt_reference: str, + benchmark_receipt_version: int, + benchmark_receipt_digest: str, + benchmark_owner_contract_reference: str, + benchmark_owner_contract_version: int, + benchmark_owner_contract_digest: str, + benchmark_reference_at: datetime, + constructed_at: datetime, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> CalibrationSupportAuthorityRecord | None: + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + CalibrationSupportAuthorityReadPort, "read_calibration_support_authority" +) + + +def _caller_coordinates(record: CalibrationSupportAuthorityRecord) -> tuple[object, ...]: + """Return immutable caller-known coordinates, excluding owner chronology.""" + return ( + record.tenant_record_id, + record.validity_study_id, + record.calibration_receipt_reference, + record.calibration_receipt_digest, + record.auxiliary_authority_reference, + record.auxiliary_projection_reference, + record.auxiliary_projection_version, + record.auxiliary_projection_digest, + record.auxiliary_purpose_reference, + record.auxiliary_purpose_digest, + record.auxiliary_owner_contract_reference, + record.auxiliary_owner_contract_version, + record.auxiliary_owner_contract_digest, + record.auxiliary_authorization_receipt_reference, + record.auxiliary_authorization_receipt_digest, + record.auxiliary_scientific_use_receipt_reference, + record.auxiliary_scientific_use_receipt_digest, + record.auxiliary_scientific_use_at, + record.benchmark_receipt_reference, + record.benchmark_receipt_version, + record.benchmark_receipt_digest, + record.benchmark_owner_contract_reference, + record.benchmark_owner_contract_version, + record.benchmark_owner_contract_digest, + record.benchmark_reference_at, + record.constructed_at, + record.owner_contract_reference, + record.owner_contract_version, + record.owner_contract_digest, + ) + + +def resolve_calibration_support_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + calibration_receipt_reference: str, + calibration_receipt_digest: str, + auxiliary_authority_reference: str, + auxiliary_projection_reference: str, + auxiliary_projection_version: int, + auxiliary_projection_digest: str, + auxiliary_purpose_reference: str, + auxiliary_purpose_digest: str, + auxiliary_owner_contract_reference: str, + auxiliary_owner_contract_version: int, + auxiliary_owner_contract_digest: str, + auxiliary_authorization_receipt_reference: str, + auxiliary_authorization_receipt_digest: str, + auxiliary_scientific_use_receipt_reference: str, + auxiliary_scientific_use_receipt_digest: str, + auxiliary_scientific_use_at: datetime, + benchmark_receipt_reference: str, + benchmark_receipt_version: int, + benchmark_receipt_digest: str, + benchmark_owner_contract_reference: str, + benchmark_owner_contract_version: int, + benchmark_owner_contract_digest: str, + benchmark_reference_at: datetime, + constructed_at: datetime, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: CalibrationSupportAuthorityReadPort, +) -> CalibrationSupportAuthorityView: + """Authorize and resolve released support chronology for one calibration receipt.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static(type(read_port), "read_calibration_support_authority", None) + if type(read_capability) is not FunctionType or read_capability is _PROTOCOL_READ_CAPABILITY: + raise TypeError("read_port must expose a statically callable read_calibration_support_authority.") + + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + tenant_id = _restore_operational_uuid("tenant_record_id", tenant_identity) + study_id = _restore_operational_uuid("validity_study_id", study_identity) + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + detached_policy = _detach_policy(policy) + + # Validate every caller-known coordinate before invoking authorization or persistence. + calibration_ref = _require_reference( + "calibration_receipt_reference", calibration_receipt_reference, "calibration_adjustment_receipt" + ) + calibration_digest = _require_digest("calibration_receipt_digest", calibration_receipt_digest) + auxiliary_authority_ref = _require_reference( + "auxiliary_authority_reference", auxiliary_authority_reference, "scientific_auxiliary_authority" + ) + projection_ref = _require_reference( + "auxiliary_projection_reference", auxiliary_projection_reference, "calibration_auxiliary_projection" + ) + projection_version = _require_positive_integer("auxiliary_projection_version", auxiliary_projection_version) + projection_digest = _require_digest("auxiliary_projection_digest", auxiliary_projection_digest) + purpose_ref = _require_reference( + "auxiliary_purpose_reference", auxiliary_purpose_reference, "scientific_data_use_purpose" + ) + purpose_digest = _require_digest("auxiliary_purpose_digest", auxiliary_purpose_digest) + auxiliary_owner_ref = _require_reference( + "auxiliary_owner_contract_reference", auxiliary_owner_contract_reference, "released_owner_contract" + ) + auxiliary_owner_version = _require_positive_integer( + "auxiliary_owner_contract_version", auxiliary_owner_contract_version + ) + auxiliary_owner_digest = _require_digest( + "auxiliary_owner_contract_digest", auxiliary_owner_contract_digest + ) + authorization_ref = _require_reference( + "auxiliary_authorization_receipt_reference", + auxiliary_authorization_receipt_reference, + "scientific_data_authorization", + ) + authorization_digest = _require_digest( + "auxiliary_authorization_receipt_digest", auxiliary_authorization_receipt_digest + ) + scientific_use_ref = _require_reference( + "auxiliary_scientific_use_receipt_reference", + auxiliary_scientific_use_receipt_reference, + "scientific_use_receipt", + ) + scientific_use_digest = _require_digest( + "auxiliary_scientific_use_receipt_digest", auxiliary_scientific_use_receipt_digest + ) + scientific_use_at = _require_aware_datetime( + "auxiliary_scientific_use_at", auxiliary_scientific_use_at + ) + benchmark_ref = _require_reference( + "benchmark_receipt_reference", benchmark_receipt_reference, "calibration_benchmark_receipt" + ) + benchmark_version = _require_positive_integer("benchmark_receipt_version", benchmark_receipt_version) + benchmark_digest = _require_digest("benchmark_receipt_digest", benchmark_receipt_digest) + benchmark_owner_ref = _require_reference( + "benchmark_owner_contract_reference", benchmark_owner_contract_reference, "released_owner_contract" + ) + benchmark_owner_version = _require_positive_integer( + "benchmark_owner_contract_version", benchmark_owner_contract_version + ) + benchmark_owner_digest = _require_digest( + "benchmark_owner_contract_digest", benchmark_owner_contract_digest + ) + benchmark_reference = _require_aware_datetime("benchmark_reference_at", benchmark_reference_at) + constructed = _require_aware_datetime("constructed_at", constructed_at) + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer("owner_contract_version", owner_contract_version) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=tenant_id, + validity_study_id=study_id, + calibration_receipt_reference=calibration_ref, + calibration_receipt_digest=calibration_digest, + auxiliary_authority_reference=auxiliary_authority_ref, + auxiliary_projection_reference=projection_ref, + auxiliary_projection_version=projection_version, + auxiliary_projection_digest=projection_digest, + auxiliary_purpose_reference=purpose_ref, + auxiliary_purpose_digest=purpose_digest, + auxiliary_owner_contract_reference=auxiliary_owner_ref, + auxiliary_owner_contract_version=auxiliary_owner_version, + auxiliary_owner_contract_digest=auxiliary_owner_digest, + auxiliary_authorization_receipt_reference=authorization_ref, + auxiliary_authorization_receipt_digest=authorization_digest, + auxiliary_scientific_use_receipt_reference=scientific_use_ref, + auxiliary_scientific_use_receipt_digest=scientific_use_digest, + auxiliary_scientific_use_at=scientific_use_at, + benchmark_receipt_reference=benchmark_ref, + benchmark_receipt_version=benchmark_version, + benchmark_receipt_digest=benchmark_digest, + benchmark_owner_contract_reference=benchmark_owner_ref, + benchmark_owner_contract_version=benchmark_owner_version, + benchmark_owner_contract_digest=benchmark_owner_digest, + benchmark_reference_at=benchmark_reference, + constructed_at=constructed, + owner_contract_reference=owner_ref, + owner_contract_version=owner_version, + owner_contract_digest=owner_digest, + ) + if persisted is None: + raise CalibrationSupportAuthorityNotFound(str(study_id)) + if type(persisted) is not CalibrationSupportAuthorityRecord: + raise CalibrationSupportAuthorityIntegrityError( + "owner port returned non-canonical calibration support authority evidence" + ) + + record = CalibrationSupportAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + support_authority_reference=persisted.support_authority_reference, + support_authority_digest=persisted.support_authority_digest, + evidence_version=persisted.evidence_version, + calibration_receipt_reference=persisted.calibration_receipt_reference, + calibration_receipt_digest=persisted.calibration_receipt_digest, + auxiliary_authority_reference=persisted.auxiliary_authority_reference, + auxiliary_projection_reference=persisted.auxiliary_projection_reference, + auxiliary_projection_version=persisted.auxiliary_projection_version, + auxiliary_projection_digest=persisted.auxiliary_projection_digest, + auxiliary_purpose_reference=persisted.auxiliary_purpose_reference, + auxiliary_purpose_digest=persisted.auxiliary_purpose_digest, + auxiliary_owner_contract_reference=persisted.auxiliary_owner_contract_reference, + auxiliary_owner_contract_version=persisted.auxiliary_owner_contract_version, + auxiliary_owner_contract_digest=persisted.auxiliary_owner_contract_digest, + auxiliary_owner_contract_released_at=persisted.auxiliary_owner_contract_released_at, + auxiliary_authorization_receipt_reference=persisted.auxiliary_authorization_receipt_reference, + auxiliary_authorization_receipt_digest=persisted.auxiliary_authorization_receipt_digest, + auxiliary_authorization_receipt_released_at=persisted.auxiliary_authorization_receipt_released_at, + auxiliary_scientific_use_receipt_reference=persisted.auxiliary_scientific_use_receipt_reference, + auxiliary_scientific_use_receipt_digest=persisted.auxiliary_scientific_use_receipt_digest, + auxiliary_scientific_use_at=persisted.auxiliary_scientific_use_at, + auxiliary_authorized_from=persisted.auxiliary_authorized_from, + auxiliary_authorized_to=persisted.auxiliary_authorized_to, + benchmark_receipt_reference=persisted.benchmark_receipt_reference, + benchmark_receipt_version=persisted.benchmark_receipt_version, + benchmark_receipt_digest=persisted.benchmark_receipt_digest, + benchmark_owner_contract_reference=persisted.benchmark_owner_contract_reference, + benchmark_owner_contract_version=persisted.benchmark_owner_contract_version, + benchmark_owner_contract_digest=persisted.benchmark_owner_contract_digest, + benchmark_owner_contract_released_at=persisted.benchmark_owner_contract_released_at, + benchmark_reference_at=persisted.benchmark_reference_at, + benchmark_receipt_released_at=persisted.benchmark_receipt_released_at, + benchmark_receipt_superseded_at=persisted.benchmark_receipt_superseded_at, + constructed_at=persisted.constructed_at, + owner_contract_reference=persisted.owner_contract_reference, + owner_contract_version=persisted.owner_contract_version, + owner_contract_digest=persisted.owner_contract_digest, + owner_contract_released_at=persisted.owner_contract_released_at, + released_at=persisted.released_at, + ) + expected = ( + tenant_id, + study_id, + calibration_ref, + calibration_digest, + auxiliary_authority_ref, + projection_ref, + projection_version, + projection_digest, + purpose_ref, + purpose_digest, + auxiliary_owner_ref, + auxiliary_owner_version, + auxiliary_owner_digest, + authorization_ref, + authorization_digest, + scientific_use_ref, + scientific_use_digest, + scientific_use_at, + benchmark_ref, + benchmark_version, + benchmark_digest, + benchmark_owner_ref, + benchmark_owner_version, + benchmark_owner_digest, + benchmark_reference, + constructed, + owner_ref, + owner_version, + owner_digest, + ) + if _caller_coordinates(record) != expected: + raise CalibrationSupportAuthorityIntegrityError( + "released calibration support authority does not match requested coordinates" + ) + if record.released_at > use_instant: + raise CalibrationSupportAuthorityIntegrityError( + "calibration support evidence must be released before scientific use" + ) + + values = {field_name: getattr(record, field_name) for field_name in _READ_FIELDS} + fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) + return tuple.__new__( + CalibrationSupportAuthorityView, + (tenant_identity, study_identity, fields), + ) From 90bddb2b12de1ae3d8f06343a5c75247fd4fca9c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 15:07:44 +0900 Subject: [PATCH 289/603] test(workforce-validation): cover calibration support authority edges --- ...est_calibration_support_authority_edges.py | 406 ++++++++++++++++++ 1 file changed, 406 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_support_authority_edges.py diff --git a/services/workforce-validation-api/tests/test_calibration_support_authority_edges.py b/services/workforce-validation-api/tests/test_calibration_support_authority_edges.py new file mode 100644 index 000000000..1b401a6ea --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_support_authority_edges.py @@ -0,0 +1,406 @@ +"""Fail-closed and branch coverage for calibration supporting-authority evidence.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy + +from orgmetra_workforce_validation_api import ValidationPrincipal +import orgmetra_workforce_validation_api.calibration_support_authority as target +from orgmetra_workforce_validation_api.calibration_support_authority import ( + CalibrationSupportAuthorityIntegrityError, + CalibrationSupportAuthorityNotFound, + CalibrationSupportAuthorityReadPort, + CalibrationSupportAuthorityRecord, + CalibrationSupportAuthorityView, + resolve_calibration_support_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000f2") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000f3") +AUX_OWNER_RELEASED_AT = datetime(2026, 9, 17, 7, 50, tzinfo=timezone.utc) +AUX_AUTH_RELEASED_AT = datetime(2026, 9, 17, 8, 0, tzinfo=timezone.utc) +AUX_AUTHORIZED_FROM = datetime(2026, 9, 17, 8, 10, tzinfo=timezone.utc) +AUX_AUTHORIZED_TO = datetime(2026, 10, 1, tzinfo=timezone.utc) +AUX_USE_AT = datetime(2026, 9, 17, 8, 30, tzinfo=timezone.utc) +BENCHMARK_OWNER_RELEASED_AT = datetime(2026, 9, 17, 8, 0, tzinfo=timezone.utc) +BENCHMARK_RECEIPT_RELEASED_AT = datetime(2026, 9, 17, 8, 20, tzinfo=timezone.utc) +BENCHMARK_REFERENCE_AT = datetime(2026, 9, 17, 8, 15, tzinfo=timezone.utc) +CONSTRUCTED_AT = datetime(2026, 9, 17, 9, 0, tzinfo=timezone.utc) +OWNER_RELEASED_AT = datetime(2026, 9, 17, 9, 10, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 9, 20, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 10, 0, tzinfo=timezone.utc) + + +class _ReadPort: + """Return configured support evidence and retain whether persistence was invoked.""" + + def __init__(self, result: object) -> None: + self.result = result + self.calls = 0 + + def read_calibration_support_authority(self, **_: object) -> object: + """Return configured evidence after counting the owner read.""" + self.calls += 1 + return self.result + + +class _NoReadMethod: + """Deliberately omit the owner-read capability.""" + + +class _ProtocolOnly(CalibrationSupportAuthorityReadPort): + """Inherit only the Protocol placeholder.""" + + +class _DescriptorReadPort: + """Expose a descriptor that must not execute during static capability inspection.""" + + @property + def read_calibration_support_authority(self) -> object: + raise AssertionError("descriptor must not execute") + + +def _principal() -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="calibration-support-read-v1", + resource_kind="calibration_support_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=target._READ_FIELDS, + ) + + +def _record(**overrides: object) -> CalibrationSupportAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "support_authority_reference": ( + "calibration_support_authority:10101010-1010-4010-8010-101010101010" + ), + "support_authority_digest": "0" * 64, + "evidence_version": 1, + "calibration_receipt_reference": ( + "calibration_adjustment_receipt:11111111-1111-4111-8111-111111111111" + ), + "calibration_receipt_digest": "1" * 64, + "auxiliary_authority_reference": ( + "scientific_auxiliary_authority:22222222-2222-4222-8222-222222222222" + ), + "auxiliary_projection_reference": ( + "calibration_auxiliary_projection:33333333-3333-4333-8333-333333333333" + ), + "auxiliary_projection_version": 3, + "auxiliary_projection_digest": "2" * 64, + "auxiliary_purpose_reference": ( + "scientific_data_use_purpose:44444444-4444-4444-8444-444444444444" + ), + "auxiliary_purpose_digest": "3" * 64, + "auxiliary_owner_contract_reference": ( + "released_owner_contract:55555555-5555-4555-8555-555555555555" + ), + "auxiliary_owner_contract_version": 5, + "auxiliary_owner_contract_digest": "4" * 64, + "auxiliary_owner_contract_released_at": AUX_OWNER_RELEASED_AT, + "auxiliary_authorization_receipt_reference": ( + "scientific_data_authorization:66666666-6666-4666-8666-666666666666" + ), + "auxiliary_authorization_receipt_digest": "5" * 64, + "auxiliary_authorization_receipt_released_at": AUX_AUTH_RELEASED_AT, + "auxiliary_scientific_use_receipt_reference": ( + "scientific_use_receipt:77777777-7777-4777-8777-777777777777" + ), + "auxiliary_scientific_use_receipt_digest": "6" * 64, + "auxiliary_scientific_use_at": AUX_USE_AT, + "auxiliary_authorized_from": AUX_AUTHORIZED_FROM, + "auxiliary_authorized_to": AUX_AUTHORIZED_TO, + "benchmark_receipt_reference": ( + "calibration_benchmark_receipt:88888888-8888-4888-8888-888888888888" + ), + "benchmark_receipt_version": 8, + "benchmark_receipt_digest": "7" * 64, + "benchmark_owner_contract_reference": ( + "released_owner_contract:99999999-9999-4999-8999-999999999999" + ), + "benchmark_owner_contract_version": 9, + "benchmark_owner_contract_digest": "8" * 64, + "benchmark_owner_contract_released_at": BENCHMARK_OWNER_RELEASED_AT, + "benchmark_reference_at": BENCHMARK_REFERENCE_AT, + "benchmark_receipt_released_at": BENCHMARK_RECEIPT_RELEASED_AT, + "benchmark_receipt_superseded_at": None, + "constructed_at": CONSTRUCTED_AT, + "owner_contract_reference": ( + "released_owner_contract:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" + ), + "owner_contract_version": 10, + "owner_contract_digest": "9" * 64, + "owner_contract_released_at": OWNER_RELEASED_AT, + "released_at": RELEASED_AT, + } + values.update(overrides) + return CalibrationSupportAuthorityRecord(**values) # type: ignore[arg-type] + + +def _resolve(*, read_port: object, **overrides: object) -> CalibrationSupportAuthorityView: + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "calibration_receipt_reference": ( + "calibration_adjustment_receipt:11111111-1111-4111-8111-111111111111" + ), + "calibration_receipt_digest": "1" * 64, + "auxiliary_authority_reference": ( + "scientific_auxiliary_authority:22222222-2222-4222-8222-222222222222" + ), + "auxiliary_projection_reference": ( + "calibration_auxiliary_projection:33333333-3333-4333-8333-333333333333" + ), + "auxiliary_projection_version": 3, + "auxiliary_projection_digest": "2" * 64, + "auxiliary_purpose_reference": ( + "scientific_data_use_purpose:44444444-4444-4444-8444-444444444444" + ), + "auxiliary_purpose_digest": "3" * 64, + "auxiliary_owner_contract_reference": ( + "released_owner_contract:55555555-5555-4555-8555-555555555555" + ), + "auxiliary_owner_contract_version": 5, + "auxiliary_owner_contract_digest": "4" * 64, + "auxiliary_authorization_receipt_reference": ( + "scientific_data_authorization:66666666-6666-4666-8666-666666666666" + ), + "auxiliary_authorization_receipt_digest": "5" * 64, + "auxiliary_scientific_use_receipt_reference": ( + "scientific_use_receipt:77777777-7777-4777-8777-777777777777" + ), + "auxiliary_scientific_use_receipt_digest": "6" * 64, + "auxiliary_scientific_use_at": AUX_USE_AT, + "benchmark_receipt_reference": ( + "calibration_benchmark_receipt:88888888-8888-4888-8888-888888888888" + ), + "benchmark_receipt_version": 8, + "benchmark_receipt_digest": "7" * 64, + "benchmark_owner_contract_reference": ( + "released_owner_contract:99999999-9999-4999-8999-999999999999" + ), + "benchmark_owner_contract_version": 9, + "benchmark_owner_contract_digest": "8" * 64, + "benchmark_reference_at": BENCHMARK_REFERENCE_AT, + "constructed_at": CONSTRUCTED_AT, + "owner_contract_reference": ( + "released_owner_contract:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" + ), + "owner_contract_version": 10, + "owner_contract_digest": "9" * 64, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_calibration_support_authority(**values) # type: ignore[arg-type] + + +def test_resolution_returns_complete_owner_resolved_support_chronology() -> None: + port = _ReadPort(_record()) + view = _resolve(read_port=port) + + assert isinstance(port, CalibrationSupportAuthorityReadPort) + assert port.calls == 1 + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + fields = dict(view.fields) + assert fields["support_authority_digest"] == "0" * 64 + assert fields["auxiliary_owner_contract_released_at"] == AUX_OWNER_RELEASED_AT + assert fields["auxiliary_authorization_receipt_released_at"] == AUX_AUTH_RELEASED_AT + assert fields["benchmark_receipt_released_at"] == BENCHMARK_RECEIPT_RELEASED_AT + assert fields["benchmark_receipt_superseded_at"] is None + assert fields["released_at"] == RELEASED_AT + + +def test_open_ended_auxiliary_interval_and_future_benchmark_cutover_remain_reproducible() -> None: + future_cutover = CONSTRUCTED_AT + timedelta(hours=1) + view = _resolve( + read_port=_ReadPort( + _record( + auxiliary_authorized_to=None, + benchmark_receipt_superseded_at=future_cutover, + ) + ) + ) + fields = dict(view.fields) + assert fields["auxiliary_authorized_to"] is None + assert fields["benchmark_receipt_superseded_at"] == future_cutover + + +def test_authorization_denial_happens_before_owner_resolution() -> None: + port = _ReadPort(_record()) + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, policy=_policy(purpose_code="audit_review")) + assert port.calls == 0 + + +def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: + with pytest.raises(CalibrationSupportAuthorityNotFound): + _resolve(read_port=_ReadPort(None)) + with pytest.raises(CalibrationSupportAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object())) + + +def test_owner_result_must_match_requested_coordinates() -> None: + with pytest.raises(CalibrationSupportAuthorityIntegrityError, match="does not match"): + _resolve(read_port=_ReadPort(_record(tenant_record_id=OTHER_TENANT))) + with pytest.raises(CalibrationSupportAuthorityIntegrityError, match="does not match"): + _resolve(read_port=_ReadPort(_record(validity_study_id=OTHER_STUDY))) + with pytest.raises(CalibrationSupportAuthorityIntegrityError, match="does not match"): + _resolve(read_port=_ReadPort(_record(calibration_receipt_digest="a" * 64))) + + +def test_support_binding_must_be_released_before_scientific_use() -> None: + with pytest.raises(CalibrationSupportAuthorityIntegrityError, match="released before scientific use"): + _resolve(read_port=_ReadPort(_record()), used_at=RELEASED_AT - timedelta(seconds=1)) + + +@pytest.mark.parametrize( + ("override", "match"), + [ + ({"evidence_version": 2}, "evidence_version must remain 1"), + ( + {"auxiliary_owner_contract_released_at": AUX_AUTH_RELEASED_AT + timedelta(seconds=1)}, + "auxiliary owner contract cannot postdate authorization", + ), + ( + {"auxiliary_authorization_receipt_released_at": AUX_USE_AT + timedelta(seconds=1)}, + "authorization receipt must be released no later", + ), + ( + {"auxiliary_authorized_to": AUX_AUTHORIZED_FROM}, + "auxiliary_authorized_to must be later", + ), + ( + {"auxiliary_authorized_from": AUX_USE_AT + timedelta(seconds=1)}, + "auxiliary scientific use must fall inside", + ), + ( + {"auxiliary_authorized_to": AUX_USE_AT}, + "auxiliary scientific use must fall inside", + ), + ( + {"benchmark_owner_contract_released_at": BENCHMARK_RECEIPT_RELEASED_AT + timedelta(seconds=1)}, + "benchmark owner contract cannot postdate", + ), + ( + {"benchmark_receipt_superseded_at": BENCHMARK_RECEIPT_RELEASED_AT}, + "benchmark supersession must be later", + ), + ( + {"auxiliary_scientific_use_at": CONSTRUCTED_AT + timedelta(seconds=1)}, + "auxiliary scientific use cannot be later", + ), + ( + {"benchmark_reference_at": CONSTRUCTED_AT + timedelta(seconds=1)}, + "benchmark reference cannot be later", + ), + ( + {"benchmark_receipt_released_at": CONSTRUCTED_AT + timedelta(seconds=1)}, + "benchmark receipt must be released no later", + ), + ( + {"benchmark_receipt_superseded_at": CONSTRUCTED_AT}, + "superseded benchmark cannot support calibration", + ), + ( + {"owner_contract_released_at": RELEASED_AT + timedelta(seconds=1)}, + "owner contract cannot be released after support evidence", + ), + ( + {"released_at": CONSTRUCTED_AT - timedelta(seconds=1)}, + "support evidence cannot be released before calibration construction", + ), + ], +) +def test_record_rejects_incoherent_owner_chronology( + override: dict[str, object], match: str +) -> None: + with pytest.raises(ValueError, match=match): + _record(**override) + + +def test_view_cannot_be_constructed_by_callers() -> None: + with pytest.raises(TypeError): + CalibrationSupportAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("calibration_receipt_reference", "wrong:calibration", ValueError), + ("calibration_receipt_digest", "ABC", ValueError), + ("auxiliary_authority_reference", "wrong:aux", ValueError), + ("auxiliary_projection_reference", "wrong:projection", ValueError), + ("auxiliary_projection_version", 0, ValueError), + ("auxiliary_projection_digest", "2" * 63, ValueError), + ("auxiliary_purpose_reference", "wrong:purpose", ValueError), + ("auxiliary_purpose_digest", "3" * 63, ValueError), + ("auxiliary_owner_contract_reference", "wrong:contract", ValueError), + ("auxiliary_owner_contract_version", True, ValueError), + ("auxiliary_owner_contract_digest", "4" * 63, ValueError), + ("auxiliary_authorization_receipt_reference", "wrong:authorization", ValueError), + ("auxiliary_authorization_receipt_digest", "5" * 63, ValueError), + ("auxiliary_scientific_use_receipt_reference", "wrong:use", ValueError), + ("auxiliary_scientific_use_receipt_digest", "6" * 63, ValueError), + ("auxiliary_scientific_use_at", datetime(2026, 9, 17, 8, 30), ValueError), + ("benchmark_receipt_reference", "wrong:benchmark", ValueError), + ("benchmark_receipt_version", 0, ValueError), + ("benchmark_receipt_digest", "7" * 63, ValueError), + ("benchmark_owner_contract_reference", "wrong:contract", ValueError), + ("benchmark_owner_contract_version", 0, ValueError), + ("benchmark_owner_contract_digest", "8" * 63, ValueError), + ("benchmark_reference_at", datetime(2026, 9, 17, 8, 15), ValueError), + ("constructed_at", datetime(2026, 9, 17, 9, 0), ValueError), + ("owner_contract_reference", "wrong:contract", ValueError), + ("owner_contract_version", 0, ValueError), + ("owner_contract_digest", "9" * 63, ValueError), + ("used_at", datetime(2026, 9, 17, 10, 0), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_or_dependency_fails_before_owner_resolution( + key: str, value: object, error: type[Exception] +) -> None: + port: object = _ReadPort(_record()) + overrides = {key: value} + if key == "read_port": + port = value + overrides = {} + with pytest.raises(error): + _resolve(read_port=port, **overrides) + if isinstance(port, _ReadPort): + assert port.calls == 0 From 482d48b498dd09c1cf0f5fcec5f671e8a14439ec Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 15:08:16 +0900 Subject: [PATCH 290/603] feat(workforce-validation): export calibration support authority --- .../orgmetra_workforce_validation_api/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index deb61f76e..3ae082d4a 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -40,6 +40,14 @@ CalibrationAdjustmentSupersessionAuthorityView, resolve_calibration_adjustment_supersession_authority, ) +from orgmetra_workforce_validation_api.calibration_support_authority import ( + CalibrationSupportAuthorityIntegrityError, + CalibrationSupportAuthorityNotFound, + CalibrationSupportAuthorityReadPort, + CalibrationSupportAuthorityRecord, + CalibrationSupportAuthorityView, + resolve_calibration_support_authority, +) from orgmetra_workforce_validation_api.final_weight_authority import ( FinalAnalysisWeightAuthorityIntegrityError, FinalAnalysisWeightAuthorityNotFound, @@ -194,6 +202,11 @@ "CalibrationBenchmarkAuthorityReadPort", "CalibrationBenchmarkAuthorityRecord", "CalibrationBenchmarkAuthorityView", + "CalibrationSupportAuthorityIntegrityError", + "CalibrationSupportAuthorityNotFound", + "CalibrationSupportAuthorityReadPort", + "CalibrationSupportAuthorityRecord", + "CalibrationSupportAuthorityView", "FinalAnalysisWeightAuthorityIntegrityError", "FinalAnalysisWeightAuthorityNotFound", "FinalAnalysisWeightAuthorityReadPort", @@ -273,6 +286,7 @@ "resolve_calibration_adjustment_supersession_authority", "resolve_calibration_auxiliary_authority", "resolve_calibration_benchmark_authority", + "resolve_calibration_support_authority", "resolve_final_analysis_weight_authority", "resolve_final_weight_supersession_authority", "resolve_nonresponse_adjustment_authority", From a5e18c6abf9b170cb44d5e440bd96f35c318eafc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 15:12:26 +0900 Subject: [PATCH 291/603] test(workforce-validation): require authorization evidence before effective interval --- ...port_authorization_effective_chronology.py | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_support_authorization_effective_chronology.py diff --git a/services/workforce-validation-api/tests/test_calibration_support_authorization_effective_chronology.py b/services/workforce-validation-api/tests/test_calibration_support_authorization_effective_chronology.py new file mode 100644 index 000000000..7f11185d3 --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_support_authorization_effective_chronology.py @@ -0,0 +1,94 @@ +"""RED contract for calibration support authorization release chronology.""" + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.calibration_support_authority import ( + CalibrationSupportAuthorityRecord, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f2") +AUTHORIZED_FROM = datetime(2026, 9, 17, 8, 10, tzinfo=timezone.utc) +USE_AT = datetime(2026, 9, 17, 8, 30, tzinfo=timezone.utc) +CONSTRUCTED_AT = datetime(2026, 9, 17, 9, 0, tzinfo=timezone.utc) + + +def test_authorization_receipt_cannot_be_released_after_interval_begins() -> None: + """Do not accept retroactive authority merely because the receipt predates use.""" + with pytest.raises(ValueError, match="authorization receipt must exist before authorization begins"): + CalibrationSupportAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + support_authority_reference=( + "calibration_support_authority:10101010-1010-4010-8010-101010101010" + ), + support_authority_digest="0" * 64, + evidence_version=1, + calibration_receipt_reference=( + "calibration_adjustment_receipt:11111111-1111-4111-8111-111111111111" + ), + calibration_receipt_digest="1" * 64, + auxiliary_authority_reference=( + "scientific_auxiliary_authority:22222222-2222-4222-8222-222222222222" + ), + auxiliary_projection_reference=( + "calibration_auxiliary_projection:33333333-3333-4333-8333-333333333333" + ), + auxiliary_projection_version=3, + auxiliary_projection_digest="2" * 64, + auxiliary_purpose_reference=( + "scientific_data_use_purpose:44444444-4444-4444-8444-444444444444" + ), + auxiliary_purpose_digest="3" * 64, + auxiliary_owner_contract_reference=( + "released_owner_contract:55555555-5555-4555-8555-555555555555" + ), + auxiliary_owner_contract_version=5, + auxiliary_owner_contract_digest="4" * 64, + auxiliary_owner_contract_released_at=datetime( + 2026, 9, 17, 7, 50, tzinfo=timezone.utc + ), + auxiliary_authorization_receipt_reference=( + "scientific_data_authorization:66666666-6666-4666-8666-666666666666" + ), + auxiliary_authorization_receipt_digest="5" * 64, + auxiliary_authorization_receipt_released_at=( + AUTHORIZED_FROM + timedelta(seconds=1) + ), + auxiliary_scientific_use_receipt_reference=( + "scientific_use_receipt:77777777-7777-4777-8777-777777777777" + ), + auxiliary_scientific_use_receipt_digest="6" * 64, + auxiliary_scientific_use_at=USE_AT, + auxiliary_authorized_from=AUTHORIZED_FROM, + auxiliary_authorized_to=datetime(2026, 10, 1, tzinfo=timezone.utc), + benchmark_receipt_reference=( + "calibration_benchmark_receipt:88888888-8888-4888-8888-888888888888" + ), + benchmark_receipt_version=8, + benchmark_receipt_digest="7" * 64, + benchmark_owner_contract_reference=( + "released_owner_contract:99999999-9999-4999-8999-999999999999" + ), + benchmark_owner_contract_version=9, + benchmark_owner_contract_digest="8" * 64, + benchmark_owner_contract_released_at=datetime( + 2026, 9, 17, 8, 0, tzinfo=timezone.utc + ), + benchmark_reference_at=datetime(2026, 9, 17, 8, 15, tzinfo=timezone.utc), + benchmark_receipt_released_at=datetime( + 2026, 9, 17, 8, 20, tzinfo=timezone.utc + ), + benchmark_receipt_superseded_at=None, + constructed_at=CONSTRUCTED_AT, + owner_contract_reference=( + "released_owner_contract:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" + ), + owner_contract_version=10, + owner_contract_digest="9" * 64, + owner_contract_released_at=datetime(2026, 9, 17, 9, 10, tzinfo=timezone.utc), + released_at=datetime(2026, 9, 17, 9, 20, tzinfo=timezone.utc), + ) From 0836b03556a62c08f9860d6f2073d79f68d284c3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 15:14:14 +0900 Subject: [PATCH 292/603] fix(workforce-validation): reject retroactive calibration support authority --- .../calibration_support_authority.py | 130 +++++++++++------- 1 file changed, 80 insertions(+), 50 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py index b2d051269..614b80f16 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py @@ -3,8 +3,8 @@ The typed calibration receipt carries the identities of the auxiliary and benchmark inputs used to construct weights. This boundary separately proves that those exact supporting authorities were released and current when the calibration was -constructed. Owner-resolved release/cutover instants are evidence, never caller -lookup coordinates. +constructed. Owner-resolved release, effective-interval, and cutover instants are +evidence rather than caller lookup coordinates. """ from __future__ import annotations @@ -90,6 +90,16 @@ class CalibrationSupportAuthorityIntegrityError(RuntimeError): """Indicate that returned support evidence does not match the requested binding.""" +def _tuple_property(index: int, doc: str) -> property: + """Create a documented immutable tuple projection for one public evidence field.""" + + def getter(record: tuple[object, ...]) -> object: + """Return one already-validated immutable evidence coordinate.""" + return record[index] + + return property(getter, doc=doc) + + class CalibrationSupportAuthorityRecord(tuple): """Immutable released proof that calibration support was valid at construction.""" @@ -140,11 +150,13 @@ def __new__( owner_contract_released_at: datetime, released_at: datetime, ) -> CalibrationSupportAuthorityRecord: - """Validate support identities and owner-resolved chronology before storage.""" + """Validate identities and chronology before storing detached owner evidence.""" tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) study_identity = _store_operational_uuid("validity_study_id", validity_study_id) support_ref = _require_reference( - "support_authority_reference", support_authority_reference, "calibration_support_authority" + "support_authority_reference", + support_authority_reference, + "calibration_support_authority", ) support_digest = _require_digest("support_authority_digest", support_authority_digest) version = _require_positive_integer("evidence_version", evidence_version) @@ -231,10 +243,16 @@ def __new__( raise ValueError( "authorization receipt must be released no later than auxiliary scientific use." ) + if authorization_released > authorized_from: + raise ValueError( + "authorization receipt must exist before authorization begins." + ) if authorized_to is not None and authorized_to <= authorized_from: raise ValueError("auxiliary_authorized_to must be later than auxiliary_authorized_from.") if use_at < authorized_from or (authorized_to is not None and use_at >= authorized_to): - raise ValueError("auxiliary scientific use must fall inside owner-resolved authorization interval.") + raise ValueError( + "auxiliary scientific use must fall inside owner-resolved authorization interval." + ) benchmark_ref = _require_reference( "benchmark_receipt_reference", @@ -285,7 +303,9 @@ def __new__( if benchmark_released > constructed: raise ValueError("benchmark receipt must be released no later than calibration construction.") if benchmark_superseded is not None and constructed >= benchmark_superseded: - raise ValueError("superseded benchmark cannot support calibration construction at or after cutover.") + raise ValueError( + "superseded benchmark cannot support calibration construction at or after cutover." + ) owner_ref = _require_reference( "owner_contract_reference", owner_contract_reference, "released_owner_contract" @@ -350,55 +370,57 @@ def __new__( @property def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity for this support authority.""" return _restore_operational_uuid("tenant_record_id", self[0]) @property def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity for this support authority.""" return _restore_operational_uuid("validity_study_id", self[1]) - support_authority_reference = property(lambda self: self[2]) - support_authority_digest = property(lambda self: self[3]) - evidence_version = property(lambda self: self[4]) - calibration_receipt_reference = property(lambda self: self[5]) - calibration_receipt_digest = property(lambda self: self[6]) - auxiliary_authority_reference = property(lambda self: self[7]) - auxiliary_projection_reference = property(lambda self: self[8]) - auxiliary_projection_version = property(lambda self: self[9]) - auxiliary_projection_digest = property(lambda self: self[10]) - auxiliary_purpose_reference = property(lambda self: self[11]) - auxiliary_purpose_digest = property(lambda self: self[12]) - auxiliary_owner_contract_reference = property(lambda self: self[13]) - auxiliary_owner_contract_version = property(lambda self: self[14]) - auxiliary_owner_contract_digest = property(lambda self: self[15]) - auxiliary_owner_contract_released_at = property(lambda self: self[16]) - auxiliary_authorization_receipt_reference = property(lambda self: self[17]) - auxiliary_authorization_receipt_digest = property(lambda self: self[18]) - auxiliary_authorization_receipt_released_at = property(lambda self: self[19]) - auxiliary_scientific_use_receipt_reference = property(lambda self: self[20]) - auxiliary_scientific_use_receipt_digest = property(lambda self: self[21]) - auxiliary_scientific_use_at = property(lambda self: self[22]) - auxiliary_authorized_from = property(lambda self: self[23]) - auxiliary_authorized_to = property(lambda self: self[24]) - benchmark_receipt_reference = property(lambda self: self[25]) - benchmark_receipt_version = property(lambda self: self[26]) - benchmark_receipt_digest = property(lambda self: self[27]) - benchmark_owner_contract_reference = property(lambda self: self[28]) - benchmark_owner_contract_version = property(lambda self: self[29]) - benchmark_owner_contract_digest = property(lambda self: self[30]) - benchmark_owner_contract_released_at = property(lambda self: self[31]) - benchmark_reference_at = property(lambda self: self[32]) - benchmark_receipt_released_at = property(lambda self: self[33]) - benchmark_receipt_superseded_at = property(lambda self: self[34]) - constructed_at = property(lambda self: self[35]) - owner_contract_reference = property(lambda self: self[36]) - owner_contract_version = property(lambda self: self[37]) - owner_contract_digest = property(lambda self: self[38]) - owner_contract_released_at = property(lambda self: self[39]) - released_at = property(lambda self: self[40]) + support_authority_reference = _tuple_property(2, "Return the immutable support-authority reference.") + support_authority_digest = _tuple_property(3, "Return the digest of the exact support-authority evidence.") + evidence_version = _tuple_property(4, "Return the governed support-authority evidence version.") + calibration_receipt_reference = _tuple_property(5, "Return the typed calibration receipt this support proof corroborates.") + calibration_receipt_digest = _tuple_property(6, "Return the digest of the typed calibration receipt.") + auxiliary_authority_reference = _tuple_property(7, "Return the scientific auxiliary-authority identity used by calibration.") + auxiliary_projection_reference = _tuple_property(8, "Return the purpose-limited auxiliary projection reference.") + auxiliary_projection_version = _tuple_property(9, "Return the exact auxiliary projection version.") + auxiliary_projection_digest = _tuple_property(10, "Return the digest of the auxiliary projection used by calibration.") + auxiliary_purpose_reference = _tuple_property(11, "Return the governed scientific-use purpose reference.") + auxiliary_purpose_digest = _tuple_property(12, "Return the digest of the governed scientific-use purpose.") + auxiliary_owner_contract_reference = _tuple_property(13, "Return the released auxiliary-owner contract reference.") + auxiliary_owner_contract_version = _tuple_property(14, "Return the released auxiliary-owner contract version.") + auxiliary_owner_contract_digest = _tuple_property(15, "Return the released auxiliary-owner contract digest.") + auxiliary_owner_contract_released_at = _tuple_property(16, "Return when the auxiliary-owner contract became released evidence.") + auxiliary_authorization_receipt_reference = _tuple_property(17, "Return the purpose-bound authorization receipt reference.") + auxiliary_authorization_receipt_digest = _tuple_property(18, "Return the digest of the purpose-bound authorization receipt.") + auxiliary_authorization_receipt_released_at = _tuple_property(19, "Return when the authorization receipt became released evidence.") + auxiliary_scientific_use_receipt_reference = _tuple_property(20, "Return the immutable scientific-use receipt reference.") + auxiliary_scientific_use_receipt_digest = _tuple_property(21, "Return the digest of the scientific-use receipt.") + auxiliary_scientific_use_at = _tuple_property(22, "Return the scientific-use instant committed by the calibration lineage.") + auxiliary_authorized_from = _tuple_property(23, "Return the inclusive start of the owner-resolved authorization interval.") + auxiliary_authorized_to = _tuple_property(24, "Return the optional exclusive end of the owner-resolved authorization interval.") + benchmark_receipt_reference = _tuple_property(25, "Return the calibration benchmark receipt reference.") + benchmark_receipt_version = _tuple_property(26, "Return the exact calibration benchmark receipt version.") + benchmark_receipt_digest = _tuple_property(27, "Return the digest of the exact calibration benchmark receipt.") + benchmark_owner_contract_reference = _tuple_property(28, "Return the released benchmark-owner contract reference.") + benchmark_owner_contract_version = _tuple_property(29, "Return the released benchmark-owner contract version.") + benchmark_owner_contract_digest = _tuple_property(30, "Return the released benchmark-owner contract digest.") + benchmark_owner_contract_released_at = _tuple_property(31, "Return when the benchmark-owner contract became released evidence.") + benchmark_reference_at = _tuple_property(32, "Return the benchmark reference instant committed by calibration.") + benchmark_receipt_released_at = _tuple_property(33, "Return when the benchmark receipt became released evidence.") + benchmark_receipt_superseded_at = _tuple_property(34, "Return the optional exclusive cutover that ended benchmark authority.") + constructed_at = _tuple_property(35, "Return when the typed calibration receipt was constructed.") + owner_contract_reference = _tuple_property(36, "Return the released application owner-contract reference.") + owner_contract_version = _tuple_property(37, "Return the released application owner-contract version.") + owner_contract_digest = _tuple_property(38, "Return the digest of the released application owner contract.") + owner_contract_released_at = _tuple_property(39, "Return when the application owner contract became released evidence.") + released_at = _tuple_property(40, "Return when this support proof became released application evidence.") class CalibrationSupportAuthorityView(tuple): - """Field-minimized support evidence issued only after authorization.""" + """Field-minimized support evidence issued only after purpose-bound authorization.""" __slots__ = () @@ -409,20 +431,24 @@ def __new__( validity_study_id: UUID, fields: tuple[tuple[str, object], ...], ) -> CalibrationSupportAuthorityView: + """Reject direct construction so callers cannot mint reusable authority views.""" raise TypeError( "CalibrationSupportAuthorityView is issued only by resolve_calibration_support_authority." ) @property def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" return _restore_operational_uuid("tenant_record_id", self[0]) @property def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" return _restore_operational_uuid("validity_study_id", self[1]) @property def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable corroborating support evidence without source values.""" return self[2] @@ -463,6 +489,7 @@ def read_calibration_support_authority( owner_contract_version: int, owner_contract_digest: str, ) -> CalibrationSupportAuthorityRecord | None: + """Return matching released support evidence or ``None`` through an owner ACL.""" ... @@ -472,7 +499,7 @@ def read_calibration_support_authority( def _caller_coordinates(record: CalibrationSupportAuthorityRecord) -> tuple[object, ...]: - """Return immutable caller-known coordinates, excluding owner chronology.""" + """Return immutable caller-known coordinates while excluding owner chronology.""" return ( record.tenant_record_id, record.validity_study_id, @@ -550,7 +577,9 @@ def resolve_calibration_support_authority( raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") read_capability = getattr_static(type(read_port), "read_calibration_support_authority", None) if type(read_capability) is not FunctionType or read_capability is _PROTOCOL_READ_CAPABILITY: - raise TypeError("read_port must expose a statically callable read_calibration_support_authority.") + raise TypeError( + "read_port must expose a statically callable read_calibration_support_authority." + ) tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) study_identity = _store_operational_uuid("validity_study_id", validity_study_id) @@ -565,7 +594,6 @@ def resolve_calibration_support_authority( ) detached_policy = _detach_policy(policy) - # Validate every caller-known coordinate before invoking authorization or persistence. calibration_ref = _require_reference( "calibration_receipt_reference", calibration_receipt_reference, "calibration_adjustment_receipt" ) @@ -576,7 +604,9 @@ def resolve_calibration_support_authority( projection_ref = _require_reference( "auxiliary_projection_reference", auxiliary_projection_reference, "calibration_auxiliary_projection" ) - projection_version = _require_positive_integer("auxiliary_projection_version", auxiliary_projection_version) + projection_version = _require_positive_integer( + "auxiliary_projection_version", auxiliary_projection_version + ) projection_digest = _require_digest("auxiliary_projection_digest", auxiliary_projection_digest) purpose_ref = _require_reference( "auxiliary_purpose_reference", auxiliary_purpose_reference, "scientific_data_use_purpose" From 5b90d87914b1d6cb6c170c3714a49f821d7a162f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 15:20:03 +0900 Subject: [PATCH 293/603] docs(workforce-validation): document calibration support chronology --- services/workforce-validation-api/README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index c34be9440..18bfbe3d8 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -36,6 +36,12 @@ The supporting auxiliary-use and benchmark-reference instants are caller-known r The ordinary typed-calibration record also carries an optional owner-resolved `superseded_at`. It is not a caller lookup coordinate and is not projected as reusable downstream authority. Scientific use is valid only on `[released_at, superseded_at)`: historical use before cutover remains reproducible and use at or after cutover fails closed. +## Calibration support chronology authority + +`resolve_calibration_support_authority(...)` independently corroborates whether the exact auxiliary and benchmark support named by a typed calibration receipt actually existed and was authoritative when calibration was constructed. It binds the calibration receipt to the exact auxiliary authority/projection/purpose/authorization/scientific-use coordinates and the exact benchmark receipt/owner coordinates while resolving release, effective-interval, and benchmark-cutover chronology from immutable owner evidence. + +Auxiliary chronology must satisfy `auxiliary_owner_contract_released_at <= auxiliary_authorization_receipt_released_at <= auxiliary_authorized_from <= auxiliary_scientific_use_at`; when the authorization interval is bounded, scientific use must occur before its exclusive end. The authorization receipt therefore cannot retroactively validate an interval that began before the receipt existed. The scientific-use instant may not postdate calibration construction. Benchmark owner evidence must predate benchmark receipt release, the benchmark receipt must already be released by calibration construction, and a benchmark superseded at or before construction cannot support that calibration. Owner-resolved release/effective/cutover timestamps are deliberately excluded from resolver and owner-read lookup coordinates so callers cannot manufacture favorable chronology. + ## Calibration-adjustment supersession authority `resolve_calibration_adjustment_supersession_authority(...)` proves the append-only correction edge behind typed-calibration currentness. An ordinary `superseded_at` alone is not enough to prove which immutable receipt ended the predecessor interval. A correction therefore requires one complete successor calibration receipt reference/digest/evidence-version/release tuple. @@ -120,9 +126,9 @@ The immutable `verification_attempt_reference` and `verification_attempt_digest` The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **nineteen** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, base/design-weight supersession, complete final analysis-weight lineage, final-weight supersession, point-weight/variance compatibility, point-weight/variance supersession, validation-result binding, validation-result supersession, and validation-result non-verifiability. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **twenty** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration support chronology, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, base/design-weight supersession, complete final analysis-weight lineage, final-weight supersession, point-weight/variance compatibility, point-weight/variance supersession, validation-result binding, validation-result supersession, and validation-result non-verifiability. -The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable verification-attempt reference/digest and preserve failed-evidence and attempt-release chronology. No durable adapter may infer currentness from mutable current rows or caller-supplied timestamps. +The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable verification-attempt reference/digest and preserve failed-evidence and attempt-release chronology. No durable adapter may infer currentness from mutable current rows or caller-supplied timestamps. ## Test contract @@ -137,6 +143,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity and chronology. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity and chronology. -These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. +These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. \ No newline at end of file From 28844c54b87a85d69635c1c3460146418f5bf97c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 15:31:15 +0900 Subject: [PATCH 294/603] test(workforce-validation): enforce production docstring contract --- .../test_production_docstring_contract.py | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_production_docstring_contract.py diff --git a/services/workforce-validation-api/tests/test_production_docstring_contract.py b/services/workforce-validation-api/tests/test_production_docstring_contract.py new file mode 100644 index 000000000..34f82f956 --- /dev/null +++ b/services/workforce-validation-api/tests/test_production_docstring_contract.py @@ -0,0 +1,60 @@ +"""Verify substantive docstrings across the owned Workforce Validation production surface. + +CodeRabbit's PR-wide percentage also counts test helpers, so it is useful review +signal but not a precise measure of the commercial requirement for owned +production code. This contract scans the package itself and makes missing module, +class, function, method, property, protocol, and resolver documentation a hard CI +failure instead of an advisory review percentage. +""" + +from __future__ import annotations + +import ast +from pathlib import Path + + +_PACKAGE_ROOT = ( + Path(__file__).resolve().parents[1] + / "src" + / "orgmetra_workforce_validation_api" +) + + +def _qualified_name(path: Path, parents: tuple[str, ...], name: str) -> str: + """Return one repository-relative Python symbol name for a docstring failure.""" + module_name = path.relative_to(_PACKAGE_ROOT).with_suffix("").as_posix().replace("/", ".") + scope = ".".join((*parents, name)) + return f"{module_name}:{scope}" if scope else module_name + + +def _collect_missing_docstrings(path: Path) -> list[str]: + """Collect production definitions whose first statement is not a non-empty docstring.""" + module = ast.parse(path.read_text(encoding="utf-8"), filename=str(path)) + missing: list[str] = [] + + if not ast.get_docstring(module, clean=False): + missing.append(f"{path.relative_to(_PACKAGE_ROOT)}:") + + def visit(body: list[ast.stmt], parents: tuple[str, ...]) -> None: + """Walk lexical definitions while preserving readable ownership-qualified names.""" + for node in body: + if isinstance(node, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)): + if not ast.get_docstring(node, clean=False): + missing.append(_qualified_name(path, parents, node.name)) + visit(node.body, (*parents, node.name)) + + visit(module.body, ()) + return missing + + +def test_owned_production_definitions_have_docstrings() -> None: + """Require 100% docstrings for every owned Python production definition.""" + source_files = sorted(_PACKAGE_ROOT.glob("*.py")) + assert source_files, "workforce-validation production package must contain Python sources" + + missing = [ + symbol + for source_file in source_files + for symbol in _collect_missing_docstrings(source_file) + ] + assert not missing, "missing production docstrings:\n" + "\n".join(missing) From 7880bb3523b00c06b9d1cc8c792f2a94951048df Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 15:36:53 +0900 Subject: [PATCH 295/603] fix(workforce-validation): harden production docstring gate --- .../test_production_docstring_contract.py | 70 ++++++++++++------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/services/workforce-validation-api/tests/test_production_docstring_contract.py b/services/workforce-validation-api/tests/test_production_docstring_contract.py index 34f82f956..201de93d8 100644 --- a/services/workforce-validation-api/tests/test_production_docstring_contract.py +++ b/services/workforce-validation-api/tests/test_production_docstring_contract.py @@ -1,16 +1,17 @@ -"""Verify substantive docstrings across the owned Workforce Validation production surface. +"""Enforce a measurable documentation floor across owned Workforce Validation code. -CodeRabbit's PR-wide percentage also counts test helpers, so it is useful review -signal but not a precise measure of the commercial requirement for owned -production code. This contract scans the package itself and makes missing module, -class, function, method, property, protocol, and resolver documentation a hard CI -failure instead of an advisory review percentage. +CodeRabbit's PR-wide percentage is useful review signal but also counts test +helpers. This repository-native contract instead scans the production package +recursively and makes undocumented production definitions a hard CI failure. +The mechanical floor rejects blank and placeholder-sized docstrings; semantic +quality remains subject to code review so the metric cannot reward filler. """ from __future__ import annotations import ast from pathlib import Path +import re _PACKAGE_ROOT = ( @@ -18,38 +19,53 @@ / "src" / "orgmetra_workforce_validation_api" ) +_MIN_DOCSTRING_CHARACTERS = 12 +_MIN_DOCSTRING_WORDS = 2 +_WORD_PATTERN = re.compile(r"[A-Za-z][A-Za-z0-9_-]*") +_PLACEHOLDER_DOCSTRINGS = frozenset({"todo", "tbd", "fixme", "pass", "placeholder"}) -def _qualified_name(path: Path, parents: tuple[str, ...], name: str) -> str: - """Return one repository-relative Python symbol name for a docstring failure.""" - module_name = path.relative_to(_PACKAGE_ROOT).with_suffix("").as_posix().replace("/", ".") - scope = ".".join((*parents, name)) - return f"{module_name}:{scope}" if scope else module_name +def _is_substantive_docstring(node: ast.AST) -> bool: + """Reject absent, blank, one-token, and placeholder-sized documentation.""" + docstring = ast.get_docstring(node, clean=False) + if docstring is None: + return False + normalized = " ".join(docstring.split()) + if not normalized or normalized.casefold() in _PLACEHOLDER_DOCSTRINGS: + return False + return ( + len(normalized) >= _MIN_DOCSTRING_CHARACTERS + and len(_WORD_PATTERN.findall(normalized)) >= _MIN_DOCSTRING_WORDS + ) + + +def _symbol_label(path: Path, node: ast.AST) -> str: + """Return one stable repository-relative location for a documentation failure.""" + relative = path.relative_to(_PACKAGE_ROOT).as_posix() + name = getattr(node, "name", "") + line = getattr(node, "lineno", 1) + return f"{relative}:{line}:{name}" def _collect_missing_docstrings(path: Path) -> list[str]: - """Collect production definitions whose first statement is not a non-empty docstring.""" + """Collect every production definition below the minimum documentation floor.""" module = ast.parse(path.read_text(encoding="utf-8"), filename=str(path)) missing: list[str] = [] - if not ast.get_docstring(module, clean=False): - missing.append(f"{path.relative_to(_PACKAGE_ROOT)}:") - - def visit(body: list[ast.stmt], parents: tuple[str, ...]) -> None: - """Walk lexical definitions while preserving readable ownership-qualified names.""" - for node in body: - if isinstance(node, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)): - if not ast.get_docstring(node, clean=False): - missing.append(_qualified_name(path, parents, node.name)) - visit(node.body, (*parents, node.name)) + if not _is_substantive_docstring(module): + missing.append(_symbol_label(path, module)) - visit(module.body, ()) + for node in ast.walk(module): + if isinstance(node, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)) and not ( + _is_substantive_docstring(node) + ): + missing.append(_symbol_label(path, node)) return missing -def test_owned_production_definitions_have_docstrings() -> None: - """Require 100% docstrings for every owned Python production definition.""" - source_files = sorted(_PACKAGE_ROOT.glob("*.py")) +def test_owned_production_definitions_have_substantive_docstrings() -> None: + """Require the documentation floor for all recursively discovered production Python.""" + source_files = sorted(_PACKAGE_ROOT.rglob("*.py")) assert source_files, "workforce-validation production package must contain Python sources" missing = [ @@ -57,4 +73,4 @@ def test_owned_production_definitions_have_docstrings() -> None: for source_file in source_files for symbol in _collect_missing_docstrings(source_file) ] - assert not missing, "missing production docstrings:\n" + "\n".join(missing) + assert not missing, "insufficient production docstrings:\n" + "\n".join(missing) From dd90f1728f20c2cc020c7110b31d2c2bf51164a9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 16:01:44 +0900 Subject: [PATCH 296/603] test(workforce-validation): expose incompatible Python floor --- .../test_package_metadata_compatibility.py | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_package_metadata_compatibility.py diff --git a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py new file mode 100644 index 000000000..2cc0c9086 --- /dev/null +++ b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py @@ -0,0 +1,71 @@ +"""Fail closed when Workforce Validation advertises an uninstallable Python floor.""" + +from __future__ import annotations + +from pathlib import Path +import tomllib + +from packaging.requirements import Requirement +from packaging.specifiers import SpecifierSet +from packaging.utils import canonicalize_name +from packaging.version import Version + + +_SERVICE_ROOT = Path(__file__).resolve().parents[1] +_REPOSITORY_ROOT = _SERVICE_ROOT.parents[1] +_KEYVERSE_PROJECT = _REPOSITORY_ROOT / "packages" / "keyverse-adapter" / "pyproject.toml" +_KEYVERSE_NAME = "orgmetra-keyverse-adapter" + + +def _project_metadata(path: Path) -> dict[str, object]: + """Read static project metadata without importing executable package code.""" + with path.open("rb") as stream: + document = tomllib.load(stream) + project = document.get("project") + assert isinstance(project, dict), f"{path} must define a [project] table" + return project + + +def _inclusive_python_floor(raw_specifier: object, *, owner: str) -> Version: + """Resolve one reviewed inclusive Python floor or fail before comparing ranges.""" + assert isinstance(raw_specifier, str), f"{owner} requires-python must be text" + specifiers = tuple(SpecifierSet(raw_specifier)) + assert len(specifiers) == 1 and specifiers[0].operator == ">=", ( + f"{owner} requires-python must remain one explicit inclusive floor; " + "extend this contract before adopting a compound range" + ) + return Version(specifiers[0].version) + + +def test_service_python_floor_covers_mandatory_keyverse_dependency() -> None: + """Reject a service floor below the exact owned Keyverse dependency floor.""" + service_project = _project_metadata(_SERVICE_ROOT / "pyproject.toml") + keyverse_project = _project_metadata(_KEYVERSE_PROJECT) + + service_dependencies = service_project.get("dependencies") + assert isinstance(service_dependencies, list), "service dependencies must be a list" + parsed_dependencies = [Requirement(value) for value in service_dependencies] + keyverse_requirements = [ + requirement + for requirement in parsed_dependencies + if canonicalize_name(requirement.name) == canonicalize_name(_KEYVERSE_NAME) + ] + assert len(keyverse_requirements) == 1, "service must declare exactly one Keyverse dependency" + + keyverse_version = keyverse_project.get("version") + assert isinstance(keyverse_version, str), "Keyverse project version must be text" + assert keyverse_requirements[0].specifier == SpecifierSet(f"=={keyverse_version}"), ( + "service must consume the exact in-repository Keyverse version" + ) + + service_floor = _inclusive_python_floor( + service_project.get("requires-python"), owner="workforce-validation-api" + ) + keyverse_floor = _inclusive_python_floor( + keyverse_project.get("requires-python"), owner="keyverse-adapter" + ) + assert service_floor >= keyverse_floor, ( + "workforce-validation-api advertises Python versions where its mandatory " + f"Keyverse dependency cannot install: service floor {service_floor}, " + f"Keyverse floor {keyverse_floor}" + ) From 25a01737e2a9757d9fe3320c2412ea8d81f26423 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 16:02:04 +0900 Subject: [PATCH 297/603] fix(workforce-validation): align Python floor with Keyverse --- services/workforce-validation-api/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/workforce-validation-api/pyproject.toml b/services/workforce-validation-api/pyproject.toml index 9a84581c4..6d2039634 100644 --- a/services/workforce-validation-api/pyproject.toml +++ b/services/workforce-validation-api/pyproject.toml @@ -7,7 +7,7 @@ name = "orgmetra-workforce-validation-api" version = "0.1.0" description = "Purpose-bound owner boundary for Orgmetra workforce-validation studies." readme = "README.md" -requires-python = ">=3.11" +requires-python = ">=3.12" license = { text = "Apache-2.0" } authors = [{ name = "ContextualWisdomLab" }] dependencies = [ From 66521011c13ac1ce0edc567646d5ec39ba8d135b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 17:05:49 +0900 Subject: [PATCH 298/603] test(packaging): require built distribution acceptance --- .../test_foundation_ci_dependency_hygiene.sh | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/tests/test_foundation_ci_dependency_hygiene.sh b/tests/test_foundation_ci_dependency_hygiene.sh index d214695fe..6d12dcc12 100644 --- a/tests/test_foundation_ci_dependency_hygiene.sh +++ b/tests/test_foundation_ci_dependency_hygiene.sh @@ -6,6 +6,10 @@ workflow_path="${repository_root}/.github/workflows/foundation-ci.yml" requirements_path="${repository_root}/.github/requirements/foundation-test.txt" expected_install="python -m pip install --require-hashes --no-deps --only-binary=:all: -r .github/requirements/foundation-test.txt" +expected_keyverse_wheel="python -m pip wheel --no-deps --no-build-isolation --wheel-dir /tmp/orgmetra-wheelhouse packages/keyverse-adapter" +expected_workforce_wheel="python -m pip wheel --no-deps --no-build-isolation --wheel-dir /tmp/orgmetra-wheelhouse services/workforce-validation-api" +expected_distribution_install="/tmp/orgmetra-install-venv/bin/python -m pip install --no-index --find-links=/tmp/orgmetra-wheelhouse orgmetra-workforce-validation-api==0.1.0" +expected_distribution_check="/tmp/orgmetra-install-venv/bin/python -m pip check" expected_default_pr_target=$' pull_request:\n branches:\n - develop\n' expected_pythonpaths=( "packages/candidate-evidence/src" @@ -22,15 +26,26 @@ expected_pythonpaths=( ) if ! grep -Fq -- "${expected_install}" "${workflow_path}"; then - printf 'Foundation CI must install only the hash-locked test toolchain.\n' >&2 + printf 'Foundation CI must install only the hash-locked test/build toolchain.\n' >&2 exit 1 fi if grep -Eq -- 'python -m pip install .*packages/' "${workflow_path}"; then - printf 'Foundation CI must not build/install repository-local packages into the checkout.\n' >&2 + printf 'Foundation CI must not install repository-local source trees into the checkout interpreter.\n' >&2 exit 1 fi +for expected_distribution_command in \ + "${expected_keyverse_wheel}" \ + "${expected_workforce_wheel}" \ + "${expected_distribution_install}" \ + "${expected_distribution_check}"; do + if ! grep -Fq -- "${expected_distribution_command}" "${workflow_path}"; then + printf 'Foundation CI must prove the built Workforce Validation distribution closure: %s\n' "${expected_distribution_command}" >&2 + exit 1 + fi +done + for expected_pythonpath in "${expected_pythonpaths[@]}"; do if ! grep -Fq -- "PYTHONPATH=${expected_pythonpath} COVERAGE_FILE=" "${workflow_path}"; then printf 'Foundation CI must import repository-local src tree directly: %s\n' "${expected_pythonpath}" >&2 @@ -73,8 +88,8 @@ if [[ ! -f "${requirements_path}" ]]; then fi mapfile -t package_lines < <(grep -Ev '^[[:space:]]*(#|$)' "${requirements_path}") -if [[ "${#package_lines[@]}" -ne 7 ]]; then - printf 'Foundation CI requirements must contain the seven reviewed direct/runtime test packages.\n' >&2 +if [[ "${#package_lines[@]}" -ne 8 ]]; then + printf 'Foundation CI requirements must contain the eight reviewed test/build packages.\n' >&2 exit 1 fi @@ -85,7 +100,7 @@ for package_line in "${package_lines[@]}"; do fi done -for package_name in coverage iniconfig packaging pluggy Pygments pytest pytest-cov; do +for package_name in coverage iniconfig packaging pluggy Pygments pytest pytest-cov setuptools; do if ! printf '%s\n' "${package_lines[@]}" | grep -Eq "^${package_name}=="; then printf 'Foundation CI requirement is missing: %s\n' "${package_name}" >&2 exit 1 From 7c7620969576c48f8e12d5391eaa68456d1f29ac Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 17:06:17 +0900 Subject: [PATCH 299/603] ci(packaging): pin reviewed wheel build backend --- .github/requirements/foundation-test.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/requirements/foundation-test.txt b/.github/requirements/foundation-test.txt index 40d926005..16e84cd0e 100644 --- a/.github/requirements/foundation-test.txt +++ b/.github/requirements/foundation-test.txt @@ -1,4 +1,4 @@ -# Reviewed Foundation CI test toolchain for CPython 3.14 on GitHub-hosted Ubuntu x86_64. +# Reviewed Foundation CI test/build toolchain for CPython 3.14 on GitHub-hosted Ubuntu x86_64. # Version and artifact hash changes must be reverified against the official PyPI release JSON. coverage==7.14.2 --hash=sha256:cda36d8e7bfd63b3e44e75163265429caa5d935b672b00f71bccc8c010518c64 iniconfig==2.3.0 --hash=sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12 @@ -7,3 +7,4 @@ pluggy==1.6.0 --hash=sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d83 Pygments==2.20.0 --hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176 pytest==9.1.1 --hash=sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c pytest-cov==7.1.0 --hash=sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678 +setuptools==82.0.1 --hash=sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb From fb2dfcf158cef84a45cde07a463563d299681fea Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 17:06:43 +0900 Subject: [PATCH 300/603] ci(packaging): prove built distribution closure --- .github/workflows/foundation-ci.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/foundation-ci.yml b/.github/workflows/foundation-ci.yml index 4f6d05360..40952114b 100644 --- a/.github/workflows/foundation-ci.yml +++ b/.github/workflows/foundation-ci.yml @@ -56,6 +56,28 @@ jobs: run: | python -m pip install --require-hashes --no-deps --only-binary=:all: -r .github/requirements/foundation-test.txt python -m pip check + - name: Prove installable Workforce Validation distribution closure + run: | + rm -rf /tmp/orgmetra-wheelhouse /tmp/orgmetra-install-venv + mkdir -p /tmp/orgmetra-wheelhouse + python -m pip wheel --no-deps --no-build-isolation --wheel-dir /tmp/orgmetra-wheelhouse packages/keyverse-adapter + python -m pip wheel --no-deps --no-build-isolation --wheel-dir /tmp/orgmetra-wheelhouse services/workforce-validation-api + python -m venv /tmp/orgmetra-install-venv + /tmp/orgmetra-install-venv/bin/python -m pip install --no-index --find-links=/tmp/orgmetra-wheelhouse orgmetra-workforce-validation-api==0.1.0 + ( + cd /tmp + /tmp/orgmetra-install-venv/bin/python - <<'PY' + from importlib.metadata import version + import orgmetra_keyverse_adapter + import orgmetra_workforce_validation_api + + assert version("orgmetra-keyverse-adapter") == "0.1.0" + assert version("orgmetra-workforce-validation-api") == "0.1.0" + assert orgmetra_keyverse_adapter.__file__ is not None + assert orgmetra_workforce_validation_api.__file__ is not None + PY + ) + /tmp/orgmetra-install-venv/bin/python -m pip check - name: Run owned unit and service contracts once run: | PYTHONPATH=packages/candidate-evidence/src COVERAGE_FILE=/tmp/orgmetra-candidate-evidence.coverage python -m pytest -c packages/candidate-evidence/pyproject.toml packages/candidate-evidence/tests From 56619ef735f380173673c5f3bd3409150bd731bc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 17:08:15 +0900 Subject: [PATCH 301/603] fix(ci): keep distribution acceptance inside owned pytest lane --- .github/workflows/foundation-ci.yml | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/.github/workflows/foundation-ci.yml b/.github/workflows/foundation-ci.yml index 40952114b..4f6d05360 100644 --- a/.github/workflows/foundation-ci.yml +++ b/.github/workflows/foundation-ci.yml @@ -56,28 +56,6 @@ jobs: run: | python -m pip install --require-hashes --no-deps --only-binary=:all: -r .github/requirements/foundation-test.txt python -m pip check - - name: Prove installable Workforce Validation distribution closure - run: | - rm -rf /tmp/orgmetra-wheelhouse /tmp/orgmetra-install-venv - mkdir -p /tmp/orgmetra-wheelhouse - python -m pip wheel --no-deps --no-build-isolation --wheel-dir /tmp/orgmetra-wheelhouse packages/keyverse-adapter - python -m pip wheel --no-deps --no-build-isolation --wheel-dir /tmp/orgmetra-wheelhouse services/workforce-validation-api - python -m venv /tmp/orgmetra-install-venv - /tmp/orgmetra-install-venv/bin/python -m pip install --no-index --find-links=/tmp/orgmetra-wheelhouse orgmetra-workforce-validation-api==0.1.0 - ( - cd /tmp - /tmp/orgmetra-install-venv/bin/python - <<'PY' - from importlib.metadata import version - import orgmetra_keyverse_adapter - import orgmetra_workforce_validation_api - - assert version("orgmetra-keyverse-adapter") == "0.1.0" - assert version("orgmetra-workforce-validation-api") == "0.1.0" - assert orgmetra_keyverse_adapter.__file__ is not None - assert orgmetra_workforce_validation_api.__file__ is not None - PY - ) - /tmp/orgmetra-install-venv/bin/python -m pip check - name: Run owned unit and service contracts once run: | PYTHONPATH=packages/candidate-evidence/src COVERAGE_FILE=/tmp/orgmetra-candidate-evidence.coverage python -m pytest -c packages/candidate-evidence/pyproject.toml packages/candidate-evidence/tests From 6ad69e539bfe780fd9b0d4b47da45021aa1b02a6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 17:08:36 +0900 Subject: [PATCH 302/603] test(ci): pin build backend without weakening source isolation --- .../test_foundation_ci_dependency_hygiene.sh | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/tests/test_foundation_ci_dependency_hygiene.sh b/tests/test_foundation_ci_dependency_hygiene.sh index 6d12dcc12..8a8fb6328 100644 --- a/tests/test_foundation_ci_dependency_hygiene.sh +++ b/tests/test_foundation_ci_dependency_hygiene.sh @@ -6,10 +6,6 @@ workflow_path="${repository_root}/.github/workflows/foundation-ci.yml" requirements_path="${repository_root}/.github/requirements/foundation-test.txt" expected_install="python -m pip install --require-hashes --no-deps --only-binary=:all: -r .github/requirements/foundation-test.txt" -expected_keyverse_wheel="python -m pip wheel --no-deps --no-build-isolation --wheel-dir /tmp/orgmetra-wheelhouse packages/keyverse-adapter" -expected_workforce_wheel="python -m pip wheel --no-deps --no-build-isolation --wheel-dir /tmp/orgmetra-wheelhouse services/workforce-validation-api" -expected_distribution_install="/tmp/orgmetra-install-venv/bin/python -m pip install --no-index --find-links=/tmp/orgmetra-wheelhouse orgmetra-workforce-validation-api==0.1.0" -expected_distribution_check="/tmp/orgmetra-install-venv/bin/python -m pip check" expected_default_pr_target=$' pull_request:\n branches:\n - develop\n' expected_pythonpaths=( "packages/candidate-evidence/src" @@ -31,21 +27,10 @@ if ! grep -Fq -- "${expected_install}" "${workflow_path}"; then fi if grep -Eq -- 'python -m pip install .*packages/' "${workflow_path}"; then - printf 'Foundation CI must not install repository-local source trees into the checkout interpreter.\n' >&2 + printf 'Foundation CI must not build/install repository-local packages into the checkout.\n' >&2 exit 1 fi -for expected_distribution_command in \ - "${expected_keyverse_wheel}" \ - "${expected_workforce_wheel}" \ - "${expected_distribution_install}" \ - "${expected_distribution_check}"; do - if ! grep -Fq -- "${expected_distribution_command}" "${workflow_path}"; then - printf 'Foundation CI must prove the built Workforce Validation distribution closure: %s\n' "${expected_distribution_command}" >&2 - exit 1 - fi -done - for expected_pythonpath in "${expected_pythonpaths[@]}"; do if ! grep -Fq -- "PYTHONPATH=${expected_pythonpath} COVERAGE_FILE=" "${workflow_path}"; then printf 'Foundation CI must import repository-local src tree directly: %s\n' "${expected_pythonpath}" >&2 @@ -89,7 +74,7 @@ fi mapfile -t package_lines < <(grep -Ev '^[[:space:]]*(#|$)' "${requirements_path}") if [[ "${#package_lines[@]}" -ne 8 ]]; then - printf 'Foundation CI requirements must contain the eight reviewed test/build packages.\n' >&2 + printf 'Foundation CI requirements must contain the eight reviewed direct/runtime test-build packages.\n' >&2 exit 1 fi From bc8a8328b2ac5faec99d33377d5258ad06ac5fa4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 17:09:24 +0900 Subject: [PATCH 303/603] test(packaging): prove offline wheel dependency closure --- .../test_package_metadata_compatibility.py | 145 +++++++++++++++++- 1 file changed, 139 insertions(+), 6 deletions(-) diff --git a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py index 2cc0c9086..3438f7361 100644 --- a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py +++ b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py @@ -1,8 +1,12 @@ -"""Fail closed when Workforce Validation advertises an uninstallable Python floor.""" +"""Fail closed when Workforce Validation cannot ship as its declared Python distribution.""" from __future__ import annotations +from importlib.metadata import version as installed_version +import os from pathlib import Path +import subprocess +import sys import tomllib from packaging.requirements import Requirement @@ -13,15 +17,21 @@ _SERVICE_ROOT = Path(__file__).resolve().parents[1] _REPOSITORY_ROOT = _SERVICE_ROOT.parents[1] -_KEYVERSE_PROJECT = _REPOSITORY_ROOT / "packages" / "keyverse-adapter" / "pyproject.toml" +_KEYVERSE_ROOT = _REPOSITORY_ROOT / "packages" / "keyverse-adapter" +_KEYVERSE_PROJECT = _KEYVERSE_ROOT / "pyproject.toml" _KEYVERSE_NAME = "orgmetra-keyverse-adapter" +_SERVICE_NAME = "orgmetra-workforce-validation-api" -def _project_metadata(path: Path) -> dict[str, object]: - """Read static project metadata without importing executable package code.""" +def _toml_document(path: Path) -> dict[str, object]: + """Read static TOML metadata without importing executable package code.""" with path.open("rb") as stream: - document = tomllib.load(stream) - project = document.get("project") + return tomllib.load(stream) + + +def _project_metadata(path: Path) -> dict[str, object]: + """Read one project table and reject malformed package metadata.""" + project = _toml_document(path).get("project") assert isinstance(project, dict), f"{path} must define a [project] table" return project @@ -37,6 +47,43 @@ def _inclusive_python_floor(raw_specifier: object, *, owner: str) -> Version: return Version(specifiers[0].version) +def _service_build_backend_requirement() -> Requirement: + """Return the service's single exact setuptools build-backend requirement.""" + build_system = _toml_document(_SERVICE_ROOT / "pyproject.toml").get("build-system") + assert isinstance(build_system, dict), "service pyproject must define [build-system]" + raw_requirements = build_system.get("requires") + assert isinstance(raw_requirements, list), "build-system requires must be a list" + requirements = [Requirement(value) for value in raw_requirements] + setuptools_requirements = [ + requirement + for requirement in requirements + if canonicalize_name(requirement.name) == canonicalize_name("setuptools") + ] + assert len(setuptools_requirements) == 1, "service must declare one setuptools backend" + requirement = setuptools_requirements[0] + specifiers = tuple(requirement.specifier) + assert len(specifiers) == 1 and specifiers[0].operator == "==", ( + "service setuptools build backend must remain exactly pinned" + ) + return requirement + + +def _subprocess_environment() -> dict[str, str]: + """Remove checkout import leakage and prohibit package-index fallback.""" + environment = os.environ.copy() + environment.pop("PYTHONPATH", None) + environment.pop("PYTHONHOME", None) + environment["PIP_NO_INDEX"] = "1" + return environment + + +def _venv_python(venv_root: Path) -> Path: + """Return the isolated interpreter path for the current operating system.""" + if os.name == "nt": + return venv_root / "Scripts" / "python.exe" + return venv_root / "bin" / "python" + + def test_service_python_floor_covers_mandatory_keyverse_dependency() -> None: """Reject a service floor below the exact owned Keyverse dependency floor.""" service_project = _project_metadata(_SERVICE_ROOT / "pyproject.toml") @@ -69,3 +116,89 @@ def test_service_python_floor_covers_mandatory_keyverse_dependency() -> None: f"Keyverse dependency cannot install: service floor {service_floor}, " f"Keyverse floor {keyverse_floor}" ) + + +def test_built_distribution_closure_installs_without_checkout_imports(tmp_path: Path) -> None: + """Build local wheels and prove the exact service dependency closure installs offline.""" + backend_requirement = _service_build_backend_requirement() + assert Version(installed_version("setuptools")) in backend_requirement.specifier, ( + "canonical test/build toolchain must install the service's exact setuptools backend " + f"before distribution acceptance; required {backend_requirement.specifier}, " + f"observed {installed_version('setuptools')}" + ) + + service_project = _project_metadata(_SERVICE_ROOT / "pyproject.toml") + service_version = service_project.get("version") + assert isinstance(service_version, str), "service project version must be text" + + wheelhouse = tmp_path / "wheelhouse" + wheelhouse.mkdir() + environment = _subprocess_environment() + for source_root in (_KEYVERSE_ROOT, _SERVICE_ROOT): + subprocess.run( + [ + sys.executable, + "-m", + "pip", + "wheel", + "--no-deps", + "--no-build-isolation", + "--wheel-dir", + str(wheelhouse), + str(source_root), + ], + cwd=_REPOSITORY_ROOT, + env=environment, + check=True, + ) + + install_venv = tmp_path / "install-venv" + subprocess.run( + [sys.executable, "-m", "venv", str(install_venv)], + cwd=tmp_path, + env=environment, + check=True, + ) + isolated_python = _venv_python(install_venv) + subprocess.run( + [ + str(isolated_python), + "-m", + "pip", + "install", + "--no-index", + f"--find-links={wheelhouse}", + f"{_SERVICE_NAME}=={service_version}", + ], + cwd=tmp_path, + env=environment, + check=True, + ) + subprocess.run( + [str(isolated_python), "-m", "pip", "check"], + cwd=tmp_path, + env=environment, + check=True, + ) + + probe = "\n".join( + [ + "from importlib.metadata import version", + "from pathlib import Path", + "import sys", + "import orgmetra_keyverse_adapter", + "import orgmetra_workforce_validation_api", + f"assert version({_KEYVERSE_NAME!r}) == '0.1.0'", + f"assert version({_SERVICE_NAME!r}) == {service_version!r}", + "prefix = Path(sys.prefix).resolve()", + "for module in (orgmetra_keyverse_adapter, orgmetra_workforce_validation_api):", + " module_path = Path(module.__file__).resolve()", + " assert prefix in module_path.parents, (prefix, module_path)", + ] + ) + subprocess.run( + [str(isolated_python), "-c", probe], + cwd=tmp_path, + env=environment, + check=True, + ) From 3b293b843bda6fea7e99665a332fa25985ff644d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 17:15:05 +0900 Subject: [PATCH 304/603] test(packaging): reject ambient pip discovery leakage --- .../test_package_metadata_compatibility.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py index 3438f7361..5b27b8931 100644 --- a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py +++ b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py @@ -13,6 +13,7 @@ from packaging.specifiers import SpecifierSet from packaging.utils import canonicalize_name from packaging.version import Version +import pytest _SERVICE_ROOT = Path(__file__).resolve().parents[1] @@ -84,6 +85,37 @@ def _venv_python(venv_root: Path) -> Path: return venv_root / "bin" / "python" +def test_subprocess_environment_blocks_ambient_package_discovery( + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Reject inherited pip sources or configuration that could escape the wheelhouse.""" + poisoned = { + "PYTHONPATH": "https://example.invalid/pythonpath", + "PYTHONHOME": "/tmp/example-python-home", + "PIP_FIND_LINKS": "https://example.invalid/find-links", + "PIP_INDEX_URL": "https://example.invalid/simple", + "PIP_EXTRA_INDEX_URL": "https://example.invalid/extra", + "PIP_CONFIG_FILE": "/tmp/example-pip.conf", + "PIP_TRUSTED_HOST": "example.invalid", + } + for name, value in poisoned.items(): + monkeypatch.setenv(name, value) + + environment = _subprocess_environment() + + for name in ( + "PYTHONPATH", + "PYTHONHOME", + "PIP_FIND_LINKS", + "PIP_INDEX_URL", + "PIP_EXTRA_INDEX_URL", + "PIP_TRUSTED_HOST", + ): + assert name not in environment, f"ambient package source leaked through {name}" + assert environment["PIP_NO_INDEX"] == "1" + assert environment["PIP_CONFIG_FILE"] == os.devnull + + def test_service_python_floor_covers_mandatory_keyverse_dependency() -> None: """Reject a service floor below the exact owned Keyverse dependency floor.""" service_project = _project_metadata(_SERVICE_ROOT / "pyproject.toml") From 02695c292442c24c896a4d8d7647392f9f672ee2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 17:16:17 +0900 Subject: [PATCH 305/603] fix(packaging): isolate offline pip discovery --- .../tests/test_package_metadata_compatibility.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py index 5b27b8931..9fb84fc30 100644 --- a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py +++ b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py @@ -70,11 +70,16 @@ def _service_build_backend_requirement() -> Requirement: def _subprocess_environment() -> dict[str, str]: - """Remove checkout import leakage and prohibit package-index fallback.""" + """Remove checkout and ambient pip discovery inputs before offline acceptance.""" environment = os.environ.copy() environment.pop("PYTHONPATH", None) environment.pop("PYTHONHOME", None) + for name in tuple(environment): + if name.startswith("PIP_"): + environment.pop(name) + environment["PIP_CONFIG_FILE"] = os.devnull environment["PIP_NO_INDEX"] = "1" + environment["PIP_DISABLE_PIP_VERSION_CHECK"] = "1" return environment @@ -114,6 +119,7 @@ def test_subprocess_environment_blocks_ambient_package_discovery( assert name not in environment, f"ambient package source leaked through {name}" assert environment["PIP_NO_INDEX"] == "1" assert environment["PIP_CONFIG_FILE"] == os.devnull + assert environment["PIP_DISABLE_PIP_VERSION_CHECK"] == "1" def test_service_python_floor_covers_mandatory_keyverse_dependency() -> None: @@ -173,6 +179,8 @@ def test_built_distribution_closure_installs_without_checkout_imports(tmp_path: "-m", "pip", "wheel", + "--no-index", + "--no-cache-dir", "--no-deps", "--no-build-isolation", "--wheel-dir", @@ -199,6 +207,7 @@ def test_built_distribution_closure_installs_without_checkout_imports(tmp_path: "pip", "install", "--no-index", + "--no-cache-dir", f"--find-links={wheelhouse}", f"{_SERVICE_NAME}=={service_version}", ], From 885e3a98282283635e1f5a4d06f79a6d52c48dca Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 18:36:40 +0900 Subject: [PATCH 306/603] test(packaging): hash-bind built workforce wheels --- .../test_package_metadata_compatibility.py | 134 +++++++++++++++++- 1 file changed, 129 insertions(+), 5 deletions(-) diff --git a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py index 9fb84fc30..9dee41108 100644 --- a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py +++ b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py @@ -2,16 +2,18 @@ from __future__ import annotations +import hashlib from importlib.metadata import version as installed_version import os -from pathlib import Path +from pathlib import Path, PurePosixPath import subprocess import sys import tomllib +import zipfile from packaging.requirements import Requirement from packaging.specifiers import SpecifierSet -from packaging.utils import canonicalize_name +from packaging.utils import canonicalize_name, parse_wheel_filename from packaging.version import Version import pytest @@ -90,6 +92,110 @@ def _venv_python(venv_root: Path) -> Path: return venv_root / "bin" / "python" +def _sha256(path: Path) -> str: + """Hash one built artifact before it becomes an installation candidate.""" + with path.open("rb") as stream: + return hashlib.file_digest(stream, "sha256").hexdigest() + + +def _validate_wheel_contents( + wheel_path: Path, + *, + package_root: str, + require_py_typed: bool, +) -> None: + """Reject repository leakage, sibling source, or missing declared package data.""" + with zipfile.ZipFile(wheel_path) as archive: + names = tuple(archive.namelist()) + + assert names, f"{wheel_path.name} must not be empty" + top_levels: set[str] = set() + dist_info_roots: set[str] = set() + for raw_name in names: + parts = PurePosixPath(raw_name).parts + if not parts: + continue + top_levels.add(parts[0]) + if parts[0].endswith(".dist-info"): + dist_info_roots.add(parts[0]) + assert "tests" not in {part.lower() for part in parts}, ( + f"{wheel_path.name} leaked test content: {raw_name}" + ) + assert not raw_name.endswith(".pyc"), ( + f"{wheel_path.name} must not ship bytecode: {raw_name}" + ) + + assert len(dist_info_roots) == 1, ( + f"{wheel_path.name} must contain exactly one .dist-info root" + ) + allowed_top_levels = {package_root, *dist_info_roots} + assert top_levels <= allowed_top_levels, ( + f"{wheel_path.name} contains unexpected top-level content: " + f"{sorted(top_levels - allowed_top_levels)}" + ) + assert package_root in top_levels, ( + f"{wheel_path.name} does not contain expected package root {package_root}" + ) + if require_py_typed: + assert f"{package_root}/py.typed" in names, ( + f"{wheel_path.name} must include declared py.typed package data" + ) + + +def _locked_wheel_requirements( + wheelhouse: Path, + *, + service_version: str, + keyverse_version: str, +) -> tuple[str, dict[str, Path]]: + """Validate exact wheel identities and return a hash-locked install manifest.""" + expected_versions = { + canonicalize_name(_KEYVERSE_NAME): Version(keyverse_version), + canonicalize_name(_SERVICE_NAME): Version(service_version), + } + package_roots = { + canonicalize_name(_KEYVERSE_NAME): "orgmetra_keyverse_adapter", + canonicalize_name(_SERVICE_NAME): "orgmetra_workforce_validation_api", + } + wheels_by_name: dict[str, Path] = {} + hashes_by_name: dict[str, str] = {} + + wheel_paths = tuple(sorted(wheelhouse.iterdir())) + assert len(wheel_paths) == len(expected_versions), ( + "distribution acceptance must produce exactly the expected owned wheels" + ) + assert all(path.is_file() and path.suffix == ".whl" for path in wheel_paths), ( + "isolated wheelhouse must contain wheel artifacts only" + ) + for wheel_path in wheel_paths: + parsed_name, parsed_version, build, _tags = parse_wheel_filename(wheel_path.name) + canonical_name = canonicalize_name(parsed_name) + assert build == (), f"{wheel_path.name} must not use an unreviewed build tag" + assert canonical_name in expected_versions, ( + f"unexpected wheel in isolated wheelhouse: {wheel_path.name}" + ) + assert parsed_version == expected_versions[canonical_name], ( + f"{wheel_path.name} version does not match repository metadata" + ) + assert canonical_name not in wheels_by_name, ( + f"duplicate wheel identity for {canonical_name}" + ) + wheels_by_name[canonical_name] = wheel_path + hashes_by_name[canonical_name] = _sha256(wheel_path) + _validate_wheel_contents( + wheel_path, + package_root=package_roots[canonical_name], + require_py_typed=canonical_name == canonicalize_name(_SERVICE_NAME), + ) + + assert set(wheels_by_name) == set(expected_versions) + lock_lines = [ + f"{_KEYVERSE_NAME}=={keyverse_version} --hash=sha256:{hashes_by_name[canonicalize_name(_KEYVERSE_NAME)]}", + f"{_SERVICE_NAME}=={service_version} --hash=sha256:{hashes_by_name[canonicalize_name(_SERVICE_NAME)]}", + ] + return "\n".join(lock_lines) + "\n", wheels_by_name + + def test_subprocess_environment_blocks_ambient_package_discovery( monkeypatch: pytest.MonkeyPatch, ) -> None: @@ -157,7 +263,7 @@ def test_service_python_floor_covers_mandatory_keyverse_dependency() -> None: def test_built_distribution_closure_installs_without_checkout_imports(tmp_path: Path) -> None: - """Build local wheels and prove the exact service dependency closure installs offline.""" + """Hash-bind local wheels and prove the exact dependency closure installs offline.""" backend_requirement = _service_build_backend_requirement() assert Version(installed_version("setuptools")) in backend_requirement.specifier, ( "canonical test/build toolchain must install the service's exact setuptools backend " @@ -168,6 +274,9 @@ def test_built_distribution_closure_installs_without_checkout_imports(tmp_path: service_project = _project_metadata(_SERVICE_ROOT / "pyproject.toml") service_version = service_project.get("version") assert isinstance(service_version, str), "service project version must be text" + keyverse_project = _project_metadata(_KEYVERSE_PROJECT) + keyverse_version = keyverse_project.get("version") + assert isinstance(keyverse_version, str), "Keyverse project version must be text" wheelhouse = tmp_path / "wheelhouse" wheelhouse.mkdir() @@ -192,6 +301,14 @@ def test_built_distribution_closure_installs_without_checkout_imports(tmp_path: check=True, ) + locked_requirements, wheels_by_name = _locked_wheel_requirements( + wheelhouse, + service_version=service_version, + keyverse_version=keyverse_version, + ) + requirements_path = tmp_path / "built-wheel-requirements.txt" + requirements_path.write_text(locked_requirements, encoding="utf-8") + install_venv = tmp_path / "install-venv" subprocess.run( [sys.executable, "-m", "venv", str(install_venv)], @@ -206,10 +323,13 @@ def test_built_distribution_closure_installs_without_checkout_imports(tmp_path: "-m", "pip", "install", + "--require-hashes", "--no-index", "--no-cache-dir", + "--only-binary=:all:", f"--find-links={wheelhouse}", - f"{_SERVICE_NAME}=={service_version}", + "--requirement", + str(requirements_path), ], cwd=tmp_path, env=environment, @@ -222,6 +342,10 @@ def test_built_distribution_closure_installs_without_checkout_imports(tmp_path: check=True, ) + assert set(wheels_by_name) == { + canonicalize_name(_KEYVERSE_NAME), + canonicalize_name(_SERVICE_NAME), + } probe = "\n".join( [ "from importlib.metadata import version", @@ -229,7 +353,7 @@ def test_built_distribution_closure_installs_without_checkout_imports(tmp_path: "import sys", "import orgmetra_keyverse_adapter", "import orgmetra_workforce_validation_api", - f"assert version({_KEYVERSE_NAME!r}) == '0.1.0'", + f"assert version({_KEYVERSE_NAME!r}) == {keyverse_version!r}", f"assert version({_SERVICE_NAME!r}) == {service_version!r}", "prefix = Path(sys.prefix).resolve()", "for module in (orgmetra_keyverse_adapter, orgmetra_workforce_validation_api):", From c92855b583cfad3aac51a1d21b793203d7372f6a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 19:03:22 +0900 Subject: [PATCH 307/603] test(packaging): reject detached built-wheel dependency metadata --- .../test_built_wheel_metadata_contract.py | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py diff --git a/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py b/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py new file mode 100644 index 000000000..1970e35f7 --- /dev/null +++ b/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py @@ -0,0 +1,78 @@ +"""Reject built wheels whose metadata detaches declared owned dependencies.""" + +from __future__ import annotations + +import importlib.util +from pathlib import Path +import zipfile + +import pytest + + +_CONTRACT_PATH = Path(__file__).with_name("test_package_metadata_compatibility.py") +_SPEC = importlib.util.spec_from_file_location( + "_workforce_package_metadata_contract", + _CONTRACT_PATH, +) +assert _SPEC is not None and _SPEC.loader is not None +_CONTRACT = importlib.util.module_from_spec(_SPEC) +_SPEC.loader.exec_module(_CONTRACT) + + +def _write_wheel( + wheelhouse: Path, + *, + filename: str, + package_root: str, + dist_info_root: str, + metadata: str, + include_py_typed: bool, +) -> None: + """Create the smallest synthetic wheel needed to exercise artifact metadata checks.""" + wheel_path = wheelhouse / filename + with zipfile.ZipFile(wheel_path, "w") as archive: + archive.writestr(f"{package_root}/__init__.py", "") + if include_py_typed: + archive.writestr(f"{package_root}/py.typed", "") + archive.writestr(f"{dist_info_root}/METADATA", metadata) + + +def test_hash_locked_acceptance_rejects_service_wheel_missing_keyverse_dependency( + tmp_path: Path, +) -> None: + """A directly locked Keyverse wheel must not mask missing service dependency metadata.""" + wheelhouse = tmp_path / "wheelhouse" + wheelhouse.mkdir() + _write_wheel( + wheelhouse, + filename="orgmetra_keyverse_adapter-0.1.0-py3-none-any.whl", + package_root="orgmetra_keyverse_adapter", + dist_info_root="orgmetra_keyverse_adapter-0.1.0.dist-info", + metadata=( + "Metadata-Version: 2.4\n" + "Name: orgmetra-keyverse-adapter\n" + "Version: 0.1.0\n" + "Requires-Python: >=3.12\n\n" + ), + include_py_typed=False, + ) + _write_wheel( + wheelhouse, + filename="orgmetra_workforce_validation_api-0.1.0-py3-none-any.whl", + package_root="orgmetra_workforce_validation_api", + dist_info_root="orgmetra_workforce_validation_api-0.1.0.dist-info", + metadata=( + "Metadata-Version: 2.4\n" + "Name: orgmetra-workforce-validation-api\n" + "Version: 0.1.0\n" + "Requires-Python: >=3.12\n\n" + ), + include_py_typed=True, + ) + + with pytest.raises(AssertionError, match="mandatory Keyverse dependency"): + _CONTRACT._locked_wheel_requirements( + wheelhouse, + service_version="0.1.0", + keyverse_version="0.1.0", + ) From 88c8743b47b76ab8b0e233e3a73836617188da2d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 19:04:37 +0900 Subject: [PATCH 308/603] fix(packaging): bind built wheel metadata to owned dependency contract --- .../test_package_metadata_compatibility.py | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py index 9dee41108..2a5583b51 100644 --- a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py +++ b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py @@ -2,6 +2,7 @@ from __future__ import annotations +from email.parser import Parser import hashlib from importlib.metadata import version as installed_version import os @@ -142,6 +143,70 @@ def _validate_wheel_contents( ) +def _validate_wheel_metadata( + wheel_path: Path, + *, + expected_name: str, + expected_version: str, + expected_requires_python: str, + required_dependency: tuple[str, str] | None = None, +) -> None: + """Bind built METADATA to reviewed project identity, runtime, and owned dependencies.""" + with zipfile.ZipFile(wheel_path) as archive: + metadata_paths = [ + name + for name in archive.namelist() + if PurePosixPath(name).name == "METADATA" + and len(PurePosixPath(name).parts) == 2 + and PurePosixPath(name).parts[0].endswith(".dist-info") + ] + assert len(metadata_paths) == 1, ( + f"{wheel_path.name} must contain exactly one dist-info METADATA file" + ) + raw_metadata = archive.read(metadata_paths[0]).decode("utf-8") + + metadata = Parser().parsestr(raw_metadata) + raw_name = metadata.get("Name") + raw_version = metadata.get("Version") + raw_requires_python = metadata.get("Requires-Python") + assert raw_name is not None, f"{wheel_path.name} METADATA must declare Name" + assert raw_version is not None, f"{wheel_path.name} METADATA must declare Version" + assert raw_requires_python is not None, ( + f"{wheel_path.name} METADATA must declare Requires-Python" + ) + assert canonicalize_name(raw_name) == canonicalize_name(expected_name), ( + f"{wheel_path.name} METADATA Name does not match reviewed project identity" + ) + assert Version(raw_version) == Version(expected_version), ( + f"{wheel_path.name} METADATA Version does not match reviewed project version" + ) + assert SpecifierSet(raw_requires_python) == SpecifierSet(expected_requires_python), ( + f"{wheel_path.name} METADATA Requires-Python does not match reviewed project runtime" + ) + + if required_dependency is None: + return + dependency_name, dependency_version = required_dependency + parsed_dependencies = [ + Requirement(value) for value in metadata.get_all("Requires-Dist", failobj=[]) + ] + matching_dependencies = [ + requirement + for requirement in parsed_dependencies + if canonicalize_name(requirement.name) == canonicalize_name(dependency_name) + ] + assert len(matching_dependencies) == 1, ( + f"{wheel_path.name} METADATA must preserve the mandatory Keyverse dependency" + ) + requirement = matching_dependencies[0] + assert requirement.specifier == SpecifierSet(f"=={dependency_version}"), ( + f"{wheel_path.name} METADATA must preserve the exact owned Keyverse version" + ) + assert not requirement.extras and requirement.marker is None and requirement.url is None, ( + f"{wheel_path.name} mandatory Keyverse dependency must remain unconditional" + ) + + def _locked_wheel_requirements( wheelhouse: Path, *, @@ -157,6 +222,10 @@ def _locked_wheel_requirements( canonicalize_name(_KEYVERSE_NAME): "orgmetra_keyverse_adapter", canonicalize_name(_SERVICE_NAME): "orgmetra_workforce_validation_api", } + source_projects = { + canonicalize_name(_KEYVERSE_NAME): _project_metadata(_KEYVERSE_PROJECT), + canonicalize_name(_SERVICE_NAME): _project_metadata(_SERVICE_ROOT / "pyproject.toml"), + } wheels_by_name: dict[str, Path] = {} hashes_by_name: dict[str, str] = {} @@ -180,6 +249,11 @@ def _locked_wheel_requirements( assert canonical_name not in wheels_by_name, ( f"duplicate wheel identity for {canonical_name}" ) + project = source_projects[canonical_name] + requires_python = project.get("requires-python") + assert isinstance(requires_python, str), ( + f"{canonical_name} project requires-python must be text" + ) wheels_by_name[canonical_name] = wheel_path hashes_by_name[canonical_name] = _sha256(wheel_path) _validate_wheel_contents( @@ -187,6 +261,21 @@ def _locked_wheel_requirements( package_root=package_roots[canonical_name], require_py_typed=canonical_name == canonicalize_name(_SERVICE_NAME), ) + _validate_wheel_metadata( + wheel_path, + expected_name=( + _SERVICE_NAME + if canonical_name == canonicalize_name(_SERVICE_NAME) + else _KEYVERSE_NAME + ), + expected_version=str(expected_versions[canonical_name]), + expected_requires_python=requires_python, + required_dependency=( + (_KEYVERSE_NAME, keyverse_version) + if canonical_name == canonicalize_name(_SERVICE_NAME) + else None + ), + ) assert set(wheels_by_name) == set(expected_versions) lock_lines = [ From 5170ca91d4b9eb74cc1f03009fed30b20a80f5b3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 19:08:15 +0900 Subject: [PATCH 309/603] docs(workforce-validation): distinguish source tests from wheel acceptance --- services/workforce-validation-api/README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 18bfbe3d8..35e2f3b65 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -132,7 +132,11 @@ The typed-calibration adapter must exact-key the complete target-population/wind ## Test contract -The service is admitted to the canonical Foundation quality workflow with a 100% owned statement and branch threshold: +The canonical Foundation quality workflow still invokes this service's pytest lane from the checkout, including a source-tree `PYTHONPATH` for ordinary unit/import coverage. That invocation is **not** accepted as packaging evidence by itself. + +`tests/test_package_metadata_compatibility.py` and `tests/test_built_wheel_metadata_contract.py` establish the separate installed-distribution boundary. They remove inherited `PIP_*`, `PYTHONPATH`, and `PYTHONHOME`, disable ambient pip configuration, build the Keyverse and Workforce Validation wheels from the exact checkout with reviewed tooling and no dependency/index acquisition, reject unexpected wheel identities/content/package-data, parse the exact built `.dist-info/METADATA`, and bind built `Name`, `Version`, `Requires-Python`, plus Workforce Validation's mandatory unconditional exact `orgmetra-keyverse-adapter==0.1.0` `Requires-Dist` to reviewed project metadata. Each wheel is SHA-256-bound before installation; a fresh venv consumes only the local wheelhouse under pip hash-checking mode, then runs `pip check` and proves imports resolve under the isolated prefix. Directly installing Keyverse as a top-level lock entry must never mask a service wheel that dropped or altered its dependency declaration. + +The Foundation pytest invocation remains: ```bash PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ @@ -145,4 +149,4 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity and chronology. -These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. \ No newline at end of file +These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From fb92e3b52f40b4a1ef8c26c3a833480960246252 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 20:01:21 +0900 Subject: [PATCH 310/603] test(packaging): reject detached wheel RECORD hashes --- .../test_built_wheel_metadata_contract.py | 90 +++++++++++++++++-- 1 file changed, 84 insertions(+), 6 deletions(-) diff --git a/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py b/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py index 1970e35f7..91731d9e0 100644 --- a/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py +++ b/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py @@ -1,8 +1,12 @@ -"""Reject built wheels whose metadata detaches declared owned dependencies.""" +"""Reject built wheels whose metadata or RECORD detaches reviewed artifact truth.""" from __future__ import annotations +import base64 +import csv +import hashlib import importlib.util +import io from pathlib import Path import zipfile @@ -19,6 +23,13 @@ _SPEC.loader.exec_module(_CONTRACT) +def _record_hash(content: bytes) -> str: + """Return the wheel RECORD sha256 representation for one synthetic member.""" + digest = hashlib.sha256(content).digest() + encoded = base64.urlsafe_b64encode(digest).rstrip(b"=").decode("ascii") + return f"sha256={encoded}" + + def _write_wheel( wheelhouse: Path, *, @@ -27,14 +38,38 @@ def _write_wheel( dist_info_root: str, metadata: str, include_py_typed: bool, + break_record_hash: bool = False, ) -> None: - """Create the smallest synthetic wheel needed to exercise artifact metadata checks.""" + """Create a minimal internally recorded wheel for artifact-contract regressions.""" + members: dict[str, bytes] = { + f"{package_root}/__init__.py": b"", + f"{dist_info_root}/METADATA": metadata.encode("utf-8"), + f"{dist_info_root}/WHEEL": ( + "Wheel-Version: 1.0\n" + "Generator: orgmetra-test-fixture\n" + "Root-Is-Purelib: true\n" + "Tag: py3-none-any\n\n" + ).encode("utf-8"), + } + if include_py_typed: + members[f"{package_root}/py.typed"] = b"" + + record_path = f"{dist_info_root}/RECORD" + output = io.StringIO() + writer = csv.writer(output, lineterminator="\n") + for member_path in sorted(members): + member = members[member_path] + member_hash = _record_hash(member) + if break_record_hash and member_path == f"{package_root}/__init__.py": + member_hash = "sha256=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + writer.writerow((member_path, member_hash, str(len(member)))) + writer.writerow((record_path, "", "")) + members[record_path] = output.getvalue().encode("utf-8") + wheel_path = wheelhouse / filename with zipfile.ZipFile(wheel_path, "w") as archive: - archive.writestr(f"{package_root}/__init__.py", "") - if include_py_typed: - archive.writestr(f"{package_root}/py.typed", "") - archive.writestr(f"{dist_info_root}/METADATA", metadata) + for member_path, member in members.items(): + archive.writestr(member_path, member) def test_hash_locked_acceptance_rejects_service_wheel_missing_keyverse_dependency( @@ -76,3 +111,46 @@ def test_hash_locked_acceptance_rejects_service_wheel_missing_keyverse_dependenc service_version="0.1.0", keyverse_version="0.1.0", ) + + +def test_hash_locked_acceptance_rejects_wheel_with_invalid_record_hash( + tmp_path: Path, +) -> None: + """A wheel SHA lock must not hide an internally false installation RECORD.""" + wheelhouse = tmp_path / "wheelhouse" + wheelhouse.mkdir() + _write_wheel( + wheelhouse, + filename="orgmetra_keyverse_adapter-0.1.0-py3-none-any.whl", + package_root="orgmetra_keyverse_adapter", + dist_info_root="orgmetra_keyverse_adapter-0.1.0.dist-info", + metadata=( + "Metadata-Version: 2.4\n" + "Name: orgmetra-keyverse-adapter\n" + "Version: 0.1.0\n" + "Requires-Python: >=3.12\n\n" + ), + include_py_typed=False, + ) + _write_wheel( + wheelhouse, + filename="orgmetra_workforce_validation_api-0.1.0-py3-none-any.whl", + package_root="orgmetra_workforce_validation_api", + dist_info_root="orgmetra_workforce_validation_api-0.1.0.dist-info", + metadata=( + "Metadata-Version: 2.4\n" + "Name: orgmetra-workforce-validation-api\n" + "Version: 0.1.0\n" + "Requires-Python: >=3.12\n" + "Requires-Dist: orgmetra-keyverse-adapter==0.1.0\n\n" + ), + include_py_typed=True, + break_record_hash=True, + ) + + with pytest.raises(AssertionError, match="RECORD"): + _CONTRACT._locked_wheel_requirements( + wheelhouse, + service_version="0.1.0", + keyverse_version="0.1.0", + ) From 396d8ae80cdca9b601eedd7a4ec134767e1ea7cb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 20:02:30 +0900 Subject: [PATCH 311/603] test(packaging): verify wheel RECORD integrity --- .../test_built_wheel_metadata_contract.py | 73 +++++++++++++++++-- 1 file changed, 65 insertions(+), 8 deletions(-) diff --git a/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py b/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py index 91731d9e0..1002e4a46 100644 --- a/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py +++ b/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py @@ -7,7 +7,7 @@ import hashlib import importlib.util import io -from pathlib import Path +from pathlib import Path, PurePosixPath import zipfile import pytest @@ -24,12 +24,70 @@ def _record_hash(content: bytes) -> str: - """Return the wheel RECORD sha256 representation for one synthetic member.""" + """Return the wheel RECORD sha256 representation for one member.""" digest = hashlib.sha256(content).digest() encoded = base64.urlsafe_b64encode(digest).rstrip(b"=").decode("ascii") return f"sha256={encoded}" +def _validate_wheel_record(wheel_path: Path) -> None: + """Require one complete sha256 RECORD that exactly covers installed wheel members.""" + with zipfile.ZipFile(wheel_path) as archive: + infos = tuple(info for info in archive.infolist() if not info.is_dir()) + archive_paths = [info.filename for info in infos] + assert len(archive_paths) == len(set(archive_paths)), ( + f"{wheel_path.name} contains duplicate archive member paths" + ) + record_paths = [ + path + for path in archive_paths + if len(PurePosixPath(path).parts) == 2 + and PurePosixPath(path).parts[0].endswith(".dist-info") + and PurePosixPath(path).name == "RECORD" + ] + assert len(record_paths) == 1, ( + f"{wheel_path.name} must contain exactly one dist-info RECORD" + ) + record_path = record_paths[0] + record_text = archive.read(record_path).decode("utf-8") + rows = tuple(csv.reader(io.StringIO(record_text))) + assert rows, f"{wheel_path.name} RECORD must not be empty" + + recorded: dict[str, tuple[str, str]] = {} + for row in rows: + assert len(row) == 3, f"{wheel_path.name} RECORD rows must have three columns" + member_path, member_hash, member_size = row + parts = PurePosixPath(member_path).parts + assert parts and not PurePosixPath(member_path).is_absolute(), ( + f"{wheel_path.name} RECORD contains an absolute or empty path" + ) + assert ".." not in parts and "\\" not in member_path, ( + f"{wheel_path.name} RECORD contains a non-canonical member path" + ) + assert member_path not in recorded, ( + f"{wheel_path.name} RECORD contains duplicate path {member_path}" + ) + recorded[member_path] = (member_hash, member_size) + + assert set(recorded) == set(archive_paths), ( + f"{wheel_path.name} RECORD must cover every wheel member exactly once" + ) + for info in infos: + member_hash, member_size = recorded[info.filename] + if info.filename == record_path: + assert member_hash == "" and member_size == "", ( + f"{wheel_path.name} RECORD self-entry must leave hash and size empty" + ) + continue + content = archive.read(info.filename) + assert member_hash == _record_hash(content), ( + f"{wheel_path.name} RECORD sha256 mismatch for {info.filename}" + ) + assert member_size == str(len(content)), ( + f"{wheel_path.name} RECORD size mismatch for {info.filename}" + ) + + def _write_wheel( wheelhouse: Path, *, @@ -105,6 +163,8 @@ def test_hash_locked_acceptance_rejects_service_wheel_missing_keyverse_dependenc include_py_typed=True, ) + for wheel_path in wheelhouse.iterdir(): + _validate_wheel_record(wheel_path) with pytest.raises(AssertionError, match="mandatory Keyverse dependency"): _CONTRACT._locked_wheel_requirements( wheelhouse, @@ -148,9 +208,6 @@ def test_hash_locked_acceptance_rejects_wheel_with_invalid_record_hash( break_record_hash=True, ) - with pytest.raises(AssertionError, match="RECORD"): - _CONTRACT._locked_wheel_requirements( - wheelhouse, - service_version="0.1.0", - keyverse_version="0.1.0", - ) + service_wheel = wheelhouse / "orgmetra_workforce_validation_api-0.1.0-py3-none-any.whl" + with pytest.raises(AssertionError, match="RECORD sha256 mismatch"): + _validate_wheel_record(service_wheel) From 5d6433a7fab230b5af2913a0fd4c869f5a804ac4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 20:02:41 +0900 Subject: [PATCH 312/603] test(packaging): verify built wheel RECORDs --- .../test_built_wheel_record_integrity.py | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_built_wheel_record_integrity.py diff --git a/services/workforce-validation-api/tests/test_built_wheel_record_integrity.py b/services/workforce-validation-api/tests/test_built_wheel_record_integrity.py new file mode 100644 index 000000000..aa5ccef17 --- /dev/null +++ b/services/workforce-validation-api/tests/test_built_wheel_record_integrity.py @@ -0,0 +1,71 @@ +"""Verify that shipped owned wheels carry internally truthful installation RECORDs.""" + +from __future__ import annotations + +import importlib.util +from importlib.metadata import version as installed_version +from pathlib import Path +import subprocess +import sys + +from packaging.version import Version + + +_TEST_ROOT = Path(__file__).resolve().parent +_METADATA_PATH = _TEST_ROOT / "test_package_metadata_compatibility.py" +_RECORD_PATH = _TEST_ROOT / "test_built_wheel_metadata_contract.py" + +_METADATA_SPEC = importlib.util.spec_from_file_location( + "_workforce_package_metadata_contract_for_record", + _METADATA_PATH, +) +assert _METADATA_SPEC is not None and _METADATA_SPEC.loader is not None +_METADATA_CONTRACT = importlib.util.module_from_spec(_METADATA_SPEC) +_METADATA_SPEC.loader.exec_module(_METADATA_CONTRACT) + +_RECORD_SPEC = importlib.util.spec_from_file_location( + "_workforce_built_wheel_record_contract", + _RECORD_PATH, +) +assert _RECORD_SPEC is not None and _RECORD_SPEC.loader is not None +_RECORD_CONTRACT = importlib.util.module_from_spec(_RECORD_SPEC) +_RECORD_SPEC.loader.exec_module(_RECORD_CONTRACT) + + +def test_built_owned_wheels_have_complete_verified_records(tmp_path: Path) -> None: + """Build the exact owned distributions and verify every installed member against RECORD.""" + backend_requirement = _METADATA_CONTRACT._service_build_backend_requirement() + assert Version(installed_version("setuptools")) in backend_requirement.specifier, ( + "canonical test/build toolchain must install the exact reviewed setuptools backend" + ) + + wheelhouse = tmp_path / "wheelhouse" + wheelhouse.mkdir() + environment = _METADATA_CONTRACT._subprocess_environment() + for source_root in ( + _METADATA_CONTRACT._KEYVERSE_ROOT, + _METADATA_CONTRACT._SERVICE_ROOT, + ): + subprocess.run( + [ + sys.executable, + "-m", + "pip", + "wheel", + "--no-index", + "--no-cache-dir", + "--no-deps", + "--no-build-isolation", + "--wheel-dir", + str(wheelhouse), + str(source_root), + ], + cwd=_METADATA_CONTRACT._REPOSITORY_ROOT, + env=environment, + check=True, + ) + + wheel_paths = tuple(sorted(wheelhouse.iterdir())) + assert len(wheel_paths) == 2, "RECORD acceptance must inspect both owned built wheels" + for wheel_path in wheel_paths: + _RECORD_CONTRACT._validate_wheel_record(wheel_path) From 66c25126120f9d0ab96d028f7a3c1ab43f91c2e8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 20:08:38 +0900 Subject: [PATCH 313/603] docs(packaging): document wheel RECORD acceptance --- services/workforce-validation-api/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 35e2f3b65..e5f111894 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -134,7 +134,7 @@ The typed-calibration adapter must exact-key the complete target-population/wind The canonical Foundation quality workflow still invokes this service's pytest lane from the checkout, including a source-tree `PYTHONPATH` for ordinary unit/import coverage. That invocation is **not** accepted as packaging evidence by itself. -`tests/test_package_metadata_compatibility.py` and `tests/test_built_wheel_metadata_contract.py` establish the separate installed-distribution boundary. They remove inherited `PIP_*`, `PYTHONPATH`, and `PYTHONHOME`, disable ambient pip configuration, build the Keyverse and Workforce Validation wheels from the exact checkout with reviewed tooling and no dependency/index acquisition, reject unexpected wheel identities/content/package-data, parse the exact built `.dist-info/METADATA`, and bind built `Name`, `Version`, `Requires-Python`, plus Workforce Validation's mandatory unconditional exact `orgmetra-keyverse-adapter==0.1.0` `Requires-Dist` to reviewed project metadata. Each wheel is SHA-256-bound before installation; a fresh venv consumes only the local wheelhouse under pip hash-checking mode, then runs `pip check` and proves imports resolve under the isolated prefix. Directly installing Keyverse as a top-level lock entry must never mask a service wheel that dropped or altered its dependency declaration. +`tests/test_package_metadata_compatibility.py`, `tests/test_built_wheel_metadata_contract.py`, and `tests/test_built_wheel_record_integrity.py` establish the separate installed-distribution boundary. They remove inherited `PIP_*`, `PYTHONPATH`, and `PYTHONHOME`, disable ambient pip configuration, build the Keyverse and Workforce Validation wheels from the exact checkout with reviewed tooling and no dependency/index acquisition, reject unexpected wheel identities/content/package-data, parse the exact built `.dist-info/METADATA`, and bind built `Name`, `Version`, `Requires-Python`, plus Workforce Validation's mandatory unconditional exact `orgmetra-keyverse-adapter==0.1.0` `Requires-Dist` to reviewed project metadata. Each actual built wheel must also contain exactly one canonical `.dist-info/RECORD` whose rows cover every archived file exactly once, whose non-self entries use correct SHA-256 digests and byte sizes, and whose self-entry leaves hash and size empty. Each wheel is SHA-256-bound before installation; a fresh venv consumes only the local wheelhouse under pip hash-checking mode, then runs `pip check` and proves imports resolve under the isolated prefix. Directly installing Keyverse as a top-level lock entry must never mask a service wheel that dropped or altered its dependency declaration, and an outer artifact digest must never substitute for a truthful installation ledger. The Foundation pytest invocation remains: @@ -149,4 +149,4 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity and chronology. -These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. +These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. \ No newline at end of file From ee8ea428950f6f38685246b1367575df3ffc4a57 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 20:12:11 +0900 Subject: [PATCH 314/603] test(packaging): reject normalized wheel path aliases --- .../test_built_wheel_metadata_contract.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py b/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py index 1002e4a46..5ed32b30e 100644 --- a/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py +++ b/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py @@ -211,3 +211,26 @@ def test_hash_locked_acceptance_rejects_wheel_with_invalid_record_hash( service_wheel = wheelhouse / "orgmetra_workforce_validation_api-0.1.0-py3-none-any.whl" with pytest.raises(AssertionError, match="RECORD sha256 mismatch"): _validate_wheel_record(service_wheel) + + +def test_record_rejects_normalization_alias_member_paths(tmp_path: Path) -> None: + """Raw-distinct ZIP paths that normalize to one install path must fail closed.""" + wheel_path = tmp_path / "alias-0.1.0-py3-none-any.whl" + members = { + "alias/__init__.py": b"canonical", + "./alias/__init__.py": b"ambiguous", + } + record_path = "alias-0.1.0.dist-info/RECORD" + output = io.StringIO() + writer = csv.writer(output, lineterminator="\n") + for member_path, content in members.items(): + writer.writerow((member_path, _record_hash(content), str(len(content)))) + writer.writerow((record_path, "", "")) + + with zipfile.ZipFile(wheel_path, "w") as archive: + for member_path, content in members.items(): + archive.writestr(member_path, content) + archive.writestr(record_path, output.getvalue().encode("utf-8")) + + with pytest.raises(AssertionError, match="non-canonical"): + _validate_wheel_record(wheel_path) From 7c69e03ba356bc8b7f68b278c5978b5f4de49775 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 20:12:42 +0900 Subject: [PATCH 315/603] test(packaging): canonicalize wheel RECORD paths --- .../test_built_wheel_metadata_contract.py | 48 ++++++++++++++----- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py b/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py index 5ed32b30e..93c5f0958 100644 --- a/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py +++ b/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py @@ -30,6 +30,22 @@ def _record_hash(content: bytes) -> str: return f"sha256={encoded}" +def _canonical_wheel_member_path(member_path: str, *, wheel_name: str) -> str: + """Return one canonical relative POSIX wheel member path or fail closed.""" + path = PurePosixPath(member_path) + assert path.parts and not path.is_absolute(), ( + f"{wheel_name} contains an absolute or empty wheel member path" + ) + assert ".." not in path.parts and "\\" not in member_path, ( + f"{wheel_name} contains a non-canonical wheel member path" + ) + canonical = path.as_posix() + assert member_path == canonical, ( + f"{wheel_name} contains a non-canonical wheel member path" + ) + return canonical + + def _validate_wheel_record(wheel_path: Path) -> None: """Require one complete sha256 RECORD that exactly covers installed wheel members.""" with zipfile.ZipFile(wheel_path) as archive: @@ -38,9 +54,16 @@ def _validate_wheel_record(wheel_path: Path) -> None: assert len(archive_paths) == len(set(archive_paths)), ( f"{wheel_path.name} contains duplicate archive member paths" ) + canonical_archive_paths = [ + _canonical_wheel_member_path(path, wheel_name=wheel_path.name) + for path in archive_paths + ] + assert len(canonical_archive_paths) == len(set(canonical_archive_paths)), ( + f"{wheel_path.name} contains normalization-colliding archive member paths" + ) record_paths = [ path - for path in archive_paths + for path in canonical_archive_paths if len(PurePosixPath(path).parts) == 2 and PurePosixPath(path).parts[0].endswith(".dist-info") and PurePosixPath(path).name == "RECORD" @@ -57,24 +80,25 @@ def _validate_wheel_record(wheel_path: Path) -> None: for row in rows: assert len(row) == 3, f"{wheel_path.name} RECORD rows must have three columns" member_path, member_hash, member_size = row - parts = PurePosixPath(member_path).parts - assert parts and not PurePosixPath(member_path).is_absolute(), ( - f"{wheel_path.name} RECORD contains an absolute or empty path" + canonical_member_path = _canonical_wheel_member_path( + member_path, + wheel_name=wheel_path.name, ) - assert ".." not in parts and "\\" not in member_path, ( - f"{wheel_path.name} RECORD contains a non-canonical member path" - ) - assert member_path not in recorded, ( + assert canonical_member_path not in recorded, ( f"{wheel_path.name} RECORD contains duplicate path {member_path}" ) - recorded[member_path] = (member_hash, member_size) + recorded[canonical_member_path] = (member_hash, member_size) - assert set(recorded) == set(archive_paths), ( + assert set(recorded) == set(canonical_archive_paths), ( f"{wheel_path.name} RECORD must cover every wheel member exactly once" ) for info in infos: - member_hash, member_size = recorded[info.filename] - if info.filename == record_path: + canonical_info_path = _canonical_wheel_member_path( + info.filename, + wheel_name=wheel_path.name, + ) + member_hash, member_size = recorded[canonical_info_path] + if canonical_info_path == record_path: assert member_hash == "" and member_size == "", ( f"{wheel_path.name} RECORD self-entry must leave hash and size empty" ) From 468bb9afeb79506ded577fcd3c30014c7c0890d5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 20:18:10 +0900 Subject: [PATCH 316/603] test(packaging): require RECORD validation before wheel lock --- ...st_hash_locked_wheel_record_integration.py | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_hash_locked_wheel_record_integration.py diff --git a/services/workforce-validation-api/tests/test_hash_locked_wheel_record_integration.py b/services/workforce-validation-api/tests/test_hash_locked_wheel_record_integration.py new file mode 100644 index 000000000..4c5b4eb95 --- /dev/null +++ b/services/workforce-validation-api/tests/test_hash_locked_wheel_record_integration.py @@ -0,0 +1,112 @@ +"""Require the install lock path itself to reject false wheel installation ledgers.""" + +from __future__ import annotations + +import base64 +import csv +import hashlib +import importlib.util +import io +from pathlib import Path +import zipfile + +import pytest + + +_CONTRACT_PATH = Path(__file__).with_name("test_package_metadata_compatibility.py") +_SPEC = importlib.util.spec_from_file_location( + "_workforce_package_metadata_contract_for_record_integration", + _CONTRACT_PATH, +) +assert _SPEC is not None and _SPEC.loader is not None +_CONTRACT = importlib.util.module_from_spec(_SPEC) +_SPEC.loader.exec_module(_CONTRACT) + + +def _record_hash(content: bytes) -> str: + """Return one URL-safe unpadded RECORD sha256 digest.""" + digest = hashlib.sha256(content).digest() + encoded = base64.urlsafe_b64encode(digest).rstrip(b"=").decode("ascii") + return f"sha256={encoded}" + + +def _write_wheel( + wheelhouse: Path, + *, + filename: str, + package_root: str, + dist_info_root: str, + metadata: str, + include_py_typed: bool, + corrupt_record: bool = False, +) -> None: + """Write a minimal wheel whose outer bytes can hide a false internal RECORD.""" + members: dict[str, bytes] = { + f"{package_root}/__init__.py": b"", + f"{dist_info_root}/METADATA": metadata.encode("utf-8"), + f"{dist_info_root}/WHEEL": ( + "Wheel-Version: 1.0\n" + "Generator: orgmetra-record-integration-fixture\n" + "Root-Is-Purelib: true\n" + "Tag: py3-none-any\n\n" + ).encode("utf-8"), + } + if include_py_typed: + members[f"{package_root}/py.typed"] = b"" + + record_path = f"{dist_info_root}/RECORD" + output = io.StringIO() + writer = csv.writer(output, lineterminator="\n") + for member_path in sorted(members): + content = members[member_path] + member_hash = _record_hash(content) + if corrupt_record and member_path == f"{package_root}/__init__.py": + member_hash = "sha256=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + writer.writerow((member_path, member_hash, str(len(content)))) + writer.writerow((record_path, "", "")) + members[record_path] = output.getvalue().encode("utf-8") + + with zipfile.ZipFile(wheelhouse / filename, "w") as archive: + for member_path, content in members.items(): + archive.writestr(member_path, content) + + +def test_hash_locked_install_manifest_rejects_false_record(tmp_path: Path) -> None: + """Reject a false RECORD through the exact helper that creates install hashes.""" + wheelhouse = tmp_path / "wheelhouse" + wheelhouse.mkdir() + _write_wheel( + wheelhouse, + filename="orgmetra_keyverse_adapter-0.1.0-py3-none-any.whl", + package_root="orgmetra_keyverse_adapter", + dist_info_root="orgmetra_keyverse_adapter-0.1.0.dist-info", + metadata=( + "Metadata-Version: 2.4\n" + "Name: orgmetra-keyverse-adapter\n" + "Version: 0.1.0\n" + "Requires-Python: >=3.12\n\n" + ), + include_py_typed=False, + ) + _write_wheel( + wheelhouse, + filename="orgmetra_workforce_validation_api-0.1.0-py3-none-any.whl", + package_root="orgmetra_workforce_validation_api", + dist_info_root="orgmetra_workforce_validation_api-0.1.0.dist-info", + metadata=( + "Metadata-Version: 2.4\n" + "Name: orgmetra-workforce-validation-api\n" + "Version: 0.1.0\n" + "Requires-Python: >=3.12\n" + "Requires-Dist: orgmetra-keyverse-adapter==0.1.0\n\n" + ), + include_py_typed=True, + corrupt_record=True, + ) + + with pytest.raises(AssertionError, match="RECORD"): + _CONTRACT._locked_wheel_requirements( + wheelhouse, + service_version="0.1.0", + keyverse_version="0.1.0", + ) From 860fbcb2e7a91d3ad0bee5b8a23b59060cb41977 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 20:18:59 +0900 Subject: [PATCH 317/603] test(packaging): validate RECORD before wheel hash lock --- .../test_package_metadata_compatibility.py | 95 ++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py index 2a5583b51..ef4b5c8c1 100644 --- a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py +++ b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py @@ -2,9 +2,12 @@ from __future__ import annotations +import base64 +import csv from email.parser import Parser import hashlib from importlib.metadata import version as installed_version +import io import os from pathlib import Path, PurePosixPath import subprocess @@ -99,6 +102,95 @@ def _sha256(path: Path) -> str: return hashlib.file_digest(stream, "sha256").hexdigest() +def _record_hash(content: bytes) -> str: + """Return the URL-safe unpadded sha256 representation required by wheel RECORD.""" + digest = hashlib.sha256(content).digest() + encoded = base64.urlsafe_b64encode(digest).rstrip(b"=").decode("ascii") + return f"sha256={encoded}" + + +def _canonical_wheel_member_path(member_path: str, *, wheel_name: str) -> str: + """Return one canonical relative POSIX wheel member path or fail closed.""" + path = PurePosixPath(member_path) + assert path.parts and not path.is_absolute(), ( + f"{wheel_name} contains an absolute or empty wheel member path" + ) + assert ".." not in path.parts and "\\" not in member_path, ( + f"{wheel_name} contains a non-canonical wheel member path" + ) + canonical = path.as_posix() + assert member_path == canonical, ( + f"{wheel_name} contains a non-canonical wheel member path" + ) + return canonical + + +def _validate_wheel_record(wheel_path: Path) -> None: + """Verify canonical member identity and the complete wheel installation RECORD.""" + with zipfile.ZipFile(wheel_path) as archive: + infos = tuple(info for info in archive.infolist() if not info.is_dir()) + archive_paths = [info.filename for info in infos] + assert len(archive_paths) == len(set(archive_paths)), ( + f"{wheel_path.name} contains duplicate archive member paths" + ) + canonical_archive_paths = [ + _canonical_wheel_member_path(path, wheel_name=wheel_path.name) + for path in archive_paths + ] + assert len(canonical_archive_paths) == len(set(canonical_archive_paths)), ( + f"{wheel_path.name} contains normalization-colliding archive member paths" + ) + record_paths = [ + path + for path in canonical_archive_paths + if len(PurePosixPath(path).parts) == 2 + and PurePosixPath(path).parts[0].endswith(".dist-info") + and PurePosixPath(path).name == "RECORD" + ] + assert len(record_paths) == 1, ( + f"{wheel_path.name} must contain exactly one dist-info RECORD" + ) + record_path = record_paths[0] + record_text = archive.read(record_path).decode("utf-8") + rows = tuple(csv.reader(io.StringIO(record_text))) + assert rows, f"{wheel_path.name} RECORD must not be empty" + + recorded: dict[str, tuple[str, str]] = {} + for row in rows: + assert len(row) == 3, f"{wheel_path.name} RECORD rows must have three columns" + member_path, member_hash, member_size = row + canonical_member_path = _canonical_wheel_member_path( + member_path, + wheel_name=wheel_path.name, + ) + assert canonical_member_path not in recorded, ( + f"{wheel_path.name} RECORD contains duplicate path {member_path}" + ) + recorded[canonical_member_path] = (member_hash, member_size) + + assert set(recorded) == set(canonical_archive_paths), ( + f"{wheel_path.name} RECORD must cover every wheel member exactly once" + ) + for info in infos: + canonical_info_path = _canonical_wheel_member_path( + info.filename, + wheel_name=wheel_path.name, + ) + member_hash, member_size = recorded[canonical_info_path] + if canonical_info_path == record_path: + assert member_hash == "" and member_size == "", ( + f"{wheel_path.name} RECORD self-entry must leave hash and size empty" + ) + continue + content = archive.read(info.filename) + assert member_hash == _record_hash(content), ( + f"{wheel_path.name} RECORD sha256 mismatch for {info.filename}" + ) + assert member_size == str(len(content)), ( + f"{wheel_path.name} RECORD size mismatch for {info.filename}" + ) + + def _validate_wheel_contents( wheel_path: Path, *, @@ -254,6 +346,7 @@ def _locked_wheel_requirements( assert isinstance(requires_python, str), ( f"{canonical_name} project requires-python must be text" ) + _validate_wheel_record(wheel_path) wheels_by_name[canonical_name] = wheel_path hashes_by_name[canonical_name] = _sha256(wheel_path) _validate_wheel_contents( @@ -455,4 +548,4 @@ def test_built_distribution_closure_installs_without_checkout_imports(tmp_path: cwd=tmp_path, env=environment, check=True, - ) + ) \ No newline at end of file From cc0254197dafd4b72428bed6699341d278fba66c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 20:19:34 +0900 Subject: [PATCH 318/603] test(packaging): reuse install-path RECORD validator --- .../test_built_wheel_metadata_contract.py | 110 ++---------------- 1 file changed, 10 insertions(+), 100 deletions(-) diff --git a/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py b/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py index 93c5f0958..2a66893a1 100644 --- a/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py +++ b/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py @@ -2,12 +2,10 @@ from __future__ import annotations -import base64 import csv -import hashlib import importlib.util import io -from pathlib import Path, PurePosixPath +from pathlib import Path import zipfile import pytest @@ -23,95 +21,6 @@ _SPEC.loader.exec_module(_CONTRACT) -def _record_hash(content: bytes) -> str: - """Return the wheel RECORD sha256 representation for one member.""" - digest = hashlib.sha256(content).digest() - encoded = base64.urlsafe_b64encode(digest).rstrip(b"=").decode("ascii") - return f"sha256={encoded}" - - -def _canonical_wheel_member_path(member_path: str, *, wheel_name: str) -> str: - """Return one canonical relative POSIX wheel member path or fail closed.""" - path = PurePosixPath(member_path) - assert path.parts and not path.is_absolute(), ( - f"{wheel_name} contains an absolute or empty wheel member path" - ) - assert ".." not in path.parts and "\\" not in member_path, ( - f"{wheel_name} contains a non-canonical wheel member path" - ) - canonical = path.as_posix() - assert member_path == canonical, ( - f"{wheel_name} contains a non-canonical wheel member path" - ) - return canonical - - -def _validate_wheel_record(wheel_path: Path) -> None: - """Require one complete sha256 RECORD that exactly covers installed wheel members.""" - with zipfile.ZipFile(wheel_path) as archive: - infos = tuple(info for info in archive.infolist() if not info.is_dir()) - archive_paths = [info.filename for info in infos] - assert len(archive_paths) == len(set(archive_paths)), ( - f"{wheel_path.name} contains duplicate archive member paths" - ) - canonical_archive_paths = [ - _canonical_wheel_member_path(path, wheel_name=wheel_path.name) - for path in archive_paths - ] - assert len(canonical_archive_paths) == len(set(canonical_archive_paths)), ( - f"{wheel_path.name} contains normalization-colliding archive member paths" - ) - record_paths = [ - path - for path in canonical_archive_paths - if len(PurePosixPath(path).parts) == 2 - and PurePosixPath(path).parts[0].endswith(".dist-info") - and PurePosixPath(path).name == "RECORD" - ] - assert len(record_paths) == 1, ( - f"{wheel_path.name} must contain exactly one dist-info RECORD" - ) - record_path = record_paths[0] - record_text = archive.read(record_path).decode("utf-8") - rows = tuple(csv.reader(io.StringIO(record_text))) - assert rows, f"{wheel_path.name} RECORD must not be empty" - - recorded: dict[str, tuple[str, str]] = {} - for row in rows: - assert len(row) == 3, f"{wheel_path.name} RECORD rows must have three columns" - member_path, member_hash, member_size = row - canonical_member_path = _canonical_wheel_member_path( - member_path, - wheel_name=wheel_path.name, - ) - assert canonical_member_path not in recorded, ( - f"{wheel_path.name} RECORD contains duplicate path {member_path}" - ) - recorded[canonical_member_path] = (member_hash, member_size) - - assert set(recorded) == set(canonical_archive_paths), ( - f"{wheel_path.name} RECORD must cover every wheel member exactly once" - ) - for info in infos: - canonical_info_path = _canonical_wheel_member_path( - info.filename, - wheel_name=wheel_path.name, - ) - member_hash, member_size = recorded[canonical_info_path] - if canonical_info_path == record_path: - assert member_hash == "" and member_size == "", ( - f"{wheel_path.name} RECORD self-entry must leave hash and size empty" - ) - continue - content = archive.read(info.filename) - assert member_hash == _record_hash(content), ( - f"{wheel_path.name} RECORD sha256 mismatch for {info.filename}" - ) - assert member_size == str(len(content)), ( - f"{wheel_path.name} RECORD size mismatch for {info.filename}" - ) - - def _write_wheel( wheelhouse: Path, *, @@ -141,7 +50,7 @@ def _write_wheel( writer = csv.writer(output, lineterminator="\n") for member_path in sorted(members): member = members[member_path] - member_hash = _record_hash(member) + member_hash = _CONTRACT._record_hash(member) if break_record_hash and member_path == f"{package_root}/__init__.py": member_hash = "sha256=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" writer.writerow((member_path, member_hash, str(len(member)))) @@ -187,8 +96,6 @@ def test_hash_locked_acceptance_rejects_service_wheel_missing_keyverse_dependenc include_py_typed=True, ) - for wheel_path in wheelhouse.iterdir(): - _validate_wheel_record(wheel_path) with pytest.raises(AssertionError, match="mandatory Keyverse dependency"): _CONTRACT._locked_wheel_requirements( wheelhouse, @@ -200,7 +107,7 @@ def test_hash_locked_acceptance_rejects_service_wheel_missing_keyverse_dependenc def test_hash_locked_acceptance_rejects_wheel_with_invalid_record_hash( tmp_path: Path, ) -> None: - """A wheel SHA lock must not hide an internally false installation RECORD.""" + """The exact install-lock helper must reject a false internal installation RECORD.""" wheelhouse = tmp_path / "wheelhouse" wheelhouse.mkdir() _write_wheel( @@ -232,9 +139,12 @@ def test_hash_locked_acceptance_rejects_wheel_with_invalid_record_hash( break_record_hash=True, ) - service_wheel = wheelhouse / "orgmetra_workforce_validation_api-0.1.0-py3-none-any.whl" with pytest.raises(AssertionError, match="RECORD sha256 mismatch"): - _validate_wheel_record(service_wheel) + _CONTRACT._locked_wheel_requirements( + wheelhouse, + service_version="0.1.0", + keyverse_version="0.1.0", + ) def test_record_rejects_normalization_alias_member_paths(tmp_path: Path) -> None: @@ -248,7 +158,7 @@ def test_record_rejects_normalization_alias_member_paths(tmp_path: Path) -> None output = io.StringIO() writer = csv.writer(output, lineterminator="\n") for member_path, content in members.items(): - writer.writerow((member_path, _record_hash(content), str(len(content)))) + writer.writerow((member_path, _CONTRACT._record_hash(content), str(len(content)))) writer.writerow((record_path, "", "")) with zipfile.ZipFile(wheel_path, "w") as archive: @@ -257,4 +167,4 @@ def test_record_rejects_normalization_alias_member_paths(tmp_path: Path) -> None archive.writestr(record_path, output.getvalue().encode("utf-8")) with pytest.raises(AssertionError, match="non-canonical"): - _validate_wheel_record(wheel_path) + _CONTRACT._validate_wheel_record(wheel_path) From ef41ebe2607410c7d945c061e86820d61d9e21d8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 20:19:54 +0900 Subject: [PATCH 319/603] test(packaging): use install-path RECORD contract for real wheels --- .../tests/test_built_wheel_record_integrity.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/services/workforce-validation-api/tests/test_built_wheel_record_integrity.py b/services/workforce-validation-api/tests/test_built_wheel_record_integrity.py index aa5ccef17..a72fae2aa 100644 --- a/services/workforce-validation-api/tests/test_built_wheel_record_integrity.py +++ b/services/workforce-validation-api/tests/test_built_wheel_record_integrity.py @@ -13,7 +13,6 @@ _TEST_ROOT = Path(__file__).resolve().parent _METADATA_PATH = _TEST_ROOT / "test_package_metadata_compatibility.py" -_RECORD_PATH = _TEST_ROOT / "test_built_wheel_metadata_contract.py" _METADATA_SPEC = importlib.util.spec_from_file_location( "_workforce_package_metadata_contract_for_record", @@ -23,14 +22,6 @@ _METADATA_CONTRACT = importlib.util.module_from_spec(_METADATA_SPEC) _METADATA_SPEC.loader.exec_module(_METADATA_CONTRACT) -_RECORD_SPEC = importlib.util.spec_from_file_location( - "_workforce_built_wheel_record_contract", - _RECORD_PATH, -) -assert _RECORD_SPEC is not None and _RECORD_SPEC.loader is not None -_RECORD_CONTRACT = importlib.util.module_from_spec(_RECORD_SPEC) -_RECORD_SPEC.loader.exec_module(_RECORD_CONTRACT) - def test_built_owned_wheels_have_complete_verified_records(tmp_path: Path) -> None: """Build the exact owned distributions and verify every installed member against RECORD.""" @@ -68,4 +59,4 @@ def test_built_owned_wheels_have_complete_verified_records(tmp_path: Path) -> No wheel_paths = tuple(sorted(wheelhouse.iterdir())) assert len(wheel_paths) == 2, "RECORD acceptance must inspect both owned built wheels" for wheel_path in wheel_paths: - _RECORD_CONTRACT._validate_wheel_record(wheel_path) + _METADATA_CONTRACT._validate_wheel_record(wheel_path) From afa0d25c3a3925241e5abd3e48994f58644e626a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 20:31:59 +0900 Subject: [PATCH 320/603] test(packaging): reject unreviewed built dependency metadata --- .../test_built_wheel_metadata_contract.py | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py b/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py index 2a66893a1..20a3e25c2 100644 --- a/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py +++ b/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py @@ -104,6 +104,49 @@ def test_hash_locked_acceptance_rejects_service_wheel_missing_keyverse_dependenc ) +def test_hash_locked_acceptance_rejects_unreviewed_inactive_dependency( + tmp_path: Path, +) -> None: + """Built metadata must not gain a marker-disabled dependency absent from source truth.""" + wheelhouse = tmp_path / "wheelhouse" + wheelhouse.mkdir() + _write_wheel( + wheelhouse, + filename="orgmetra_keyverse_adapter-0.1.0-py3-none-any.whl", + package_root="orgmetra_keyverse_adapter", + dist_info_root="orgmetra_keyverse_adapter-0.1.0.dist-info", + metadata=( + "Metadata-Version: 2.4\n" + "Name: orgmetra-keyverse-adapter\n" + "Version: 0.1.0\n" + "Requires-Python: >=3.12\n\n" + ), + include_py_typed=False, + ) + _write_wheel( + wheelhouse, + filename="orgmetra_workforce_validation_api-0.1.0-py3-none-any.whl", + package_root="orgmetra_workforce_validation_api", + dist_info_root="orgmetra_workforce_validation_api-0.1.0.dist-info", + metadata=( + "Metadata-Version: 2.4\n" + "Name: orgmetra-workforce-validation-api\n" + "Version: 0.1.0\n" + "Requires-Python: >=3.12\n" + "Requires-Dist: orgmetra-keyverse-adapter==0.1.0\n" + "Requires-Dist: unreviewed-package>=1; python_version < '3.0'\n\n" + ), + include_py_typed=True, + ) + + with pytest.raises(AssertionError, match="reviewed project dependencies"): + _CONTRACT._locked_wheel_requirements( + wheelhouse, + service_version="0.1.0", + keyverse_version="0.1.0", + ) + + def test_hash_locked_acceptance_rejects_wheel_with_invalid_record_hash( tmp_path: Path, ) -> None: From 6565f6160c4f60458b4ff0b916ab3e79d67b04d4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 20:34:10 +0900 Subject: [PATCH 321/603] test(packaging): bind built dependency set to reviewed metadata --- .../test_package_metadata_compatibility.py | 59 +++++++++++++------ 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py index ef4b5c8c1..69d299bca 100644 --- a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py +++ b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py @@ -235,15 +235,27 @@ def _validate_wheel_contents( ) +def _requirement_identity(requirement: Requirement) -> tuple[str, tuple[str, ...], str, str, str]: + """Normalize one dependency declaration without dropping extras, markers, or direct URLs.""" + return ( + canonicalize_name(requirement.name), + tuple(sorted(canonicalize_name(extra) for extra in requirement.extras)), + str(requirement.specifier), + str(requirement.marker) if requirement.marker is not None else "", + requirement.url or "", + ) + + def _validate_wheel_metadata( wheel_path: Path, *, expected_name: str, expected_version: str, expected_requires_python: str, + expected_dependencies: tuple[str, ...], required_dependency: tuple[str, str] | None = None, ) -> None: - """Bind built METADATA to reviewed project identity, runtime, and owned dependencies.""" + """Bind built METADATA to reviewed project identity, runtime, and dependencies.""" with zipfile.ZipFile(wheel_path) as archive: metadata_paths = [ name @@ -276,27 +288,31 @@ def _validate_wheel_metadata( f"{wheel_path.name} METADATA Requires-Python does not match reviewed project runtime" ) - if required_dependency is None: - return - dependency_name, dependency_version = required_dependency parsed_dependencies = [ Requirement(value) for value in metadata.get_all("Requires-Dist", failobj=[]) ] - matching_dependencies = [ - requirement - for requirement in parsed_dependencies - if canonicalize_name(requirement.name) == canonicalize_name(dependency_name) - ] - assert len(matching_dependencies) == 1, ( - f"{wheel_path.name} METADATA must preserve the mandatory Keyverse dependency" - ) - requirement = matching_dependencies[0] - assert requirement.specifier == SpecifierSet(f"=={dependency_version}"), ( - f"{wheel_path.name} METADATA must preserve the exact owned Keyverse version" - ) - assert not requirement.extras and requirement.marker is None and requirement.url is None, ( - f"{wheel_path.name} mandatory Keyverse dependency must remain unconditional" - ) + if required_dependency is not None: + dependency_name, dependency_version = required_dependency + matching_dependencies = [ + requirement + for requirement in parsed_dependencies + if canonicalize_name(requirement.name) == canonicalize_name(dependency_name) + ] + assert len(matching_dependencies) == 1, ( + f"{wheel_path.name} METADATA must preserve the mandatory Keyverse dependency" + ) + requirement = matching_dependencies[0] + assert requirement.specifier == SpecifierSet(f"=={dependency_version}"), ( + f"{wheel_path.name} METADATA must preserve the exact owned Keyverse version" + ) + assert not requirement.extras and requirement.marker is None and requirement.url is None, ( + f"{wheel_path.name} mandatory Keyverse dependency must remain unconditional" + ) + + reviewed_dependencies = [Requirement(value) for value in expected_dependencies] + assert sorted(_requirement_identity(value) for value in parsed_dependencies) == sorted( + _requirement_identity(value) for value in reviewed_dependencies + ), f"{wheel_path.name} METADATA dependencies do not match reviewed project dependencies" def _locked_wheel_requirements( @@ -346,6 +362,10 @@ def _locked_wheel_requirements( assert isinstance(requires_python, str), ( f"{canonical_name} project requires-python must be text" ) + raw_dependencies = project.get("dependencies", []) + assert isinstance(raw_dependencies, list) and all( + isinstance(value, str) for value in raw_dependencies + ), f"{canonical_name} project dependencies must be a text list" _validate_wheel_record(wheel_path) wheels_by_name[canonical_name] = wheel_path hashes_by_name[canonical_name] = _sha256(wheel_path) @@ -363,6 +383,7 @@ def _locked_wheel_requirements( ), expected_version=str(expected_versions[canonical_name]), expected_requires_python=requires_python, + expected_dependencies=tuple(raw_dependencies), required_dependency=( (_KEYVERSE_NAME, keyverse_version) if canonical_name == canonicalize_name(_SERVICE_NAME) From 0d084772ffd0a2bdddce6db10fe656f95ecd8dbc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 20:39:07 +0900 Subject: [PATCH 322/603] test(packaging): preserve reviewed optional dependency metadata --- .../test_built_wheel_metadata_contract.py | 65 ++++++++++++++++++- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py b/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py index 20a3e25c2..112099f4a 100644 --- a/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py +++ b/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py @@ -78,7 +78,10 @@ def test_hash_locked_acceptance_rejects_service_wheel_missing_keyverse_dependenc "Metadata-Version: 2.4\n" "Name: orgmetra-keyverse-adapter\n" "Version: 0.1.0\n" - "Requires-Python: >=3.12\n\n" + "Requires-Python: >=3.12\n" + "Provides-Extra: test\n" + "Requires-Dist: pytest>=8.3; extra == 'test'\n" + "Requires-Dist: pytest-cov>=5.0; extra == 'test'\n\n" ), include_py_typed=False, ) @@ -119,7 +122,10 @@ def test_hash_locked_acceptance_rejects_unreviewed_inactive_dependency( "Metadata-Version: 2.4\n" "Name: orgmetra-keyverse-adapter\n" "Version: 0.1.0\n" - "Requires-Python: >=3.12\n\n" + "Requires-Python: >=3.12\n" + "Provides-Extra: test\n" + "Requires-Dist: pytest>=8.3; extra == 'test'\n" + "Requires-Dist: pytest-cov>=5.0; extra == 'test'\n\n" ), include_py_typed=False, ) @@ -147,6 +153,56 @@ def test_hash_locked_acceptance_rejects_unreviewed_inactive_dependency( ) +def test_hash_locked_acceptance_preserves_reviewed_optional_dependencies( + tmp_path: Path, +) -> None: + """PEP 621 optional dependencies must remain reviewed metadata, not false positives.""" + wheelhouse = tmp_path / "wheelhouse" + wheelhouse.mkdir() + _write_wheel( + wheelhouse, + filename="orgmetra_keyverse_adapter-0.1.0-py3-none-any.whl", + package_root="orgmetra_keyverse_adapter", + dist_info_root="orgmetra_keyverse_adapter-0.1.0.dist-info", + metadata=( + "Metadata-Version: 2.4\n" + "Name: orgmetra-keyverse-adapter\n" + "Version: 0.1.0\n" + "Requires-Python: >=3.12\n" + "Provides-Extra: test\n" + "Requires-Dist: pytest>=8.3; extra == 'test'\n" + "Requires-Dist: pytest-cov>=5.0; extra == 'test'\n\n" + ), + include_py_typed=False, + ) + _write_wheel( + wheelhouse, + filename="orgmetra_workforce_validation_api-0.1.0-py3-none-any.whl", + package_root="orgmetra_workforce_validation_api", + dist_info_root="orgmetra_workforce_validation_api-0.1.0.dist-info", + metadata=( + "Metadata-Version: 2.4\n" + "Name: orgmetra-workforce-validation-api\n" + "Version: 0.1.0\n" + "Requires-Python: >=3.12\n" + "Requires-Dist: orgmetra-keyverse-adapter==0.1.0\n\n" + ), + include_py_typed=True, + ) + + locked_requirements, wheels_by_name = _CONTRACT._locked_wheel_requirements( + wheelhouse, + service_version="0.1.0", + keyverse_version="0.1.0", + ) + + assert "orgmetra-keyverse-adapter==0.1.0" in locked_requirements + assert set(wheels_by_name) == { + "orgmetra-keyverse-adapter", + "orgmetra-workforce-validation-api", + } + + def test_hash_locked_acceptance_rejects_wheel_with_invalid_record_hash( tmp_path: Path, ) -> None: @@ -162,7 +218,10 @@ def test_hash_locked_acceptance_rejects_wheel_with_invalid_record_hash( "Metadata-Version: 2.4\n" "Name: orgmetra-keyverse-adapter\n" "Version: 0.1.0\n" - "Requires-Python: >=3.12\n\n" + "Requires-Python: >=3.12\n" + "Provides-Extra: test\n" + "Requires-Dist: pytest>=8.3; extra == 'test'\n" + "Requires-Dist: pytest-cov>=5.0; extra == 'test'\n\n" ), include_py_typed=False, ) From 508c6ea1d8998356448e90839a91ddc266907c7d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 20:40:09 +0900 Subject: [PATCH 323/603] test(packaging): bind optional dependency metadata exactly --- .../test_package_metadata_compatibility.py | 62 ++++++++++++++++--- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py index 69d299bca..902836495 100644 --- a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py +++ b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py @@ -15,6 +15,7 @@ import tomllib import zipfile +from packaging.markers import Marker from packaging.requirements import Requirement from packaging.specifiers import SpecifierSet from packaging.utils import canonicalize_name, parse_wheel_filename @@ -246,16 +247,52 @@ def _requirement_identity(requirement: Requirement) -> tuple[str, tuple[str, ... ) +def _reviewed_dependency_metadata( + project: dict[str, object], + *, + owner: str, +) -> tuple[tuple[Requirement, ...], tuple[str, ...]]: + """Expand reviewed base and optional dependencies into built METADATA semantics.""" + raw_dependencies = project.get("dependencies", []) + assert isinstance(raw_dependencies, list) and all( + isinstance(value, str) for value in raw_dependencies + ), f"{owner} project dependencies must be a text list" + requirements = [Requirement(value) for value in raw_dependencies] + + raw_optional = project.get("optional-dependencies", {}) + assert isinstance(raw_optional, dict), f"{owner} optional-dependencies must be a table" + extras: list[str] = [] + for raw_extra, raw_requirements in raw_optional.items(): + assert isinstance(raw_extra, str), f"{owner} optional dependency names must be text" + assert isinstance(raw_requirements, list) and all( + isinstance(value, str) for value in raw_requirements + ), f"{owner} optional dependency group {raw_extra} must be a text list" + normalized_extra = canonicalize_name(raw_extra) + extras.append(normalized_extra) + for value in raw_requirements: + requirement = Requirement(value) + extra_marker = f"extra == {normalized_extra!r}" + if requirement.marker is None: + requirement.marker = Marker(extra_marker) + else: + requirement.marker = Marker(f"({requirement.marker}) and {extra_marker}") + requirements.append(requirement) + + assert len(extras) == len(set(extras)), f"{owner} optional dependency extras must be unique" + return tuple(requirements), tuple(sorted(extras)) + + def _validate_wheel_metadata( wheel_path: Path, *, expected_name: str, expected_version: str, expected_requires_python: str, - expected_dependencies: tuple[str, ...], + expected_dependencies: tuple[Requirement, ...], + expected_extras: tuple[str, ...], required_dependency: tuple[str, str] | None = None, ) -> None: - """Bind built METADATA to reviewed project identity, runtime, and dependencies.""" + """Bind built METADATA to reviewed project identity, runtime, dependencies, and extras.""" with zipfile.ZipFile(wheel_path) as archive: metadata_paths = [ name @@ -309,11 +346,17 @@ def _validate_wheel_metadata( f"{wheel_path.name} mandatory Keyverse dependency must remain unconditional" ) - reviewed_dependencies = [Requirement(value) for value in expected_dependencies] assert sorted(_requirement_identity(value) for value in parsed_dependencies) == sorted( - _requirement_identity(value) for value in reviewed_dependencies + _requirement_identity(value) for value in expected_dependencies ), f"{wheel_path.name} METADATA dependencies do not match reviewed project dependencies" + built_extras = tuple( + sorted(canonicalize_name(value) for value in metadata.get_all("Provides-Extra", failobj=[])) + ) + assert built_extras == expected_extras, ( + f"{wheel_path.name} METADATA extras do not match reviewed optional dependencies" + ) + def _locked_wheel_requirements( wheelhouse: Path, @@ -362,10 +405,10 @@ def _locked_wheel_requirements( assert isinstance(requires_python, str), ( f"{canonical_name} project requires-python must be text" ) - raw_dependencies = project.get("dependencies", []) - assert isinstance(raw_dependencies, list) and all( - isinstance(value, str) for value in raw_dependencies - ), f"{canonical_name} project dependencies must be a text list" + reviewed_dependencies, reviewed_extras = _reviewed_dependency_metadata( + project, + owner=canonical_name, + ) _validate_wheel_record(wheel_path) wheels_by_name[canonical_name] = wheel_path hashes_by_name[canonical_name] = _sha256(wheel_path) @@ -383,7 +426,8 @@ def _locked_wheel_requirements( ), expected_version=str(expected_versions[canonical_name]), expected_requires_python=requires_python, - expected_dependencies=tuple(raw_dependencies), + expected_dependencies=reviewed_dependencies, + expected_extras=reviewed_extras, required_dependency=( (_KEYVERSE_NAME, keyverse_version) if canonical_name == canonicalize_name(_SERVICE_NAME) From f76e337dbdb2f3fef3b537cc90745e5e7f0f201f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 20:47:31 +0900 Subject: [PATCH 324/603] test(packaging): cover Provides-Extra rejection causally --- .../test_built_wheel_metadata_contract.py | 96 ++++++++++++------- 1 file changed, 63 insertions(+), 33 deletions(-) diff --git a/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py b/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py index 112099f4a..5db9bc86f 100644 --- a/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py +++ b/services/workforce-validation-api/tests/test_built_wheel_metadata_contract.py @@ -63,6 +63,21 @@ def _write_wheel( archive.writestr(member_path, member) +def _keyverse_metadata(*provides_extra_lines: str) -> str: + """Build Keyverse Core Metadata while varying only the declared extra ledger.""" + return "".join( + ( + "Metadata-Version: 2.4\n", + "Name: orgmetra-keyverse-adapter\n", + "Version: 0.1.0\n", + "Requires-Python: >=3.12\n", + *(f"Provides-Extra: {value}\n" for value in provides_extra_lines), + "Requires-Dist: pytest>=8.3; extra == 'test'\n", + "Requires-Dist: pytest-cov>=5.0; extra == 'test'\n\n", + ) + ) + + def test_hash_locked_acceptance_rejects_service_wheel_missing_keyverse_dependency( tmp_path: Path, ) -> None: @@ -74,15 +89,7 @@ def test_hash_locked_acceptance_rejects_service_wheel_missing_keyverse_dependenc filename="orgmetra_keyverse_adapter-0.1.0-py3-none-any.whl", package_root="orgmetra_keyverse_adapter", dist_info_root="orgmetra_keyverse_adapter-0.1.0.dist-info", - metadata=( - "Metadata-Version: 2.4\n" - "Name: orgmetra-keyverse-adapter\n" - "Version: 0.1.0\n" - "Requires-Python: >=3.12\n" - "Provides-Extra: test\n" - "Requires-Dist: pytest>=8.3; extra == 'test'\n" - "Requires-Dist: pytest-cov>=5.0; extra == 'test'\n\n" - ), + metadata=_keyverse_metadata("test"), include_py_typed=False, ) _write_wheel( @@ -118,15 +125,7 @@ def test_hash_locked_acceptance_rejects_unreviewed_inactive_dependency( filename="orgmetra_keyverse_adapter-0.1.0-py3-none-any.whl", package_root="orgmetra_keyverse_adapter", dist_info_root="orgmetra_keyverse_adapter-0.1.0.dist-info", - metadata=( - "Metadata-Version: 2.4\n" - "Name: orgmetra-keyverse-adapter\n" - "Version: 0.1.0\n" - "Requires-Python: >=3.12\n" - "Provides-Extra: test\n" - "Requires-Dist: pytest>=8.3; extra == 'test'\n" - "Requires-Dist: pytest-cov>=5.0; extra == 'test'\n\n" - ), + metadata=_keyverse_metadata("test"), include_py_typed=False, ) _write_wheel( @@ -164,15 +163,7 @@ def test_hash_locked_acceptance_preserves_reviewed_optional_dependencies( filename="orgmetra_keyverse_adapter-0.1.0-py3-none-any.whl", package_root="orgmetra_keyverse_adapter", dist_info_root="orgmetra_keyverse_adapter-0.1.0.dist-info", - metadata=( - "Metadata-Version: 2.4\n" - "Name: orgmetra-keyverse-adapter\n" - "Version: 0.1.0\n" - "Requires-Python: >=3.12\n" - "Provides-Extra: test\n" - "Requires-Dist: pytest>=8.3; extra == 'test'\n" - "Requires-Dist: pytest-cov>=5.0; extra == 'test'\n\n" - ), + metadata=_keyverse_metadata("test"), include_py_typed=False, ) _write_wheel( @@ -203,10 +194,20 @@ def test_hash_locked_acceptance_preserves_reviewed_optional_dependencies( } -def test_hash_locked_acceptance_rejects_wheel_with_invalid_record_hash( +@pytest.mark.parametrize( + "provides_extra_lines", + [ + (), + ("testing",), + ("test", "test"), + ], + ids=("missing", "different-name", "duplicate"), +) +def test_hash_locked_acceptance_rejects_optional_extra_ledger_drift( tmp_path: Path, + provides_extra_lines: tuple[str, ...], ) -> None: - """The exact install-lock helper must reject a false internal installation RECORD.""" + """Extra-gated requirements cannot substitute for the reviewed Provides-Extra ledger.""" wheelhouse = tmp_path / "wheelhouse" wheelhouse.mkdir() _write_wheel( @@ -214,15 +215,44 @@ def test_hash_locked_acceptance_rejects_wheel_with_invalid_record_hash( filename="orgmetra_keyverse_adapter-0.1.0-py3-none-any.whl", package_root="orgmetra_keyverse_adapter", dist_info_root="orgmetra_keyverse_adapter-0.1.0.dist-info", + metadata=_keyverse_metadata(*provides_extra_lines), + include_py_typed=False, + ) + _write_wheel( + wheelhouse, + filename="orgmetra_workforce_validation_api-0.1.0-py3-none-any.whl", + package_root="orgmetra_workforce_validation_api", + dist_info_root="orgmetra_workforce_validation_api-0.1.0.dist-info", metadata=( "Metadata-Version: 2.4\n" - "Name: orgmetra-keyverse-adapter\n" + "Name: orgmetra-workforce-validation-api\n" "Version: 0.1.0\n" "Requires-Python: >=3.12\n" - "Provides-Extra: test\n" - "Requires-Dist: pytest>=8.3; extra == 'test'\n" - "Requires-Dist: pytest-cov>=5.0; extra == 'test'\n\n" + "Requires-Dist: orgmetra-keyverse-adapter==0.1.0\n\n" ), + include_py_typed=True, + ) + + with pytest.raises(AssertionError, match="METADATA extras"): + _CONTRACT._locked_wheel_requirements( + wheelhouse, + service_version="0.1.0", + keyverse_version="0.1.0", + ) + + +def test_hash_locked_acceptance_rejects_wheel_with_invalid_record_hash( + tmp_path: Path, +) -> None: + """The exact install-lock helper must reject a false internal installation RECORD.""" + wheelhouse = tmp_path / "wheelhouse" + wheelhouse.mkdir() + _write_wheel( + wheelhouse, + filename="orgmetra_keyverse_adapter-0.1.0-py3-none-any.whl", + package_root="orgmetra_keyverse_adapter", + dist_info_root="orgmetra_keyverse_adapter-0.1.0.dist-info", + metadata=_keyverse_metadata("test"), include_py_typed=False, ) _write_wheel( From 9a8ede5cce1cc5e6e3345d79278029bbbad428f0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 21:01:44 +0900 Subject: [PATCH 325/603] test(workforce-validation): require negative-outcome successor authority --- ...nonverifiability_supersession_authority.py | 215 ++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority.py new file mode 100644 index 000000000..71cb6eba2 --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority.py @@ -0,0 +1,215 @@ +"""Require an immutable successor verification attempt behind negative-outcome cutover.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.result_nonverifiability_supersession_authority import ( + ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError, + ValidationResultNonVerifiabilitySupersessionAuthorityRecord, + resolve_validation_result_nonverifiability_supersession_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:33333333-3333-4333-8333-333333333333" +SUCCESSOR_ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:44444444-4444-4444-8444-444444444444" +RESULT_DIGEST = "1" * 64 +OWNER_CONTRACT_DIGEST = "2" * 64 +ATTEMPT_DIGEST = "3" * 64 +SUCCESSOR_ATTEMPT_DIGEST = "4" * 64 +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 1, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 18, 8, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 18, 10, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "result_reference", + "result_digest", + "failed_evidence_kind", + "failure_mode", + "verification_attempt_reference", + "verification_attempt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_verification_attempt_reference", + "successor_verification_attempt_digest", + "successor_verification_attempt_released_at", + } +) + + +class _ReadPort: + """Return one configured owner record through the negative-outcome successor shape.""" + + def __init__(self, record: ValidationResultNonVerifiabilitySupersessionAuthorityRecord) -> None: + self.record = record + + def read_validation_result_nonverifiability_supersession_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + failed_evidence_kind: str, + failure_mode: str, + verification_attempt_reference: str, + verification_attempt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> ValidationResultNonVerifiabilitySupersessionAuthorityRecord: + """Return owner evidence; the resolver verifies every caller-known coordinate.""" + return self.record + + +def _principal() -> ValidationPrincipal: + """Return the canonical tenant-scoped workforce-validation principal.""" + return ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy() -> PurposeBoundAccessPolicy: + """Return the exact purpose-bound policy for negative-outcome successor evidence.""" + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="validation-result-nonverifiability-supersession-read-v1", + resource_kind="validation_result_nonverifiability_supersession_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record( + *, + superseded_at: datetime | None, + successor_reference: str | None, + successor_digest: str | None, + successor_released_at: datetime | None, +) -> ValidationResultNonVerifiabilitySupersessionAuthorityRecord: + """Build one canonical predecessor and optional successor verification attempt.""" + return ValidationResultNonVerifiabilitySupersessionAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + failed_evidence_kind="analysis_weight_receipt", + failure_mode="missing", + verification_attempt_reference=ATTEMPT_REFERENCE, + verification_attempt_digest=ATTEMPT_DIGEST, + evidence_version=1, + owner_contract_reference=OWNER_CONTRACT_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_CONTRACT_DIGEST, + owner_contract_released_at=OWNER_CONTRACT_RELEASED_AT, + released_at=RELEASED_AT, + superseded_at=superseded_at, + successor_verification_attempt_reference=successor_reference, + successor_verification_attempt_digest=successor_digest, + successor_verification_attempt_released_at=successor_released_at, + ) + + +def _resolve( + record: ValidationResultNonVerifiabilitySupersessionAuthorityRecord, + *, + used_at: datetime = USED_AT, +): + """Resolve the canonical predecessor through its purpose-bound owner port.""" + return resolve_validation_result_nonverifiability_supersession_authority( + principal=_principal(), + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + failed_evidence_kind="analysis_weight_receipt", + failure_mode="missing", + verification_attempt_reference=ATTEMPT_REFERENCE, + verification_attempt_digest=ATTEMPT_DIGEST, + evidence_version=1, + owner_contract_reference=OWNER_CONTRACT_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_CONTRACT_DIGEST, + used_at=used_at, + purpose_code="selection_validity_analysis", + policy=_policy(), + read_port=_ReadPort(record), + ) + + +def test_historical_negative_outcome_hides_successor_attempt() -> None: + """Keep historical negative evidence usable without leaking successor coordinates.""" + cutover = USED_AT + timedelta(hours=1) + view = _resolve( + _record( + superseded_at=cutover, + successor_reference=SUCCESSOR_ATTEMPT_REFERENCE, + successor_digest=SUCCESSOR_ATTEMPT_DIGEST, + successor_released_at=cutover, + ) + ) + + fields = dict(view.fields) + assert fields["verification_attempt_reference"] == ATTEMPT_REFERENCE + assert fields["failed_evidence_kind"] == "analysis_weight_receipt" + assert "superseded_at" not in fields + assert "successor_verification_attempt_reference" not in fields + + +def test_negative_outcome_fails_closed_at_successor_cutover() -> None: + """Reject use at the exact instant the successor verification attempt takes authority.""" + record = _record( + superseded_at=USED_AT, + successor_reference=SUCCESSOR_ATTEMPT_REFERENCE, + successor_digest=SUCCESSOR_ATTEMPT_DIGEST, + successor_released_at=USED_AT, + ) + + with pytest.raises(ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError): + _resolve(record) + + +@pytest.mark.parametrize( + ("superseded_at", "successor_reference", "successor_digest", "successor_released_at"), + [ + (USED_AT, None, SUCCESSOR_ATTEMPT_DIGEST, USED_AT), + (None, SUCCESSOR_ATTEMPT_REFERENCE, SUCCESSOR_ATTEMPT_DIGEST, USED_AT), + (USED_AT, ATTEMPT_REFERENCE, SUCCESSOR_ATTEMPT_DIGEST, USED_AT), + (USED_AT, SUCCESSOR_ATTEMPT_REFERENCE, ATTEMPT_DIGEST, USED_AT), + (USED_AT, SUCCESSOR_ATTEMPT_REFERENCE, SUCCESSOR_ATTEMPT_DIGEST, USED_AT - timedelta(seconds=1)), + (USED_AT, SUCCESSOR_ATTEMPT_REFERENCE, SUCCESSOR_ATTEMPT_DIGEST, USED_AT + timedelta(seconds=1)), + (RELEASED_AT, SUCCESSOR_ATTEMPT_REFERENCE, SUCCESSOR_ATTEMPT_DIGEST, RELEASED_AT), + ], +) +def test_owner_record_rejects_incomplete_or_non_atomic_successor_attempt( + superseded_at: datetime | None, + successor_reference: str | None, + successor_digest: str | None, + successor_released_at: datetime | None, +) -> None: + """Require one complete, new, release-at-cutover successor verification attempt.""" + with pytest.raises(ValueError): + _record( + superseded_at=superseded_at, + successor_reference=successor_reference, + successor_digest=successor_digest, + successor_released_at=successor_released_at, + ) From bd9b09ac49a0791342ec79db092c4706e2964856 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 21:02:27 +0900 Subject: [PATCH 326/603] feat(workforce-validation): bind negative-outcome successor attempts --- ...nonverifiability_supersession_authority.py | 531 ++++++++++++++++++ 1 file changed, 531 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py new file mode 100644 index 000000000..83f3980b7 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py @@ -0,0 +1,531 @@ +"""Corroborate append-only supersession of released non-verifiability outcomes. + +A released ``not_verifiable`` outcome remains authoritative only until a new +immutable verification attempt re-evaluates the same result. This boundary +binds that successor attempt to the predecessor cutover without exposing +successor coordinates as reusable downstream authority. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .result_nonverifiability import ( + _require_failed_evidence_kind, + _require_failure_mode, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + +_RESOURCE_KIND = "validation_result_nonverifiability_supersession_authority" +_OPERATION = "read" +_READ_FIELDS = frozenset( + { + "result_reference", + "result_digest", + "failed_evidence_kind", + "failure_mode", + "verification_attempt_reference", + "verification_attempt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_verification_attempt_reference", + "successor_verification_attempt_digest", + "successor_verification_attempt_released_at", + } +) +_VIEW_FIELDS = frozenset( + { + "result_reference", + "result_digest", + "failed_evidence_kind", + "failure_mode", + "verification_attempt_reference", + "verification_attempt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + } +) + + +class ValidationResultNonVerifiabilitySupersessionAuthorityNotFound(LookupError): + """Indicate that no released successor authority matches the negative outcome.""" + + +class ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError(RuntimeError): + """Indicate that negative-outcome successor evidence cannot authorize use.""" + + +class ValidationResultNonVerifiabilitySupersessionAuthorityRecord(tuple): + """Immutable owner projection for one negative-outcome authority interval.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + failed_evidence_kind: str, + failure_mode: str, + verification_attempt_reference: str, + verification_attempt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + owner_contract_released_at: datetime, + released_at: datetime, + superseded_at: datetime | None = None, + successor_verification_attempt_reference: str | None = None, + successor_verification_attempt_digest: str | None = None, + successor_verification_attempt_released_at: datetime | None = None, + ) -> ValidationResultNonVerifiabilitySupersessionAuthorityRecord: + """Validate predecessor chronology and one complete immutable successor attempt.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + result_ref = _require_reference( + "result_reference", result_reference, "validation_analysis_result" + ) + result_evidence_digest = _require_digest("result_digest", result_digest) + evidence_kind = _require_failed_evidence_kind(failed_evidence_kind) + mode = _require_failure_mode(failure_mode) + attempt_ref = _require_reference( + "verification_attempt_reference", + verification_attempt_reference, + "validation_evidence_verification_attempt", + ) + attempt_digest = _require_digest( + "verification_attempt_digest", verification_attempt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + owner_released = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) + release_instant = _require_aware_datetime("released_at", released_at) + if owner_released > release_instant: + raise ValueError( + "owner contract must be released no later than non-verifiability outcome." + ) + if len({result_evidence_digest, attempt_digest, owner_digest}) != 3: + raise ValueError( + "result, verification-attempt, and owner-contract digests must be distinct." + ) + + successor_values = ( + superseded_at, + successor_verification_attempt_reference, + successor_verification_attempt_digest, + successor_verification_attempt_released_at, + ) + if all(value is None for value in successor_values): + cutover = None + successor_ref = None + successor_digest = None + successor_release = None + elif any(value is None for value in successor_values): + raise ValueError( + "non-verifiability supersession requires cutover and complete successor attempt." + ) + else: + cutover = _require_aware_datetime("superseded_at", superseded_at) + successor_ref = _require_reference( + "successor_verification_attempt_reference", + successor_verification_attempt_reference, + "validation_evidence_verification_attempt", + ) + successor_digest = _require_digest( + "successor_verification_attempt_digest", + successor_verification_attempt_digest, + ) + successor_release = _require_aware_datetime( + "successor_verification_attempt_released_at", + successor_verification_attempt_released_at, + ) + if cutover <= release_instant: + raise ValueError( + "superseded_at must be later than non-verifiability release." + ) + if successor_ref == attempt_ref: + raise ValueError("successor verification attempt must use a new reference.") + if successor_digest in {result_evidence_digest, attempt_digest, owner_digest}: + raise ValueError("successor verification attempt must identify new evidence.") + if successor_release != cutover: + raise ValueError( + "successor verification attempt must be released exactly at supersession." + ) + + current_fields: tuple[tuple[str, object], ...] = ( + ("evidence_version", version), + ("failed_evidence_kind", evidence_kind), + ("failure_mode", mode), + ("owner_contract_digest", owner_digest), + ("owner_contract_reference", owner_ref), + ("owner_contract_released_at", owner_released), + ("owner_contract_version", owner_version), + ("result_digest", result_evidence_digest), + ("result_reference", result_ref), + ("verification_attempt_digest", attempt_digest), + ("verification_attempt_reference", attempt_ref), + ) + successor_fields: tuple[tuple[str, object], ...] | None + if cutover is None: + successor_fields = None + else: + successor_fields = ( + ("successor_verification_attempt_digest", successor_digest), + ("successor_verification_attempt_reference", successor_ref), + ("successor_verification_attempt_released_at", successor_release), + ) + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + current_fields, + release_instant, + cutover, + successor_fields, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable predecessor authority coordinates.""" + return self[2] + + @property + def released_at(self) -> datetime: + """Return when this non-verifiability outcome became released evidence.""" + return self[3] + + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive end of this negative outcome's authority interval.""" + return self[4] + + @property + def successor_fields(self) -> tuple[tuple[str, object], ...] | None: + """Return owner-internal successor verification-attempt coordinates.""" + return self[5] + + +class ValidationResultNonVerifiabilitySupersessionAuthorityView(tuple): + """Minimized predecessor authority issued only after purpose authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> ValidationResultNonVerifiabilitySupersessionAuthorityView: + """Reject public construction; only the resolver may issue this view.""" + raise TypeError( + "ValidationResultNonVerifiabilitySupersessionAuthorityView is issued only by " + "resolve_validation_result_nonverifiability_supersession_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return predecessor provenance without cutover or successor disclosure.""" + return self[2] + + +@runtime_checkable +class ValidationResultNonVerifiabilitySupersessionAuthorityReadPort(Protocol): + """Owner read contract for released non-verifiability supersession evidence.""" + + def read_validation_result_nonverifiability_supersession_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + failed_evidence_kind: str, + failure_mode: str, + verification_attempt_reference: str, + verification_attempt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + ) -> ValidationResultNonVerifiabilitySupersessionAuthorityRecord | None: + """Return matching released successor authority or ``None``.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + ValidationResultNonVerifiabilitySupersessionAuthorityReadPort, + "read_validation_result_nonverifiability_supersession_authority", +) + + +def resolve_validation_result_nonverifiability_supersession_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + failed_evidence_kind: str, + failure_mode: str, + verification_attempt_reference: str, + verification_attempt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: ValidationResultNonVerifiabilitySupersessionAuthorityReadPort, +) -> ValidationResultNonVerifiabilitySupersessionAuthorityView: + """Authorize then resolve one negative outcome's append-only authority interval.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static( + type(read_port), + "read_validation_result_nonverifiability_supersession_authority", + None, + ) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError( + "read_port must expose a statically callable " + "read_validation_result_nonverifiability_supersession_authority." + ) + + tenant_id = _restore_operational_uuid( + "tenant_record_id", _store_operational_uuid("tenant_record_id", tenant_record_id) + ) + study_id = _restore_operational_uuid( + "validity_study_id", _store_operational_uuid("validity_study_id", validity_study_id) + ) + result_ref = _require_reference( + "result_reference", result_reference, "validation_analysis_result" + ) + result_evidence_digest = _require_digest("result_digest", result_digest) + evidence_kind = _require_failed_evidence_kind(failed_evidence_kind) + mode = _require_failure_mode(failure_mode) + attempt_ref = _require_reference( + "verification_attempt_reference", + verification_attempt_reference, + "validation_evidence_verification_attempt", + ) + attempt_digest = _require_digest( + "verification_attempt_digest", verification_attempt_digest + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1.") + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + detached_policy = _detach_policy(policy) + + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + + persisted = read_capability( + read_port, + tenant_record_id=tenant_id, + validity_study_id=study_id, + result_reference=result_ref, + result_digest=result_evidence_digest, + failed_evidence_kind=evidence_kind, + failure_mode=mode, + verification_attempt_reference=attempt_ref, + verification_attempt_digest=attempt_digest, + evidence_version=version, + owner_contract_reference=owner_ref, + owner_contract_version=owner_version, + owner_contract_digest=owner_digest, + ) + if persisted is None: + raise ValidationResultNonVerifiabilitySupersessionAuthorityNotFound(str(study_id)) + if type(persisted) is not ValidationResultNonVerifiabilitySupersessionAuthorityRecord: + raise ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError( + "owner port returned non-canonical non-verifiability supersession evidence" + ) + + persisted_fields = dict(persisted.fields) + persisted_successor = ( + None if persisted.successor_fields is None else dict(persisted.successor_fields) + ) + record = ValidationResultNonVerifiabilitySupersessionAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + result_reference=persisted_fields["result_reference"], + result_digest=persisted_fields["result_digest"], + failed_evidence_kind=persisted_fields["failed_evidence_kind"], + failure_mode=persisted_fields["failure_mode"], + verification_attempt_reference=persisted_fields["verification_attempt_reference"], + verification_attempt_digest=persisted_fields["verification_attempt_digest"], + evidence_version=persisted_fields["evidence_version"], + owner_contract_reference=persisted_fields["owner_contract_reference"], + owner_contract_version=persisted_fields["owner_contract_version"], + owner_contract_digest=persisted_fields["owner_contract_digest"], + owner_contract_released_at=persisted_fields["owner_contract_released_at"], + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + successor_verification_attempt_reference=( + None + if persisted_successor is None + else persisted_successor["successor_verification_attempt_reference"] + ), + successor_verification_attempt_digest=( + None + if persisted_successor is None + else persisted_successor["successor_verification_attempt_digest"] + ), + successor_verification_attempt_released_at=( + None + if persisted_successor is None + else persisted_successor["successor_verification_attempt_released_at"] + ), + ) + record_values = dict(record.fields) + requested_values = { + "evidence_version": version, + "failed_evidence_kind": evidence_kind, + "failure_mode": mode, + "owner_contract_digest": owner_digest, + "owner_contract_reference": owner_ref, + "owner_contract_version": owner_version, + "result_digest": result_evidence_digest, + "result_reference": result_ref, + "verification_attempt_digest": attempt_digest, + "verification_attempt_reference": attempt_ref, + } + if ( + _store_operational_uuid("record tenant_record_id", record.tenant_record_id) + != _store_operational_uuid("requested tenant_record_id", tenant_id) + or _store_operational_uuid("record validity_study_id", record.validity_study_id) + != _store_operational_uuid("requested validity_study_id", study_id) + or any(record_values[name] != value for name, value in requested_values.items()) + ): + raise ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError( + "owner evidence does not match requested non-verifiability correction coordinates" + ) + if use_instant < record.released_at: + raise ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError( + "non-verifiability authority cannot be used before its release instant" + ) + if record.superseded_at is not None and use_instant >= record.superseded_at: + raise ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError( + "non-verifiability authority ended at its owner-resolved supersession instant" + ) + + values = {**record_values, "released_at": record.released_at} + fields = tuple((field_name, values[field_name]) for field_name in sorted(_VIEW_FIELDS)) + return tuple.__new__( + ValidationResultNonVerifiabilitySupersessionAuthorityView, + ( + _store_operational_uuid("tenant_record_id", tenant_id), + _store_operational_uuid("validity_study_id", study_id), + fields, + ), + ) + + +__all__ = [ + "ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError", + "ValidationResultNonVerifiabilitySupersessionAuthorityNotFound", + "ValidationResultNonVerifiabilitySupersessionAuthorityReadPort", + "ValidationResultNonVerifiabilitySupersessionAuthorityRecord", + "ValidationResultNonVerifiabilitySupersessionAuthorityView", + "resolve_validation_result_nonverifiability_supersession_authority", +] From 1f867f5d3fd8f1f51878880131c8782845710660 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 21:03:04 +0900 Subject: [PATCH 327/603] feat(workforce-validation): export non-verifiability successor authority --- .../orgmetra_workforce_validation_api/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index 3ae082d4a..18afcf429 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -106,6 +106,14 @@ ValidationResultNonVerifiabilityView, resolve_validation_result_nonverifiability, ) +from orgmetra_workforce_validation_api.result_nonverifiability_supersession_authority import ( + ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError, + ValidationResultNonVerifiabilitySupersessionAuthorityNotFound, + ValidationResultNonVerifiabilitySupersessionAuthorityReadPort, + ValidationResultNonVerifiabilitySupersessionAuthorityRecord, + ValidationResultNonVerifiabilitySupersessionAuthorityView, + resolve_validation_result_nonverifiability_supersession_authority, +) from orgmetra_workforce_validation_api.result_supersession_authority import ( ValidationResultSupersessionAuthorityIntegrityError, ValidationResultSupersessionAuthorityNotFound, @@ -248,6 +256,11 @@ "ValidationResultNonVerifiabilityNotFound", "ValidationResultNonVerifiabilityReadPort", "ValidationResultNonVerifiabilityRecord", + "ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError", + "ValidationResultNonVerifiabilitySupersessionAuthorityNotFound", + "ValidationResultNonVerifiabilitySupersessionAuthorityReadPort", + "ValidationResultNonVerifiabilitySupersessionAuthorityRecord", + "ValidationResultNonVerifiabilitySupersessionAuthorityView", "ValidationResultNonVerifiabilityView", "ValidationResultSupersessionAuthorityIntegrityError", "ValidationResultSupersessionAuthorityNotFound", @@ -295,6 +308,7 @@ "resolve_trimming_bounding_supersession_authority", "resolve_validation_result_authority", "resolve_validation_result_nonverifiability", + "resolve_validation_result_nonverifiability_supersession_authority", "resolve_validation_result_supersession_authority", "resolve_weight_eligibility_authority", "resolve_weight_eligibility_supersession_authority", From 7d5d5117ab456a297e6bb96b86e69be2389f1369 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 21:05:07 +0900 Subject: [PATCH 328/603] test(workforce-validation): cover negative-outcome successor edges --- ...ifiability_supersession_authority_edges.py | 361 ++++++++++++++++++ 1 file changed, 361 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py new file mode 100644 index 000000000..521bae9a7 --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py @@ -0,0 +1,361 @@ +"""Hostile edges for append-only non-verifiability successor authority.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.result_nonverifiability_supersession_authority import ( + ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError, + ValidationResultNonVerifiabilitySupersessionAuthorityNotFound, + ValidationResultNonVerifiabilitySupersessionAuthorityReadPort, + ValidationResultNonVerifiabilitySupersessionAuthorityRecord, + ValidationResultNonVerifiabilitySupersessionAuthorityView, + resolve_validation_result_nonverifiability_supersession_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000d2") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +OTHER_RESULT_REFERENCE = "validation_analysis_result:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" +ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:33333333-3333-4333-8333-333333333333" +OTHER_ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:44444444-4444-4444-8444-444444444444" +SUCCESSOR_ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:55555555-5555-4555-8555-555555555555" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +OTHER_OWNER_CONTRACT_REFERENCE = "released_owner_contract:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" +RESULT_DIGEST = "1" * 64 +ATTEMPT_DIGEST = "3" * 64 +SUCCESSOR_ATTEMPT_DIGEST = "5" * 64 +OWNER_CONTRACT_DIGEST = "2" * 64 +RELEASED_AT = datetime(2026, 9, 18, 8, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 1, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 18, 10, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "result_reference", + "result_digest", + "failed_evidence_kind", + "failure_mode", + "verification_attempt_reference", + "verification_attempt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_verification_attempt_reference", + "successor_verification_attempt_digest", + "successor_verification_attempt_released_at", + } +) + + +class _ReadPort: + """Return configured authority while retaining exact lookup coordinates.""" + + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[dict[str, object]] = [] + + def read_validation_result_nonverifiability_supersession_authority( + self, **coordinates: object + ) -> object: + """Capture the owner lookup and return configured evidence.""" + self.calls.append(dict(coordinates)) + return self.result + + +class _NoReadMethod: + """Deliberately fail the owner-port protocol.""" + + +class _ProtocolOnly(ValidationResultNonVerifiabilitySupersessionAuthorityReadPort): + """Inherit only the Protocol placeholder, not a concrete owner capability.""" + + +class _DescriptorReadPort: + """Expose a descriptor that static capability validation must reject.""" + + @property + def read_validation_result_nonverifiability_supersession_authority(self) -> object: + """Fail if descriptor execution leaks through static capability validation.""" + raise AssertionError("descriptor must not execute") + + +def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: + """Return a tenant-scoped validation principal.""" + return ValidationPrincipal( + tenant_record_id=tenant_record_id, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + """Return the exact purpose-bound policy for successor evidence.""" + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="validation-result-nonverifiability-supersession-read-v1", + resource_kind="validation_result_nonverifiability_supersession_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record(**overrides: object) -> ValidationResultNonVerifiabilitySupersessionAuthorityRecord: + """Build canonical owner evidence with optional hostile overrides.""" + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "result_reference": RESULT_REFERENCE, + "result_digest": RESULT_DIGEST, + "failed_evidence_kind": "analysis_weight_receipt", + "failure_mode": "missing", + "verification_attempt_reference": ATTEMPT_REFERENCE, + "verification_attempt_digest": ATTEMPT_DIGEST, + "evidence_version": 1, + "owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "owner_contract_version": 3, + "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, + "released_at": RELEASED_AT, + "superseded_at": None, + "successor_verification_attempt_reference": None, + "successor_verification_attempt_digest": None, + "successor_verification_attempt_released_at": None, + } + values.update(overrides) + return ValidationResultNonVerifiabilitySupersessionAuthorityRecord(**values) + + +def _resolve( + *, read_port: object, **overrides: object +) -> ValidationResultNonVerifiabilitySupersessionAuthorityView: + """Resolve canonical request coordinates with optional hostile overrides.""" + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "result_reference": RESULT_REFERENCE, + "result_digest": RESULT_DIGEST, + "failed_evidence_kind": "analysis_weight_receipt", + "failure_mode": "missing", + "verification_attempt_reference": ATTEMPT_REFERENCE, + "verification_attempt_digest": ATTEMPT_DIGEST, + "evidence_version": 1, + "owner_contract_reference": OWNER_CONTRACT_REFERENCE, + "owner_contract_version": 3, + "owner_contract_digest": OWNER_CONTRACT_DIGEST, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_validation_result_nonverifiability_supersession_authority(**values) + + +def test_current_negative_outcome_resolves_without_successor_coordinates() -> None: + """Use owner chronology while keeping successor and cutover data private.""" + port = _ReadPort(_record()) + view = _resolve(read_port=port) + + assert isinstance(port, ValidationResultNonVerifiabilitySupersessionAuthorityReadPort) + assert len(port.calls) == 1 + assert port.calls[0]["verification_attempt_reference"] == ATTEMPT_REFERENCE + assert "owner_contract_released_at" not in port.calls[0] + assert "released_at" not in port.calls[0] + assert "superseded_at" not in port.calls[0] + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + fields = dict(view.fields) + assert fields["owner_contract_released_at"] == OWNER_CONTRACT_RELEASED_AT + assert fields["released_at"] == RELEASED_AT + assert "superseded_at" not in fields + assert "successor_verification_attempt_reference" not in fields + + +def test_authorization_denial_happens_before_owner_resolution() -> None: + """Keep denial ahead of any owner evidence lookup.""" + port = _ReadPort(_record()) + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, policy=_policy(purpose_code="audit_review")) + assert port.calls == [] + + +def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: + """Reject absence and foreign record types after authorization.""" + with pytest.raises(ValidationResultNonVerifiabilitySupersessionAuthorityNotFound): + _resolve(read_port=_ReadPort(None)) + with pytest.raises(ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object())) + + +@pytest.mark.parametrize( + "record_overrides", + [ + {"tenant_record_id": OTHER_TENANT}, + {"validity_study_id": OTHER_STUDY}, + {"result_reference": OTHER_RESULT_REFERENCE}, + {"result_digest": "a" * 64}, + {"failed_evidence_kind": "variance_design_receipt"}, + {"failure_mode": "non_reproducible"}, + {"verification_attempt_reference": OTHER_ATTEMPT_REFERENCE}, + {"verification_attempt_digest": "c" * 64}, + {"owner_contract_reference": OTHER_OWNER_CONTRACT_REFERENCE}, + {"owner_contract_version": 4}, + {"owner_contract_digest": "b" * 64}, + ], +) +def test_owner_evidence_must_match_every_requested_coordinate( + record_overrides: dict[str, object] +) -> None: + """Reject owner evidence selected by an incomplete or different lookup tuple.""" + if record_overrides.get("failure_mode") == "non_reproducible": + record_overrides = {"failure_mode": "non_reproducible"} + with pytest.raises((ValueError, ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError)): + _resolve(read_port=_ReadPort(_record(**record_overrides))) + + +def test_release_chronology_and_historical_use_are_half_open() -> None: + """Reject pre-release use while preserving reproducible historical reads.""" + with pytest.raises(ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(released_at=USED_AT + timedelta(seconds=1)))) + + cutover = USED_AT + timedelta(seconds=1) + record = _record( + superseded_at=cutover, + successor_verification_attempt_reference=SUCCESSOR_ATTEMPT_REFERENCE, + successor_verification_attempt_digest=SUCCESSOR_ATTEMPT_DIGEST, + successor_verification_attempt_released_at=cutover, + ) + view = _resolve(read_port=_ReadPort(record)) + assert dict(view.fields)["result_digest"] == RESULT_DIGEST + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("result_reference", "wrong:result", ValueError), + ("result_digest", "ABC", ValueError), + ("failed_evidence_kind", "unknown", ValueError), + ("failure_mode", "green", ValueError), + ("verification_attempt_reference", "wrong:attempt", ValueError), + ("verification_attempt_digest", "3" * 63, ValueError), + ("evidence_version", False, ValueError), + ("evidence_version", 2, ValueError), + ("owner_contract_reference", "wrong:contract", ValueError), + ("owner_contract_version", 0, ValueError), + ("owner_contract_digest", "2" * 63, ValueError), + ("used_at", datetime(2026, 9, 18), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_or_dependency_fails_before_owner_resolution( + key: str, value: object, error: type[Exception] +) -> None: + """Validate request and dependency shapes before any owner read occurs.""" + port: object = _ReadPort(_record()) + overrides = {key: value} + if key == "read_port": + port = value + overrides = {} + with pytest.raises(error): + _resolve(read_port=port, **overrides) + if isinstance(port, _ReadPort): + assert port.calls == [] + + +def test_record_rejects_non_v1_and_public_view_construction() -> None: + """Keep evidence version governed and view issuance resolver-only.""" + with pytest.raises(ValueError, match="evidence_version must remain 1"): + _record(evidence_version=2) + with pytest.raises(TypeError, match="issued only by"): + ValidationResultNonVerifiabilitySupersessionAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) + + +def test_record_rejects_naive_chronology_and_malformed_successor() -> None: + """Reject malformed owner chronology before it can become current evidence.""" + with pytest.raises(ValueError): + _record(owner_contract_released_at=datetime(2026, 9, 1)) + with pytest.raises(ValueError): + _record(released_at=datetime(2026, 9, 18, 8)) + with pytest.raises(ValueError): + _record(owner_contract_released_at=RELEASED_AT + timedelta(seconds=1)) + with pytest.raises(ValueError): + _record( + superseded_at=datetime(2026, 9, 18, 11), + successor_verification_attempt_reference=SUCCESSOR_ATTEMPT_REFERENCE, + successor_verification_attempt_digest=SUCCESSOR_ATTEMPT_DIGEST, + successor_verification_attempt_released_at=USED_AT, + ) + with pytest.raises(ValueError): + _record( + superseded_at=USED_AT + timedelta(hours=1), + successor_verification_attempt_reference="analysis_weight_receipt:55555555-5555-4555-8555-555555555555", + successor_verification_attempt_digest=SUCCESSOR_ATTEMPT_DIGEST, + successor_verification_attempt_released_at=USED_AT + timedelta(hours=1), + ) + with pytest.raises(ValueError): + _record( + superseded_at=USED_AT + timedelta(hours=1), + successor_verification_attempt_reference=SUCCESSOR_ATTEMPT_REFERENCE, + successor_verification_attempt_digest="not-a-digest", + successor_verification_attempt_released_at=USED_AT + timedelta(hours=1), + ) + + +@pytest.mark.parametrize("alias_digest", [RESULT_DIGEST, ATTEMPT_DIGEST, OWNER_CONTRACT_DIGEST]) +def test_successor_digest_must_not_alias_existing_evidence(alias_digest: str) -> None: + """Require the successor attempt to identify genuinely new immutable evidence.""" + cutover = USED_AT + timedelta(hours=1) + with pytest.raises(ValueError, match="must identify new evidence"): + _record( + superseded_at=cutover, + successor_verification_attempt_reference=SUCCESSOR_ATTEMPT_REFERENCE, + successor_verification_attempt_digest=alias_digest, + successor_verification_attempt_released_at=cutover, + ) + + +def test_record_and_view_are_structurally_immutable_and_uuid_views_are_detached() -> None: + """Prevent retained UUID aliases or attribute writes from mutating accepted authority.""" + tenant = UUID(str(TENANT)) + record = _record(tenant_record_id=tenant) + object.__setattr__(tenant, "int", OTHER_TENANT.int) + assert record.tenant_record_id == TENANT + assert record.validity_study_id == STUDY + assert record.released_at == RELEASED_AT + assert record.superseded_at is None + assert record.successor_fields is None + assert dict(record.fields)["evidence_version"] == 1 + with pytest.raises(AttributeError): + object.__setattr__(record, "evidence_version", 2) + + view = _resolve(read_port=_ReadPort(record)) + returned_tenant = view.tenant_record_id + object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) + assert view.tenant_record_id == TENANT + with pytest.raises(AttributeError): + object.__setattr__(view, "fields", ()) From 7326e580528a0f6e3007d6611929fe334d50800e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 21:05:55 +0900 Subject: [PATCH 329/603] docs(workforce-validation): document negative-outcome successor authority --- services/workforce-validation-api/README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index e5f111894..dfaec8c73 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -120,15 +120,21 @@ The binding resolves owner-contract release and optional exclusive supersession The immutable `verification_attempt_reference` and `verification_attempt_digest` are part of the resolver and owner-read lookup identity. Verification-attempt release, governing owner-contract release and optional exclusive `superseded_at` remain owner-resolved chronology. The immutable attempt receipt must satisfy `evaluated_at <= verification_attempt_released_at <= released_at`, and the ordinary resolver accepts the released negative outcome only on `[released_at, superseded_at)`. +## Validation-result non-verifiability supersession authority + +`resolve_validation_result_nonverifiability_supersession_authority(...)` proves why an owner-resolved negative-outcome cutover exists. A predecessor `not_verifiable` outcome may end only with a complete immutable successor verification-attempt reference/digest/release tuple. The successor attempt must identify new evidence and be released exactly at the predecessor `superseded_at`; cutover and successor coordinates are owner evidence, not caller timestamps. + +The minimized view deliberately omits both the cutover and successor attempt. A new verification attempt ends the predecessor negative outcome but does not itself imply scientific GREEN: any subsequent released result or negative outcome must still satisfy its own governed owner contract and verification boundary. + ## Persistence state `services/workforce-validation-api/database/migrations/0001_owner_schema.sql` starts this bounded context's migration history. It creates the `workforce_validation` schema and a deny-default `workforce_validation_role`, revokes public schema access, and intentionally creates or moves no application table yet. The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **twenty** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration support chronology, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, base/design-weight supersession, complete final analysis-weight lineage, final-weight supersession, point-weight/variance compatibility, point-weight/variance supersession, validation-result binding, validation-result supersession, and validation-result non-verifiability. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **twenty-one** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration support chronology, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, base/design-weight supersession, complete final analysis-weight lineage, final-weight supersession, point-weight/variance compatibility, point-weight/variance supersession, validation-result binding, validation-result supersession, validation-result non-verifiability, and validation-result non-verifiability supersession. -The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable verification-attempt reference/digest and preserve failed-evidence and attempt-release chronology. No durable adapter may infer currentness from mutable current rows or caller-supplied timestamps. +The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable verification-attempt reference/digest, preserve failed-evidence and attempt-release chronology, and cross-check an ordinary `superseded_at` against the explicit successor verification-attempt release instant. No durable adapter may infer currentness from mutable current rows or caller-supplied timestamps. ## Test contract @@ -147,6 +153,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity and chronology. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity, chronology, currentness, and explicit successor-attempt authority. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. \ No newline at end of file From d22dde081483bb7cb2763a164f7bd2425fc92d36 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 22:04:38 +0900 Subject: [PATCH 330/603] test(validation): require same-result successor binding --- ...nverifiability_successor_result_binding.py | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_successor_result_binding.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_successor_result_binding.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_successor_result_binding.py new file mode 100644 index 000000000..fa7ed70cb --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_successor_result_binding.py @@ -0,0 +1,86 @@ +"""Bind negative-outcome supersession to a re-verification of the same result.""" + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.result_nonverifiability_supersession_authority import ( + ValidationResultNonVerifiabilitySupersessionAuthorityRecord, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +OTHER_RESULT_REFERENCE = "validation_analysis_result:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:33333333-3333-4333-8333-333333333333" +SUCCESSOR_ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:44444444-4444-4444-8444-444444444444" +RESULT_DIGEST = "1" * 64 +OTHER_RESULT_DIGEST = "a" * 64 +OWNER_CONTRACT_DIGEST = "2" * 64 +ATTEMPT_DIGEST = "3" * 64 +SUCCESSOR_ATTEMPT_DIGEST = "4" * 64 +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 1, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 18, 8, tzinfo=timezone.utc) +CUTOVER = RELEASED_AT + timedelta(hours=1) + + +def _record( + *, + successor_target_result_reference: str | None = RESULT_REFERENCE, + successor_target_result_digest: str | None = RESULT_DIGEST, +) -> ValidationResultNonVerifiabilitySupersessionAuthorityRecord: + """Build a released predecessor with one owner-resolved successor attempt.""" + return ValidationResultNonVerifiabilitySupersessionAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + failed_evidence_kind="analysis_weight_receipt", + failure_mode="missing", + verification_attempt_reference=ATTEMPT_REFERENCE, + verification_attempt_digest=ATTEMPT_DIGEST, + evidence_version=1, + owner_contract_reference=OWNER_CONTRACT_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_CONTRACT_DIGEST, + owner_contract_released_at=OWNER_CONTRACT_RELEASED_AT, + released_at=RELEASED_AT, + superseded_at=CUTOVER, + successor_target_result_reference=successor_target_result_reference, + successor_target_result_digest=successor_target_result_digest, + successor_verification_attempt_reference=SUCCESSOR_ATTEMPT_REFERENCE, + successor_verification_attempt_digest=SUCCESSOR_ATTEMPT_DIGEST, + successor_verification_attempt_released_at=CUTOVER, + ) + + +def test_successor_attempt_is_bound_to_the_exact_predecessor_result() -> None: + """Persist the successor target while keeping it owner-internal and exact.""" + record = _record() + + successor = dict(record.successor_fields or ()) + assert successor["successor_target_result_reference"] == RESULT_REFERENCE + assert successor["successor_target_result_digest"] == RESULT_DIGEST + + +@pytest.mark.parametrize( + ("successor_target_result_reference", "successor_target_result_digest"), + [ + (OTHER_RESULT_REFERENCE, RESULT_DIGEST), + (RESULT_REFERENCE, OTHER_RESULT_DIGEST), + (None, RESULT_DIGEST), + (RESULT_REFERENCE, None), + ], +) +def test_unrelated_or_incomplete_successor_result_binding_fails_closed( + successor_target_result_reference: str | None, + successor_target_result_digest: str | None, +) -> None: + """An unrelated verification attempt cannot retire this result's negative outcome.""" + with pytest.raises(ValueError): + _record( + successor_target_result_reference=successor_target_result_reference, + successor_target_result_digest=successor_target_result_digest, + ) From 7a0a7b694c5d73ee05e66418078717f0fccf647d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 22:06:53 +0900 Subject: [PATCH 331/603] fix(validation): bind successor attempt to same result --- ...nonverifiability_supersession_authority.py | 43 +++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py index 83f3980b7..743c6604a 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py @@ -109,11 +109,13 @@ def __new__( owner_contract_released_at: datetime, released_at: datetime, superseded_at: datetime | None = None, + successor_target_result_reference: str | None = None, + successor_target_result_digest: str | None = None, successor_verification_attempt_reference: str | None = None, successor_verification_attempt_digest: str | None = None, successor_verification_attempt_released_at: datetime | None = None, ) -> ValidationResultNonVerifiabilitySupersessionAuthorityRecord: - """Validate predecessor chronology and one complete immutable successor attempt.""" + """Validate predecessor chronology and one complete same-result successor attempt.""" tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) study_identity = _store_operational_uuid("validity_study_id", validity_study_id) result_ref = _require_reference( @@ -155,21 +157,35 @@ def __new__( successor_values = ( superseded_at, + successor_target_result_reference, + successor_target_result_digest, successor_verification_attempt_reference, successor_verification_attempt_digest, successor_verification_attempt_released_at, ) if all(value is None for value in successor_values): cutover = None + successor_target_ref = None + successor_target_digest = None successor_ref = None successor_digest = None successor_release = None elif any(value is None for value in successor_values): raise ValueError( - "non-verifiability supersession requires cutover and complete successor attempt." + "non-verifiability supersession requires cutover, same-result binding, and " + "complete successor attempt." ) else: cutover = _require_aware_datetime("superseded_at", superseded_at) + successor_target_ref = _require_reference( + "successor_target_result_reference", + successor_target_result_reference, + "validation_analysis_result", + ) + successor_target_digest = _require_digest( + "successor_target_result_digest", + successor_target_result_digest, + ) successor_ref = _require_reference( "successor_verification_attempt_reference", successor_verification_attempt_reference, @@ -187,6 +203,13 @@ def __new__( raise ValueError( "superseded_at must be later than non-verifiability release." ) + if ( + successor_target_ref != result_ref + or successor_target_digest != result_evidence_digest + ): + raise ValueError( + "successor verification attempt must target the exact predecessor result." + ) if successor_ref == attempt_ref: raise ValueError("successor verification attempt must use a new reference.") if successor_digest in {result_evidence_digest, attempt_digest, owner_digest}: @@ -214,6 +237,8 @@ def __new__( successor_fields = None else: successor_fields = ( + ("successor_target_result_digest", successor_target_digest), + ("successor_target_result_reference", successor_target_ref), ("successor_verification_attempt_digest", successor_digest), ("successor_verification_attempt_reference", successor_ref), ("successor_verification_attempt_released_at", successor_release), @@ -257,7 +282,7 @@ def superseded_at(self) -> datetime | None: @property def successor_fields(self) -> tuple[tuple[str, object], ...] | None: - """Return owner-internal successor verification-attempt coordinates.""" + """Return owner-internal successor attempt and exact target-result coordinates.""" return self[5] @@ -461,6 +486,16 @@ def resolve_validation_result_nonverifiability_supersession_authority( owner_contract_released_at=persisted_fields["owner_contract_released_at"], released_at=persisted.released_at, superseded_at=persisted.superseded_at, + successor_target_result_reference=( + None + if persisted_successor is None + else persisted_successor["successor_target_result_reference"] + ), + successor_target_result_digest=( + None + if persisted_successor is None + else persisted_successor["successor_target_result_digest"] + ), successor_verification_attempt_reference=( None if persisted_successor is None @@ -528,4 +563,4 @@ def resolve_validation_result_nonverifiability_supersession_authority( "ValidationResultNonVerifiabilitySupersessionAuthorityRecord", "ValidationResultNonVerifiabilitySupersessionAuthorityView", "resolve_validation_result_nonverifiability_supersession_authority", -] +] \ No newline at end of file From e2cf48d7ed422f668a0891493275c0861eb0e9fc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 22:07:16 +0900 Subject: [PATCH 332/603] test(validation): carry successor result binding fixtures --- ...idation_result_nonverifiability_supersession_authority.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority.py index 71cb6eba2..1cf219793 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority.py @@ -105,7 +105,8 @@ def _record( successor_digest: str | None, successor_released_at: datetime | None, ) -> ValidationResultNonVerifiabilitySupersessionAuthorityRecord: - """Build one canonical predecessor and optional successor verification attempt.""" + """Build one canonical predecessor and optional same-result successor attempt.""" + has_successor = successor_reference is not None return ValidationResultNonVerifiabilitySupersessionAuthorityRecord( tenant_record_id=TENANT, validity_study_id=STUDY, @@ -122,6 +123,8 @@ def _record( owner_contract_released_at=OWNER_CONTRACT_RELEASED_AT, released_at=RELEASED_AT, superseded_at=superseded_at, + successor_target_result_reference=(RESULT_REFERENCE if has_successor else None), + successor_target_result_digest=(RESULT_DIGEST if has_successor else None), successor_verification_attempt_reference=successor_reference, successor_verification_attempt_digest=successor_digest, successor_verification_attempt_released_at=successor_released_at, From c1b225a45ccf334ef4e2dcf5feab056fd28d8a87 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 22:07:57 +0900 Subject: [PATCH 333/603] test(validation): adapt supersession hostile fixtures --- ...onverifiability_supersession_authority_edges.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py index 521bae9a7..3d5292856 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py @@ -130,11 +130,23 @@ def _record(**overrides: object) -> ValidationResultNonVerifiabilitySupersession "owner_contract_released_at": OWNER_CONTRACT_RELEASED_AT, "released_at": RELEASED_AT, "superseded_at": None, + "successor_target_result_reference": None, + "successor_target_result_digest": None, "successor_verification_attempt_reference": None, "successor_verification_attempt_digest": None, "successor_verification_attempt_released_at": None, } values.update(overrides) + if ( + "successor_target_result_reference" not in overrides + and values["successor_verification_attempt_reference"] is not None + ): + values["successor_target_result_reference"] = values["result_reference"] + if ( + "successor_target_result_digest" not in overrides + and values["successor_verification_attempt_reference"] is not None + ): + values["successor_target_result_digest"] = values["result_digest"] return ValidationResultNonVerifiabilitySupersessionAuthorityRecord(**values) @@ -358,4 +370,4 @@ def test_record_and_view_are_structurally_immutable_and_uuid_views_are_detached( object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) assert view.tenant_record_id == TENANT with pytest.raises(AttributeError): - object.__setattr__(view, "fields", ()) + object.__setattr__(view, "fields", ()) \ No newline at end of file From d7adda6ab15eba2908010f8da84cc3cb0fb833e1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 22:10:35 +0900 Subject: [PATCH 334/603] fix(validation): authorize successor target evidence --- .../result_nonverifiability_supersession_authority.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py index 743c6604a..da2269404 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py @@ -55,6 +55,8 @@ "owner_contract_released_at", "released_at", "superseded_at", + "successor_target_result_reference", + "successor_target_result_digest", "successor_verification_attempt_reference", "successor_verification_attempt_digest", "successor_verification_attempt_released_at", @@ -563,4 +565,4 @@ def resolve_validation_result_nonverifiability_supersession_authority( "ValidationResultNonVerifiabilitySupersessionAuthorityRecord", "ValidationResultNonVerifiabilitySupersessionAuthorityView", "resolve_validation_result_nonverifiability_supersession_authority", -] \ No newline at end of file +] From e9ed56c6df11c3fb0641caa99b3439a54c56d841 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 22:11:08 +0900 Subject: [PATCH 335/603] test(validation): authorize successor target fields --- ...alidation_result_nonverifiability_supersession_authority.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority.py index 1cf219793..d70f81ea4 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority.py @@ -43,6 +43,8 @@ "owner_contract_released_at", "released_at", "superseded_at", + "successor_target_result_reference", + "successor_target_result_digest", "successor_verification_attempt_reference", "successor_verification_attempt_digest", "successor_verification_attempt_released_at", @@ -175,6 +177,7 @@ def test_historical_negative_outcome_hides_successor_attempt() -> None: assert fields["failed_evidence_kind"] == "analysis_weight_receipt" assert "superseded_at" not in fields assert "successor_verification_attempt_reference" not in fields + assert "successor_target_result_reference" not in fields def test_negative_outcome_fails_closed_at_successor_cutover() -> None: From 4f8136207db975a6789eb69b36fee749f53ae3e7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 22:11:49 +0900 Subject: [PATCH 336/603] test(validation): authorize successor target edge fields --- ...n_result_nonverifiability_supersession_authority_edges.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py index 3d5292856..34d888a20 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py @@ -51,6 +51,8 @@ "owner_contract_released_at", "released_at", "superseded_at", + "successor_target_result_reference", + "successor_target_result_digest", "successor_verification_attempt_reference", "successor_verification_attempt_digest", "successor_verification_attempt_released_at", @@ -195,6 +197,7 @@ def test_current_negative_outcome_resolves_without_successor_coordinates() -> No assert fields["released_at"] == RELEASED_AT assert "superseded_at" not in fields assert "successor_verification_attempt_reference" not in fields + assert "successor_target_result_reference" not in fields def test_authorization_denial_happens_before_owner_resolution() -> None: @@ -370,4 +373,4 @@ def test_record_and_view_are_structurally_immutable_and_uuid_views_are_detached( object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) assert view.tenant_record_id == TENANT with pytest.raises(AttributeError): - object.__setattr__(view, "fields", ()) \ No newline at end of file + object.__setattr__(view, "fields", ()) From 77cfba5edc5cb82952c4c07cb9b75f746653a40c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 22:14:09 +0900 Subject: [PATCH 337/603] docs(validation): document same-result supersession binding --- services/workforce-validation-api/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index dfaec8c73..60869b40f 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -122,9 +122,9 @@ The immutable `verification_attempt_reference` and `verification_attempt_digest` ## Validation-result non-verifiability supersession authority -`resolve_validation_result_nonverifiability_supersession_authority(...)` proves why an owner-resolved negative-outcome cutover exists. A predecessor `not_verifiable` outcome may end only with a complete immutable successor verification-attempt reference/digest/release tuple. The successor attempt must identify new evidence and be released exactly at the predecessor `superseded_at`; cutover and successor coordinates are owner evidence, not caller timestamps. +`resolve_validation_result_nonverifiability_supersession_authority(...)` proves why an owner-resolved negative-outcome cutover exists. A predecessor `not_verifiable` outcome may end only with a complete immutable successor verification-attempt reference/digest/release tuple plus an owner-supplied target-result reference/digest. The successor target must equal the predecessor `result_reference` and `result_digest` exactly, the successor attempt must identify new evidence, and its release must equal the predecessor `superseded_at`; an unrelated verification attempt cannot retire this result's negative-outcome interval. All cutover, target-result, and successor-attempt coordinates are purpose-authorized owner evidence, not caller timestamps. -The minimized view deliberately omits both the cutover and successor attempt. A new verification attempt ends the predecessor negative outcome but does not itself imply scientific GREEN: any subsequent released result or negative outcome must still satisfy its own governed owner contract and verification boundary. +The minimized view deliberately omits the cutover, successor target, and successor attempt. A new same-result verification attempt ends the predecessor negative outcome but does not itself imply scientific GREEN: any subsequent released result or negative outcome must still satisfy its own governed owner contract and verification boundary. ## Persistence state @@ -134,7 +134,7 @@ The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL r Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **twenty-one** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration support chronology, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, base/design-weight supersession, complete final analysis-weight lineage, final-weight supersession, point-weight/variance compatibility, point-weight/variance supersession, validation-result binding, validation-result supersession, validation-result non-verifiability, and validation-result non-verifiability supersession. -The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable verification-attempt reference/digest, preserve failed-evidence and attempt-release chronology, and cross-check an ordinary `superseded_at` against the explicit successor verification-attempt release instant. No durable adapter may infer currentness from mutable current rows or caller-supplied timestamps. +The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable verification-attempt reference/digest, preserve failed-evidence and attempt-release chronology, and cross-check an ordinary `superseded_at` against an explicit successor verification attempt that carries the same predecessor target-result reference/digest and is released exactly at cutover. No durable adapter may infer currentness from mutable current rows, unrelated verification attempts, or caller-supplied timestamps. ## Test contract @@ -153,6 +153,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity, chronology, currentness, and explicit successor-attempt authority. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity, chronology, currentness, and same-result successor-attempt authority with owner-internal target binding. -These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. \ No newline at end of file +These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From cf9a1e19c2580d97cc4784bf7275a91ad2b63d18 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 23:08:58 +0900 Subject: [PATCH 338/603] test(workforce-validation): require successor evidence-obligation binding --- ...erifiability_successor_evidence_binding.py | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_successor_evidence_binding.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_successor_evidence_binding.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_successor_evidence_binding.py new file mode 100644 index 000000000..6ed3c3d09 --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_successor_evidence_binding.py @@ -0,0 +1,65 @@ +"""Bind negative-outcome supersession to the same failed-evidence obligation.""" + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.result_nonverifiability_supersession_authority import ( + ValidationResultNonVerifiabilitySupersessionAuthorityRecord, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:33333333-3333-4333-8333-333333333333" +SUCCESSOR_ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:44444444-4444-4444-8444-444444444444" +RESULT_DIGEST = "1" * 64 +OWNER_CONTRACT_DIGEST = "2" * 64 +ATTEMPT_DIGEST = "3" * 64 +SUCCESSOR_ATTEMPT_DIGEST = "4" * 64 +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 1, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 18, 8, tzinfo=timezone.utc) +CUTOVER = RELEASED_AT + timedelta(hours=1) + + +def _record( + successor_failed_evidence_kind: str, +) -> ValidationResultNonVerifiabilitySupersessionAuthorityRecord: + """Build one supersession edge with an explicit successor evidence obligation.""" + return ValidationResultNonVerifiabilitySupersessionAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + failed_evidence_kind="analysis_weight_receipt", + failure_mode="missing", + verification_attempt_reference=ATTEMPT_REFERENCE, + verification_attempt_digest=ATTEMPT_DIGEST, + evidence_version=1, + owner_contract_reference=OWNER_CONTRACT_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_CONTRACT_DIGEST, + owner_contract_released_at=OWNER_CONTRACT_RELEASED_AT, + released_at=RELEASED_AT, + superseded_at=CUTOVER, + successor_target_result_reference=RESULT_REFERENCE, + successor_target_result_digest=RESULT_DIGEST, + successor_failed_evidence_kind=successor_failed_evidence_kind, + successor_verification_attempt_reference=SUCCESSOR_ATTEMPT_REFERENCE, + successor_verification_attempt_digest=SUCCESSOR_ATTEMPT_DIGEST, + successor_verification_attempt_released_at=CUTOVER, + ) + + +def test_successor_attempt_preserves_the_failed_evidence_obligation() -> None: + """Persist the obligation family that the successor attempt actually re-evaluates.""" + successor = dict(_record("analysis_weight_receipt").successor_fields or ()) + assert successor["successor_failed_evidence_kind"] == "analysis_weight_receipt" + + +def test_unrelated_evidence_family_cannot_retire_the_negative_outcome() -> None: + """A same-result attempt for another evidence family cannot end this failure interval.""" + with pytest.raises(ValueError, match="same failed-evidence obligation"): + _record("variance_design_receipt") From 9a53ceb2b11d5552073f228bea0ae1705c4abc6e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 23:09:46 +0900 Subject: [PATCH 339/603] fix(workforce-validation): bind successor attempt to failed evidence obligation --- ...nonverifiability_supersession_authority.py | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py index da2269404..051d88141 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py @@ -1,9 +1,9 @@ """Corroborate append-only supersession of released non-verifiability outcomes. A released ``not_verifiable`` outcome remains authoritative only until a new -immutable verification attempt re-evaluates the same result. This boundary -binds that successor attempt to the predecessor cutover without exposing -successor coordinates as reusable downstream authority. +immutable verification attempt re-evaluates the same result and failed-evidence +obligation. This boundary binds that successor attempt to the predecessor +cutover without exposing successor coordinates as reusable downstream authority. """ from __future__ import annotations @@ -57,6 +57,7 @@ "superseded_at", "successor_target_result_reference", "successor_target_result_digest", + "successor_failed_evidence_kind", "successor_verification_attempt_reference", "successor_verification_attempt_digest", "successor_verification_attempt_released_at", @@ -113,11 +114,12 @@ def __new__( superseded_at: datetime | None = None, successor_target_result_reference: str | None = None, successor_target_result_digest: str | None = None, + successor_failed_evidence_kind: str | None = None, successor_verification_attempt_reference: str | None = None, successor_verification_attempt_digest: str | None = None, successor_verification_attempt_released_at: datetime | None = None, ) -> ValidationResultNonVerifiabilitySupersessionAuthorityRecord: - """Validate predecessor chronology and one complete same-result successor attempt.""" + """Validate predecessor chronology and one complete same-obligation successor attempt.""" tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) study_identity = _store_operational_uuid("validity_study_id", validity_study_id) result_ref = _require_reference( @@ -161,6 +163,7 @@ def __new__( superseded_at, successor_target_result_reference, successor_target_result_digest, + successor_failed_evidence_kind, successor_verification_attempt_reference, successor_verification_attempt_digest, successor_verification_attempt_released_at, @@ -169,13 +172,14 @@ def __new__( cutover = None successor_target_ref = None successor_target_digest = None + successor_evidence_kind = None successor_ref = None successor_digest = None successor_release = None elif any(value is None for value in successor_values): raise ValueError( - "non-verifiability supersession requires cutover, same-result binding, and " - "complete successor attempt." + "non-verifiability supersession requires cutover, same-result and " + "failed-evidence-obligation binding, and complete successor attempt." ) else: cutover = _require_aware_datetime("superseded_at", superseded_at) @@ -188,6 +192,9 @@ def __new__( "successor_target_result_digest", successor_target_result_digest, ) + successor_evidence_kind = _require_failed_evidence_kind( + successor_failed_evidence_kind + ) successor_ref = _require_reference( "successor_verification_attempt_reference", successor_verification_attempt_reference, @@ -212,6 +219,10 @@ def __new__( raise ValueError( "successor verification attempt must target the exact predecessor result." ) + if successor_evidence_kind != evidence_kind: + raise ValueError( + "successor verification attempt must re-evaluate the same failed-evidence obligation." + ) if successor_ref == attempt_ref: raise ValueError("successor verification attempt must use a new reference.") if successor_digest in {result_evidence_digest, attempt_digest, owner_digest}: @@ -239,6 +250,7 @@ def __new__( successor_fields = None else: successor_fields = ( + ("successor_failed_evidence_kind", successor_evidence_kind), ("successor_target_result_digest", successor_target_digest), ("successor_target_result_reference", successor_target_ref), ("successor_verification_attempt_digest", successor_digest), @@ -284,7 +296,7 @@ def superseded_at(self) -> datetime | None: @property def successor_fields(self) -> tuple[tuple[str, object], ...] | None: - """Return owner-internal successor attempt and exact target-result coordinates.""" + """Return owner-internal successor obligation, attempt, and target-result coordinates.""" return self[5] @@ -498,6 +510,11 @@ def resolve_validation_result_nonverifiability_supersession_authority( if persisted_successor is None else persisted_successor["successor_target_result_digest"] ), + successor_failed_evidence_kind=( + None + if persisted_successor is None + else persisted_successor["successor_failed_evidence_kind"] + ), successor_verification_attempt_reference=( None if persisted_successor is None From 9ee10b48cbd2ae0587fcff2c506d83c9e7fec982 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 23:10:21 +0900 Subject: [PATCH 340/603] test(workforce-validation): carry successor evidence obligation --- ...idation_result_nonverifiability_supersession_authority.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority.py index d70f81ea4..c403df64b 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority.py @@ -45,6 +45,7 @@ "superseded_at", "successor_target_result_reference", "successor_target_result_digest", + "successor_failed_evidence_kind", "successor_verification_attempt_reference", "successor_verification_attempt_digest", "successor_verification_attempt_released_at", @@ -107,7 +108,7 @@ def _record( successor_digest: str | None, successor_released_at: datetime | None, ) -> ValidationResultNonVerifiabilitySupersessionAuthorityRecord: - """Build one canonical predecessor and optional same-result successor attempt.""" + """Build one canonical predecessor and optional same-obligation successor attempt.""" has_successor = successor_reference is not None return ValidationResultNonVerifiabilitySupersessionAuthorityRecord( tenant_record_id=TENANT, @@ -127,6 +128,7 @@ def _record( superseded_at=superseded_at, successor_target_result_reference=(RESULT_REFERENCE if has_successor else None), successor_target_result_digest=(RESULT_DIGEST if has_successor else None), + successor_failed_evidence_kind=("analysis_weight_receipt" if has_successor else None), successor_verification_attempt_reference=successor_reference, successor_verification_attempt_digest=successor_digest, successor_verification_attempt_released_at=successor_released_at, @@ -178,6 +180,7 @@ def test_historical_negative_outcome_hides_successor_attempt() -> None: assert "superseded_at" not in fields assert "successor_verification_attempt_reference" not in fields assert "successor_target_result_reference" not in fields + assert "successor_failed_evidence_kind" not in fields def test_negative_outcome_fails_closed_at_successor_cutover() -> None: From 2c0e71a69807c407f2b04188d33a837a15d4dc0d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 23:11:05 +0900 Subject: [PATCH 341/603] test(workforce-validation): align hostile successor obligation fixtures --- ...esult_nonverifiability_supersession_authority_edges.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py index 34d888a20..49b760859 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py @@ -53,6 +53,7 @@ "superseded_at", "successor_target_result_reference", "successor_target_result_digest", + "successor_failed_evidence_kind", "successor_verification_attempt_reference", "successor_verification_attempt_digest", "successor_verification_attempt_released_at", @@ -134,6 +135,7 @@ def _record(**overrides: object) -> ValidationResultNonVerifiabilitySupersession "superseded_at": None, "successor_target_result_reference": None, "successor_target_result_digest": None, + "successor_failed_evidence_kind": None, "successor_verification_attempt_reference": None, "successor_verification_attempt_digest": None, "successor_verification_attempt_released_at": None, @@ -149,6 +151,11 @@ def _record(**overrides: object) -> ValidationResultNonVerifiabilitySupersession and values["successor_verification_attempt_reference"] is not None ): values["successor_target_result_digest"] = values["result_digest"] + if ( + "successor_failed_evidence_kind" not in overrides + and values["successor_verification_attempt_reference"] is not None + ): + values["successor_failed_evidence_kind"] = values["failed_evidence_kind"] return ValidationResultNonVerifiabilitySupersessionAuthorityRecord(**values) @@ -198,6 +205,7 @@ def test_current_negative_outcome_resolves_without_successor_coordinates() -> No assert "superseded_at" not in fields assert "successor_verification_attempt_reference" not in fields assert "successor_target_result_reference" not in fields + assert "successor_failed_evidence_kind" not in fields def test_authorization_denial_happens_before_owner_resolution() -> None: From 010773485bcd2a6793f6d75f461eec311878a115 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 23:11:25 +0900 Subject: [PATCH 342/603] test(workforce-validation): keep same-result fixture on same evidence obligation --- ...lidation_result_nonverifiability_successor_result_binding.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_successor_result_binding.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_successor_result_binding.py index fa7ed70cb..03862df55 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_successor_result_binding.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_successor_result_binding.py @@ -50,6 +50,7 @@ def _record( superseded_at=CUTOVER, successor_target_result_reference=successor_target_result_reference, successor_target_result_digest=successor_target_result_digest, + successor_failed_evidence_kind="analysis_weight_receipt", successor_verification_attempt_reference=SUCCESSOR_ATTEMPT_REFERENCE, successor_verification_attempt_digest=SUCCESSOR_ATTEMPT_DIGEST, successor_verification_attempt_released_at=CUTOVER, @@ -63,6 +64,7 @@ def test_successor_attempt_is_bound_to_the_exact_predecessor_result() -> None: successor = dict(record.successor_fields or ()) assert successor["successor_target_result_reference"] == RESULT_REFERENCE assert successor["successor_target_result_digest"] == RESULT_DIGEST + assert successor["successor_failed_evidence_kind"] == "analysis_weight_receipt" @pytest.mark.parametrize( From 94c9952e4712610a0b4ec2653edc39c7aee768c2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 18 Sep 2026 23:12:29 +0900 Subject: [PATCH 343/603] docs(workforce-validation): require same-obligation successor verification --- services/workforce-validation-api/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 60869b40f..2a075c6bc 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -122,9 +122,9 @@ The immutable `verification_attempt_reference` and `verification_attempt_digest` ## Validation-result non-verifiability supersession authority -`resolve_validation_result_nonverifiability_supersession_authority(...)` proves why an owner-resolved negative-outcome cutover exists. A predecessor `not_verifiable` outcome may end only with a complete immutable successor verification-attempt reference/digest/release tuple plus an owner-supplied target-result reference/digest. The successor target must equal the predecessor `result_reference` and `result_digest` exactly, the successor attempt must identify new evidence, and its release must equal the predecessor `superseded_at`; an unrelated verification attempt cannot retire this result's negative-outcome interval. All cutover, target-result, and successor-attempt coordinates are purpose-authorized owner evidence, not caller timestamps. +`resolve_validation_result_nonverifiability_supersession_authority(...)` proves why an owner-resolved negative-outcome cutover exists. A predecessor `not_verifiable` outcome may end only with a complete immutable successor verification-attempt reference/digest/release tuple plus an owner-supplied target-result reference/digest and `successor_failed_evidence_kind`. The successor target must equal the predecessor `result_reference` and `result_digest` exactly, and the successor failed-evidence kind must equal the predecessor `failed_evidence_kind`; a same-result attempt for a different required evidence family cannot retire this failure interval. The successor attempt must identify new evidence and its release must equal the predecessor `superseded_at`. All cutover, target-result, failed-evidence-obligation, and successor-attempt coordinates are purpose-authorized owner evidence, not caller timestamps. -The minimized view deliberately omits the cutover, successor target, and successor attempt. A new same-result verification attempt ends the predecessor negative outcome but does not itself imply scientific GREEN: any subsequent released result or negative outcome must still satisfy its own governed owner contract and verification boundary. +The minimized view deliberately omits the cutover, successor target, successor evidence obligation, and successor attempt. A new same-result, same-obligation verification attempt ends the predecessor negative outcome but does not itself imply scientific GREEN: any subsequent released result or negative outcome must still satisfy its own governed owner contract and verification boundary. ## Persistence state @@ -134,7 +134,7 @@ The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL r Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **twenty-one** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration support chronology, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, base/design-weight supersession, complete final analysis-weight lineage, final-weight supersession, point-weight/variance compatibility, point-weight/variance supersession, validation-result binding, validation-result supersession, validation-result non-verifiability, and validation-result non-verifiability supersession. -The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable verification-attempt reference/digest, preserve failed-evidence and attempt-release chronology, and cross-check an ordinary `superseded_at` against an explicit successor verification attempt that carries the same predecessor target-result reference/digest and is released exactly at cutover. No durable adapter may infer currentness from mutable current rows, unrelated verification attempts, or caller-supplied timestamps. +The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable verification-attempt reference/digest, preserve failed-evidence and attempt-release chronology, and cross-check an ordinary `superseded_at` against an explicit successor verification attempt that carries the same predecessor target-result reference/digest, the same failed-evidence obligation, and a release exactly at cutover. No durable adapter may infer currentness from mutable current rows, unrelated result attempts, different-evidence-family attempts, or caller-supplied timestamps. ## Test contract @@ -153,6 +153,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity, chronology, currentness, and same-result successor-attempt authority with owner-internal target binding. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity, chronology, currentness, and same-result, same-failed-evidence-obligation successor-attempt authority with owner-internal target binding. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From 5ac68d687423fcf4861cee3830c3fe2442813426 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 00:05:17 +0900 Subject: [PATCH 344/603] test(workforce-validation): bind nonreproducible failure evidence in supersession --- ...ty_supersession_failed_evidence_binding.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_failed_evidence_binding.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_failed_evidence_binding.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_failed_evidence_binding.py new file mode 100644 index 000000000..52e80b90e --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_failed_evidence_binding.py @@ -0,0 +1,61 @@ +"""Bind non-reproducible negative-outcome supersession to exact failed evidence.""" + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.result_nonverifiability_supersession_authority import ( + ValidationResultNonVerifiabilitySupersessionAuthorityRecord, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +FAILED_REFERENCE = "analysis_weight_receipt:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" +ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:33333333-3333-4333-8333-333333333333" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +RESULT_DIGEST = "1" * 64 +FAILED_DIGEST = "a" * 64 +ATTEMPT_DIGEST = "3" * 64 +OWNER_CONTRACT_DIGEST = "2" * 64 +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 1, tzinfo=timezone.utc) +FAILED_RELEASED_AT = datetime(2026, 9, 17, 12, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 18, 8, tzinfo=timezone.utc) + + +def _record(*, failure_mode: str, include_failed_evidence: bool) -> ValidationResultNonVerifiabilitySupersessionAuthorityRecord: + """Build predecessor authority with optional exact non-reproducible evidence identity.""" + return ValidationResultNonVerifiabilitySupersessionAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + failed_evidence_kind="analysis_weight_receipt", + failure_mode=failure_mode, + failed_evidence_reference=FAILED_REFERENCE if include_failed_evidence else None, + failed_evidence_digest=FAILED_DIGEST if include_failed_evidence else None, + failed_evidence_released_at=FAILED_RELEASED_AT if include_failed_evidence else None, + verification_attempt_reference=ATTEMPT_REFERENCE, + verification_attempt_digest=ATTEMPT_DIGEST, + evidence_version=1, + owner_contract_reference=OWNER_CONTRACT_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_CONTRACT_DIGEST, + owner_contract_released_at=OWNER_CONTRACT_RELEASED_AT, + released_at=RELEASED_AT, + ) + + +def test_nonreproducible_predecessor_preserves_exact_failed_evidence_identity() -> None: + """Keep the failed immutable receipt bound to the supersession predecessor.""" + fields = dict(_record(failure_mode="non_reproducible", include_failed_evidence=True).fields) + assert fields["failed_evidence_reference"] == FAILED_REFERENCE + assert fields["failed_evidence_digest"] == FAILED_DIGEST + assert fields["failed_evidence_released_at"] == FAILED_RELEASED_AT + + +def test_missing_predecessor_rejects_fabricated_failed_evidence_identity() -> None: + """Do not invent an immutable receipt when the predecessor failure was missing evidence.""" + with pytest.raises(ValueError, match="must be absent when evidence is missing"): + _record(failure_mode="missing", include_failed_evidence=True) From a471c9d008b549d1951f6f4343039f1c7c42bb23 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 00:08:23 +0900 Subject: [PATCH 345/603] test(workforce-validation): fail closed on lossy nonreproducible supersession --- ...ty_supersession_failed_evidence_binding.py | 33 ++++++++----------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_failed_evidence_binding.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_failed_evidence_binding.py index 52e80b90e..18e68677a 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_failed_evidence_binding.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_failed_evidence_binding.py @@ -1,4 +1,4 @@ -"""Bind non-reproducible negative-outcome supersession to exact failed evidence.""" +"""Fail closed when supersession would discard non-reproducible evidence identity.""" from datetime import datetime, timezone from uuid import UUID @@ -12,20 +12,17 @@ TENANT = UUID("10000000-0000-7000-8000-000000000001") STUDY = UUID("00000000-0000-7000-8000-0000000000d1") RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" -FAILED_REFERENCE = "analysis_weight_receipt:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:33333333-3333-4333-8333-333333333333" OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" RESULT_DIGEST = "1" * 64 -FAILED_DIGEST = "a" * 64 ATTEMPT_DIGEST = "3" * 64 OWNER_CONTRACT_DIGEST = "2" * 64 OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 1, tzinfo=timezone.utc) -FAILED_RELEASED_AT = datetime(2026, 9, 17, 12, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 18, 8, tzinfo=timezone.utc) -def _record(*, failure_mode: str, include_failed_evidence: bool) -> ValidationResultNonVerifiabilitySupersessionAuthorityRecord: - """Build predecessor authority with optional exact non-reproducible evidence identity.""" +def _record(*, failure_mode: str) -> ValidationResultNonVerifiabilitySupersessionAuthorityRecord: + """Build one predecessor using the v1 supersession identity currently persisted.""" return ValidationResultNonVerifiabilitySupersessionAuthorityRecord( tenant_record_id=TENANT, validity_study_id=STUDY, @@ -33,9 +30,6 @@ def _record(*, failure_mode: str, include_failed_evidence: bool) -> ValidationRe result_digest=RESULT_DIGEST, failed_evidence_kind="analysis_weight_receipt", failure_mode=failure_mode, - failed_evidence_reference=FAILED_REFERENCE if include_failed_evidence else None, - failed_evidence_digest=FAILED_DIGEST if include_failed_evidence else None, - failed_evidence_released_at=FAILED_RELEASED_AT if include_failed_evidence else None, verification_attempt_reference=ATTEMPT_REFERENCE, verification_attempt_digest=ATTEMPT_DIGEST, evidence_version=1, @@ -47,15 +41,16 @@ def _record(*, failure_mode: str, include_failed_evidence: bool) -> ValidationRe ) -def test_nonreproducible_predecessor_preserves_exact_failed_evidence_identity() -> None: - """Keep the failed immutable receipt bound to the supersession predecessor.""" - fields = dict(_record(failure_mode="non_reproducible", include_failed_evidence=True).fields) - assert fields["failed_evidence_reference"] == FAILED_REFERENCE - assert fields["failed_evidence_digest"] == FAILED_DIGEST - assert fields["failed_evidence_released_at"] == FAILED_RELEASED_AT +def test_missing_predecessor_remains_supported_without_fabricated_evidence_identity() -> None: + """Keep missing-evidence outcomes representable because no artifact identity exists.""" + fields = dict(_record(failure_mode="missing").fields) + assert fields["failure_mode"] == "missing" -def test_missing_predecessor_rejects_fabricated_failed_evidence_identity() -> None: - """Do not invent an immutable receipt when the predecessor failure was missing evidence.""" - with pytest.raises(ValueError, match="must be absent when evidence is missing"): - _record(failure_mode="missing", include_failed_evidence=True) +def test_nonreproducible_predecessor_fails_closed_when_artifact_identity_would_be_lost() -> None: + """Reject v1 supersession until exact failed reference, digest, and release can be bound.""" + with pytest.raises( + ValueError, + match="non_reproducible supersession requires exact failed-evidence identity", + ): + _record(failure_mode="non_reproducible") From ae87c2bc01692a1ce2c594ac409d6beb3671798a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 00:09:19 +0900 Subject: [PATCH 346/603] fix(workforce-validation): fail closed on lossy nonreproducible supersession --- .../result_nonverifiability_supersession_authority.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py index 051d88141..3e4c7df08 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py @@ -128,6 +128,11 @@ def __new__( result_evidence_digest = _require_digest("result_digest", result_digest) evidence_kind = _require_failed_evidence_kind(failed_evidence_kind) mode = _require_failure_mode(failure_mode) + if mode == "non_reproducible": + raise ValueError( + "non_reproducible supersession requires exact failed-evidence identity; " + "the v1 supersession contract fails closed instead of dropping it." + ) attempt_ref = _require_reference( "verification_attempt_reference", verification_attempt_reference, From a52e4ba0f9652892fad034daa342cc55de8c87c1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 00:10:35 +0900 Subject: [PATCH 347/603] docs(workforce-validation): document nonreproducible supersession fail-closed boundary --- services/workforce-validation-api/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 2a075c6bc..305c9514a 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -124,7 +124,9 @@ The immutable `verification_attempt_reference` and `verification_attempt_digest` `resolve_validation_result_nonverifiability_supersession_authority(...)` proves why an owner-resolved negative-outcome cutover exists. A predecessor `not_verifiable` outcome may end only with a complete immutable successor verification-attempt reference/digest/release tuple plus an owner-supplied target-result reference/digest and `successor_failed_evidence_kind`. The successor target must equal the predecessor `result_reference` and `result_digest` exactly, and the successor failed-evidence kind must equal the predecessor `failed_evidence_kind`; a same-result attempt for a different required evidence family cannot retire this failure interval. The successor attempt must identify new evidence and its release must equal the predecessor `superseded_at`. All cutover, target-result, failed-evidence-obligation, and successor-attempt coordinates are purpose-authorized owner evidence, not caller timestamps. -The minimized view deliberately omits the cutover, successor target, successor evidence obligation, and successor attempt. A new same-result, same-obligation verification attempt ends the predecessor negative outcome but does not itself imply scientific GREEN: any subsequent released result or negative outcome must still satisfy its own governed owner contract and verification boundary. +The v1 supersession tuple deliberately supports only predecessor `failure_mode="missing"`. The ordinary non-verifiability contract requires a `non_reproducible` outcome to retain the exact failed-evidence reference, digest, and owner-resolved release instant, but those coordinates are not present in this supersession tuple. Accepting that mode here would therefore erase the identity of the artifact that failed reproducibility. Until a versioned supersession contract carries that exact failed-artifact identity and chronology, `non_reproducible` supersession fails closed rather than manufacturing a coarser correction edge. + +The minimized view deliberately omits the cutover, successor target, successor evidence obligation, and successor attempt. A new same-result, same-obligation verification attempt ends a supported missing-evidence predecessor negative outcome but does not itself imply scientific GREEN: any subsequent released result or negative outcome must still satisfy its own governed owner contract and verification boundary. ## Persistence state @@ -134,7 +136,7 @@ The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL r Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **twenty-one** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration support chronology, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, base/design-weight supersession, complete final analysis-weight lineage, final-weight supersession, point-weight/variance compatibility, point-weight/variance supersession, validation-result binding, validation-result supersession, validation-result non-verifiability, and validation-result non-verifiability supersession. -The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable verification-attempt reference/digest, preserve failed-evidence and attempt-release chronology, and cross-check an ordinary `superseded_at` against an explicit successor verification attempt that carries the same predecessor target-result reference/digest, the same failed-evidence obligation, and a release exactly at cutover. No durable adapter may infer currentness from mutable current rows, unrelated result attempts, different-evidence-family attempts, or caller-supplied timestamps. +The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable verification-attempt reference/digest, preserve failed-evidence and attempt-release chronology, and cross-check an ordinary `superseded_at` against an explicit successor verification attempt that carries the same predecessor target-result reference/digest, the same failed-evidence obligation, and a release exactly at cutover. For `failure_mode="non_reproducible"`, the current v1 supersession contract is not sufficient persistence authority because it lacks the exact failed-artifact reference/digest/release tuple; durable adoption must leave that correction path fail-closed rather than infer it from a mutable row, the evidence-kind label, or a successor attempt. No durable adapter may infer currentness from mutable current rows, unrelated result attempts, different-evidence-family attempts, or caller-supplied timestamps. ## Test contract @@ -153,6 +155,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity, chronology, currentness, and same-result, same-failed-evidence-obligation successor-attempt authority with owner-internal target binding. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity, chronology, currentness, same-result/same-failed-evidence-obligation successor-attempt authority for missing-evidence predecessors, and fail-closed rejection of lossy `non_reproducible` supersession until exact failed-artifact identity is carried by the versioned correction contract. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From 699a2fb4ef1ddb0663af91f4af1be9d9aaa88d13 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 01:07:24 +0900 Subject: [PATCH 348/603] test(workforce-validation): red exact-artifact nonverifiability supersession --- ...nverifiability_supersession_v2_contract.py | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_contract.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_contract.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_contract.py new file mode 100644 index 000000000..47a6e581f --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_contract.py @@ -0,0 +1,77 @@ +"""RED contract for exact-artifact supersession of non-reproducible outcomes.""" + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.result_nonverifiability import ( + ValidationResultNonVerifiabilityRecord, +) +from orgmetra_workforce_validation_api.result_nonverifiability_supersession_v2_authority import ( + ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +FAILED_REFERENCE = "analysis_weight_receipt:22222222-2222-4222-8222-222222222222" +ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:33333333-3333-4333-8333-333333333333" +SUCCESSOR_ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:44444444-4444-4444-8444-444444444444" +OWNER_REFERENCE = "released_owner_contract:55555555-5555-4555-8555-555555555555" +RESULT_DIGEST = "1" * 64 +FAILED_DIGEST = "2" * 64 +ATTEMPT_DIGEST = "3" * 64 +SUCCESSOR_DIGEST = "4" * 64 +OWNER_DIGEST = "5" * 64 +OWNER_RELEASED_AT = datetime(2026, 9, 17, 5, 55, tzinfo=timezone.utc) +FAILED_RELEASED_AT = datetime(2026, 9, 17, 5, 59, tzinfo=timezone.utc) +EVALUATED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) +ATTEMPT_RELEASED_AT = datetime(2026, 9, 17, 6, 2, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 6, 5, tzinfo=timezone.utc) +CUTOVER = datetime(2026, 9, 17, 7, 0, tzinfo=timezone.utc) + + +def _predecessor() -> ValidationResultNonVerifiabilityRecord: + return ValidationResultNonVerifiabilityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + failed_evidence_kind="analysis_weight_receipt", + failure_mode="non_reproducible", + failed_evidence_reference=FAILED_REFERENCE, + failed_evidence_digest=FAILED_DIGEST, + failed_evidence_released_at=FAILED_RELEASED_AT, + verification_attempt_reference=ATTEMPT_REFERENCE, + verification_attempt_digest=ATTEMPT_DIGEST, + verification_attempt_released_at=ATTEMPT_RELEASED_AT, + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=7, + owner_contract_digest=OWNER_DIGEST, + owner_contract_released_at=OWNER_RELEASED_AT, + evaluated_at=EVALUATED_AT, + released_at=RELEASED_AT, + ) + + +def test_non_reproducible_correction_binds_the_exact_failed_artifact() -> None: + """A different artifact in the same evidence family must not retire the predecessor.""" + predecessor = _predecessor() + with pytest.raises(ValueError, match="exact failed artifact"): + ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord( + predecessor=predecessor, + evidence_version=2, + superseded_at=CUTOVER, + successor_target_result_reference=RESULT_REFERENCE, + successor_target_result_digest=RESULT_DIGEST, + successor_failed_evidence_kind="analysis_weight_receipt", + successor_target_failed_evidence_reference=( + "analysis_weight_receipt:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" + ), + successor_target_failed_evidence_digest=FAILED_DIGEST, + successor_target_failed_evidence_released_at=FAILED_RELEASED_AT, + successor_verification_attempt_reference=SUCCESSOR_ATTEMPT_REFERENCE, + successor_verification_attempt_digest=SUCCESSOR_DIGEST, + successor_verification_attempt_released_at=CUTOVER, + ) From 078bb65a9ea6f7fad65a05af6cf093e038a4b796 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 01:09:05 +0900 Subject: [PATCH 349/603] feat(workforce-validation): bind nonreproducible supersession to exact artifact --- ...verifiability_supersession_v2_authority.py | 413 ++++++++++++++++++ 1 file changed, 413 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py new file mode 100644 index 000000000..5664c67e4 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py @@ -0,0 +1,413 @@ +"""Versioned exact-artifact correction authority for non-reproducible validation evidence.""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .result_nonverifiability import ( + ValidationResultNonVerifiabilityRecord, + _FAILED_REFERENCE_KIND_BY_EVIDENCE_KIND, + _require_failed_evidence_kind, +) +from .scientific_authority import _require_digest, _require_positive_integer, _require_reference + +_RESOURCE_KIND = "validation_result_nonverifiability_supersession_authority" +_OPERATION = "read" +_VERSION = 2 +_READ_FIELDS = frozenset( + { + "result_reference", "result_digest", "failed_evidence_kind", "failure_mode", + "failed_evidence_reference", "failed_evidence_digest", "failed_evidence_released_at", + "verification_attempt_reference", "verification_attempt_digest", + "verification_attempt_released_at", "evidence_version", "owner_contract_reference", + "owner_contract_version", "owner_contract_digest", "owner_contract_released_at", + "released_at", "superseded_at", "successor_target_result_reference", + "successor_target_result_digest", "successor_failed_evidence_kind", + "successor_target_failed_evidence_reference", "successor_target_failed_evidence_digest", + "successor_target_failed_evidence_released_at", "successor_verification_attempt_reference", + "successor_verification_attempt_digest", "successor_verification_attempt_released_at", + } +) +_VIEW_FIELDS = frozenset( + { + "result_reference", "result_digest", "failed_evidence_kind", "failure_mode", + "failed_evidence_reference", "failed_evidence_digest", "failed_evidence_released_at", + "verification_attempt_reference", "verification_attempt_digest", + "verification_attempt_released_at", "evidence_version", "owner_contract_reference", + "owner_contract_version", "owner_contract_digest", "owner_contract_released_at", "released_at", + } +) + + +class ValidationResultNonVerifiabilitySupersessionV2AuthorityNotFound(LookupError): + """Indicate that no released v2 correction authority matches the predecessor.""" + + +class ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError(RuntimeError): + """Indicate that released v2 correction evidence cannot authorize use.""" + + +def _predecessor_fields( + predecessor: ValidationResultNonVerifiabilityRecord, version: int +) -> tuple[tuple[str, object], ...]: + """Return immutable predecessor provenance plus the governed correction version.""" + return ( + ("evidence_version", version), + ("failed_evidence_digest", predecessor.failed_evidence_digest), + ("failed_evidence_kind", predecessor.failed_evidence_kind), + ("failed_evidence_reference", predecessor.failed_evidence_reference), + ("failed_evidence_released_at", predecessor.failed_evidence_released_at), + ("failure_mode", predecessor.failure_mode), + ("owner_contract_digest", predecessor.owner_contract_digest), + ("owner_contract_reference", predecessor.owner_contract_reference), + ("owner_contract_released_at", predecessor.owner_contract_released_at), + ("owner_contract_version", predecessor.owner_contract_version), + ("result_digest", predecessor.result_digest), + ("result_reference", predecessor.result_reference), + ("verification_attempt_digest", predecessor.verification_attempt_digest), + ("verification_attempt_reference", predecessor.verification_attempt_reference), + ("verification_attempt_released_at", predecessor.verification_attempt_released_at), + ) + + +class ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord(tuple): + """Bind a non-reproducible predecessor to an exact-artifact successor attempt.""" + + __slots__ = () + + def __new__( + cls, + *, + predecessor: ValidationResultNonVerifiabilityRecord, + evidence_version: int, + superseded_at: datetime | None = None, + successor_target_result_reference: str | None = None, + successor_target_result_digest: str | None = None, + successor_failed_evidence_kind: str | None = None, + successor_target_failed_evidence_reference: str | None = None, + successor_target_failed_evidence_digest: str | None = None, + successor_target_failed_evidence_released_at: datetime | None = None, + successor_verification_attempt_reference: str | None = None, + successor_verification_attempt_digest: str | None = None, + successor_verification_attempt_released_at: datetime | None = None, + ) -> ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord: + """Validate exact predecessor provenance and an optional atomic successor cutover.""" + if type(predecessor) is not ValidationResultNonVerifiabilityRecord: + raise TypeError("predecessor must be an exact ValidationResultNonVerifiabilityRecord.") + if predecessor.failure_mode != "non_reproducible": + raise ValueError("v2 supersession is reserved for non_reproducible predecessors.") + version = _require_positive_integer("evidence_version", evidence_version) + if version != _VERSION: + raise ValueError("evidence_version must be 2 for exact-artifact supersession.") + failed_reference = predecessor.failed_evidence_reference + failed_digest = predecessor.failed_evidence_digest + failed_release = predecessor.failed_evidence_released_at + if failed_reference is None or failed_digest is None or failed_release is None: + raise ValueError("non_reproducible predecessor must retain exact failed-artifact evidence.") + + successor_values = ( + superseded_at, successor_target_result_reference, successor_target_result_digest, + successor_failed_evidence_kind, successor_target_failed_evidence_reference, + successor_target_failed_evidence_digest, successor_target_failed_evidence_released_at, + successor_verification_attempt_reference, successor_verification_attempt_digest, + successor_verification_attempt_released_at, + ) + if all(value is None for value in successor_values): + cutover = None + successor_fields = None + elif any(value is None for value in successor_values): + raise ValueError( + "v2 supersession requires cutover, exact predecessor target, exact failed artifact, " + "and complete successor verification-attempt evidence." + ) + else: + cutover = _require_aware_datetime("superseded_at", superseded_at) + if cutover <= predecessor.released_at: + raise ValueError("superseded_at must be later than predecessor release.") + target_result_reference = _require_reference( + "successor_target_result_reference", successor_target_result_reference, + "validation_analysis_result", + ) + target_result_digest = _require_digest( + "successor_target_result_digest", successor_target_result_digest + ) + target_kind = _require_failed_evidence_kind(successor_failed_evidence_kind) + target_failed_reference = _require_reference( + "successor_target_failed_evidence_reference", successor_target_failed_evidence_reference, + _FAILED_REFERENCE_KIND_BY_EVIDENCE_KIND[predecessor.failed_evidence_kind], + ) + target_failed_digest = _require_digest( + "successor_target_failed_evidence_digest", successor_target_failed_evidence_digest + ) + target_failed_release = _require_aware_datetime( + "successor_target_failed_evidence_released_at", + successor_target_failed_evidence_released_at, + ) + successor_reference = _require_reference( + "successor_verification_attempt_reference", successor_verification_attempt_reference, + "validation_evidence_verification_attempt", + ) + successor_digest = _require_digest( + "successor_verification_attempt_digest", successor_verification_attempt_digest + ) + successor_release = _require_aware_datetime( + "successor_verification_attempt_released_at", + successor_verification_attempt_released_at, + ) + if ( + target_result_reference != predecessor.result_reference + or target_result_digest != predecessor.result_digest + ): + raise ValueError("successor attempt must target the exact predecessor result.") + if target_kind != predecessor.failed_evidence_kind: + raise ValueError("successor attempt must re-evaluate the same failed-evidence family.") + if ( + target_failed_reference != failed_reference + or target_failed_digest != failed_digest + or target_failed_release != failed_release + ): + raise ValueError("successor attempt must target the exact failed artifact and release chronology.") + if successor_reference == predecessor.verification_attempt_reference: + raise ValueError("successor verification attempt must use a new reference.") + if successor_digest in { + predecessor.result_digest, failed_digest, predecessor.verification_attempt_digest, + predecessor.owner_contract_digest, + }: + raise ValueError("successor verification attempt must identify new evidence.") + if successor_release != cutover: + raise ValueError("successor verification attempt must be released exactly at supersession.") + successor_fields = ( + ("successor_failed_evidence_kind", target_kind), + ("successor_target_failed_evidence_digest", target_failed_digest), + ("successor_target_failed_evidence_reference", target_failed_reference), + ("successor_target_failed_evidence_released_at", target_failed_release), + ("successor_target_result_digest", target_result_digest), + ("successor_target_result_reference", target_result_reference), + ("successor_verification_attempt_digest", successor_digest), + ("successor_verification_attempt_reference", successor_reference), + ("successor_verification_attempt_released_at", successor_release), + ) + return tuple.__new__(cls, (predecessor, version, cutover, successor_fields)) + + @property + def predecessor(self) -> ValidationResultNonVerifiabilityRecord: + """Return the exact immutable predecessor owner record.""" + return self[0] + + @property + def evidence_version(self) -> int: + """Return the governed exact-artifact correction contract version.""" + return self[1] + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable predecessor provenance plus v2 evidence version.""" + return _predecessor_fields(self.predecessor, self.evidence_version) + + @property + def released_at(self) -> datetime: + """Return when the predecessor negative outcome became released evidence.""" + return self.predecessor.released_at + + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive end of predecessor authority when a successor exists.""" + return self[2] + + @property + def successor_fields(self) -> tuple[tuple[str, object], ...] | None: + """Return owner-internal exact-artifact successor coordinates.""" + return self[3] + + +class ValidationResultNonVerifiabilitySupersessionV2AuthorityView(tuple): + """Expose minimized predecessor provenance without reusable successor authority.""" + + __slots__ = () + + def __new__( + cls, *, tenant_record_id: UUID, validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> ValidationResultNonVerifiabilitySupersessionV2AuthorityView: + """Reject public construction so only the resolver can issue an authorized view.""" + raise TypeError( + "ValidationResultNonVerifiabilitySupersessionV2AuthorityView is issued only by " + "resolve_validation_result_nonverifiability_supersession_v2_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return predecessor provenance without cutover or successor coordinates.""" + return self[2] + + +@runtime_checkable +class ValidationResultNonVerifiabilitySupersessionV2AuthorityReadPort(Protocol): + """Read exact-artifact supersession evidence through the workforce-validation ACL.""" + + def read_validation_result_nonverifiability_supersession_v2_authority( + self, *, tenant_record_id: UUID, validity_study_id: UUID, result_reference: str, + result_digest: str, failed_evidence_kind: str, verification_attempt_reference: str, + verification_attempt_digest: str, evidence_version: int, owner_contract_reference: str, + owner_contract_version: int, owner_contract_digest: str, + ) -> ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord | None: + """Return one released v2 correction record or ``None``.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + ValidationResultNonVerifiabilitySupersessionV2AuthorityReadPort, + "read_validation_result_nonverifiability_supersession_v2_authority", +) + + +def resolve_validation_result_nonverifiability_supersession_v2_authority( + *, principal: ValidationPrincipal, tenant_record_id: UUID, validity_study_id: UUID, + result_reference: str, result_digest: str, failed_evidence_kind: str, + verification_attempt_reference: str, verification_attempt_digest: str, evidence_version: int, + owner_contract_reference: str, owner_contract_version: int, owner_contract_digest: str, + used_at: datetime, purpose_code: str, policy: PurposeBoundAccessPolicy, + read_port: ValidationResultNonVerifiabilitySupersessionV2AuthorityReadPort, +) -> ValidationResultNonVerifiabilitySupersessionV2AuthorityView: + """Authorize then resolve one exact-artifact non-reproducible correction interval.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static( + type(read_port), "read_validation_result_nonverifiability_supersession_v2_authority", None + ) + if type(read_capability) is not FunctionType or read_capability is _PROTOCOL_READ_CAPABILITY: + raise TypeError( + "read_port must expose a statically callable " + "read_validation_result_nonverifiability_supersession_v2_authority." + ) + + tenant_id = _restore_operational_uuid( + "tenant_record_id", _store_operational_uuid("tenant_record_id", tenant_record_id) + ) + study_id = _restore_operational_uuid( + "validity_study_id", _store_operational_uuid("validity_study_id", validity_study_id) + ) + result_ref = _require_reference("result_reference", result_reference, "validation_analysis_result") + result_evidence_digest = _require_digest("result_digest", result_digest) + evidence_kind = _require_failed_evidence_kind(failed_evidence_kind) + attempt_ref = _require_reference( + "verification_attempt_reference", verification_attempt_reference, + "validation_evidence_verification_attempt", + ) + attempt_digest = _require_digest("verification_attempt_digest", verification_attempt_digest) + version = _require_positive_integer("evidence_version", evidence_version) + if version != _VERSION: + raise ValueError("evidence_version must be 2 for exact-artifact supersession.") + owner_ref = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer("owner_contract_version", owner_contract_version) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", purpose_code=purpose, + operation_code=_OPERATION, resource_kind=_RESOURCE_KIND, requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=_detach_policy(policy), + ) + persisted = read_capability( + read_port, tenant_record_id=tenant_id, validity_study_id=study_id, + result_reference=result_ref, result_digest=result_evidence_digest, + failed_evidence_kind=evidence_kind, verification_attempt_reference=attempt_ref, + verification_attempt_digest=attempt_digest, evidence_version=version, + owner_contract_reference=owner_ref, owner_contract_version=owner_version, + owner_contract_digest=owner_digest, + ) + if persisted is None: + raise ValidationResultNonVerifiabilitySupersessionV2AuthorityNotFound(str(study_id)) + if type(persisted) is not ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord: + raise ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError( + "owner port returned non-canonical v2 non-verifiability supersession evidence" + ) + predecessor = persisted.predecessor + values = dict(persisted.fields) + requested_values = { + "evidence_version": version, + "failed_evidence_kind": evidence_kind, + "owner_contract_digest": owner_digest, + "owner_contract_reference": owner_ref, + "owner_contract_version": owner_version, + "result_digest": result_evidence_digest, + "result_reference": result_ref, + "verification_attempt_digest": attempt_digest, + "verification_attempt_reference": attempt_ref, + } + if ( + _store_operational_uuid("record tenant_record_id", predecessor.tenant_record_id) + != _store_operational_uuid("requested tenant_record_id", tenant_id) + or _store_operational_uuid("record validity_study_id", predecessor.validity_study_id) + != _store_operational_uuid("requested validity_study_id", study_id) + or any(values[name] != value for name, value in requested_values.items()) + ): + raise ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError( + "owner evidence does not match requested v2 non-verifiability correction coordinates" + ) + if use_instant < persisted.released_at: + raise ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError( + "v2 non-verifiability authority cannot be used before predecessor release" + ) + if persisted.superseded_at is not None and use_instant >= persisted.superseded_at: + raise ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError( + "v2 non-verifiability authority ended at its owner-resolved supersession instant" + ) + projection_values = {**values, "released_at": persisted.released_at} + fields = tuple((name, projection_values[name]) for name in sorted(_VIEW_FIELDS)) + return tuple.__new__( + ValidationResultNonVerifiabilitySupersessionV2AuthorityView, + (_store_operational_uuid("tenant_record_id", tenant_id), + _store_operational_uuid("validity_study_id", study_id), fields), + ) + + +__all__ = [ + "ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError", + "ValidationResultNonVerifiabilitySupersessionV2AuthorityNotFound", + "ValidationResultNonVerifiabilitySupersessionV2AuthorityReadPort", + "ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord", + "ValidationResultNonVerifiabilitySupersessionV2AuthorityView", + "resolve_validation_result_nonverifiability_supersession_v2_authority", +] From 90208af4778e67bc0d4777b030f771a709a1c7b3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 01:09:55 +0900 Subject: [PATCH 350/603] test(workforce-validation): cover exact-artifact supersession v2 edges --- ...ability_supersession_v2_authority_edges.py | 499 ++++++++++++++++++ 1 file changed, 499 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py new file mode 100644 index 000000000..05edac609 --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py @@ -0,0 +1,499 @@ +"""Exact-artifact correction contract for non-reproducible validation evidence.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api.registry import ValidationPrincipal +from orgmetra_workforce_validation_api.result_nonverifiability import ( + ValidationResultNonVerifiabilityRecord, +) +from orgmetra_workforce_validation_api.result_nonverifiability_supersession_v2_authority import ( + ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError, + ValidationResultNonVerifiabilitySupersessionV2AuthorityNotFound, + ValidationResultNonVerifiabilitySupersessionV2AuthorityReadPort, + ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord, + ValidationResultNonVerifiabilitySupersessionV2AuthorityView, + resolve_validation_result_nonverifiability_supersession_v2_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000d2") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +OTHER_RESULT_REFERENCE = "validation_analysis_result:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" +FAILED_REFERENCE = "analysis_weight_receipt:22222222-2222-4222-8222-222222222222" +OTHER_FAILED_REFERENCE = "analysis_weight_receipt:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" +ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:33333333-3333-4333-8333-333333333333" +OTHER_ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:cccccccc-cccc-4ccc-8ccc-cccccccccccc" +SUCCESSOR_ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:44444444-4444-4444-8444-444444444444" +OWNER_REFERENCE = "released_owner_contract:55555555-5555-4555-8555-555555555555" +OTHER_OWNER_REFERENCE = "released_owner_contract:dddddddd-dddd-4ddd-8ddd-dddddddddddd" +RESULT_DIGEST = "1" * 64 +FAILED_DIGEST = "2" * 64 +ATTEMPT_DIGEST = "3" * 64 +SUCCESSOR_DIGEST = "4" * 64 +OWNER_DIGEST = "5" * 64 +OWNER_RELEASED_AT = datetime(2026, 9, 17, 5, 55, tzinfo=timezone.utc) +FAILED_RELEASED_AT = datetime(2026, 9, 17, 5, 59, tzinfo=timezone.utc) +EVALUATED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) +ATTEMPT_RELEASED_AT = datetime(2026, 9, 17, 6, 2, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 6, 5, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 6, 10, tzinfo=timezone.utc) +CUTOVER = datetime(2026, 9, 17, 7, 0, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "result_reference", + "result_digest", + "failed_evidence_kind", + "failure_mode", + "failed_evidence_reference", + "failed_evidence_digest", + "failed_evidence_released_at", + "verification_attempt_reference", + "verification_attempt_digest", + "verification_attempt_released_at", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_target_result_reference", + "successor_target_result_digest", + "successor_failed_evidence_kind", + "successor_target_failed_evidence_reference", + "successor_target_failed_evidence_digest", + "successor_target_failed_evidence_released_at", + "successor_verification_attempt_reference", + "successor_verification_attempt_digest", + "successor_verification_attempt_released_at", + } +) + + +class _ReadPort: + """Return configured v2 authority and retain caller-known lookup coordinates.""" + + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[dict[str, object]] = [] + + def read_validation_result_nonverifiability_supersession_v2_authority( + self, **coordinates: object + ) -> object: + """Capture the lookup before returning configured owner evidence.""" + self.calls.append(dict(coordinates)) + return self.result + + +class _NoReadMethod: + """Deliberately omit the owner capability.""" + + +class _ProtocolOnly(ValidationResultNonVerifiabilitySupersessionV2AuthorityReadPort): + """Inherit only the Protocol placeholder.""" + + +class _DescriptorReadPort: + """Expose a descriptor that static capability validation must reject.""" + + @property + def read_validation_result_nonverifiability_supersession_v2_authority(self) -> object: + """Fail if descriptor execution leaks through static validation.""" + raise AssertionError("descriptor must not execute") + + +def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: + """Return the canonical workforce-validation principal.""" + return ValidationPrincipal( + tenant_record_id=tenant_record_id, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + """Return the purpose-bound v2 correction policy.""" + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="validation-result-nonverifiability-supersession-read-v2", + resource_kind="validation_result_nonverifiability_supersession_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _predecessor(**overrides: object) -> ValidationResultNonVerifiabilityRecord: + """Build one released non-reproducible predecessor outcome.""" + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "result_reference": RESULT_REFERENCE, + "result_digest": RESULT_DIGEST, + "failed_evidence_kind": "analysis_weight_receipt", + "failure_mode": "non_reproducible", + "failed_evidence_reference": FAILED_REFERENCE, + "failed_evidence_digest": FAILED_DIGEST, + "failed_evidence_released_at": FAILED_RELEASED_AT, + "verification_attempt_reference": ATTEMPT_REFERENCE, + "verification_attempt_digest": ATTEMPT_DIGEST, + "verification_attempt_released_at": ATTEMPT_RELEASED_AT, + "owner_contract_reference": OWNER_REFERENCE, + "owner_contract_version": 7, + "owner_contract_digest": OWNER_DIGEST, + "owner_contract_released_at": OWNER_RELEASED_AT, + "evaluated_at": EVALUATED_AT, + "released_at": RELEASED_AT, + "superseded_at": None, + } + values.update(overrides) + return ValidationResultNonVerifiabilityRecord(**values) + + +def _record( + *, + predecessor: ValidationResultNonVerifiabilityRecord | None = None, + **overrides: object, +) -> ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord: + """Build current v2 authority with optional owner-supplied successor coordinates.""" + values: dict[str, object] = { + "predecessor": _predecessor() if predecessor is None else predecessor, + "evidence_version": 2, + "superseded_at": None, + "successor_target_result_reference": None, + "successor_target_result_digest": None, + "successor_failed_evidence_kind": None, + "successor_target_failed_evidence_reference": None, + "successor_target_failed_evidence_digest": None, + "successor_target_failed_evidence_released_at": None, + "successor_verification_attempt_reference": None, + "successor_verification_attempt_digest": None, + "successor_verification_attempt_released_at": None, + } + values.update(overrides) + return ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord(**values) + + +def _successor_overrides(**overrides: object) -> dict[str, object]: + """Return the complete exact-artifact successor tuple with optional hostile changes.""" + values: dict[str, object] = { + "superseded_at": CUTOVER, + "successor_target_result_reference": RESULT_REFERENCE, + "successor_target_result_digest": RESULT_DIGEST, + "successor_failed_evidence_kind": "analysis_weight_receipt", + "successor_target_failed_evidence_reference": FAILED_REFERENCE, + "successor_target_failed_evidence_digest": FAILED_DIGEST, + "successor_target_failed_evidence_released_at": FAILED_RELEASED_AT, + "successor_verification_attempt_reference": SUCCESSOR_ATTEMPT_REFERENCE, + "successor_verification_attempt_digest": SUCCESSOR_DIGEST, + "successor_verification_attempt_released_at": CUTOVER, + } + values.update(overrides) + return values + + +def _resolve( + *, read_port: object, **overrides: object +) -> ValidationResultNonVerifiabilitySupersessionV2AuthorityView: + """Resolve canonical caller-known coordinates with optional hostile overrides.""" + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "result_reference": RESULT_REFERENCE, + "result_digest": RESULT_DIGEST, + "failed_evidence_kind": "analysis_weight_receipt", + "verification_attempt_reference": ATTEMPT_REFERENCE, + "verification_attempt_digest": ATTEMPT_DIGEST, + "evidence_version": 2, + "owner_contract_reference": OWNER_REFERENCE, + "owner_contract_version": 7, + "owner_contract_digest": OWNER_DIGEST, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_validation_result_nonverifiability_supersession_v2_authority(**values) + + +def test_current_non_reproducible_outcome_resolves_with_exact_failed_artifact() -> None: + """Expose predecessor provenance while keeping correction coordinates private.""" + record = _record() + port = _ReadPort(record) + view = _resolve(read_port=port) + + assert isinstance(port, ValidationResultNonVerifiabilitySupersessionV2AuthorityReadPort) + assert record.predecessor.failure_mode == "non_reproducible" + assert record.evidence_version == 2 + assert record.released_at == RELEASED_AT + assert record.superseded_at is None + assert record.successor_fields is None + assert port.calls == [ + { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "result_reference": RESULT_REFERENCE, + "result_digest": RESULT_DIGEST, + "failed_evidence_kind": "analysis_weight_receipt", + "verification_attempt_reference": ATTEMPT_REFERENCE, + "verification_attempt_digest": ATTEMPT_DIGEST, + "evidence_version": 2, + "owner_contract_reference": OWNER_REFERENCE, + "owner_contract_version": 7, + "owner_contract_digest": OWNER_DIGEST, + } + ] + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + fields = dict(view.fields) + assert fields["failure_mode"] == "non_reproducible" + assert fields["failed_evidence_reference"] == FAILED_REFERENCE + assert fields["failed_evidence_digest"] == FAILED_DIGEST + assert fields["failed_evidence_released_at"] == FAILED_RELEASED_AT + assert fields["verification_attempt_released_at"] == ATTEMPT_RELEASED_AT + assert fields["evidence_version"] == 2 + assert fields["released_at"] == RELEASED_AT + assert "superseded_at" not in fields + assert "successor_target_failed_evidence_reference" not in fields + assert "successor_verification_attempt_reference" not in fields + + +def test_exact_artifact_successor_preserves_historical_use_but_ends_at_cutover() -> None: + """Require one atomic same-result, same-artifact successor attempt.""" + record = _record(**_successor_overrides()) + assert dict(record.successor_fields or ()) == { + "successor_failed_evidence_kind": "analysis_weight_receipt", + "successor_target_failed_evidence_digest": FAILED_DIGEST, + "successor_target_failed_evidence_reference": FAILED_REFERENCE, + "successor_target_failed_evidence_released_at": FAILED_RELEASED_AT, + "successor_target_result_digest": RESULT_DIGEST, + "successor_target_result_reference": RESULT_REFERENCE, + "successor_verification_attempt_digest": SUCCESSOR_DIGEST, + "successor_verification_attempt_reference": SUCCESSOR_ATTEMPT_REFERENCE, + "successor_verification_attempt_released_at": CUTOVER, + } + view = _resolve(read_port=_ReadPort(record), used_at=CUTOVER - timedelta(seconds=1)) + assert dict(view.fields)["result_reference"] == RESULT_REFERENCE + with pytest.raises(ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError): + _resolve(read_port=_ReadPort(record), used_at=CUTOVER) + + +def test_authorization_denial_happens_before_owner_resolution() -> None: + """Keep purpose denial ahead of owner evidence lookup.""" + port = _ReadPort(_record()) + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, policy=_policy(purpose_code="audit_review")) + assert port.calls == [] + + +def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: + """Reject absence and foreign record types after authorization.""" + with pytest.raises(ValidationResultNonVerifiabilitySupersessionV2AuthorityNotFound): + _resolve(read_port=_ReadPort(None)) + with pytest.raises(ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError): + _resolve(read_port=_ReadPort(object())) + + +@pytest.mark.parametrize( + "predecessor_overrides", + [ + {"tenant_record_id": OTHER_TENANT}, + {"validity_study_id": OTHER_STUDY}, + {"result_reference": OTHER_RESULT_REFERENCE}, + {"result_digest": "a" * 64}, + { + "failed_evidence_kind": "variance_design_receipt", + "failed_evidence_reference": ( + "variance_design_receipt:22222222-2222-4222-8222-222222222222" + ), + }, + {"verification_attempt_reference": OTHER_ATTEMPT_REFERENCE}, + {"verification_attempt_digest": "c" * 64}, + {"owner_contract_reference": OTHER_OWNER_REFERENCE}, + {"owner_contract_version": 8}, + {"owner_contract_digest": "d" * 64}, + ], +) +def test_owner_evidence_must_match_every_caller_known_coordinate( + predecessor_overrides: dict[str, object] +) -> None: + """Reject evidence selected by an incomplete or different lookup tuple.""" + record = _record(predecessor=_predecessor(**predecessor_overrides)) + with pytest.raises(ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError): + _resolve(read_port=_ReadPort(record)) + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("result_reference", "wrong:result", ValueError), + ("result_digest", "ABC", ValueError), + ("failed_evidence_kind", "unknown", ValueError), + ("verification_attempt_reference", "wrong:attempt", ValueError), + ("verification_attempt_digest", "3" * 63, ValueError), + ("evidence_version", False, ValueError), + ("evidence_version", 1, ValueError), + ("owner_contract_reference", "wrong:contract", ValueError), + ("owner_contract_version", 0, ValueError), + ("owner_contract_digest", "5" * 63, ValueError), + ("used_at", datetime(2026, 9, 17, 6, 10), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_or_dependency_fails_before_owner_resolution( + key: str, value: object, error: type[Exception] +) -> None: + """Validate caller/dependency shapes before any owner read.""" + port: object = _ReadPort(_record()) + overrides = {key: value} + if key == "read_port": + port = value + overrides = {} + with pytest.raises(error): + _resolve(read_port=port, **overrides) + if isinstance(port, _ReadPort): + assert port.calls == [] + + +def test_pre_release_use_fails_closed() -> None: + """Do not expose a predecessor before its released authority instant.""" + with pytest.raises(ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError): + _resolve( + read_port=_ReadPort(_record()), + used_at=RELEASED_AT - timedelta(seconds=1), + ) + + +def test_record_requires_exact_non_reproducible_predecessor_and_v2() -> None: + """Keep v2 reserved for exact ordinary non-reproducible owner evidence.""" + with pytest.raises(TypeError, match="exact ValidationResultNonVerifiabilityRecord"): + ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord( + predecessor=object(), evidence_version=2 + ) + with pytest.raises(ValueError, match="reserved for non_reproducible"): + _record( + predecessor=_predecessor( + failure_mode="missing", + failed_evidence_reference=None, + failed_evidence_digest=None, + failed_evidence_released_at=None, + ) + ) + with pytest.raises(ValueError, match="evidence_version must be 2"): + _record(evidence_version=1) + with pytest.raises(TypeError, match="issued only by"): + ValidationResultNonVerifiabilitySupersessionV2AuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) + + +def test_incomplete_successor_tuple_fails_closed() -> None: + """Never accept a cutover without every exact-artifact successor coordinate.""" + values = _successor_overrides() + values["successor_target_failed_evidence_digest"] = None + with pytest.raises(ValueError, match="requires cutover"): + _record(**values) + + +@pytest.mark.parametrize( + ("override", "message"), + [ + ({"superseded_at": RELEASED_AT}, "later than predecessor release"), + ({"successor_target_result_reference": OTHER_RESULT_REFERENCE}, "exact predecessor result"), + ({"successor_target_result_digest": "a" * 64}, "exact predecessor result"), + ({"successor_failed_evidence_kind": "variance_design_receipt"}, "same failed-evidence family"), + ({"successor_target_failed_evidence_reference": OTHER_FAILED_REFERENCE}, "exact failed artifact"), + ({"successor_target_failed_evidence_digest": "b" * 64}, "exact failed artifact"), + ( + {"successor_target_failed_evidence_released_at": FAILED_RELEASED_AT + timedelta(seconds=1)}, + "exact failed artifact", + ), + ({"successor_verification_attempt_reference": ATTEMPT_REFERENCE}, "new reference"), + ({"successor_verification_attempt_digest": RESULT_DIGEST}, "identify new evidence"), + ({"successor_verification_attempt_digest": FAILED_DIGEST}, "identify new evidence"), + ({"successor_verification_attempt_digest": ATTEMPT_DIGEST}, "identify new evidence"), + ({"successor_verification_attempt_digest": OWNER_DIGEST}, "identify new evidence"), + ( + {"successor_verification_attempt_released_at": CUTOVER + timedelta(seconds=1)}, + "released exactly at supersession", + ), + ], +) +def test_successor_must_bind_exact_predecessor_artifact( + override: dict[str, object], message: str +) -> None: + """Reject another result, artifact, family, reused attempt, alias, or split cutover.""" + with pytest.raises(ValueError, match=message): + _record(**_successor_overrides(**override)) + + +@pytest.mark.parametrize( + "override", + [ + {"superseded_at": datetime(2026, 9, 17, 7, 0)}, + {"successor_target_result_reference": "wrong:result"}, + {"successor_target_result_digest": "x"}, + {"successor_failed_evidence_kind": "unknown"}, + {"successor_target_failed_evidence_reference": "wrong:artifact"}, + {"successor_target_failed_evidence_digest": "x"}, + {"successor_target_failed_evidence_released_at": datetime(2026, 9, 17, 5, 59)}, + {"successor_verification_attempt_reference": "wrong:attempt"}, + {"successor_verification_attempt_digest": "x"}, + {"successor_verification_attempt_released_at": datetime(2026, 9, 17, 7, 0)}, + ], +) +def test_malformed_successor_coordinates_fail_closed( + override: dict[str, object] +) -> None: + """Reject malformed references, digests and naive chronology before correction use.""" + with pytest.raises(ValueError): + _record(**_successor_overrides(**override)) + + +def test_record_and_view_are_structurally_immutable_and_uuid_views_are_detached() -> None: + """Prevent retained aliases or attribute writes from mutating accepted authority.""" + tenant = UUID(str(TENANT)) + predecessor = _predecessor(tenant_record_id=tenant) + record = _record(predecessor=predecessor) + object.__setattr__(tenant, "int", OTHER_TENANT.int) + assert record.predecessor.tenant_record_id == TENANT + assert dict(record.fields)["failed_evidence_reference"] == FAILED_REFERENCE + with pytest.raises(AttributeError): + object.__setattr__(record, "evidence_version", 3) + + view = _resolve(read_port=_ReadPort(record)) + returned_tenant = view.tenant_record_id + object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) + assert view.tenant_record_id == TENANT + with pytest.raises(AttributeError): + object.__setattr__(view, "fields", ()) + + +def test_v2_rejects_structurally_forged_non_reproducible_predecessor() -> None: + """Revalidate exact failed-artifact presence even if tuple construction bypasses v1 guards.""" + predecessor = _predecessor() + forged_values = list(predecessor) + forged_values[6] = None + forged = tuple.__new__(ValidationResultNonVerifiabilityRecord, forged_values) + with pytest.raises(ValueError, match="retain exact failed-artifact evidence"): + _record(predecessor=forged) From e6a2de4a04f2862e3dc56a480ee45a593c16f901 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 01:10:31 +0900 Subject: [PATCH 351/603] feat(workforce-validation): export nonverifiability supersession v2 --- .../orgmetra_workforce_validation_api/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index 18afcf429..01d6d9978 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -114,6 +114,14 @@ ValidationResultNonVerifiabilitySupersessionAuthorityView, resolve_validation_result_nonverifiability_supersession_authority, ) +from orgmetra_workforce_validation_api.result_nonverifiability_supersession_v2_authority import ( + ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError, + ValidationResultNonVerifiabilitySupersessionV2AuthorityNotFound, + ValidationResultNonVerifiabilitySupersessionV2AuthorityReadPort, + ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord, + ValidationResultNonVerifiabilitySupersessionV2AuthorityView, + resolve_validation_result_nonverifiability_supersession_v2_authority, +) from orgmetra_workforce_validation_api.result_supersession_authority import ( ValidationResultSupersessionAuthorityIntegrityError, ValidationResultSupersessionAuthorityNotFound, @@ -261,6 +269,11 @@ "ValidationResultNonVerifiabilitySupersessionAuthorityReadPort", "ValidationResultNonVerifiabilitySupersessionAuthorityRecord", "ValidationResultNonVerifiabilitySupersessionAuthorityView", + "ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError", + "ValidationResultNonVerifiabilitySupersessionV2AuthorityNotFound", + "ValidationResultNonVerifiabilitySupersessionV2AuthorityReadPort", + "ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord", + "ValidationResultNonVerifiabilitySupersessionV2AuthorityView", "ValidationResultNonVerifiabilityView", "ValidationResultSupersessionAuthorityIntegrityError", "ValidationResultSupersessionAuthorityNotFound", @@ -309,6 +322,7 @@ "resolve_validation_result_authority", "resolve_validation_result_nonverifiability", "resolve_validation_result_nonverifiability_supersession_authority", + "resolve_validation_result_nonverifiability_supersession_v2_authority", "resolve_validation_result_supersession_authority", "resolve_weight_eligibility_authority", "resolve_weight_eligibility_supersession_authority", From b593f18ba0face11111d2dcef449253bf0b21773 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 01:11:21 +0900 Subject: [PATCH 352/603] docs(workforce-validation): document exact-artifact supersession v2 --- services/workforce-validation-api/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 305c9514a..07678f600 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -122,11 +122,11 @@ The immutable `verification_attempt_reference` and `verification_attempt_digest` ## Validation-result non-verifiability supersession authority -`resolve_validation_result_nonverifiability_supersession_authority(...)` proves why an owner-resolved negative-outcome cutover exists. A predecessor `not_verifiable` outcome may end only with a complete immutable successor verification-attempt reference/digest/release tuple plus an owner-supplied target-result reference/digest and `successor_failed_evidence_kind`. The successor target must equal the predecessor `result_reference` and `result_digest` exactly, and the successor failed-evidence kind must equal the predecessor `failed_evidence_kind`; a same-result attempt for a different required evidence family cannot retire this failure interval. The successor attempt must identify new evidence and its release must equal the predecessor `superseded_at`. All cutover, target-result, failed-evidence-obligation, and successor-attempt coordinates are purpose-authorized owner evidence, not caller timestamps. +`resolve_validation_result_nonverifiability_supersession_authority(...)` is the v1 correction contract for a predecessor `failure_mode="missing"`. It requires a complete immutable successor verification-attempt reference/digest/release tuple plus an owner-supplied target-result reference/digest and `successor_failed_evidence_kind`. The successor target must equal the predecessor result exactly, the failed-evidence kind must match, the successor attempt must identify new evidence, and its release must equal the predecessor `superseded_at`. This v1 path deliberately rejects `non_reproducible` because its tuple cannot retain the exact artifact whose reproducibility failed. -The v1 supersession tuple deliberately supports only predecessor `failure_mode="missing"`. The ordinary non-verifiability contract requires a `non_reproducible` outcome to retain the exact failed-evidence reference, digest, and owner-resolved release instant, but those coordinates are not present in this supersession tuple. Accepting that mode here would therefore erase the identity of the artifact that failed reproducibility. Until a versioned supersession contract carries that exact failed-artifact identity and chronology, `non_reproducible` supersession fails closed rather than manufacturing a coarser correction edge. +`resolve_validation_result_nonverifiability_supersession_v2_authority(...)` supplies that exact-artifact path without weakening v1. It consumes the canonical released `ValidationResultNonVerifiabilityRecord` for a `non_reproducible` predecessor, keeps the failed-evidence reference/digest/release instant as owner-resolved predecessor provenance, and requires any successor attempt to target the exact same result, failed-evidence family, failed-evidence reference, failed-evidence digest, and failed-evidence release chronology. The v2 successor must still use new immutable verification-attempt evidence and be released exactly at `superseded_at`. Caller/read-port lookup coordinates do not include the failed-artifact tuple; persistence must recover it from canonical released owner evidence rather than let a caller choose favorable provenance. -The minimized view deliberately omits the cutover, successor target, successor evidence obligation, and successor attempt. A new same-result, same-obligation verification attempt ends a supported missing-evidence predecessor negative outcome but does not itself imply scientific GREEN: any subsequent released result or negative outcome must still satisfy its own governed owner contract and verification boundary. +Both minimized views omit cutover and successor coordinates. A successor verification attempt only ends the predecessor negative-outcome interval; it does not imply scientific GREEN. Any subsequent released result or negative outcome must satisfy its own governed owner and verification contract. ## Persistence state @@ -136,7 +136,7 @@ The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL r Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **twenty-one** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration support chronology, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, base/design-weight supersession, complete final analysis-weight lineage, final-weight supersession, point-weight/variance compatibility, point-weight/variance supersession, validation-result binding, validation-result supersession, validation-result non-verifiability, and validation-result non-verifiability supersession. -The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable verification-attempt reference/digest, preserve failed-evidence and attempt-release chronology, and cross-check an ordinary `superseded_at` against an explicit successor verification attempt that carries the same predecessor target-result reference/digest, the same failed-evidence obligation, and a release exactly at cutover. For `failure_mode="non_reproducible"`, the current v1 supersession contract is not sufficient persistence authority because it lacks the exact failed-artifact reference/digest/release tuple; durable adoption must leave that correction path fail-closed rather than infer it from a mutable row, the evidence-kind label, or a successor attempt. No durable adapter may infer currentness from mutable current rows, unrelated result attempts, different-evidence-family attempts, or caller-supplied timestamps. +The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable predecessor verification-attempt reference/digest and preserve failed-evidence and attempt-release chronology. Missing-evidence correction uses the v1 same-result/same-obligation successor graph. Non-reproducible correction uses v2 and must additionally persist/recover the predecessor failed-evidence reference/digest/release instant and require the successor target tuple to equal it exactly; that failed-artifact tuple is owner-resolved evidence, not a caller lookup key. Both versions require successor verification-attempt release exactly at the predecessor cutover. No durable adapter may infer currentness from mutable current rows, unrelated result attempts, different-evidence-family attempts, different artifacts in the same family, or caller-supplied timestamps. ## Test contract @@ -155,6 +155,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, and explicit missing/non-reproducible evidence including exact verification-attempt identity, chronology, currentness, same-result/same-failed-evidence-obligation successor-attempt authority for missing-evidence predecessors, and fail-closed rejection of lossy `non_reproducible` supersession until exact failed-artifact identity is carried by the versioned correction contract. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, explicit missing/non-reproducible evidence with exact verification-attempt identity and chronology, v1 same-result/same-failed-evidence-obligation correction for missing predecessors, and v2 exact failed-artifact correction for non-reproducible predecessors including hostile mismatched-artifact, chronology, authorization, owner-port and structural-integrity cases. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From e00a7b38797accfe83bc55b2693ba00ee60956fa Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 01:15:26 +0900 Subject: [PATCH 353/603] test(workforce-validation): red v2 ordinary cutover alignment --- ...ility_supersession_v2_cutover_alignment.py | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_cutover_alignment.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_cutover_alignment.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_cutover_alignment.py new file mode 100644 index 000000000..7193993d6 --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_cutover_alignment.py @@ -0,0 +1,101 @@ +"""RED contract binding v2 correction edges to ordinary predecessor cutover chronology.""" + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.result_nonverifiability import ( + ValidationResultNonVerifiabilityRecord, +) +from orgmetra_workforce_validation_api.result_nonverifiability_supersession_v2_authority import ( + ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +FAILED_REFERENCE = "analysis_weight_receipt:22222222-2222-4222-8222-222222222222" +ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:33333333-3333-4333-8333-333333333333" +SUCCESSOR_ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:44444444-4444-4444-8444-444444444444" +OWNER_REFERENCE = "released_owner_contract:55555555-5555-4555-8555-555555555555" +RESULT_DIGEST = "1" * 64 +FAILED_DIGEST = "2" * 64 +ATTEMPT_DIGEST = "3" * 64 +SUCCESSOR_DIGEST = "4" * 64 +OWNER_DIGEST = "5" * 64 +OWNER_RELEASED_AT = datetime(2026, 9, 17, 5, 55, tzinfo=timezone.utc) +FAILED_RELEASED_AT = datetime(2026, 9, 17, 5, 59, tzinfo=timezone.utc) +EVALUATED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) +ATTEMPT_RELEASED_AT = datetime(2026, 9, 17, 6, 2, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 6, 5, tzinfo=timezone.utc) +CUTOVER = datetime(2026, 9, 17, 7, 0, tzinfo=timezone.utc) +OTHER_CUTOVER = datetime(2026, 9, 17, 7, 1, tzinfo=timezone.utc) + + +def _predecessor(*, superseded_at: datetime | None) -> ValidationResultNonVerifiabilityRecord: + return ValidationResultNonVerifiabilityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + failed_evidence_kind="analysis_weight_receipt", + failure_mode="non_reproducible", + failed_evidence_reference=FAILED_REFERENCE, + failed_evidence_digest=FAILED_DIGEST, + failed_evidence_released_at=FAILED_RELEASED_AT, + verification_attempt_reference=ATTEMPT_REFERENCE, + verification_attempt_digest=ATTEMPT_DIGEST, + verification_attempt_released_at=ATTEMPT_RELEASED_AT, + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=7, + owner_contract_digest=OWNER_DIGEST, + owner_contract_released_at=OWNER_RELEASED_AT, + evaluated_at=EVALUATED_AT, + released_at=RELEASED_AT, + superseded_at=superseded_at, + ) + + +def _successor_values(*, superseded_at: datetime) -> dict[str, object]: + return { + "superseded_at": superseded_at, + "successor_target_result_reference": RESULT_REFERENCE, + "successor_target_result_digest": RESULT_DIGEST, + "successor_failed_evidence_kind": "analysis_weight_receipt", + "successor_target_failed_evidence_reference": FAILED_REFERENCE, + "successor_target_failed_evidence_digest": FAILED_DIGEST, + "successor_target_failed_evidence_released_at": FAILED_RELEASED_AT, + "successor_verification_attempt_reference": SUCCESSOR_ATTEMPT_REFERENCE, + "successor_verification_attempt_digest": SUCCESSOR_DIGEST, + "successor_verification_attempt_released_at": superseded_at, + } + + +def test_successor_requires_the_same_cutover_as_the_ordinary_predecessor() -> None: + """An explicit edge must not disagree with the ordinary owner projection.""" + with pytest.raises(ValueError, match="ordinary predecessor cutover"): + ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord( + predecessor=_predecessor(superseded_at=CUTOVER), + evidence_version=2, + **_successor_values(superseded_at=OTHER_CUTOVER), + ) + + +def test_successor_is_invalid_when_ordinary_predecessor_has_no_cutover() -> None: + """A separate edge must not manufacture currentness absent from the ordinary record.""" + with pytest.raises(ValueError, match="ordinary predecessor cutover"): + ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord( + predecessor=_predecessor(superseded_at=None), + evidence_version=2, + **_successor_values(superseded_at=CUTOVER), + ) + + +def test_current_v2_projection_rejects_a_predecessor_already_marked_superseded() -> None: + """Omitting successor coordinates must not hide an owner-resolved ordinary cutover.""" + with pytest.raises(ValueError, match="ordinary predecessor cutover"): + ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord( + predecessor=_predecessor(superseded_at=CUTOVER), + evidence_version=2, + ) From ad56ce5939af93cd7a15d398292e588edbf0c2c8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 01:16:36 +0900 Subject: [PATCH 354/603] fix(workforce-validation): align v2 edge with ordinary cutover --- ...verifiability_supersession_v2_authority.py | 234 +++++++++++++----- 1 file changed, 173 insertions(+), 61 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py index 5664c67e4..4fb30db43 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py @@ -34,25 +34,52 @@ _VERSION = 2 _READ_FIELDS = frozenset( { - "result_reference", "result_digest", "failed_evidence_kind", "failure_mode", - "failed_evidence_reference", "failed_evidence_digest", "failed_evidence_released_at", - "verification_attempt_reference", "verification_attempt_digest", - "verification_attempt_released_at", "evidence_version", "owner_contract_reference", - "owner_contract_version", "owner_contract_digest", "owner_contract_released_at", - "released_at", "superseded_at", "successor_target_result_reference", - "successor_target_result_digest", "successor_failed_evidence_kind", - "successor_target_failed_evidence_reference", "successor_target_failed_evidence_digest", - "successor_target_failed_evidence_released_at", "successor_verification_attempt_reference", - "successor_verification_attempt_digest", "successor_verification_attempt_released_at", + "result_reference", + "result_digest", + "failed_evidence_kind", + "failure_mode", + "failed_evidence_reference", + "failed_evidence_digest", + "failed_evidence_released_at", + "verification_attempt_reference", + "verification_attempt_digest", + "verification_attempt_released_at", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_target_result_reference", + "successor_target_result_digest", + "successor_failed_evidence_kind", + "successor_target_failed_evidence_reference", + "successor_target_failed_evidence_digest", + "successor_target_failed_evidence_released_at", + "successor_verification_attempt_reference", + "successor_verification_attempt_digest", + "successor_verification_attempt_released_at", } ) _VIEW_FIELDS = frozenset( { - "result_reference", "result_digest", "failed_evidence_kind", "failure_mode", - "failed_evidence_reference", "failed_evidence_digest", "failed_evidence_released_at", - "verification_attempt_reference", "verification_attempt_digest", - "verification_attempt_released_at", "evidence_version", "owner_contract_reference", - "owner_contract_version", "owner_contract_digest", "owner_contract_released_at", "released_at", + "result_reference", + "result_digest", + "failed_evidence_kind", + "failure_mode", + "failed_evidence_reference", + "failed_evidence_digest", + "failed_evidence_released_at", + "verification_attempt_reference", + "verification_attempt_digest", + "verification_attempt_released_at", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", } ) @@ -121,16 +148,28 @@ def __new__( failed_digest = predecessor.failed_evidence_digest failed_release = predecessor.failed_evidence_released_at if failed_reference is None or failed_digest is None or failed_release is None: - raise ValueError("non_reproducible predecessor must retain exact failed-artifact evidence.") + raise ValueError( + "non_reproducible predecessor must retain exact failed-artifact evidence." + ) successor_values = ( - superseded_at, successor_target_result_reference, successor_target_result_digest, - successor_failed_evidence_kind, successor_target_failed_evidence_reference, - successor_target_failed_evidence_digest, successor_target_failed_evidence_released_at, - successor_verification_attempt_reference, successor_verification_attempt_digest, + superseded_at, + successor_target_result_reference, + successor_target_result_digest, + successor_failed_evidence_kind, + successor_target_failed_evidence_reference, + successor_target_failed_evidence_digest, + successor_target_failed_evidence_released_at, + successor_verification_attempt_reference, + successor_verification_attempt_digest, successor_verification_attempt_released_at, ) + ordinary_cutover = predecessor.superseded_at if all(value is None for value in successor_values): + if ordinary_cutover is not None: + raise ValueError( + "v2 correction coordinates must match the ordinary predecessor cutover." + ) cutover = None successor_fields = None elif any(value is None for value in successor_values): @@ -140,10 +179,15 @@ def __new__( ) else: cutover = _require_aware_datetime("superseded_at", superseded_at) + if ordinary_cutover is None or cutover != ordinary_cutover: + raise ValueError( + "v2 supersession must equal the ordinary predecessor cutover." + ) if cutover <= predecessor.released_at: raise ValueError("superseded_at must be later than predecessor release.") target_result_reference = _require_reference( - "successor_target_result_reference", successor_target_result_reference, + "successor_target_result_reference", + successor_target_result_reference, "validation_analysis_result", ) target_result_digest = _require_digest( @@ -151,22 +195,26 @@ def __new__( ) target_kind = _require_failed_evidence_kind(successor_failed_evidence_kind) target_failed_reference = _require_reference( - "successor_target_failed_evidence_reference", successor_target_failed_evidence_reference, + "successor_target_failed_evidence_reference", + successor_target_failed_evidence_reference, _FAILED_REFERENCE_KIND_BY_EVIDENCE_KIND[predecessor.failed_evidence_kind], ) target_failed_digest = _require_digest( - "successor_target_failed_evidence_digest", successor_target_failed_evidence_digest + "successor_target_failed_evidence_digest", + successor_target_failed_evidence_digest, ) target_failed_release = _require_aware_datetime( "successor_target_failed_evidence_released_at", successor_target_failed_evidence_released_at, ) successor_reference = _require_reference( - "successor_verification_attempt_reference", successor_verification_attempt_reference, + "successor_verification_attempt_reference", + successor_verification_attempt_reference, "validation_evidence_verification_attempt", ) successor_digest = _require_digest( - "successor_verification_attempt_digest", successor_verification_attempt_digest + "successor_verification_attempt_digest", + successor_verification_attempt_digest, ) successor_release = _require_aware_datetime( "successor_verification_attempt_released_at", @@ -178,22 +226,32 @@ def __new__( ): raise ValueError("successor attempt must target the exact predecessor result.") if target_kind != predecessor.failed_evidence_kind: - raise ValueError("successor attempt must re-evaluate the same failed-evidence family.") + raise ValueError( + "successor attempt must re-evaluate the same failed-evidence family." + ) if ( target_failed_reference != failed_reference or target_failed_digest != failed_digest or target_failed_release != failed_release ): - raise ValueError("successor attempt must target the exact failed artifact and release chronology.") + raise ValueError( + "successor attempt must target the exact failed artifact and release chronology." + ) if successor_reference == predecessor.verification_attempt_reference: raise ValueError("successor verification attempt must use a new reference.") if successor_digest in { - predecessor.result_digest, failed_digest, predecessor.verification_attempt_digest, + predecessor.result_digest, + failed_digest, + predecessor.verification_attempt_digest, predecessor.owner_contract_digest, }: - raise ValueError("successor verification attempt must identify new evidence.") + raise ValueError( + "successor verification attempt must identify new evidence." + ) if successor_release != cutover: - raise ValueError("successor verification attempt must be released exactly at supersession.") + raise ValueError( + "successor verification attempt must be released exactly at supersession." + ) successor_fields = ( ("successor_failed_evidence_kind", target_kind), ("successor_target_failed_evidence_digest", target_failed_digest), @@ -244,7 +302,10 @@ class ValidationResultNonVerifiabilitySupersessionV2AuthorityView(tuple): __slots__ = () def __new__( - cls, *, tenant_record_id: UUID, validity_study_id: UUID, + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, fields: tuple[tuple[str, object], ...], ) -> ValidationResultNonVerifiabilitySupersessionV2AuthorityView: """Reject public construction so only the resolver can issue an authorized view.""" @@ -274,10 +335,19 @@ class ValidationResultNonVerifiabilitySupersessionV2AuthorityReadPort(Protocol): """Read exact-artifact supersession evidence through the workforce-validation ACL.""" def read_validation_result_nonverifiability_supersession_v2_authority( - self, *, tenant_record_id: UUID, validity_study_id: UUID, result_reference: str, - result_digest: str, failed_evidence_kind: str, verification_attempt_reference: str, - verification_attempt_digest: str, evidence_version: int, owner_contract_reference: str, - owner_contract_version: int, owner_contract_digest: str, + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + failed_evidence_kind: str, + verification_attempt_reference: str, + verification_attempt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, ) -> ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord | None: """Return one released v2 correction record or ``None``.""" ... @@ -290,11 +360,22 @@ def read_validation_result_nonverifiability_supersession_v2_authority( def resolve_validation_result_nonverifiability_supersession_v2_authority( - *, principal: ValidationPrincipal, tenant_record_id: UUID, validity_study_id: UUID, - result_reference: str, result_digest: str, failed_evidence_kind: str, - verification_attempt_reference: str, verification_attempt_digest: str, evidence_version: int, - owner_contract_reference: str, owner_contract_version: int, owner_contract_digest: str, - used_at: datetime, purpose_code: str, policy: PurposeBoundAccessPolicy, + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + failed_evidence_kind: str, + verification_attempt_reference: str, + verification_attempt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, read_port: ValidationResultNonVerifiabilitySupersessionV2AuthorityReadPort, ) -> ValidationResultNonVerifiabilitySupersessionV2AuthorityView: """Authorize then resolve one exact-artifact non-reproducible correction interval.""" @@ -303,7 +384,9 @@ def resolve_validation_result_nonverifiability_supersession_v2_authority( if type(policy) is not PurposeBoundAccessPolicy: raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") read_capability = getattr_static( - type(read_port), "read_validation_result_nonverifiability_supersession_v2_authority", None + type(read_port), + "read_validation_result_nonverifiability_supersession_v2_authority", + None, ) if type(read_capability) is not FunctionType or read_capability is _PROTOCOL_READ_CAPABILITY: raise TypeError( @@ -315,50 +398,72 @@ def resolve_validation_result_nonverifiability_supersession_v2_authority( "tenant_record_id", _store_operational_uuid("tenant_record_id", tenant_record_id) ) study_id = _restore_operational_uuid( - "validity_study_id", _store_operational_uuid("validity_study_id", validity_study_id) + "validity_study_id", + _store_operational_uuid("validity_study_id", validity_study_id), + ) + result_ref = _require_reference( + "result_reference", result_reference, "validation_analysis_result" ) - result_ref = _require_reference("result_reference", result_reference, "validation_analysis_result") result_evidence_digest = _require_digest("result_digest", result_digest) evidence_kind = _require_failed_evidence_kind(failed_evidence_kind) attempt_ref = _require_reference( - "verification_attempt_reference", verification_attempt_reference, + "verification_attempt_reference", + verification_attempt_reference, "validation_evidence_verification_attempt", ) - attempt_digest = _require_digest("verification_attempt_digest", verification_attempt_digest) + attempt_digest = _require_digest( + "verification_attempt_digest", verification_attempt_digest + ) version = _require_positive_integer("evidence_version", evidence_version) if version != _VERSION: raise ValueError("evidence_version must be 2 for exact-artifact supersession.") owner_ref = _require_reference( "owner_contract_reference", owner_contract_reference, "released_owner_contract" ) - owner_version = _require_positive_integer("owner_contract_version", owner_contract_version) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) use_instant = _require_aware_datetime("used_at", used_at) purpose = _require_code("purpose_code", purpose_code) detached_principal = ValidationPrincipal( - tenant_record_id=principal.tenant_record_id, actor_reference=principal.actor_reference, + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, granted_scope_codes=principal.granted_scope_codes, ) require_purpose_bound_access( request=PurposeBoundAccessRequest( - tenant_record_id=tenant_id, actor_tenant_record_id=detached_principal.tenant_record_id, - resource_tenant_record_id=tenant_id, actor_reference=detached_principal.actor_reference, - resource_reference=f"{_RESOURCE_KIND}:{study_id}", purpose_code=purpose, - operation_code=_OPERATION, resource_kind=_RESOURCE_KIND, requested_fields=_READ_FIELDS, + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, granted_scope_codes=detached_principal.granted_scope_codes, ), policy=_detach_policy(policy), ) persisted = read_capability( - read_port, tenant_record_id=tenant_id, validity_study_id=study_id, - result_reference=result_ref, result_digest=result_evidence_digest, - failed_evidence_kind=evidence_kind, verification_attempt_reference=attempt_ref, - verification_attempt_digest=attempt_digest, evidence_version=version, - owner_contract_reference=owner_ref, owner_contract_version=owner_version, + read_port, + tenant_record_id=tenant_id, + validity_study_id=study_id, + result_reference=result_ref, + result_digest=result_evidence_digest, + failed_evidence_kind=evidence_kind, + verification_attempt_reference=attempt_ref, + verification_attempt_digest=attempt_digest, + evidence_version=version, + owner_contract_reference=owner_ref, + owner_contract_version=owner_version, owner_contract_digest=owner_digest, ) if persisted is None: - raise ValidationResultNonVerifiabilitySupersessionV2AuthorityNotFound(str(study_id)) + raise ValidationResultNonVerifiabilitySupersessionV2AuthorityNotFound( + str(study_id) + ) if type(persisted) is not ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord: raise ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError( "owner port returned non-canonical v2 non-verifiability supersession evidence" @@ -377,9 +482,13 @@ def resolve_validation_result_nonverifiability_supersession_v2_authority( "verification_attempt_reference": attempt_ref, } if ( - _store_operational_uuid("record tenant_record_id", predecessor.tenant_record_id) + _store_operational_uuid( + "record tenant_record_id", predecessor.tenant_record_id + ) != _store_operational_uuid("requested tenant_record_id", tenant_id) - or _store_operational_uuid("record validity_study_id", predecessor.validity_study_id) + or _store_operational_uuid( + "record validity_study_id", predecessor.validity_study_id + ) != _store_operational_uuid("requested validity_study_id", study_id) or any(values[name] != value for name, value in requested_values.items()) ): @@ -398,8 +507,11 @@ def resolve_validation_result_nonverifiability_supersession_v2_authority( fields = tuple((name, projection_values[name]) for name in sorted(_VIEW_FIELDS)) return tuple.__new__( ValidationResultNonVerifiabilitySupersessionV2AuthorityView, - (_store_operational_uuid("tenant_record_id", tenant_id), - _store_operational_uuid("validity_study_id", study_id), fields), + ( + _store_operational_uuid("tenant_record_id", tenant_id), + _store_operational_uuid("validity_study_id", study_id), + fields, + ), ) From 5d25f305c6839ece74a26b17eed52131beb2b09c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 01:18:01 +0900 Subject: [PATCH 355/603] test(workforce-validation): align v2 fixtures with ordinary cutover --- ...ifiability_supersession_v2_authority_edges.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py index 05edac609..c92a6a69a 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py @@ -164,9 +164,8 @@ def _record( predecessor: ValidationResultNonVerifiabilityRecord | None = None, **overrides: object, ) -> ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord: - """Build current v2 authority with optional owner-supplied successor coordinates.""" + """Build v2 authority while keeping the ordinary cutover and explicit edge aligned.""" values: dict[str, object] = { - "predecessor": _predecessor() if predecessor is None else predecessor, "evidence_version": 2, "superseded_at": None, "successor_target_result_reference": None, @@ -180,6 +179,18 @@ def _record( "successor_verification_attempt_released_at": None, } values.update(overrides) + if predecessor is None: + requested_cutover = values["superseded_at"] + if ( + type(requested_cutover) is datetime + and requested_cutover.tzinfo is not None + and requested_cutover.utcoffset() is not None + and requested_cutover > RELEASED_AT + ): + predecessor = _predecessor(superseded_at=requested_cutover) + else: + predecessor = _predecessor() + values["predecessor"] = predecessor return ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord(**values) @@ -272,6 +283,7 @@ def test_current_non_reproducible_outcome_resolves_with_exact_failed_artifact() def test_exact_artifact_successor_preserves_historical_use_but_ends_at_cutover() -> None: """Require one atomic same-result, same-artifact successor attempt.""" record = _record(**_successor_overrides()) + assert record.predecessor.superseded_at == CUTOVER assert dict(record.successor_fields or ()) == { "successor_failed_evidence_kind": "analysis_weight_receipt", "successor_target_failed_evidence_digest": FAILED_DIGEST, From 56e779f486fba8f95347829d1b2c5b8e4bbace7c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 01:18:54 +0900 Subject: [PATCH 356/603] fix(workforce-validation): preserve malformed-cutover rejection order --- .../result_nonverifiability_supersession_v2_authority.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py index 4fb30db43..25a028a63 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py @@ -179,12 +179,12 @@ def __new__( ) else: cutover = _require_aware_datetime("superseded_at", superseded_at) + if cutover <= predecessor.released_at: + raise ValueError("superseded_at must be later than predecessor release.") if ordinary_cutover is None or cutover != ordinary_cutover: raise ValueError( "v2 supersession must equal the ordinary predecessor cutover." ) - if cutover <= predecessor.released_at: - raise ValueError("superseded_at must be later than predecessor release.") target_result_reference = _require_reference( "successor_target_result_reference", successor_target_result_reference, From e91d8a5cde75756b2aba613f797f758a9227a894 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 01:20:47 +0900 Subject: [PATCH 357/603] docs(workforce-validation): bind v2 edge to ordinary cutover --- services/workforce-validation-api/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 07678f600..aaa89d8fa 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -124,7 +124,7 @@ The immutable `verification_attempt_reference` and `verification_attempt_digest` `resolve_validation_result_nonverifiability_supersession_authority(...)` is the v1 correction contract for a predecessor `failure_mode="missing"`. It requires a complete immutable successor verification-attempt reference/digest/release tuple plus an owner-supplied target-result reference/digest and `successor_failed_evidence_kind`. The successor target must equal the predecessor result exactly, the failed-evidence kind must match, the successor attempt must identify new evidence, and its release must equal the predecessor `superseded_at`. This v1 path deliberately rejects `non_reproducible` because its tuple cannot retain the exact artifact whose reproducibility failed. -`resolve_validation_result_nonverifiability_supersession_v2_authority(...)` supplies that exact-artifact path without weakening v1. It consumes the canonical released `ValidationResultNonVerifiabilityRecord` for a `non_reproducible` predecessor, keeps the failed-evidence reference/digest/release instant as owner-resolved predecessor provenance, and requires any successor attempt to target the exact same result, failed-evidence family, failed-evidence reference, failed-evidence digest, and failed-evidence release chronology. The v2 successor must still use new immutable verification-attempt evidence and be released exactly at `superseded_at`. Caller/read-port lookup coordinates do not include the failed-artifact tuple; persistence must recover it from canonical released owner evidence rather than let a caller choose favorable provenance. +`resolve_validation_result_nonverifiability_supersession_v2_authority(...)` supplies that exact-artifact path without weakening v1. It consumes the canonical released `ValidationResultNonVerifiabilityRecord` for a `non_reproducible` predecessor, keeps the failed-evidence reference/digest/release instant as owner-resolved predecessor provenance, and requires any successor attempt to target the exact same result, failed-evidence family, failed-evidence reference, failed-evidence digest, and failed-evidence release chronology. The v2 successor must use new immutable verification-attempt evidence and be released exactly at the ordinary predecessor's owner-resolved `superseded_at`. An explicit v2 successor is invalid when the ordinary predecessor has no cutover or a different cutover, and omitting successor coordinates is invalid when the ordinary predecessor is already marked superseded. Caller/read-port lookup coordinates do not include the failed-artifact tuple or cutover; persistence must recover both from canonical released owner evidence rather than let a caller choose favorable provenance. Both minimized views omit cutover and successor coordinates. A successor verification attempt only ends the predecessor negative-outcome interval; it does not imply scientific GREEN. Any subsequent released result or negative outcome must satisfy its own governed owner and verification contract. @@ -136,7 +136,7 @@ The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL r Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **twenty-one** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration support chronology, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, base/design-weight supersession, complete final analysis-weight lineage, final-weight supersession, point-weight/variance compatibility, point-weight/variance supersession, validation-result binding, validation-result supersession, validation-result non-verifiability, and validation-result non-verifiability supersession. -The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable predecessor verification-attempt reference/digest and preserve failed-evidence and attempt-release chronology. Missing-evidence correction uses the v1 same-result/same-obligation successor graph. Non-reproducible correction uses v2 and must additionally persist/recover the predecessor failed-evidence reference/digest/release instant and require the successor target tuple to equal it exactly; that failed-artifact tuple is owner-resolved evidence, not a caller lookup key. Both versions require successor verification-attempt release exactly at the predecessor cutover. No durable adapter may infer currentness from mutable current rows, unrelated result attempts, different-evidence-family attempts, different artifacts in the same family, or caller-supplied timestamps. +The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable predecessor verification-attempt reference/digest and preserve failed-evidence and attempt-release chronology. Missing-evidence correction uses the v1 same-result/same-obligation successor graph. Non-reproducible correction uses v2 and must additionally persist/recover the predecessor failed-evidence reference/digest/release instant and require the successor target tuple to equal it exactly; that failed-artifact tuple is owner-resolved evidence, not a caller lookup key. V2 must also cross-check the explicit correction cutover against the ordinary predecessor's owner-resolved `superseded_at`; neither side may manufacture or hide the other. Both versions require successor verification-attempt release exactly at the predecessor cutover. No durable adapter may infer currentness from mutable current rows, unrelated result attempts, different-evidence-family attempts, different artifacts in the same family, or caller-supplied timestamps. ## Test contract @@ -155,6 +155,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, explicit missing/non-reproducible evidence with exact verification-attempt identity and chronology, v1 same-result/same-failed-evidence-obligation correction for missing predecessors, and v2 exact failed-artifact correction for non-reproducible predecessors including hostile mismatched-artifact, chronology, authorization, owner-port and structural-integrity cases. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, explicit missing/non-reproducible evidence with exact verification-attempt identity and chronology, v1 same-result/same-failed-evidence-obligation correction for missing predecessors, and v2 exact failed-artifact correction for non-reproducible predecessors including ordinary-cutover alignment, hostile mismatched-artifact, chronology, authorization, owner-port and structural-integrity cases. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From c68c6c5e46e2142ecf473096448519fdc2a754d1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 01:29:08 +0900 Subject: [PATCH 358/603] test(workforce-validation): revalidate v2 predecessor invariants --- ...y_supersession_v2_predecessor_integrity.py | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_predecessor_integrity.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_predecessor_integrity.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_predecessor_integrity.py new file mode 100644 index 000000000..050f95623 --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_predecessor_integrity.py @@ -0,0 +1,80 @@ +"""Require v2 correction authority to revalidate the complete predecessor contract.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.result_nonverifiability import ( + ValidationResultNonVerifiabilityRecord, +) +from orgmetra_workforce_validation_api.result_nonverifiability_supersession_v2_authority import ( + ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +FAILED_REFERENCE = "analysis_weight_receipt:22222222-2222-4222-8222-222222222222" +ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:33333333-3333-4333-8333-333333333333" +OWNER_REFERENCE = "released_owner_contract:55555555-5555-4555-8555-555555555555" +RESULT_DIGEST = "1" * 64 +FAILED_DIGEST = "2" * 64 +ATTEMPT_DIGEST = "3" * 64 +OWNER_DIGEST = "5" * 64 +OWNER_RELEASED_AT = datetime(2026, 9, 17, 5, 55, tzinfo=timezone.utc) +FAILED_RELEASED_AT = datetime(2026, 9, 17, 5, 59, tzinfo=timezone.utc) +EVALUATED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) +ATTEMPT_RELEASED_AT = datetime(2026, 9, 17, 6, 2, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 6, 5, tzinfo=timezone.utc) + + +def _predecessor() -> ValidationResultNonVerifiabilityRecord: + """Build one canonical non-reproducible predecessor before structural corruption.""" + return ValidationResultNonVerifiabilityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + failed_evidence_kind="analysis_weight_receipt", + failure_mode="non_reproducible", + failed_evidence_reference=FAILED_REFERENCE, + failed_evidence_digest=FAILED_DIGEST, + failed_evidence_released_at=FAILED_RELEASED_AT, + verification_attempt_reference=ATTEMPT_REFERENCE, + verification_attempt_digest=ATTEMPT_DIGEST, + verification_attempt_released_at=ATTEMPT_RELEASED_AT, + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=7, + owner_contract_digest=OWNER_DIGEST, + owner_contract_released_at=OWNER_RELEASED_AT, + evaluated_at=EVALUATED_AT, + released_at=RELEASED_AT, + ) + + +@pytest.mark.parametrize( + ("tuple_index", "hostile_value"), + [ + (7, RESULT_DIGEST), + (13, EVALUATED_AT + timedelta(seconds=1)), + (17, EVALUATED_AT + timedelta(seconds=1)), + (18, EVALUATED_AT - timedelta(seconds=1)), + ], +) +def test_v2_revalidates_full_predecessor_invariants( + tuple_index: int, hostile_value: object +) -> None: + """Reject exact-typed predecessors forged around v1 digest or chronology guards.""" + canonical = _predecessor() + forged_values = list(canonical) + forged_values[tuple_index] = hostile_value + forged = tuple.__new__(ValidationResultNonVerifiabilityRecord, forged_values) + + with pytest.raises(ValueError): + ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord( + predecessor=forged, + evidence_version=2, + ) From ad366a1ab4e7f7bcfb21953bfeafc24d912a4a25 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 01:30:28 +0900 Subject: [PATCH 359/603] fix(workforce-validation): revalidate v2 predecessor invariants --- ...verifiability_supersession_v2_authority.py | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py index 25a028a63..9e6e57a6f 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py @@ -115,6 +115,33 @@ def _predecessor_fields( ) +def _revalidate_predecessor( + predecessor: ValidationResultNonVerifiabilityRecord, +) -> ValidationResultNonVerifiabilityRecord: + """Reconstruct the predecessor so tuple-level forgery cannot bypass owner invariants.""" + return ValidationResultNonVerifiabilityRecord( + tenant_record_id=predecessor.tenant_record_id, + validity_study_id=predecessor.validity_study_id, + result_reference=predecessor.result_reference, + result_digest=predecessor.result_digest, + failed_evidence_kind=predecessor.failed_evidence_kind, + failure_mode=predecessor.failure_mode, + failed_evidence_reference=predecessor.failed_evidence_reference, + failed_evidence_digest=predecessor.failed_evidence_digest, + failed_evidence_released_at=predecessor.failed_evidence_released_at, + verification_attempt_reference=predecessor.verification_attempt_reference, + verification_attempt_digest=predecessor.verification_attempt_digest, + verification_attempt_released_at=predecessor.verification_attempt_released_at, + owner_contract_reference=predecessor.owner_contract_reference, + owner_contract_version=predecessor.owner_contract_version, + owner_contract_digest=predecessor.owner_contract_digest, + owner_contract_released_at=predecessor.owner_contract_released_at, + evaluated_at=predecessor.evaluated_at, + released_at=predecessor.released_at, + superseded_at=predecessor.superseded_at, + ) + + class ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord(tuple): """Bind a non-reproducible predecessor to an exact-artifact successor attempt.""" @@ -139,6 +166,7 @@ def __new__( """Validate exact predecessor provenance and an optional atomic successor cutover.""" if type(predecessor) is not ValidationResultNonVerifiabilityRecord: raise TypeError("predecessor must be an exact ValidationResultNonVerifiabilityRecord.") + predecessor = _revalidate_predecessor(predecessor) if predecessor.failure_mode != "non_reproducible": raise ValueError("v2 supersession is reserved for non_reproducible predecessors.") version = _require_positive_integer("evidence_version", evidence_version) From 675e533b659823dcc8453a6b3e574382ca9f0bf9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 01:31:26 +0900 Subject: [PATCH 360/603] test(workforce-validation): reject forged v2 owner evidence --- ...y_supersession_v2_predecessor_integrity.py | 86 ++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_predecessor_integrity.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_predecessor_integrity.py index 050f95623..b9296267f 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_predecessor_integrity.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_predecessor_integrity.py @@ -6,12 +6,16 @@ from uuid import UUID import pytest - +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api.registry import ValidationPrincipal from orgmetra_workforce_validation_api.result_nonverifiability import ( ValidationResultNonVerifiabilityRecord, ) from orgmetra_workforce_validation_api.result_nonverifiability_supersession_v2_authority import ( + ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError, ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord, + _READ_FIELDS, + resolve_validation_result_nonverifiability_supersession_v2_authority, ) TENANT = UUID("10000000-0000-7000-8000-000000000001") @@ -29,6 +33,7 @@ EVALUATED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) ATTEMPT_RELEASED_AT = datetime(2026, 9, 17, 6, 2, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 17, 6, 5, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 6, 10, tzinfo=timezone.utc) def _predecessor() -> ValidationResultNonVerifiabilityRecord: @@ -55,6 +60,42 @@ def _predecessor() -> ValidationResultNonVerifiabilityRecord: ) +class _ReadPort: + """Return configured owner evidence through the v2 read capability.""" + + def __init__(self, result: object) -> None: + self.result = result + + def read_validation_result_nonverifiability_supersession_v2_authority( + self, **coordinates: object + ) -> object: + """Return configured evidence after accepting caller-known lookup coordinates.""" + del coordinates + return self.result + + +def _policy() -> PurposeBoundAccessPolicy: + """Permit the full owner evidence set used by the v2 resolver.""" + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="validation-result-nonverifiability-supersession-read-v2", + resource_kind="validation_result_nonverifiability_supersession_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=_READ_FIELDS, + ) + + +def _principal() -> ValidationPrincipal: + """Return one tenant-bound validation reader.""" + return ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + @pytest.mark.parametrize( ("tuple_index", "hostile_value"), [ @@ -78,3 +119,46 @@ def test_v2_revalidates_full_predecessor_invariants( predecessor=forged, evidence_version=2, ) + + +def test_resolver_revalidates_exact_typed_owner_evidence() -> None: + """Reject a structurally forged v2 record returned directly by an owner adapter.""" + canonical_predecessor = _predecessor() + forged_values = list(canonical_predecessor) + forged_values[13] = EVALUATED_AT + timedelta(seconds=1) + forged_predecessor = tuple.__new__( + ValidationResultNonVerifiabilityRecord, forged_values + ) + canonical_authority = ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord( + predecessor=canonical_predecessor, + evidence_version=2, + ) + forged_authority = tuple.__new__( + ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord, + ( + forged_predecessor, + canonical_authority.evidence_version, + canonical_authority.superseded_at, + canonical_authority.successor_fields, + ), + ) + + with pytest.raises(ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError): + resolve_validation_result_nonverifiability_supersession_v2_authority( + principal=_principal(), + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + failed_evidence_kind="analysis_weight_receipt", + verification_attempt_reference=ATTEMPT_REFERENCE, + verification_attempt_digest=ATTEMPT_DIGEST, + evidence_version=2, + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=7, + owner_contract_digest=OWNER_DIGEST, + used_at=USED_AT, + purpose_code="selection_validity_analysis", + policy=_policy(), + read_port=_ReadPort(forged_authority), + ) From aa1ec5082ecedebbe10d246c78f85859f8378265 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 01:32:29 +0900 Subject: [PATCH 361/603] fix(workforce-validation): canonicalize v2 owner evidence --- ...onverifiability_supersession_v2_authority.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py index 9e6e57a6f..8806170ea 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py @@ -496,6 +496,23 @@ def resolve_validation_result_nonverifiability_supersession_v2_authority( raise ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError( "owner port returned non-canonical v2 non-verifiability supersession evidence" ) + try: + successor_coordinates = dict(persisted.successor_fields or ()) + canonical = ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord( + predecessor=persisted.predecessor, + evidence_version=persisted.evidence_version, + superseded_at=persisted.superseded_at, + **successor_coordinates, + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError( + "owner port returned structurally invalid v2 non-verifiability supersession evidence" + ) from exc + if canonical != persisted: + raise ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError( + "owner port returned non-canonical v2 non-verifiability supersession structure" + ) + persisted = canonical predecessor = persisted.predecessor values = dict(persisted.fields) requested_values = { From 8bd5d9109a8935908ba2e47bdf7779322760e79c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 01:43:44 +0900 Subject: [PATCH 362/603] test(workforce-validation): cover v2 successor view nondisclosure --- ...ifiability_supersession_v2_authority_edges.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py index c92a6a69a..b944f34e2 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py @@ -296,7 +296,21 @@ def test_exact_artifact_successor_preserves_historical_use_but_ends_at_cutover() "successor_verification_attempt_released_at": CUTOVER, } view = _resolve(read_port=_ReadPort(record), used_at=CUTOVER - timedelta(seconds=1)) - assert dict(view.fields)["result_reference"] == RESULT_REFERENCE + fields = dict(view.fields) + assert fields["result_reference"] == RESULT_REFERENCE + hidden_owner_coordinates = { + "superseded_at", + "successor_target_result_reference", + "successor_target_result_digest", + "successor_failed_evidence_kind", + "successor_target_failed_evidence_reference", + "successor_target_failed_evidence_digest", + "successor_target_failed_evidence_released_at", + "successor_verification_attempt_reference", + "successor_verification_attempt_digest", + "successor_verification_attempt_released_at", + } + assert hidden_owner_coordinates.isdisjoint(fields) with pytest.raises(ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError): _resolve(read_port=_ReadPort(record), used_at=CUTOVER) From 73088822520b8c5a587caeaa60f0413920aeaa7a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 02:02:51 +0900 Subject: [PATCH 363/603] test(packaging): expose dist-info identity false green --- .../test_built_wheel_dist_info_identity.py | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py diff --git a/services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py b/services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py new file mode 100644 index 000000000..0ce9455bd --- /dev/null +++ b/services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py @@ -0,0 +1,101 @@ +"""Reject wheels whose dist-info directory does not match the built distribution identity.""" + +from __future__ import annotations + +import csv +import importlib.util +import io +from pathlib import Path +import zipfile + +import pytest + + +_CONTRACT_PATH = Path(__file__).with_name("test_package_metadata_compatibility.py") +_SPEC = importlib.util.spec_from_file_location( + "_workforce_package_metadata_contract_dist_info", + _CONTRACT_PATH, +) +assert _SPEC is not None and _SPEC.loader is not None +_CONTRACT = importlib.util.module_from_spec(_SPEC) +_SPEC.loader.exec_module(_CONTRACT) + + +def _write_wheel( + wheelhouse: Path, + *, + filename: str, + package_root: str, + dist_info_root: str, + metadata: str, + include_py_typed: bool, +) -> None: + """Create one internally self-consistent wheel with a selectable dist-info root.""" + members: dict[str, bytes] = { + f"{package_root}/__init__.py": b"", + f"{dist_info_root}/METADATA": metadata.encode("utf-8"), + f"{dist_info_root}/WHEEL": ( + "Wheel-Version: 1.0\n" + "Generator: orgmetra-test-fixture\n" + "Root-Is-Purelib: true\n" + "Tag: py3-none-any\n\n" + ).encode("utf-8"), + } + if include_py_typed: + members[f"{package_root}/py.typed"] = b"" + + record_path = f"{dist_info_root}/RECORD" + output = io.StringIO() + writer = csv.writer(output, lineterminator="\n") + for member_path in sorted(members): + member = members[member_path] + writer.writerow((member_path, _CONTRACT._record_hash(member), str(len(member)))) + writer.writerow((record_path, "", "")) + members[record_path] = output.getvalue().encode("utf-8") + + with zipfile.ZipFile(wheelhouse / filename, "w") as archive: + for member_path, content in members.items(): + archive.writestr(member_path, content) + + +def test_hash_locked_acceptance_rejects_mismatched_dist_info_identity(tmp_path: Path) -> None: + """A correct filename and METADATA must not hide a foreign dist-info directory identity.""" + wheelhouse = tmp_path / "wheelhouse" + wheelhouse.mkdir() + _write_wheel( + wheelhouse, + filename="orgmetra_keyverse_adapter-0.1.0-py3-none-any.whl", + package_root="orgmetra_keyverse_adapter", + dist_info_root="orgmetra_keyverse_adapter-0.1.0.dist-info", + metadata=( + "Metadata-Version: 2.4\n" + "Name: orgmetra-keyverse-adapter\n" + "Version: 0.1.0\n" + "Requires-Python: >=3.12\n" + "Provides-Extra: test\n" + "Requires-Dist: pytest>=8.3; extra == 'test'\n" + "Requires-Dist: pytest-cov>=5.0; extra == 'test'\n\n" + ), + include_py_typed=False, + ) + _write_wheel( + wheelhouse, + filename="orgmetra_workforce_validation_api-0.1.0-py3-none-any.whl", + package_root="orgmetra_workforce_validation_api", + dist_info_root="foreign_distribution-0.1.0.dist-info", + metadata=( + "Metadata-Version: 2.4\n" + "Name: orgmetra-workforce-validation-api\n" + "Version: 0.1.0\n" + "Requires-Python: >=3.12\n" + "Requires-Dist: orgmetra-keyverse-adapter==0.1.0\n\n" + ), + include_py_typed=True, + ) + + with pytest.raises(AssertionError, match="dist-info identity"): + _CONTRACT._locked_wheel_requirements( + wheelhouse, + service_version="0.1.0", + keyverse_version="0.1.0", + ) From a1c61dc62fdbf47cb882177610793f2e5bf3b803 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 02:05:02 +0900 Subject: [PATCH 364/603] test(packaging): bind dist-info root to built wheel identity --- .../test_built_wheel_dist_info_identity.py | 85 ++++++++++++++++++- 1 file changed, 83 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py b/services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py index 0ce9455bd..85ff3c430 100644 --- a/services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py +++ b/services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py @@ -5,9 +5,12 @@ import csv import importlib.util import io -from pathlib import Path +from pathlib import Path, PurePosixPath +import subprocess +import sys import zipfile +from packaging.utils import canonicalize_name, parse_wheel_filename import pytest @@ -58,6 +61,41 @@ def _write_wheel( archive.writestr(member_path, content) +def _assert_dist_info_identity(wheel_path: Path) -> None: + """Bind the sole dist-info root to the normalized wheel filename name and version.""" + parsed_name, parsed_version, _build, _tags = parse_wheel_filename(wheel_path.name) + expected_root = ( + f"{canonicalize_name(parsed_name).replace('-', '_')}-{parsed_version}.dist-info" + ) + with zipfile.ZipFile(wheel_path) as archive: + roots = { + PurePosixPath(name).parts[0] + for name in archive.namelist() + if PurePosixPath(name).parts + and PurePosixPath(name).parts[0].endswith(".dist-info") + } + assert roots == {expected_root}, ( + f"{wheel_path.name} dist-info identity must be {expected_root}, observed {sorted(roots)}" + ) + + +def _validate_distribution_acceptance( + wheelhouse: Path, + *, + service_version: str, + keyverse_version: str, +) -> tuple[str, dict[str, Path]]: + """Run the existing wheel lock contract plus exact dist-info directory identity binding.""" + locked_requirements, wheels_by_name = _CONTRACT._locked_wheel_requirements( + wheelhouse, + service_version=service_version, + keyverse_version=keyverse_version, + ) + for wheel_path in wheels_by_name.values(): + _assert_dist_info_identity(wheel_path) + return locked_requirements, wheels_by_name + + def test_hash_locked_acceptance_rejects_mismatched_dist_info_identity(tmp_path: Path) -> None: """A correct filename and METADATA must not hide a foreign dist-info directory identity.""" wheelhouse = tmp_path / "wheelhouse" @@ -94,8 +132,51 @@ def test_hash_locked_acceptance_rejects_mismatched_dist_info_identity(tmp_path: ) with pytest.raises(AssertionError, match="dist-info identity"): - _CONTRACT._locked_wheel_requirements( + _validate_distribution_acceptance( wheelhouse, service_version="0.1.0", keyverse_version="0.1.0", ) + + +def test_built_owned_wheels_bind_dist_info_to_filename_identity(tmp_path: Path) -> None: + """Prove the exact wheels built from reviewed owned sources satisfy the identity binding.""" + service_project = _CONTRACT._project_metadata(_CONTRACT._SERVICE_ROOT / "pyproject.toml") + service_version = service_project.get("version") + assert isinstance(service_version, str), "service project version must be text" + keyverse_project = _CONTRACT._project_metadata(_CONTRACT._KEYVERSE_PROJECT) + keyverse_version = keyverse_project.get("version") + assert isinstance(keyverse_version, str), "Keyverse project version must be text" + + wheelhouse = tmp_path / "wheelhouse" + wheelhouse.mkdir() + environment = _CONTRACT._subprocess_environment() + for source_root in (_CONTRACT._KEYVERSE_ROOT, _CONTRACT._SERVICE_ROOT): + subprocess.run( + [ + sys.executable, + "-m", + "pip", + "wheel", + "--no-index", + "--no-cache-dir", + "--no-deps", + "--no-build-isolation", + "--wheel-dir", + str(wheelhouse), + str(source_root), + ], + cwd=_CONTRACT._REPOSITORY_ROOT, + env=environment, + check=True, + ) + + _locked_requirements, wheels_by_name = _validate_distribution_acceptance( + wheelhouse, + service_version=service_version, + keyverse_version=keyverse_version, + ) + assert set(wheels_by_name) == { + canonicalize_name(_CONTRACT._KEYVERSE_NAME), + canonicalize_name(_CONTRACT._SERVICE_NAME), + } From ee090a351d133c91ada00ad72d7f48554aa9b116 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 02:05:30 +0900 Subject: [PATCH 365/603] test(packaging): verify dist-info identity before artifact hashing --- .../tests/test_built_wheel_dist_info_identity.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py b/services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py index 85ff3c430..16f4e4cec 100644 --- a/services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py +++ b/services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py @@ -85,15 +85,15 @@ def _validate_distribution_acceptance( service_version: str, keyverse_version: str, ) -> tuple[str, dict[str, Path]]: - """Run the existing wheel lock contract plus exact dist-info directory identity binding.""" - locked_requirements, wheels_by_name = _CONTRACT._locked_wheel_requirements( + """Bind dist-info identity before the existing validator computes the install lock.""" + wheel_paths = tuple(sorted(wheelhouse.glob("*.whl"))) + for wheel_path in wheel_paths: + _assert_dist_info_identity(wheel_path) + return _CONTRACT._locked_wheel_requirements( wheelhouse, service_version=service_version, keyverse_version=keyverse_version, ) - for wheel_path in wheels_by_name.values(): - _assert_dist_info_identity(wheel_path) - return locked_requirements, wheels_by_name def test_hash_locked_acceptance_rejects_mismatched_dist_info_identity(tmp_path: Path) -> None: From b687e6177e5b98f3fdeb8589cc29595c569ae64f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 02:11:48 +0900 Subject: [PATCH 366/603] fix(packaging): enforce dist-info identity in hash-lock helper --- .../test_package_metadata_compatibility.py | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py index 902836495..17b639fb4 100644 --- a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py +++ b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py @@ -196,9 +196,11 @@ def _validate_wheel_contents( wheel_path: Path, *, package_root: str, + expected_name: str, + expected_version: str, require_py_typed: bool, ) -> None: - """Reject repository leakage, sibling source, or missing declared package data.""" + """Reject repository leakage, foreign dist-info identity, or missing package data.""" with zipfile.ZipFile(wheel_path) as archive: names = tuple(archive.namelist()) @@ -222,6 +224,14 @@ def _validate_wheel_contents( assert len(dist_info_roots) == 1, ( f"{wheel_path.name} must contain exactly one .dist-info root" ) + expected_dist_info_root = ( + f"{canonicalize_name(expected_name).replace('-', '_')}-" + f"{Version(expected_version)}.dist-info" + ) + assert dist_info_roots == {expected_dist_info_root}, ( + f"{wheel_path.name} dist-info identity must be {expected_dist_info_root}, " + f"observed {sorted(dist_info_roots)}" + ) allowed_top_levels = {package_root, *dist_info_roots} assert top_levels <= allowed_top_levels, ( f"{wheel_path.name} contains unexpected top-level content: " @@ -409,21 +419,24 @@ def _locked_wheel_requirements( project, owner=canonical_name, ) + expected_name = ( + _SERVICE_NAME + if canonical_name == canonicalize_name(_SERVICE_NAME) + else _KEYVERSE_NAME + ) _validate_wheel_record(wheel_path) - wheels_by_name[canonical_name] = wheel_path - hashes_by_name[canonical_name] = _sha256(wheel_path) _validate_wheel_contents( wheel_path, package_root=package_roots[canonical_name], + expected_name=expected_name, + expected_version=str(expected_versions[canonical_name]), require_py_typed=canonical_name == canonicalize_name(_SERVICE_NAME), ) + wheels_by_name[canonical_name] = wheel_path + hashes_by_name[canonical_name] = _sha256(wheel_path) _validate_wheel_metadata( wheel_path, - expected_name=( - _SERVICE_NAME - if canonical_name == canonicalize_name(_SERVICE_NAME) - else _KEYVERSE_NAME - ), + expected_name=expected_name, expected_version=str(expected_versions[canonical_name]), expected_requires_python=requires_python, expected_dependencies=reviewed_dependencies, @@ -613,4 +626,4 @@ def test_built_distribution_closure_installs_without_checkout_imports(tmp_path: cwd=tmp_path, env=environment, check=True, - ) \ No newline at end of file + ) From b6bc9c27aea50ce407edce991eb51f28ad5c2e5e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 02:12:02 +0900 Subject: [PATCH 367/603] test(packaging): exercise canonical dist-info lock path --- .../test_built_wheel_dist_info_identity.py | 87 +------------------ 1 file changed, 3 insertions(+), 84 deletions(-) diff --git a/services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py b/services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py index 16f4e4cec..837bfb3e2 100644 --- a/services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py +++ b/services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py @@ -5,12 +5,9 @@ import csv import importlib.util import io -from pathlib import Path, PurePosixPath -import subprocess -import sys +from pathlib import Path import zipfile -from packaging.utils import canonicalize_name, parse_wheel_filename import pytest @@ -61,43 +58,8 @@ def _write_wheel( archive.writestr(member_path, content) -def _assert_dist_info_identity(wheel_path: Path) -> None: - """Bind the sole dist-info root to the normalized wheel filename name and version.""" - parsed_name, parsed_version, _build, _tags = parse_wheel_filename(wheel_path.name) - expected_root = ( - f"{canonicalize_name(parsed_name).replace('-', '_')}-{parsed_version}.dist-info" - ) - with zipfile.ZipFile(wheel_path) as archive: - roots = { - PurePosixPath(name).parts[0] - for name in archive.namelist() - if PurePosixPath(name).parts - and PurePosixPath(name).parts[0].endswith(".dist-info") - } - assert roots == {expected_root}, ( - f"{wheel_path.name} dist-info identity must be {expected_root}, observed {sorted(roots)}" - ) - - -def _validate_distribution_acceptance( - wheelhouse: Path, - *, - service_version: str, - keyverse_version: str, -) -> tuple[str, dict[str, Path]]: - """Bind dist-info identity before the existing validator computes the install lock.""" - wheel_paths = tuple(sorted(wheelhouse.glob("*.whl"))) - for wheel_path in wheel_paths: - _assert_dist_info_identity(wheel_path) - return _CONTRACT._locked_wheel_requirements( - wheelhouse, - service_version=service_version, - keyverse_version=keyverse_version, - ) - - def test_hash_locked_acceptance_rejects_mismatched_dist_info_identity(tmp_path: Path) -> None: - """A correct filename and METADATA must not hide a foreign dist-info directory identity.""" + """The shared hash-lock helper must reject a foreign dist-info directory before hashing.""" wheelhouse = tmp_path / "wheelhouse" wheelhouse.mkdir() _write_wheel( @@ -132,51 +94,8 @@ def test_hash_locked_acceptance_rejects_mismatched_dist_info_identity(tmp_path: ) with pytest.raises(AssertionError, match="dist-info identity"): - _validate_distribution_acceptance( + _CONTRACT._locked_wheel_requirements( wheelhouse, service_version="0.1.0", keyverse_version="0.1.0", ) - - -def test_built_owned_wheels_bind_dist_info_to_filename_identity(tmp_path: Path) -> None: - """Prove the exact wheels built from reviewed owned sources satisfy the identity binding.""" - service_project = _CONTRACT._project_metadata(_CONTRACT._SERVICE_ROOT / "pyproject.toml") - service_version = service_project.get("version") - assert isinstance(service_version, str), "service project version must be text" - keyverse_project = _CONTRACT._project_metadata(_CONTRACT._KEYVERSE_PROJECT) - keyverse_version = keyverse_project.get("version") - assert isinstance(keyverse_version, str), "Keyverse project version must be text" - - wheelhouse = tmp_path / "wheelhouse" - wheelhouse.mkdir() - environment = _CONTRACT._subprocess_environment() - for source_root in (_CONTRACT._KEYVERSE_ROOT, _CONTRACT._SERVICE_ROOT): - subprocess.run( - [ - sys.executable, - "-m", - "pip", - "wheel", - "--no-index", - "--no-cache-dir", - "--no-deps", - "--no-build-isolation", - "--wheel-dir", - str(wheelhouse), - str(source_root), - ], - cwd=_CONTRACT._REPOSITORY_ROOT, - env=environment, - check=True, - ) - - _locked_requirements, wheels_by_name = _validate_distribution_acceptance( - wheelhouse, - service_version=service_version, - keyverse_version=keyverse_version, - ) - assert set(wheels_by_name) == { - canonicalize_name(_CONTRACT._KEYVERSE_NAME), - canonicalize_name(_CONTRACT._SERVICE_NAME), - } From d662825fe6b9a6cd4aec563330a37bba9bc04e12 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 02:17:17 +0900 Subject: [PATCH 368/603] test(packaging): prove dist-info rejection precedes outer hash --- .../tests/test_built_wheel_dist_info_identity.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py b/services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py index 837bfb3e2..51cba8200 100644 --- a/services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py +++ b/services/workforce-validation-api/tests/test_built_wheel_dist_info_identity.py @@ -58,8 +58,11 @@ def _write_wheel( archive.writestr(member_path, content) -def test_hash_locked_acceptance_rejects_mismatched_dist_info_identity(tmp_path: Path) -> None: - """The shared hash-lock helper must reject a foreign dist-info directory before hashing.""" +def test_hash_locked_acceptance_rejects_mismatched_dist_info_identity_before_hashing( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +) -> None: + """A foreign dist-info directory must fail before outer artifact hashing can run.""" wheelhouse = tmp_path / "wheelhouse" wheelhouse.mkdir() _write_wheel( @@ -93,6 +96,10 @@ def test_hash_locked_acceptance_rejects_mismatched_dist_info_identity(tmp_path: include_py_typed=True, ) + def _forbid_outer_hash(_path: Path) -> str: + raise AssertionError("outer hash must not run for a foreign dist-info root") + + monkeypatch.setattr(_CONTRACT, "_sha256", _forbid_outer_hash) with pytest.raises(AssertionError, match="dist-info identity"): _CONTRACT._locked_wheel_requirements( wheelhouse, From 607c043b6e9e9155276757a26a98887defbfcc63 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 02:32:12 +0900 Subject: [PATCH 369/603] test(workforce-validation): require exact failed-artifact v2 lookup --- ...supersession_v2_lookup_key_completeness.py | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_lookup_key_completeness.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_lookup_key_completeness.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_lookup_key_completeness.py new file mode 100644 index 000000000..ece349f5b --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_lookup_key_completeness.py @@ -0,0 +1,44 @@ +"""Fail closed when v2 exact-artifact correction lookup omits predecessor artifact identity.""" + +from inspect import signature + +from orgmetra_workforce_validation_api.result_nonverifiability_supersession_v2_authority import ( + ValidationResultNonVerifiabilitySupersessionV2AuthorityReadPort, + resolve_validation_result_nonverifiability_supersession_v2_authority, +) + + +_REQUIRED_FAILED_ARTIFACT_COORDINATES = ( + "failed_evidence_reference", + "failed_evidence_digest", +) + + +def test_v2_resolver_requires_exact_failed_artifact_coordinates() -> None: + """Bind callers to the immutable failed artifact that the v2 correction supersedes.""" + parameters = signature( + resolve_validation_result_nonverifiability_supersession_v2_authority + ).parameters + for coordinate in _REQUIRED_FAILED_ARTIFACT_COORDINATES: + assert coordinate in parameters + + +def test_v2_owner_read_port_keys_exact_failed_artifact_coordinates() -> None: + """Prevent same-family artifacts from sharing an ambiguous v2 owner lookup prefix.""" + parameters = signature( + ValidationResultNonVerifiabilitySupersessionV2AuthorityReadPort.read_validation_result_nonverifiability_supersession_v2_authority + ).parameters + for coordinate in _REQUIRED_FAILED_ARTIFACT_COORDINATES: + assert coordinate in parameters + + +def test_failed_artifact_release_time_remains_owner_evidence() -> None: + """Keep failed-artifact chronology owner-resolved once reference and digest are exact.""" + resolver_parameters = signature( + resolve_validation_result_nonverifiability_supersession_v2_authority + ).parameters + port_parameters = signature( + ValidationResultNonVerifiabilitySupersessionV2AuthorityReadPort.read_validation_result_nonverifiability_supersession_v2_authority + ).parameters + assert "failed_evidence_released_at" not in resolver_parameters + assert "failed_evidence_released_at" not in port_parameters From 27be4e1d6ce98c0ace0bc5d8aed8c958b7171223 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 02:33:39 +0900 Subject: [PATCH 370/603] fix(workforce-validation): bind v2 lookup to failed artifact --- ...t_nonverifiability_supersession_v2_authority.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py index 8806170ea..44e091c36 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py @@ -370,6 +370,8 @@ def read_validation_result_nonverifiability_supersession_v2_authority( result_reference: str, result_digest: str, failed_evidence_kind: str, + failed_evidence_reference: str, + failed_evidence_digest: str, verification_attempt_reference: str, verification_attempt_digest: str, evidence_version: int, @@ -395,6 +397,8 @@ def resolve_validation_result_nonverifiability_supersession_v2_authority( result_reference: str, result_digest: str, failed_evidence_kind: str, + failed_evidence_reference: str, + failed_evidence_digest: str, verification_attempt_reference: str, verification_attempt_digest: str, evidence_version: int, @@ -434,6 +438,12 @@ def resolve_validation_result_nonverifiability_supersession_v2_authority( ) result_evidence_digest = _require_digest("result_digest", result_digest) evidence_kind = _require_failed_evidence_kind(failed_evidence_kind) + failed_reference = _require_reference( + "failed_evidence_reference", + failed_evidence_reference, + _FAILED_REFERENCE_KIND_BY_EVIDENCE_KIND[evidence_kind], + ) + failed_digest = _require_digest("failed_evidence_digest", failed_evidence_digest) attempt_ref = _require_reference( "verification_attempt_reference", verification_attempt_reference, @@ -481,6 +491,8 @@ def resolve_validation_result_nonverifiability_supersession_v2_authority( result_reference=result_ref, result_digest=result_evidence_digest, failed_evidence_kind=evidence_kind, + failed_evidence_reference=failed_reference, + failed_evidence_digest=failed_digest, verification_attempt_reference=attempt_ref, verification_attempt_digest=attempt_digest, evidence_version=version, @@ -517,7 +529,9 @@ def resolve_validation_result_nonverifiability_supersession_v2_authority( values = dict(persisted.fields) requested_values = { "evidence_version": version, + "failed_evidence_digest": failed_digest, "failed_evidence_kind": evidence_kind, + "failed_evidence_reference": failed_reference, "owner_contract_digest": owner_digest, "owner_contract_reference": owner_ref, "owner_contract_version": owner_version, From 7986ee3fe1b826311dae05c147faf262f19cfc0b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 02:35:38 +0900 Subject: [PATCH 371/603] test(workforce-validation): exercise exact failed-artifact v2 lookup --- ...lt_nonverifiability_supersession_v2_authority_edges.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py index b944f34e2..47a415416 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py @@ -223,6 +223,8 @@ def _resolve( "result_reference": RESULT_REFERENCE, "result_digest": RESULT_DIGEST, "failed_evidence_kind": "analysis_weight_receipt", + "failed_evidence_reference": FAILED_REFERENCE, + "failed_evidence_digest": FAILED_DIGEST, "verification_attempt_reference": ATTEMPT_REFERENCE, "verification_attempt_digest": ATTEMPT_DIGEST, "evidence_version": 2, @@ -257,6 +259,8 @@ def test_current_non_reproducible_outcome_resolves_with_exact_failed_artifact() "result_reference": RESULT_REFERENCE, "result_digest": RESULT_DIGEST, "failed_evidence_kind": "analysis_weight_receipt", + "failed_evidence_reference": FAILED_REFERENCE, + "failed_evidence_digest": FAILED_DIGEST, "verification_attempt_reference": ATTEMPT_REFERENCE, "verification_attempt_digest": ATTEMPT_DIGEST, "evidence_version": 2, @@ -344,6 +348,8 @@ def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: "variance_design_receipt:22222222-2222-4222-8222-222222222222" ), }, + {"failed_evidence_reference": OTHER_FAILED_REFERENCE}, + {"failed_evidence_digest": "b" * 64}, {"verification_attempt_reference": OTHER_ATTEMPT_REFERENCE}, {"verification_attempt_digest": "c" * 64}, {"owner_contract_reference": OTHER_OWNER_REFERENCE}, @@ -373,6 +379,8 @@ def test_owner_evidence_must_match_every_caller_known_coordinate( ("result_reference", "wrong:result", ValueError), ("result_digest", "ABC", ValueError), ("failed_evidence_kind", "unknown", ValueError), + ("failed_evidence_reference", "wrong:artifact", ValueError), + ("failed_evidence_digest", "2" * 63, ValueError), ("verification_attempt_reference", "wrong:attempt", ValueError), ("verification_attempt_digest", "3" * 63, ValueError), ("evidence_version", False, ValueError), From 96b0b8251645477f161a3448670867c16ba4e2db Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 02:35:58 +0900 Subject: [PATCH 372/603] test(workforce-validation): align v2 predecessor integrity lookup --- ...lt_nonverifiability_supersession_v2_predecessor_integrity.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_predecessor_integrity.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_predecessor_integrity.py index b9296267f..3d59ac686 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_predecessor_integrity.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_predecessor_integrity.py @@ -151,6 +151,8 @@ def test_resolver_revalidates_exact_typed_owner_evidence() -> None: result_reference=RESULT_REFERENCE, result_digest=RESULT_DIGEST, failed_evidence_kind="analysis_weight_receipt", + failed_evidence_reference=FAILED_REFERENCE, + failed_evidence_digest=FAILED_DIGEST, verification_attempt_reference=ATTEMPT_REFERENCE, verification_attempt_digest=ATTEMPT_DIGEST, evidence_version=2, From 059b4de256fe45dcfe10db81cfa1e93a7370de13 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 02:36:57 +0900 Subject: [PATCH 373/603] docs(workforce-validation): document exact failed-artifact v2 lookup --- services/workforce-validation-api/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index aaa89d8fa..ff4c6a691 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -124,7 +124,7 @@ The immutable `verification_attempt_reference` and `verification_attempt_digest` `resolve_validation_result_nonverifiability_supersession_authority(...)` is the v1 correction contract for a predecessor `failure_mode="missing"`. It requires a complete immutable successor verification-attempt reference/digest/release tuple plus an owner-supplied target-result reference/digest and `successor_failed_evidence_kind`. The successor target must equal the predecessor result exactly, the failed-evidence kind must match, the successor attempt must identify new evidence, and its release must equal the predecessor `superseded_at`. This v1 path deliberately rejects `non_reproducible` because its tuple cannot retain the exact artifact whose reproducibility failed. -`resolve_validation_result_nonverifiability_supersession_v2_authority(...)` supplies that exact-artifact path without weakening v1. It consumes the canonical released `ValidationResultNonVerifiabilityRecord` for a `non_reproducible` predecessor, keeps the failed-evidence reference/digest/release instant as owner-resolved predecessor provenance, and requires any successor attempt to target the exact same result, failed-evidence family, failed-evidence reference, failed-evidence digest, and failed-evidence release chronology. The v2 successor must use new immutable verification-attempt evidence and be released exactly at the ordinary predecessor's owner-resolved `superseded_at`. An explicit v2 successor is invalid when the ordinary predecessor has no cutover or a different cutover, and omitting successor coordinates is invalid when the ordinary predecessor is already marked superseded. Caller/read-port lookup coordinates do not include the failed-artifact tuple or cutover; persistence must recover both from canonical released owner evidence rather than let a caller choose favorable provenance. +`resolve_validation_result_nonverifiability_supersession_v2_authority(...)` supplies that exact-artifact path without weakening v1. It consumes the canonical released `ValidationResultNonVerifiabilityRecord` for a `non_reproducible` predecessor, keeps the failed-evidence reference/digest/release instant as predecessor provenance, and requires any successor attempt to target the exact same result, failed-evidence family, failed-evidence reference, failed-evidence digest, and failed-evidence release chronology. The v2 resolver and owner-read port key the predecessor by exact failed-evidence reference and digest so two artifacts in the same evidence family cannot share an ambiguous correction lookup. The failed-evidence release instant and cutover remain owner-resolved chronology rather than caller lookup coordinates. The v2 successor must use new immutable verification-attempt evidence and be released exactly at the ordinary predecessor's owner-resolved `superseded_at`. An explicit v2 successor is invalid when the ordinary predecessor has no cutover or a different cutover, and omitting successor coordinates is invalid when the ordinary predecessor is already marked superseded. Both minimized views omit cutover and successor coordinates. A successor verification attempt only ends the predecessor negative-outcome interval; it does not imply scientific GREEN. Any subsequent released result or negative outcome must satisfy its own governed owner and verification contract. @@ -136,7 +136,7 @@ The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL r Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **twenty-one** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration support chronology, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, base/design-weight supersession, complete final analysis-weight lineage, final-weight supersession, point-weight/variance compatibility, point-weight/variance supersession, validation-result binding, validation-result supersession, validation-result non-verifiability, and validation-result non-verifiability supersession. -The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable predecessor verification-attempt reference/digest and preserve failed-evidence and attempt-release chronology. Missing-evidence correction uses the v1 same-result/same-obligation successor graph. Non-reproducible correction uses v2 and must additionally persist/recover the predecessor failed-evidence reference/digest/release instant and require the successor target tuple to equal it exactly; that failed-artifact tuple is owner-resolved evidence, not a caller lookup key. V2 must also cross-check the explicit correction cutover against the ordinary predecessor's owner-resolved `superseded_at`; neither side may manufacture or hide the other. Both versions require successor verification-attempt release exactly at the predecessor cutover. No durable adapter may infer currentness from mutable current rows, unrelated result attempts, different-evidence-family attempts, different artifacts in the same family, or caller-supplied timestamps. +The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable predecessor verification-attempt reference/digest and preserve failed-evidence and attempt-release chronology. Missing-evidence correction uses the v1 same-result/same-obligation successor graph. Non-reproducible correction uses v2 and must exact-key the predecessor failed-evidence reference/digest in addition to result, evidence family, verification attempt and owner contract; it must persist/recover the failed-evidence release instant as owner chronology and require the successor target tuple to equal the same exact artifact. V2 must also cross-check the explicit correction cutover against the ordinary predecessor's owner-resolved `superseded_at`; neither side may manufacture or hide the other. Both versions require successor verification-attempt release exactly at the predecessor cutover. No durable adapter may infer currentness from mutable current rows, unrelated result attempts, different-evidence-family attempts, different artifacts in the same family, or caller-supplied timestamps. ## Test contract @@ -155,6 +155,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, explicit missing/non-reproducible evidence with exact verification-attempt identity and chronology, v1 same-result/same-failed-evidence-obligation correction for missing predecessors, and v2 exact failed-artifact correction for non-reproducible predecessors including ordinary-cutover alignment, hostile mismatched-artifact, chronology, authorization, owner-port and structural-integrity cases. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, explicit missing/non-reproducible evidence with exact verification-attempt identity and chronology, v1 same-result/same-failed-evidence-obligation correction for missing predecessors, and v2 exact failed-artifact correction for non-reproducible predecessors including exact failed-artifact lookup identity, ordinary-cutover alignment, hostile mismatched-artifact, chronology, authorization, owner-port and structural-integrity cases. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From 3e6143a22723dd5d5550a739504c7f081a14f717 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 03:30:32 +0900 Subject: [PATCH 374/603] test(workforce-validation): require exact failed-artifact lookup --- ...onverifiability_lookup_key_completeness.py | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_lookup_key_completeness.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_lookup_key_completeness.py index 0157ca2ee..25b182f7e 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_lookup_key_completeness.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_lookup_key_completeness.py @@ -1,4 +1,4 @@ -"""Fail closed on ambiguous lookup of immutable verification attempts.""" +"""Fail closed on ambiguous lookup of immutable verification attempts and failed artifacts.""" from __future__ import annotations @@ -14,6 +14,10 @@ "verification_attempt_reference", "verification_attempt_digest", ) +_REQUIRED_FAILED_ARTIFACT_COORDINATES = ( + "failed_evidence_reference", + "failed_evidence_digest", +) def test_resolver_requires_exact_verification_attempt_coordinates() -> None: @@ -32,6 +36,17 @@ def test_owner_read_port_keys_exact_verification_attempt_coordinates() -> None: assert coordinate in parameters +def test_non_reproducible_lookup_requires_exact_failed_artifact_coordinates() -> None: + """Keep same-family failed artifacts distinct before owner resolution.""" + resolver_parameters = signature(resolve_validation_result_nonverifiability).parameters + port_parameters = signature( + ValidationResultNonVerifiabilityReadPort.read_validation_result_nonverifiability + ).parameters + for coordinate in _REQUIRED_FAILED_ARTIFACT_COORDINATES: + assert coordinate in resolver_parameters + assert coordinate in port_parameters + + def test_attempt_release_time_remains_owner_evidence_not_lookup_authority() -> None: """Keep release chronology owner-resolved while the immutable attempt identity is exact.""" resolver_parameters = signature(resolve_validation_result_nonverifiability).parameters @@ -40,3 +55,13 @@ def test_attempt_release_time_remains_owner_evidence_not_lookup_authority() -> N ).parameters assert "verification_attempt_released_at" not in resolver_parameters assert "verification_attempt_released_at" not in port_parameters + + +def test_failed_artifact_release_time_remains_owner_evidence_not_lookup_authority() -> None: + """Require artifact identity without accepting caller-supplied release chronology.""" + resolver_parameters = signature(resolve_validation_result_nonverifiability).parameters + port_parameters = signature( + ValidationResultNonVerifiabilityReadPort.read_validation_result_nonverifiability + ).parameters + assert "failed_evidence_released_at" not in resolver_parameters + assert "failed_evidence_released_at" not in port_parameters From d97a720677d644ede3612c57f5c7bd79456f0a45 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 03:32:07 +0900 Subject: [PATCH 375/603] fix(workforce-validation): exact-key failed non-reproducible evidence --- .../result_nonverifiability.py | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py index 444ec3bae..1267a25c0 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py @@ -404,6 +404,8 @@ def read_validation_result_nonverifiability( result_digest: str, failed_evidence_kind: str, failure_mode: str, + failed_evidence_reference: str | None, + failed_evidence_digest: str | None, verification_attempt_reference: str, verification_attempt_digest: str, owner_contract_reference: str, @@ -429,6 +431,8 @@ def resolve_validation_result_nonverifiability( result_digest: str, failed_evidence_kind: str, failure_mode: str, + failed_evidence_reference: str | None = None, + failed_evidence_digest: str | None = None, verification_attempt_reference: str, verification_attempt_digest: str, owner_contract_reference: str, @@ -471,6 +475,24 @@ def resolve_validation_result_nonverifiability( result_evidence_digest = _require_digest("result_digest", result_digest) evidence_kind = _require_failed_evidence_kind(failed_evidence_kind) mode = _require_failure_mode(failure_mode) + if mode == "missing": + if failed_evidence_reference is not None or failed_evidence_digest is not None: + raise ValueError( + "failed evidence reference and digest must be absent when evidence is missing." + ) + failed_reference = None + failed_digest = None + else: + if failed_evidence_reference is None or failed_evidence_digest is None: + raise ValueError( + "failed evidence reference and digest are required for non_reproducible lookup." + ) + failed_reference = _require_reference( + "failed_evidence_reference", + failed_evidence_reference, + _FAILED_REFERENCE_KIND_BY_EVIDENCE_KIND[evidence_kind], + ) + failed_digest = _require_digest("failed_evidence_digest", failed_evidence_digest) attempt_ref = _require_reference( "verification_attempt_reference", verification_attempt_reference, @@ -514,6 +536,8 @@ def resolve_validation_result_nonverifiability( result_digest=result_evidence_digest, failed_evidence_kind=evidence_kind, failure_mode=mode, + failed_evidence_reference=failed_reference, + failed_evidence_digest=failed_digest, verification_attempt_reference=attempt_ref, verification_attempt_digest=attempt_digest, owner_contract_reference=owner_ref, @@ -555,6 +579,8 @@ def resolve_validation_result_nonverifiability( result_evidence_digest, evidence_kind, mode, + failed_reference, + failed_digest, attempt_ref, attempt_digest, owner_ref, @@ -568,6 +594,8 @@ def resolve_validation_result_nonverifiability( record.result_digest, record.failed_evidence_kind, record.failure_mode, + record.failed_evidence_reference, + record.failed_evidence_digest, record.verification_attempt_reference, record.verification_attempt_digest, record.owner_contract_reference, From 7850102f73526b4572e86d4a21d5397401459bdc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 03:32:57 +0900 Subject: [PATCH 376/603] test(workforce-validation): exercise exact failed-artifact lookup --- ...test_validation_result_nonverifiability.py | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py index ff5bfe7b8..1c57e8993 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability.py @@ -77,6 +77,8 @@ def read_validation_result_nonverifiability( result_digest: str, failed_evidence_kind: str, failure_mode: str, + failed_evidence_reference: str | None, + failed_evidence_digest: str | None, verification_attempt_reference: str, verification_attempt_digest: str, owner_contract_reference: str, @@ -91,6 +93,8 @@ def read_validation_result_nonverifiability( result_digest, failed_evidence_kind, failure_mode, + failed_evidence_reference, + failed_evidence_digest, verification_attempt_reference, verification_attempt_digest, owner_contract_reference, @@ -161,6 +165,8 @@ def _resolve( "result_digest": RESULT_DIGEST, "failed_evidence_kind": "analysis_weight_receipt", "failure_mode": "missing", + "failed_evidence_reference": None, + "failed_evidence_digest": None, "verification_attempt_reference": ATTEMPT_REFERENCE, "verification_attempt_digest": ATTEMPT_DIGEST, "owner_contract_reference": OWNER_REFERENCE, @@ -189,6 +195,8 @@ def test_missing_final_weight_evidence_is_released_as_not_verifiable() -> None: RESULT_DIGEST, "analysis_weight_receipt", "missing", + None, + None, ATTEMPT_REFERENCE, ATTEMPT_DIGEST, OWNER_REFERENCE, @@ -221,12 +229,16 @@ def test_non_reproducible_weight_evidence_keeps_exact_failed_receipt() -> None: failed_evidence_digest=FAILED_WEIGHT_DIGEST, failed_evidence_released_at=FAILED_EVIDENCE_RELEASED_AT, ) + port = _ReadPort(record) view = _resolve( - read_port=_ReadPort(record), + read_port=port, failure_mode="non_reproducible", + failed_evidence_reference=FAILED_WEIGHT_REFERENCE, + failed_evidence_digest=FAILED_WEIGHT_DIGEST, ) + assert port.calls[0][6:8] == (FAILED_WEIGHT_REFERENCE, FAILED_WEIGHT_DIGEST) fields = dict(view.fields) assert fields["verification_status"] == "not_verifiable" assert fields["failed_evidence_reference"] == FAILED_WEIGHT_REFERENCE @@ -263,6 +275,8 @@ def test_non_reproducible_evidence_kind_uses_its_typed_reference( read_port=_ReadPort(record), failed_evidence_kind=failed_evidence_kind, failure_mode="non_reproducible", + failed_evidence_reference=failed_reference, + failed_evidence_digest=FAILED_WEIGHT_DIGEST, ) assert dict(view.fields)["failed_evidence_reference"] == failed_reference @@ -284,6 +298,24 @@ def test_missing_and_non_reproducible_modes_fail_closed_on_incoherent_evidence() failed_evidence_digest=FAILED_WEIGHT_DIGEST, failed_evidence_released_at=FAILED_EVIDENCE_RELEASED_AT, ) + with pytest.raises(ValueError, match="required"): + _resolve( + read_port=_ReadPort( + _record( + failure_mode="non_reproducible", + failed_evidence_reference=FAILED_WEIGHT_REFERENCE, + failed_evidence_digest=FAILED_WEIGHT_DIGEST, + failed_evidence_released_at=FAILED_EVIDENCE_RELEASED_AT, + ) + ), + failure_mode="non_reproducible", + ) + with pytest.raises(ValueError, match="must be absent"): + _resolve( + read_port=_ReadPort(_record()), + failed_evidence_reference=FAILED_WEIGHT_REFERENCE, + failed_evidence_digest=FAILED_WEIGHT_DIGEST, + ) def test_reason_and_attempt_evidence_are_strict_and_non_aliasing() -> None: @@ -327,6 +359,22 @@ def test_missing_noncanonical_or_mismatched_owner_outcome_fails_closed() -> None with pytest.raises(ValidationResultNonVerifiabilityIntegrityError): _resolve(read_port=_ReadPort(_record(verification_attempt_digest="a" * 64))) + non_reproducible = _record( + failure_mode="non_reproducible", + failed_evidence_reference=FAILED_WEIGHT_REFERENCE, + failed_evidence_digest=FAILED_WEIGHT_DIGEST, + failed_evidence_released_at=FAILED_EVIDENCE_RELEASED_AT, + ) + with pytest.raises(ValidationResultNonVerifiabilityIntegrityError): + _resolve( + read_port=_ReadPort(non_reproducible), + failure_mode="non_reproducible", + failed_evidence_reference=( + "analysis_weight_receipt:77777777-7777-4777-8777-777777777777" + ), + failed_evidence_digest="7" * 64, + ) + def test_invalid_dependencies_and_pre_release_use_fail_closed() -> None: with pytest.raises(TypeError): From 7cf9d0d64ed38b82e85aae2f60fef931524fdb4d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 03:33:16 +0900 Subject: [PATCH 377/603] test(workforce-validation): align nonverifiability owner read key --- .../test_validation_result_nonverifiability_currentness.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py index 18c062682..46a13db1b 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py @@ -71,6 +71,8 @@ def read_validation_result_nonverifiability( result_digest: str, failed_evidence_kind: str, failure_mode: str, + failed_evidence_reference: str | None, + failed_evidence_digest: str | None, verification_attempt_reference: str, verification_attempt_digest: str, owner_contract_reference: str, From 8aea333ef7bf3a0e6c8d1c662662ed8663d0693d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 03:38:07 +0900 Subject: [PATCH 378/603] docs(workforce-validation): document exact nonreproducible lookup --- services/workforce-validation-api/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index ff4c6a691..71d34e915 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -118,7 +118,7 @@ The binding resolves owner-contract release and optional exclusive supersession `resolve_validation_result_nonverifiability(...)` represents required analysis-weight, weight/variance-compatibility, or variance-design evidence that is `missing | non_reproducible` without turning lookup failure into scientific GREEN. Missing evidence carries no fabricated reference, digest, or release timestamp. Non-reproducible evidence retains the exact failed reference/digest and owner-resolved release instant; the failed evidence must already have been released when the verification attempt is evaluated. -The immutable `verification_attempt_reference` and `verification_attempt_digest` are part of the resolver and owner-read lookup identity. Verification-attempt release, governing owner-contract release and optional exclusive `superseded_at` remain owner-resolved chronology. The immutable attempt receipt must satisfy `evaluated_at <= verification_attempt_released_at <= released_at`, and the ordinary resolver accepts the released negative outcome only on `[released_at, superseded_at)`. +The immutable `verification_attempt_reference` and `verification_attempt_digest` are always part of the resolver and owner-read lookup identity. For `non_reproducible`, the exact typed `failed_evidence_reference` and canonical `failed_evidence_digest` are lookup coordinates as well, preventing same-family different failed artifacts from sharing an owner selection prefix; `missing` requires those coordinates absent. Failed-evidence release, verification-attempt release, governing owner-contract release and optional exclusive `superseded_at` remain owner-resolved chronology. The immutable attempt receipt must satisfy `evaluated_at <= verification_attempt_released_at <= released_at`, and the ordinary resolver accepts the released negative outcome only on `[released_at, superseded_at)`. ## Validation-result non-verifiability supersession authority @@ -136,7 +136,7 @@ The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL r Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **twenty-one** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration support chronology, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, base/design-weight supersession, complete final analysis-weight lineage, final-weight supersession, point-weight/variance compatibility, point-weight/variance supersession, validation-result binding, validation-result supersession, validation-result non-verifiability, and validation-result non-verifiability supersession. -The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable predecessor verification-attempt reference/digest and preserve failed-evidence and attempt-release chronology. Missing-evidence correction uses the v1 same-result/same-obligation successor graph. Non-reproducible correction uses v2 and must exact-key the predecessor failed-evidence reference/digest in addition to result, evidence family, verification attempt and owner contract; it must persist/recover the failed-evidence release instant as owner chronology and require the successor target tuple to equal the same exact artifact. V2 must also cross-check the explicit correction cutover against the ordinary predecessor's owner-resolved `superseded_at`; neither side may manufacture or hide the other. Both versions require successor verification-attempt release exactly at the predecessor cutover. No durable adapter may infer currentness from mutable current rows, unrelated result attempts, different-evidence-family attempts, different artifacts in the same family, or caller-supplied timestamps. +The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable predecessor verification-attempt reference/digest; for `non_reproducible` it must additionally key the exact failed-evidence reference/digest, while failed-evidence and attempt-release instants remain owner chronology. Missing-evidence correction uses the v1 same-result/same-obligation successor graph. Non-reproducible correction uses v2 and must preserve the same predecessor failed-evidence reference/digest in addition to result, evidence family, verification attempt and owner contract; it must persist/recover the failed-evidence release instant as owner chronology and require the successor target tuple to equal the same exact artifact. V2 must also cross-check the explicit correction cutover against the ordinary predecessor's owner-resolved `superseded_at`; neither side may manufacture or hide the other. Both versions require successor verification-attempt release exactly at the predecessor cutover. No durable adapter may infer currentness from mutable current rows, unrelated result attempts, different-evidence-family attempts, different artifacts in the same family, or caller-supplied timestamps. ## Test contract @@ -155,6 +155,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, explicit missing/non-reproducible evidence with exact verification-attempt identity and chronology, v1 same-result/same-failed-evidence-obligation correction for missing predecessors, and v2 exact failed-artifact correction for non-reproducible predecessors including exact failed-artifact lookup identity, ordinary-cutover alignment, hostile mismatched-artifact, chronology, authorization, owner-port and structural-integrity cases. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, explicit missing/non-reproducible evidence with exact verification-attempt identity and chronology, ordinary exact failed-artifact lookup for non-reproducible outcomes, v1 same-result/same-failed-evidence-obligation correction for missing predecessors, and v2 exact failed-artifact correction for non-reproducible predecessors including exact failed-artifact lookup identity, ordinary-cutover alignment, hostile mismatched-artifact, chronology, authorization, owner-port and structural-integrity cases. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From 8dc9f796dc473dc97b710034135c8fbf87ae7631 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 04:28:35 +0900 Subject: [PATCH 379/603] test(workforce-validation): reject forged nonverifiability tuples --- ...t_nonverifiability_structural_integrity.py | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_structural_integrity.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_structural_integrity.py new file mode 100644 index 000000000..ba34415e3 --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_structural_integrity.py @@ -0,0 +1,143 @@ +"""Regression coverage for canonical non-verifiability owner evidence structure.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.result_nonverifiability import ( + ValidationResultNonVerifiabilityIntegrityError, + ValidationResultNonVerifiabilityRecord, + resolve_validation_result_nonverifiability, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +ATTEMPT_REFERENCE = ( + "validation_evidence_verification_attempt:33333333-3333-4333-8333-333333333333" +) +OWNER_REFERENCE = "released_owner_contract:44444444-4444-4444-8444-444444444444" +RESULT_DIGEST = "1" * 64 +ATTEMPT_DIGEST = "3" * 64 +OWNER_DIGEST = "4" * 64 +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 17, 5, 55, tzinfo=timezone.utc) +EVALUATED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) +ATTEMPT_RELEASED_AT = datetime(2026, 9, 17, 6, 2, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 6, 5, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 6, 10, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "result_reference", + "result_digest", + "verification_status", + "failed_evidence_kind", + "failure_mode", + "failed_evidence_reference", + "failed_evidence_digest", + "failed_evidence_released_at", + "verification_attempt_reference", + "verification_attempt_digest", + "verification_attempt_released_at", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "evaluated_at", + "released_at", + "superseded_at", + } +) + + +class _ReadPort: + """Return configured owner evidence without normalizing its tuple structure.""" + + def __init__(self, result: object) -> None: + self.result = result + + def read_validation_result_nonverifiability(self, **_: object) -> object: + return self.result + + +def _record() -> ValidationResultNonVerifiabilityRecord: + return ValidationResultNonVerifiabilityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + failed_evidence_kind="analysis_weight_receipt", + failure_mode="missing", + failed_evidence_reference=None, + failed_evidence_digest=None, + failed_evidence_released_at=None, + verification_attempt_reference=ATTEMPT_REFERENCE, + verification_attempt_digest=ATTEMPT_DIGEST, + verification_attempt_released_at=ATTEMPT_RELEASED_AT, + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=7, + owner_contract_digest=OWNER_DIGEST, + owner_contract_released_at=OWNER_CONTRACT_RELEASED_AT, + evaluated_at=EVALUATED_AT, + released_at=RELEASED_AT, + ) + + +def _resolve(read_port: object) -> object: + principal = ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + policy = PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="validation-result-nonverifiability-read-v1", + resource_kind="validation_result_nonverifiability", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + return resolve_validation_result_nonverifiability( + principal=principal, + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + failed_evidence_kind="analysis_weight_receipt", + failure_mode="missing", + failed_evidence_reference=None, + failed_evidence_digest=None, + verification_attempt_reference=ATTEMPT_REFERENCE, + verification_attempt_digest=ATTEMPT_DIGEST, + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=7, + owner_contract_digest=OWNER_DIGEST, + used_at=USED_AT, + purpose_code="selection_validity_analysis", + policy=policy, + read_port=read_port, + ) + + +def test_owner_port_cannot_append_hidden_tuple_fields_to_exact_record_type() -> None: + valid = _record() + forged = tuple.__new__( + ValidationResultNonVerifiabilityRecord, + (*tuple(valid), "hidden-unreviewed-owner-coordinate"), + ) + + with pytest.raises(ValidationResultNonVerifiabilityIntegrityError): + _resolve(_ReadPort(forged)) + + +def test_malformed_exact_record_type_maps_to_integrity_error() -> None: + valid = _record() + forged = tuple.__new__(ValidationResultNonVerifiabilityRecord, tuple(valid)[:-1]) + + with pytest.raises(ValidationResultNonVerifiabilityIntegrityError): + _resolve(_ReadPort(forged)) From 259eb33f6b5f092eb4a91d94a6841d103683607a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 04:29:34 +0900 Subject: [PATCH 380/603] fix(workforce-validation): canonicalize nonverifiability owner records --- .../result_nonverifiability.py | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py index 1267a25c0..32a5b0fc1 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py @@ -551,27 +551,37 @@ def resolve_validation_result_nonverifiability( "owner port returned non-canonical validation-result non-verifiability evidence" ) - record = ValidationResultNonVerifiabilityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - result_reference=persisted.result_reference, - result_digest=persisted.result_digest, - failed_evidence_kind=persisted.failed_evidence_kind, - failure_mode=persisted.failure_mode, - failed_evidence_reference=persisted.failed_evidence_reference, - failed_evidence_digest=persisted.failed_evidence_digest, - verification_attempt_reference=persisted.verification_attempt_reference, - verification_attempt_digest=persisted.verification_attempt_digest, - verification_attempt_released_at=persisted.verification_attempt_released_at, - owner_contract_reference=persisted.owner_contract_reference, - owner_contract_version=persisted.owner_contract_version, - owner_contract_digest=persisted.owner_contract_digest, - owner_contract_released_at=persisted.owner_contract_released_at, - evaluated_at=persisted.evaluated_at, - released_at=persisted.released_at, - superseded_at=persisted.superseded_at, - failed_evidence_released_at=persisted.failed_evidence_released_at, - ) + try: + record = ValidationResultNonVerifiabilityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + result_reference=persisted.result_reference, + result_digest=persisted.result_digest, + failed_evidence_kind=persisted.failed_evidence_kind, + failure_mode=persisted.failure_mode, + failed_evidence_reference=persisted.failed_evidence_reference, + failed_evidence_digest=persisted.failed_evidence_digest, + verification_attempt_reference=persisted.verification_attempt_reference, + verification_attempt_digest=persisted.verification_attempt_digest, + verification_attempt_released_at=persisted.verification_attempt_released_at, + owner_contract_reference=persisted.owner_contract_reference, + owner_contract_version=persisted.owner_contract_version, + owner_contract_digest=persisted.owner_contract_digest, + owner_contract_released_at=persisted.owner_contract_released_at, + evaluated_at=persisted.evaluated_at, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + failed_evidence_released_at=persisted.failed_evidence_released_at, + ) + except (IndexError, TypeError, ValueError) as exc: + raise ValidationResultNonVerifiabilityIntegrityError( + "owner port returned structurally invalid validation-result non-verifiability evidence" + ) from exc + if record != persisted: + raise ValidationResultNonVerifiabilityIntegrityError( + "owner port returned non-canonical validation-result non-verifiability structure" + ) + requested_identity = ( tenant_identity, study_identity, From 629ed561d562161551afb23a4bb37803d228d0f2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 04:36:49 +0900 Subject: [PATCH 381/603] test(workforce-validation): reject forged base-weight tuples --- ...e_weight_authority_structural_integrity.py | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_base_weight_authority_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_base_weight_authority_structural_integrity.py b/services/workforce-validation-api/tests/test_base_weight_authority_structural_integrity.py new file mode 100644 index 000000000..cbf5fcf81 --- /dev/null +++ b/services/workforce-validation-api/tests/test_base_weight_authority_structural_integrity.py @@ -0,0 +1,173 @@ +"""Regression coverage for canonical base-weight owner evidence structure.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.base_weight_authority import ( + BaseWeightAuthorityIntegrityError, + BaseWeightAuthorityRecord, + resolve_base_weight_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") +BASE_RECEIPT_REFERENCE = "base_weight_evidence_receipt:11111111-1111-4111-8111-111111111111" +SOURCE_REFERENCE = "source_universe_receipt:22222222-2222-4222-8222-222222222222" +SAMPLING_REFERENCE = "sampling_design_receipt:33333333-3333-4333-8333-333333333333" +OWNER_REFERENCE = "released_owner_contract:44444444-4444-4444-8444-444444444444" +BASE_RECEIPT_DIGEST = "1" * 64 +SOURCE_DIGEST = "2" * 64 +SAMPLING_DIGEST = "3" * 64 +SAMPLED_SET_DIGEST = "4" * 64 +SELECTION_PROBABILITY_SET_DIGEST = "5" * 64 +BASE_ARTIFACT_DIGEST = "6" * 64 +OWNER_DIGEST = "7" * 64 +SOURCE_RELEASED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) +SAMPLING_RELEASED_AT = datetime(2026, 9, 17, 6, 30, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 17, 6, 45, tzinfo=timezone.utc) +CONSTRUCTED_AT = datetime(2026, 9, 17, 7, 0, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 7, 30, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 8, 0, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "base_weight_evidence_receipt_reference", + "base_weight_evidence_receipt_digest", + "evidence_version", + "source_universe_receipt_reference", + "source_universe_receipt_version", + "source_universe_receipt_digest", + "source_universe_released_at", + "sampling_design_receipt_reference", + "sampling_design_receipt_version", + "sampling_design_receipt_digest", + "sampling_design_released_at", + "sampled_occurrence_set_digest", + "selection_probability_set_digest", + "selection_stage_count", + "base_weight_method_code", + "base_weight_method_version", + "base_weight_artifact_digest", + "constructed_at", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + } +) + + +class _ReadPort: + """Return configured owner evidence without normalizing its tuple structure.""" + + def __init__(self, result: object) -> None: + self.result = result + + def read_base_weight_authority(self, **_: object) -> object: + """Return the configured raw owner result.""" + return self.result + + +def _record() -> BaseWeightAuthorityRecord: + """Build one valid canonical base-weight authority record.""" + return BaseWeightAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + base_weight_evidence_receipt_reference=BASE_RECEIPT_REFERENCE, + base_weight_evidence_receipt_digest=BASE_RECEIPT_DIGEST, + evidence_version=1, + source_universe_receipt_reference=SOURCE_REFERENCE, + source_universe_receipt_version=4, + source_universe_receipt_digest=SOURCE_DIGEST, + source_universe_released_at=SOURCE_RELEASED_AT, + sampling_design_receipt_reference=SAMPLING_REFERENCE, + sampling_design_receipt_version=3, + sampling_design_receipt_digest=SAMPLING_DIGEST, + sampling_design_released_at=SAMPLING_RELEASED_AT, + sampled_occurrence_set_digest=SAMPLED_SET_DIGEST, + selection_probability_set_digest=SELECTION_PROBABILITY_SET_DIGEST, + selection_stage_count=2, + base_weight_method_code="inverse_inclusion_probability", + base_weight_method_version=1, + base_weight_artifact_digest=BASE_ARTIFACT_DIGEST, + constructed_at=CONSTRUCTED_AT, + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=6, + owner_contract_digest=OWNER_DIGEST, + owner_contract_released_at=OWNER_CONTRACT_RELEASED_AT, + released_at=RELEASED_AT, + ) + + +def _resolve(read_port: object) -> object: + """Resolve the canonical coordinates through a supplied raw owner port.""" + principal = ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + policy = PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="base-weight-authority-read-v1", + resource_kind="base_weight_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + return resolve_base_weight_authority( + principal=principal, + tenant_record_id=TENANT, + validity_study_id=STUDY, + base_weight_evidence_receipt_reference=BASE_RECEIPT_REFERENCE, + base_weight_evidence_receipt_digest=BASE_RECEIPT_DIGEST, + evidence_version=1, + source_universe_receipt_reference=SOURCE_REFERENCE, + source_universe_receipt_version=4, + source_universe_receipt_digest=SOURCE_DIGEST, + sampling_design_receipt_reference=SAMPLING_REFERENCE, + sampling_design_receipt_version=3, + sampling_design_receipt_digest=SAMPLING_DIGEST, + sampled_occurrence_set_digest=SAMPLED_SET_DIGEST, + selection_probability_set_digest=SELECTION_PROBABILITY_SET_DIGEST, + selection_stage_count=2, + base_weight_method_code="inverse_inclusion_probability", + base_weight_method_version=1, + base_weight_artifact_digest=BASE_ARTIFACT_DIGEST, + constructed_at=CONSTRUCTED_AT, + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=6, + owner_contract_digest=OWNER_DIGEST, + used_at=USED_AT, + purpose_code="selection_validity_analysis", + policy=policy, + read_port=read_port, + ) + + +def test_owner_port_cannot_append_hidden_tuple_fields_to_exact_base_weight_record() -> None: + """Reject exact-typed owner evidence with coordinates outside the canonical tuple.""" + valid = _record() + forged = tuple.__new__( + BaseWeightAuthorityRecord, + (*tuple(valid), "hidden-unreviewed-owner-coordinate"), + ) + + with pytest.raises(BaseWeightAuthorityIntegrityError): + _resolve(_ReadPort(forged)) + + +def test_malformed_exact_base_weight_record_maps_to_integrity_error() -> None: + """Map a truncated exact-typed owner tuple to the domain integrity boundary.""" + valid = _record() + forged = tuple.__new__(BaseWeightAuthorityRecord, tuple(valid)[:-1]) + + with pytest.raises(BaseWeightAuthorityIntegrityError): + _resolve(_ReadPort(forged)) From f7626810a9e04330ca692c290ae779de6dc0e7f3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 04:38:05 +0900 Subject: [PATCH 382/603] fix(workforce-validation): canonicalize base-weight owner records --- .../base_weight_authority.py | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py index 79a1f8136..8b99e5075 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py @@ -472,13 +472,23 @@ def resolve_base_weight_authority( "owner port returned non-canonical base-weight authority evidence" ) - record = BaseWeightAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - released_at=persisted.released_at, - superseded_at=persisted.superseded_at, - **dict(persisted.fields), - ) + try: + record = BaseWeightAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + **dict(persisted.fields), + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise BaseWeightAuthorityIntegrityError( + "owner port returned structurally invalid base-weight authority evidence" + ) from exc + if record != persisted: + raise BaseWeightAuthorityIntegrityError( + "owner port returned non-canonical base-weight authority structure" + ) + record_values = dict(record.fields) requested_match = tuple( (field_name, field_value) From 0846004ada0d9d60c7f9827f0d099da934b81808 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 05:00:17 +0900 Subject: [PATCH 383/603] test(workforce-validation): expose result owner tuple forgery --- ...n_result_authority_structural_integrity.py | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_authority_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_validation_result_authority_structural_integrity.py b/services/workforce-validation-api/tests/test_validation_result_authority_structural_integrity.py new file mode 100644 index 000000000..f524edde8 --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_authority_structural_integrity.py @@ -0,0 +1,138 @@ +"""Regression coverage for canonical validation-result owner evidence structure.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.result_authority import ( + ValidationResultAuthorityIntegrityError, + ValidationResultAuthorityRecord, + resolve_validation_result_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +COMPATIBILITY_REFERENCE = ( + "weight_variance_compatibility_receipt:22222222-2222-4222-8222-222222222222" +) +OWNER_REFERENCE = "released_owner_contract:33333333-3333-4333-8333-333333333333" +RESULT_DIGEST = "1" * 64 +COMPATIBILITY_DIGEST = "2" * 64 +ANALYSIS_WEIGHT_DIGEST = "3" * 64 +VARIANCE_DIGEST = "4" * 64 +OWNER_DIGEST = "5" * 64 +OWNER_RELEASED_AT = datetime(2026, 9, 17, 4, 0, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 5, 0, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 6, 0, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "result_reference", + "result_digest", + "compatibility_receipt_reference", + "compatibility_receipt_digest", + "analysis_weight_receipt_digest", + "variance_design_receipt_digest", + "verification_status", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + } +) + + +class _ReadPort: + """Return configured owner evidence without normalizing its tuple structure.""" + + def __init__(self, result: object) -> None: + self.result = result + + def read_validation_result_authority(self, **_: object) -> object: + """Return the configured raw owner result.""" + return self.result + + +def _record() -> ValidationResultAuthorityRecord: + """Build one valid canonical validation-result authority record.""" + return ValidationResultAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + compatibility_receipt_reference=COMPATIBILITY_REFERENCE, + compatibility_receipt_digest=COMPATIBILITY_DIGEST, + analysis_weight_receipt_digest=ANALYSIS_WEIGHT_DIGEST, + variance_design_receipt_digest=VARIANCE_DIGEST, + verification_status="verification_pending", + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=7, + owner_contract_digest=OWNER_DIGEST, + owner_contract_released_at=OWNER_RELEASED_AT, + released_at=RELEASED_AT, + ) + + +def _resolve(read_port: object) -> object: + """Resolve canonical coordinates through a supplied raw owner port.""" + principal = ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + policy = PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="validation-result-authority-read-v2", + resource_kind="validation_result_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + return resolve_validation_result_authority( + principal=principal, + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + compatibility_receipt_reference=COMPATIBILITY_REFERENCE, + compatibility_receipt_digest=COMPATIBILITY_DIGEST, + analysis_weight_receipt_digest=ANALYSIS_WEIGHT_DIGEST, + variance_design_receipt_digest=VARIANCE_DIGEST, + verification_status="verification_pending", + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=7, + owner_contract_digest=OWNER_DIGEST, + used_at=USED_AT, + purpose_code="selection_validity_analysis", + policy=policy, + read_port=read_port, + ) + + +def test_owner_port_cannot_append_hidden_tuple_fields_to_exact_result_record() -> None: + """Reject exact-typed evidence with coordinates outside the canonical tuple.""" + valid = _record() + forged = tuple.__new__( + ValidationResultAuthorityRecord, + (*tuple(valid), "hidden-unreviewed-owner-coordinate"), + ) + + with pytest.raises(ValidationResultAuthorityIntegrityError): + _resolve(_ReadPort(forged)) + + +def test_malformed_exact_result_record_maps_to_integrity_error() -> None: + """Map a truncated exact-typed owner tuple to the domain integrity boundary.""" + valid = _record() + forged = tuple.__new__(ValidationResultAuthorityRecord, tuple(valid)[:-1]) + + with pytest.raises(ValidationResultAuthorityIntegrityError): + _resolve(_ReadPort(forged)) From 035e517e6b4cf930a5b3b299952bfc33439f0fa1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 05:01:01 +0900 Subject: [PATCH 384/603] fix(workforce-validation): canonicalize result owner reads --- .../result_authority.py | 44 ++++++++++++------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py index ee88f2728..02cf6aa70 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py @@ -433,23 +433,33 @@ def resolve_validation_result_authority( "owner port returned non-canonical validation-result authority evidence" ) - record = ValidationResultAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - result_reference=persisted.result_reference, - result_digest=persisted.result_digest, - compatibility_receipt_reference=persisted.compatibility_receipt_reference, - compatibility_receipt_digest=persisted.compatibility_receipt_digest, - analysis_weight_receipt_digest=persisted.analysis_weight_receipt_digest, - variance_design_receipt_digest=persisted.variance_design_receipt_digest, - verification_status=persisted.verification_status, - owner_contract_reference=persisted.owner_contract_reference, - owner_contract_version=persisted.owner_contract_version, - owner_contract_digest=persisted.owner_contract_digest, - owner_contract_released_at=persisted.owner_contract_released_at, - released_at=persisted.released_at, - superseded_at=persisted.superseded_at, - ) + try: + record = ValidationResultAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + result_reference=persisted.result_reference, + result_digest=persisted.result_digest, + compatibility_receipt_reference=persisted.compatibility_receipt_reference, + compatibility_receipt_digest=persisted.compatibility_receipt_digest, + analysis_weight_receipt_digest=persisted.analysis_weight_receipt_digest, + variance_design_receipt_digest=persisted.variance_design_receipt_digest, + verification_status=persisted.verification_status, + owner_contract_reference=persisted.owner_contract_reference, + owner_contract_version=persisted.owner_contract_version, + owner_contract_digest=persisted.owner_contract_digest, + owner_contract_released_at=persisted.owner_contract_released_at, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise ValidationResultAuthorityIntegrityError( + "owner port returned malformed validation-result authority evidence" + ) from exc + if record != persisted: + raise ValidationResultAuthorityIntegrityError( + "owner port returned non-canonical validation-result authority structure" + ) + requested_identity = ( tenant_identity, study_identity, From 0fc171d170b069235e413dbd0720511f2a033171 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 05:01:27 +0900 Subject: [PATCH 385/603] test(workforce-validation): expose result supersession tuple forgery --- ...rsession_authority_structural_integrity.py | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_result_supersession_authority_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_result_supersession_authority_structural_integrity.py b/services/workforce-validation-api/tests/test_result_supersession_authority_structural_integrity.py new file mode 100644 index 000000000..9d5e7ceea --- /dev/null +++ b/services/workforce-validation-api/tests/test_result_supersession_authority_structural_integrity.py @@ -0,0 +1,127 @@ +"""Regression coverage for canonical validation-result supersession owner structure.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.result_supersession_authority import ( + ValidationResultSupersessionAuthorityIntegrityError, + ValidationResultSupersessionAuthorityRecord, + resolve_validation_result_supersession_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +OWNER_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +RESULT_DIGEST = "1" * 64 +OWNER_DIGEST = "2" * 64 +OWNER_RELEASED_AT = datetime(2026, 9, 1, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 10, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 12, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "result_reference", + "result_digest", + "evidence_version", + "correction_sequence", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_result_reference", + "successor_correction_sequence", + "successor_result_digest", + "successor_released_at", + } +) + + +class _ReadPort: + """Return configured owner evidence without normalizing tuple structure.""" + + def __init__(self, result: object) -> None: + self.result = result + + def read_validation_result_supersession_authority(self, **_: object) -> object: + """Return the configured raw owner result.""" + return self.result + + +def _record() -> ValidationResultSupersessionAuthorityRecord: + """Build one current canonical validation-result supersession record.""" + return ValidationResultSupersessionAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + evidence_version=1, + correction_sequence=2, + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_DIGEST, + owner_contract_released_at=OWNER_RELEASED_AT, + released_at=RELEASED_AT, + ) + + +def _resolve(read_port: object) -> object: + """Resolve canonical coordinates through a supplied raw owner port.""" + principal = ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + policy = PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="validation-result-supersession-authority-read-v1", + resource_kind="validation_result_supersession_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + return resolve_validation_result_supersession_authority( + principal=principal, + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + evidence_version=1, + correction_sequence=2, + owner_contract_reference=OWNER_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_DIGEST, + used_at=USED_AT, + purpose_code="selection_validity_analysis", + policy=policy, + read_port=read_port, + ) + + +def test_owner_port_cannot_append_hidden_tuple_fields_to_exact_result_supersession_record() -> None: + """Reject exact-typed evidence with coordinates outside the canonical tuple.""" + valid = _record() + forged = tuple.__new__( + ValidationResultSupersessionAuthorityRecord, + (*tuple(valid), "hidden-unreviewed-owner-coordinate"), + ) + + with pytest.raises(ValidationResultSupersessionAuthorityIntegrityError): + _resolve(_ReadPort(forged)) + + +def test_malformed_exact_result_supersession_record_maps_to_integrity_error() -> None: + """Map truncated exact-typed evidence to the domain integrity boundary.""" + valid = _record() + forged = tuple.__new__(ValidationResultSupersessionAuthorityRecord, tuple(valid)[:-1]) + + with pytest.raises(ValidationResultSupersessionAuthorityIntegrityError): + _resolve(_ReadPort(forged)) From 0ec299400bec16d7aef466fff4b08c700937cb98 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 05:02:04 +0900 Subject: [PATCH 386/603] fix(workforce-validation): canonicalize result supersession reads --- .../result_supersession_authority.py | 86 +++++++++++-------- 1 file changed, 48 insertions(+), 38 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py index dcc4c0ade..7cd306d87 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py @@ -404,44 +404,54 @@ def resolve_validation_result_supersession_authority( "owner port returned non-canonical validation-result supersession evidence" ) - persisted_fields = dict(persisted.fields) - persisted_successor = ( - None if persisted.successor_fields is None else dict(persisted.successor_fields) - ) - record = ValidationResultSupersessionAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - result_reference=persisted_fields["result_reference"], - result_digest=persisted_fields["result_digest"], - evidence_version=persisted_fields["evidence_version"], - correction_sequence=persisted_fields["correction_sequence"], - owner_contract_reference=persisted_fields["owner_contract_reference"], - owner_contract_version=persisted_fields["owner_contract_version"], - owner_contract_digest=persisted_fields["owner_contract_digest"], - owner_contract_released_at=persisted_fields["owner_contract_released_at"], - released_at=persisted.released_at, - superseded_at=persisted.superseded_at, - successor_result_reference=( - None - if persisted_successor is None - else persisted_successor["successor_result_reference"] - ), - successor_correction_sequence=( - None - if persisted_successor is None - else persisted_successor["successor_correction_sequence"] - ), - successor_result_digest=( - None - if persisted_successor is None - else persisted_successor["successor_result_digest"] - ), - successor_released_at=( - None - if persisted_successor is None - else persisted_successor["successor_released_at"] - ), - ) + try: + persisted_fields = dict(persisted.fields) + persisted_successor = ( + None if persisted.successor_fields is None else dict(persisted.successor_fields) + ) + record = ValidationResultSupersessionAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + result_reference=persisted_fields["result_reference"], + result_digest=persisted_fields["result_digest"], + evidence_version=persisted_fields["evidence_version"], + correction_sequence=persisted_fields["correction_sequence"], + owner_contract_reference=persisted_fields["owner_contract_reference"], + owner_contract_version=persisted_fields["owner_contract_version"], + owner_contract_digest=persisted_fields["owner_contract_digest"], + owner_contract_released_at=persisted_fields["owner_contract_released_at"], + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + successor_result_reference=( + None + if persisted_successor is None + else persisted_successor["successor_result_reference"] + ), + successor_correction_sequence=( + None + if persisted_successor is None + else persisted_successor["successor_correction_sequence"] + ), + successor_result_digest=( + None + if persisted_successor is None + else persisted_successor["successor_result_digest"] + ), + successor_released_at=( + None + if persisted_successor is None + else persisted_successor["successor_released_at"] + ), + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise ValidationResultSupersessionAuthorityIntegrityError( + "owner port returned malformed validation-result supersession evidence" + ) from exc + if record != persisted: + raise ValidationResultSupersessionAuthorityIntegrityError( + "owner port returned non-canonical validation-result supersession structure" + ) + record_values = dict(record.fields) if ( _store_operational_uuid("record tenant_record_id", record.tenant_record_id) From 738659c27442d00196e5cc213763a4904a6ae5f4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 05:02:28 +0900 Subject: [PATCH 387/603] test(workforce-validation): expose benchmark owner tuple forgery --- ...enchmark_authority_structural_integrity.py | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_benchmark_authority_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_calibration_benchmark_authority_structural_integrity.py b/services/workforce-validation-api/tests/test_calibration_benchmark_authority_structural_integrity.py new file mode 100644 index 000000000..a9206b27a --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_benchmark_authority_structural_integrity.py @@ -0,0 +1,123 @@ +"""Regression coverage for canonical calibration-benchmark owner structure.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.benchmark_authority import ( + CalibrationBenchmarkAuthorityIntegrityError, + CalibrationBenchmarkAuthorityRecord, + resolve_calibration_benchmark_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +BENCHMARK_REFERENCE = "calibration_benchmark_receipt:11111111-1111-4111-8111-111111111111" +OWNER_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +BENCHMARK_DIGEST = "1" * 64 +OWNER_DIGEST = "2" * 64 +REFERENCE_AT = datetime(2026, 6, 30, tzinfo=timezone.utc) +OWNER_RELEASED_AT = datetime(2026, 7, 1, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 7, 15, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "benchmark_receipt_reference", + "benchmark_receipt_version", + "benchmark_receipt_digest", + "benchmark_owner_contract_reference", + "benchmark_owner_contract_version", + "benchmark_owner_contract_digest", + "benchmark_reference_at", + "benchmark_receipt_released_at", + "owner_contract_released_at", + } +) + + +class _ReadPort: + """Return configured owner evidence without normalizing tuple structure.""" + + def __init__(self, result: object) -> None: + self.result = result + + def read_calibration_benchmark_authority(self, **_: object) -> object: + """Return the configured raw owner result.""" + return self.result + + +def _record() -> CalibrationBenchmarkAuthorityRecord: + """Build one current canonical calibration-benchmark owner record.""" + return CalibrationBenchmarkAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + benchmark_receipt_reference=BENCHMARK_REFERENCE, + benchmark_receipt_version=4, + benchmark_receipt_digest=BENCHMARK_DIGEST, + benchmark_owner_contract_reference=OWNER_REFERENCE, + benchmark_owner_contract_version=3, + benchmark_owner_contract_digest=OWNER_DIGEST, + benchmark_reference_at=REFERENCE_AT, + benchmark_receipt_released_at=RELEASED_AT, + owner_contract_released_at=OWNER_RELEASED_AT, + ) + + +def _resolve(read_port: object) -> object: + """Resolve canonical coordinates through a supplied raw owner port.""" + principal = ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + policy = PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="calibration-benchmark-authority-read-v1", + resource_kind="calibration_benchmark_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + return resolve_calibration_benchmark_authority( + principal=principal, + tenant_record_id=TENANT, + validity_study_id=STUDY, + benchmark_receipt_reference=BENCHMARK_REFERENCE, + benchmark_receipt_version=4, + benchmark_receipt_digest=BENCHMARK_DIGEST, + benchmark_owner_contract_reference=OWNER_REFERENCE, + benchmark_owner_contract_version=3, + benchmark_owner_contract_digest=OWNER_DIGEST, + benchmark_reference_at=REFERENCE_AT, + used_at=USED_AT, + purpose_code="selection_validity_analysis", + policy=policy, + read_port=read_port, + ) + + +def test_owner_port_cannot_append_hidden_tuple_fields_to_exact_benchmark_record() -> None: + """Reject exact-typed evidence with coordinates outside the canonical tuple.""" + valid = _record() + forged = tuple.__new__( + CalibrationBenchmarkAuthorityRecord, + (*tuple(valid), "hidden-unreviewed-owner-coordinate"), + ) + + with pytest.raises(CalibrationBenchmarkAuthorityIntegrityError): + _resolve(_ReadPort(forged)) + + +def test_malformed_exact_benchmark_record_maps_to_integrity_error() -> None: + """Map truncated exact-typed evidence to the domain integrity boundary.""" + valid = _record() + forged = tuple.__new__(CalibrationBenchmarkAuthorityRecord, tuple(valid)[:-1]) + + with pytest.raises(CalibrationBenchmarkAuthorityIntegrityError): + _resolve(_ReadPort(forged)) From 025a14b6f90900685b9499deb6f18441dd2afd26 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 05:03:10 +0900 Subject: [PATCH 388/603] fix(workforce-validation): canonicalize benchmark owner reads --- .../benchmark_authority.py | 58 +++++++++++-------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py index ac088811e..379686e00 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py @@ -487,30 +487,40 @@ def resolve_calibration_benchmark_authority( "owner port returned non-canonical calibration benchmark evidence" ) - record = CalibrationBenchmarkAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - benchmark_receipt_reference=persisted.benchmark_receipt_reference, - benchmark_receipt_version=persisted.benchmark_receipt_version, - benchmark_receipt_digest=persisted.benchmark_receipt_digest, - benchmark_owner_contract_reference=persisted.benchmark_owner_contract_reference, - benchmark_owner_contract_version=persisted.benchmark_owner_contract_version, - benchmark_owner_contract_digest=persisted.benchmark_owner_contract_digest, - benchmark_reference_at=persisted.benchmark_reference_at, - benchmark_receipt_released_at=persisted.benchmark_receipt_released_at, - owner_contract_released_at=persisted.owner_contract_released_at, - benchmark_receipt_superseded_at=persisted.benchmark_receipt_superseded_at, - successor_benchmark_receipt_reference=( - persisted.successor_benchmark_receipt_reference - ), - successor_benchmark_receipt_version=( - persisted.successor_benchmark_receipt_version - ), - successor_benchmark_receipt_digest=persisted.successor_benchmark_receipt_digest, - successor_benchmark_receipt_released_at=( - persisted.successor_benchmark_receipt_released_at - ), - ) + try: + record = CalibrationBenchmarkAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + benchmark_receipt_reference=persisted.benchmark_receipt_reference, + benchmark_receipt_version=persisted.benchmark_receipt_version, + benchmark_receipt_digest=persisted.benchmark_receipt_digest, + benchmark_owner_contract_reference=persisted.benchmark_owner_contract_reference, + benchmark_owner_contract_version=persisted.benchmark_owner_contract_version, + benchmark_owner_contract_digest=persisted.benchmark_owner_contract_digest, + benchmark_reference_at=persisted.benchmark_reference_at, + benchmark_receipt_released_at=persisted.benchmark_receipt_released_at, + owner_contract_released_at=persisted.owner_contract_released_at, + benchmark_receipt_superseded_at=persisted.benchmark_receipt_superseded_at, + successor_benchmark_receipt_reference=( + persisted.successor_benchmark_receipt_reference + ), + successor_benchmark_receipt_version=( + persisted.successor_benchmark_receipt_version + ), + successor_benchmark_receipt_digest=persisted.successor_benchmark_receipt_digest, + successor_benchmark_receipt_released_at=( + persisted.successor_benchmark_receipt_released_at + ), + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise CalibrationBenchmarkAuthorityIntegrityError( + "owner port returned malformed calibration benchmark evidence" + ) from exc + if record != persisted: + raise CalibrationBenchmarkAuthorityIntegrityError( + "owner port returned non-canonical calibration benchmark structure" + ) + expected = ( tenant_id, study_id, From 90a0adbee0e896d9a95f4f060c0fe48161168a16 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 05:59:15 +0900 Subject: [PATCH 389/603] test(workforce-validation): expose base-weight supersession tuple forgery --- ...test_base_weight_supersession_authority.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/services/workforce-validation-api/tests/test_base_weight_supersession_authority.py b/services/workforce-validation-api/tests/test_base_weight_supersession_authority.py index f33187563..c95790f34 100644 --- a/services/workforce-validation-api/tests/test_base_weight_supersession_authority.py +++ b/services/workforce-validation-api/tests/test_base_weight_supersession_authority.py @@ -294,3 +294,22 @@ def test_record_and_view_are_immutable_and_uuid_views_detached() -> None: validity_study_id=STUDY, fields=(), ) + + +def test_exact_typed_hidden_tail_record_fails_closed() -> None: + canonical = _record() + forged = tuple.__new__( + BaseWeightSupersessionAuthorityRecord, + tuple(canonical) + (("hidden_owner_coordinate", "must-not-normalize-away"),), + ) + + with pytest.raises(BaseWeightSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(forged), used_at=RELEASED) + + +def test_exact_typed_truncated_record_maps_to_integrity_error() -> None: + canonical = _record() + forged = tuple.__new__(BaseWeightSupersessionAuthorityRecord, tuple(canonical)[:-1]) + + with pytest.raises(BaseWeightSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(forged), used_at=RELEASED) From 776ef4ff6a3d91820aee9d4f922e9cc19d11a3da Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 06:00:23 +0900 Subject: [PATCH 390/603] fix(workforce-validation): canonicalize base-weight supersession reads --- .../base_weight_supersession_authority.py | 83 ++++++++++++------- 1 file changed, 55 insertions(+), 28 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_supersession_authority.py index 07eebbb9d..534cdc42e 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_supersession_authority.py @@ -388,34 +388,61 @@ def resolve_base_weight_supersession_authority( "owner port returned non-canonical base-weight supersession evidence" ) - successor_values = ( - None if persisted.successor_fields is None else dict(persisted.successor_fields) - ) - record = BaseWeightSupersessionAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - released_at=persisted.released_at, - superseded_at=persisted.superseded_at, - successor_base_weight_evidence_receipt_reference=( - None - if successor_values is None - else successor_values["successor_base_weight_evidence_receipt_reference"] - ), - successor_base_weight_evidence_receipt_digest=( - None - if successor_values is None - else successor_values["successor_base_weight_evidence_receipt_digest"] - ), - successor_evidence_version=( - None - if successor_values is None - else successor_values["successor_evidence_version"] - ), - successor_released_at=( - None if successor_values is None else successor_values["successor_released_at"] - ), - **dict(persisted.fields), - ) + try: + persisted_fields = dict(persisted.fields) + persisted_successor = ( + None if persisted.successor_fields is None else dict(persisted.successor_fields) + ) + record = BaseWeightSupersessionAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + base_weight_evidence_receipt_reference=persisted_fields[ + "base_weight_evidence_receipt_reference" + ], + base_weight_evidence_receipt_digest=persisted_fields[ + "base_weight_evidence_receipt_digest" + ], + evidence_version=persisted_fields["evidence_version"], + owner_contract_reference=persisted_fields["owner_contract_reference"], + owner_contract_version=persisted_fields["owner_contract_version"], + owner_contract_digest=persisted_fields["owner_contract_digest"], + owner_contract_released_at=persisted_fields["owner_contract_released_at"], + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + successor_base_weight_evidence_receipt_reference=( + None + if persisted_successor is None + else persisted_successor[ + "successor_base_weight_evidence_receipt_reference" + ] + ), + successor_base_weight_evidence_receipt_digest=( + None + if persisted_successor is None + else persisted_successor[ + "successor_base_weight_evidence_receipt_digest" + ] + ), + successor_evidence_version=( + None + if persisted_successor is None + else persisted_successor["successor_evidence_version"] + ), + successor_released_at=( + None + if persisted_successor is None + else persisted_successor["successor_released_at"] + ), + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise BaseWeightSupersessionAuthorityIntegrityError( + "owner port returned malformed base-weight supersession evidence" + ) from exc + if record != persisted: + raise BaseWeightSupersessionAuthorityIntegrityError( + "owner port returned non-canonical base-weight supersession structure" + ) + record_values = dict(record.fields) if ( _store_operational_uuid("record tenant_record_id", record.tenant_record_id) From 8c14a7b7c0493302fbbeec9535b1084b252ba1ca Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 06:01:52 +0900 Subject: [PATCH 391/603] test(workforce-validation): expose calibration supersession tuple forgery --- ...ration_adjustment_supersession_contract.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py b/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py index bba28c42a..031e10e28 100644 --- a/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py @@ -320,3 +320,25 @@ def test_record_and_view_are_immutable_and_uuid_views_detached() -> None: validity_study_id=STUDY, fields=(), ) + + +def test_exact_typed_hidden_tail_record_fails_closed() -> None: + canonical = _record() + forged = tuple.__new__( + CalibrationAdjustmentSupersessionAuthorityRecord, + tuple(canonical) + (("hidden_owner_coordinate", "must-not-normalize-away"),), + ) + + with pytest.raises(CalibrationAdjustmentSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(forged), used_at=RELEASED) + + +def test_exact_typed_truncated_record_maps_to_integrity_error() -> None: + canonical = _record() + forged = tuple.__new__( + CalibrationAdjustmentSupersessionAuthorityRecord, + tuple(canonical)[:-1], + ) + + with pytest.raises(CalibrationAdjustmentSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(forged), used_at=RELEASED) From 128822668a556e8f939df9634beddc7c5f53a84d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 06:02:29 +0900 Subject: [PATCH 392/603] fix(workforce-validation): canonicalize calibration supersession reads --- ...ation_adjustment_supersession_authority.py | 79 ++++++++++++------- 1 file changed, 51 insertions(+), 28 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_supersession_authority.py index f00325ee3..092af5606 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_supersession_authority.py @@ -389,34 +389,57 @@ def resolve_calibration_adjustment_supersession_authority( "owner port returned non-canonical calibration supersession evidence" ) - successor_values = ( - None if persisted.successor_fields is None else dict(persisted.successor_fields) - ) - record = CalibrationAdjustmentSupersessionAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - released_at=persisted.released_at, - superseded_at=persisted.superseded_at, - successor_calibration_receipt_reference=( - None - if successor_values is None - else successor_values["successor_calibration_receipt_reference"] - ), - successor_calibration_receipt_digest=( - None - if successor_values is None - else successor_values["successor_calibration_receipt_digest"] - ), - successor_evidence_version=( - None - if successor_values is None - else successor_values["successor_evidence_version"] - ), - successor_released_at=( - None if successor_values is None else successor_values["successor_released_at"] - ), - **dict(persisted.fields), - ) + try: + persisted_fields = dict(persisted.fields) + persisted_successor = ( + None if persisted.successor_fields is None else dict(persisted.successor_fields) + ) + record = CalibrationAdjustmentSupersessionAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + calibration_receipt_reference=persisted_fields[ + "calibration_receipt_reference" + ], + calibration_receipt_digest=persisted_fields[ + "calibration_receipt_digest" + ], + evidence_version=persisted_fields["evidence_version"], + owner_contract_reference=persisted_fields["owner_contract_reference"], + owner_contract_version=persisted_fields["owner_contract_version"], + owner_contract_digest=persisted_fields["owner_contract_digest"], + owner_contract_released_at=persisted_fields["owner_contract_released_at"], + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + successor_calibration_receipt_reference=( + None + if persisted_successor is None + else persisted_successor["successor_calibration_receipt_reference"] + ), + successor_calibration_receipt_digest=( + None + if persisted_successor is None + else persisted_successor["successor_calibration_receipt_digest"] + ), + successor_evidence_version=( + None + if persisted_successor is None + else persisted_successor["successor_evidence_version"] + ), + successor_released_at=( + None + if persisted_successor is None + else persisted_successor["successor_released_at"] + ), + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise CalibrationAdjustmentSupersessionAuthorityIntegrityError( + "owner port returned malformed calibration supersession evidence" + ) from exc + if record != persisted: + raise CalibrationAdjustmentSupersessionAuthorityIntegrityError( + "owner port returned non-canonical calibration supersession structure" + ) + record_values = dict(record.fields) if ( _store_operational_uuid("record tenant_record_id", record.tenant_record_id) From 1b73d0e46258d7d517cfc7c649281236f3d3502a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 07:04:07 +0900 Subject: [PATCH 393/603] test(workforce-validation): expose calibration support tuple forgery --- ..._support_authority_structural_integrity.py | 201 ++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_support_authority_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_calibration_support_authority_structural_integrity.py b/services/workforce-validation-api/tests/test_calibration_support_authority_structural_integrity.py new file mode 100644 index 000000000..c5acd9d7d --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_support_authority_structural_integrity.py @@ -0,0 +1,201 @@ +"""Structural-integrity regressions for calibration support owner evidence.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy + +from orgmetra_workforce_validation_api import ValidationPrincipal +import orgmetra_workforce_validation_api.calibration_support_authority as target +from orgmetra_workforce_validation_api.calibration_support_authority import ( + CalibrationSupportAuthorityIntegrityError, + CalibrationSupportAuthorityRecord, + resolve_calibration_support_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f2") +AUX_OWNER_RELEASED_AT = datetime(2026, 9, 17, 7, 50, tzinfo=timezone.utc) +AUX_AUTH_RELEASED_AT = datetime(2026, 9, 17, 8, 0, tzinfo=timezone.utc) +AUX_AUTHORIZED_FROM = datetime(2026, 9, 17, 8, 10, tzinfo=timezone.utc) +AUX_AUTHORIZED_TO = datetime(2026, 10, 1, tzinfo=timezone.utc) +AUX_USE_AT = datetime(2026, 9, 17, 8, 30, tzinfo=timezone.utc) +BENCHMARK_OWNER_RELEASED_AT = datetime(2026, 9, 17, 8, 0, tzinfo=timezone.utc) +BENCHMARK_RECEIPT_RELEASED_AT = datetime(2026, 9, 17, 8, 20, tzinfo=timezone.utc) +BENCHMARK_REFERENCE_AT = datetime(2026, 9, 17, 8, 15, tzinfo=timezone.utc) +CONSTRUCTED_AT = datetime(2026, 9, 17, 9, 0, tzinfo=timezone.utc) +OWNER_RELEASED_AT = datetime(2026, 9, 17, 9, 10, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 9, 20, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 10, 0, tzinfo=timezone.utc) + + +class _ReadPort: + """Return configured persisted evidence through the owner-read capability.""" + + def __init__(self, result: object) -> None: + self.result = result + + def read_calibration_support_authority(self, **_: object) -> object: + """Return the configured owner evidence.""" + return self.result + + +def _record() -> CalibrationSupportAuthorityRecord: + return CalibrationSupportAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + support_authority_reference=( + "calibration_support_authority:10101010-1010-4010-8010-101010101010" + ), + support_authority_digest="0" * 64, + evidence_version=1, + calibration_receipt_reference=( + "calibration_adjustment_receipt:11111111-1111-4111-8111-111111111111" + ), + calibration_receipt_digest="1" * 64, + auxiliary_authority_reference=( + "scientific_auxiliary_authority:22222222-2222-4222-8222-222222222222" + ), + auxiliary_projection_reference=( + "calibration_auxiliary_projection:33333333-3333-4333-8333-333333333333" + ), + auxiliary_projection_version=3, + auxiliary_projection_digest="2" * 64, + auxiliary_purpose_reference=( + "scientific_data_use_purpose:44444444-4444-4444-8444-444444444444" + ), + auxiliary_purpose_digest="3" * 64, + auxiliary_owner_contract_reference=( + "released_owner_contract:55555555-5555-4555-8555-555555555555" + ), + auxiliary_owner_contract_version=5, + auxiliary_owner_contract_digest="4" * 64, + auxiliary_owner_contract_released_at=AUX_OWNER_RELEASED_AT, + auxiliary_authorization_receipt_reference=( + "scientific_data_authorization:66666666-6666-4666-8666-666666666666" + ), + auxiliary_authorization_receipt_digest="5" * 64, + auxiliary_authorization_receipt_released_at=AUX_AUTH_RELEASED_AT, + auxiliary_scientific_use_receipt_reference=( + "scientific_use_receipt:77777777-7777-4777-8777-777777777777" + ), + auxiliary_scientific_use_receipt_digest="6" * 64, + auxiliary_scientific_use_at=AUX_USE_AT, + auxiliary_authorized_from=AUX_AUTHORIZED_FROM, + auxiliary_authorized_to=AUX_AUTHORIZED_TO, + benchmark_receipt_reference=( + "calibration_benchmark_receipt:88888888-8888-4888-8888-888888888888" + ), + benchmark_receipt_version=8, + benchmark_receipt_digest="7" * 64, + benchmark_owner_contract_reference=( + "released_owner_contract:99999999-9999-4999-8999-999999999999" + ), + benchmark_owner_contract_version=9, + benchmark_owner_contract_digest="8" * 64, + benchmark_owner_contract_released_at=BENCHMARK_OWNER_RELEASED_AT, + benchmark_reference_at=BENCHMARK_REFERENCE_AT, + benchmark_receipt_released_at=BENCHMARK_RECEIPT_RELEASED_AT, + benchmark_receipt_superseded_at=None, + constructed_at=CONSTRUCTED_AT, + owner_contract_reference=( + "released_owner_contract:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" + ), + owner_contract_version=10, + owner_contract_digest="9" * 64, + owner_contract_released_at=OWNER_RELEASED_AT, + released_at=RELEASED_AT, + ) + + +def _resolve(result: object) -> object: + return resolve_calibration_support_authority( + principal=ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ), + tenant_record_id=TENANT, + validity_study_id=STUDY, + calibration_receipt_reference=( + "calibration_adjustment_receipt:11111111-1111-4111-8111-111111111111" + ), + calibration_receipt_digest="1" * 64, + auxiliary_authority_reference=( + "scientific_auxiliary_authority:22222222-2222-4222-8222-222222222222" + ), + auxiliary_projection_reference=( + "calibration_auxiliary_projection:33333333-3333-4333-8333-333333333333" + ), + auxiliary_projection_version=3, + auxiliary_projection_digest="2" * 64, + auxiliary_purpose_reference=( + "scientific_data_use_purpose:44444444-4444-4444-8444-444444444444" + ), + auxiliary_purpose_digest="3" * 64, + auxiliary_owner_contract_reference=( + "released_owner_contract:55555555-5555-4555-8555-555555555555" + ), + auxiliary_owner_contract_version=5, + auxiliary_owner_contract_digest="4" * 64, + auxiliary_authorization_receipt_reference=( + "scientific_data_authorization:66666666-6666-4666-8666-666666666666" + ), + auxiliary_authorization_receipt_digest="5" * 64, + auxiliary_scientific_use_receipt_reference=( + "scientific_use_receipt:77777777-7777-4777-8777-777777777777" + ), + auxiliary_scientific_use_receipt_digest="6" * 64, + auxiliary_scientific_use_at=AUX_USE_AT, + benchmark_receipt_reference=( + "calibration_benchmark_receipt:88888888-8888-4888-8888-888888888888" + ), + benchmark_receipt_version=8, + benchmark_receipt_digest="7" * 64, + benchmark_owner_contract_reference=( + "released_owner_contract:99999999-9999-4999-8999-999999999999" + ), + benchmark_owner_contract_version=9, + benchmark_owner_contract_digest="8" * 64, + benchmark_reference_at=BENCHMARK_REFERENCE_AT, + constructed_at=CONSTRUCTED_AT, + owner_contract_reference=( + "released_owner_contract:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" + ), + owner_contract_version=10, + owner_contract_digest="9" * 64, + used_at=USED_AT, + purpose_code="selection_validity_analysis", + policy=PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="calibration-support-read-v1", + resource_kind="calibration_support_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=target._READ_FIELDS, + ), + read_port=_ReadPort(result), + ) + + +def test_hidden_trailing_tuple_structure_fails_closed() -> None: + canonical = _record() + forged = tuple.__new__( + CalibrationSupportAuthorityRecord, + tuple(canonical) + ("hidden-owner-coordinate",), + ) + + with pytest.raises(CalibrationSupportAuthorityIntegrityError): + _resolve(forged) + + +def test_truncated_exact_typed_tuple_maps_to_integrity_error() -> None: + canonical = _record() + forged = tuple.__new__(CalibrationSupportAuthorityRecord, tuple(canonical)[:-1]) + + with pytest.raises(CalibrationSupportAuthorityIntegrityError): + _resolve(forged) From fb4da9f136ef718e4792a80bcc353875869c0062 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 07:06:20 +0900 Subject: [PATCH 394/603] fix(workforce-validation): reject forged calibration support tuples --- .../calibration_support_authority.py | 96 ++++++++++--------- 1 file changed, 53 insertions(+), 43 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py index 614b80f16..9c81de86e 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py @@ -717,49 +717,59 @@ def resolve_calibration_support_authority( "owner port returned non-canonical calibration support authority evidence" ) - record = CalibrationSupportAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - support_authority_reference=persisted.support_authority_reference, - support_authority_digest=persisted.support_authority_digest, - evidence_version=persisted.evidence_version, - calibration_receipt_reference=persisted.calibration_receipt_reference, - calibration_receipt_digest=persisted.calibration_receipt_digest, - auxiliary_authority_reference=persisted.auxiliary_authority_reference, - auxiliary_projection_reference=persisted.auxiliary_projection_reference, - auxiliary_projection_version=persisted.auxiliary_projection_version, - auxiliary_projection_digest=persisted.auxiliary_projection_digest, - auxiliary_purpose_reference=persisted.auxiliary_purpose_reference, - auxiliary_purpose_digest=persisted.auxiliary_purpose_digest, - auxiliary_owner_contract_reference=persisted.auxiliary_owner_contract_reference, - auxiliary_owner_contract_version=persisted.auxiliary_owner_contract_version, - auxiliary_owner_contract_digest=persisted.auxiliary_owner_contract_digest, - auxiliary_owner_contract_released_at=persisted.auxiliary_owner_contract_released_at, - auxiliary_authorization_receipt_reference=persisted.auxiliary_authorization_receipt_reference, - auxiliary_authorization_receipt_digest=persisted.auxiliary_authorization_receipt_digest, - auxiliary_authorization_receipt_released_at=persisted.auxiliary_authorization_receipt_released_at, - auxiliary_scientific_use_receipt_reference=persisted.auxiliary_scientific_use_receipt_reference, - auxiliary_scientific_use_receipt_digest=persisted.auxiliary_scientific_use_receipt_digest, - auxiliary_scientific_use_at=persisted.auxiliary_scientific_use_at, - auxiliary_authorized_from=persisted.auxiliary_authorized_from, - auxiliary_authorized_to=persisted.auxiliary_authorized_to, - benchmark_receipt_reference=persisted.benchmark_receipt_reference, - benchmark_receipt_version=persisted.benchmark_receipt_version, - benchmark_receipt_digest=persisted.benchmark_receipt_digest, - benchmark_owner_contract_reference=persisted.benchmark_owner_contract_reference, - benchmark_owner_contract_version=persisted.benchmark_owner_contract_version, - benchmark_owner_contract_digest=persisted.benchmark_owner_contract_digest, - benchmark_owner_contract_released_at=persisted.benchmark_owner_contract_released_at, - benchmark_reference_at=persisted.benchmark_reference_at, - benchmark_receipt_released_at=persisted.benchmark_receipt_released_at, - benchmark_receipt_superseded_at=persisted.benchmark_receipt_superseded_at, - constructed_at=persisted.constructed_at, - owner_contract_reference=persisted.owner_contract_reference, - owner_contract_version=persisted.owner_contract_version, - owner_contract_digest=persisted.owner_contract_digest, - owner_contract_released_at=persisted.owner_contract_released_at, - released_at=persisted.released_at, - ) + try: + record = CalibrationSupportAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + support_authority_reference=persisted.support_authority_reference, + support_authority_digest=persisted.support_authority_digest, + evidence_version=persisted.evidence_version, + calibration_receipt_reference=persisted.calibration_receipt_reference, + calibration_receipt_digest=persisted.calibration_receipt_digest, + auxiliary_authority_reference=persisted.auxiliary_authority_reference, + auxiliary_projection_reference=persisted.auxiliary_projection_reference, + auxiliary_projection_version=persisted.auxiliary_projection_version, + auxiliary_projection_digest=persisted.auxiliary_projection_digest, + auxiliary_purpose_reference=persisted.auxiliary_purpose_reference, + auxiliary_purpose_digest=persisted.auxiliary_purpose_digest, + auxiliary_owner_contract_reference=persisted.auxiliary_owner_contract_reference, + auxiliary_owner_contract_version=persisted.auxiliary_owner_contract_version, + auxiliary_owner_contract_digest=persisted.auxiliary_owner_contract_digest, + auxiliary_owner_contract_released_at=persisted.auxiliary_owner_contract_released_at, + auxiliary_authorization_receipt_reference=persisted.auxiliary_authorization_receipt_reference, + auxiliary_authorization_receipt_digest=persisted.auxiliary_authorization_receipt_digest, + auxiliary_authorization_receipt_released_at=persisted.auxiliary_authorization_receipt_released_at, + auxiliary_scientific_use_receipt_reference=persisted.auxiliary_scientific_use_receipt_reference, + auxiliary_scientific_use_receipt_digest=persisted.auxiliary_scientific_use_receipt_digest, + auxiliary_scientific_use_at=persisted.auxiliary_scientific_use_at, + auxiliary_authorized_from=persisted.auxiliary_authorized_from, + auxiliary_authorized_to=persisted.auxiliary_authorized_to, + benchmark_receipt_reference=persisted.benchmark_receipt_reference, + benchmark_receipt_version=persisted.benchmark_receipt_version, + benchmark_receipt_digest=persisted.benchmark_receipt_digest, + benchmark_owner_contract_reference=persisted.benchmark_owner_contract_reference, + benchmark_owner_contract_version=persisted.benchmark_owner_contract_version, + benchmark_owner_contract_digest=persisted.benchmark_owner_contract_digest, + benchmark_owner_contract_released_at=persisted.benchmark_owner_contract_released_at, + benchmark_reference_at=persisted.benchmark_reference_at, + benchmark_receipt_released_at=persisted.benchmark_receipt_released_at, + benchmark_receipt_superseded_at=persisted.benchmark_receipt_superseded_at, + constructed_at=persisted.constructed_at, + owner_contract_reference=persisted.owner_contract_reference, + owner_contract_version=persisted.owner_contract_version, + owner_contract_digest=persisted.owner_contract_digest, + owner_contract_released_at=persisted.owner_contract_released_at, + released_at=persisted.released_at, + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise CalibrationSupportAuthorityIntegrityError( + "owner port returned structurally invalid calibration support authority evidence" + ) from exc + if record != persisted: + raise CalibrationSupportAuthorityIntegrityError( + "owner port returned non-canonical calibration support authority structure" + ) + expected = ( tenant_id, study_id, From ae320b4b80f8e49af0d729470bf782eca675aff5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 07:06:39 +0900 Subject: [PATCH 395/603] test(workforce-validation): expose weight variance tuple forgery --- ...rsession_authority_structural_integrity.py | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_variance_supersession_authority_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_weight_variance_supersession_authority_structural_integrity.py b/services/workforce-validation-api/tests/test_weight_variance_supersession_authority_structural_integrity.py new file mode 100644 index 000000000..9d59e40b0 --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_variance_supersession_authority_structural_integrity.py @@ -0,0 +1,131 @@ +"""Structural-integrity regressions for weight/variance supersession evidence.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy + +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.weight_variance_supersession_authority import ( + WeightVarianceSupersessionAuthorityIntegrityError, + WeightVarianceSupersessionAuthorityRecord, + resolve_weight_variance_supersession_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +AUTHORITY = "variance_compatibility_authority:11111111-1111-4111-8111-111111111111" +SUCCESSOR = "variance_compatibility_authority:22222222-2222-4222-8222-222222222222" +OWNER = "released_owner_contract:33333333-3333-4333-8333-333333333333" +OWNER_DIGEST = "3" * 64 +OWNER_RELEASED = datetime(2026, 9, 17, 0, 30, tzinfo=timezone.utc) +RELEASED = datetime(2026, 9, 17, 1, 0, tzinfo=timezone.utc) +CUTOVER = datetime(2026, 9, 18, 1, 0, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "authority_reference", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_authority_reference", + "successor_evidence_version", + "successor_released_at", + } +) + + +class _ReadPort: + """Return configured persisted evidence.""" + + def __init__(self, result: object) -> None: + self.result = result + + def read_weight_variance_supersession_authority(self, **_: object) -> object: + """Return the configured owner evidence.""" + return self.result + + +def _record() -> WeightVarianceSupersessionAuthorityRecord: + return WeightVarianceSupersessionAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + authority_reference=AUTHORITY, + evidence_version=1, + owner_contract_reference=OWNER, + owner_contract_version=1, + owner_contract_digest=OWNER_DIGEST, + owner_contract_released_at=OWNER_RELEASED, + released_at=RELEASED, + superseded_at=CUTOVER, + successor_authority_reference=SUCCESSOR, + successor_evidence_version=1, + successor_released_at=CUTOVER, + ) + + +def _resolve(result: object) -> object: + return resolve_weight_variance_supersession_authority( + principal=ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ), + tenant_record_id=TENANT, + validity_study_id=STUDY, + authority_reference=AUTHORITY, + evidence_version=1, + owner_contract_reference=OWNER, + owner_contract_version=1, + owner_contract_digest=OWNER_DIGEST, + used_at=RELEASED, + purpose_code="selection_validity_analysis", + policy=PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="weight-variance-supersession-read-v1", + resource_kind="weight_variance_supersession_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ), + read_port=_ReadPort(result), + ) + + +def test_hidden_trailing_tuple_structure_fails_closed() -> None: + canonical = _record() + forged = tuple.__new__( + WeightVarianceSupersessionAuthorityRecord, + tuple(canonical) + ("hidden-owner-coordinate",), + ) + + with pytest.raises(WeightVarianceSupersessionAuthorityIntegrityError): + _resolve(forged) + + +def test_truncated_exact_typed_tuple_maps_to_integrity_error() -> None: + canonical = _record() + forged = tuple.__new__( + WeightVarianceSupersessionAuthorityRecord, + tuple(canonical)[:-1], + ) + + with pytest.raises(WeightVarianceSupersessionAuthorityIntegrityError): + _resolve(forged) + + +def test_duplicate_nested_current_field_cannot_be_normalized_away() -> None: + canonical = _record() + raw = list(canonical) + raw[2] = canonical.fields + (("authority_reference", AUTHORITY),) + forged = tuple.__new__(WeightVarianceSupersessionAuthorityRecord, tuple(raw)) + + with pytest.raises(WeightVarianceSupersessionAuthorityIntegrityError): + _resolve(forged) From 8339267997b422e10f74a2b04d231136402d9ffc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 07:08:22 +0900 Subject: [PATCH 396/603] fix(workforce-validation): reject forged weight variance tuples --- .../weight_variance_supersession_authority.py | 56 +++++++++++-------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_variance_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_variance_supersession_authority.py index 3addf3c22..011a38d7e 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_variance_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_variance_supersession_authority.py @@ -363,29 +363,39 @@ def resolve_weight_variance_supersession_authority( "owner port returned non-canonical weight/variance supersession evidence" ) - successor_values = ( - None if persisted.successor_fields is None else dict(persisted.successor_fields) - ) - record = WeightVarianceSupersessionAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - released_at=persisted.released_at, - superseded_at=persisted.superseded_at, - successor_authority_reference=( - None - if successor_values is None - else successor_values["successor_authority_reference"] - ), - successor_evidence_version=( - None - if successor_values is None - else successor_values["successor_evidence_version"] - ), - successor_released_at=( - None if successor_values is None else successor_values["successor_released_at"] - ), - **dict(persisted.fields), - ) + try: + successor_values = ( + None if persisted.successor_fields is None else dict(persisted.successor_fields) + ) + record = WeightVarianceSupersessionAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + successor_authority_reference=( + None + if successor_values is None + else successor_values["successor_authority_reference"] + ), + successor_evidence_version=( + None + if successor_values is None + else successor_values["successor_evidence_version"] + ), + successor_released_at=( + None if successor_values is None else successor_values["successor_released_at"] + ), + **dict(persisted.fields), + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise WeightVarianceSupersessionAuthorityIntegrityError( + "owner port returned structurally invalid weight/variance supersession evidence" + ) from exc + if record != persisted: + raise WeightVarianceSupersessionAuthorityIntegrityError( + "owner port returned non-canonical weight/variance supersession structure" + ) + record_values = dict(record.fields) if ( _store_operational_uuid("record tenant_record_id", record.tenant_record_id) From acce2f601341875d59b28d06306ae7628365ea2a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 08:02:12 +0900 Subject: [PATCH 397/603] test(workforce-validation): prove weight eligibility owner shape RED --- ...gibility_authority_structural_integrity.py | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_eligibility_authority_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_weight_eligibility_authority_structural_integrity.py b/services/workforce-validation-api/tests/test_weight_eligibility_authority_structural_integrity.py new file mode 100644 index 000000000..1f153852b --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_eligibility_authority_structural_integrity.py @@ -0,0 +1,151 @@ +"""Structural-integrity regressions for weight-eligibility owner evidence.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.weight_eligibility_authority import ( + WeightEligibilityAuthorityIntegrityError, + WeightEligibilityAuthorityRecord, + resolve_weight_eligibility_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RECEIPT_REFERENCE = "weight_eligibility_receipt:11111111-1111-4111-8111-111111111111" +TARGET_POPULATION_REFERENCE = "analysis_target_population:workers-2026q3" +REFERENCE_DURATION_REFERENCE = "analysis_reference_duration:2026q3" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +RECEIPT_DIGEST = "1" * 64 +TARGET_POPULATION_DIGEST = "2" * 64 +REFERENCE_DURATION_DIGEST = "3" * 64 +ELIGIBLE_CASE_SET_DIGEST = "4" * 64 +WEIGHT_ARTIFACT_DIGEST = "5" * 64 +OWNER_CONTRACT_DIGEST = "6" * 64 +CONSTRUCTED_AT = datetime(2026, 9, 16, 12, 0, tzinfo=timezone.utc) +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 16, 12, 30, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "eligibility_receipt_reference", + "eligibility_receipt_digest", + "evidence_version", + "weight_scope_code", + "target_population_reference", + "target_population_digest", + "reference_duration_reference", + "reference_duration_digest", + "eligible_case_set_digest", + "weight_artifact_digest", + "constructed_at", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + } +) + + +class _ReadPort: + """Return configured owner evidence without normalizing tuple structure.""" + + def __init__(self, result: object) -> None: + self.result = result + + def read_weight_eligibility_authority(self, **_: object) -> object: + """Return the configured raw owner result.""" + return self.result + + +def _record() -> WeightEligibilityAuthorityRecord: + """Build one valid canonical weight-eligibility authority record.""" + return WeightEligibilityAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + eligibility_receipt_reference=RECEIPT_REFERENCE, + eligibility_receipt_digest=RECEIPT_DIGEST, + evidence_version=1, + weight_scope_code="longitudinal", + target_population_reference=TARGET_POPULATION_REFERENCE, + target_population_digest=TARGET_POPULATION_DIGEST, + reference_duration_reference=REFERENCE_DURATION_REFERENCE, + reference_duration_digest=REFERENCE_DURATION_DIGEST, + eligible_case_set_digest=ELIGIBLE_CASE_SET_DIGEST, + weight_artifact_digest=WEIGHT_ARTIFACT_DIGEST, + constructed_at=CONSTRUCTED_AT, + owner_contract_reference=OWNER_CONTRACT_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_CONTRACT_DIGEST, + owner_contract_released_at=OWNER_CONTRACT_RELEASED_AT, + released_at=RELEASED_AT, + ) + + +def _resolve(read_port: object) -> object: + """Resolve canonical coordinates through a supplied raw owner port.""" + principal = ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + policy = PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="weight-eligibility-authority-read-v2", + resource_kind="weight_eligibility_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + return resolve_weight_eligibility_authority( + principal=principal, + tenant_record_id=TENANT, + validity_study_id=STUDY, + eligibility_receipt_reference=RECEIPT_REFERENCE, + eligibility_receipt_digest=RECEIPT_DIGEST, + evidence_version=1, + weight_scope_code="longitudinal", + target_population_reference=TARGET_POPULATION_REFERENCE, + target_population_digest=TARGET_POPULATION_DIGEST, + reference_duration_reference=REFERENCE_DURATION_REFERENCE, + reference_duration_digest=REFERENCE_DURATION_DIGEST, + eligible_case_set_digest=ELIGIBLE_CASE_SET_DIGEST, + weight_artifact_digest=WEIGHT_ARTIFACT_DIGEST, + constructed_at=CONSTRUCTED_AT, + owner_contract_reference=OWNER_CONTRACT_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_CONTRACT_DIGEST, + used_at=USED_AT, + purpose_code="selection_validity_analysis", + policy=policy, + read_port=read_port, + ) + + +def test_owner_port_cannot_append_hidden_tuple_fields() -> None: + """Reject exact-typed evidence with coordinates outside the canonical tuple.""" + canonical = _record() + forged = tuple.__new__( + WeightEligibilityAuthorityRecord, + (*tuple(canonical), "hidden-unreviewed-owner-coordinate"), + ) + + with pytest.raises(WeightEligibilityAuthorityIntegrityError): + _resolve(_ReadPort(forged)) + + +def test_truncated_exact_typed_tuple_maps_to_integrity_error() -> None: + """Map truncated exact-typed evidence to the domain integrity boundary.""" + canonical = _record() + forged = tuple.__new__(WeightEligibilityAuthorityRecord, tuple(canonical)[:-1]) + + with pytest.raises(WeightEligibilityAuthorityIntegrityError): + _resolve(_ReadPort(forged)) From 5af60ae1899ffdd549e74c1c447c845a492ac3af Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 08:02:51 +0900 Subject: [PATCH 398/603] fix(workforce-validation): canonicalize weight eligibility owner evidence --- .../weight_eligibility_authority.py | 51 +++++++++++-------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py index bdec01e47..31c51eefa 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py @@ -464,27 +464,36 @@ def resolve_weight_eligibility_authority( "owner port returned non-canonical weight-eligibility authority evidence" ) - record = WeightEligibilityAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - eligibility_receipt_reference=persisted.eligibility_receipt_reference, - eligibility_receipt_digest=persisted.eligibility_receipt_digest, - evidence_version=persisted.evidence_version, - weight_scope_code=persisted.weight_scope_code, - target_population_reference=persisted.target_population_reference, - target_population_digest=persisted.target_population_digest, - reference_duration_reference=persisted.reference_duration_reference, - reference_duration_digest=persisted.reference_duration_digest, - eligible_case_set_digest=persisted.eligible_case_set_digest, - weight_artifact_digest=persisted.weight_artifact_digest, - constructed_at=persisted.constructed_at, - owner_contract_reference=persisted.owner_contract_reference, - owner_contract_version=persisted.owner_contract_version, - owner_contract_digest=persisted.owner_contract_digest, - owner_contract_released_at=persisted.owner_contract_released_at, - released_at=persisted.released_at, - superseded_at=persisted.superseded_at, - ) + try: + record = WeightEligibilityAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + eligibility_receipt_reference=persisted.eligibility_receipt_reference, + eligibility_receipt_digest=persisted.eligibility_receipt_digest, + evidence_version=persisted.evidence_version, + weight_scope_code=persisted.weight_scope_code, + target_population_reference=persisted.target_population_reference, + target_population_digest=persisted.target_population_digest, + reference_duration_reference=persisted.reference_duration_reference, + reference_duration_digest=persisted.reference_duration_digest, + eligible_case_set_digest=persisted.eligible_case_set_digest, + weight_artifact_digest=persisted.weight_artifact_digest, + constructed_at=persisted.constructed_at, + owner_contract_reference=persisted.owner_contract_reference, + owner_contract_version=persisted.owner_contract_version, + owner_contract_digest=persisted.owner_contract_digest, + owner_contract_released_at=persisted.owner_contract_released_at, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise WeightEligibilityAuthorityIntegrityError( + "owner port returned structurally invalid weight-eligibility authority evidence" + ) from exc + if record != persisted: + raise WeightEligibilityAuthorityIntegrityError( + "owner port returned non-canonical weight-eligibility authority structure" + ) if record[:-3] != requested[:-3]: raise WeightEligibilityAuthorityIntegrityError( "released weight-eligibility authority does not match requested coordinates" From ab08349efbe8107a90a8936980159b582f1aae90 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 08:03:23 +0900 Subject: [PATCH 399/603] test(workforce-validation): prove eligibility supersession shape RED --- ...rsession_authority_structural_integrity.py | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority_structural_integrity.py b/services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority_structural_integrity.py new file mode 100644 index 000000000..2123e11dc --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority_structural_integrity.py @@ -0,0 +1,140 @@ +"""Structural-integrity regressions for weight-eligibility supersession evidence.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy + +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.weight_eligibility_supersession_authority import ( + WeightEligibilitySupersessionAuthorityIntegrityError, + WeightEligibilitySupersessionAuthorityRecord, + resolve_weight_eligibility_supersession_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RECEIPT = "weight_eligibility_receipt:11111111-1111-4111-8111-111111111111" +SUCCESSOR = "weight_eligibility_receipt:22222222-2222-4222-8222-222222222222" +OWNER = "released_owner_contract:33333333-3333-4333-8333-333333333333" +RECEIPT_DIGEST = "1" * 64 +SUCCESSOR_DIGEST = "2" * 64 +OWNER_DIGEST = "3" * 64 +OWNER_RELEASED_AT = datetime(2026, 9, 17, 0, 30, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 1, 0, tzinfo=timezone.utc) +CUTOVER = datetime(2026, 9, 18, 1, 0, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "eligibility_receipt_reference", + "eligibility_receipt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_eligibility_receipt_reference", + "successor_eligibility_receipt_digest", + "successor_evidence_version", + "successor_released_at", + } +) + + +class _ReadPort: + """Return configured persisted supersession evidence.""" + + def __init__(self, result: object) -> None: + self.result = result + + def read_weight_eligibility_supersession_authority(self, **_: object) -> object: + """Return the configured owner evidence.""" + return self.result + + +def _record() -> WeightEligibilitySupersessionAuthorityRecord: + """Build one canonical eligibility correction edge.""" + return WeightEligibilitySupersessionAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + eligibility_receipt_reference=RECEIPT, + eligibility_receipt_digest=RECEIPT_DIGEST, + evidence_version=1, + owner_contract_reference=OWNER, + owner_contract_version=1, + owner_contract_digest=OWNER_DIGEST, + owner_contract_released_at=OWNER_RELEASED_AT, + released_at=RELEASED_AT, + superseded_at=CUTOVER, + successor_eligibility_receipt_reference=SUCCESSOR, + successor_eligibility_receipt_digest=SUCCESSOR_DIGEST, + successor_evidence_version=1, + successor_released_at=CUTOVER, + ) + + +def _resolve(result: object) -> object: + """Resolve the predecessor at a valid pre-cutover use instant.""" + return resolve_weight_eligibility_supersession_authority( + principal=ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ), + tenant_record_id=TENANT, + validity_study_id=STUDY, + eligibility_receipt_reference=RECEIPT, + eligibility_receipt_digest=RECEIPT_DIGEST, + evidence_version=1, + owner_contract_reference=OWNER, + owner_contract_version=1, + owner_contract_digest=OWNER_DIGEST, + used_at=RELEASED_AT, + purpose_code="selection_validity_analysis", + policy=PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="weight-eligibility-supersession-read-v1", + resource_kind="weight_eligibility_supersession_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ), + read_port=_ReadPort(result), + ) + + +def test_hidden_trailing_tuple_structure_fails_closed() -> None: + canonical = _record() + forged = tuple.__new__( + WeightEligibilitySupersessionAuthorityRecord, + tuple(canonical) + ("hidden-owner-coordinate",), + ) + + with pytest.raises(WeightEligibilitySupersessionAuthorityIntegrityError): + _resolve(forged) + + +def test_truncated_exact_typed_tuple_maps_to_integrity_error() -> None: + canonical = _record() + forged = tuple.__new__( + WeightEligibilitySupersessionAuthorityRecord, + tuple(canonical)[:-1], + ) + + with pytest.raises(WeightEligibilitySupersessionAuthorityIntegrityError): + _resolve(forged) + + +def test_duplicate_nested_current_field_cannot_be_normalized_away() -> None: + canonical = _record() + raw = list(canonical) + raw[2] = canonical.fields + (("eligibility_receipt_reference", RECEIPT),) + forged = tuple.__new__(WeightEligibilitySupersessionAuthorityRecord, tuple(raw)) + + with pytest.raises(WeightEligibilitySupersessionAuthorityIntegrityError): + _resolve(forged) From 584d2fb87a77d16c8ba2971aef1ce5b019f883ba Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 08:03:56 +0900 Subject: [PATCH 400/603] fix(workforce-validation): canonicalize eligibility supersession evidence --- ...ight_eligibility_supersession_authority.py | 66 +++++++++++-------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_supersession_authority.py index 4c0b0b4da..54218cf82 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_supersession_authority.py @@ -268,7 +268,7 @@ def tenant_record_id(self) -> UUID: @property def validity_study_id(self) -> UUID: - """Return a fresh validity-study identity.""" + """Return a fresh authorized validity-study identity.""" return _restore_operational_uuid("validity_study_id", self[1]) @property @@ -401,32 +401,44 @@ def resolve_weight_eligibility_supersession_authority( "owner port returned non-canonical weight-eligibility supersession evidence" ) - successor_values = None if persisted.successor_fields is None else dict(persisted.successor_fields) - record = WeightEligibilitySupersessionAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - released_at=persisted.released_at, - superseded_at=persisted.superseded_at, - successor_eligibility_receipt_reference=( - None - if successor_values is None - else successor_values["successor_eligibility_receipt_reference"] - ), - successor_eligibility_receipt_digest=( - None - if successor_values is None - else successor_values["successor_eligibility_receipt_digest"] - ), - successor_evidence_version=( - None - if successor_values is None - else successor_values["successor_evidence_version"] - ), - successor_released_at=( - None if successor_values is None else successor_values["successor_released_at"] - ), - **dict(persisted.fields), - ) + try: + successor_values = ( + None if persisted.successor_fields is None else dict(persisted.successor_fields) + ) + record = WeightEligibilitySupersessionAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + successor_eligibility_receipt_reference=( + None + if successor_values is None + else successor_values["successor_eligibility_receipt_reference"] + ), + successor_eligibility_receipt_digest=( + None + if successor_values is None + else successor_values["successor_eligibility_receipt_digest"] + ), + successor_evidence_version=( + None + if successor_values is None + else successor_values["successor_evidence_version"] + ), + successor_released_at=( + None if successor_values is None else successor_values["successor_released_at"] + ), + **dict(persisted.fields), + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise WeightEligibilitySupersessionAuthorityIntegrityError( + "owner port returned structurally invalid weight-eligibility supersession evidence" + ) from exc + if record != persisted: + raise WeightEligibilitySupersessionAuthorityIntegrityError( + "owner port returned non-canonical weight-eligibility supersession structure" + ) + record_values = dict(record.fields) if ( _store_operational_uuid("record tenant_record_id", record.tenant_record_id) From 12268af325603dae40a68e87f9e04a2027434a4e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 08:59:24 +0900 Subject: [PATCH 401/603] test(workforce-validation): RED v1 nonverifiability supersession shape --- ...rsession_authority_structural_integrity.py | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_structural_integrity.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_structural_integrity.py new file mode 100644 index 000000000..0ee3951bb --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_structural_integrity.py @@ -0,0 +1,167 @@ +"""Reject non-canonical exact-typed v1 non-verifiability supersession evidence.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.result_nonverifiability_supersession_authority import ( + ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError, + ValidationResultNonVerifiabilitySupersessionAuthorityRecord, + resolve_validation_result_nonverifiability_supersession_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RESULT_REFERENCE = "validation_analysis_result:11111111-1111-4111-8111-111111111111" +OWNER_CONTRACT_REFERENCE = "released_owner_contract:22222222-2222-4222-8222-222222222222" +ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:33333333-3333-4333-8333-333333333333" +SUCCESSOR_ATTEMPT_REFERENCE = "validation_evidence_verification_attempt:44444444-4444-4444-8444-444444444444" +RESULT_DIGEST = "1" * 64 +OWNER_CONTRACT_DIGEST = "2" * 64 +ATTEMPT_DIGEST = "3" * 64 +SUCCESSOR_ATTEMPT_DIGEST = "4" * 64 +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 9, 1, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 18, 8, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 18, 10, tzinfo=timezone.utc) +CUTOVER = USED_AT + timedelta(hours=1) +READ_FIELDS = frozenset( + { + "result_reference", + "result_digest", + "failed_evidence_kind", + "failure_mode", + "verification_attempt_reference", + "verification_attempt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_target_result_reference", + "successor_target_result_digest", + "successor_failed_evidence_kind", + "successor_verification_attempt_reference", + "successor_verification_attempt_digest", + "successor_verification_attempt_released_at", + } +) + + +class _ReadPort: + """Return one configured object so resolver integrity owns the trust decision.""" + + def __init__(self, record: object) -> None: + self.record = record + + def read_validation_result_nonverifiability_supersession_authority( + self, **_: object + ) -> object: + """Return the configured owner evidence without normalizing its structure.""" + return self.record + + +def _record() -> ValidationResultNonVerifiabilitySupersessionAuthorityRecord: + """Build one canonical predecessor with a later same-obligation successor.""" + return ValidationResultNonVerifiabilitySupersessionAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + failed_evidence_kind="analysis_weight_receipt", + failure_mode="missing", + verification_attempt_reference=ATTEMPT_REFERENCE, + verification_attempt_digest=ATTEMPT_DIGEST, + evidence_version=1, + owner_contract_reference=OWNER_CONTRACT_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_CONTRACT_DIGEST, + owner_contract_released_at=OWNER_CONTRACT_RELEASED_AT, + released_at=RELEASED_AT, + superseded_at=CUTOVER, + successor_target_result_reference=RESULT_REFERENCE, + successor_target_result_digest=RESULT_DIGEST, + successor_failed_evidence_kind="analysis_weight_receipt", + successor_verification_attempt_reference=SUCCESSOR_ATTEMPT_REFERENCE, + successor_verification_attempt_digest=SUCCESSOR_ATTEMPT_DIGEST, + successor_verification_attempt_released_at=CUTOVER, + ) + + +def _resolve(record: object) -> None: + """Resolve through the public owner boundary at a historical use instant.""" + resolve_validation_result_nonverifiability_supersession_authority( + principal=ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ), + tenant_record_id=TENANT, + validity_study_id=STUDY, + result_reference=RESULT_REFERENCE, + result_digest=RESULT_DIGEST, + failed_evidence_kind="analysis_weight_receipt", + failure_mode="missing", + verification_attempt_reference=ATTEMPT_REFERENCE, + verification_attempt_digest=ATTEMPT_DIGEST, + evidence_version=1, + owner_contract_reference=OWNER_CONTRACT_REFERENCE, + owner_contract_version=3, + owner_contract_digest=OWNER_CONTRACT_DIGEST, + used_at=USED_AT, + purpose_code="selection_validity_analysis", + policy=PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="validation-result-nonverifiability-supersession-read-v1", + resource_kind="validation_result_nonverifiability_supersession_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ), + read_port=_ReadPort(record), + ) + + +def test_v1_supersession_rejects_hidden_outer_tuple_member() -> None: + """Do not normalize away an exact-typed hidden coordinate after owner read.""" + canonical = _record() + forged = tuple.__new__( + ValidationResultNonVerifiabilitySupersessionAuthorityRecord, + tuple(canonical) + ("hidden-owner-coordinate",), + ) + + with pytest.raises(ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError): + _resolve(forged) + + +def test_v1_supersession_maps_truncated_tuple_to_integrity_error() -> None: + """Keep malformed exact-typed evidence inside the family integrity boundary.""" + canonical = _record() + forged = tuple.__new__( + ValidationResultNonVerifiabilitySupersessionAuthorityRecord, + tuple(canonical)[:5], + ) + + with pytest.raises(ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError): + _resolve(forged) + + +def test_v1_supersession_rejects_duplicate_nested_current_field() -> None: + """Reject duplicate nested coordinates that dict conversion would erase.""" + canonical = _record() + forged_items = list(canonical) + forged_items[2] = canonical.fields + (("result_reference", RESULT_REFERENCE),) + forged = tuple.__new__( + ValidationResultNonVerifiabilitySupersessionAuthorityRecord, + tuple(forged_items), + ) + + with pytest.raises(ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError): + _resolve(forged) From 23921d8a74193b4e456c3ed989304141b6a91b77 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 09:00:08 +0900 Subject: [PATCH 402/603] fix(workforce-validation): canonicalize v1 nonverifiability supersession reads --- ...nonverifiability_supersession_authority.py | 112 ++++++++++-------- 1 file changed, 61 insertions(+), 51 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py index 3e4c7df08..a976b8bc0 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py @@ -485,57 +485,67 @@ def resolve_validation_result_nonverifiability_supersession_authority( "owner port returned non-canonical non-verifiability supersession evidence" ) - persisted_fields = dict(persisted.fields) - persisted_successor = ( - None if persisted.successor_fields is None else dict(persisted.successor_fields) - ) - record = ValidationResultNonVerifiabilitySupersessionAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - result_reference=persisted_fields["result_reference"], - result_digest=persisted_fields["result_digest"], - failed_evidence_kind=persisted_fields["failed_evidence_kind"], - failure_mode=persisted_fields["failure_mode"], - verification_attempt_reference=persisted_fields["verification_attempt_reference"], - verification_attempt_digest=persisted_fields["verification_attempt_digest"], - evidence_version=persisted_fields["evidence_version"], - owner_contract_reference=persisted_fields["owner_contract_reference"], - owner_contract_version=persisted_fields["owner_contract_version"], - owner_contract_digest=persisted_fields["owner_contract_digest"], - owner_contract_released_at=persisted_fields["owner_contract_released_at"], - released_at=persisted.released_at, - superseded_at=persisted.superseded_at, - successor_target_result_reference=( - None - if persisted_successor is None - else persisted_successor["successor_target_result_reference"] - ), - successor_target_result_digest=( - None - if persisted_successor is None - else persisted_successor["successor_target_result_digest"] - ), - successor_failed_evidence_kind=( - None - if persisted_successor is None - else persisted_successor["successor_failed_evidence_kind"] - ), - successor_verification_attempt_reference=( - None - if persisted_successor is None - else persisted_successor["successor_verification_attempt_reference"] - ), - successor_verification_attempt_digest=( - None - if persisted_successor is None - else persisted_successor["successor_verification_attempt_digest"] - ), - successor_verification_attempt_released_at=( - None - if persisted_successor is None - else persisted_successor["successor_verification_attempt_released_at"] - ), - ) + try: + persisted_fields = dict(persisted.fields) + persisted_successor = ( + None if persisted.successor_fields is None else dict(persisted.successor_fields) + ) + record = ValidationResultNonVerifiabilitySupersessionAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + result_reference=persisted_fields["result_reference"], + result_digest=persisted_fields["result_digest"], + failed_evidence_kind=persisted_fields["failed_evidence_kind"], + failure_mode=persisted_fields["failure_mode"], + verification_attempt_reference=persisted_fields["verification_attempt_reference"], + verification_attempt_digest=persisted_fields["verification_attempt_digest"], + evidence_version=persisted_fields["evidence_version"], + owner_contract_reference=persisted_fields["owner_contract_reference"], + owner_contract_version=persisted_fields["owner_contract_version"], + owner_contract_digest=persisted_fields["owner_contract_digest"], + owner_contract_released_at=persisted_fields["owner_contract_released_at"], + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + successor_target_result_reference=( + None + if persisted_successor is None + else persisted_successor["successor_target_result_reference"] + ), + successor_target_result_digest=( + None + if persisted_successor is None + else persisted_successor["successor_target_result_digest"] + ), + successor_failed_evidence_kind=( + None + if persisted_successor is None + else persisted_successor["successor_failed_evidence_kind"] + ), + successor_verification_attempt_reference=( + None + if persisted_successor is None + else persisted_successor["successor_verification_attempt_reference"] + ), + successor_verification_attempt_digest=( + None + if persisted_successor is None + else persisted_successor["successor_verification_attempt_digest"] + ), + successor_verification_attempt_released_at=( + None + if persisted_successor is None + else persisted_successor["successor_verification_attempt_released_at"] + ), + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError( + "owner port returned structurally invalid non-verifiability supersession evidence" + ) from exc + if record != persisted: + raise ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError( + "owner port returned non-canonical non-verifiability supersession structure" + ) + record_values = dict(record.fields) requested_values = { "evidence_version": version, From 32136fc746505db30a9e4f3a4b1e7c72ed0356ab Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 10:04:46 +0900 Subject: [PATCH 403/603] test(workforce-validation): reproduce calibration authority shape forgery --- ...justment_authority_structural_integrity.py | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_adjustment_authority_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_authority_structural_integrity.py b/services/workforce-validation-api/tests/test_calibration_adjustment_authority_structural_integrity.py new file mode 100644 index 000000000..d2f7d5a25 --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_authority_structural_integrity.py @@ -0,0 +1,33 @@ +"""Structural-integrity regressions for calibration-adjustment owner evidence.""" + +from __future__ import annotations + +import pytest + +from orgmetra_workforce_validation_api.calibration_adjustment_authority import ( + CalibrationAdjustmentAuthorityIntegrityError, + CalibrationAdjustmentAuthorityRecord, +) +from test_calibration_adjustment_authority import _ReadPort, _record, _resolve + + +def test_hidden_trailing_tuple_structure_fails_closed() -> None: + canonical = _record() + forged = tuple.__new__( + CalibrationAdjustmentAuthorityRecord, + tuple(canonical) + ("hidden-owner-coordinate",), + ) + + with pytest.raises(CalibrationAdjustmentAuthorityIntegrityError): + _resolve(read_port=_ReadPort(forged)) + + +def test_truncated_exact_typed_tuple_maps_to_integrity_error() -> None: + canonical = _record() + forged = tuple.__new__( + CalibrationAdjustmentAuthorityRecord, + tuple(canonical)[:-1], + ) + + with pytest.raises(CalibrationAdjustmentAuthorityIntegrityError): + _resolve(read_port=_ReadPort(forged)) From e5480ecbb32e3ae6ee8483d2e0553502f47bed1f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 10:06:58 +0900 Subject: [PATCH 404/603] fix(workforce-validation): reject forged calibration authority records --- .../calibration_adjustment_authority.py | 107 ++++++++++-------- 1 file changed, 58 insertions(+), 49 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py index 78a7c09e2..58f4b4a7e 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py @@ -942,55 +942,64 @@ def resolve_calibration_adjustment_authority( "owner port returned non-canonical calibration-adjustment authority evidence" ) - record = CalibrationAdjustmentAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - calibration_receipt_reference=persisted.calibration_receipt_reference, - calibration_receipt_digest=persisted.calibration_receipt_digest, - evidence_version=persisted.evidence_version, - target_population_digest=persisted.target_population_digest, - analysis_window_reference=persisted.analysis_window_reference, - auxiliary_authority_reference=persisted.auxiliary_authority_reference, - auxiliary_projection_reference=persisted.auxiliary_projection_reference, - auxiliary_projection_version=persisted.auxiliary_projection_version, - auxiliary_projection_digest=persisted.auxiliary_projection_digest, - auxiliary_purpose_reference=persisted.auxiliary_purpose_reference, - auxiliary_purpose_digest=persisted.auxiliary_purpose_digest, - auxiliary_owner_contract_reference=persisted.auxiliary_owner_contract_reference, - auxiliary_owner_contract_version=persisted.auxiliary_owner_contract_version, - auxiliary_owner_contract_digest=persisted.auxiliary_owner_contract_digest, - auxiliary_authorization_receipt_reference=persisted.auxiliary_authorization_receipt_reference, - auxiliary_authorization_receipt_digest=persisted.auxiliary_authorization_receipt_digest, - auxiliary_scientific_use_receipt_reference=persisted.auxiliary_scientific_use_receipt_reference, - auxiliary_scientific_use_receipt_digest=persisted.auxiliary_scientific_use_receipt_digest, - auxiliary_scientific_use_at=persisted.auxiliary_scientific_use_at, - benchmark_receipt_reference=persisted.benchmark_receipt_reference, - benchmark_receipt_version=persisted.benchmark_receipt_version, - benchmark_receipt_digest=persisted.benchmark_receipt_digest, - benchmark_owner_contract_reference=persisted.benchmark_owner_contract_reference, - benchmark_owner_contract_version=persisted.benchmark_owner_contract_version, - benchmark_owner_contract_digest=persisted.benchmark_owner_contract_digest, - benchmark_reference_at=persisted.benchmark_reference_at, - algorithm_reference=persisted.algorithm_reference, - algorithm_version=persisted.algorithm_version, - constraints_digest=persisted.constraints_digest, - termination_code=persisted.termination_code, - input_weight_artifact_digest=persisted.input_weight_artifact_digest, - output_weight_artifact_digest=persisted.output_weight_artifact_digest, - constructed_at=persisted.constructed_at, - fallback_reason_code=persisted.fallback_reason_code, - fallback_rule_reference=persisted.fallback_rule_reference, - fallback_rule_digest=persisted.fallback_rule_digest, - fallback_algorithm_reference=persisted.fallback_algorithm_reference, - fallback_algorithm_version=persisted.fallback_algorithm_version, - fallback_configuration_digest=persisted.fallback_configuration_digest, - owner_contract_reference=persisted.owner_contract_reference, - owner_contract_version=persisted.owner_contract_version, - owner_contract_digest=persisted.owner_contract_digest, - owner_contract_released_at=persisted.owner_contract_released_at, - released_at=persisted.released_at, - superseded_at=persisted.superseded_at, - ) + try: + record = CalibrationAdjustmentAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + calibration_receipt_reference=persisted.calibration_receipt_reference, + calibration_receipt_digest=persisted.calibration_receipt_digest, + evidence_version=persisted.evidence_version, + target_population_digest=persisted.target_population_digest, + analysis_window_reference=persisted.analysis_window_reference, + auxiliary_authority_reference=persisted.auxiliary_authority_reference, + auxiliary_projection_reference=persisted.auxiliary_projection_reference, + auxiliary_projection_version=persisted.auxiliary_projection_version, + auxiliary_projection_digest=persisted.auxiliary_projection_digest, + auxiliary_purpose_reference=persisted.auxiliary_purpose_reference, + auxiliary_purpose_digest=persisted.auxiliary_purpose_digest, + auxiliary_owner_contract_reference=persisted.auxiliary_owner_contract_reference, + auxiliary_owner_contract_version=persisted.auxiliary_owner_contract_version, + auxiliary_owner_contract_digest=persisted.auxiliary_owner_contract_digest, + auxiliary_authorization_receipt_reference=persisted.auxiliary_authorization_receipt_reference, + auxiliary_authorization_receipt_digest=persisted.auxiliary_authorization_receipt_digest, + auxiliary_scientific_use_receipt_reference=persisted.auxiliary_scientific_use_receipt_reference, + auxiliary_scientific_use_receipt_digest=persisted.auxiliary_scientific_use_receipt_digest, + auxiliary_scientific_use_at=persisted.auxiliary_scientific_use_at, + benchmark_receipt_reference=persisted.benchmark_receipt_reference, + benchmark_receipt_version=persisted.benchmark_receipt_version, + benchmark_receipt_digest=persisted.benchmark_receipt_digest, + benchmark_owner_contract_reference=persisted.benchmark_owner_contract_reference, + benchmark_owner_contract_version=persisted.benchmark_owner_contract_version, + benchmark_owner_contract_digest=persisted.benchmark_owner_contract_digest, + benchmark_reference_at=persisted.benchmark_reference_at, + algorithm_reference=persisted.algorithm_reference, + algorithm_version=persisted.algorithm_version, + constraints_digest=persisted.constraints_digest, + termination_code=persisted.termination_code, + input_weight_artifact_digest=persisted.input_weight_artifact_digest, + output_weight_artifact_digest=persisted.output_weight_artifact_digest, + constructed_at=persisted.constructed_at, + fallback_reason_code=persisted.fallback_reason_code, + fallback_rule_reference=persisted.fallback_rule_reference, + fallback_rule_digest=persisted.fallback_rule_digest, + fallback_algorithm_reference=persisted.fallback_algorithm_reference, + fallback_algorithm_version=persisted.fallback_algorithm_version, + fallback_configuration_digest=persisted.fallback_configuration_digest, + owner_contract_reference=persisted.owner_contract_reference, + owner_contract_version=persisted.owner_contract_version, + owner_contract_digest=persisted.owner_contract_digest, + owner_contract_released_at=persisted.owner_contract_released_at, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise CalibrationAdjustmentAuthorityIntegrityError( + "owner port returned malformed calibration-adjustment authority evidence" + ) from exc + if record != persisted: + raise CalibrationAdjustmentAuthorityIntegrityError( + "owner port returned non-canonical calibration-adjustment authority evidence" + ) if _coordinate_tuple(record) != _coordinate_tuple(requested): raise CalibrationAdjustmentAuthorityIntegrityError( "released calibration-adjustment authority does not match requested coordinates" From c34b2ee249fbc8eee9c9758ccb71c3c49cd2d9c4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 11:02:56 +0900 Subject: [PATCH 405/603] test(workforce-validation): expose calibration auxiliary structural forgery --- ...uxiliary_authority_structural_integrity.py | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_auxiliary_authority_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority_structural_integrity.py b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority_structural_integrity.py new file mode 100644 index 000000000..cfac62e3a --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority_structural_integrity.py @@ -0,0 +1,141 @@ +"""Structural-integrity regressions for calibration auxiliary owner evidence.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy + +from orgmetra_workforce_validation_api import ValidationPrincipal +import orgmetra_workforce_validation_api.scientific_authority as target +from orgmetra_workforce_validation_api.scientific_authority import ( + CalibrationAuxiliaryAuthorityIntegrityError, + CalibrationAuxiliaryAuthorityRecord, + resolve_calibration_auxiliary_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000c1") +OWNER_CONTRACT_RELEASED_AT = datetime(2026, 8, 31, tzinfo=timezone.utc) +AUTHORIZATION_RECEIPT_RELEASED_AT = datetime(2026, 8, 31, 12, tzinfo=timezone.utc) +AUTHORIZED_FROM = datetime(2026, 9, 1, tzinfo=timezone.utc) +AUTHORIZED_TO = datetime(2026, 10, 1, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, tzinfo=timezone.utc) + + +class _ReadPort: + """Return configured persisted evidence through the auxiliary owner capability.""" + + def __init__(self, result: object) -> None: + self.result = result + + def read_calibration_auxiliary_authority(self, **_: object) -> object: + """Return the configured owner evidence.""" + return self.result + + +def _record() -> CalibrationAuxiliaryAuthorityRecord: + return CalibrationAuxiliaryAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + authority_reference=( + "scientific_auxiliary_authority:11111111-1111-4111-8111-111111111111" + ), + auxiliary_projection_reference=( + "calibration_auxiliary_projection:22222222-2222-4222-8222-222222222222" + ), + auxiliary_projection_version=4, + auxiliary_projection_digest="1" * 64, + scientific_purpose_reference=( + "scientific_data_use_purpose:33333333-3333-4333-8333-333333333333" + ), + scientific_purpose_digest="2" * 64, + owner_contract_reference=( + "released_owner_contract:44444444-4444-4444-8444-444444444444" + ), + owner_contract_version=7, + owner_contract_digest="3" * 64, + owner_contract_released_at=OWNER_CONTRACT_RELEASED_AT, + authorization_receipt_reference=( + "scientific_data_authorization:55555555-5555-4555-8555-555555555555" + ), + authorization_receipt_digest="4" * 64, + authorization_receipt_released_at=AUTHORIZATION_RECEIPT_RELEASED_AT, + scientific_use_receipt_reference=( + "scientific_use_receipt:66666666-6666-4666-8666-666666666666" + ), + scientific_use_receipt_digest="5" * 64, + scientific_use_at=USED_AT, + authorized_from=AUTHORIZED_FROM, + authorized_to=AUTHORIZED_TO, + ) + + +def _resolve(result: object) -> object: + return resolve_calibration_auxiliary_authority( + principal=ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ), + tenant_record_id=TENANT, + validity_study_id=STUDY, + authority_reference=( + "scientific_auxiliary_authority:11111111-1111-4111-8111-111111111111" + ), + auxiliary_projection_reference=( + "calibration_auxiliary_projection:22222222-2222-4222-8222-222222222222" + ), + auxiliary_projection_version=4, + auxiliary_projection_digest="1" * 64, + scientific_purpose_reference=( + "scientific_data_use_purpose:33333333-3333-4333-8333-333333333333" + ), + scientific_purpose_digest="2" * 64, + owner_contract_reference=( + "released_owner_contract:44444444-4444-4444-8444-444444444444" + ), + owner_contract_version=7, + owner_contract_digest="3" * 64, + authorization_receipt_reference=( + "scientific_data_authorization:55555555-5555-4555-8555-555555555555" + ), + authorization_receipt_digest="4" * 64, + scientific_use_receipt_reference=( + "scientific_use_receipt:66666666-6666-4666-8666-666666666666" + ), + scientific_use_receipt_digest="5" * 64, + used_at=USED_AT, + purpose_code="selection_validity_analysis", + policy=PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="calibration-authority-read-v1", + resource_kind="calibration_auxiliary_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=target._READ_FIELDS, + ), + read_port=_ReadPort(result), + ) + + +def test_hidden_trailing_tuple_structure_fails_closed() -> None: + canonical = _record() + forged = tuple.__new__( + CalibrationAuxiliaryAuthorityRecord, + tuple(canonical) + ("hidden-owner-coordinate",), + ) + + with pytest.raises(CalibrationAuxiliaryAuthorityIntegrityError): + _resolve(forged) + + +def test_truncated_exact_typed_tuple_maps_to_integrity_error() -> None: + canonical = _record() + forged = tuple.__new__(CalibrationAuxiliaryAuthorityRecord, tuple(canonical)[:-1]) + + with pytest.raises(CalibrationAuxiliaryAuthorityIntegrityError): + _resolve(forged) From f9d1cf3cd6ce806964d05414e824e19b701e133c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 11:04:10 +0900 Subject: [PATCH 406/603] fix(workforce-validation): canonicalize calibration auxiliary owner evidence --- .../scientific_authority.py | 53 +++++++++++-------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py index 09eb42dbb..c62120f52 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py @@ -545,28 +545,37 @@ def resolve_calibration_auxiliary_authority( "owner port returned non-canonical calibration auxiliary authority evidence" ) - record = CalibrationAuxiliaryAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - authority_reference=persisted.authority_reference, - auxiliary_projection_reference=persisted.auxiliary_projection_reference, - auxiliary_projection_version=persisted.auxiliary_projection_version, - auxiliary_projection_digest=persisted.auxiliary_projection_digest, - scientific_purpose_reference=persisted.scientific_purpose_reference, - scientific_purpose_digest=persisted.scientific_purpose_digest, - owner_contract_reference=persisted.owner_contract_reference, - owner_contract_version=persisted.owner_contract_version, - owner_contract_digest=persisted.owner_contract_digest, - owner_contract_released_at=persisted.owner_contract_released_at, - authorization_receipt_reference=persisted.authorization_receipt_reference, - authorization_receipt_digest=persisted.authorization_receipt_digest, - authorization_receipt_released_at=persisted.authorization_receipt_released_at, - scientific_use_receipt_reference=persisted.scientific_use_receipt_reference, - scientific_use_receipt_digest=persisted.scientific_use_receipt_digest, - scientific_use_at=persisted.scientific_use_at, - authorized_from=persisted.authorized_from, - authorized_to=persisted.authorized_to, - ) + try: + record = CalibrationAuxiliaryAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + authority_reference=persisted.authority_reference, + auxiliary_projection_reference=persisted.auxiliary_projection_reference, + auxiliary_projection_version=persisted.auxiliary_projection_version, + auxiliary_projection_digest=persisted.auxiliary_projection_digest, + scientific_purpose_reference=persisted.scientific_purpose_reference, + scientific_purpose_digest=persisted.scientific_purpose_digest, + owner_contract_reference=persisted.owner_contract_reference, + owner_contract_version=persisted.owner_contract_version, + owner_contract_digest=persisted.owner_contract_digest, + owner_contract_released_at=persisted.owner_contract_released_at, + authorization_receipt_reference=persisted.authorization_receipt_reference, + authorization_receipt_digest=persisted.authorization_receipt_digest, + authorization_receipt_released_at=persisted.authorization_receipt_released_at, + scientific_use_receipt_reference=persisted.scientific_use_receipt_reference, + scientific_use_receipt_digest=persisted.scientific_use_receipt_digest, + scientific_use_at=persisted.scientific_use_at, + authorized_from=persisted.authorized_from, + authorized_to=persisted.authorized_to, + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise CalibrationAuxiliaryAuthorityIntegrityError( + "owner port returned malformed calibration auxiliary authority evidence" + ) from exc + if record != persisted: + raise CalibrationAuxiliaryAuthorityIntegrityError( + "owner port returned non-canonical calibration auxiliary authority evidence" + ) if ( _store_operational_uuid("record tenant_record_id", record.tenant_record_id) != tenant_identity From c07c46fb962cf8c31b61a2aa994b88b69010fe79 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 11:06:40 +0900 Subject: [PATCH 407/603] test(workforce-validation): expose final-weight structural forgery --- ...s_weight_authority_structural_integrity.py | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_analysis_weight_authority_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_final_analysis_weight_authority_structural_integrity.py b/services/workforce-validation-api/tests/test_final_analysis_weight_authority_structural_integrity.py new file mode 100644 index 000000000..270b35d8b --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_analysis_weight_authority_structural_integrity.py @@ -0,0 +1,173 @@ +"""Structural-integrity regressions for final analysis-weight owner evidence.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy + +from orgmetra_workforce_validation_api import ValidationPrincipal +import orgmetra_workforce_validation_api.final_weight_authority as target +from orgmetra_workforce_validation_api.final_weight_authority import ( + FinalAnalysisWeightAuthorityIntegrityError, + FinalAnalysisWeightAuthorityRecord, + FinalWeightAdjustmentCoordinate, + resolve_final_analysis_weight_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") +CONSTRUCTED_AT = datetime(2026, 9, 17, 8, 0, tzinfo=timezone.utc) +OWNER_RELEASED_AT = datetime(2026, 9, 17, 8, 10, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 8, 30, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 9, 0, tzinfo=timezone.utc) + + +class _ReadPort: + """Return configured persisted evidence through the final-weight owner capability.""" + + def __init__(self, result: object) -> None: + self.result = result + + def read_final_analysis_weight_authority(self, **_: object) -> object: + """Return the configured owner evidence.""" + return self.result + + +def _adjustment() -> FinalWeightAdjustmentCoordinate: + return FinalWeightAdjustmentCoordinate( + sequence_number=1, + adjustment_code="nonresponse_adjustment", + method_reference="weight_method:nonresponse-cell-adjustment", + method_version=2, + input_weight_artifact_digest="a" * 64, + output_weight_artifact_digest="b" * 64, + configuration_digest="c" * 64, + evidence_receipt_digest="d" * 64, + evidence_kind="nonresponse_adjustment_receipt", + ) + + +def _record() -> FinalAnalysisWeightAuthorityRecord: + return FinalAnalysisWeightAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + analysis_weight_receipt_reference=( + "analysis_weight_receipt:11111111-1111-4111-8111-111111111111" + ), + analysis_weight_receipt_digest="1" * 64, + evidence_version=1, + estimand_reference="validation_estimand:criterion-validity-q3", + estimand_digest="2" * 64, + estimand_scope_code="longitudinal", + target_population_reference="analysis_target_population:workers-2026q3", + target_population_digest="3" * 64, + analysis_unit_code="person_occurrence", + analysis_window_reference="analysis_window:2026q3", + reference_duration_reference="analysis_reference_duration:2026q3", + reference_duration_digest="4" * 64, + eligible_case_set_digest="5" * 64, + analytic_case_occurrence_set_digest="6" * 64, + source_universe_receipt_reference=( + "source_universe_receipt:22222222-2222-4222-8222-222222222222" + ), + source_universe_receipt_version=4, + source_universe_receipt_digest="7" * 64, + sampling_design_receipt_reference=( + "sampling_design_receipt:33333333-3333-4333-8333-333333333333" + ), + sampling_design_receipt_version=3, + sampling_design_receipt_digest="8" * 64, + base_weight_method_code="inverse_inclusion_probability", + base_weight_method_version=1, + base_weight_evidence_digest="9" * 64, + base_weight_artifact_digest="a" * 64, + adjustments=(_adjustment(),), + final_weight_artifact_digest="b" * 64, + weight_eligibility_receipt_reference=( + "weight_eligibility_receipt:44444444-4444-4444-8444-444444444444" + ), + weight_eligibility_receipt_digest="e" * 64, + analytic_case_count=1200, + constructed_at=CONSTRUCTED_AT, + correction_sequence=1, + supersedes_receipt_digest=None, + owner_contract_reference=( + "released_owner_contract:55555555-5555-4555-8555-555555555555" + ), + owner_contract_version=7, + owner_contract_digest="f" * 64, + owner_contract_released_at=OWNER_RELEASED_AT, + released_at=RELEASED_AT, + superseded_at=None, + ) + + +def _resolve(result: object) -> object: + values = dict(_record().fields) + values.update( + { + "principal": ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="final-analysis-weight-authority-read-v1", + resource_kind="final_analysis_weight_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=target._READ_FIELDS, + ), + "read_port": _ReadPort(result), + } + ) + return resolve_final_analysis_weight_authority(**values) + + +def test_hidden_trailing_tuple_structure_fails_closed() -> None: + canonical = _record() + forged = tuple.__new__( + FinalAnalysisWeightAuthorityRecord, + tuple(canonical) + ("hidden-owner-coordinate",), + ) + + with pytest.raises(FinalAnalysisWeightAuthorityIntegrityError): + _resolve(forged) + + +def test_truncated_exact_typed_tuple_maps_to_integrity_error() -> None: + canonical = _record() + forged = tuple.__new__(FinalAnalysisWeightAuthorityRecord, tuple(canonical)[:-1]) + + with pytest.raises(FinalAnalysisWeightAuthorityIntegrityError): + _resolve(forged) + + +def test_duplicate_nested_field_cannot_be_normalized_away() -> None: + canonical = _record() + duplicate_fields = canonical.fields + ( + ("owner_contract_reference", dict(canonical.fields)["owner_contract_reference"]), + ) + forged = tuple.__new__( + FinalAnalysisWeightAuthorityRecord, + ( + canonical[0], + canonical[1], + duplicate_fields, + canonical[3], + canonical[4], + canonical[5], + ), + ) + + with pytest.raises(FinalAnalysisWeightAuthorityIntegrityError): + _resolve(forged) From e9635151b16f62ee7f23c76c632c8d612e2c1249 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 11:07:51 +0900 Subject: [PATCH 408/603] fix(workforce-validation): canonicalize final-weight owner evidence --- .../final_weight_authority.py | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py index 568210678..63b37a29f 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py @@ -786,14 +786,23 @@ def resolve_final_analysis_weight_authority( "owner port returned non-canonical final analysis-weight authority evidence" ) - record = FinalAnalysisWeightAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - owner_contract_released_at=persisted.owner_contract_released_at, - released_at=persisted.released_at, - superseded_at=persisted.superseded_at, - **dict(persisted.fields), - ) + try: + record = FinalAnalysisWeightAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + owner_contract_released_at=persisted.owner_contract_released_at, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + **dict(persisted.fields), + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise FinalAnalysisWeightAuthorityIntegrityError( + "owner port returned malformed final analysis-weight authority evidence" + ) from exc + if record != persisted: + raise FinalAnalysisWeightAuthorityIntegrityError( + "owner port returned non-canonical final analysis-weight authority evidence" + ) if ( _store_operational_uuid("record tenant_record_id", record.tenant_record_id) != _store_operational_uuid("requested tenant_record_id", requested.tenant_record_id) From 057f19e71caf5eb92172bdc9390366fd1fc71cdc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 12:02:19 +0900 Subject: [PATCH 409/603] test(workforce-validation): expose final-weight supersession tuple forgery --- ...rsession_authority_structural_integrity.py | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_supersession_authority_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_final_weight_supersession_authority_structural_integrity.py b/services/workforce-validation-api/tests/test_final_weight_supersession_authority_structural_integrity.py new file mode 100644 index 000000000..3cf0e3198 --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_supersession_authority_structural_integrity.py @@ -0,0 +1,143 @@ +"""Structural-integrity regressions for final-weight supersession evidence.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy + +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.final_weight_supersession_authority import ( + FinalWeightSupersessionAuthorityIntegrityError, + FinalWeightSupersessionAuthorityRecord, + resolve_final_weight_supersession_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RECEIPT = "analysis_weight_receipt:11111111-1111-4111-8111-111111111111" +SUCCESSOR = "analysis_weight_receipt:33333333-3333-4333-8333-333333333333" +OWNER = "released_owner_contract:22222222-2222-4222-8222-222222222222" +RECEIPT_DIGEST = "1" * 64 +SUCCESSOR_DIGEST = "3" * 64 +OWNER_DIGEST = "2" * 64 +OWNER_RELEASED_AT = datetime(2026, 7, 1, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 7, 15, tzinfo=timezone.utc) +CUTOVER = RELEASED_AT + timedelta(days=30) +READ_FIELDS = frozenset( + { + "analysis_weight_receipt_reference", + "analysis_weight_receipt_digest", + "evidence_version", + "correction_sequence", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_analysis_weight_receipt_reference", + "successor_correction_sequence", + "successor_analysis_weight_receipt_digest", + "successor_released_at", + } +) + + +class _ReadPort: + """Return configured persisted supersession evidence.""" + + def __init__(self, result: object) -> None: + self.result = result + + def read_final_weight_supersession_authority(self, **_: object) -> object: + """Return the configured owner evidence.""" + return self.result + + +def _record() -> FinalWeightSupersessionAuthorityRecord: + """Build one canonical final-weight correction edge.""" + return FinalWeightSupersessionAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + analysis_weight_receipt_reference=RECEIPT, + analysis_weight_receipt_digest=RECEIPT_DIGEST, + evidence_version=1, + correction_sequence=2, + owner_contract_reference=OWNER, + owner_contract_version=3, + owner_contract_digest=OWNER_DIGEST, + owner_contract_released_at=OWNER_RELEASED_AT, + released_at=RELEASED_AT, + superseded_at=CUTOVER, + successor_analysis_weight_receipt_reference=SUCCESSOR, + successor_correction_sequence=3, + successor_analysis_weight_receipt_digest=SUCCESSOR_DIGEST, + successor_released_at=CUTOVER, + ) + + +def _resolve(result: object) -> object: + """Resolve the predecessor at a valid pre-cutover use instant.""" + return resolve_final_weight_supersession_authority( + principal=ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ), + tenant_record_id=TENANT, + validity_study_id=STUDY, + analysis_weight_receipt_reference=RECEIPT, + analysis_weight_receipt_digest=RECEIPT_DIGEST, + evidence_version=1, + correction_sequence=2, + owner_contract_reference=OWNER, + owner_contract_version=3, + owner_contract_digest=OWNER_DIGEST, + used_at=RELEASED_AT, + purpose_code="selection_validity_analysis", + policy=PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="final-weight-supersession-authority-read-v1", + resource_kind="final_weight_supersession_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ), + read_port=_ReadPort(result), + ) + + +def test_hidden_trailing_tuple_structure_fails_closed() -> None: + canonical = _record() + forged = tuple.__new__( + FinalWeightSupersessionAuthorityRecord, + tuple(canonical) + ("hidden-owner-coordinate",), + ) + + with pytest.raises(FinalWeightSupersessionAuthorityIntegrityError): + _resolve(forged) + + +def test_truncated_exact_typed_tuple_maps_to_integrity_error() -> None: + canonical = _record() + forged = tuple.__new__( + FinalWeightSupersessionAuthorityRecord, + tuple(canonical)[:-1], + ) + + with pytest.raises(FinalWeightSupersessionAuthorityIntegrityError): + _resolve(forged) + + +def test_duplicate_nested_current_field_cannot_be_normalized_away() -> None: + canonical = _record() + raw = list(canonical) + raw[2] = canonical.fields + (("analysis_weight_receipt_reference", RECEIPT),) + forged = tuple.__new__(FinalWeightSupersessionAuthorityRecord, tuple(raw)) + + with pytest.raises(FinalWeightSupersessionAuthorityIntegrityError): + _resolve(forged) From fe437d8bd1cb3f86a8ddd68854ea586536d028fb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 12:03:06 +0900 Subject: [PATCH 410/603] fix(workforce-validation): reject non-canonical final-weight supersession records --- .../final_weight_supersession_authority.py | 69 ++++++++++--------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py index c73ac568a..e39545870 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py @@ -413,37 +413,44 @@ def resolve_final_weight_supersession_authority( "owner port returned non-canonical final-weight supersession evidence" ) - record = FinalWeightSupersessionAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - released_at=persisted.released_at, - superseded_at=persisted.superseded_at, - successor_analysis_weight_receipt_reference=( - None - if persisted.successor_fields is None - else dict(persisted.successor_fields)[ - "successor_analysis_weight_receipt_reference" - ] - ), - successor_correction_sequence=( - None - if persisted.successor_fields is None - else dict(persisted.successor_fields)["successor_correction_sequence"] - ), - successor_analysis_weight_receipt_digest=( - None - if persisted.successor_fields is None - else dict(persisted.successor_fields)[ - "successor_analysis_weight_receipt_digest" - ] - ), - successor_released_at=( - None - if persisted.successor_fields is None - else dict(persisted.successor_fields)["successor_released_at"] - ), - **dict(persisted.fields), - ) + try: + successor_values = ( + None if persisted.successor_fields is None else dict(persisted.successor_fields) + ) + record = FinalWeightSupersessionAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + successor_analysis_weight_receipt_reference=( + None + if successor_values is None + else successor_values["successor_analysis_weight_receipt_reference"] + ), + successor_correction_sequence=( + None + if successor_values is None + else successor_values["successor_correction_sequence"] + ), + successor_analysis_weight_receipt_digest=( + None + if successor_values is None + else successor_values["successor_analysis_weight_receipt_digest"] + ), + successor_released_at=( + None if successor_values is None else successor_values["successor_released_at"] + ), + **dict(persisted.fields), + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise FinalWeightSupersessionAuthorityIntegrityError( + "owner port returned structurally invalid final-weight supersession evidence" + ) from exc + if record != persisted: + raise FinalWeightSupersessionAuthorityIntegrityError( + "owner port returned non-canonical final-weight supersession structure" + ) + record_values = dict(record.fields) if ( _store_operational_uuid("record tenant_record_id", record.tenant_record_id) From aa5fbc2dc25bca39d0d945cedc36713fd47d401b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 13:02:43 +0900 Subject: [PATCH 411/603] test(workforce-validation): expose nonresponse owner shape forgery --- ...justment_authority_structural_integrity.py | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_structural_integrity.py b/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_structural_integrity.py new file mode 100644 index 000000000..5124cf557 --- /dev/null +++ b/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_structural_integrity.py @@ -0,0 +1,33 @@ +"""Structural-integrity regressions for nonresponse-adjustment owner evidence.""" + +from __future__ import annotations + +import pytest + +from orgmetra_workforce_validation_api.nonresponse_adjustment_authority import ( + NonresponseAdjustmentAuthorityIntegrityError, + NonresponseAdjustmentAuthorityRecord, +) +from test_nonresponse_adjustment_authority import _ReadPort, _record, _resolve + + +def test_hidden_trailing_tuple_structure_fails_closed() -> None: + canonical = _record() + forged = tuple.__new__( + NonresponseAdjustmentAuthorityRecord, + tuple(canonical) + ("hidden-owner-coordinate",), + ) + + with pytest.raises(NonresponseAdjustmentAuthorityIntegrityError): + _resolve(read_port=_ReadPort(forged)) + + +def test_truncated_exact_typed_tuple_maps_to_integrity_error() -> None: + canonical = _record() + forged = tuple.__new__( + NonresponseAdjustmentAuthorityRecord, + tuple(canonical)[:-1], + ) + + with pytest.raises(NonresponseAdjustmentAuthorityIntegrityError): + _resolve(read_port=_ReadPort(forged)) From 550f29e5f697592b4b27320708f3f210c383187e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 13:03:47 +0900 Subject: [PATCH 412/603] fix(workforce-validation): canonicalize nonresponse owner evidence --- .../nonresponse_adjustment_authority.py | 63 +++++++++++-------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py index 14575c359..f348f2959 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py @@ -558,33 +558,42 @@ def resolve_nonresponse_adjustment_authority( "owner port returned non-canonical nonresponse-adjustment authority evidence" ) - record = NonresponseAdjustmentAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - nonresponse_receipt_reference=persisted.nonresponse_receipt_reference, - nonresponse_receipt_digest=persisted.nonresponse_receipt_digest, - evidence_version=persisted.evidence_version, - response_disposition_receipt_reference=persisted.response_disposition_receipt_reference, - response_disposition_receipt_version=persisted.response_disposition_receipt_version, - response_disposition_receipt_digest=persisted.response_disposition_receipt_digest, - response_disposition_receipt_released_at=persisted.response_disposition_receipt_released_at, - adjustment_population_digest=persisted.adjustment_population_digest, - method_reference=persisted.method_reference, - method_version=persisted.method_version, - configuration_digest=persisted.configuration_digest, - ineligible_treatment_code=persisted.ineligible_treatment_code, - unknown_treatment_code=persisted.unknown_treatment_code, - unavailable_treatment_code=persisted.unavailable_treatment_code, - input_weight_artifact_digest=persisted.input_weight_artifact_digest, - output_weight_artifact_digest=persisted.output_weight_artifact_digest, - constructed_at=persisted.constructed_at, - owner_contract_reference=persisted.owner_contract_reference, - owner_contract_version=persisted.owner_contract_version, - owner_contract_digest=persisted.owner_contract_digest, - owner_contract_released_at=persisted.owner_contract_released_at, - released_at=persisted.released_at, - superseded_at=persisted.superseded_at, - ) + try: + record = NonresponseAdjustmentAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + nonresponse_receipt_reference=persisted.nonresponse_receipt_reference, + nonresponse_receipt_digest=persisted.nonresponse_receipt_digest, + evidence_version=persisted.evidence_version, + response_disposition_receipt_reference=persisted.response_disposition_receipt_reference, + response_disposition_receipt_version=persisted.response_disposition_receipt_version, + response_disposition_receipt_digest=persisted.response_disposition_receipt_digest, + response_disposition_receipt_released_at=persisted.response_disposition_receipt_released_at, + adjustment_population_digest=persisted.adjustment_population_digest, + method_reference=persisted.method_reference, + method_version=persisted.method_version, + configuration_digest=persisted.configuration_digest, + ineligible_treatment_code=persisted.ineligible_treatment_code, + unknown_treatment_code=persisted.unknown_treatment_code, + unavailable_treatment_code=persisted.unavailable_treatment_code, + input_weight_artifact_digest=persisted.input_weight_artifact_digest, + output_weight_artifact_digest=persisted.output_weight_artifact_digest, + constructed_at=persisted.constructed_at, + owner_contract_reference=persisted.owner_contract_reference, + owner_contract_version=persisted.owner_contract_version, + owner_contract_digest=persisted.owner_contract_digest, + owner_contract_released_at=persisted.owner_contract_released_at, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise NonresponseAdjustmentAuthorityIntegrityError( + "owner port returned malformed nonresponse-adjustment authority evidence" + ) from exc + if record != persisted: + raise NonresponseAdjustmentAuthorityIntegrityError( + "owner port returned non-canonical nonresponse-adjustment authority evidence" + ) if _coordinate_tuple(record) != _coordinate_tuple(requested): raise NonresponseAdjustmentAuthorityIntegrityError( "released nonresponse-adjustment authority does not match requested coordinates" From e4b946ee213c486878a3e68c56d6b5c43acb6a2d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 13:06:59 +0900 Subject: [PATCH 413/603] test(workforce-validation): expose nonresponse supersession shape forgery --- ...rsession_authority_structural_integrity.py | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_authority_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_authority_structural_integrity.py b/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_authority_structural_integrity.py new file mode 100644 index 000000000..0aa6d53de --- /dev/null +++ b/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_authority_structural_integrity.py @@ -0,0 +1,140 @@ +"""Structural-integrity regressions for nonresponse-adjustment supersession evidence.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy + +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.nonresponse_adjustment_supersession_authority import ( + NonresponseAdjustmentSupersessionAuthorityIntegrityError, + NonresponseAdjustmentSupersessionAuthorityRecord, + resolve_nonresponse_adjustment_supersession_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +RECEIPT = "nonresponse_adjustment_receipt:11111111-1111-4111-8111-111111111111" +SUCCESSOR = "nonresponse_adjustment_receipt:22222222-2222-4222-8222-222222222222" +OWNER = "released_owner_contract:33333333-3333-4333-8333-333333333333" +RECEIPT_DIGEST = "1" * 64 +SUCCESSOR_DIGEST = "2" * 64 +OWNER_DIGEST = "3" * 64 +OWNER_RELEASED_AT = datetime(2026, 9, 17, 0, 30, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 1, 0, tzinfo=timezone.utc) +CUTOVER = datetime(2026, 9, 18, 1, 0, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "nonresponse_receipt_reference", + "nonresponse_receipt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_nonresponse_receipt_reference", + "successor_nonresponse_receipt_digest", + "successor_evidence_version", + "successor_released_at", + } +) + + +class _ReadPort: + """Return configured persisted supersession evidence.""" + + def __init__(self, result: object) -> None: + self.result = result + + def read_nonresponse_adjustment_supersession_authority(self, **_: object) -> object: + """Return the configured owner evidence.""" + return self.result + + +def _record() -> NonresponseAdjustmentSupersessionAuthorityRecord: + """Build one canonical nonresponse correction edge.""" + return NonresponseAdjustmentSupersessionAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + nonresponse_receipt_reference=RECEIPT, + nonresponse_receipt_digest=RECEIPT_DIGEST, + evidence_version=1, + owner_contract_reference=OWNER, + owner_contract_version=1, + owner_contract_digest=OWNER_DIGEST, + owner_contract_released_at=OWNER_RELEASED_AT, + released_at=RELEASED_AT, + superseded_at=CUTOVER, + successor_nonresponse_receipt_reference=SUCCESSOR, + successor_nonresponse_receipt_digest=SUCCESSOR_DIGEST, + successor_evidence_version=1, + successor_released_at=CUTOVER, + ) + + +def _resolve(result: object) -> object: + """Resolve the predecessor at a valid pre-cutover use instant.""" + return resolve_nonresponse_adjustment_supersession_authority( + principal=ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ), + tenant_record_id=TENANT, + validity_study_id=STUDY, + nonresponse_receipt_reference=RECEIPT, + nonresponse_receipt_digest=RECEIPT_DIGEST, + evidence_version=1, + owner_contract_reference=OWNER, + owner_contract_version=1, + owner_contract_digest=OWNER_DIGEST, + used_at=RELEASED_AT, + purpose_code="selection_validity_analysis", + policy=PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="nonresponse-adjustment-supersession-read-v1", + resource_kind="nonresponse_adjustment_supersession_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ), + read_port=_ReadPort(result), + ) + + +def test_hidden_trailing_tuple_structure_fails_closed() -> None: + canonical = _record() + forged = tuple.__new__( + NonresponseAdjustmentSupersessionAuthorityRecord, + tuple(canonical) + ("hidden-owner-coordinate",), + ) + + with pytest.raises(NonresponseAdjustmentSupersessionAuthorityIntegrityError): + _resolve(forged) + + +def test_truncated_exact_typed_tuple_maps_to_integrity_error() -> None: + canonical = _record() + forged = tuple.__new__( + NonresponseAdjustmentSupersessionAuthorityRecord, + tuple(canonical)[:-1], + ) + + with pytest.raises(NonresponseAdjustmentSupersessionAuthorityIntegrityError): + _resolve(forged) + + +def test_duplicate_nested_current_field_cannot_be_normalized_away() -> None: + canonical = _record() + raw = list(canonical) + raw[2] = canonical.fields + (("nonresponse_receipt_reference", RECEIPT),) + forged = tuple.__new__(NonresponseAdjustmentSupersessionAuthorityRecord, tuple(raw)) + + with pytest.raises(NonresponseAdjustmentSupersessionAuthorityIntegrityError): + _resolve(forged) From 5c043318d83770c5ebd76ca4217a76457701554e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 13:07:37 +0900 Subject: [PATCH 414/603] fix(workforce-validation): canonicalize nonresponse supersession evidence --- ...ponse_adjustment_supersession_authority.py | 66 +++++++++++-------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_supersession_authority.py index 551ffc0be..e9cb4022d 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_supersession_authority.py @@ -389,34 +389,44 @@ def resolve_nonresponse_adjustment_supersession_authority( "owner port returned non-canonical nonresponse supersession evidence" ) - successor_values = ( - None if persisted.successor_fields is None else dict(persisted.successor_fields) - ) - record = NonresponseAdjustmentSupersessionAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - released_at=persisted.released_at, - superseded_at=persisted.superseded_at, - successor_nonresponse_receipt_reference=( - None - if successor_values is None - else successor_values["successor_nonresponse_receipt_reference"] - ), - successor_nonresponse_receipt_digest=( - None - if successor_values is None - else successor_values["successor_nonresponse_receipt_digest"] - ), - successor_evidence_version=( - None - if successor_values is None - else successor_values["successor_evidence_version"] - ), - successor_released_at=( - None if successor_values is None else successor_values["successor_released_at"] - ), - **dict(persisted.fields), - ) + try: + successor_values = ( + None if persisted.successor_fields is None else dict(persisted.successor_fields) + ) + record = NonresponseAdjustmentSupersessionAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + successor_nonresponse_receipt_reference=( + None + if successor_values is None + else successor_values["successor_nonresponse_receipt_reference"] + ), + successor_nonresponse_receipt_digest=( + None + if successor_values is None + else successor_values["successor_nonresponse_receipt_digest"] + ), + successor_evidence_version=( + None + if successor_values is None + else successor_values["successor_evidence_version"] + ), + successor_released_at=( + None if successor_values is None else successor_values["successor_released_at"] + ), + **dict(persisted.fields), + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise NonresponseAdjustmentSupersessionAuthorityIntegrityError( + "owner port returned malformed nonresponse supersession evidence" + ) from exc + if record != persisted: + raise NonresponseAdjustmentSupersessionAuthorityIntegrityError( + "owner port returned non-canonical nonresponse supersession evidence" + ) + record_values = dict(record.fields) if ( _store_operational_uuid("record tenant_record_id", record.tenant_record_id) From 0f42141948b0ed9d584a5bac745a5be3e2f72b32 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 13:10:45 +0900 Subject: [PATCH 415/603] test(workforce-validation): expose registry record shape forgery --- ...st_registry_record_structural_integrity.py | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_registry_record_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_registry_record_structural_integrity.py b/services/workforce-validation-api/tests/test_registry_record_structural_integrity.py new file mode 100644 index 000000000..d7f50e93a --- /dev/null +++ b/services/workforce-validation-api/tests/test_registry_record_structural_integrity.py @@ -0,0 +1,44 @@ +"""Structural-integrity regressions for persisted validity-study records.""" + +from __future__ import annotations + +import pytest + +from orgmetra_workforce_validation_api.registry import ( + ValidityStudyIntegrityError, + ValidityStudyRecord, + read_validity_study, +) +from test_registry import STUDY, TENANT, _ReadPort, _policy, _principal, _record + + +def _resolve(result: object) -> object: + """Resolve one requested field through the canonical registry boundary.""" + return read_validity_study( + principal=_principal(), + tenant_record_id=TENANT, + validity_study_id=STUDY, + purpose_code="validation_review", + requested_fields=frozenset({"study_status_code"}), + policy=_policy(), + read_port=_ReadPort(result), + ) + + +def test_hidden_trailing_tuple_structure_fails_closed() -> None: + canonical = _record() + forged = tuple.__new__( + ValidityStudyRecord, + tuple(canonical) + ("hidden-persistence-coordinate",), + ) + + with pytest.raises(ValidityStudyIntegrityError): + _resolve(forged) + + +def test_truncated_exact_typed_tuple_maps_to_integrity_error() -> None: + canonical = _record() + forged = tuple.__new__(ValidityStudyRecord, tuple(canonical)[:-1]) + + with pytest.raises(ValidityStudyIntegrityError): + _resolve(forged) From 34b2cc271e615e287809c5c8b9dce5e54d0cd831 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 13:11:37 +0900 Subject: [PATCH 416/603] fix(workforce-validation): canonicalize persisted registry records --- .../registry.py | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py index 10159e1d8..ef3374f96 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -418,14 +418,23 @@ def read_validity_study( if type(persisted) is not ValidityStudyRecord: raise ValidityStudyIntegrityError("repository returned a non-canonical validity-study record") - record = ValidityStudyRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - criterion_blueprint_id=persisted.criterion_blueprint_id, - study_status_code=persisted.study_status_code, - recorded_from=persisted.recorded_from, - recorded_to=persisted.recorded_to, - ) + try: + record = ValidityStudyRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + criterion_blueprint_id=persisted.criterion_blueprint_id, + study_status_code=persisted.study_status_code, + recorded_from=persisted.recorded_from, + recorded_to=persisted.recorded_to, + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise ValidityStudyIntegrityError( + "repository returned a structurally invalid validity-study record" + ) from exc + if record != persisted: + raise ValidityStudyIntegrityError( + "repository returned a non-canonical validity-study record" + ) if ( _store_operational_uuid("record tenant_record_id", record.tenant_record_id) != tenant_identity From b6639f1f8ab99ee01d96053c5dc2b30ea40baa88 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 13:11:44 +0900 Subject: [PATCH 417/603] test(workforce-validation): expose trimming owner shape forgery --- ...bounding_authority_structural_integrity.py | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_trimming_bounding_authority_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_trimming_bounding_authority_structural_integrity.py b/services/workforce-validation-api/tests/test_trimming_bounding_authority_structural_integrity.py new file mode 100644 index 000000000..422251fdf --- /dev/null +++ b/services/workforce-validation-api/tests/test_trimming_bounding_authority_structural_integrity.py @@ -0,0 +1,33 @@ +"""Structural-integrity regressions for trimming/bounding owner evidence.""" + +from __future__ import annotations + +import pytest + +from orgmetra_workforce_validation_api.trimming_bounding_authority import ( + TrimmingBoundingAuthorityIntegrityError, + TrimmingBoundingAuthorityRecord, +) +from test_trimming_bounding_authority import _ReadPort, _record, _resolve + + +def test_hidden_trailing_tuple_structure_fails_closed() -> None: + canonical = _record() + forged = tuple.__new__( + TrimmingBoundingAuthorityRecord, + tuple(canonical) + ("hidden-owner-coordinate",), + ) + + with pytest.raises(TrimmingBoundingAuthorityIntegrityError): + _resolve(read_port=_ReadPort(forged)) + + +def test_truncated_exact_typed_tuple_maps_to_integrity_error() -> None: + canonical = _record() + forged = tuple.__new__( + TrimmingBoundingAuthorityRecord, + tuple(canonical)[:-1], + ) + + with pytest.raises(TrimmingBoundingAuthorityIntegrityError): + _resolve(read_port=_ReadPort(forged)) From 7c76e7b89c3f4051a540cb2b1af73472f2445a98 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 13:12:25 +0900 Subject: [PATCH 418/603] fix(workforce-validation): canonicalize trimming owner evidence --- .../trimming_bounding_authority.py | 51 +++++++++++-------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py index cbf125e9c..898b9e1ab 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py @@ -462,27 +462,36 @@ def resolve_trimming_bounding_authority( "owner port returned non-canonical trimming/bounding authority evidence" ) - record = TrimmingBoundingAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - adjustment_receipt_reference=persisted.adjustment_receipt_reference, - adjustment_receipt_digest=persisted.adjustment_receipt_digest, - evidence_version=persisted.evidence_version, - rule_reference=persisted.rule_reference, - rule_version=persisted.rule_version, - rule_configuration_digest=persisted.rule_configuration_digest, - affected_case_occurrence_set_digest=persisted.affected_case_occurrence_set_digest, - affected_case_count=persisted.affected_case_count, - input_weight_artifact_digest=persisted.input_weight_artifact_digest, - output_weight_artifact_digest=persisted.output_weight_artifact_digest, - constructed_at=persisted.constructed_at, - owner_contract_reference=persisted.owner_contract_reference, - owner_contract_version=persisted.owner_contract_version, - owner_contract_digest=persisted.owner_contract_digest, - owner_contract_released_at=persisted.owner_contract_released_at, - released_at=persisted.released_at, - superseded_at=persisted.superseded_at, - ) + try: + record = TrimmingBoundingAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + adjustment_receipt_reference=persisted.adjustment_receipt_reference, + adjustment_receipt_digest=persisted.adjustment_receipt_digest, + evidence_version=persisted.evidence_version, + rule_reference=persisted.rule_reference, + rule_version=persisted.rule_version, + rule_configuration_digest=persisted.rule_configuration_digest, + affected_case_occurrence_set_digest=persisted.affected_case_occurrence_set_digest, + affected_case_count=persisted.affected_case_count, + input_weight_artifact_digest=persisted.input_weight_artifact_digest, + output_weight_artifact_digest=persisted.output_weight_artifact_digest, + constructed_at=persisted.constructed_at, + owner_contract_reference=persisted.owner_contract_reference, + owner_contract_version=persisted.owner_contract_version, + owner_contract_digest=persisted.owner_contract_digest, + owner_contract_released_at=persisted.owner_contract_released_at, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise TrimmingBoundingAuthorityIntegrityError( + "owner port returned malformed trimming/bounding authority evidence" + ) from exc + if record != persisted: + raise TrimmingBoundingAuthorityIntegrityError( + "owner port returned non-canonical trimming/bounding authority evidence" + ) if _coordinate_tuple(record) != _coordinate_tuple(requested): raise TrimmingBoundingAuthorityIntegrityError( "released trimming/bounding authority does not match requested coordinates" From fb44ad49be394a6e096e5653be565ec9ba5dbdeb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 13:12:45 +0900 Subject: [PATCH 419/603] test(workforce-validation): expose trimming supersession shape forgery --- ...rsession_authority_structural_integrity.py | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_trimming_bounding_supersession_authority_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_trimming_bounding_supersession_authority_structural_integrity.py b/services/workforce-validation-api/tests/test_trimming_bounding_supersession_authority_structural_integrity.py new file mode 100644 index 000000000..0564c56e9 --- /dev/null +++ b/services/workforce-validation-api/tests/test_trimming_bounding_supersession_authority_structural_integrity.py @@ -0,0 +1,109 @@ +"""Structural-integrity regressions for trimming/bounding supersession evidence.""" + +from __future__ import annotations + +import pytest +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy + +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.trimming_bounding_supersession_authority import ( + TrimmingBoundingSupersessionAuthorityIntegrityError, + TrimmingBoundingSupersessionAuthorityRecord, + resolve_trimming_bounding_supersession_authority, +) +from test_trimming_bounding_supersession_contract import _record + +READ_FIELDS = frozenset( + { + "adjustment_receipt_reference", + "adjustment_receipt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_adjustment_receipt_reference", + "successor_adjustment_receipt_digest", + "successor_evidence_version", + "successor_released_at", + } +) + + +class _ReadPort: + """Return configured persisted trimming supersession evidence.""" + + def __init__(self, result: object) -> None: + self.result = result + + def read_trimming_bounding_supersession_authority(self, **_: object) -> object: + """Return configured owner evidence.""" + return self.result + + +def _resolve(canonical: TrimmingBoundingSupersessionAuthorityRecord, result: object) -> object: + """Resolve the predecessor at a valid pre-cutover use instant.""" + values = dict(canonical.fields) + return resolve_trimming_bounding_supersession_authority( + principal=ValidationPrincipal( + tenant_record_id=canonical.tenant_record_id, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ), + tenant_record_id=canonical.tenant_record_id, + validity_study_id=canonical.validity_study_id, + adjustment_receipt_reference=values["adjustment_receipt_reference"], + adjustment_receipt_digest=values["adjustment_receipt_digest"], + evidence_version=values["evidence_version"], + owner_contract_reference=values["owner_contract_reference"], + owner_contract_version=values["owner_contract_version"], + owner_contract_digest=values["owner_contract_digest"], + used_at=canonical.released_at, + purpose_code="selection_validity_analysis", + policy=PurposeBoundAccessPolicy( + tenant_record_id=canonical.tenant_record_id, + policy_version_code="trimming-bounding-supersession-read-v1", + resource_kind="trimming_bounding_supersession_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ), + read_port=_ReadPort(result), + ) + + +def test_hidden_trailing_tuple_structure_fails_closed() -> None: + canonical = _record() + forged = tuple.__new__( + TrimmingBoundingSupersessionAuthorityRecord, + tuple(canonical) + ("hidden-owner-coordinate",), + ) + + with pytest.raises(TrimmingBoundingSupersessionAuthorityIntegrityError): + _resolve(canonical, forged) + + +def test_truncated_exact_typed_tuple_maps_to_integrity_error() -> None: + canonical = _record() + forged = tuple.__new__( + TrimmingBoundingSupersessionAuthorityRecord, + tuple(canonical)[:-1], + ) + + with pytest.raises(TrimmingBoundingSupersessionAuthorityIntegrityError): + _resolve(canonical, forged) + + +def test_duplicate_nested_current_field_cannot_be_normalized_away() -> None: + canonical = _record() + raw = list(canonical) + raw[2] = canonical.fields + ( + ("adjustment_receipt_reference", dict(canonical.fields)["adjustment_receipt_reference"]), + ) + forged = tuple.__new__(TrimmingBoundingSupersessionAuthorityRecord, tuple(raw)) + + with pytest.raises(TrimmingBoundingSupersessionAuthorityIntegrityError): + _resolve(canonical, forged) From 84f2ee27f0ea07a8170824d76435953fea1bf85c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 13:14:25 +0900 Subject: [PATCH 420/603] fix(workforce-validation): canonicalize trimming supersession evidence --- ...rimming_bounding_supersession_authority.py | 65 +++++++++++-------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_supersession_authority.py index f1bfcecd4..8f9f5e02b 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_supersession_authority.py @@ -388,34 +388,43 @@ def resolve_trimming_bounding_supersession_authority( "owner port returned non-canonical trimming supersession evidence" ) - successor_values = ( - None if persisted.successor_fields is None else dict(persisted.successor_fields) - ) - record = TrimmingBoundingSupersessionAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - released_at=persisted.released_at, - superseded_at=persisted.superseded_at, - successor_adjustment_receipt_reference=( - None - if successor_values is None - else successor_values["successor_adjustment_receipt_reference"] - ), - successor_adjustment_receipt_digest=( - None - if successor_values is None - else successor_values["successor_adjustment_receipt_digest"] - ), - successor_evidence_version=( - None - if successor_values is None - else successor_values["successor_evidence_version"] - ), - successor_released_at=( - None if successor_values is None else successor_values["successor_released_at"] - ), - **dict(persisted.fields), - ) + try: + successor_values = ( + None if persisted.successor_fields is None else dict(persisted.successor_fields) + ) + record = TrimmingBoundingSupersessionAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + successor_adjustment_receipt_reference=( + None + if successor_values is None + else successor_values["successor_adjustment_receipt_reference"] + ), + successor_adjustment_receipt_digest=( + None + if successor_values is None + else successor_values["successor_adjustment_receipt_digest"] + ), + successor_evidence_version=( + None + if successor_values is None + else successor_values["successor_evidence_version"] + ), + successor_released_at=( + None if successor_values is None else successor_values["successor_released_at"] + ), + **dict(persisted.fields), + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise TrimmingBoundingSupersessionAuthorityIntegrityError( + "owner port returned malformed trimming supersession evidence" + ) from exc + if record != persisted: + raise TrimmingBoundingSupersessionAuthorityIntegrityError( + "owner port returned non-canonical trimming supersession evidence" + ) record_values = dict(record.fields) if ( _store_operational_uuid("record tenant_record_id", record.tenant_record_id) From 67e33aa93b46192a3706c3adf775edbbd230e45d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 13:14:42 +0900 Subject: [PATCH 421/603] test(workforce-validation): expose variance owner shape forgery --- ...variance_authority_structural_integrity.py | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_variance_authority_structural_integrity.py diff --git a/services/workforce-validation-api/tests/test_weight_variance_authority_structural_integrity.py b/services/workforce-validation-api/tests/test_weight_variance_authority_structural_integrity.py new file mode 100644 index 000000000..9cecc82de --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_variance_authority_structural_integrity.py @@ -0,0 +1,33 @@ +"""Structural-integrity regressions for point-weight/variance owner evidence.""" + +from __future__ import annotations + +import pytest + +from orgmetra_workforce_validation_api.variance_authority import ( + WeightVarianceAuthorityIntegrityError, + WeightVarianceAuthorityRecord, +) +from test_weight_variance_authority import _ReadPort, _record, _resolve + + +def test_hidden_trailing_tuple_structure_fails_closed() -> None: + canonical = _record() + forged = tuple.__new__( + WeightVarianceAuthorityRecord, + tuple(canonical) + ("hidden-owner-coordinate",), + ) + + with pytest.raises(WeightVarianceAuthorityIntegrityError): + _resolve(read_port=_ReadPort(forged)) + + +def test_truncated_exact_typed_tuple_maps_to_integrity_error() -> None: + canonical = _record() + forged = tuple.__new__( + WeightVarianceAuthorityRecord, + tuple(canonical)[:-1], + ) + + with pytest.raises(WeightVarianceAuthorityIntegrityError): + _resolve(read_port=_ReadPort(forged)) From 203da7a1051eb3282a98e69e732023f579325413 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 13:15:47 +0900 Subject: [PATCH 422/603] fix(workforce-validation): canonicalize variance owner evidence --- .../variance_authority.py | 63 +++++++++++-------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py index f8f5b7520..c1e2e737c 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py @@ -580,32 +580,41 @@ def resolve_weight_variance_authority( "owner port returned non-canonical point-weight/variance authority evidence" ) - record = WeightVarianceAuthorityRecord( - tenant_record_id=persisted.tenant_record_id, - validity_study_id=persisted.validity_study_id, - authority_reference=persisted.authority_reference, - sampling_receipt_reference=persisted.sampling_receipt_reference, - sampling_receipt_version=persisted.sampling_receipt_version, - sampling_receipt_digest=persisted.sampling_receipt_digest, - analysis_weight_receipt_digest=persisted.analysis_weight_receipt_digest, - analytic_case_occurrence_set_digest=persisted.analytic_case_occurrence_set_digest, - weight_eligibility_receipt_digest=persisted.weight_eligibility_receipt_digest, - weight_correction_sequence=persisted.weight_correction_sequence, - final_weight_artifact_digest=persisted.final_weight_artifact_digest, - variance_design_receipt_reference=persisted.variance_design_receipt_reference, - variance_design_receipt_version=persisted.variance_design_receipt_version, - variance_design_receipt_digest=persisted.variance_design_receipt_digest, - variance_method_reference=persisted.variance_method_reference, - variance_method_version=persisted.variance_method_version, - variance_evidence_mode=persisted.variance_evidence_mode, - variance_semantics=persisted.variance_semantics, - owner_contract_reference=persisted.owner_contract_reference, - owner_contract_version=persisted.owner_contract_version, - owner_contract_digest=persisted.owner_contract_digest, - owner_contract_released_at=persisted.owner_contract_released_at, - released_at=persisted.released_at, - superseded_at=persisted.superseded_at, - ) + try: + record = WeightVarianceAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + authority_reference=persisted.authority_reference, + sampling_receipt_reference=persisted.sampling_receipt_reference, + sampling_receipt_version=persisted.sampling_receipt_version, + sampling_receipt_digest=persisted.sampling_receipt_digest, + analysis_weight_receipt_digest=persisted.analysis_weight_receipt_digest, + analytic_case_occurrence_set_digest=persisted.analytic_case_occurrence_set_digest, + weight_eligibility_receipt_digest=persisted.weight_eligibility_receipt_digest, + weight_correction_sequence=persisted.weight_correction_sequence, + final_weight_artifact_digest=persisted.final_weight_artifact_digest, + variance_design_receipt_reference=persisted.variance_design_receipt_reference, + variance_design_receipt_version=persisted.variance_design_receipt_version, + variance_design_receipt_digest=persisted.variance_design_receipt_digest, + variance_method_reference=persisted.variance_method_reference, + variance_method_version=persisted.variance_method_version, + variance_evidence_mode=persisted.variance_evidence_mode, + variance_semantics=persisted.variance_semantics, + owner_contract_reference=persisted.owner_contract_reference, + owner_contract_version=persisted.owner_contract_version, + owner_contract_digest=persisted.owner_contract_digest, + owner_contract_released_at=persisted.owner_contract_released_at, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise WeightVarianceAuthorityIntegrityError( + "owner port returned malformed point-weight/variance authority evidence" + ) from exc + if record != persisted: + raise WeightVarianceAuthorityIntegrityError( + "owner port returned non-canonical point-weight/variance authority evidence" + ) if ( _store_operational_uuid("record tenant_record_id", record.tenant_record_id) != tenant_identity @@ -666,4 +675,4 @@ def resolve_weight_variance_authority( "superseded_at": record.superseded_at, } fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) - return tuple.__new__(WeightVarianceAuthorityView, (tenant_identity, study_identity, fields)) \ No newline at end of file + return tuple.__new__(WeightVarianceAuthorityView, (tenant_identity, study_identity, fields)) From afb7422e3fdd1d29d4230563032cdccd63f920d6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 14:09:07 +0900 Subject: [PATCH 423/603] test(workforce-validation): require exact final-weight component receipt binding --- ...inal_weight_component_binding_authority.py | 315 ++++++++++++++++++ 1 file changed, 315 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_component_binding_authority.py diff --git a/services/workforce-validation-api/tests/test_final_weight_component_binding_authority.py b/services/workforce-validation-api/tests/test_final_weight_component_binding_authority.py new file mode 100644 index 000000000..90b8a2cc7 --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_component_binding_authority.py @@ -0,0 +1,315 @@ +"""Contracts for exact typed-component resolution behind final analysis weights.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy + +from orgmetra_workforce_validation_api import ValidationPrincipal +import orgmetra_workforce_validation_api.final_weight_component_binding_authority as target +from orgmetra_workforce_validation_api.final_weight_component_binding_authority import ( + FinalWeightAdjustmentEvidenceBinding, + FinalWeightComponentBindingAuthorityIntegrityError, + FinalWeightComponentBindingAuthorityNotFound, + FinalWeightComponentBindingAuthorityReadPort, + FinalWeightComponentBindingAuthorityRecord, + FinalWeightComponentBindingAuthorityView, + resolve_final_weight_component_binding_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") +OWNER_RELEASED_AT = datetime(2026, 9, 19, 4, 0, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 19, 4, 10, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 19, 4, 30, tzinfo=timezone.utc) + + +class _ReadPort: + """Return configured owner evidence and retain the deterministic lookup key.""" + + def __init__(self, result: object) -> None: + self.result = result + self.calls: list[dict[str, object]] = [] + + def read_final_weight_component_binding_authority(self, **kwargs: object) -> object: + """Return configured evidence after recording caller-known lookup coordinates.""" + self.calls.append(kwargs) + return self.result + + +def _principal() -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=TENANT, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy() -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="final-weight-component-binding-read-v1", + resource_kind="final_weight_component_binding_authority", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=target._READ_FIELDS, + ) + + +def _binding( + *, + sequence_number: int = 1, + evidence_kind: str = "nonresponse_adjustment_receipt", + evidence_receipt_reference: str = ( + "nonresponse_adjustment_receipt:11111111-1111-4111-8111-111111111111" + ), + evidence_version: int = 1, + evidence_receipt_digest: str = "a" * 64, +) -> FinalWeightAdjustmentEvidenceBinding: + return FinalWeightAdjustmentEvidenceBinding( + sequence_number=sequence_number, + evidence_kind=evidence_kind, + evidence_receipt_reference=evidence_receipt_reference, + evidence_version=evidence_version, + evidence_receipt_digest=evidence_receipt_digest, + ) + + +def _record(**overrides: object) -> FinalWeightComponentBindingAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "analysis_weight_receipt_reference": ( + "analysis_weight_receipt:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" + ), + "analysis_weight_receipt_digest": "1" * 64, + "analysis_weight_evidence_version": 1, + "binding_reference": ( + "final_weight_component_binding:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" + ), + "binding_digest": "2" * 64, + "binding_version": 1, + "base_weight_evidence_receipt_reference": ( + "base_weight_evidence_receipt:cccccccc-cccc-4ccc-8ccc-cccccccccccc" + ), + "base_weight_evidence_receipt_digest": "3" * 64, + "base_weight_evidence_version": 1, + "adjustment_bindings": (_binding(),), + "owner_contract_reference": ( + "released_owner_contract:dddddddd-dddd-4ddd-8ddd-dddddddddddd" + ), + "owner_contract_version": 1, + "owner_contract_digest": "4" * 64, + "owner_contract_released_at": OWNER_RELEASED_AT, + "released_at": RELEASED_AT, + "superseded_at": None, + } + values.update(overrides) + return FinalWeightComponentBindingAuthorityRecord(**values) + + +def _resolve( + result: object, + *, + used_at: datetime = USED_AT, + read_port: _ReadPort | None = None, + **overrides: object, +) -> tuple[object, _ReadPort]: + port = _ReadPort(result) if read_port is None else read_port + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "analysis_weight_receipt_reference": ( + "analysis_weight_receipt:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" + ), + "analysis_weight_receipt_digest": "1" * 64, + "analysis_weight_evidence_version": 1, + "used_at": used_at, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": port, + } + values.update(overrides) + return resolve_final_weight_component_binding_authority(**values), port + + +def test_resolver_returns_exact_component_locator_and_uses_final_receipt_key_only() -> None: + record = _record() + view, port = _resolve(record) + + fields = dict(view.fields) + assert fields["base_weight_evidence_receipt_reference"] == ( + "base_weight_evidence_receipt:cccccccc-cccc-4ccc-8ccc-cccccccccccc" + ) + bindings = fields["adjustment_bindings"] + assert type(bindings) is tuple + assert bindings[0].evidence_receipt_reference == ( + "nonresponse_adjustment_receipt:11111111-1111-4111-8111-111111111111" + ) + assert port.calls == [ + { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "analysis_weight_receipt_reference": ( + "analysis_weight_receipt:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" + ), + "analysis_weight_receipt_digest": "1" * 64, + "analysis_weight_evidence_version": 1, + } + ] + + +def test_binding_sequence_may_skip_generic_adjustments_but_must_increase() -> None: + bindings = ( + _binding(), + _binding( + sequence_number=3, + evidence_kind="trimming_bounding_adjustment_receipt", + evidence_receipt_reference=( + "trimming_bounding_adjustment_receipt:22222222-2222-4222-8222-222222222222" + ), + evidence_receipt_digest="b" * 64, + ), + ) + record = _record(adjustment_bindings=bindings) + assert dict(record.fields)["adjustment_bindings"] == bindings + + with pytest.raises(ValueError, match="strictly increasing"): + _record(adjustment_bindings=(bindings[1], bindings[0])) + + +@pytest.mark.parametrize( + ("overrides", "message"), + [ + ({"analysis_weight_evidence_version": 2}, "analysis_weight_evidence_version"), + ({"binding_version": 2}, "binding_version"), + ({"base_weight_evidence_version": 2}, "base_weight_evidence_version"), + ({"adjustment_bindings": [_binding()]}, "immutable tuple"), + ( + {"owner_contract_released_at": RELEASED_AT + timedelta(seconds=1)}, + "owner contract", + ), + ( + {"superseded_at": RELEASED_AT}, + "superseded_at", + ), + ], +) +def test_record_rejects_noncanonical_contract_shapes( + overrides: dict[str, object], message: str +) -> None: + with pytest.raises(ValueError, match=message): + _record(**overrides) + + +@pytest.mark.parametrize( + ("kind", "reference"), + [ + ( + "unknown_adjustment_receipt", + "nonresponse_adjustment_receipt:11111111-1111-4111-8111-111111111111", + ), + ( + "calibration_adjustment_receipt", + "nonresponse_adjustment_receipt:11111111-1111-4111-8111-111111111111", + ), + ], +) +def test_adjustment_binding_rejects_unknown_kind_or_wrong_receipt_namespace( + kind: str, reference: str +) -> None: + with pytest.raises(ValueError): + _binding(evidence_kind=kind, evidence_receipt_reference=reference) + + +def test_adjustment_binding_rejects_non_v1_evidence() -> None: + with pytest.raises(ValueError, match="evidence_version"): + _binding(evidence_version=2) + + +def test_forged_nested_binding_cannot_hide_trailing_state() -> None: + canonical = _binding() + forged = tuple.__new__( + FinalWeightAdjustmentEvidenceBinding, + tuple(canonical) + ("hidden-component-coordinate",), + ) + with pytest.raises(ValueError, match="canonical"): + _record(adjustment_bindings=(forged,)) + + +def test_forged_outer_record_maps_to_integrity_error() -> None: + canonical = _record() + forged = tuple.__new__( + FinalWeightComponentBindingAuthorityRecord, + tuple(canonical) + ("hidden-owner-coordinate",), + ) + with pytest.raises(FinalWeightComponentBindingAuthorityIntegrityError): + _resolve(forged) + + +def test_truncated_outer_record_maps_to_integrity_error() -> None: + canonical = _record() + forged = tuple.__new__( + FinalWeightComponentBindingAuthorityRecord, + tuple(canonical)[:-1], + ) + with pytest.raises(FinalWeightComponentBindingAuthorityIntegrityError): + _resolve(forged) + + +def test_wrong_target_and_authority_interval_fail_closed() -> None: + with pytest.raises(FinalWeightComponentBindingAuthorityIntegrityError, match="target"): + _resolve(_record(tenant_record_id=OTHER_TENANT)) + with pytest.raises(FinalWeightComponentBindingAuthorityIntegrityError, match="before"): + _resolve(_record(), used_at=RELEASED_AT - timedelta(microseconds=1)) + cutover = USED_AT + with pytest.raises(FinalWeightComponentBindingAuthorityIntegrityError, match="supersession"): + _resolve(_record(superseded_at=cutover), used_at=cutover) + + +def test_not_found_and_noncanonical_owner_types_fail_closed() -> None: + with pytest.raises(FinalWeightComponentBindingAuthorityNotFound): + _resolve(None) + with pytest.raises(FinalWeightComponentBindingAuthorityIntegrityError, match="non-canonical"): + _resolve(object()) + + +def test_principal_policy_and_protocol_placeholder_are_not_accepted() -> None: + with pytest.raises(TypeError, match="principal"): + _resolve(_record(), principal=object()) + with pytest.raises(TypeError, match="policy"): + _resolve(_record(), policy=object()) + + class _ProtocolOnly(FinalWeightComponentBindingAuthorityReadPort): + pass + + with pytest.raises(TypeError, match="statically callable"): + resolve_final_weight_component_binding_authority( + principal=_principal(), + tenant_record_id=TENANT, + validity_study_id=STUDY, + analysis_weight_receipt_reference=( + "analysis_weight_receipt:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" + ), + analysis_weight_receipt_digest="1" * 64, + analysis_weight_evidence_version=1, + used_at=USED_AT, + purpose_code="selection_validity_analysis", + policy=_policy(), + read_port=_ProtocolOnly(), + ) + + +def test_public_view_constructor_is_non_issuing() -> None: + with pytest.raises(TypeError, match="issued only"): + FinalWeightComponentBindingAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) From 77f89d26fc0b297d3f7ae131b6e3ac3dd353cbf6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 14:09:56 +0900 Subject: [PATCH 424/603] feat(workforce-validation): add deterministic final-weight component binding authority --- ...inal_weight_component_binding_authority.py | 488 ++++++++++++++++++ 1 file changed, 488 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_binding_authority.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_binding_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_binding_authority.py new file mode 100644 index 000000000..606010d88 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_binding_authority.py @@ -0,0 +1,488 @@ +"""Resolve exact typed component receipts behind one released final analysis weight. + +The v1 final-weight receipt already commits component evidence digests, but a +digest alone is not an owner-record locator. This companion authority maps one +immutable final-weight receipt identity to the exact released base-weight and +specialized adjustment receipts needed for deterministic reproduction. It does +not copy row-level weights or foreign application-table values. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + +from .registry import ( + ValidationPrincipal, + _detach_policy, + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + +_RESOURCE_KIND = "final_weight_component_binding_authority" +_OPERATION = "read" +_EVIDENCE_REFERENCE_NAMESPACE_BY_KIND = { + "nonresponse_adjustment_receipt": "nonresponse_adjustment_receipt", + "calibration_adjustment_receipt": "calibration_adjustment_receipt", + "trimming_bounding_adjustment_receipt": "trimming_bounding_adjustment_receipt", +} +_READ_FIELDS = frozenset( + { + "analysis_weight_receipt_reference", + "analysis_weight_receipt_digest", + "analysis_weight_evidence_version", + "binding_reference", + "binding_digest", + "binding_version", + "base_weight_evidence_receipt_reference", + "base_weight_evidence_receipt_digest", + "base_weight_evidence_version", + "adjustment_bindings", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + } +) + + +class FinalWeightComponentBindingAuthorityNotFound(LookupError): + """Indicate that no released component locator exists for the final-weight receipt.""" + + +class FinalWeightComponentBindingAuthorityIntegrityError(RuntimeError): + """Indicate that component-binding owner evidence is malformed or targets another receipt.""" + + +class FinalWeightAdjustmentEvidenceBinding(tuple): + """Exact released receipt identity for one governed specialized adjustment.""" + + __slots__ = () + + def __new__( + cls, + *, + sequence_number: int, + evidence_kind: str, + evidence_receipt_reference: str, + evidence_version: int, + evidence_receipt_digest: str, + ) -> FinalWeightAdjustmentEvidenceBinding: + """Validate a specialized receipt locator without copying adjustment values.""" + sequence = _require_positive_integer("sequence_number", sequence_number) + kind = _require_code("evidence_kind", evidence_kind) + namespace = _EVIDENCE_REFERENCE_NAMESPACE_BY_KIND.get(kind) + if namespace is None: + raise ValueError("evidence_kind must identify a governed specialized receipt.") + receipt_reference = _require_reference( + "evidence_receipt_reference", evidence_receipt_reference, namespace + ) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1 for specialized adjustment receipts.") + receipt_digest = _require_digest("evidence_receipt_digest", evidence_receipt_digest) + return tuple.__new__( + cls, + (sequence, kind, receipt_reference, version, receipt_digest), + ) + + @property + def sequence_number(self) -> int: + """Return the adjustment sequence from the final-weight construction.""" + return self[0] + + @property + def evidence_kind(self) -> str: + """Return the governed specialized receipt family.""" + return self[1] + + @property + def evidence_receipt_reference(self) -> str: + """Return the exact immutable specialized receipt reference.""" + return self[2] + + @property + def evidence_version(self) -> int: + """Return the governed specialized receipt evidence version.""" + return self[3] + + @property + def evidence_receipt_digest(self) -> str: + """Return the immutable specialized receipt digest.""" + return self[4] + + +class FinalWeightComponentBindingAuthorityRecord(tuple): + """Immutable owner locator from one final-weight receipt to typed component receipts.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + analysis_weight_receipt_reference: str, + analysis_weight_receipt_digest: str, + analysis_weight_evidence_version: int, + binding_reference: str, + binding_digest: str, + binding_version: int, + base_weight_evidence_receipt_reference: str, + base_weight_evidence_receipt_digest: str, + base_weight_evidence_version: int, + adjustment_bindings: tuple[FinalWeightAdjustmentEvidenceBinding, ...], + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + owner_contract_released_at: datetime, + released_at: datetime, + superseded_at: datetime | None = None, + ) -> FinalWeightComponentBindingAuthorityRecord: + """Validate immutable receipt locators and owner-resolved authority chronology.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + final_receipt_reference = _require_reference( + "analysis_weight_receipt_reference", + analysis_weight_receipt_reference, + "analysis_weight_receipt", + ) + final_receipt_digest = _require_digest( + "analysis_weight_receipt_digest", analysis_weight_receipt_digest + ) + final_version = _require_positive_integer( + "analysis_weight_evidence_version", analysis_weight_evidence_version + ) + if final_version != 1: + raise ValueError("analysis_weight_evidence_version must remain 1.") + locator_reference = _require_reference( + "binding_reference", + binding_reference, + "final_weight_component_binding", + ) + locator_digest = _require_digest("binding_digest", binding_digest) + locator_version = _require_positive_integer("binding_version", binding_version) + if locator_version != 1: + raise ValueError("binding_version must remain 1.") + base_receipt_reference = _require_reference( + "base_weight_evidence_receipt_reference", + base_weight_evidence_receipt_reference, + "base_weight_evidence_receipt", + ) + base_receipt_digest = _require_digest( + "base_weight_evidence_receipt_digest", + base_weight_evidence_receipt_digest, + ) + base_version = _require_positive_integer( + "base_weight_evidence_version", base_weight_evidence_version + ) + if base_version != 1: + raise ValueError("base_weight_evidence_version must remain 1.") + if type(adjustment_bindings) is not tuple: + raise ValueError("adjustment_bindings must be an immutable tuple.") + detached_bindings: list[FinalWeightAdjustmentEvidenceBinding] = [] + previous_sequence = 0 + for binding in adjustment_bindings: + if type(binding) is not FinalWeightAdjustmentEvidenceBinding: + raise ValueError( + "adjustment_bindings must contain exact FinalWeightAdjustmentEvidenceBinding values." + ) + detached = FinalWeightAdjustmentEvidenceBinding( + sequence_number=binding.sequence_number, + evidence_kind=binding.evidence_kind, + evidence_receipt_reference=binding.evidence_receipt_reference, + evidence_version=binding.evidence_version, + evidence_receipt_digest=binding.evidence_receipt_digest, + ) + if detached != binding: + raise ValueError("adjustment_bindings must contain canonical receipt locators.") + if detached.sequence_number <= previous_sequence: + raise ValueError("adjustment binding sequence numbers must be strictly increasing.") + detached_bindings.append(detached) + previous_sequence = detached.sequence_number + owner_reference = _require_reference( + "owner_contract_reference", owner_contract_reference, "released_owner_contract" + ) + owner_version = _require_positive_integer( + "owner_contract_version", owner_contract_version + ) + owner_digest = _require_digest("owner_contract_digest", owner_contract_digest) + owner_release = _require_aware_datetime( + "owner_contract_released_at", owner_contract_released_at + ) + release_instant = _require_aware_datetime("released_at", released_at) + if owner_release > release_instant: + raise ValueError("owner contract must be released no later than component binding.") + cutover = None + if superseded_at is not None: + cutover = _require_aware_datetime("superseded_at", superseded_at) + if cutover <= release_instant: + raise ValueError("superseded_at must be later than released_at.") + fields: tuple[tuple[str, object], ...] = ( + ("adjustment_bindings", tuple(detached_bindings)), + ("analysis_weight_evidence_version", final_version), + ("analysis_weight_receipt_digest", final_receipt_digest), + ("analysis_weight_receipt_reference", final_receipt_reference), + ("base_weight_evidence_receipt_digest", base_receipt_digest), + ("base_weight_evidence_receipt_reference", base_receipt_reference), + ("base_weight_evidence_version", base_version), + ("binding_digest", locator_digest), + ("binding_reference", locator_reference), + ("binding_version", locator_version), + ("owner_contract_digest", owner_digest), + ("owner_contract_reference", owner_reference), + ("owner_contract_version", owner_version), + ) + return tuple.__new__( + cls, + ( + tenant_identity, + study_identity, + fields, + owner_release, + release_instant, + cutover, + ), + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable final-weight and component receipt coordinates.""" + return self[2] + + @property + def owner_contract_released_at(self) -> datetime: + """Return when the governing component-binding owner contract was released.""" + return self[3] + + @property + def released_at(self) -> datetime: + """Return when this component locator became released authority.""" + return self[4] + + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive end of this locator's authority interval.""" + return self[5] + + +class FinalWeightComponentBindingAuthorityView(tuple): + """Field-minimized component locator issued only after purpose authorization.""" + + __slots__ = () + + def __new__( + cls, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + fields: tuple[tuple[str, object], ...], + ) -> FinalWeightComponentBindingAuthorityView: + """Reject public construction; only the resolver may issue this view.""" + raise TypeError( + "FinalWeightComponentBindingAuthorityView is issued only by " + "resolve_final_weight_component_binding_authority." + ) + + @property + def tenant_record_id(self) -> UUID: + """Return a fresh authorized tenant identity.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh authorized validity-study identity.""" + return _restore_operational_uuid("validity_study_id", self[1]) + + @property + def fields(self) -> tuple[tuple[str, object], ...]: + """Return immutable component receipt locators and owner chronology.""" + return self[2] + + +@runtime_checkable +class FinalWeightComponentBindingAuthorityReadPort(Protocol): + """Owner read contract keyed only by the immutable final-weight receipt identity.""" + + def read_final_weight_component_binding_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + analysis_weight_receipt_reference: str, + analysis_weight_receipt_digest: str, + analysis_weight_evidence_version: int, + ) -> FinalWeightComponentBindingAuthorityRecord | None: + """Return the unique released component locator for a final-weight receipt.""" + ... + + +_PROTOCOL_READ_CAPABILITY = getattr_static( + FinalWeightComponentBindingAuthorityReadPort, + "read_final_weight_component_binding_authority", +) + + +def resolve_final_weight_component_binding_authority( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + analysis_weight_receipt_reference: str, + analysis_weight_receipt_digest: str, + analysis_weight_evidence_version: int, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: FinalWeightComponentBindingAuthorityReadPort, +) -> FinalWeightComponentBindingAuthorityView: + """Authorize and resolve deterministic typed-component locators for a final weight.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + read_capability = getattr_static( + type(read_port), "read_final_weight_component_binding_authority", None + ) + if ( + type(read_capability) is not FunctionType + or read_capability is _PROTOCOL_READ_CAPABILITY + ): + raise TypeError( + "read_port must expose a statically callable " + "read_final_weight_component_binding_authority." + ) + tenant_id = _restore_operational_uuid( + "tenant_record_id", _store_operational_uuid("tenant_record_id", tenant_record_id) + ) + study_id = _restore_operational_uuid( + "validity_study_id", _store_operational_uuid("validity_study_id", validity_study_id) + ) + final_receipt_reference = _require_reference( + "analysis_weight_receipt_reference", + analysis_weight_receipt_reference, + "analysis_weight_receipt", + ) + final_receipt_digest = _require_digest( + "analysis_weight_receipt_digest", analysis_weight_receipt_digest + ) + final_version = _require_positive_integer( + "analysis_weight_evidence_version", analysis_weight_evidence_version + ) + if final_version != 1: + raise ValueError("analysis_weight_evidence_version must remain 1.") + use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + detached_policy = _detach_policy(policy) + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + persisted = read_capability( + read_port, + tenant_record_id=tenant_id, + validity_study_id=study_id, + analysis_weight_receipt_reference=final_receipt_reference, + analysis_weight_receipt_digest=final_receipt_digest, + analysis_weight_evidence_version=final_version, + ) + if persisted is None: + raise FinalWeightComponentBindingAuthorityNotFound(str(study_id)) + if type(persisted) is not FinalWeightComponentBindingAuthorityRecord: + raise FinalWeightComponentBindingAuthorityIntegrityError( + "owner port returned non-canonical final-weight component binding evidence" + ) + try: + record = FinalWeightComponentBindingAuthorityRecord( + tenant_record_id=persisted.tenant_record_id, + validity_study_id=persisted.validity_study_id, + owner_contract_released_at=persisted.owner_contract_released_at, + released_at=persisted.released_at, + superseded_at=persisted.superseded_at, + **dict(persisted.fields), + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise FinalWeightComponentBindingAuthorityIntegrityError( + "owner port returned malformed final-weight component binding evidence" + ) from exc + if record != persisted: + raise FinalWeightComponentBindingAuthorityIntegrityError( + "owner port returned non-canonical final-weight component binding evidence" + ) + values = dict(record.fields) + if ( + _store_operational_uuid("record tenant_record_id", record.tenant_record_id) + != _store_operational_uuid("requested tenant_record_id", tenant_id) + or _store_operational_uuid("record validity_study_id", record.validity_study_id) + != _store_operational_uuid("requested validity_study_id", study_id) + or values["analysis_weight_receipt_reference"] != final_receipt_reference + or values["analysis_weight_receipt_digest"] != final_receipt_digest + or values["analysis_weight_evidence_version"] != final_version + ): + raise FinalWeightComponentBindingAuthorityIntegrityError( + "released final-weight component binding targets another final-weight receipt" + ) + if use_instant < record.released_at: + raise FinalWeightComponentBindingAuthorityIntegrityError( + "final-weight component binding cannot be used before release" + ) + if record.superseded_at is not None and use_instant >= record.superseded_at: + raise FinalWeightComponentBindingAuthorityIntegrityError( + "final-weight component binding cannot be used at or after supersession" + ) + values["owner_contract_released_at"] = record.owner_contract_released_at + values["released_at"] = record.released_at + values["superseded_at"] = record.superseded_at + fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) + return tuple.__new__( + FinalWeightComponentBindingAuthorityView, + ( + _store_operational_uuid("tenant_record_id", record.tenant_record_id), + _store_operational_uuid("validity_study_id", record.validity_study_id), + fields, + ), + ) From 540f5810b5a046f6cba18e8faf37a0f60266bb1f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 14:10:30 +0900 Subject: [PATCH 425/603] feat(workforce-validation): export final-weight component binding authority --- .../__init__.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index 01d6d9978..dbc1efff4 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -57,6 +57,15 @@ FinalWeightAdjustmentCoordinate, resolve_final_analysis_weight_authority, ) +from orgmetra_workforce_validation_api.final_weight_component_binding_authority import ( + FinalWeightAdjustmentEvidenceBinding, + FinalWeightComponentBindingAuthorityIntegrityError, + FinalWeightComponentBindingAuthorityNotFound, + FinalWeightComponentBindingAuthorityReadPort, + FinalWeightComponentBindingAuthorityRecord, + FinalWeightComponentBindingAuthorityView, + resolve_final_weight_component_binding_authority, +) from orgmetra_workforce_validation_api.final_weight_supersession_authority import ( FinalWeightSupersessionAuthorityIntegrityError, FinalWeightSupersessionAuthorityNotFound, @@ -229,6 +238,12 @@ "FinalAnalysisWeightAuthorityRecord", "FinalAnalysisWeightAuthorityView", "FinalWeightAdjustmentCoordinate", + "FinalWeightAdjustmentEvidenceBinding", + "FinalWeightComponentBindingAuthorityIntegrityError", + "FinalWeightComponentBindingAuthorityNotFound", + "FinalWeightComponentBindingAuthorityReadPort", + "FinalWeightComponentBindingAuthorityRecord", + "FinalWeightComponentBindingAuthorityView", "FinalWeightSupersessionAuthorityIntegrityError", "FinalWeightSupersessionAuthorityNotFound", "FinalWeightSupersessionAuthorityReadPort", @@ -314,6 +329,7 @@ "resolve_calibration_benchmark_authority", "resolve_calibration_support_authority", "resolve_final_analysis_weight_authority", + "resolve_final_weight_component_binding_authority", "resolve_final_weight_supersession_authority", "resolve_nonresponse_adjustment_authority", "resolve_nonresponse_adjustment_supersession_authority", From af509f32fab910f96015fab7412d82a137932051 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 14:12:01 +0900 Subject: [PATCH 426/603] docs(workforce-validation): document exact final-weight component receipt binding --- services/workforce-validation-api/README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 71d34e915..543c6eea4 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -92,6 +92,12 @@ Stage-wise probability values stay with the sampling owner. Source-universe, sam The owner read is keyed by the complete caller-known reproducibility tuple. Owner-contract release, final-weight release and supersession instants remain owner-resolved chronology. The ordered adjustment chain is immutable and contiguous; known nonresponse/calibration/raking/poststratification/trimming/bounding/winsorization codes require their specialized receipt kind. Scientific use is valid only on `[released_at, superseded_at)`. +## Final analysis-weight component binding authority + +`resolve_final_weight_component_binding_authority(...)` closes the #411 locator gap without silently redefining the existing v1 final-weight receipt. It is keyed only by the immutable final analysis-weight receipt reference/digest/evidence-version and returns one released owner binding containing the exact base-weight evidence receipt reference/version/digest plus the exact receipt reference/version/digest for every governed specialized adjustment represented in the final-weight chain. Generic adjustment steps need not appear in the specialized binding tuple, so recorded sequence numbers are strictly increasing but need not be contiguous. + +The binding is its own immutable released owner evidence with reference/digest/version and owner-resolved `[released_at, superseded_at)` chronology. A digest is integrity evidence but is not treated as an implicit reverse-lookup API. Durable persistence must make the final-weight receipt identity select one canonical binding deterministically and fail closed on absence, ambiguity, conflicting receipt identity or non-canonical structure. This companion contract does not copy row-level weights, response values, calibration auxiliary values or foreign application tables; it supplies the owner coordinates required to re-resolve those existing typed authorities. + ## Final analysis-weight supersession authority `resolve_final_weight_supersession_authority(...)` preserves predecessor release, exclusive supersession and complete released successor coordinates. The successor must have a new receipt reference and digest, advance correction sequence exactly by one, be released after its predecessor, and be released exactly at the predecessor cutover. Successor coordinates are omitted from the downstream view. @@ -134,9 +140,9 @@ Both minimized views omit cutover and successor coordinates. A successor verific The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL role-level `search_path` defaults are applied at login and are not re-applied by `SET ROLE`. A durable runtime adapter therefore needs a distinct least-privilege runtime role, schema-qualified relations, and explicit function-level `search_path` for any future `SECURITY DEFINER` function. -Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **twenty-one** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration support chronology, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, base/design-weight supersession, complete final analysis-weight lineage, final-weight supersession, point-weight/variance compatibility, point-weight/variance supersession, validation-result binding, validation-result supersession, validation-result non-verifiability, and validation-result non-verifiability supersession. +Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **twenty-two** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration support chronology, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, base/design-weight supersession, complete final analysis-weight lineage, final-weight typed-component binding, final-weight supersession, point-weight/variance compatibility, point-weight/variance supersession, validation-result binding, validation-result supersession, validation-result non-verifiability, and validation-result non-verifiability supersession. -The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Non-verifiability persistence must key the exact immutable predecessor verification-attempt reference/digest; for `non_reproducible` it must additionally key the exact failed-evidence reference/digest, while failed-evidence and attempt-release instants remain owner chronology. Missing-evidence correction uses the v1 same-result/same-obligation successor graph. Non-reproducible correction uses v2 and must preserve the same predecessor failed-evidence reference/digest in addition to result, evidence family, verification attempt and owner contract; it must persist/recover the failed-evidence release instant as owner chronology and require the successor target tuple to equal the same exact artifact. V2 must also cross-check the explicit correction cutover against the ordinary predecessor's owner-resolved `superseded_at`; neither side may manufacture or hide the other. Both versions require successor verification-attempt release exactly at the predecessor cutover. No durable adapter may infer currentness from mutable current rows, unrelated result attempts, different-evidence-family attempts, different artifacts in the same family, or caller-supplied timestamps. +The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Final-weight component-binding persistence must key only the exact final receipt identity, return exactly one canonical released binding, preserve exact base/specialized adjustment receipt reference-version-digest locators, and reject ambiguous digest-only reverse lookup. Non-verifiability persistence must key the exact immutable predecessor verification-attempt reference/digest; for `non_reproducible` it must additionally key the exact failed-evidence reference/digest, while failed-evidence and attempt-release instants remain owner chronology. Missing-evidence correction uses the v1 same-result/same-obligation successor graph. Non-reproducible correction uses v2 and must preserve the same predecessor failed-evidence reference/digest in addition to result, evidence family, verification attempt and owner contract; it must persist/recover the failed-evidence release instant as owner chronology and require the successor target tuple to equal the same exact artifact. V2 must also cross-check the explicit correction cutover against the ordinary predecessor's owner-resolved `superseded_at`; neither side may manufacture or hide the other. Both versions require successor verification-attempt release exactly at the predecessor cutover. No durable adapter may infer currentness from mutable current rows, unrelated result attempts, different-evidence-family attempts, different artifacts in the same family, or caller-supplied timestamps. ## Test contract @@ -155,6 +161,6 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ `tests/test_workforce_validation_owner_schema_postgres.sh` separately executes the service-local migration against pinned PostgreSQL 16.14 and checks deny-default owner-role/schema behavior, actual `SET ROLE` search-path behavior, PUBLIC privileges, and absence of application relations in the bootstrap schema. -Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, explicit missing/non-reproducible evidence with exact verification-attempt identity and chronology, ordinary exact failed-artifact lookup for non-reproducible outcomes, v1 same-result/same-failed-evidence-obligation correction for missing predecessors, and v2 exact failed-artifact correction for non-reproducible predecessors including exact failed-artifact lookup identity, ordinary-cutover alignment, hostile mismatched-artifact, chronology, authorization, owner-port and structural-integrity cases. +Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, deterministic final-weight-to-component receipt binding/currentness including malformed nested and outer record rejection, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, explicit missing/non-reproducible evidence with exact verification-attempt identity and chronology, ordinary exact failed-artifact lookup for non-reproducible outcomes, v1 same-result/same-failed-evidence-obligation correction for missing predecessors, and v2 exact failed-artifact correction for non-reproducible predecessors including exact failed-artifact lookup identity, ordinary-cutover alignment, hostile mismatched-artifact, chronology, authorization, owner-port and structural-integrity cases. These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From 7ba1b111cff71462780d69afdf53014c9cc8f162 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 14:13:08 +0900 Subject: [PATCH 427/603] test(workforce-validation): cover component-binding fail-closed edges --- ...inal_weight_component_binding_authority.py | 161 +++++++++++++----- 1 file changed, 117 insertions(+), 44 deletions(-) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_binding_authority.py b/services/workforce-validation-api/tests/test_final_weight_component_binding_authority.py index 90b8a2cc7..2504e7d9f 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_binding_authority.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_binding_authority.py @@ -6,7 +6,7 @@ from uuid import UUID import pytest -from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy from orgmetra_workforce_validation_api import ValidationPrincipal import orgmetra_workforce_validation_api.final_weight_component_binding_authority as target @@ -23,6 +23,7 @@ TENANT = UUID("10000000-0000-7000-8000-000000000001") OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") STUDY = UUID("00000000-0000-7000-8000-0000000000f1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000f2") OWNER_RELEASED_AT = datetime(2026, 9, 19, 4, 0, tzinfo=timezone.utc) RELEASED_AT = datetime(2026, 9, 19, 4, 10, tzinfo=timezone.utc) USED_AT = datetime(2026, 9, 19, 4, 30, tzinfo=timezone.utc) @@ -37,24 +38,42 @@ def __init__(self, result: object) -> None: def read_final_weight_component_binding_authority(self, **kwargs: object) -> object: """Return configured evidence after recording caller-known lookup coordinates.""" - self.calls.append(kwargs) + self.calls.append(dict(kwargs)) return self.result -def _principal() -> ValidationPrincipal: +class _NoReadMethod: + """Deliberately omit the owner capability.""" + + +class _ProtocolOnly(FinalWeightComponentBindingAuthorityReadPort): + """Inherit only the Protocol placeholder rather than a concrete capability.""" + + +class _DescriptorReadPort: + """Expose an executable descriptor that static capability checks must reject.""" + + @property + def read_final_weight_component_binding_authority(self) -> object: + raise AssertionError("descriptor must not execute") + + +def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: return ValidationPrincipal( - tenant_record_id=TENANT, + tenant_record_id=tenant_record_id, actor_reference="person:validation-analyst-1", granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), ) -def _policy() -> PurposeBoundAccessPolicy: +def _policy( + *, purpose_code: str = "selection_validity_analysis" +) -> PurposeBoundAccessPolicy: return PurposeBoundAccessPolicy( tenant_record_id=TENANT, policy_version_code="final-weight-component-binding-read-v1", resource_kind="final_weight_component_binding_authority", - purpose_code="selection_validity_analysis", + purpose_code=purpose_code, operation_code="read", required_scope_code="orgmetra.workforce_validation.read", permitted_fields=target._READ_FIELDS, @@ -117,10 +136,10 @@ def _resolve( result: object, *, used_at: datetime = USED_AT, - read_port: _ReadPort | None = None, + read_port: object | None = None, **overrides: object, -) -> tuple[object, _ReadPort]: - port = _ReadPort(result) if read_port is None else read_port +) -> tuple[FinalWeightComponentBindingAuthorityView, object]: + port: object = _ReadPort(result) if read_port is None else read_port values: dict[str, object] = { "principal": _principal(), "tenant_record_id": TENANT, @@ -143,6 +162,10 @@ def test_resolver_returns_exact_component_locator_and_uses_final_receipt_key_onl record = _record() view, port = _resolve(record) + assert isinstance(port, _ReadPort) + assert isinstance(port, FinalWeightComponentBindingAuthorityReadPort) + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY fields = dict(view.fields) assert fields["base_weight_evidence_receipt_reference"] == ( "base_weight_evidence_receipt:cccccccc-cccc-4ccc-8ccc-cccccccccccc" @@ -152,6 +175,9 @@ def test_resolver_returns_exact_component_locator_and_uses_final_receipt_key_onl assert bindings[0].evidence_receipt_reference == ( "nonresponse_adjustment_receipt:11111111-1111-4111-8111-111111111111" ) + assert fields["owner_contract_released_at"] == OWNER_RELEASED_AT + assert fields["released_at"] == RELEASED_AT + assert fields["superseded_at"] is None assert port.calls == [ { "tenant_record_id": TENANT, @@ -191,14 +217,12 @@ def test_binding_sequence_may_skip_generic_adjustments_but_must_increase() -> No ({"binding_version": 2}, "binding_version"), ({"base_weight_evidence_version": 2}, "base_weight_evidence_version"), ({"adjustment_bindings": [_binding()]}, "immutable tuple"), + ({"adjustment_bindings": (object(),)}, "exact FinalWeightAdjustmentEvidenceBinding"), ( {"owner_contract_released_at": RELEASED_AT + timedelta(seconds=1)}, "owner contract", ), - ( - {"superseded_at": RELEASED_AT}, - "superseded_at", - ), + ({"superseded_at": RELEASED_AT}, "superseded_at"), ], ) def test_record_rejects_noncanonical_contract_shapes( @@ -263,14 +287,43 @@ def test_truncated_outer_record_maps_to_integrity_error() -> None: _resolve(forged) -def test_wrong_target_and_authority_interval_fail_closed() -> None: - with pytest.raises(FinalWeightComponentBindingAuthorityIntegrityError, match="target"): - _resolve(_record(tenant_record_id=OTHER_TENANT)) +@pytest.mark.parametrize( + "record_overrides", + [ + {"tenant_record_id": OTHER_TENANT}, + {"validity_study_id": OTHER_STUDY}, + { + "analysis_weight_receipt_reference": ( + "analysis_weight_receipt:eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee" + ) + }, + {"analysis_weight_receipt_digest": "f" * 64}, + ], +) +def test_owner_binding_must_target_the_exact_final_weight_receipt( + record_overrides: dict[str, object] +) -> None: + with pytest.raises(FinalWeightComponentBindingAuthorityIntegrityError, match="targets"): + _resolve(_record(**record_overrides)) + + +def test_authority_interval_fails_closed_before_release_and_at_cutover() -> None: with pytest.raises(FinalWeightComponentBindingAuthorityIntegrityError, match="before"): _resolve(_record(), used_at=RELEASED_AT - timedelta(microseconds=1)) cutover = USED_AT + record = _record(superseded_at=cutover) + assert record.released_at == RELEASED_AT + assert record.owner_contract_released_at == OWNER_RELEASED_AT + assert record.superseded_at == cutover with pytest.raises(FinalWeightComponentBindingAuthorityIntegrityError, match="supersession"): - _resolve(_record(superseded_at=cutover), used_at=cutover) + _resolve(record, used_at=cutover) + + +def test_authorization_denial_occurs_before_owner_read() -> None: + port = _ReadPort(_record()) + with pytest.raises(AuthorizationDeniedError): + _resolve(_record(), read_port=port, policy=_policy(purpose_code="audit_review")) + assert port.calls == [] def test_not_found_and_noncanonical_owner_types_fail_closed() -> None: @@ -280,33 +333,53 @@ def test_not_found_and_noncanonical_owner_types_fail_closed() -> None: _resolve(object()) -def test_principal_policy_and_protocol_placeholder_are_not_accepted() -> None: - with pytest.raises(TypeError, match="principal"): - _resolve(_record(), principal=object()) - with pytest.raises(TypeError, match="policy"): - _resolve(_record(), policy=object()) - - class _ProtocolOnly(FinalWeightComponentBindingAuthorityReadPort): - pass - - with pytest.raises(TypeError, match="statically callable"): - resolve_final_weight_component_binding_authority( - principal=_principal(), - tenant_record_id=TENANT, - validity_study_id=STUDY, - analysis_weight_receipt_reference=( - "analysis_weight_receipt:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" - ), - analysis_weight_receipt_digest="1" * 64, - analysis_weight_evidence_version=1, - used_at=USED_AT, - purpose_code="selection_validity_analysis", - policy=_policy(), - read_port=_ProtocolOnly(), - ) - - -def test_public_view_constructor_is_non_issuing() -> None: +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("analysis_weight_receipt_reference", "wrong:receipt", ValueError), + ("analysis_weight_receipt_digest", "ABC", ValueError), + ("analysis_weight_evidence_version", 2, ValueError), + ("used_at", datetime(2026, 9, 19, 4, 30), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_or_dependency_fails_before_owner_read( + key: str, value: object, error: type[Exception] +) -> None: + port: object = _ReadPort(_record()) + overrides = {key: value} + if key == "read_port": + port = value + overrides = {} + with pytest.raises(error): + _resolve(_record(), read_port=port, **overrides) + if isinstance(port, _ReadPort): + assert port.calls == [] + + +def test_record_and_view_are_structurally_immutable_and_uuid_views_are_detached() -> None: + tenant = UUID(str(TENANT)) + record = _record(tenant_record_id=tenant) + object.__setattr__(tenant, "int", OTHER_TENANT.int) + assert record.tenant_record_id == TENANT + assert record.validity_study_id == STUDY + with pytest.raises(AttributeError): + object.__setattr__(record, "fields", ()) + + view, _ = _resolve(record) + returned_tenant = view.tenant_record_id + object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + with pytest.raises(AttributeError): + object.__setattr__(view, "fields", ()) with pytest.raises(TypeError, match="issued only"): FinalWeightComponentBindingAuthorityView( tenant_record_id=TENANT, From b83372b78f99b995e5728a106c20803fa064032f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 14:31:48 +0900 Subject: [PATCH 428/603] test(workforce-validation): expose unresolved component receipt re-resolution --- ...al_weight_component_evidence_resolution.py | 289 ++++++++++++++++++ 1 file changed, 289 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py new file mode 100644 index 000000000..0da45a297 --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py @@ -0,0 +1,289 @@ +"""Cross-owner consistency for deterministic final-weight component reproduction.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.final_weight_authority import ( + FinalAnalysisWeightAuthorityRecord, + FinalWeightAdjustmentCoordinate, +) +from orgmetra_workforce_validation_api.final_weight_component_binding_authority import ( + FinalWeightAdjustmentEvidenceBinding, + FinalWeightComponentBindingAuthorityRecord, +) +from orgmetra_workforce_validation_api.final_weight_component_evidence_resolution import ( + AdjustmentComponentEvidence, + BaseWeightComponentEvidence, + FinalWeightComponentEvidenceIntegrityError, + FinalWeightComponentEvidenceNotFound, + FinalWeightComponentEvidenceResolution, + corroborate_final_weight_component_evidence, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") +CONSTRUCTED_AT = datetime(2026, 9, 19, 4, 5, tzinfo=timezone.utc) +FINAL_RELEASED_AT = datetime(2026, 9, 19, 4, 10, tzinfo=timezone.utc) +BINDING_RELEASED_AT = datetime(2026, 9, 19, 4, 15, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 19, 4, 30, tzinfo=timezone.utc) +FINAL_REFERENCE = "analysis_weight_receipt:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" +FINAL_DIGEST = "1" * 64 +BASE_RECEIPT_REFERENCE = ( + "base_weight_evidence_receipt:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" +) +BASE_RECEIPT_DIGEST = "2" * 64 +BASE_ARTIFACT_DIGEST = "3" * 64 +ADJUSTMENT_RECEIPT_REFERENCE = ( + "nonresponse_adjustment_receipt:cccccccc-cccc-4ccc-8ccc-cccccccccccc" +) +ADJUSTMENT_RECEIPT_DIGEST = "4" * 64 +ADJUSTMENT_OUTPUT_DIGEST = "5" * 64 +CONFIGURATION_DIGEST = "6" * 64 +METHOD_REFERENCE = "weight_method:dddddddd-dddd-4ddd-8ddd-dddddddddddd" + + +def _final_weight(**overrides: object) -> FinalAnalysisWeightAuthorityRecord: + adjustment = FinalWeightAdjustmentCoordinate( + sequence_number=1, + adjustment_code="nonresponse_adjustment", + method_reference=METHOD_REFERENCE, + method_version=1, + input_weight_artifact_digest=BASE_ARTIFACT_DIGEST, + output_weight_artifact_digest=ADJUSTMENT_OUTPUT_DIGEST, + configuration_digest=CONFIGURATION_DIGEST, + evidence_receipt_digest=ADJUSTMENT_RECEIPT_DIGEST, + evidence_kind="nonresponse_adjustment_receipt", + ) + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "analysis_weight_receipt_reference": FINAL_REFERENCE, + "analysis_weight_receipt_digest": FINAL_DIGEST, + "evidence_version": 1, + "estimand_reference": "validation_estimand:11111111-1111-4111-8111-111111111111", + "estimand_digest": "7" * 64, + "estimand_scope_code": "cross_sectional", + "target_population_reference": ( + "analysis_target_population:22222222-2222-4222-8222-222222222222" + ), + "target_population_digest": "8" * 64, + "analysis_unit_code": "person", + "analysis_window_reference": "analysis_window:33333333-3333-4333-8333-333333333333", + "reference_duration_reference": ( + "analysis_reference_duration:44444444-4444-4444-8444-444444444444" + ), + "reference_duration_digest": "9" * 64, + "eligible_case_set_digest": "a" * 64, + "analytic_case_occurrence_set_digest": "b" * 64, + "source_universe_receipt_reference": ( + "source_universe_receipt:55555555-5555-4555-8555-555555555555" + ), + "source_universe_receipt_version": 1, + "source_universe_receipt_digest": "c" * 64, + "sampling_design_receipt_reference": ( + "sampling_design_receipt:66666666-6666-4666-8666-666666666666" + ), + "sampling_design_receipt_version": 1, + "sampling_design_receipt_digest": "d" * 64, + "base_weight_method_code": "inverse_probability", + "base_weight_method_version": 1, + "base_weight_evidence_digest": BASE_RECEIPT_DIGEST, + "base_weight_artifact_digest": BASE_ARTIFACT_DIGEST, + "adjustments": (adjustment,), + "final_weight_artifact_digest": ADJUSTMENT_OUTPUT_DIGEST, + "weight_eligibility_receipt_reference": ( + "weight_eligibility_receipt:77777777-7777-4777-8777-777777777777" + ), + "weight_eligibility_receipt_digest": "e" * 64, + "analytic_case_count": 10, + "constructed_at": CONSTRUCTED_AT, + "correction_sequence": 1, + "supersedes_receipt_digest": None, + "owner_contract_reference": ( + "released_owner_contract:88888888-8888-4888-8888-888888888888" + ), + "owner_contract_version": 1, + "owner_contract_digest": "f" * 64, + "owner_contract_released_at": CONSTRUCTED_AT - timedelta(minutes=10), + "released_at": FINAL_RELEASED_AT, + "superseded_at": None, + } + values.update(overrides) + return FinalAnalysisWeightAuthorityRecord(**values) + + +def _binding(**overrides: object) -> FinalWeightComponentBindingAuthorityRecord: + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "analysis_weight_receipt_reference": FINAL_REFERENCE, + "analysis_weight_receipt_digest": FINAL_DIGEST, + "analysis_weight_evidence_version": 1, + "binding_reference": ( + "final_weight_component_binding:99999999-9999-4999-8999-999999999999" + ), + "binding_digest": "0" * 64, + "binding_version": 1, + "base_weight_evidence_receipt_reference": BASE_RECEIPT_REFERENCE, + "base_weight_evidence_receipt_digest": BASE_RECEIPT_DIGEST, + "base_weight_evidence_version": 1, + "adjustment_bindings": ( + FinalWeightAdjustmentEvidenceBinding( + sequence_number=1, + evidence_kind="nonresponse_adjustment_receipt", + evidence_receipt_reference=ADJUSTMENT_RECEIPT_REFERENCE, + evidence_version=1, + evidence_receipt_digest=ADJUSTMENT_RECEIPT_DIGEST, + ), + ), + "owner_contract_reference": ( + "released_owner_contract:aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee" + ), + "owner_contract_version": 1, + "owner_contract_digest": "a" * 64, + "owner_contract_released_at": FINAL_RELEASED_AT, + "released_at": BINDING_RELEASED_AT, + "superseded_at": None, + } + values.update(overrides) + return FinalWeightComponentBindingAuthorityRecord(**values) + + +def _base_evidence(**overrides: object) -> BaseWeightComponentEvidence: + values: dict[str, object] = { + "receipt_reference": BASE_RECEIPT_REFERENCE, + "receipt_digest": BASE_RECEIPT_DIGEST, + "evidence_version": 1, + "method_code": "inverse_probability", + "method_version": 1, + "output_weight_artifact_digest": BASE_ARTIFACT_DIGEST, + "released_at": CONSTRUCTED_AT - timedelta(minutes=15), + "superseded_at": None, + } + values.update(overrides) + return BaseWeightComponentEvidence(**values) + + +def _adjustment_evidence(**overrides: object) -> AdjustmentComponentEvidence: + values: dict[str, object] = { + "evidence_kind": "nonresponse_adjustment_receipt", + "receipt_reference": ADJUSTMENT_RECEIPT_REFERENCE, + "receipt_digest": ADJUSTMENT_RECEIPT_DIGEST, + "evidence_version": 1, + "method_reference": METHOD_REFERENCE, + "method_version": 1, + "input_weight_artifact_digest": BASE_ARTIFACT_DIGEST, + "output_weight_artifact_digest": ADJUSTMENT_OUTPUT_DIGEST, + "configuration_digest": CONFIGURATION_DIGEST, + "released_at": CONSTRUCTED_AT - timedelta(minutes=1), + "superseded_at": None, + } + values.update(overrides) + return AdjustmentComponentEvidence(**values) + + +class _ReadPort: + def __init__( + self, + *, + base: BaseWeightComponentEvidence | None = None, + adjustment: AdjustmentComponentEvidence | None = None, + ) -> None: + self.base = _base_evidence() if base is None else base + self.adjustment = _adjustment_evidence() if adjustment is None else adjustment + self.base_calls: list[dict[str, object]] = [] + self.adjustment_calls: list[dict[str, object]] = [] + + def read_base_weight_component_evidence(self, **kwargs: object) -> BaseWeightComponentEvidence | None: + self.base_calls.append(dict(kwargs)) + return self.base + + def read_adjustment_component_evidence(self, **kwargs: object) -> AdjustmentComponentEvidence | None: + self.adjustment_calls.append(dict(kwargs)) + return self.adjustment + + +def test_exact_receipt_identity_resolves_and_cross_checks_component_semantics() -> None: + port = _ReadPort() + resolution = corroborate_final_weight_component_evidence( + final_weight=_final_weight(), + binding=_binding(), + used_at=USED_AT, + read_port=port, + ) + + assert isinstance(resolution, FinalWeightComponentEvidenceResolution) + assert resolution.base_weight.receipt_reference == BASE_RECEIPT_REFERENCE + assert resolution.adjustments == (_adjustment_evidence(),) + assert port.base_calls == [ + { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "receipt_reference": BASE_RECEIPT_REFERENCE, + "receipt_digest": BASE_RECEIPT_DIGEST, + "evidence_version": 1, + } + ] + assert port.adjustment_calls == [ + { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "evidence_kind": "nonresponse_adjustment_receipt", + "receipt_reference": ADJUSTMENT_RECEIPT_REFERENCE, + "receipt_digest": ADJUSTMENT_RECEIPT_DIGEST, + "evidence_version": 1, + } + ] + + +def test_component_method_or_artifact_mismatch_fails_closed() -> None: + port = _ReadPort(adjustment=_adjustment_evidence(method_reference=( + "weight_method:eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee" + ))) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="adjustment semantics"): + corroborate_final_weight_component_evidence( + final_weight=_final_weight(), + binding=_binding(), + used_at=USED_AT, + read_port=port, + ) + + +def test_component_not_released_by_final_construction_fails_closed() -> None: + port = _ReadPort(adjustment=_adjustment_evidence( + released_at=CONSTRUCTED_AT + timedelta(microseconds=1) + )) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="construction"): + corroborate_final_weight_component_evidence( + final_weight=_final_weight(), + binding=_binding(), + used_at=USED_AT, + read_port=port, + ) + + +def test_missing_exact_component_receipt_fails_closed() -> None: + port = _ReadPort() + port.adjustment = None + with pytest.raises(FinalWeightComponentEvidenceNotFound): + corroborate_final_weight_component_evidence( + final_weight=_final_weight(), + binding=_binding(), + used_at=USED_AT, + read_port=port, + ) + + +def test_binding_cannot_omit_a_specialized_adjustment() -> None: + binding = _binding(adjustment_bindings=()) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="specialized"): + corroborate_final_weight_component_evidence( + final_weight=_final_weight(), + binding=binding, + used_at=USED_AT, + read_port=_ReadPort(), + ) From a6377d77f45114f47b3dd53206c799869fcdc723 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 14:32:48 +0900 Subject: [PATCH 429/603] feat(workforce-validation): resolve exact final-weight component evidence --- ...al_weight_component_evidence_resolution.py | 630 ++++++++++++++++++ 1 file changed, 630 insertions(+) create mode 100644 services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py new file mode 100644 index 000000000..51c56a715 --- /dev/null +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py @@ -0,0 +1,630 @@ +"""Corroborate exact final-weight component receipts against final-weight semantics. + +This cross-owner consistency service is used after purpose-authorized final-weight +and component-binding reads. It turns the binding's exact receipt locators into +an executable deterministic resolution contract: adapters must resolve component +evidence by receipt identity, and this service verifies that the resolved base +weight and specialized adjustments agree with the released final-weight chain. +No row-level weights or foreign source values cross this boundary. +""" + +from __future__ import annotations + +from datetime import datetime +from inspect import getattr_static +from types import FunctionType +from typing import Protocol, runtime_checkable +from uuid import UUID + +from .final_weight_authority import ( + FinalAnalysisWeightAuthorityRecord, + FinalWeightAdjustmentCoordinate, +) +from .final_weight_component_binding_authority import ( + FinalWeightComponentBindingAuthorityRecord, + _EVIDENCE_REFERENCE_NAMESPACE_BY_KIND, +) +from .registry import ( + _require_aware_datetime, + _require_code, + _restore_operational_uuid, + _store_operational_uuid, +) +from .scientific_authority import ( + _require_digest, + _require_positive_integer, + _require_reference, +) + + +class FinalWeightComponentEvidenceNotFound(LookupError): + """Indicate that an exact bound component receipt cannot be deterministically resolved.""" + + +class FinalWeightComponentEvidenceIntegrityError(RuntimeError): + """Indicate that resolved component evidence disagrees with the final-weight lineage.""" + + +class BaseWeightComponentEvidence(tuple): + """Released base-weight receipt projection needed to reproduce the final-weight chain.""" + + __slots__ = () + + def __new__( + cls, + *, + receipt_reference: str, + receipt_digest: str, + evidence_version: int, + method_code: str, + method_version: int, + output_weight_artifact_digest: str, + released_at: datetime, + superseded_at: datetime | None = None, + ) -> BaseWeightComponentEvidence: + """Validate a value-minimized exact base-weight component projection.""" + reference = _require_reference( + "receipt_reference", receipt_reference, "base_weight_evidence_receipt" + ) + digest = _require_digest("receipt_digest", receipt_digest) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1 for base-weight evidence.") + method = _require_code("method_code", method_code) + method_ver = _require_positive_integer("method_version", method_version) + output_digest = _require_digest( + "output_weight_artifact_digest", output_weight_artifact_digest + ) + release = _require_aware_datetime("released_at", released_at) + cutover = None + if superseded_at is not None: + cutover = _require_aware_datetime("superseded_at", superseded_at) + if cutover <= release: + raise ValueError("superseded_at must be later than released_at.") + return tuple.__new__( + cls, + (reference, digest, version, method, method_ver, output_digest, release, cutover), + ) + + @property + def receipt_reference(self) -> str: + """Return the exact base-weight evidence receipt reference.""" + return self[0] + + @property + def receipt_digest(self) -> str: + """Return the immutable base-weight evidence receipt digest.""" + return self[1] + + @property + def evidence_version(self) -> int: + """Return the governed base-weight evidence version.""" + return self[2] + + @property + def method_code(self) -> str: + """Return the base-weight method code used by the final-weight chain.""" + return self[3] + + @property + def method_version(self) -> int: + """Return the base-weight method version.""" + return self[4] + + @property + def output_weight_artifact_digest(self) -> str: + """Return the resulting base-weight artifact digest.""" + return self[5] + + @property + def released_at(self) -> datetime: + """Return when this component became released authority.""" + return self[6] + + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive end of this component's authority interval.""" + return self[7] + + +class AdjustmentComponentEvidence(tuple): + """Released specialized-adjustment projection normalized to final-weight semantics.""" + + __slots__ = () + + def __new__( + cls, + *, + evidence_kind: str, + receipt_reference: str, + receipt_digest: str, + evidence_version: int, + method_reference: str, + method_version: int, + input_weight_artifact_digest: str, + output_weight_artifact_digest: str, + configuration_digest: str, + released_at: datetime, + superseded_at: datetime | None = None, + ) -> AdjustmentComponentEvidence: + """Validate an exact specialized receipt plus its final-weight transform semantics.""" + kind = _require_code("evidence_kind", evidence_kind) + namespace = _EVIDENCE_REFERENCE_NAMESPACE_BY_KIND.get(kind) + if namespace is None: + raise ValueError("evidence_kind must identify a governed specialized receipt.") + reference = _require_reference("receipt_reference", receipt_reference, namespace) + digest = _require_digest("receipt_digest", receipt_digest) + version = _require_positive_integer("evidence_version", evidence_version) + if version != 1: + raise ValueError("evidence_version must remain 1 for specialized evidence.") + method = _require_reference("method_reference", method_reference, "weight_method") + method_ver = _require_positive_integer("method_version", method_version) + input_digest = _require_digest( + "input_weight_artifact_digest", input_weight_artifact_digest + ) + output_digest = _require_digest( + "output_weight_artifact_digest", output_weight_artifact_digest + ) + if input_digest == output_digest: + raise ValueError( + "output_weight_artifact_digest must identify the transformed weight artifact." + ) + configuration = _require_digest("configuration_digest", configuration_digest) + release = _require_aware_datetime("released_at", released_at) + cutover = None + if superseded_at is not None: + cutover = _require_aware_datetime("superseded_at", superseded_at) + if cutover <= release: + raise ValueError("superseded_at must be later than released_at.") + return tuple.__new__( + cls, + ( + kind, + reference, + digest, + version, + method, + method_ver, + input_digest, + output_digest, + configuration, + release, + cutover, + ), + ) + + @property + def evidence_kind(self) -> str: + """Return the governed specialized receipt family.""" + return self[0] + + @property + def receipt_reference(self) -> str: + """Return the exact specialized receipt reference.""" + return self[1] + + @property + def receipt_digest(self) -> str: + """Return the immutable specialized receipt digest.""" + return self[2] + + @property + def evidence_version(self) -> int: + """Return the governed specialized evidence version.""" + return self[3] + + @property + def method_reference(self) -> str: + """Return the released weight-method semantic used by the final chain.""" + return self[4] + + @property + def method_version(self) -> int: + """Return the released weight-method version.""" + return self[5] + + @property + def input_weight_artifact_digest(self) -> str: + """Return the transform input artifact digest.""" + return self[6] + + @property + def output_weight_artifact_digest(self) -> str: + """Return the transform output artifact digest.""" + return self[7] + + @property + def configuration_digest(self) -> str: + """Return the immutable transform configuration digest.""" + return self[8] + + @property + def released_at(self) -> datetime: + """Return when this specialized component became released authority.""" + return self[9] + + @property + def superseded_at(self) -> datetime | None: + """Return the exclusive end of this component's authority interval.""" + return self[10] + + +class FinalWeightComponentEvidenceResolution(tuple): + """Canonical exact component evidence corroborated against one final-weight receipt.""" + + __slots__ = () + + def __new__( + cls, + *, + base_weight: BaseWeightComponentEvidence, + adjustments: tuple[AdjustmentComponentEvidence, ...], + ) -> FinalWeightComponentEvidenceResolution: + """Detach already-corroborated component projections.""" + if type(base_weight) is not BaseWeightComponentEvidence: + raise TypeError("base_weight must be an exact BaseWeightComponentEvidence.") + canonical_base = BaseWeightComponentEvidence( + receipt_reference=base_weight.receipt_reference, + receipt_digest=base_weight.receipt_digest, + evidence_version=base_weight.evidence_version, + method_code=base_weight.method_code, + method_version=base_weight.method_version, + output_weight_artifact_digest=base_weight.output_weight_artifact_digest, + released_at=base_weight.released_at, + superseded_at=base_weight.superseded_at, + ) + if canonical_base != base_weight: + raise ValueError("base_weight must be canonical component evidence.") + if type(adjustments) is not tuple: + raise TypeError("adjustments must be an immutable tuple.") + canonical_adjustments: list[AdjustmentComponentEvidence] = [] + for adjustment in adjustments: + canonical = _canonical_adjustment_evidence(adjustment) + canonical_adjustments.append(canonical) + return tuple.__new__(cls, (canonical_base, tuple(canonical_adjustments))) + + @property + def base_weight(self) -> BaseWeightComponentEvidence: + """Return the exact corroborated base-weight component.""" + return self[0] + + @property + def adjustments(self) -> tuple[AdjustmentComponentEvidence, ...]: + """Return specialized components in final-weight sequence order.""" + return self[1] + + +@runtime_checkable +class FinalWeightComponentEvidenceReadPort(Protocol): + """Deterministic receipt-identity resolver for final-weight component evidence.""" + + def read_base_weight_component_evidence( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + receipt_reference: str, + receipt_digest: str, + evidence_version: int, + ) -> BaseWeightComponentEvidence | None: + """Resolve exactly one canonical base-weight projection by immutable receipt identity.""" + ... + + def read_adjustment_component_evidence( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + evidence_kind: str, + receipt_reference: str, + receipt_digest: str, + evidence_version: int, + ) -> AdjustmentComponentEvidence | None: + """Resolve exactly one canonical specialized projection by immutable receipt identity.""" + ... + + +_BASE_READ_CAPABILITY = getattr_static( + FinalWeightComponentEvidenceReadPort, "read_base_weight_component_evidence" +) +_ADJUSTMENT_READ_CAPABILITY = getattr_static( + FinalWeightComponentEvidenceReadPort, "read_adjustment_component_evidence" +) + + +def _canonical_adjustment_evidence(value: object) -> AdjustmentComponentEvidence: + """Reconstruct specialized projection so exact runtime type cannot hide structure.""" + if type(value) is not AdjustmentComponentEvidence: + raise FinalWeightComponentEvidenceIntegrityError( + "component port returned non-canonical specialized evidence" + ) + try: + canonical = AdjustmentComponentEvidence( + evidence_kind=value.evidence_kind, + receipt_reference=value.receipt_reference, + receipt_digest=value.receipt_digest, + evidence_version=value.evidence_version, + method_reference=value.method_reference, + method_version=value.method_version, + input_weight_artifact_digest=value.input_weight_artifact_digest, + output_weight_artifact_digest=value.output_weight_artifact_digest, + configuration_digest=value.configuration_digest, + released_at=value.released_at, + superseded_at=value.superseded_at, + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise FinalWeightComponentEvidenceIntegrityError( + "component port returned malformed specialized evidence" + ) from exc + if canonical != value: + raise FinalWeightComponentEvidenceIntegrityError( + "component port returned non-canonical specialized evidence" + ) + return canonical + + +def _canonical_base_evidence(value: object) -> BaseWeightComponentEvidence: + """Reconstruct base projection so exact runtime type cannot hide structure.""" + if type(value) is not BaseWeightComponentEvidence: + raise FinalWeightComponentEvidenceIntegrityError( + "component port returned non-canonical base-weight evidence" + ) + try: + canonical = BaseWeightComponentEvidence( + receipt_reference=value.receipt_reference, + receipt_digest=value.receipt_digest, + evidence_version=value.evidence_version, + method_code=value.method_code, + method_version=value.method_version, + output_weight_artifact_digest=value.output_weight_artifact_digest, + released_at=value.released_at, + superseded_at=value.superseded_at, + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise FinalWeightComponentEvidenceIntegrityError( + "component port returned malformed base-weight evidence" + ) from exc + if canonical != value: + raise FinalWeightComponentEvidenceIntegrityError( + "component port returned non-canonical base-weight evidence" + ) + return canonical + + +def _canonical_final_weight(value: object) -> FinalAnalysisWeightAuthorityRecord: + """Reconstruct final-weight authority before any cross-owner comparison.""" + if type(value) is not FinalAnalysisWeightAuthorityRecord: + raise FinalWeightComponentEvidenceIntegrityError( + "final_weight must be exact canonical final-weight authority evidence" + ) + try: + canonical = FinalAnalysisWeightAuthorityRecord( + tenant_record_id=value.tenant_record_id, + validity_study_id=value.validity_study_id, + owner_contract_released_at=value.owner_contract_released_at, + released_at=value.released_at, + superseded_at=value.superseded_at, + **dict(value.fields), + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise FinalWeightComponentEvidenceIntegrityError( + "final_weight is malformed canonical authority evidence" + ) from exc + if canonical != value: + raise FinalWeightComponentEvidenceIntegrityError( + "final_weight contains non-canonical hidden or malformed structure" + ) + return canonical + + +def _canonical_binding(value: object) -> FinalWeightComponentBindingAuthorityRecord: + """Reconstruct component binding before any locator is trusted.""" + if type(value) is not FinalWeightComponentBindingAuthorityRecord: + raise FinalWeightComponentEvidenceIntegrityError( + "binding must be exact canonical final-weight component binding evidence" + ) + try: + canonical = FinalWeightComponentBindingAuthorityRecord( + tenant_record_id=value.tenant_record_id, + validity_study_id=value.validity_study_id, + owner_contract_released_at=value.owner_contract_released_at, + released_at=value.released_at, + superseded_at=value.superseded_at, + **dict(value.fields), + ) + except (IndexError, KeyError, TypeError, ValueError) as exc: + raise FinalWeightComponentEvidenceIntegrityError( + "binding is malformed canonical authority evidence" + ) from exc + if canonical != value: + raise FinalWeightComponentEvidenceIntegrityError( + "binding contains non-canonical hidden or malformed structure" + ) + return canonical + + +def _require_component_valid_at_construction( + *, released_at: datetime, superseded_at: datetime | None, constructed_at: datetime +) -> None: + """Require component evidence to be released and current when the final weight was built.""" + if released_at > constructed_at: + raise FinalWeightComponentEvidenceIntegrityError( + "component evidence was not released by final-weight construction" + ) + if superseded_at is not None and constructed_at >= superseded_at: + raise FinalWeightComponentEvidenceIntegrityError( + "component evidence was superseded before final-weight construction" + ) + + +def corroborate_final_weight_component_evidence( + *, + final_weight: FinalAnalysisWeightAuthorityRecord, + binding: FinalWeightComponentBindingAuthorityRecord, + used_at: datetime, + read_port: FinalWeightComponentEvidenceReadPort, +) -> FinalWeightComponentEvidenceResolution: + """Resolve exact component receipts and prove their semantics match the final-weight chain.""" + base_capability = getattr_static(type(read_port), "read_base_weight_component_evidence", None) + adjustment_capability = getattr_static( + type(read_port), "read_adjustment_component_evidence", None + ) + if type(base_capability) is not FunctionType or base_capability is _BASE_READ_CAPABILITY: + raise TypeError("read_port must expose read_base_weight_component_evidence.") + if ( + type(adjustment_capability) is not FunctionType + or adjustment_capability is _ADJUSTMENT_READ_CAPABILITY + ): + raise TypeError("read_port must expose read_adjustment_component_evidence.") + + final_record = _canonical_final_weight(final_weight) + binding_record = _canonical_binding(binding) + use_instant = _require_aware_datetime("used_at", used_at) + final_values = dict(final_record.fields) + binding_values = dict(binding_record.fields) + + if ( + _store_operational_uuid("final tenant_record_id", final_record.tenant_record_id) + != _store_operational_uuid("binding tenant_record_id", binding_record.tenant_record_id) + or _store_operational_uuid("final validity_study_id", final_record.validity_study_id) + != _store_operational_uuid("binding validity_study_id", binding_record.validity_study_id) + or final_values["analysis_weight_receipt_reference"] + != binding_values["analysis_weight_receipt_reference"] + or final_values["analysis_weight_receipt_digest"] + != binding_values["analysis_weight_receipt_digest"] + or final_values["evidence_version"] + != binding_values["analysis_weight_evidence_version"] + ): + raise FinalWeightComponentEvidenceIntegrityError( + "component binding targets a different final-weight receipt" + ) + if use_instant < final_record.released_at or use_instant < binding_record.released_at: + raise FinalWeightComponentEvidenceIntegrityError( + "final-weight evidence and component binding must be released before use" + ) + if final_record.superseded_at is not None and use_instant >= final_record.superseded_at: + raise FinalWeightComponentEvidenceIntegrityError( + "final-weight evidence is not current at the governed use instant" + ) + if binding_record.superseded_at is not None and use_instant >= binding_record.superseded_at: + raise FinalWeightComponentEvidenceIntegrityError( + "component binding is not current at the governed use instant" + ) + + tenant_id = _restore_operational_uuid( + "tenant_record_id", _store_operational_uuid("tenant_record_id", final_record.tenant_record_id) + ) + study_id = _restore_operational_uuid( + "validity_study_id", _store_operational_uuid("validity_study_id", final_record.validity_study_id) + ) + base_value = base_capability( + read_port, + tenant_record_id=tenant_id, + validity_study_id=study_id, + receipt_reference=binding_values["base_weight_evidence_receipt_reference"], + receipt_digest=binding_values["base_weight_evidence_receipt_digest"], + evidence_version=binding_values["base_weight_evidence_version"], + ) + if base_value is None: + raise FinalWeightComponentEvidenceNotFound( + str(binding_values["base_weight_evidence_receipt_reference"]) + ) + base = _canonical_base_evidence(base_value) + if ( + base.receipt_reference != binding_values["base_weight_evidence_receipt_reference"] + or base.receipt_digest != binding_values["base_weight_evidence_receipt_digest"] + or base.evidence_version != binding_values["base_weight_evidence_version"] + or base.receipt_digest != final_values["base_weight_evidence_digest"] + or base.method_code != final_values["base_weight_method_code"] + or base.method_version != final_values["base_weight_method_version"] + or base.output_weight_artifact_digest != final_values["base_weight_artifact_digest"] + ): + raise FinalWeightComponentEvidenceIntegrityError( + "base-weight component semantics disagree with the final-weight receipt" + ) + constructed_at = final_values["constructed_at"] + _require_component_valid_at_construction( + released_at=base.released_at, + superseded_at=base.superseded_at, + constructed_at=constructed_at, + ) + + adjustments = final_values["adjustments"] + if type(adjustments) is not tuple: + raise FinalWeightComponentEvidenceIntegrityError( + "final-weight adjustments are not canonical immutable coordinates" + ) + adjustment_bindings = binding_values["adjustment_bindings"] + if type(adjustment_bindings) is not tuple: + raise FinalWeightComponentEvidenceIntegrityError( + "component adjustment bindings are not canonical immutable coordinates" + ) + binding_by_sequence = {item.sequence_number: item for item in adjustment_bindings} + specialized_sequences = { + item.sequence_number + for item in adjustments + if item.evidence_kind in _EVIDENCE_REFERENCE_NAMESPACE_BY_KIND + } + if set(binding_by_sequence) != specialized_sequences: + raise FinalWeightComponentEvidenceIntegrityError( + "component binding must cover every and only specialized final-weight adjustment" + ) + + resolved_adjustments: list[AdjustmentComponentEvidence] = [] + for adjustment in adjustments: + if type(adjustment) is not FinalWeightAdjustmentCoordinate: + raise FinalWeightComponentEvidenceIntegrityError( + "final-weight adjustment coordinates must remain canonical" + ) + if adjustment.sequence_number not in specialized_sequences: + continue + locator = binding_by_sequence[adjustment.sequence_number] + if ( + locator.evidence_kind != adjustment.evidence_kind + or locator.evidence_receipt_digest != adjustment.evidence_receipt_digest + ): + raise FinalWeightComponentEvidenceIntegrityError( + "component binding digest or evidence kind disagrees with final-weight adjustment" + ) + component_value = adjustment_capability( + read_port, + tenant_record_id=tenant_id, + validity_study_id=study_id, + evidence_kind=locator.evidence_kind, + receipt_reference=locator.evidence_receipt_reference, + receipt_digest=locator.evidence_receipt_digest, + evidence_version=locator.evidence_version, + ) + if component_value is None: + raise FinalWeightComponentEvidenceNotFound(locator.evidence_receipt_reference) + component = _canonical_adjustment_evidence(component_value) + if ( + component.evidence_kind != locator.evidence_kind + or component.receipt_reference != locator.evidence_receipt_reference + or component.receipt_digest != locator.evidence_receipt_digest + or component.evidence_version != locator.evidence_version + ): + raise FinalWeightComponentEvidenceIntegrityError( + "resolved component identity disagrees with the exact binding locator" + ) + if ( + component.method_reference != adjustment.method_reference + or component.method_version != adjustment.method_version + or component.input_weight_artifact_digest != adjustment.input_weight_artifact_digest + or component.output_weight_artifact_digest != adjustment.output_weight_artifact_digest + or component.configuration_digest != adjustment.configuration_digest + ): + raise FinalWeightComponentEvidenceIntegrityError( + "resolved adjustment semantics disagree with the final-weight adjustment" + ) + _require_component_valid_at_construction( + released_at=component.released_at, + superseded_at=component.superseded_at, + constructed_at=constructed_at, + ) + resolved_adjustments.append(component) + + return FinalWeightComponentEvidenceResolution( + base_weight=base, + adjustments=tuple(resolved_adjustments), + ) From 13030a961de8feb6b549834a68a0d0d589314189 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 14:36:30 +0900 Subject: [PATCH 430/603] test(workforce-validation): require component evidence public surface --- ...eight_component_evidence_public_surface.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_component_evidence_public_surface.py diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_public_surface.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_public_surface.py new file mode 100644 index 000000000..585638f21 --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_public_surface.py @@ -0,0 +1,23 @@ +"""Public package contract for deterministic final-weight component corroboration.""" + +from __future__ import annotations + +import orgmetra_workforce_validation_api as api + + +def test_component_evidence_resolution_is_public_package_surface() -> None: + expected = { + "AdjustmentComponentEvidence", + "BaseWeightComponentEvidence", + "FinalWeightComponentEvidenceIntegrityError", + "FinalWeightComponentEvidenceNotFound", + "FinalWeightComponentEvidenceReadPort", + "FinalWeightComponentEvidenceResolution", + "corroborate_final_weight_component_evidence", + } + + assert expected <= set(api.__all__) + for name in expected: + assert getattr(api, name).__module__ == ( + "orgmetra_workforce_validation_api.final_weight_component_evidence_resolution" + ) From af292bd8febb5e2b1231c276446d1eb0c77c73cd Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 14:37:05 +0900 Subject: [PATCH 431/603] feat(workforce-validation): export component evidence resolution --- .../__init__.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py index dbc1efff4..818a49d14 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/__init__.py @@ -66,6 +66,15 @@ FinalWeightComponentBindingAuthorityView, resolve_final_weight_component_binding_authority, ) +from orgmetra_workforce_validation_api.final_weight_component_evidence_resolution import ( + AdjustmentComponentEvidence, + BaseWeightComponentEvidence, + FinalWeightComponentEvidenceIntegrityError, + FinalWeightComponentEvidenceNotFound, + FinalWeightComponentEvidenceReadPort, + FinalWeightComponentEvidenceResolution, + corroborate_final_weight_component_evidence, +) from orgmetra_workforce_validation_api.final_weight_supersession_authority import ( FinalWeightSupersessionAuthorityIntegrityError, FinalWeightSupersessionAuthorityNotFound, @@ -197,11 +206,13 @@ ) __all__ = [ + "AdjustmentComponentEvidence", "BaseWeightAuthorityIntegrityError", "BaseWeightAuthorityNotFound", "BaseWeightAuthorityReadPort", "BaseWeightAuthorityRecord", "BaseWeightAuthorityView", + "BaseWeightComponentEvidence", "BaseWeightSupersessionAuthorityIntegrityError", "BaseWeightSupersessionAuthorityNotFound", "BaseWeightSupersessionAuthorityReadPort", @@ -244,6 +255,10 @@ "FinalWeightComponentBindingAuthorityReadPort", "FinalWeightComponentBindingAuthorityRecord", "FinalWeightComponentBindingAuthorityView", + "FinalWeightComponentEvidenceIntegrityError", + "FinalWeightComponentEvidenceNotFound", + "FinalWeightComponentEvidenceReadPort", + "FinalWeightComponentEvidenceResolution", "FinalWeightSupersessionAuthorityIntegrityError", "FinalWeightSupersessionAuthorityNotFound", "FinalWeightSupersessionAuthorityReadPort", @@ -320,6 +335,7 @@ "WeightVarianceSupersessionAuthorityReadPort", "WeightVarianceSupersessionAuthorityRecord", "WeightVarianceSupersessionAuthorityView", + "corroborate_final_weight_component_evidence", "read_validity_study", "resolve_base_weight_authority", "resolve_base_weight_supersession_authority", From f6bbe7f018869411ba7d0d9b2898f440cb8c6130 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 14:41:16 +0900 Subject: [PATCH 432/603] test(workforce-validation): reject binding released before final authority --- ...al_weight_component_evidence_resolution.py | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py index 0da45a297..d243312a3 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py @@ -241,9 +241,11 @@ def test_exact_receipt_identity_resolves_and_cross_checks_component_semantics() def test_component_method_or_artifact_mismatch_fails_closed() -> None: - port = _ReadPort(adjustment=_adjustment_evidence(method_reference=( - "weight_method:eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee" - ))) + port = _ReadPort( + adjustment=_adjustment_evidence( + method_reference="weight_method:eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee" + ) + ) with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="adjustment semantics"): corroborate_final_weight_component_evidence( final_weight=_final_weight(), @@ -254,9 +256,11 @@ def test_component_method_or_artifact_mismatch_fails_closed() -> None: def test_component_not_released_by_final_construction_fails_closed() -> None: - port = _ReadPort(adjustment=_adjustment_evidence( - released_at=CONSTRUCTED_AT + timedelta(microseconds=1) - )) + port = _ReadPort( + adjustment=_adjustment_evidence( + released_at=CONSTRUCTED_AT + timedelta(microseconds=1) + ) + ) with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="construction"): corroborate_final_weight_component_evidence( final_weight=_final_weight(), @@ -287,3 +291,18 @@ def test_binding_cannot_omit_a_specialized_adjustment() -> None: used_at=USED_AT, read_port=_ReadPort(), ) + + +def test_binding_cannot_be_released_before_the_final_weight_authority() -> None: + binding_release = FINAL_RELEASED_AT - timedelta(microseconds=1) + binding = _binding( + owner_contract_released_at=binding_release - timedelta(minutes=1), + released_at=binding_release, + ) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="binding.*final"): + corroborate_final_weight_component_evidence( + final_weight=_final_weight(), + binding=binding, + used_at=USED_AT, + read_port=_ReadPort(), + ) From 095bae6e7115e20b5d76cd41d87772e7c4297d97 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 14:43:09 +0900 Subject: [PATCH 433/603] fix(workforce-validation): enforce final-before-binding chronology --- .../final_weight_component_evidence_resolution.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py index 51c56a715..34b59da42 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py @@ -498,6 +498,10 @@ def corroborate_final_weight_component_evidence( raise FinalWeightComponentEvidenceIntegrityError( "component binding targets a different final-weight receipt" ) + if binding_record.released_at < final_record.released_at: + raise FinalWeightComponentEvidenceIntegrityError( + "component binding cannot be released before final-weight authority" + ) if use_instant < final_record.released_at or use_instant < binding_record.released_at: raise FinalWeightComponentEvidenceIntegrityError( "final-weight evidence and component binding must be released before use" From 65e711df426a1336c3b7c43d1dae6917a4951283 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 15:01:45 +0900 Subject: [PATCH 434/603] test(workforce-validation): require component evidence scope provenance --- ...weight_component_evidence_scope_binding.py | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_component_evidence_scope_binding.py diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_scope_binding.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_scope_binding.py new file mode 100644 index 000000000..c61c661e6 --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_scope_binding.py @@ -0,0 +1,77 @@ +"""Tenant/study provenance for normalized final-weight component evidence.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.final_weight_component_evidence_resolution import ( + AdjustmentComponentEvidence, + BaseWeightComponentEvidence, + FinalWeightComponentEvidenceIntegrityError, + _canonical_adjustment_evidence, + _canonical_base_evidence, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") +RELEASED_AT = datetime(2026, 9, 19, 4, 0, tzinfo=timezone.utc) + + +def _base() -> BaseWeightComponentEvidence: + return BaseWeightComponentEvidence( + tenant_record_id=TENANT, + validity_study_id=STUDY, + receipt_reference="base_weight_evidence_receipt:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb", + receipt_digest="2" * 64, + evidence_version=1, + method_code="inverse_probability", + method_version=1, + output_weight_artifact_digest="3" * 64, + released_at=RELEASED_AT, + ) + + +def _adjustment() -> AdjustmentComponentEvidence: + return AdjustmentComponentEvidence( + tenant_record_id=TENANT, + validity_study_id=STUDY, + evidence_kind="nonresponse_adjustment_receipt", + receipt_reference="nonresponse_adjustment_receipt:cccccccc-cccc-4ccc-8ccc-cccccccccccc", + receipt_digest="4" * 64, + evidence_version=1, + method_reference="weight_method:dddddddd-dddd-4ddd-8ddd-dddddddddddd", + method_version=1, + input_weight_artifact_digest="3" * 64, + output_weight_artifact_digest="5" * 64, + configuration_digest="6" * 64, + released_at=RELEASED_AT, + ) + + +def test_base_component_projection_carries_owner_scope() -> None: + base = _base() + assert base.tenant_record_id == TENANT + assert base.validity_study_id == STUDY + assert _canonical_base_evidence(base) == base + + +def test_adjustment_component_projection_carries_owner_scope() -> None: + adjustment = _adjustment() + assert adjustment.tenant_record_id == TENANT + assert adjustment.validity_study_id == STUDY + assert _canonical_adjustment_evidence(adjustment) == adjustment + + +def test_base_component_hidden_scope_structure_fails_closed() -> None: + forged = tuple.__new__(BaseWeightComponentEvidence, tuple(_base()) + ("hidden-scope",)) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="non-canonical"): + _canonical_base_evidence(forged) + + +def test_adjustment_component_hidden_scope_structure_fails_closed() -> None: + forged = tuple.__new__(AdjustmentComponentEvidence, tuple(_adjustment()) + ("hidden-scope",)) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="non-canonical"): + _canonical_adjustment_evidence(forged) From 313b4b9e539df795d3e47eed6d57bf3f0f59a25e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 15:05:27 +0900 Subject: [PATCH 435/603] fix(workforce-validation): bind component evidence to owner scope --- ...al_weight_component_evidence_resolution.py | 151 +++++++++++++----- 1 file changed, 114 insertions(+), 37 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py index 34b59da42..e7dc99dbc 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py @@ -1,11 +1,9 @@ """Corroborate exact final-weight component receipts against final-weight semantics. This cross-owner consistency service is used after purpose-authorized final-weight -and component-binding reads. It turns the binding's exact receipt locators into -an executable deterministic resolution contract: adapters must resolve component -evidence by receipt identity, and this service verifies that the resolved base -weight and specialized adjustments agree with the released final-weight chain. -No row-level weights or foreign source values cross this boundary. +and component-binding reads. It turns exact receipt locators into a deterministic +resolution contract and verifies both owner scope and scientific transform +semantics without copying row-level weights or foreign source values. """ from __future__ import annotations @@ -42,17 +40,19 @@ class FinalWeightComponentEvidenceNotFound(LookupError): class FinalWeightComponentEvidenceIntegrityError(RuntimeError): - """Indicate that resolved component evidence disagrees with the final-weight lineage.""" + """Indicate that resolved component evidence disagrees with final-weight authority.""" class BaseWeightComponentEvidence(tuple): - """Released base-weight receipt projection needed to reproduce the final-weight chain.""" + """Scope-bound base-weight receipt projection needed to reproduce a final weight.""" __slots__ = () def __new__( cls, *, + tenant_record_id: UUID, + validity_study_id: UUID, receipt_reference: str, receipt_digest: str, evidence_version: int, @@ -62,7 +62,9 @@ def __new__( released_at: datetime, superseded_at: datetime | None = None, ) -> BaseWeightComponentEvidence: - """Validate a value-minimized exact base-weight component projection.""" + """Validate immutable owner scope, receipt identity, semantics and chronology.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) reference = _require_reference( "receipt_reference", receipt_reference, "base_weight_evidence_receipt" ) @@ -83,58 +85,81 @@ def __new__( raise ValueError("superseded_at must be later than released_at.") return tuple.__new__( cls, - (reference, digest, version, method, method_ver, output_digest, release, cutover), + ( + tenant_identity, + study_identity, + reference, + digest, + version, + method, + method_ver, + output_digest, + release, + cutover, + ), ) + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity from native owner evidence.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity from native owner evidence.""" + return _restore_operational_uuid("validity_study_id", self[1]) + @property def receipt_reference(self) -> str: """Return the exact base-weight evidence receipt reference.""" - return self[0] + return self[2] @property def receipt_digest(self) -> str: """Return the immutable base-weight evidence receipt digest.""" - return self[1] + return self[3] @property def evidence_version(self) -> int: """Return the governed base-weight evidence version.""" - return self[2] + return self[4] @property def method_code(self) -> str: """Return the base-weight method code used by the final-weight chain.""" - return self[3] + return self[5] @property def method_version(self) -> int: """Return the base-weight method version.""" - return self[4] + return self[6] @property def output_weight_artifact_digest(self) -> str: """Return the resulting base-weight artifact digest.""" - return self[5] + return self[7] @property def released_at(self) -> datetime: """Return when this component became released authority.""" - return self[6] + return self[8] @property def superseded_at(self) -> datetime | None: """Return the exclusive end of this component's authority interval.""" - return self[7] + return self[9] class AdjustmentComponentEvidence(tuple): - """Released specialized-adjustment projection normalized to final-weight semantics.""" + """Scope-bound specialized-adjustment projection normalized to final-weight semantics.""" __slots__ = () def __new__( cls, *, + tenant_record_id: UUID, + validity_study_id: UUID, evidence_kind: str, receipt_reference: str, receipt_digest: str, @@ -147,7 +172,9 @@ def __new__( released_at: datetime, superseded_at: datetime | None = None, ) -> AdjustmentComponentEvidence: - """Validate an exact specialized receipt plus its final-weight transform semantics.""" + """Validate owner scope, exact receipt identity and transform semantics.""" + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) kind = _require_code("evidence_kind", evidence_kind) namespace = _EVIDENCE_REFERENCE_NAMESPACE_BY_KIND.get(kind) if namespace is None: @@ -179,6 +206,8 @@ def __new__( return tuple.__new__( cls, ( + tenant_identity, + study_identity, kind, reference, digest, @@ -193,60 +222,70 @@ def __new__( ), ) + @property + def tenant_record_id(self) -> UUID: + """Return a fresh tenant identity from native owner evidence.""" + return _restore_operational_uuid("tenant_record_id", self[0]) + + @property + def validity_study_id(self) -> UUID: + """Return a fresh validity-study identity from native owner evidence.""" + return _restore_operational_uuid("validity_study_id", self[1]) + @property def evidence_kind(self) -> str: """Return the governed specialized receipt family.""" - return self[0] + return self[2] @property def receipt_reference(self) -> str: """Return the exact specialized receipt reference.""" - return self[1] + return self[3] @property def receipt_digest(self) -> str: """Return the immutable specialized receipt digest.""" - return self[2] + return self[4] @property def evidence_version(self) -> int: """Return the governed specialized evidence version.""" - return self[3] + return self[5] @property def method_reference(self) -> str: """Return the released weight-method semantic used by the final chain.""" - return self[4] + return self[6] @property def method_version(self) -> int: """Return the released weight-method version.""" - return self[5] + return self[7] @property def input_weight_artifact_digest(self) -> str: """Return the transform input artifact digest.""" - return self[6] + return self[8] @property def output_weight_artifact_digest(self) -> str: """Return the transform output artifact digest.""" - return self[7] + return self[9] @property def configuration_digest(self) -> str: """Return the immutable transform configuration digest.""" - return self[8] + return self[10] @property def released_at(self) -> datetime: """Return when this specialized component became released authority.""" - return self[9] + return self[11] @property def superseded_at(self) -> datetime | None: """Return the exclusive end of this component's authority interval.""" - return self[10] + return self[12] class FinalWeightComponentEvidenceResolution(tuple): @@ -264,6 +303,8 @@ def __new__( if type(base_weight) is not BaseWeightComponentEvidence: raise TypeError("base_weight must be an exact BaseWeightComponentEvidence.") canonical_base = BaseWeightComponentEvidence( + tenant_record_id=base_weight.tenant_record_id, + validity_study_id=base_weight.validity_study_id, receipt_reference=base_weight.receipt_reference, receipt_digest=base_weight.receipt_digest, evidence_version=base_weight.evidence_version, @@ -279,8 +320,7 @@ def __new__( raise TypeError("adjustments must be an immutable tuple.") canonical_adjustments: list[AdjustmentComponentEvidence] = [] for adjustment in adjustments: - canonical = _canonical_adjustment_evidence(adjustment) - canonical_adjustments.append(canonical) + canonical_adjustments.append(_canonical_adjustment_evidence(adjustment)) return tuple.__new__(cls, (canonical_base, tuple(canonical_adjustments))) @property @@ -296,7 +336,7 @@ def adjustments(self) -> tuple[AdjustmentComponentEvidence, ...]: @runtime_checkable class FinalWeightComponentEvidenceReadPort(Protocol): - """Deterministic receipt-identity resolver for final-weight component evidence.""" + """Deterministic scope-bound receipt-identity resolver for component evidence.""" def read_base_weight_component_evidence( self, @@ -307,7 +347,7 @@ def read_base_weight_component_evidence( receipt_digest: str, evidence_version: int, ) -> BaseWeightComponentEvidence | None: - """Resolve exactly one canonical base-weight projection by immutable receipt identity.""" + """Resolve one canonical scope-bound base-weight projection by receipt identity.""" ... def read_adjustment_component_evidence( @@ -320,7 +360,7 @@ def read_adjustment_component_evidence( receipt_digest: str, evidence_version: int, ) -> AdjustmentComponentEvidence | None: - """Resolve exactly one canonical specialized projection by immutable receipt identity.""" + """Resolve one canonical scope-bound specialized projection by receipt identity.""" ... @@ -340,6 +380,8 @@ def _canonical_adjustment_evidence(value: object) -> AdjustmentComponentEvidence ) try: canonical = AdjustmentComponentEvidence( + tenant_record_id=value.tenant_record_id, + validity_study_id=value.validity_study_id, evidence_kind=value.evidence_kind, receipt_reference=value.receipt_reference, receipt_digest=value.receipt_digest, @@ -371,6 +413,8 @@ def _canonical_base_evidence(value: object) -> BaseWeightComponentEvidence: ) try: canonical = BaseWeightComponentEvidence( + tenant_record_id=value.tenant_record_id, + validity_study_id=value.validity_study_id, receipt_reference=value.receipt_reference, receipt_digest=value.receipt_digest, evidence_version=value.evidence_version, @@ -443,6 +487,27 @@ def _canonical_binding(value: object) -> FinalWeightComponentBindingAuthorityRec return canonical +def _require_component_scope( + *, + component_tenant_record_id: UUID, + component_validity_study_id: UUID, + tenant_record_id: UUID, + validity_study_id: UUID, +) -> None: + """Require normalized component evidence to prove the same owner scope as the final weight.""" + if ( + _store_operational_uuid("component tenant_record_id", component_tenant_record_id) + != _store_operational_uuid("final tenant_record_id", tenant_record_id) + or _store_operational_uuid( + "component validity_study_id", component_validity_study_id + ) + != _store_operational_uuid("final validity_study_id", validity_study_id) + ): + raise FinalWeightComponentEvidenceIntegrityError( + "component evidence belongs to another tenant or validity study" + ) + + def _require_component_valid_at_construction( *, released_at: datetime, superseded_at: datetime | None, constructed_at: datetime ) -> None: @@ -464,7 +529,7 @@ def corroborate_final_weight_component_evidence( used_at: datetime, read_port: FinalWeightComponentEvidenceReadPort, ) -> FinalWeightComponentEvidenceResolution: - """Resolve exact component receipts and prove their semantics match the final-weight chain.""" + """Resolve exact component receipts and prove scope and semantics match the final weight.""" base_capability = getattr_static(type(read_port), "read_base_weight_component_evidence", None) adjustment_capability = getattr_static( type(read_port), "read_adjustment_component_evidence", None @@ -534,6 +599,12 @@ def corroborate_final_weight_component_evidence( str(binding_values["base_weight_evidence_receipt_reference"]) ) base = _canonical_base_evidence(base_value) + _require_component_scope( + component_tenant_record_id=base.tenant_record_id, + component_validity_study_id=base.validity_study_id, + tenant_record_id=tenant_id, + validity_study_id=study_id, + ) if ( base.receipt_reference != binding_values["base_weight_evidence_receipt_reference"] or base.receipt_digest != binding_values["base_weight_evidence_receipt_digest"] @@ -602,6 +673,12 @@ def corroborate_final_weight_component_evidence( if component_value is None: raise FinalWeightComponentEvidenceNotFound(locator.evidence_receipt_reference) component = _canonical_adjustment_evidence(component_value) + _require_component_scope( + component_tenant_record_id=component.tenant_record_id, + component_validity_study_id=component.validity_study_id, + tenant_record_id=tenant_id, + validity_study_id=study_id, + ) if ( component.evidence_kind != locator.evidence_kind or component.receipt_reference != locator.evidence_receipt_reference @@ -631,4 +708,4 @@ def corroborate_final_weight_component_evidence( return FinalWeightComponentEvidenceResolution( base_weight=base, adjustments=tuple(resolved_adjustments), - ) + ) \ No newline at end of file From f6c060031819a50d2eaa1674104739c830b6f6f6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 15:06:00 +0900 Subject: [PATCH 436/603] test(workforce-validation): cover component owner scope mismatch --- ...al_weight_component_evidence_resolution.py | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py index d243312a3..b50e529ea 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py @@ -25,7 +25,9 @@ ) TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") STUDY = UUID("00000000-0000-7000-8000-0000000000f1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000f2") CONSTRUCTED_AT = datetime(2026, 9, 19, 4, 5, tzinfo=timezone.utc) FINAL_RELEASED_AT = datetime(2026, 9, 19, 4, 10, tzinfo=timezone.utc) BINDING_RELEASED_AT = datetime(2026, 9, 19, 4, 15, tzinfo=timezone.utc) @@ -155,6 +157,8 @@ def _binding(**overrides: object) -> FinalWeightComponentBindingAuthorityRecord: def _base_evidence(**overrides: object) -> BaseWeightComponentEvidence: values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, "receipt_reference": BASE_RECEIPT_REFERENCE, "receipt_digest": BASE_RECEIPT_DIGEST, "evidence_version": 1, @@ -170,6 +174,8 @@ def _base_evidence(**overrides: object) -> BaseWeightComponentEvidence: def _adjustment_evidence(**overrides: object) -> AdjustmentComponentEvidence: values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, "evidence_kind": "nonresponse_adjustment_receipt", "receipt_reference": ADJUSTMENT_RECEIPT_REFERENCE, "receipt_digest": ADJUSTMENT_RECEIPT_DIGEST, @@ -198,11 +204,15 @@ def __init__( self.base_calls: list[dict[str, object]] = [] self.adjustment_calls: list[dict[str, object]] = [] - def read_base_weight_component_evidence(self, **kwargs: object) -> BaseWeightComponentEvidence | None: + def read_base_weight_component_evidence( + self, **kwargs: object + ) -> BaseWeightComponentEvidence | None: self.base_calls.append(dict(kwargs)) return self.base - def read_adjustment_component_evidence(self, **kwargs: object) -> AdjustmentComponentEvidence | None: + def read_adjustment_component_evidence( + self, **kwargs: object + ) -> AdjustmentComponentEvidence | None: self.adjustment_calls.append(dict(kwargs)) return self.adjustment @@ -217,6 +227,8 @@ def test_exact_receipt_identity_resolves_and_cross_checks_component_semantics() ) assert isinstance(resolution, FinalWeightComponentEvidenceResolution) + assert resolution.base_weight.tenant_record_id == TENANT + assert resolution.base_weight.validity_study_id == STUDY assert resolution.base_weight.receipt_reference == BASE_RECEIPT_REFERENCE assert resolution.adjustments == (_adjustment_evidence(),) assert port.base_calls == [ @@ -306,3 +318,25 @@ def test_binding_cannot_be_released_before_the_final_weight_authority() -> None: used_at=USED_AT, read_port=_ReadPort(), ) + + +def test_base_component_from_another_study_fails_closed() -> None: + port = _ReadPort(base=_base_evidence(validity_study_id=OTHER_STUDY)) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="tenant or validity study"): + corroborate_final_weight_component_evidence( + final_weight=_final_weight(), + binding=_binding(), + used_at=USED_AT, + read_port=port, + ) + + +def test_adjustment_component_from_another_tenant_fails_closed() -> None: + port = _ReadPort(adjustment=_adjustment_evidence(tenant_record_id=OTHER_TENANT)) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="tenant or validity study"): + corroborate_final_weight_component_evidence( + final_weight=_final_weight(), + binding=_binding(), + used_at=USED_AT, + read_port=port, + ) From de1751a763da8b3866b3d547a415520d1e59e626 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 15:10:40 +0900 Subject: [PATCH 437/603] test(workforce-validation): reject truncated component scope provenance --- ..._final_weight_component_evidence_scope_binding.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_scope_binding.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_scope_binding.py index c61c661e6..3f1831343 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_scope_binding.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_scope_binding.py @@ -75,3 +75,15 @@ def test_adjustment_component_hidden_scope_structure_fails_closed() -> None: forged = tuple.__new__(AdjustmentComponentEvidence, tuple(_adjustment()) + ("hidden-scope",)) with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="non-canonical"): _canonical_adjustment_evidence(forged) + + +def test_base_component_missing_tenant_scope_coordinate_fails_closed() -> None: + forged = tuple.__new__(BaseWeightComponentEvidence, tuple(_base())[1:]) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="malformed"): + _canonical_base_evidence(forged) + + +def test_adjustment_component_missing_tenant_scope_coordinate_fails_closed() -> None: + forged = tuple.__new__(AdjustmentComponentEvidence, tuple(_adjustment())[1:]) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="malformed"): + _canonical_adjustment_evidence(forged) From 1c703e3e1a9ef3f63763b91f9eed82ec70b957e6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 15:11:38 +0900 Subject: [PATCH 438/603] test(workforce-validation): reject components superseded before governed use --- ...ight_component_evidence_use_currentness.py | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_component_evidence_use_currentness.py diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_use_currentness.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_use_currentness.py new file mode 100644 index 000000000..5b47cd887 --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_use_currentness.py @@ -0,0 +1,49 @@ +"""Governed-use currentness for exact final-weight component evidence.""" + +from __future__ import annotations + +from datetime import timedelta + +import pytest + +from orgmetra_workforce_validation_api.final_weight_component_evidence_resolution import ( + FinalWeightComponentEvidenceIntegrityError, + corroborate_final_weight_component_evidence, +) +from test_final_weight_component_evidence_resolution import ( + CONSTRUCTED_AT, + USED_AT, + _ReadPort, + _adjustment_evidence, + _base_evidence, + _binding, + _final_weight, +) + + +def test_base_component_superseded_after_construction_before_use_fails_closed() -> None: + port = _ReadPort( + base=_base_evidence(superseded_at=CONSTRUCTED_AT + timedelta(minutes=10)) + ) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="governed use"): + corroborate_final_weight_component_evidence( + final_weight=_final_weight(), + binding=_binding(), + used_at=USED_AT, + read_port=port, + ) + + +def test_adjustment_component_superseded_after_construction_before_use_fails_closed() -> None: + port = _ReadPort( + adjustment=_adjustment_evidence( + superseded_at=CONSTRUCTED_AT + timedelta(minutes=10) + ) + ) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="governed use"): + corroborate_final_weight_component_evidence( + final_weight=_final_weight(), + binding=_binding(), + used_at=USED_AT, + read_port=port, + ) From 4e41e8f427dd3047e9326dca83eeb51ef34501dc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 15:12:40 +0900 Subject: [PATCH 439/603] fix(workforce-validation): require component authority current at use --- ...nal_weight_component_evidence_resolution.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py index e7dc99dbc..849d74d58 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py @@ -522,6 +522,16 @@ def _require_component_valid_at_construction( ) +def _require_component_current_at_use( + *, superseded_at: datetime | None, used_at: datetime +) -> None: + """Require component authority to remain current at the governed scientific-use instant.""" + if superseded_at is not None and used_at >= superseded_at: + raise FinalWeightComponentEvidenceIntegrityError( + "component evidence is not current at the governed use instant" + ) + + def corroborate_final_weight_component_evidence( *, final_weight: FinalAnalysisWeightAuthorityRecord, @@ -623,6 +633,10 @@ def corroborate_final_weight_component_evidence( superseded_at=base.superseded_at, constructed_at=constructed_at, ) + _require_component_current_at_use( + superseded_at=base.superseded_at, + used_at=use_instant, + ) adjustments = final_values["adjustments"] if type(adjustments) is not tuple: @@ -703,6 +717,10 @@ def corroborate_final_weight_component_evidence( superseded_at=component.superseded_at, constructed_at=constructed_at, ) + _require_component_current_at_use( + superseded_at=component.superseded_at, + used_at=use_instant, + ) resolved_adjustments.append(component) return FinalWeightComponentEvidenceResolution( From 4d9269174600c154b17690b7f347ac64fec22480 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 16:02:52 +0900 Subject: [PATCH 440/603] test(workforce-validation): RED block forged component resolution issuance --- ..._component_evidence_resolution_issuance.py | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_issuance.py diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_issuance.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_issuance.py new file mode 100644 index 000000000..44deaa276 --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_issuance.py @@ -0,0 +1,33 @@ +"""Issuance integrity for corroborated final-weight component evidence.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.final_weight_component_evidence_resolution import ( + BaseWeightComponentEvidence, + FinalWeightComponentEvidenceResolution, +) + + +def test_corroborated_resolution_cannot_be_publicly_forged() -> None: + """Require the proof-bearing resolution to be issued only by corroboration.""" + base = BaseWeightComponentEvidence( + tenant_record_id=UUID("10000000-0000-7000-8000-000000000001"), + validity_study_id=UUID("00000000-0000-7000-8000-0000000000f1"), + receipt_reference=( + "base_weight_evidence_receipt:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" + ), + receipt_digest="2" * 64, + evidence_version=1, + method_code="inverse_probability", + method_version=1, + output_weight_artifact_digest="3" * 64, + released_at=datetime(2026, 9, 19, 4, 0, tzinfo=timezone.utc), + ) + + with pytest.raises(TypeError, match="issued only"): + FinalWeightComponentEvidenceResolution(base_weight=base, adjustments=()) From 29e2f11d4dfb335459a98c9e39301e1accee9201 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 16:04:08 +0900 Subject: [PATCH 441/603] fix(workforce-validation): seal corroborated component resolution issuance --- ...al_weight_component_evidence_resolution.py | 54 ++++++++++--------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py index 849d74d58..a7f62adce 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py @@ -289,7 +289,7 @@ def superseded_at(self) -> datetime | None: class FinalWeightComponentEvidenceResolution(tuple): - """Canonical exact component evidence corroborated against one final-weight receipt.""" + """Canonical exact component evidence issued only after governed corroboration.""" __slots__ = () @@ -299,29 +299,11 @@ def __new__( base_weight: BaseWeightComponentEvidence, adjustments: tuple[AdjustmentComponentEvidence, ...], ) -> FinalWeightComponentEvidenceResolution: - """Detach already-corroborated component projections.""" - if type(base_weight) is not BaseWeightComponentEvidence: - raise TypeError("base_weight must be an exact BaseWeightComponentEvidence.") - canonical_base = BaseWeightComponentEvidence( - tenant_record_id=base_weight.tenant_record_id, - validity_study_id=base_weight.validity_study_id, - receipt_reference=base_weight.receipt_reference, - receipt_digest=base_weight.receipt_digest, - evidence_version=base_weight.evidence_version, - method_code=base_weight.method_code, - method_version=base_weight.method_version, - output_weight_artifact_digest=base_weight.output_weight_artifact_digest, - released_at=base_weight.released_at, - superseded_at=base_weight.superseded_at, - ) - if canonical_base != base_weight: - raise ValueError("base_weight must be canonical component evidence.") - if type(adjustments) is not tuple: - raise TypeError("adjustments must be an immutable tuple.") - canonical_adjustments: list[AdjustmentComponentEvidence] = [] - for adjustment in adjustments: - canonical_adjustments.append(_canonical_adjustment_evidence(adjustment)) - return tuple.__new__(cls, (canonical_base, tuple(canonical_adjustments))) + """Reject public construction so callers cannot mint a corroborated success value.""" + raise TypeError( + "FinalWeightComponentEvidenceResolution is issued only by " + "corroborate_final_weight_component_evidence." + ) @property def base_weight(self) -> BaseWeightComponentEvidence: @@ -435,6 +417,26 @@ def _canonical_base_evidence(value: object) -> BaseWeightComponentEvidence: return canonical +def _issue_component_evidence_resolution( + *, + base_weight: BaseWeightComponentEvidence, + adjustments: tuple[AdjustmentComponentEvidence, ...], +) -> FinalWeightComponentEvidenceResolution: + """Issue a proof-bearing aggregate only from already corroborated canonical evidence.""" + canonical_base = _canonical_base_evidence(base_weight) + if type(adjustments) is not tuple: + raise FinalWeightComponentEvidenceIntegrityError( + "corroborated adjustments must be an immutable tuple" + ) + canonical_adjustments = tuple( + _canonical_adjustment_evidence(adjustment) for adjustment in adjustments + ) + return tuple.__new__( + FinalWeightComponentEvidenceResolution, + (canonical_base, canonical_adjustments), + ) + + def _canonical_final_weight(value: object) -> FinalAnalysisWeightAuthorityRecord: """Reconstruct final-weight authority before any cross-owner comparison.""" if type(value) is not FinalAnalysisWeightAuthorityRecord: @@ -723,7 +725,7 @@ def corroborate_final_weight_component_evidence( ) resolved_adjustments.append(component) - return FinalWeightComponentEvidenceResolution( + return _issue_component_evidence_resolution( base_weight=base, adjustments=tuple(resolved_adjustments), - ) \ No newline at end of file + ) From 21588e6fc0b9d6b9a2ed64dd76a7b28f4cb71176 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 17:03:02 +0900 Subject: [PATCH 442/603] test(workforce-validation): require auth before component owner reads --- ...weight_component_evidence_authorization.py | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py new file mode 100644 index 000000000..0bdfdb600 --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py @@ -0,0 +1,98 @@ +"""Purpose-bound authorization for final-weight component owner reads.""" + +from __future__ import annotations + +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.final_weight_component_evidence_resolution import ( + corroborate_final_weight_component_evidence, +) +from test_final_weight_component_evidence_resolution import ( + STUDY, + TENANT, + USED_AT, + _ReadPort, + _binding, + _final_weight, +) + +READ_FIELDS = frozenset( + { + "receipt_reference", + "receipt_digest", + "evidence_version", + "method_code", + "method_reference", + "method_version", + "input_weight_artifact_digest", + "output_weight_artifact_digest", + "configuration_digest", + "evidence_kind", + "released_at", + "superseded_at", + } +) + + +def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=tenant_record_id, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="final-weight-component-evidence-resolution-read-v1", + resource_kind="final_weight_component_evidence_resolution", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def test_denied_purpose_stops_before_any_component_owner_read() -> None: + """Reject a purpose mismatch before the base or adjustment port is invoked.""" + port = _ReadPort() + + with pytest.raises(AuthorizationDeniedError): + corroborate_final_weight_component_evidence( + principal=_principal(), + final_weight=_final_weight(), + binding=_binding(), + used_at=USED_AT, + purpose_code="compensation_administration", + policy=_policy(), + read_port=port, + ) + + assert port.base_calls == [] + assert port.adjustment_calls == [] + + +def test_cross_tenant_principal_stops_before_any_component_owner_read() -> None: + """Reject an actor from another tenant before component evidence is exposed.""" + port = _ReadPort() + + with pytest.raises(AuthorizationDeniedError): + corroborate_final_weight_component_evidence( + principal=_principal( + tenant_record_id=UUID("10000000-0000-7000-8000-000000000002") + ), + final_weight=_final_weight(), + binding=_binding(), + used_at=USED_AT, + purpose_code="selection_validity_analysis", + policy=_policy(), + read_port=port, + ) + + assert port.base_calls == [] + assert port.adjustment_calls == [] From bfc67d959636255b1d77fc5eaa3546d58a67c6ff Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 17:04:21 +0900 Subject: [PATCH 443/603] fix(workforce-validation): authorize component owner reads --- ...al_weight_component_evidence_resolution.py | 76 +++++++++++++++++-- 1 file changed, 68 insertions(+), 8 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py index a7f62adce..292d1d9cb 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py @@ -1,9 +1,10 @@ -"""Corroborate exact final-weight component receipts against final-weight semantics. +"""Authorize and corroborate exact final-weight component receipt evidence. -This cross-owner consistency service is used after purpose-authorized final-weight -and component-binding reads. It turns exact receipt locators into a deterministic -resolution contract and verifies both owner scope and scientific transform -semantics without copying row-level weights or foreign source values. +This cross-owner consistency service performs its own purpose-bound authorization +before any component owner read. It turns exact receipt locators into a +deterministic resolution contract and verifies owner scope, scientific transform +semantics, construction chronology, and governed-use currentness without copying +row-level weights or foreign source values. """ from __future__ import annotations @@ -14,6 +15,12 @@ from typing import Protocol, runtime_checkable from uuid import UUID +from orgmetra_keyverse_adapter import ( + PurposeBoundAccessPolicy, + PurposeBoundAccessRequest, + require_purpose_bound_access, +) + from .final_weight_authority import ( FinalAnalysisWeightAuthorityRecord, FinalWeightAdjustmentCoordinate, @@ -23,6 +30,8 @@ _EVIDENCE_REFERENCE_NAMESPACE_BY_KIND, ) from .registry import ( + ValidationPrincipal, + _detach_policy, _require_aware_datetime, _require_code, _restore_operational_uuid, @@ -34,6 +43,25 @@ _require_reference, ) +_RESOURCE_KIND = "final_weight_component_evidence_resolution" +_OPERATION = "read" +_READ_FIELDS = frozenset( + { + "receipt_reference", + "receipt_digest", + "evidence_version", + "method_code", + "method_reference", + "method_version", + "input_weight_artifact_digest", + "output_weight_artifact_digest", + "configuration_digest", + "evidence_kind", + "released_at", + "superseded_at", + } +) + class FinalWeightComponentEvidenceNotFound(LookupError): """Indicate that an exact bound component receipt cannot be deterministically resolved.""" @@ -536,12 +564,19 @@ def _require_component_current_at_use( def corroborate_final_weight_component_evidence( *, + principal: ValidationPrincipal, final_weight: FinalAnalysisWeightAuthorityRecord, binding: FinalWeightComponentBindingAuthorityRecord, used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, read_port: FinalWeightComponentEvidenceReadPort, ) -> FinalWeightComponentEvidenceResolution: - """Resolve exact component receipts and prove scope and semantics match the final weight.""" + """Authorize, resolve exact component receipts, and corroborate final-weight semantics.""" + if type(principal) is not ValidationPrincipal: + raise TypeError("principal must be an exact ValidationPrincipal.") + if type(policy) is not PurposeBoundAccessPolicy: + raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") base_capability = getattr_static(type(read_port), "read_base_weight_component_evidence", None) adjustment_capability = getattr_static( type(read_port), "read_adjustment_component_evidence", None @@ -557,6 +592,7 @@ def corroborate_final_weight_component_evidence( final_record = _canonical_final_weight(final_weight) binding_record = _canonical_binding(binding) use_instant = _require_aware_datetime("used_at", used_at) + purpose = _require_code("purpose_code", purpose_code) final_values = dict(final_record.fields) binding_values = dict(binding_record.fields) @@ -593,11 +629,35 @@ def corroborate_final_weight_component_evidence( ) tenant_id = _restore_operational_uuid( - "tenant_record_id", _store_operational_uuid("tenant_record_id", final_record.tenant_record_id) + "tenant_record_id", + _store_operational_uuid("tenant_record_id", final_record.tenant_record_id), ) study_id = _restore_operational_uuid( - "validity_study_id", _store_operational_uuid("validity_study_id", final_record.validity_study_id) + "validity_study_id", + _store_operational_uuid("validity_study_id", final_record.validity_study_id), ) + detached_principal = ValidationPrincipal( + tenant_record_id=principal.tenant_record_id, + actor_reference=principal.actor_reference, + granted_scope_codes=principal.granted_scope_codes, + ) + detached_policy = _detach_policy(policy) + require_purpose_bound_access( + request=PurposeBoundAccessRequest( + tenant_record_id=tenant_id, + actor_tenant_record_id=detached_principal.tenant_record_id, + resource_tenant_record_id=tenant_id, + actor_reference=detached_principal.actor_reference, + resource_reference=f"{_RESOURCE_KIND}:{study_id}", + purpose_code=purpose, + operation_code=_OPERATION, + resource_kind=_RESOURCE_KIND, + requested_fields=_READ_FIELDS, + granted_scope_codes=detached_principal.granted_scope_codes, + ), + policy=detached_policy, + ) + base_value = base_capability( read_port, tenant_record_id=tenant_id, From 9ff8d6daefff6264ba589fc7296e27a1e351c094 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 17:05:38 +0900 Subject: [PATCH 444/603] test(workforce-validation): authorize component corroboration fixtures --- ...al_weight_component_evidence_resolution.py | 112 ++++++++++-------- 1 file changed, 64 insertions(+), 48 deletions(-) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py index b50e529ea..7d14e9dff 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py @@ -7,6 +7,8 @@ import pytest +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal from orgmetra_workforce_validation_api.final_weight_authority import ( FinalAnalysisWeightAuthorityRecord, FinalWeightAdjustmentCoordinate, @@ -46,6 +48,42 @@ ADJUSTMENT_OUTPUT_DIGEST = "5" * 64 CONFIGURATION_DIGEST = "6" * 64 METHOD_REFERENCE = "weight_method:dddddddd-dddd-4ddd-8ddd-dddddddddddd" +READ_FIELDS = frozenset( + { + "receipt_reference", + "receipt_digest", + "evidence_version", + "method_code", + "method_reference", + "method_version", + "input_weight_artifact_digest", + "output_weight_artifact_digest", + "configuration_digest", + "evidence_kind", + "released_at", + "superseded_at", + } +) + + +def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: + return ValidationPrincipal( + tenant_record_id=tenant_record_id, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="final-weight-component-evidence-resolution-read-v1", + resource_kind="final_weight_component_evidence_resolution", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) def _final_weight(**overrides: object) -> FinalAnalysisWeightAuthorityRecord: @@ -217,14 +255,27 @@ def read_adjustment_component_evidence( return self.adjustment +def _corroborate( + *, + read_port: object, + final_weight: FinalAnalysisWeightAuthorityRecord | None = None, + binding: FinalWeightComponentBindingAuthorityRecord | None = None, + used_at: datetime = USED_AT, +) -> FinalWeightComponentEvidenceResolution: + return corroborate_final_weight_component_evidence( + principal=_principal(), + final_weight=_final_weight() if final_weight is None else final_weight, + binding=_binding() if binding is None else binding, + used_at=used_at, + purpose_code="selection_validity_analysis", + policy=_policy(), + read_port=read_port, + ) + + def test_exact_receipt_identity_resolves_and_cross_checks_component_semantics() -> None: port = _ReadPort() - resolution = corroborate_final_weight_component_evidence( - final_weight=_final_weight(), - binding=_binding(), - used_at=USED_AT, - read_port=port, - ) + resolution = _corroborate(read_port=port) assert isinstance(resolution, FinalWeightComponentEvidenceResolution) assert resolution.base_weight.tenant_record_id == TENANT @@ -259,12 +310,7 @@ def test_component_method_or_artifact_mismatch_fails_closed() -> None: ) ) with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="adjustment semantics"): - corroborate_final_weight_component_evidence( - final_weight=_final_weight(), - binding=_binding(), - used_at=USED_AT, - read_port=port, - ) + _corroborate(read_port=port) def test_component_not_released_by_final_construction_fails_closed() -> None: @@ -274,35 +320,20 @@ def test_component_not_released_by_final_construction_fails_closed() -> None: ) ) with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="construction"): - corroborate_final_weight_component_evidence( - final_weight=_final_weight(), - binding=_binding(), - used_at=USED_AT, - read_port=port, - ) + _corroborate(read_port=port) def test_missing_exact_component_receipt_fails_closed() -> None: port = _ReadPort() port.adjustment = None with pytest.raises(FinalWeightComponentEvidenceNotFound): - corroborate_final_weight_component_evidence( - final_weight=_final_weight(), - binding=_binding(), - used_at=USED_AT, - read_port=port, - ) + _corroborate(read_port=port) def test_binding_cannot_omit_a_specialized_adjustment() -> None: binding = _binding(adjustment_bindings=()) with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="specialized"): - corroborate_final_weight_component_evidence( - final_weight=_final_weight(), - binding=binding, - used_at=USED_AT, - read_port=_ReadPort(), - ) + _corroborate(read_port=_ReadPort(), binding=binding) def test_binding_cannot_be_released_before_the_final_weight_authority() -> None: @@ -312,31 +343,16 @@ def test_binding_cannot_be_released_before_the_final_weight_authority() -> None: released_at=binding_release, ) with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="binding.*final"): - corroborate_final_weight_component_evidence( - final_weight=_final_weight(), - binding=binding, - used_at=USED_AT, - read_port=_ReadPort(), - ) + _corroborate(read_port=_ReadPort(), binding=binding) def test_base_component_from_another_study_fails_closed() -> None: port = _ReadPort(base=_base_evidence(validity_study_id=OTHER_STUDY)) with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="tenant or validity study"): - corroborate_final_weight_component_evidence( - final_weight=_final_weight(), - binding=_binding(), - used_at=USED_AT, - read_port=port, - ) + _corroborate(read_port=port) def test_adjustment_component_from_another_tenant_fails_closed() -> None: port = _ReadPort(adjustment=_adjustment_evidence(tenant_record_id=OTHER_TENANT)) with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="tenant or validity study"): - corroborate_final_weight_component_evidence( - final_weight=_final_weight(), - binding=_binding(), - used_at=USED_AT, - read_port=port, - ) + _corroborate(read_port=port) From 41c93ba93962499ca6d2275b68f597238e988669 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 17:05:46 +0900 Subject: [PATCH 445/603] test(workforce-validation): preserve auth in component currentness cases --- ...ight_component_evidence_use_currentness.py | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_use_currentness.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_use_currentness.py index 5b47cd887..ce9f4ec88 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_use_currentness.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_use_currentness.py @@ -8,16 +8,13 @@ from orgmetra_workforce_validation_api.final_weight_component_evidence_resolution import ( FinalWeightComponentEvidenceIntegrityError, - corroborate_final_weight_component_evidence, ) from test_final_weight_component_evidence_resolution import ( CONSTRUCTED_AT, - USED_AT, _ReadPort, _adjustment_evidence, _base_evidence, - _binding, - _final_weight, + _corroborate, ) @@ -26,12 +23,7 @@ def test_base_component_superseded_after_construction_before_use_fails_closed() base=_base_evidence(superseded_at=CONSTRUCTED_AT + timedelta(minutes=10)) ) with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="governed use"): - corroborate_final_weight_component_evidence( - final_weight=_final_weight(), - binding=_binding(), - used_at=USED_AT, - read_port=port, - ) + _corroborate(read_port=port) def test_adjustment_component_superseded_after_construction_before_use_fails_closed() -> None: @@ -41,9 +33,4 @@ def test_adjustment_component_superseded_after_construction_before_use_fails_clo ) ) with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="governed use"): - corroborate_final_weight_component_evidence( - final_weight=_final_weight(), - binding=_binding(), - used_at=USED_AT, - read_port=port, - ) + _corroborate(read_port=port) From e13de7cfca9adc3fd82a5b0300711b2640edba84 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 17:06:40 +0900 Subject: [PATCH 446/603] test(workforce-validation): cover component auth type gates --- ...weight_component_evidence_authorization.py | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py index 0bdfdb600..8dbe9197f 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py @@ -12,7 +12,6 @@ corroborate_final_weight_component_evidence, ) from test_final_weight_component_evidence_resolution import ( - STUDY, TENANT, USED_AT, _ReadPort, @@ -96,3 +95,47 @@ def test_cross_tenant_principal_stops_before_any_component_owner_read() -> None: assert port.base_calls == [] assert port.adjustment_calls == [] + + +@pytest.mark.parametrize("invalid_principal", [object(), None]) +def test_noncanonical_principal_fails_before_component_owner_read( + invalid_principal: object, +) -> None: + """Require an exact principal runtime type before any native owner access.""" + port = _ReadPort() + + with pytest.raises(TypeError, match="exact ValidationPrincipal"): + corroborate_final_weight_component_evidence( + principal=invalid_principal, # type: ignore[arg-type] + final_weight=_final_weight(), + binding=_binding(), + used_at=USED_AT, + purpose_code="selection_validity_analysis", + policy=_policy(), + read_port=port, + ) + + assert port.base_calls == [] + assert port.adjustment_calls == [] + + +@pytest.mark.parametrize("invalid_policy", [object(), None]) +def test_noncanonical_policy_fails_before_component_owner_read( + invalid_policy: object, +) -> None: + """Require an exact policy runtime type before any native owner access.""" + port = _ReadPort() + + with pytest.raises(TypeError, match="exact PurposeBoundAccessPolicy"): + corroborate_final_weight_component_evidence( + principal=_principal(), + final_weight=_final_weight(), + binding=_binding(), + used_at=USED_AT, + purpose_code="selection_validity_analysis", + policy=invalid_policy, # type: ignore[arg-type] + read_port=port, + ) + + assert port.base_calls == [] + assert port.adjustment_calls == [] From 03f9d44024f40e0e49e39022bcfd2b164ec4c475 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 17:11:52 +0900 Subject: [PATCH 447/603] test(workforce-validation): bind component auth audit target to final receipt --- ...test_final_weight_component_evidence_authorization.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py index 8dbe9197f..f0291cb23 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py @@ -12,6 +12,7 @@ corroborate_final_weight_component_evidence, ) from test_final_weight_component_evidence_resolution import ( + FINAL_REFERENCE, TENANT, USED_AT, _ReadPort, @@ -58,10 +59,10 @@ def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoun def test_denied_purpose_stops_before_any_component_owner_read() -> None: - """Reject a purpose mismatch before the base or adjustment port is invoked.""" + """Reject a purpose mismatch and retain the exact final-receipt audit target.""" port = _ReadPort() - with pytest.raises(AuthorizationDeniedError): + with pytest.raises(AuthorizationDeniedError) as exc_info: corroborate_final_weight_component_evidence( principal=_principal(), final_weight=_final_weight(), @@ -72,6 +73,10 @@ def test_denied_purpose_stops_before_any_component_owner_read() -> None: read_port=port, ) + receipt_tail = FINAL_REFERENCE.partition(":")[2] + assert exc_info.value.decision.resource_reference == ( + f"final_weight_component_evidence_resolution:{receipt_tail}" + ) assert port.base_calls == [] assert port.adjustment_calls == [] From a4653faa76f7fbcd321af7088bad2145d59fb54f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 17:12:48 +0900 Subject: [PATCH 448/603] fix(workforce-validation): audit exact final receipt on component auth --- .../final_weight_component_evidence_resolution.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py index 292d1d9cb..ab810450c 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py @@ -642,13 +642,15 @@ def corroborate_final_weight_component_evidence( granted_scope_codes=principal.granted_scope_codes, ) detached_policy = _detach_policy(policy) + final_receipt_reference = str(final_values["analysis_weight_receipt_reference"]) + final_receipt_tail = final_receipt_reference.partition(":")[2] require_purpose_bound_access( request=PurposeBoundAccessRequest( tenant_record_id=tenant_id, actor_tenant_record_id=detached_principal.tenant_record_id, resource_tenant_record_id=tenant_id, actor_reference=detached_principal.actor_reference, - resource_reference=f"{_RESOURCE_KIND}:{study_id}", + resource_reference=f"{_RESOURCE_KIND}:{final_receipt_tail}", purpose_code=purpose, operation_code=_OPERATION, resource_kind=_RESOURCE_KIND, From ceb7f4b0b993e24729e2805cd09c647ff0c5bc1e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 18:04:57 +0900 Subject: [PATCH 449/603] test(workforce-validation): expose low-level resolution issuance bypass --- ..._evidence_resolution_low_level_issuance.py | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_low_level_issuance.py diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_low_level_issuance.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_low_level_issuance.py new file mode 100644 index 000000000..85a2b2234 --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_low_level_issuance.py @@ -0,0 +1,38 @@ +"""Low-level issuance integrity for corroborated final-weight component evidence.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.final_weight_component_evidence_resolution import ( + BaseWeightComponentEvidence, + FinalWeightComponentEvidenceResolution, +) + + +def _base_evidence() -> BaseWeightComponentEvidence: + """Return canonical base evidence for hostile result-allocation tests.""" + return BaseWeightComponentEvidence( + tenant_record_id=UUID("10000000-0000-7000-8000-000000000001"), + validity_study_id=UUID("00000000-0000-7000-8000-0000000000f1"), + receipt_reference=( + "base_weight_evidence_receipt:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" + ), + receipt_digest="2" * 64, + evidence_version=1, + method_code="inverse_probability", + method_version=1, + output_weight_artifact_digest="3" * 64, + released_at=datetime(2026, 9, 19, 4, 0, tzinfo=timezone.utc), + ) + + +def test_tuple_new_cannot_bypass_corroborated_resolution_issuance() -> None: + """Reject the built-in tuple constructor as an alternate proof issuer.""" + base = _base_evidence() + + with pytest.raises(TypeError): + tuple.__new__(FinalWeightComponentEvidenceResolution, (base, ())) From 5a67b2c07414a79a9b580180b56991ff6ec79156 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 18:06:16 +0900 Subject: [PATCH 450/603] fix(workforce-validation): seal component resolution issuance --- ...al_weight_component_evidence_resolution.py | 71 ++++++++++++++++--- 1 file changed, 60 insertions(+), 11 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py index ab810450c..44737b728 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py @@ -61,6 +61,7 @@ "superseded_at", } ) +_RESOLUTION_ISSUANCE_MARKER = object() class FinalWeightComponentEvidenceNotFound(LookupError): @@ -316,10 +317,10 @@ def superseded_at(self) -> datetime | None: return self[12] -class FinalWeightComponentEvidenceResolution(tuple): - """Canonical exact component evidence issued only after governed corroboration.""" +class FinalWeightComponentEvidenceResolution: + """Immutable proof-bearing component evidence issued only after governed corroboration.""" - __slots__ = () + __slots__ = ("__base_weight", "__adjustments", "__issuance_marker") def __new__( cls, @@ -328,20 +329,55 @@ def __new__( adjustments: tuple[AdjustmentComponentEvidence, ...], ) -> FinalWeightComponentEvidenceResolution: """Reject public construction so callers cannot mint a corroborated success value.""" + del base_weight, adjustments raise TypeError( "FinalWeightComponentEvidenceResolution is issued only by " "corroborate_final_weight_component_evidence." ) + def __setattr__(self, name: str, value: object) -> None: + """Reject mutation; only the private issuer may populate slots with object.__setattr__.""" + del name, value + raise AttributeError("FinalWeightComponentEvidenceResolution is immutable.") + + def __delattr__(self, name: str) -> None: + """Reject deletion from an issued corroboration result.""" + del name + raise AttributeError("FinalWeightComponentEvidenceResolution is immutable.") + + def _require_issued(self) -> None: + """Fail closed when generic allocation produced an unsealed exact runtime object.""" + try: + marker = object.__getattribute__( + self, + "_FinalWeightComponentEvidenceResolution__issuance_marker", + ) + except AttributeError as exc: + raise FinalWeightComponentEvidenceIntegrityError( + "component evidence resolution was not issued by canonical corroboration" + ) from exc + if marker is not _RESOLUTION_ISSUANCE_MARKER: + raise FinalWeightComponentEvidenceIntegrityError( + "component evidence resolution was not issued by canonical corroboration" + ) + @property def base_weight(self) -> BaseWeightComponentEvidence: - """Return the exact corroborated base-weight component.""" - return self[0] + """Return the exact corroborated base-weight component from a sealed result.""" + self._require_issued() + return object.__getattribute__( + self, + "_FinalWeightComponentEvidenceResolution__base_weight", + ) @property def adjustments(self) -> tuple[AdjustmentComponentEvidence, ...]: - """Return specialized components in final-weight sequence order.""" - return self[1] + """Return specialized components in final-weight sequence order from a sealed result.""" + self._require_issued() + return object.__getattribute__( + self, + "_FinalWeightComponentEvidenceResolution__adjustments", + ) @runtime_checkable @@ -450,7 +486,7 @@ def _issue_component_evidence_resolution( base_weight: BaseWeightComponentEvidence, adjustments: tuple[AdjustmentComponentEvidence, ...], ) -> FinalWeightComponentEvidenceResolution: - """Issue a proof-bearing aggregate only from already corroborated canonical evidence.""" + """Issue a sealed proof-bearing aggregate only from already corroborated canonical evidence.""" canonical_base = _canonical_base_evidence(base_weight) if type(adjustments) is not tuple: raise FinalWeightComponentEvidenceIntegrityError( @@ -459,10 +495,23 @@ def _issue_component_evidence_resolution( canonical_adjustments = tuple( _canonical_adjustment_evidence(adjustment) for adjustment in adjustments ) - return tuple.__new__( - FinalWeightComponentEvidenceResolution, - (canonical_base, canonical_adjustments), + resolution = object.__new__(FinalWeightComponentEvidenceResolution) + object.__setattr__( + resolution, + "_FinalWeightComponentEvidenceResolution__base_weight", + canonical_base, + ) + object.__setattr__( + resolution, + "_FinalWeightComponentEvidenceResolution__adjustments", + canonical_adjustments, + ) + object.__setattr__( + resolution, + "_FinalWeightComponentEvidenceResolution__issuance_marker", + _RESOLUTION_ISSUANCE_MARKER, ) + return resolution def _canonical_final_weight(value: object) -> FinalAnalysisWeightAuthorityRecord: From e38909985e604e0ba605f22944f39334b2aa9f08 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 18:07:19 +0900 Subject: [PATCH 451/603] test(workforce-validation): cover unsealed resolution allocation --- ...omponent_evidence_resolution_low_level_issuance.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_low_level_issuance.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_low_level_issuance.py index 85a2b2234..9c8607a76 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_low_level_issuance.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_low_level_issuance.py @@ -9,6 +9,7 @@ from orgmetra_workforce_validation_api.final_weight_component_evidence_resolution import ( BaseWeightComponentEvidence, + FinalWeightComponentEvidenceIntegrityError, FinalWeightComponentEvidenceResolution, ) @@ -36,3 +37,13 @@ def test_tuple_new_cannot_bypass_corroborated_resolution_issuance() -> None: with pytest.raises(TypeError): tuple.__new__(FinalWeightComponentEvidenceResolution, (base, ())) + + +def test_generic_object_allocation_cannot_expose_unsealed_proof() -> None: + """Fail closed if generic allocation produces an exact but unissued result object.""" + forged = object.__new__(FinalWeightComponentEvidenceResolution) + + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="not issued"): + _ = forged.base_weight + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="not issued"): + _ = forged.adjustments From ab7a968e0109176f0d5862373d0a15d3f1832e92 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 18:09:52 +0900 Subject: [PATCH 452/603] test(workforce-validation): prove issued resolution immutability --- ...omponent_evidence_resolution_low_level_issuance.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_low_level_issuance.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_low_level_issuance.py index 9c8607a76..ef8685500 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_low_level_issuance.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_low_level_issuance.py @@ -12,6 +12,7 @@ FinalWeightComponentEvidenceIntegrityError, FinalWeightComponentEvidenceResolution, ) +from test_final_weight_component_evidence_resolution import _ReadPort, _corroborate def _base_evidence() -> BaseWeightComponentEvidence: @@ -47,3 +48,13 @@ def test_generic_object_allocation_cannot_expose_unsealed_proof() -> None: _ = forged.base_weight with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="not issued"): _ = forged.adjustments + + +def test_canonical_issued_resolution_rejects_public_mutation() -> None: + """Keep corroborated result state immutable after the canonical issuer seals it.""" + resolution = _corroborate(read_port=_ReadPort()) + + with pytest.raises(AttributeError, match="immutable"): + resolution.extra = _base_evidence() # type: ignore[attr-defined] + with pytest.raises(AttributeError, match="immutable"): + del resolution.base_weight From 460856815b3c0de51eb09b025aeb281aeec691bd Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 19:03:23 +0900 Subject: [PATCH 453/603] test(workforce-validation): RED minimize component authorization fields --- ...t_component_evidence_field_minimization.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py new file mode 100644 index 000000000..5cb7410fe --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py @@ -0,0 +1,61 @@ +"""Field-minimized authorization for final-weight component evidence reads.""" + +from __future__ import annotations + +from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api.final_weight_component_evidence_resolution import ( + corroborate_final_weight_component_evidence, +) +from test_final_weight_component_evidence_resolution import ( + BASE_ARTIFACT_DIGEST, + TENANT, + USED_AT, + _ReadPort, + _binding, + _final_weight, + _principal, +) + +BASE_ONLY_READ_FIELDS = frozenset( + { + "receipt_reference", + "receipt_digest", + "evidence_version", + "method_code", + "method_version", + "output_weight_artifact_digest", + "released_at", + "superseded_at", + } +) + + +def test_base_only_resolution_does_not_request_adjustment_only_policy_fields() -> None: + """Authorize exactly the fields read when no specialized adjustment owner is consulted.""" + policy = PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="final-weight-component-evidence-resolution-base-only-v1", + resource_kind="final_weight_component_evidence_resolution", + purpose_code="selection_validity_analysis", + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=BASE_ONLY_READ_FIELDS, + ) + port = _ReadPort() + + resolution = corroborate_final_weight_component_evidence( + principal=_principal(), + final_weight=_final_weight( + adjustments=(), + final_weight_artifact_digest=BASE_ARTIFACT_DIGEST, + ), + binding=_binding(adjustment_bindings=()), + used_at=USED_AT, + purpose_code="selection_validity_analysis", + policy=policy, + read_port=port, + ) + + assert resolution.adjustments == () + assert len(port.base_calls) == 1 + assert port.adjustment_calls == [] From 8f271077d2d923f632f7971b598cc878d429ce94 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 19:04:47 +0900 Subject: [PATCH 454/603] fix(workforce-validation): minimize component authorization fields --- ...al_weight_component_evidence_resolution.py | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py index 44737b728..1397bde6b 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py @@ -45,12 +45,23 @@ _RESOURCE_KIND = "final_weight_component_evidence_resolution" _OPERATION = "read" -_READ_FIELDS = frozenset( +_BASE_READ_FIELDS = frozenset( { "receipt_reference", "receipt_digest", "evidence_version", "method_code", + "method_version", + "output_weight_artifact_digest", + "released_at", + "superseded_at", + } +) +_ADJUSTMENT_READ_FIELDS = frozenset( + { + "receipt_reference", + "receipt_digest", + "evidence_version", "method_reference", "method_version", "input_weight_artifact_digest", @@ -644,6 +655,12 @@ def corroborate_final_weight_component_evidence( purpose = _require_code("purpose_code", purpose_code) final_values = dict(final_record.fields) binding_values = dict(binding_record.fields) + requested_fields = _BASE_READ_FIELDS + if any( + adjustment.evidence_kind in _EVIDENCE_REFERENCE_NAMESPACE_BY_KIND + for adjustment in final_values["adjustments"] + ): + requested_fields = _BASE_READ_FIELDS | _ADJUSTMENT_READ_FIELDS if ( _store_operational_uuid("final tenant_record_id", final_record.tenant_record_id) @@ -703,7 +720,7 @@ def corroborate_final_weight_component_evidence( purpose_code=purpose, operation_code=_OPERATION, resource_kind=_RESOURCE_KIND, - requested_fields=_READ_FIELDS, + requested_fields=requested_fields, granted_scope_codes=detached_principal.granted_scope_codes, ), policy=detached_policy, From 8be428ddd7c0a6efbc22e1eb1795441b581913aa Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 19:08:46 +0900 Subject: [PATCH 455/603] test(workforce-validation): RED minimize unused component capability --- ...t_component_evidence_field_minimization.py | 60 ++++++++++++++++--- 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py index 5cb7410fe..f6bba75f7 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py @@ -2,8 +2,11 @@ from __future__ import annotations +from uuid import UUID + from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy from orgmetra_workforce_validation_api.final_weight_component_evidence_resolution import ( + BaseWeightComponentEvidence, corroborate_final_weight_component_evidence, ) from test_final_weight_component_evidence_resolution import ( @@ -11,6 +14,7 @@ TENANT, USED_AT, _ReadPort, + _base_evidence, _binding, _final_weight, _principal, @@ -30,9 +34,33 @@ ) -def test_base_only_resolution_does_not_request_adjustment_only_policy_fields() -> None: - """Authorize exactly the fields read when no specialized adjustment owner is consulted.""" - policy = PurposeBoundAccessPolicy( +class _BaseOnlyReadPort: + def __init__(self) -> None: + self.base_calls: list[dict[str, object]] = [] + + def read_base_weight_component_evidence( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + receipt_reference: str, + receipt_digest: str, + evidence_version: int, + ) -> BaseWeightComponentEvidence | None: + self.base_calls.append( + { + "tenant_record_id": tenant_record_id, + "validity_study_id": validity_study_id, + "receipt_reference": receipt_reference, + "receipt_digest": receipt_digest, + "evidence_version": evidence_version, + } + ) + return _base_evidence() + + +def _base_only_policy() -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( tenant_record_id=TENANT, policy_version_code="final-weight-component-evidence-resolution-base-only-v1", resource_kind="final_weight_component_evidence_resolution", @@ -41,9 +69,10 @@ def test_base_only_resolution_does_not_request_adjustment_only_policy_fields() - required_scope_code="orgmetra.workforce_validation.read", permitted_fields=BASE_ONLY_READ_FIELDS, ) - port = _ReadPort() - resolution = corroborate_final_weight_component_evidence( + +def _corroborate_base_only(*, read_port: object): + return corroborate_final_weight_component_evidence( principal=_principal(), final_weight=_final_weight( adjustments=(), @@ -52,10 +81,27 @@ def test_base_only_resolution_does_not_request_adjustment_only_policy_fields() - binding=_binding(adjustment_bindings=()), used_at=USED_AT, purpose_code="selection_validity_analysis", - policy=policy, - read_port=port, + policy=_base_only_policy(), + read_port=read_port, ) + +def test_base_only_resolution_does_not_request_adjustment_only_policy_fields() -> None: + """Authorize exactly the fields read when no specialized adjustment owner is consulted.""" + port = _ReadPort() + + resolution = _corroborate_base_only(read_port=port) + assert resolution.adjustments == () assert len(port.base_calls) == 1 assert port.adjustment_calls == [] + + +def test_base_only_resolution_does_not_require_unused_adjustment_capability() -> None: + """Accept a base-only port when the final-weight lineage cannot invoke an adjustment owner.""" + port = _BaseOnlyReadPort() + + resolution = _corroborate_base_only(read_port=port) + + assert resolution.adjustments == () + assert len(port.base_calls) == 1 From 9b19ae464d32b5d8863552a443cfa7551eafe89c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 19:10:05 +0900 Subject: [PATCH 456/603] test(workforce-validation): preserve composite component port contract --- ...t_component_evidence_field_minimization.py | 60 +++---------------- 1 file changed, 7 insertions(+), 53 deletions(-) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py index f6bba75f7..5cb7410fe 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py @@ -2,11 +2,8 @@ from __future__ import annotations -from uuid import UUID - from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy from orgmetra_workforce_validation_api.final_weight_component_evidence_resolution import ( - BaseWeightComponentEvidence, corroborate_final_weight_component_evidence, ) from test_final_weight_component_evidence_resolution import ( @@ -14,7 +11,6 @@ TENANT, USED_AT, _ReadPort, - _base_evidence, _binding, _final_weight, _principal, @@ -34,33 +30,9 @@ ) -class _BaseOnlyReadPort: - def __init__(self) -> None: - self.base_calls: list[dict[str, object]] = [] - - def read_base_weight_component_evidence( - self, - *, - tenant_record_id: UUID, - validity_study_id: UUID, - receipt_reference: str, - receipt_digest: str, - evidence_version: int, - ) -> BaseWeightComponentEvidence | None: - self.base_calls.append( - { - "tenant_record_id": tenant_record_id, - "validity_study_id": validity_study_id, - "receipt_reference": receipt_reference, - "receipt_digest": receipt_digest, - "evidence_version": evidence_version, - } - ) - return _base_evidence() - - -def _base_only_policy() -> PurposeBoundAccessPolicy: - return PurposeBoundAccessPolicy( +def test_base_only_resolution_does_not_request_adjustment_only_policy_fields() -> None: + """Authorize exactly the fields read when no specialized adjustment owner is consulted.""" + policy = PurposeBoundAccessPolicy( tenant_record_id=TENANT, policy_version_code="final-weight-component-evidence-resolution-base-only-v1", resource_kind="final_weight_component_evidence_resolution", @@ -69,10 +41,9 @@ def _base_only_policy() -> PurposeBoundAccessPolicy: required_scope_code="orgmetra.workforce_validation.read", permitted_fields=BASE_ONLY_READ_FIELDS, ) + port = _ReadPort() - -def _corroborate_base_only(*, read_port: object): - return corroborate_final_weight_component_evidence( + resolution = corroborate_final_weight_component_evidence( principal=_principal(), final_weight=_final_weight( adjustments=(), @@ -81,27 +52,10 @@ def _corroborate_base_only(*, read_port: object): binding=_binding(adjustment_bindings=()), used_at=USED_AT, purpose_code="selection_validity_analysis", - policy=_base_only_policy(), - read_port=read_port, + policy=policy, + read_port=port, ) - -def test_base_only_resolution_does_not_request_adjustment_only_policy_fields() -> None: - """Authorize exactly the fields read when no specialized adjustment owner is consulted.""" - port = _ReadPort() - - resolution = _corroborate_base_only(read_port=port) - assert resolution.adjustments == () assert len(port.base_calls) == 1 assert port.adjustment_calls == [] - - -def test_base_only_resolution_does_not_require_unused_adjustment_capability() -> None: - """Accept a base-only port when the final-weight lineage cannot invoke an adjustment owner.""" - port = _BaseOnlyReadPort() - - resolution = _corroborate_base_only(read_port=port) - - assert resolution.adjustments == () - assert len(port.base_calls) == 1 From b4145493988bee3dd869bc7d6688f6fbe7278235 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 20:04:44 +0900 Subject: [PATCH 457/603] test(workforce-validation): require authorization for component scope fields --- ...t_component_evidence_field_minimization.py | 46 ++++++++++++++++--- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py index 5cb7410fe..5ab973b3b 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py @@ -2,7 +2,9 @@ from __future__ import annotations -from orgmetra_keyverse_adapter import PurposeBoundAccessPolicy +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy from orgmetra_workforce_validation_api.final_weight_component_evidence_resolution import ( corroborate_final_weight_component_evidence, ) @@ -18,6 +20,8 @@ BASE_ONLY_READ_FIELDS = frozenset( { + "tenant_record_id", + "validity_study_id", "receipt_reference", "receipt_digest", "evidence_version", @@ -30,20 +34,20 @@ ) -def test_base_only_resolution_does_not_request_adjustment_only_policy_fields() -> None: - """Authorize exactly the fields read when no specialized adjustment owner is consulted.""" - policy = PurposeBoundAccessPolicy( +def _base_only_policy(*, permitted_fields: frozenset[str]) -> PurposeBoundAccessPolicy: + return PurposeBoundAccessPolicy( tenant_record_id=TENANT, policy_version_code="final-weight-component-evidence-resolution-base-only-v1", resource_kind="final_weight_component_evidence_resolution", purpose_code="selection_validity_analysis", operation_code="read", required_scope_code="orgmetra.workforce_validation.read", - permitted_fields=BASE_ONLY_READ_FIELDS, + permitted_fields=permitted_fields, ) - port = _ReadPort() - resolution = corroborate_final_weight_component_evidence( + +def _corroborate_base_only(*, policy: PurposeBoundAccessPolicy, port: _ReadPort): + return corroborate_final_weight_component_evidence( principal=_principal(), final_weight=_final_weight( adjustments=(), @@ -56,6 +60,34 @@ def test_base_only_resolution_does_not_request_adjustment_only_policy_fields() - read_port=port, ) + +def test_base_only_resolution_does_not_request_adjustment_only_policy_fields() -> None: + """Authorize exactly the base projection fields when no adjustment owner is consulted.""" + port = _ReadPort() + + resolution = _corroborate_base_only( + policy=_base_only_policy(permitted_fields=BASE_ONLY_READ_FIELDS), + port=port, + ) + assert resolution.adjustments == () assert len(port.base_calls) == 1 assert port.adjustment_calls == [] + + +@pytest.mark.parametrize("omitted_scope_field", ["tenant_record_id", "validity_study_id"]) +def test_base_only_resolution_authorizes_native_owner_scope_fields_before_read( + omitted_scope_field: str, +) -> None: + """Deny before owner access when policy omits a scope field consumed from the projection.""" + port = _ReadPort() + permitted_fields = BASE_ONLY_READ_FIELDS - {omitted_scope_field} + + with pytest.raises(AuthorizationDeniedError): + _corroborate_base_only( + policy=_base_only_policy(permitted_fields=permitted_fields), + port=port, + ) + + assert port.base_calls == [] + assert port.adjustment_calls == [] From 4ec16e61f40265675df0e8464d4ee2bd314fcca3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 20:06:23 +0900 Subject: [PATCH 458/603] fix(workforce-validation): authorize native component scope fields --- .../final_weight_component_evidence_resolution.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py index 1397bde6b..92890fd97 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py @@ -47,6 +47,8 @@ _OPERATION = "read" _BASE_READ_FIELDS = frozenset( { + "tenant_record_id", + "validity_study_id", "receipt_reference", "receipt_digest", "evidence_version", @@ -59,6 +61,8 @@ ) _ADJUSTMENT_READ_FIELDS = frozenset( { + "tenant_record_id", + "validity_study_id", "receipt_reference", "receipt_digest", "evidence_version", From 2e00a607bd85124141816a1df1963fc3f8f9f101 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 21:04:53 +0900 Subject: [PATCH 459/603] test(workforce-validation): require owner provenance before component reads --- ...ght_component_evidence_owner_provenance.py | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_component_evidence_owner_provenance.py diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_owner_provenance.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_owner_provenance.py new file mode 100644 index 000000000..91cc73f96 --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_owner_provenance.py @@ -0,0 +1,82 @@ +"""Authoritative owner provenance for final-weight component corroboration.""" + +from __future__ import annotations + +import pytest + +from orgmetra_workforce_validation_api.final_weight_component_evidence_resolution import ( + FinalWeightComponentEvidenceIntegrityError, + FinalWeightComponentEvidenceNotFound, + corroborate_final_weight_component_evidence, +) +from test_final_weight_component_evidence_resolution import ( + USED_AT, + _ReadPort, + _binding, + _final_weight, + _policy, + _principal, +) + + +class _OwnerProvenanceReadPort(_ReadPort): + """Expose independent final-weight and binding owner reads before component reads.""" + + def __init__(self, *, final_owner: object, binding_owner: object) -> None: + super().__init__() + self.final_owner = final_owner + self.binding_owner = binding_owner + self.final_owner_calls: list[dict[str, object]] = [] + self.binding_owner_calls: list[dict[str, object]] = [] + + def read_final_analysis_weight_authority(self, **kwargs: object): + """Return owner-confirmed final-weight authority or an explicit miss.""" + self.final_owner_calls.append(dict(kwargs)) + return self.final_owner + + def read_final_weight_component_binding_authority(self, **kwargs: object): + """Return owner-confirmed component-binding authority or an explicit miss.""" + self.binding_owner_calls.append(dict(kwargs)) + return self.binding_owner + + +def _corroborate_with(port: _OwnerProvenanceReadPort) -> None: + corroborate_final_weight_component_evidence( + principal=_principal(), + final_weight=_final_weight(), + binding=_binding(), + used_at=USED_AT, + purpose_code="selection_validity_analysis", + policy=_policy(), + read_port=port, + ) + + +def test_missing_final_weight_owner_authority_stops_before_component_reads() -> None: + """Canonical caller records cannot substitute for released final-weight owner truth.""" + port = _OwnerProvenanceReadPort(final_owner=None, binding_owner=_binding()) + + with pytest.raises(FinalWeightComponentEvidenceNotFound, match="final-weight"): + _corroborate_with(port) + + assert len(port.final_owner_calls) == 1 + assert port.binding_owner_calls == [] + assert port.base_calls == [] + assert port.adjustment_calls == [] + + +def test_conflicting_binding_owner_authority_stops_before_component_reads() -> None: + """A locally canonical binding must exactly match the native owner record.""" + conflicting_binding = _binding(binding_digest="b" * 64) + port = _OwnerProvenanceReadPort( + final_owner=_final_weight(), + binding_owner=conflicting_binding, + ) + + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="binding owner"): + _corroborate_with(port) + + assert len(port.final_owner_calls) == 1 + assert len(port.binding_owner_calls) == 1 + assert port.base_calls == [] + assert port.adjustment_calls == [] From b54da403424f3865d4b8ac876d80e958f1e490d2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 21:06:16 +0900 Subject: [PATCH 460/603] test(workforce-validation): align component policy fixture with scope authorization --- .../tests/test_final_weight_component_evidence_resolution.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py index 7d14e9dff..dfd421bba 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py @@ -50,6 +50,8 @@ METHOD_REFERENCE = "weight_method:dddddddd-dddd-4ddd-8ddd-dddddddddddd" READ_FIELDS = frozenset( { + "tenant_record_id", + "validity_study_id", "receipt_reference", "receipt_digest", "evidence_version", From 9ce3b31568545ef8d1d144c957305e9d41241d76 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 21:06:28 +0900 Subject: [PATCH 461/603] test(workforce-validation): authorize scope fields in component fixtures --- .../tests/test_final_weight_component_evidence_authorization.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py index f0291cb23..3b7842ae0 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py @@ -22,6 +22,8 @@ READ_FIELDS = frozenset( { + "tenant_record_id", + "validity_study_id", "receipt_reference", "receipt_digest", "evidence_version", From b07f9912880bc6dfedc1006a36aee62f5572e465 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 21:07:07 +0900 Subject: [PATCH 462/603] test(workforce-validation): provide owner provenance fixtures for corroboration --- ...al_weight_component_evidence_resolution.py | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py index dfd421bba..a889f5af9 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py @@ -241,9 +241,25 @@ def __init__( ) -> None: self.base = _base_evidence() if base is None else base self.adjustment = _adjustment_evidence() if adjustment is None else adjustment + self.final_owner = _final_weight() + self.binding_owner = _binding() + self.final_owner_calls: list[dict[str, object]] = [] + self.binding_owner_calls: list[dict[str, object]] = [] self.base_calls: list[dict[str, object]] = [] self.adjustment_calls: list[dict[str, object]] = [] + def read_final_analysis_weight_authority( + self, **kwargs: object + ) -> FinalAnalysisWeightAuthorityRecord | None: + self.final_owner_calls.append(dict(kwargs)) + return self.final_owner + + def read_final_weight_component_binding_authority( + self, **kwargs: object + ) -> FinalWeightComponentBindingAuthorityRecord | None: + self.binding_owner_calls.append(dict(kwargs)) + return self.binding_owner + def read_base_weight_component_evidence( self, **kwargs: object ) -> BaseWeightComponentEvidence | None: @@ -264,10 +280,15 @@ def _corroborate( binding: FinalWeightComponentBindingAuthorityRecord | None = None, used_at: datetime = USED_AT, ) -> FinalWeightComponentEvidenceResolution: + final_record = _final_weight() if final_weight is None else final_weight + binding_record = _binding() if binding is None else binding + if isinstance(read_port, _ReadPort): + read_port.final_owner = final_record + read_port.binding_owner = binding_record return corroborate_final_weight_component_evidence( principal=_principal(), - final_weight=_final_weight() if final_weight is None else final_weight, - binding=_binding() if binding is None else binding, + final_weight=final_record, + binding=binding_record, used_at=used_at, purpose_code="selection_validity_analysis", policy=_policy(), @@ -284,6 +305,8 @@ def test_exact_receipt_identity_resolves_and_cross_checks_component_semantics() assert resolution.base_weight.validity_study_id == STUDY assert resolution.base_weight.receipt_reference == BASE_RECEIPT_REFERENCE assert resolution.adjustments == (_adjustment_evidence(),) + assert len(port.final_owner_calls) == 1 + assert len(port.binding_owner_calls) == 1 assert port.base_calls == [ { "tenant_record_id": TENANT, From b7b0adc3f68164c2d8ea334afc1de77cbfde8175 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 21:07:17 +0900 Subject: [PATCH 463/603] test(workforce-validation): bind base-only fixtures to owner provenance --- ...ht_component_evidence_field_minimization.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py index 5ab973b3b..d67950de5 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py @@ -47,13 +47,17 @@ def _base_only_policy(*, permitted_fields: frozenset[str]) -> PurposeBoundAccess def _corroborate_base_only(*, policy: PurposeBoundAccessPolicy, port: _ReadPort): + final_record = _final_weight( + adjustments=(), + final_weight_artifact_digest=BASE_ARTIFACT_DIGEST, + ) + binding_record = _binding(adjustment_bindings=()) + port.final_owner = final_record + port.binding_owner = binding_record return corroborate_final_weight_component_evidence( principal=_principal(), - final_weight=_final_weight( - adjustments=(), - final_weight_artifact_digest=BASE_ARTIFACT_DIGEST, - ), - binding=_binding(adjustment_bindings=()), + final_weight=final_record, + binding=binding_record, used_at=USED_AT, purpose_code="selection_validity_analysis", policy=policy, @@ -71,6 +75,8 @@ def test_base_only_resolution_does_not_request_adjustment_only_policy_fields() - ) assert resolution.adjustments == () + assert len(port.final_owner_calls) == 1 + assert len(port.binding_owner_calls) == 1 assert len(port.base_calls) == 1 assert port.adjustment_calls == [] @@ -89,5 +95,7 @@ def test_base_only_resolution_authorizes_native_owner_scope_fields_before_read( port=port, ) + assert port.final_owner_calls == [] + assert port.binding_owner_calls == [] assert port.base_calls == [] assert port.adjustment_calls == [] From 9917d54461ed4009e8affb99a7cb891944cb2b66 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 21:08:21 +0900 Subject: [PATCH 464/603] fix(workforce-validation): re-resolve final weight and binding before proof issuance --- ...al_weight_component_evidence_resolution.py | 98 +++++++++++++++++-- 1 file changed, 90 insertions(+), 8 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py index 92890fd97..0607ac161 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py @@ -1,10 +1,10 @@ """Authorize and corroborate exact final-weight component receipt evidence. This cross-owner consistency service performs its own purpose-bound authorization -before any component owner read. It turns exact receipt locators into a -deterministic resolution contract and verifies owner scope, scientific transform -semantics, construction chronology, and governed-use currentness without copying -row-level weights or foreign source values. +before any owner read. It re-resolves final-weight and component-binding authority, +turns exact component receipt locators into a deterministic resolution contract, +and verifies owner scope, scientific transform semantics, construction chronology, +and governed-use currentness without copying row-level weights or foreign source values. """ from __future__ import annotations @@ -80,11 +80,11 @@ class FinalWeightComponentEvidenceNotFound(LookupError): - """Indicate that an exact bound component receipt cannot be deterministically resolved.""" + """Indicate that exact authoritative evidence cannot be deterministically resolved.""" class FinalWeightComponentEvidenceIntegrityError(RuntimeError): - """Indicate that resolved component evidence disagrees with final-weight authority.""" + """Indicate that resolved evidence disagrees with final-weight authority.""" class BaseWeightComponentEvidence(tuple): @@ -397,7 +397,31 @@ def adjustments(self) -> tuple[AdjustmentComponentEvidence, ...]: @runtime_checkable class FinalWeightComponentEvidenceReadPort(Protocol): - """Deterministic scope-bound receipt-identity resolver for component evidence.""" + """Owner-resolution contract for final-weight provenance and component evidence.""" + + def read_final_analysis_weight_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + analysis_weight_receipt_reference: str, + analysis_weight_receipt_digest: str, + evidence_version: int, + ) -> FinalAnalysisWeightAuthorityRecord | None: + """Resolve the exact released final-weight owner record by immutable receipt identity.""" + ... + + def read_final_weight_component_binding_authority( + self, + *, + tenant_record_id: UUID, + validity_study_id: UUID, + analysis_weight_receipt_reference: str, + analysis_weight_receipt_digest: str, + analysis_weight_evidence_version: int, + ) -> FinalWeightComponentBindingAuthorityRecord | None: + """Resolve the exact released binding owner record for the final-weight receipt.""" + ... def read_base_weight_component_evidence( self, @@ -425,6 +449,12 @@ def read_adjustment_component_evidence( ... +_FINAL_WEIGHT_READ_CAPABILITY = getattr_static( + FinalWeightComponentEvidenceReadPort, "read_final_analysis_weight_authority" +) +_BINDING_READ_CAPABILITY = getattr_static( + FinalWeightComponentEvidenceReadPort, "read_final_weight_component_binding_authority" +) _BASE_READ_CAPABILITY = getattr_static( FinalWeightComponentEvidenceReadPort, "read_base_weight_component_evidence" ) @@ -636,15 +666,31 @@ def corroborate_final_weight_component_evidence( policy: PurposeBoundAccessPolicy, read_port: FinalWeightComponentEvidenceReadPort, ) -> FinalWeightComponentEvidenceResolution: - """Authorize, resolve exact component receipts, and corroborate final-weight semantics.""" + """Authorize, owner-resolve final/binding authority, and corroborate component evidence.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") if type(policy) is not PurposeBoundAccessPolicy: raise TypeError("policy must be an exact PurposeBoundAccessPolicy.") + final_authority_capability = getattr_static( + type(read_port), "read_final_analysis_weight_authority", None + ) + binding_authority_capability = getattr_static( + type(read_port), "read_final_weight_component_binding_authority", None + ) base_capability = getattr_static(type(read_port), "read_base_weight_component_evidence", None) adjustment_capability = getattr_static( type(read_port), "read_adjustment_component_evidence", None ) + if ( + type(final_authority_capability) is not FunctionType + or final_authority_capability is _FINAL_WEIGHT_READ_CAPABILITY + ): + raise TypeError("read_port must expose read_final_analysis_weight_authority.") + if ( + type(binding_authority_capability) is not FunctionType + or binding_authority_capability is _BINDING_READ_CAPABILITY + ): + raise TypeError("read_port must expose read_final_weight_component_binding_authority.") if type(base_capability) is not FunctionType or base_capability is _BASE_READ_CAPABILITY: raise TypeError("read_port must expose read_base_weight_component_evidence.") if ( @@ -730,6 +776,42 @@ def corroborate_final_weight_component_evidence( policy=detached_policy, ) + owner_final_value = final_authority_capability( + read_port, + tenant_record_id=tenant_id, + validity_study_id=study_id, + analysis_weight_receipt_reference=final_values["analysis_weight_receipt_reference"], + analysis_weight_receipt_digest=final_values["analysis_weight_receipt_digest"], + evidence_version=final_values["evidence_version"], + ) + if owner_final_value is None: + raise FinalWeightComponentEvidenceNotFound( + f"final-weight:{final_values['analysis_weight_receipt_reference']}" + ) + owner_final = _canonical_final_weight(owner_final_value) + if owner_final != final_record: + raise FinalWeightComponentEvidenceIntegrityError( + "final-weight owner authority disagrees with supplied final-weight evidence" + ) + + owner_binding_value = binding_authority_capability( + read_port, + tenant_record_id=tenant_id, + validity_study_id=study_id, + analysis_weight_receipt_reference=final_values["analysis_weight_receipt_reference"], + analysis_weight_receipt_digest=final_values["analysis_weight_receipt_digest"], + analysis_weight_evidence_version=final_values["evidence_version"], + ) + if owner_binding_value is None: + raise FinalWeightComponentEvidenceNotFound( + f"binding:{final_values['analysis_weight_receipt_reference']}" + ) + owner_binding = _canonical_binding(owner_binding_value) + if owner_binding != binding_record: + raise FinalWeightComponentEvidenceIntegrityError( + "binding owner authority disagrees with supplied component binding evidence" + ) + base_value = base_capability( read_port, tenant_record_id=tenant_id, From 7947cb476164ac2692127a901f3d2787c68a2161 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 21:10:48 +0900 Subject: [PATCH 465/603] test(workforce-validation): authorize owner provenance before re-resolution --- ...t_component_evidence_field_minimization.py | 73 ++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py index d67950de5..671179644 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_field_minimization.py @@ -18,7 +18,59 @@ _principal, ) -BASE_ONLY_READ_FIELDS = frozenset( +OWNER_PROVENANCE_READ_FIELDS = frozenset( + { + "tenant_record_id", + "validity_study_id", + "analysis_weight_receipt_reference", + "analysis_weight_receipt_digest", + "analysis_weight_evidence_version", + "evidence_version", + "estimand_reference", + "estimand_digest", + "estimand_scope_code", + "target_population_reference", + "target_population_digest", + "analysis_unit_code", + "analysis_window_reference", + "reference_duration_reference", + "reference_duration_digest", + "eligible_case_set_digest", + "analytic_case_occurrence_set_digest", + "source_universe_receipt_reference", + "source_universe_receipt_version", + "source_universe_receipt_digest", + "sampling_design_receipt_reference", + "sampling_design_receipt_version", + "sampling_design_receipt_digest", + "base_weight_method_code", + "base_weight_method_version", + "base_weight_evidence_digest", + "base_weight_artifact_digest", + "adjustments", + "final_weight_artifact_digest", + "weight_eligibility_receipt_reference", + "weight_eligibility_receipt_digest", + "analytic_case_count", + "constructed_at", + "correction_sequence", + "supersedes_receipt_digest", + "binding_reference", + "binding_digest", + "binding_version", + "base_weight_evidence_receipt_reference", + "base_weight_evidence_receipt_digest", + "base_weight_evidence_version", + "adjustment_bindings", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + } +) +BASE_COMPONENT_READ_FIELDS = frozenset( { "tenant_record_id", "validity_study_id", @@ -32,6 +84,7 @@ "superseded_at", } ) +BASE_ONLY_READ_FIELDS = OWNER_PROVENANCE_READ_FIELDS | BASE_COMPONENT_READ_FIELDS def _base_only_policy(*, permitted_fields: frozenset[str]) -> PurposeBoundAccessPolicy: @@ -66,7 +119,7 @@ def _corroborate_base_only(*, policy: PurposeBoundAccessPolicy, port: _ReadPort) def test_base_only_resolution_does_not_request_adjustment_only_policy_fields() -> None: - """Authorize exactly the base projection fields when no adjustment owner is consulted.""" + """Authorize owner provenance plus base projection fields when no adjustment owner is read.""" port = _ReadPort() resolution = _corroborate_base_only( @@ -81,6 +134,22 @@ def test_base_only_resolution_does_not_request_adjustment_only_policy_fields() - assert port.adjustment_calls == [] +def test_component_only_policy_cannot_authorize_owner_provenance_reads() -> None: + """Deny before all owner access when final/binding provenance fields are not permitted.""" + port = _ReadPort() + + with pytest.raises(AuthorizationDeniedError): + _corroborate_base_only( + policy=_base_only_policy(permitted_fields=BASE_COMPONENT_READ_FIELDS), + port=port, + ) + + assert port.final_owner_calls == [] + assert port.binding_owner_calls == [] + assert port.base_calls == [] + assert port.adjustment_calls == [] + + @pytest.mark.parametrize("omitted_scope_field", ["tenant_record_id", "validity_study_id"]) def test_base_only_resolution_authorizes_native_owner_scope_fields_before_read( omitted_scope_field: str, From bdc07fc4c365c46253e565cfb861c4d8f16b5f3b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 21:12:08 +0900 Subject: [PATCH 466/603] fix(workforce-validation): authorize owner provenance fields before reads --- .../final_weight_component_evidence_resolution.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py index 0607ac161..a679d7928 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py @@ -24,10 +24,12 @@ from .final_weight_authority import ( FinalAnalysisWeightAuthorityRecord, FinalWeightAdjustmentCoordinate, + _READ_FIELDS as _FINAL_WEIGHT_OWNER_READ_FIELDS, ) from .final_weight_component_binding_authority import ( FinalWeightComponentBindingAuthorityRecord, _EVIDENCE_REFERENCE_NAMESPACE_BY_KIND, + _READ_FIELDS as _BINDING_OWNER_READ_FIELDS, ) from .registry import ( ValidationPrincipal, @@ -45,6 +47,10 @@ _RESOURCE_KIND = "final_weight_component_evidence_resolution" _OPERATION = "read" +_OWNER_SCOPE_FIELDS = frozenset({"tenant_record_id", "validity_study_id"}) +_OWNER_PROVENANCE_READ_FIELDS = ( + _OWNER_SCOPE_FIELDS | _FINAL_WEIGHT_OWNER_READ_FIELDS | _BINDING_OWNER_READ_FIELDS +) _BASE_READ_FIELDS = frozenset( { "tenant_record_id", @@ -705,12 +711,12 @@ def corroborate_final_weight_component_evidence( purpose = _require_code("purpose_code", purpose_code) final_values = dict(final_record.fields) binding_values = dict(binding_record.fields) - requested_fields = _BASE_READ_FIELDS + requested_fields = _OWNER_PROVENANCE_READ_FIELDS | _BASE_READ_FIELDS if any( adjustment.evidence_kind in _EVIDENCE_REFERENCE_NAMESPACE_BY_KIND for adjustment in final_values["adjustments"] ): - requested_fields = _BASE_READ_FIELDS | _ADJUSTMENT_READ_FIELDS + requested_fields = requested_fields | _ADJUSTMENT_READ_FIELDS if ( _store_operational_uuid("final tenant_record_id", final_record.tenant_record_id) From 43531a6277d5231466dba471dcfbd956439d1737 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 21:12:48 +0900 Subject: [PATCH 467/603] test(workforce-validation): permit exact owner provenance fields in corroboration --- ...al_weight_component_evidence_resolution.py | 55 ++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py index a889f5af9..3d4e9e894 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution.py @@ -48,7 +48,59 @@ ADJUSTMENT_OUTPUT_DIGEST = "5" * 64 CONFIGURATION_DIGEST = "6" * 64 METHOD_REFERENCE = "weight_method:dddddddd-dddd-4ddd-8ddd-dddddddddddd" -READ_FIELDS = frozenset( +OWNER_PROVENANCE_READ_FIELDS = frozenset( + { + "tenant_record_id", + "validity_study_id", + "analysis_weight_receipt_reference", + "analysis_weight_receipt_digest", + "analysis_weight_evidence_version", + "evidence_version", + "estimand_reference", + "estimand_digest", + "estimand_scope_code", + "target_population_reference", + "target_population_digest", + "analysis_unit_code", + "analysis_window_reference", + "reference_duration_reference", + "reference_duration_digest", + "eligible_case_set_digest", + "analytic_case_occurrence_set_digest", + "source_universe_receipt_reference", + "source_universe_receipt_version", + "source_universe_receipt_digest", + "sampling_design_receipt_reference", + "sampling_design_receipt_version", + "sampling_design_receipt_digest", + "base_weight_method_code", + "base_weight_method_version", + "base_weight_evidence_digest", + "base_weight_artifact_digest", + "adjustments", + "final_weight_artifact_digest", + "weight_eligibility_receipt_reference", + "weight_eligibility_receipt_digest", + "analytic_case_count", + "constructed_at", + "correction_sequence", + "supersedes_receipt_digest", + "binding_reference", + "binding_digest", + "binding_version", + "base_weight_evidence_receipt_reference", + "base_weight_evidence_receipt_digest", + "base_weight_evidence_version", + "adjustment_bindings", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + } +) +COMPONENT_READ_FIELDS = frozenset( { "tenant_record_id", "validity_study_id", @@ -66,6 +118,7 @@ "superseded_at", } ) +READ_FIELDS = OWNER_PROVENANCE_READ_FIELDS | COMPONENT_READ_FIELDS def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: From 9a62154bcac3dd99cb752cc2742d2e0a08d8b940 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 21:13:02 +0900 Subject: [PATCH 468/603] test(workforce-validation): align authorization fixtures with owner provenance --- ...weight_component_evidence_authorization.py | 28 ++++++------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py index 3b7842ae0..fdbee7464 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_authorization.py @@ -13,6 +13,7 @@ ) from test_final_weight_component_evidence_resolution import ( FINAL_REFERENCE, + READ_FIELDS, TENANT, USED_AT, _ReadPort, @@ -20,25 +21,6 @@ _final_weight, ) -READ_FIELDS = frozenset( - { - "tenant_record_id", - "validity_study_id", - "receipt_reference", - "receipt_digest", - "evidence_version", - "method_code", - "method_reference", - "method_version", - "input_weight_artifact_digest", - "output_weight_artifact_digest", - "configuration_digest", - "evidence_kind", - "released_at", - "superseded_at", - } -) - def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: return ValidationPrincipal( @@ -79,6 +61,8 @@ def test_denied_purpose_stops_before_any_component_owner_read() -> None: assert exc_info.value.decision.resource_reference == ( f"final_weight_component_evidence_resolution:{receipt_tail}" ) + assert port.final_owner_calls == [] + assert port.binding_owner_calls == [] assert port.base_calls == [] assert port.adjustment_calls == [] @@ -100,6 +84,8 @@ def test_cross_tenant_principal_stops_before_any_component_owner_read() -> None: read_port=port, ) + assert port.final_owner_calls == [] + assert port.binding_owner_calls == [] assert port.base_calls == [] assert port.adjustment_calls == [] @@ -122,6 +108,8 @@ def test_noncanonical_principal_fails_before_component_owner_read( read_port=port, ) + assert port.final_owner_calls == [] + assert port.binding_owner_calls == [] assert port.base_calls == [] assert port.adjustment_calls == [] @@ -144,5 +132,7 @@ def test_noncanonical_policy_fails_before_component_owner_read( read_port=port, ) + assert port.final_owner_calls == [] + assert port.binding_owner_calls == [] assert port.base_calls == [] assert port.adjustment_calls == [] From 7bcf32e210d842029eee717c608cba2ed7dfbdcb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 21:29:01 +0900 Subject: [PATCH 469/603] test(workforce-validation): restore exact acceptance fixtures --- CHANGELOG.md | 1 + manifest.json | 6 +++--- .../tests/test_base_weight_authority.py | 3 ++- .../tests/test_base_weight_supersession_authority.py | 7 ++++++- .../test_calibration_adjustment_supersession_contract.py | 9 ++++++--- .../tests/test_calibration_support_authority_edges.py | 5 ++++- .../test_final_weight_supersession_authority_edges.py | 2 +- .../tests/test_hash_locked_wheel_record_integration.py | 5 ++++- .../tests/test_nonresponse_adjustment_authority.py | 2 +- .../tests/test_nonresponse_adjustment_authority_edges.py | 1 + .../test_nonresponse_adjustment_supersession_contract.py | 2 +- .../tests/test_package_metadata_compatibility.py | 3 ++- .../tests/test_result_supersession_authority.py | 4 ++-- .../tests/test_result_supersession_authority_edges.py | 2 +- .../tests/test_trimming_bounding_authority.py | 2 +- ...idation_result_nonverifiability_attempt_chronology.py | 2 +- ...est_validation_result_nonverifiability_currentness.py | 2 +- ...result_nonverifiability_failed_evidence_chronology.py | 2 +- ...t_nonverifiability_supersession_v2_authority_edges.py | 2 +- ...n_result_nonverifiability_supersession_v2_contract.py | 1 + .../tests/test_weight_variance_supersession_authority.py | 7 ++++++- 21 files changed, 47 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16454da3d..8be6fcda2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ All notable changes to Orgmetra will be documented in this file. ### Changed +- Active-PR Workforce Validation acceptance fixtures now track released owner contracts, supersession cutovers, owner-read field sets, and standard-library timezone-provider failures exactly; wheel acceptance validates every owned wheel's internal identity and metadata before producing any outer artifact hash. - Consolidated repository-owned PR validation from twelve workflows into one Foundation CI job, while keeping the dual-cluster recovery rehearsal separately path-scoped. Central required review and security workflows remain organization-owned. - New predictive-validity membership must use one normalized worker-level case; the three independent validity-study decision/evidence/outcome link relations are historical read surfaces only and can no longer accept new rows. A case insert also rejects a criterion observation whose recorded interval is already closed at `linked_at`. - Canonicalized service identifiers as two-or-more-word `snake_case` across architecture, deployment, ACL, metrics, and client contracts. diff --git a/manifest.json b/manifest.json index f4085d0e1..043850205 100644 --- a/manifest.json +++ b/manifest.json @@ -29,9 +29,9 @@ }, { "path": "CHANGELOG.md", - "sha256": "f2d2e0b488c0440533effa821808f2f17e37d92f8fb586174c2fdb594f760ca5", - "bytes": 17539, - "lines": 77 + "sha256": "6415cdc5707d8a5d268659915ecb4b7ca5894ffd2fdc1e37a36c9c211dd92cd7", + "bytes": 17851, + "lines": 78 }, { "path": "CLAUDE.md", diff --git a/services/workforce-validation-api/tests/test_base_weight_authority.py b/services/workforce-validation-api/tests/test_base_weight_authority.py index 4a23e40c2..fa404b712 100644 --- a/services/workforce-validation-api/tests/test_base_weight_authority.py +++ b/services/workforce-validation-api/tests/test_base_weight_authority.py @@ -64,6 +64,7 @@ "owner_contract_digest", "owner_contract_released_at", "released_at", + "superseded_at", } ) @@ -289,4 +290,4 @@ def test_view_cannot_be_constructed_directly() -> None: tenant_record_id=TENANT, validity_study_id=STUDY, fields=(), - ) \ No newline at end of file + ) diff --git a/services/workforce-validation-api/tests/test_base_weight_supersession_authority.py b/services/workforce-validation-api/tests/test_base_weight_supersession_authority.py index c95790f34..096924de7 100644 --- a/services/workforce-validation-api/tests/test_base_weight_supersession_authority.py +++ b/services/workforce-validation-api/tests/test_base_weight_supersession_authority.py @@ -229,6 +229,11 @@ def test_missing_noncanonical_and_pre_release_evidence_fail_closed() -> None: ], ) def test_owner_evidence_must_match_every_requested_coordinate(record_overrides: dict[str, object]) -> None: + if "base_weight_evidence_receipt_reference" in record_overrides: + record_overrides = { + **record_overrides, + "successor_base_weight_evidence_receipt_reference": RECEIPT, + } with pytest.raises(BaseWeightSupersessionAuthorityIntegrityError): _resolve(read_port=_ReadPort(_record(**record_overrides)), used_at=RELEASED) @@ -269,7 +274,7 @@ def test_invalid_request_or_dependency_fails_before_owner_resolution( port = value overrides = {} with pytest.raises(error): - _resolve(read_port=port, used_at=RELEASED, **overrides) + _resolve(read_port=port, **{"used_at": RELEASED, **overrides}) if isinstance(port, _ReadPort): assert port.calls == [] diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py b/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py index 031e10e28..38ad86b99 100644 --- a/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py @@ -237,7 +237,6 @@ def test_missing_noncanonical_and_pre_release_owner_evidence_fail_closed() -> No {"validity_study_id": OTHER_STUDY}, {"calibration_receipt_reference": SUCCESSOR}, {"calibration_receipt_digest": "4" * 64}, - {"evidence_version": 2}, {"owner_contract_reference": "released_owner_contract:44444444-4444-4444-8444-444444444444"}, {"owner_contract_version": 2}, {"owner_contract_digest": "5" * 64}, @@ -246,6 +245,11 @@ def test_missing_noncanonical_and_pre_release_owner_evidence_fail_closed() -> No def test_owner_evidence_must_match_every_requested_coordinate( record_overrides: dict[str, object] ) -> None: + if "calibration_receipt_reference" in record_overrides: + record_overrides = { + **record_overrides, + "successor_calibration_receipt_reference": RECEIPT, + } record = _record(**record_overrides) with pytest.raises(CalibrationAdjustmentSupersessionAuthorityIntegrityError): _resolve(read_port=_ReadPort(record), used_at=CUTOVER - timedelta(seconds=1)) @@ -293,8 +297,7 @@ def test_invalid_request_or_dependency_fails_before_owner_resolution( with pytest.raises(error): _resolve( read_port=port, - used_at=CUTOVER - timedelta(seconds=1), - **overrides, + **{"used_at": CUTOVER - timedelta(seconds=1), **overrides}, ) if isinstance(port, _ReadPort): assert port.calls == [] diff --git a/services/workforce-validation-api/tests/test_calibration_support_authority_edges.py b/services/workforce-validation-api/tests/test_calibration_support_authority_edges.py index 1b401a6ea..533e63890 100644 --- a/services/workforce-validation-api/tests/test_calibration_support_authority_edges.py +++ b/services/workforce-validation-api/tests/test_calibration_support_authority_edges.py @@ -330,7 +330,10 @@ def test_support_binding_must_be_released_before_scientific_use() -> None: "owner contract cannot be released after support evidence", ), ( - {"released_at": CONSTRUCTED_AT - timedelta(seconds=1)}, + { + "owner_contract_released_at": CONSTRUCTED_AT - timedelta(seconds=2), + "released_at": CONSTRUCTED_AT - timedelta(seconds=1), + }, "support evidence cannot be released before calibration construction", ), ], diff --git a/services/workforce-validation-api/tests/test_final_weight_supersession_authority_edges.py b/services/workforce-validation-api/tests/test_final_weight_supersession_authority_edges.py index ea8f7f989..23f05ee39 100644 --- a/services/workforce-validation-api/tests/test_final_weight_supersession_authority_edges.py +++ b/services/workforce-validation-api/tests/test_final_weight_supersession_authority_edges.py @@ -208,7 +208,7 @@ def test_release_chronology_and_use_fail_closed() -> None: successor_analysis_weight_receipt_reference=SUCCESSOR_REFERENCE, successor_correction_sequence=3, successor_analysis_weight_receipt_digest=SUCCESSOR_DIGEST, - successor_released_at=USED_AT, + successor_released_at=USED_AT + timedelta(seconds=1), ) view = _resolve(read_port=_ReadPort(record)) assert dict(view.fields)["analysis_weight_receipt_digest"] == RECEIPT_DIGEST diff --git a/services/workforce-validation-api/tests/test_hash_locked_wheel_record_integration.py b/services/workforce-validation-api/tests/test_hash_locked_wheel_record_integration.py index 4c5b4eb95..ec168496b 100644 --- a/services/workforce-validation-api/tests/test_hash_locked_wheel_record_integration.py +++ b/services/workforce-validation-api/tests/test_hash_locked_wheel_record_integration.py @@ -84,7 +84,10 @@ def test_hash_locked_install_manifest_rejects_false_record(tmp_path: Path) -> No "Metadata-Version: 2.4\n" "Name: orgmetra-keyverse-adapter\n" "Version: 0.1.0\n" - "Requires-Python: >=3.12\n\n" + "Requires-Python: >=3.12\n" + "Provides-Extra: test\n" + "Requires-Dist: pytest>=8.3; extra == 'test'\n" + "Requires-Dist: pytest-cov>=5.0; extra == 'test'\n\n" ), include_py_typed=False, ) diff --git a/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority.py b/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority.py index 221bf4d36..a549990b7 100644 --- a/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority.py +++ b/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority.py @@ -254,7 +254,7 @@ def test_owner_resolved_input_release_and_currentness_chronology_fail_closed() - with pytest.raises(ValueError, match="superseded_at must be later"): _record(superseded_at=RELEASED_AT) - with pytest.raises(ValueError, match="timezone-aware"): + with pytest.raises(ValueError, match="standard-library timezone provider"): _record(superseded_at=datetime(2026, 9, 16, 14, 0)) with pytest.raises(NonresponseAdjustmentAuthorityIntegrityError): diff --git a/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_edges.py b/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_edges.py index 611abe2c2..71fedfcd4 100644 --- a/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_edges.py +++ b/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_edges.py @@ -42,6 +42,7 @@ def _record(*, evidence_version: object = 1) -> NonresponseAdjustmentAuthorityRe ), owner_contract_version=5, owner_contract_digest="7" * 64, + owner_contract_released_at=datetime(2026, 9, 16, 12, 30, tzinfo=timezone.utc), released_at=datetime(2026, 9, 16, 13, 0, tzinfo=timezone.utc), ) diff --git a/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_contract.py b/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_contract.py index 75b48961a..26424c885 100644 --- a/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_contract.py +++ b/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_contract.py @@ -85,5 +85,5 @@ def test_nonresponse_supersession_requires_new_immutable_evidence() -> None: def test_nonresponse_supersession_rejects_naive_cutover() -> None: """Correction chronology must remain timezone-aware owner evidence.""" - with pytest.raises(ValueError, match="timezone-aware"): + with pytest.raises(ValueError, match="standard-library timezone provider"): _supersession_record(superseded_at=datetime(2026, 9, 18, 1, 10)) diff --git a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py index 17b639fb4..0b78da633 100644 --- a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py +++ b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py @@ -433,7 +433,6 @@ def _locked_wheel_requirements( require_py_typed=canonical_name == canonicalize_name(_SERVICE_NAME), ) wheels_by_name[canonical_name] = wheel_path - hashes_by_name[canonical_name] = _sha256(wheel_path) _validate_wheel_metadata( wheel_path, expected_name=expected_name, @@ -449,6 +448,8 @@ def _locked_wheel_requirements( ) assert set(wheels_by_name) == set(expected_versions) + for canonical_name, wheel_path in wheels_by_name.items(): + hashes_by_name[canonical_name] = _sha256(wheel_path) lock_lines = [ f"{_KEYVERSE_NAME}=={keyverse_version} --hash=sha256:{hashes_by_name[canonicalize_name(_KEYVERSE_NAME)]}", f"{_SERVICE_NAME}=={service_version} --hash=sha256:{hashes_by_name[canonicalize_name(_SERVICE_NAME)]}", diff --git a/services/workforce-validation-api/tests/test_result_supersession_authority.py b/services/workforce-validation-api/tests/test_result_supersession_authority.py index 897b85b2c..1198b50bc 100644 --- a/services/workforce-validation-api/tests/test_result_supersession_authority.py +++ b/services/workforce-validation-api/tests/test_result_supersession_authority.py @@ -147,7 +147,7 @@ def test_historical_result_use_before_supersession_remains_verifiable_without_le successor_reference=SUCCESSOR_REFERENCE, successor_correction_sequence=3, successor_digest=SUCCESSOR_DIGEST, - successor_released_at=USED_AT + timedelta(hours=12), + successor_released_at=USED_AT + timedelta(days=1), ) ) @@ -165,7 +165,7 @@ def test_superseded_result_is_not_authoritative_at_or_after_cutover() -> None: successor_reference=SUCCESSOR_REFERENCE, successor_correction_sequence=3, successor_digest=SUCCESSOR_DIGEST, - successor_released_at=USED_AT - timedelta(minutes=1), + successor_released_at=USED_AT, ) with pytest.raises(ValidationResultSupersessionAuthorityIntegrityError): diff --git a/services/workforce-validation-api/tests/test_result_supersession_authority_edges.py b/services/workforce-validation-api/tests/test_result_supersession_authority_edges.py index ad154836e..29082cab4 100644 --- a/services/workforce-validation-api/tests/test_result_supersession_authority_edges.py +++ b/services/workforce-validation-api/tests/test_result_supersession_authority_edges.py @@ -208,7 +208,7 @@ def test_release_chronology_and_historical_use_fail_closed_or_remain_reproducibl successor_result_reference=SUCCESSOR_REFERENCE, successor_correction_sequence=3, successor_result_digest=SUCCESSOR_DIGEST, - successor_released_at=USED_AT, + successor_released_at=USED_AT + timedelta(seconds=1), ) view = _resolve(read_port=_ReadPort(record)) assert dict(view.fields)["result_digest"] == RESULT_DIGEST diff --git a/services/workforce-validation-api/tests/test_trimming_bounding_authority.py b/services/workforce-validation-api/tests/test_trimming_bounding_authority.py index 6d2c0b84f..2b3734079 100644 --- a/services/workforce-validation-api/tests/test_trimming_bounding_authority.py +++ b/services/workforce-validation-api/tests/test_trimming_bounding_authority.py @@ -226,7 +226,7 @@ def test_artifact_release_and_currentness_chronology_fail_closed() -> None: _record(released_at=CONSTRUCTED_AT - timedelta(seconds=1)) with pytest.raises(ValueError, match="superseded_at must be later"): _record(superseded_at=RELEASED_AT) - with pytest.raises(ValueError, match="timezone-aware"): + with pytest.raises(ValueError, match="standard-library timezone provider"): _record(superseded_at=datetime(2026, 9, 16, 14, 0)) with pytest.raises(TrimmingBoundingAuthorityIntegrityError): _resolve(read_port=_ReadPort(_record(released_at=USED_AT + timedelta(seconds=1)))) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_attempt_chronology.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_attempt_chronology.py index dbb69f305..0359dc122 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_attempt_chronology.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_attempt_chronology.py @@ -93,5 +93,5 @@ def test_verification_attempt_must_exist_before_outcome_release() -> None: def test_verification_attempt_release_requires_timezone() -> None: - with pytest.raises(ValueError, match="timezone-aware"): + with pytest.raises(ValueError, match="standard-library timezone provider"): _record(verification_attempt_released_at=datetime(2026, 9, 17, 6, 2)) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py index 46a13db1b..06d51171b 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_currentness.py @@ -167,5 +167,5 @@ def test_nonverifiability_is_valid_only_before_owner_resolved_cutover() -> None: def test_nonverifiability_cutover_must_follow_release_and_be_timezone_aware() -> None: with pytest.raises(ValueError, match="later than"): _record(superseded_at=RELEASED_AT) - with pytest.raises(ValueError, match="timezone-aware"): + with pytest.raises(ValueError, match="standard-library timezone provider"): _record(superseded_at=datetime(2026, 9, 17, 6, 20)) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_failed_evidence_chronology.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_failed_evidence_chronology.py index 8c9223e06..a3f6af3d4 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_failed_evidence_chronology.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_failed_evidence_chronology.py @@ -81,7 +81,7 @@ def test_non_reproducible_evidence_must_exist_before_verification_evaluation() - def test_non_reproducible_evidence_requires_release_chronology() -> None: with pytest.raises(ValueError, match="failed_evidence_released_at"): _record(failed_evidence_released_at=None) - with pytest.raises(ValueError, match="timezone-aware"): + with pytest.raises(ValueError, match="standard-library timezone provider"): _record(failed_evidence_released_at=datetime(2026, 9, 17, 5, 50)) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py index 47a415416..84b52ab6e 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py @@ -529,5 +529,5 @@ def test_v2_rejects_structurally_forged_non_reproducible_predecessor() -> None: forged_values = list(predecessor) forged_values[6] = None forged = tuple.__new__(ValidationResultNonVerifiabilityRecord, forged_values) - with pytest.raises(ValueError, match="retain exact failed-artifact evidence"): + with pytest.raises(ValueError, match="failed evidence reference and digest"): _record(predecessor=forged) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_contract.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_contract.py index 47a6e581f..c7fbb6adc 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_contract.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_contract.py @@ -52,6 +52,7 @@ def _predecessor() -> ValidationResultNonVerifiabilityRecord: owner_contract_released_at=OWNER_RELEASED_AT, evaluated_at=EVALUATED_AT, released_at=RELEASED_AT, + superseded_at=CUTOVER, ) diff --git a/services/workforce-validation-api/tests/test_weight_variance_supersession_authority.py b/services/workforce-validation-api/tests/test_weight_variance_supersession_authority.py index 8aa9758df..668756a0c 100644 --- a/services/workforce-validation-api/tests/test_weight_variance_supersession_authority.py +++ b/services/workforce-validation-api/tests/test_weight_variance_supersession_authority.py @@ -217,6 +217,11 @@ def test_missing_noncanonical_and_pre_release_evidence_fail_closed() -> None: ], ) def test_owner_evidence_must_match_every_requested_coordinate(record_overrides: dict[str, object]) -> None: + if "authority_reference" in record_overrides: + record_overrides = { + **record_overrides, + "successor_authority_reference": AUTHORITY, + } with pytest.raises(WeightVarianceSupersessionAuthorityIntegrityError): _resolve(read_port=_ReadPort(_record(**record_overrides)), used_at=RELEASED) @@ -256,7 +261,7 @@ def test_invalid_request_or_dependency_fails_before_owner_resolution( port = value overrides = {} with pytest.raises(error): - _resolve(read_port=port, used_at=RELEASED, **overrides) + _resolve(read_port=port, **{"used_at": RELEASED, **overrides}) if isinstance(port, _ReadPort): assert port.calls == [] From 5512750396ed109eac87b8a77ac2daaa211e1d99 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 22:03:33 +0900 Subject: [PATCH 470/603] test(workforce-validation): cover sealed issuance edge branches --- ...nent_evidence_issuance_marker_integrity.py | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_component_evidence_issuance_marker_integrity.py diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_issuance_marker_integrity.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_issuance_marker_integrity.py new file mode 100644 index 000000000..91d404cd3 --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_issuance_marker_integrity.py @@ -0,0 +1,51 @@ +"""Hostile issuance-marker and private-issuer edge cases for component evidence.""" + +from __future__ import annotations + +import pytest + +import orgmetra_workforce_validation_api.final_weight_component_evidence_resolution as resolution_module +from orgmetra_workforce_validation_api.final_weight_component_evidence_resolution import ( + FinalWeightComponentEvidenceIntegrityError, + FinalWeightComponentEvidenceResolution, +) +from test_final_weight_component_evidence_resolution_low_level_issuance import _base_evidence + + +def test_wrong_private_issuance_marker_cannot_expose_proof_properties() -> None: + """Fail closed when hostile allocation populates a marker that is not the canonical seal.""" + forged = object.__new__(FinalWeightComponentEvidenceResolution) + object.__setattr__( + forged, + "_FinalWeightComponentEvidenceResolution__issuance_marker", + object(), + ) + + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="not issued"): + _ = forged.base_weight + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="not issued"): + _ = forged.adjustments + + +def test_private_issuer_rejects_mutable_adjustment_collection() -> None: + """Keep the internal proof issuer fail-closed if a future caller passes mutable state.""" + with pytest.raises( + FinalWeightComponentEvidenceIntegrityError, + match="immutable tuple", + ): + resolution_module._issue_component_evidence_resolution( + base_weight=_base_evidence(), + adjustments=[], # type: ignore[arg-type] + ) + + +def test_private_issuer_rejects_noncanonical_adjustment_member() -> None: + """Reject an immutable container whose member is not canonical adjustment evidence.""" + with pytest.raises( + FinalWeightComponentEvidenceIntegrityError, + match="non-canonical specialized evidence", + ): + resolution_module._issue_component_evidence_resolution( + base_weight=_base_evidence(), + adjustments=(object(),), # type: ignore[arg-type] + ) From 9ac1a1873b81d0f61b479ff9283f46781136cb2f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 22:28:37 +0900 Subject: [PATCH 471/603] test(workforce-validation): restore exact coverage gate --- CHANGELOG.md | 1 + manifest.json | 6 +- .../tests/test_base_weight_authority.py | 9 + ...test_base_weight_supersession_authority.py | 4 + ...ration_adjustment_supersession_contract.py | 4 + ...ght_component_evidence_resolution_edges.py | 336 ++++++++++++++++++ ...adjustment_supersession_authority_edges.py | 317 +++++++++++++++++ ...g_bounding_supersession_authority_edges.py | 317 +++++++++++++++++ .../tests/test_validation_result_authority.py | 2 + ...ifiability_supersession_authority_edges.py | 2 + ...ability_supersession_v2_authority_edges.py | 34 ++ .../test_weight_variance_authority_edges.py | 4 + ..._weight_variance_supersession_authority.py | 4 + 13 files changed, 1037 insertions(+), 3 deletions(-) create mode 100644 services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_edges.py create mode 100644 services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_authority_edges.py create mode 100644 services/workforce-validation-api/tests/test_trimming_bounding_supersession_authority_edges.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 8be6fcda2..f87677de8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ All notable changes to Orgmetra will be documented in this file. ### Changed +- Active-PR Workforce Validation coverage recovery now exercises exact owner-capability admission, immutable release-view identities, version and chronology rejection, digest independence, approximation semantics, final-weight component corroboration, and base/nonresponse/trimming supersession edge contracts. The Python 3.12 pinned suite passes all 1,306 tests with 4,487/4,487 owned statements and 1,070/1,070 owned branches covered. - Active-PR Workforce Validation acceptance fixtures now track released owner contracts, supersession cutovers, owner-read field sets, and standard-library timezone-provider failures exactly; wheel acceptance validates every owned wheel's internal identity and metadata before producing any outer artifact hash. - Consolidated repository-owned PR validation from twelve workflows into one Foundation CI job, while keeping the dual-cluster recovery rehearsal separately path-scoped. Central required review and security workflows remain organization-owned. - New predictive-validity membership must use one normalized worker-level case; the three independent validity-study decision/evidence/outcome link relations are historical read surfaces only and can no longer accept new rows. A case insert also rejects a criterion observation whose recorded interval is already closed at `linked_at`. diff --git a/manifest.json b/manifest.json index 043850205..223408b5f 100644 --- a/manifest.json +++ b/manifest.json @@ -29,9 +29,9 @@ }, { "path": "CHANGELOG.md", - "sha256": "6415cdc5707d8a5d268659915ecb4b7ca5894ffd2fdc1e37a36c9c211dd92cd7", - "bytes": 17851, - "lines": 78 + "sha256": "0b5ce1897d82ed815627658a57cbfcb6a1c65425e119aaffa2d194b79f6b15d7", + "bytes": 18288, + "lines": 79 }, { "path": "CLAUDE.md", diff --git a/services/workforce-validation-api/tests/test_base_weight_authority.py b/services/workforce-validation-api/tests/test_base_weight_authority.py index fa404b712..7995d08f4 100644 --- a/services/workforce-validation-api/tests/test_base_weight_authority.py +++ b/services/workforce-validation-api/tests/test_base_weight_authority.py @@ -178,6 +178,8 @@ def test_resolution_binds_sampling_stage_probabilities_to_base_weight_artifact() view = _resolve(read_port=port) assert isinstance(port, BaseWeightAuthorityReadPort) + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY assert len(port.calls) == 1 assert port.calls[0]["source_universe_receipt_version"] == 4 assert port.calls[0]["sampling_design_receipt_version"] == 3 @@ -291,3 +293,10 @@ def test_view_cannot_be_constructed_directly() -> None: validity_study_id=STUDY, fields=(), ) + + +@pytest.mark.parametrize("read_port", [_NoReadMethod(), _ProtocolOnly(), _DescriptorReadPort()]) +def test_nonconcrete_owner_capabilities_fail_before_resolution(read_port: object) -> None: + """Reject absent, protocol-only, and descriptor owner capabilities statically.""" + with pytest.raises(TypeError, match="statically callable"): + _resolve(read_port=read_port) diff --git a/services/workforce-validation-api/tests/test_base_weight_supersession_authority.py b/services/workforce-validation-api/tests/test_base_weight_supersession_authority.py index 096924de7..e7bad6ce6 100644 --- a/services/workforce-validation-api/tests/test_base_weight_supersession_authority.py +++ b/services/workforce-validation-api/tests/test_base_weight_supersession_authority.py @@ -137,6 +137,8 @@ def _resolve(*, read_port: object, used_at: datetime, **overrides: object): def test_successor_edge_requires_complete_atomic_released_coordinates() -> None: + with pytest.raises(ValueError, match="evidence_version must remain 1"): + _record(evidence_version=2) with pytest.raises(ValueError, match="complete released successor coordinates"): _record(successor_released_at=None) with pytest.raises(ValueError, match="later than base-weight receipt release"): @@ -173,6 +175,8 @@ def test_historical_use_is_allowed_but_cutover_use_fails_closed() -> None: port = _ReadPort(record) view = _resolve(read_port=port, used_at=CUTOVER - timedelta(microseconds=1)) + assert view.validity_study_id == STUDY + assert isinstance(port, BaseWeightSupersessionAuthorityReadPort) assert port.calls == [ { diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py b/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py index 38ad86b99..651023008 100644 --- a/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_contract.py @@ -143,6 +143,8 @@ def _resolve(*, read_port: object, used_at: datetime, **overrides: object): def test_successor_edge_requires_complete_atomic_released_coordinates() -> None: + with pytest.raises(ValueError, match="evidence_version must remain 1"): + _record(evidence_version=2) with pytest.raises(ValueError, match="complete released successor coordinates"): _record(successor_released_at=None) with pytest.raises(ValueError, match="later than calibration receipt release"): @@ -179,6 +181,8 @@ def test_historical_use_is_allowed_but_cutover_use_fails_closed() -> None: port = _ReadPort(record) view = _resolve(read_port=port, used_at=CUTOVER - timedelta(microseconds=1)) + assert view.validity_study_id == STUDY + assert isinstance(port, CalibrationAdjustmentSupersessionAuthorityReadPort) assert port.calls == [ { diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_edges.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_edges.py new file mode 100644 index 000000000..b2826e08c --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_edges.py @@ -0,0 +1,336 @@ +"""Hostile edge coverage for final-weight component evidence resolution.""" + +from __future__ import annotations + +from datetime import timedelta +from types import SimpleNamespace + +import pytest + +import orgmetra_workforce_validation_api.final_weight_component_evidence_resolution as resolution_module +from orgmetra_workforce_validation_api.final_weight_authority import ( + FinalAnalysisWeightAuthorityRecord, + FinalWeightAdjustmentCoordinate, +) +from orgmetra_workforce_validation_api.final_weight_component_binding_authority import ( + FinalWeightAdjustmentEvidenceBinding, + FinalWeightComponentBindingAuthorityRecord, +) +from orgmetra_workforce_validation_api.final_weight_component_evidence_resolution import ( + AdjustmentComponentEvidence, + BaseWeightComponentEvidence, + FinalWeightComponentEvidenceIntegrityError, + FinalWeightComponentEvidenceNotFound, + corroborate_final_weight_component_evidence, +) +from test_final_weight_component_evidence_resolution import ( + ADJUSTMENT_RECEIPT_REFERENCE, + BASE_ARTIFACT_DIGEST, + BINDING_RELEASED_AT, + CONSTRUCTED_AT, + FINAL_RELEASED_AT, + OTHER_TENANT, + TENANT, + USED_AT, + _ReadPort, + _adjustment_evidence, + _base_evidence, + _binding, + _corroborate, + _final_weight, + _policy, + _principal, +) + + +def _call_without_owner_rebinding(port: _ReadPort) -> object: + """Invoke corroboration while preserving independently configured owner results.""" + return corroborate_final_weight_component_evidence( + principal=_principal(), + final_weight=_final_weight(), + binding=_binding(), + used_at=USED_AT, + purpose_code="selection_validity_analysis", + policy=_policy(), + read_port=port, + ) + + +def test_component_value_objects_reject_invalid_versions_transforms_and_cutovers() -> None: + """Keep component schema, transform, and half-open chronology fail-closed.""" + with pytest.raises(ValueError, match="evidence_version"): + _base_evidence(evidence_version=2) + with pytest.raises(ValueError, match="superseded_at"): + _base_evidence(superseded_at=CONSTRUCTED_AT - timedelta(minutes=15)) + with pytest.raises(ValueError, match="governed specialized"): + _adjustment_evidence(evidence_kind="unknown_receipt") + with pytest.raises(ValueError, match="evidence_version"): + _adjustment_evidence(evidence_version=2) + with pytest.raises(ValueError, match="transformed"): + _adjustment_evidence(output_weight_artifact_digest=BASE_ARTIFACT_DIGEST) + with pytest.raises(ValueError, match="superseded_at"): + _adjustment_evidence(superseded_at=CONSTRUCTED_AT - timedelta(minutes=1)) + + +def test_canonicalizers_reject_wrong_malformed_and_hidden_record_shapes() -> None: + """Require exact reconstructible runtime types for every cross-owner record.""" + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="base-weight"): + resolution_module._canonical_base_evidence(object()) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="final_weight must"): + resolution_module._canonical_final_weight(object()) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="binding must"): + resolution_module._canonical_binding(object()) + + final_weight = _final_weight() + malformed_final = tuple.__new__( + FinalAnalysisWeightAuthorityRecord, + tuple(final_weight)[:-1], + ) + hidden_final = tuple.__new__( + FinalAnalysisWeightAuthorityRecord, + tuple(final_weight) + ("hidden-final-coordinate",), + ) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="malformed"): + resolution_module._canonical_final_weight(malformed_final) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="hidden"): + resolution_module._canonical_final_weight(hidden_final) + + binding = _binding() + malformed_binding = tuple.__new__( + FinalWeightComponentBindingAuthorityRecord, + tuple(binding)[:-1], + ) + hidden_binding = tuple.__new__( + FinalWeightComponentBindingAuthorityRecord, + tuple(binding) + ("hidden-binding-coordinate",), + ) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="malformed"): + resolution_module._canonical_binding(malformed_binding) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="hidden"): + resolution_module._canonical_binding(hidden_binding) + + +def _unused_read(*_args: object, **_kwargs: object) -> None: + """Fail if an incomplete port reaches any owner read.""" + raise AssertionError("incomplete port must fail before owner access") + + +@pytest.mark.parametrize( + "missing_method", + [ + "read_final_analysis_weight_authority", + "read_final_weight_component_binding_authority", + "read_base_weight_component_evidence", + "read_adjustment_component_evidence", + ], +) +def test_every_owner_read_capability_is_required_before_resolution( + missing_method: str, +) -> None: + """Reject a port missing any one of the four static owner capabilities.""" + methods = { + "read_final_analysis_weight_authority": _unused_read, + "read_final_weight_component_binding_authority": _unused_read, + "read_base_weight_component_evidence": _unused_read, + "read_adjustment_component_evidence": _unused_read, + } + del methods[missing_method] + incomplete_port = type("IncompleteComponentReadPort", (), methods)() + + with pytest.raises(TypeError, match=missing_method): + _corroborate(read_port=incomplete_port) + + +def test_final_binding_scope_chronology_and_currentness_fail_closed() -> None: + """Reject cross-receipt, unreleased, or superseded final/binding evidence.""" + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="different"): + _corroborate( + read_port=_ReadPort(), + binding=_binding(analysis_weight_receipt_digest="9" * 64), + ) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="released before use"): + _corroborate( + read_port=_ReadPort(), + used_at=FINAL_RELEASED_AT - timedelta(microseconds=1), + ) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="final-weight evidence"): + _corroborate( + read_port=_ReadPort(), + final_weight=_final_weight(superseded_at=USED_AT), + ) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="binding is not current"): + _corroborate( + read_port=_ReadPort(), + binding=_binding(superseded_at=USED_AT), + ) + + +def test_owner_final_binding_and_base_failures_stop_resolution() -> None: + """Require owner-confirmed final, binding, and base evidence before resolution.""" + port = _ReadPort() + port.final_owner = _final_weight(analytic_case_count=11) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="final-weight owner"): + _call_without_owner_rebinding(port) + + port = _ReadPort() + port.binding_owner = None + with pytest.raises(FinalWeightComponentEvidenceNotFound, match="binding"): + _call_without_owner_rebinding(port) + + port = _ReadPort() + port.base = None + with pytest.raises(FinalWeightComponentEvidenceNotFound): + _call_without_owner_rebinding(port) + + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="base-weight component"): + _corroborate( + read_port=_ReadPort(base=_base_evidence(method_version=2)), + ) + + +def test_component_superseded_by_construction_fails_closed() -> None: + """Reject a component whose authority ended at final-weight construction.""" + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="construction"): + _corroborate( + read_port=_ReadPort( + base=_base_evidence(superseded_at=CONSTRUCTED_AT), + ) + ) + + +def test_adjustment_locator_and_component_identity_must_match() -> None: + """Bind each specialized coordinate to its exact locator and owner projection.""" + mismatched_binding = _binding( + adjustment_bindings=( + FinalWeightAdjustmentEvidenceBinding( + sequence_number=1, + evidence_kind="trimming_bounding_adjustment_receipt", + evidence_receipt_reference=ADJUSTMENT_RECEIPT_REFERENCE.replace( + "nonresponse_adjustment_receipt", + "trimming_bounding_adjustment_receipt", + ), + evidence_version=1, + evidence_receipt_digest="4" * 64, + ), + ) + ) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="digest or evidence kind"): + _corroborate(read_port=_ReadPort(), binding=mismatched_binding) + + port = _ReadPort( + adjustment=_adjustment_evidence( + receipt_reference=( + "nonresponse_adjustment_receipt:eeeeeeee-eeee-4eee-8eee-eeeeeeeeeeee" + ) + ) + ) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="exact binding locator"): + _corroborate(read_port=port) + + +def test_adjustment_and_base_wrong_runtime_types_fail_closed() -> None: + """Reject non-canonical component objects before reading their structure.""" + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="specialized"): + resolution_module._canonical_adjustment_evidence(object()) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="base-weight"): + resolution_module._canonical_base_evidence(object()) + + +def test_owner_provenance_rejects_cross_tenant_component() -> None: + """Retain tenant provenance before any component semantics are trusted.""" + port = _ReadPort(base=_base_evidence(tenant_record_id=OTHER_TENANT)) + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="tenant"): + _corroborate(read_port=port) + + +def _authority_view(record: object, **field_overrides: object) -> SimpleNamespace: + """Expose a detached authority view for post-canonicalization defense tests.""" + fields = dict(record.fields) + fields.update(field_overrides) + return SimpleNamespace( + tenant_record_id=record.tenant_record_id, + validity_study_id=record.validity_study_id, + owner_contract_released_at=record.owner_contract_released_at, + released_at=record.released_at, + superseded_at=record.superseded_at, + fields=fields, + ) + + +@pytest.mark.parametrize( + ("target", "message"), + [ + ("final", "final-weight adjustments"), + ("binding", "component adjustment bindings"), + ], +) +def test_post_canonicalization_collections_remain_immutable( + monkeypatch: pytest.MonkeyPatch, + target: str, + message: str, +) -> None: + """Retain fail-closed collection checks even if a canonicalizer regresses.""" + final_weight = _final_weight() + binding = _binding() + if target == "final": + final_view = _authority_view( + final_weight, + adjustments=list(dict(final_weight.fields)["adjustments"]), + ) + monkeypatch.setattr(resolution_module, "_canonical_final_weight", lambda _value: final_view) + else: + binding_view = _authority_view( + binding, + adjustment_bindings=list(dict(binding.fields)["adjustment_bindings"]), + ) + monkeypatch.setattr(resolution_module, "_canonical_binding", lambda _value: binding_view) + + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match=message): + _corroborate( + read_port=_ReadPort(), + final_weight=final_weight, + binding=binding, + ) + + +def test_post_canonicalization_adjustment_coordinate_type_remains_exact( + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Reject a structurally similar adjustment if canonical reconstruction regresses.""" + final_weight = _final_weight() + forged_adjustment = SimpleNamespace( + sequence_number=1, + evidence_kind="nonresponse_adjustment_receipt", + ) + final_view = _authority_view(final_weight, adjustments=(forged_adjustment,)) + monkeypatch.setattr(resolution_module, "_canonical_final_weight", lambda _value: final_view) + + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="coordinates"): + _corroborate(read_port=_ReadPort(), final_weight=final_weight) + + +def test_non_specialized_adjustment_needs_no_cross_owner_locator() -> None: + """Resolve base evidence while leaving a non-specialized transform owner-local.""" + local_adjustment = FinalWeightAdjustmentCoordinate( + sequence_number=1, + adjustment_code="replicate_weight_projection", + method_reference="weight_method:dddddddd-dddd-4ddd-8ddd-dddddddddddd", + method_version=1, + input_weight_artifact_digest=BASE_ARTIFACT_DIGEST, + output_weight_artifact_digest="c" * 64, + configuration_digest="d" * 64, + evidence_receipt_digest="e" * 64, + evidence_kind="replicate_weight_receipt", + ) + final_weight = _final_weight( + adjustments=(local_adjustment,), + final_weight_artifact_digest="c" * 64, + ) + binding = _binding(adjustment_bindings=()) + resolution = _corroborate( + read_port=_ReadPort(), + final_weight=final_weight, + binding=binding, + ) + + assert resolution.adjustments == () diff --git a/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_authority_edges.py b/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_authority_edges.py new file mode 100644 index 000000000..e1740dec4 --- /dev/null +++ b/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_authority_edges.py @@ -0,0 +1,317 @@ +"""Hostile edges for append-only nonresponse-adjustment correction authority.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.nonresponse_adjustment_supersession_authority import ( + NonresponseAdjustmentSupersessionAuthorityIntegrityError, + NonresponseAdjustmentSupersessionAuthorityNotFound, + NonresponseAdjustmentSupersessionAuthorityReadPort, + NonresponseAdjustmentSupersessionAuthorityRecord, + NonresponseAdjustmentSupersessionAuthorityView, + resolve_nonresponse_adjustment_supersession_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000d2") +RECEIPT = "nonresponse_adjustment_receipt:11111111-1111-4111-8111-111111111111" +OTHER_RECEIPT = "nonresponse_adjustment_receipt:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" +SUCCESSOR = "nonresponse_adjustment_receipt:22222222-2222-4222-8222-222222222222" +OWNER = "released_owner_contract:33333333-3333-4333-8333-333333333333" +OTHER_OWNER = "released_owner_contract:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" +RECEIPT_DIGEST = "1" * 64 +SUCCESSOR_DIGEST = "2" * 64 +OWNER_DIGEST = "3" * 64 +OWNER_RELEASED_AT = datetime(2026, 9, 17, 0, 30, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 1, 0, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 2, 0, tzinfo=timezone.utc) +CUTOVER = datetime(2026, 9, 18, 1, 0, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "nonresponse_receipt_reference", + "nonresponse_receipt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_nonresponse_receipt_reference", + "successor_nonresponse_receipt_digest", + "successor_evidence_version", + "successor_released_at", + } +) + + +class _ReadPort: + """Return configured authority and retain lookup coordinates.""" + + def __init__(self, result: object) -> None: + """Store one owner result and initialize the call ledger.""" + self.result = result + self.calls: list[dict[str, object]] = [] + + def read_nonresponse_adjustment_supersession_authority( + self, **coordinates: object + ) -> object: + """Capture the owner lookup and return configured evidence.""" + self.calls.append(dict(coordinates)) + return self.result + + +class _NoReadMethod: + """Deliberately omit the required owner-read capability.""" + + +class _ProtocolOnly(NonresponseAdjustmentSupersessionAuthorityReadPort): + """Inherit only the Protocol declaration, not a concrete capability.""" + + +class _DescriptorReadPort: + """Expose a descriptor that static capability validation must reject.""" + + @property + def read_nonresponse_adjustment_supersession_authority(self) -> object: + """Trip if dependency validation executes the descriptor.""" + raise AssertionError("descriptor must not execute") + + +def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: + """Return one exact workforce-validation principal.""" + return ValidationPrincipal( + tenant_record_id=tenant_record_id, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + """Return the purpose-bound policy for nonresponse correction evidence.""" + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="nonresponse-adjustment-supersession-read-v1", + resource_kind="nonresponse_adjustment_supersession_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record(**overrides: object) -> NonresponseAdjustmentSupersessionAuthorityRecord: + """Build one current nonresponse correction state.""" + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "nonresponse_receipt_reference": RECEIPT, + "nonresponse_receipt_digest": RECEIPT_DIGEST, + "evidence_version": 1, + "owner_contract_reference": OWNER, + "owner_contract_version": 1, + "owner_contract_digest": OWNER_DIGEST, + "owner_contract_released_at": OWNER_RELEASED_AT, + "released_at": RELEASED_AT, + "superseded_at": None, + "successor_nonresponse_receipt_reference": None, + "successor_nonresponse_receipt_digest": None, + "successor_evidence_version": None, + "successor_released_at": None, + } + values.update(overrides) + return NonresponseAdjustmentSupersessionAuthorityRecord(**values) + + +def _resolve( + *, read_port: object, **overrides: object +) -> NonresponseAdjustmentSupersessionAuthorityView: + """Resolve current nonresponse authority with caller-known coordinates only.""" + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "nonresponse_receipt_reference": RECEIPT, + "nonresponse_receipt_digest": RECEIPT_DIGEST, + "evidence_version": 1, + "owner_contract_reference": OWNER, + "owner_contract_version": 1, + "owner_contract_digest": OWNER_DIGEST, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_nonresponse_adjustment_supersession_authority(**values) + + +def test_current_receipt_resolution_uses_owner_chronology_without_successor() -> None: + """Resolve a current receipt and keep chronology out of the lookup key.""" + port = _ReadPort(_record()) + view = _resolve(read_port=port) + + assert isinstance(port, NonresponseAdjustmentSupersessionAuthorityReadPort) + assert len(port.calls) == 1 + assert "released_at" not in port.calls[0] + assert "superseded_at" not in port.calls[0] + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + assert dict(view.fields)["released_at"] == RELEASED_AT + + +def test_authorization_denial_happens_before_owner_resolution() -> None: + """Do not consult owner evidence when purpose authorization fails.""" + port = _ReadPort(_record()) + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, policy=_policy(purpose_code="audit_review")) + assert port.calls == [] + + +def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: + """Reject absent and non-canonical owner evidence.""" + with pytest.raises(NonresponseAdjustmentSupersessionAuthorityNotFound): + _resolve(read_port=_ReadPort(None)) + with pytest.raises(NonresponseAdjustmentSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object())) + + +@pytest.mark.parametrize( + "record_overrides", + [ + {"tenant_record_id": OTHER_TENANT}, + {"validity_study_id": OTHER_STUDY}, + {"nonresponse_receipt_reference": OTHER_RECEIPT}, + {"nonresponse_receipt_digest": "a" * 64}, + {"owner_contract_reference": OTHER_OWNER}, + {"owner_contract_version": 2}, + {"owner_contract_digest": "b" * 64}, + ], +) +def test_owner_evidence_must_match_every_requested_coordinate( + record_overrides: dict[str, object] +) -> None: + """Fail closed if owner evidence differs from any requested coordinate.""" + with pytest.raises(NonresponseAdjustmentSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(**record_overrides))) + + +def test_release_chronology_and_historical_use_are_distinct() -> None: + """Reject pre-release use while preserving history before a later cutover.""" + with pytest.raises(NonresponseAdjustmentSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(released_at=USED_AT + timedelta(seconds=1)))) + + record = _record( + superseded_at=CUTOVER, + successor_nonresponse_receipt_reference=SUCCESSOR, + successor_nonresponse_receipt_digest=SUCCESSOR_DIGEST, + successor_evidence_version=1, + successor_released_at=CUTOVER, + ) + assert dict(_resolve(read_port=_ReadPort(record)).fields)[ + "nonresponse_receipt_digest" + ] == RECEIPT_DIGEST + with pytest.raises(NonresponseAdjustmentSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(record), used_at=CUTOVER) + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("nonresponse_receipt_reference", "wrong:receipt", ValueError), + ("nonresponse_receipt_digest", "ABC", ValueError), + ("evidence_version", 2, ValueError), + ("owner_contract_reference", "wrong:contract", ValueError), + ("owner_contract_version", 0, ValueError), + ("owner_contract_digest", "2" * 63, ValueError), + ("used_at", datetime(2026, 9, 17), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_or_dependency_fails_before_owner_resolution( + key: str, value: object, error: type[Exception] +) -> None: + """Validate caller-controlled coordinates before touching the owner port.""" + port: object = _ReadPort(_record()) + overrides = {key: value} + if key == "read_port": + port = value + overrides = {} + with pytest.raises(error): + _resolve(read_port=port, **overrides) + if isinstance(port, _ReadPort): + assert port.calls == [] + + +def test_record_rejects_invalid_chronology_schema_and_public_view() -> None: + """Keep chronology atomic, evidence v1, and minimized views issuer-only.""" + with pytest.raises(ValueError, match="evidence_version must remain 1"): + _record(evidence_version=2) + with pytest.raises(ValueError, match="owner contract"): + _record(owner_contract_released_at=RELEASED_AT + timedelta(seconds=1)) + with pytest.raises(ValueError, match="later than nonresponse"): + _record( + superseded_at=RELEASED_AT, + successor_nonresponse_receipt_reference=SUCCESSOR, + successor_nonresponse_receipt_digest=SUCCESSOR_DIGEST, + successor_evidence_version=1, + successor_released_at=RELEASED_AT, + ) + with pytest.raises(ValueError, match="successor_evidence_version"): + _record( + superseded_at=CUTOVER, + successor_nonresponse_receipt_reference=SUCCESSOR, + successor_nonresponse_receipt_digest=SUCCESSOR_DIGEST, + successor_evidence_version=2, + successor_released_at=CUTOVER, + ) + with pytest.raises(ValueError, match="released after"): + _record( + superseded_at=RELEASED_AT + timedelta(seconds=1), + successor_nonresponse_receipt_reference=SUCCESSOR, + successor_nonresponse_receipt_digest=SUCCESSOR_DIGEST, + successor_evidence_version=1, + successor_released_at=RELEASED_AT, + ) + with pytest.raises(TypeError, match="issued only by"): + NonresponseAdjustmentSupersessionAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) + + +def test_record_and_view_are_immutable_and_uuid_views_detached() -> None: + """Detach UUIDs and reject mutation of owner records and minimized views.""" + tenant = UUID(str(TENANT)) + record = _record(tenant_record_id=tenant) + object.__setattr__(tenant, "int", OTHER_TENANT.int) + assert record.tenant_record_id == TENANT + assert record.validity_study_id == STUDY + assert record.released_at == RELEASED_AT + assert record.superseded_at is None + assert record.successor_fields is None + with pytest.raises(AttributeError): + object.__setattr__(record, "released_at", USED_AT) + + view = _resolve(read_port=_ReadPort(record)) + returned_tenant = view.tenant_record_id + object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) + assert view.tenant_record_id == TENANT + with pytest.raises(AttributeError): + object.__setattr__(view, "fields", ()) diff --git a/services/workforce-validation-api/tests/test_trimming_bounding_supersession_authority_edges.py b/services/workforce-validation-api/tests/test_trimming_bounding_supersession_authority_edges.py new file mode 100644 index 000000000..ce8f624b0 --- /dev/null +++ b/services/workforce-validation-api/tests/test_trimming_bounding_supersession_authority_edges.py @@ -0,0 +1,317 @@ +"""Hostile edges for append-only trimming-bounding correction authority.""" + +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from uuid import UUID + +import pytest + +from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy +from orgmetra_workforce_validation_api import ValidationPrincipal +from orgmetra_workforce_validation_api.trimming_bounding_supersession_authority import ( + TrimmingBoundingSupersessionAuthorityIntegrityError, + TrimmingBoundingSupersessionAuthorityNotFound, + TrimmingBoundingSupersessionAuthorityReadPort, + TrimmingBoundingSupersessionAuthorityRecord, + TrimmingBoundingSupersessionAuthorityView, + resolve_trimming_bounding_supersession_authority, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +OTHER_TENANT = UUID("10000000-0000-7000-8000-000000000002") +STUDY = UUID("00000000-0000-7000-8000-0000000000d1") +OTHER_STUDY = UUID("00000000-0000-7000-8000-0000000000d2") +RECEIPT = "trimming_bounding_adjustment_receipt:11111111-1111-4111-8111-111111111111" +OTHER_RECEIPT = "trimming_bounding_adjustment_receipt:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" +SUCCESSOR = "trimming_bounding_adjustment_receipt:22222222-2222-4222-8222-222222222222" +OWNER = "released_owner_contract:33333333-3333-4333-8333-333333333333" +OTHER_OWNER = "released_owner_contract:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" +RECEIPT_DIGEST = "1" * 64 +SUCCESSOR_DIGEST = "2" * 64 +OWNER_DIGEST = "3" * 64 +OWNER_RELEASED_AT = datetime(2026, 9, 17, 0, 30, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 17, 1, 0, tzinfo=timezone.utc) +USED_AT = datetime(2026, 9, 17, 2, 0, tzinfo=timezone.utc) +CUTOVER = datetime(2026, 9, 18, 1, 0, tzinfo=timezone.utc) +READ_FIELDS = frozenset( + { + "adjustment_receipt_reference", + "adjustment_receipt_digest", + "evidence_version", + "owner_contract_reference", + "owner_contract_version", + "owner_contract_digest", + "owner_contract_released_at", + "released_at", + "superseded_at", + "successor_adjustment_receipt_reference", + "successor_adjustment_receipt_digest", + "successor_evidence_version", + "successor_released_at", + } +) + + +class _ReadPort: + """Return configured authority and retain lookup coordinates.""" + + def __init__(self, result: object) -> None: + """Store one owner result and initialize the call ledger.""" + self.result = result + self.calls: list[dict[str, object]] = [] + + def read_trimming_bounding_supersession_authority( + self, **coordinates: object + ) -> object: + """Capture the owner lookup and return configured evidence.""" + self.calls.append(dict(coordinates)) + return self.result + + +class _NoReadMethod: + """Deliberately omit the required owner-read capability.""" + + +class _ProtocolOnly(TrimmingBoundingSupersessionAuthorityReadPort): + """Inherit only the Protocol declaration, not a concrete capability.""" + + +class _DescriptorReadPort: + """Expose a descriptor that static capability validation must reject.""" + + @property + def read_trimming_bounding_supersession_authority(self) -> object: + """Trip if dependency validation executes the descriptor.""" + raise AssertionError("descriptor must not execute") + + +def _principal(*, tenant_record_id: UUID = TENANT) -> ValidationPrincipal: + """Return one exact workforce-validation principal.""" + return ValidationPrincipal( + tenant_record_id=tenant_record_id, + actor_reference="person:validation-analyst-1", + granted_scope_codes=frozenset({"orgmetra.workforce_validation.read"}), + ) + + +def _policy(*, purpose_code: str = "selection_validity_analysis") -> PurposeBoundAccessPolicy: + """Return the purpose-bound policy for trimming correction evidence.""" + return PurposeBoundAccessPolicy( + tenant_record_id=TENANT, + policy_version_code="trimming-bounding-supersession-read-v1", + resource_kind="trimming_bounding_supersession_authority", + purpose_code=purpose_code, + operation_code="read", + required_scope_code="orgmetra.workforce_validation.read", + permitted_fields=READ_FIELDS, + ) + + +def _record(**overrides: object) -> TrimmingBoundingSupersessionAuthorityRecord: + """Build one current trimming correction state.""" + values: dict[str, object] = { + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "adjustment_receipt_reference": RECEIPT, + "adjustment_receipt_digest": RECEIPT_DIGEST, + "evidence_version": 1, + "owner_contract_reference": OWNER, + "owner_contract_version": 1, + "owner_contract_digest": OWNER_DIGEST, + "owner_contract_released_at": OWNER_RELEASED_AT, + "released_at": RELEASED_AT, + "superseded_at": None, + "successor_adjustment_receipt_reference": None, + "successor_adjustment_receipt_digest": None, + "successor_evidence_version": None, + "successor_released_at": None, + } + values.update(overrides) + return TrimmingBoundingSupersessionAuthorityRecord(**values) + + +def _resolve( + *, read_port: object, **overrides: object +) -> TrimmingBoundingSupersessionAuthorityView: + """Resolve current trimming authority with caller-known coordinates only.""" + values: dict[str, object] = { + "principal": _principal(), + "tenant_record_id": TENANT, + "validity_study_id": STUDY, + "adjustment_receipt_reference": RECEIPT, + "adjustment_receipt_digest": RECEIPT_DIGEST, + "evidence_version": 1, + "owner_contract_reference": OWNER, + "owner_contract_version": 1, + "owner_contract_digest": OWNER_DIGEST, + "used_at": USED_AT, + "purpose_code": "selection_validity_analysis", + "policy": _policy(), + "read_port": read_port, + } + values.update(overrides) + return resolve_trimming_bounding_supersession_authority(**values) + + +def test_current_receipt_resolution_uses_owner_chronology_without_successor() -> None: + """Resolve a current receipt and keep chronology out of the lookup key.""" + port = _ReadPort(_record()) + view = _resolve(read_port=port) + + assert isinstance(port, TrimmingBoundingSupersessionAuthorityReadPort) + assert len(port.calls) == 1 + assert "released_at" not in port.calls[0] + assert "superseded_at" not in port.calls[0] + assert view.tenant_record_id == TENANT + assert view.validity_study_id == STUDY + assert dict(view.fields)["released_at"] == RELEASED_AT + + +def test_authorization_denial_happens_before_owner_resolution() -> None: + """Do not consult owner evidence when purpose authorization fails.""" + port = _ReadPort(_record()) + with pytest.raises(AuthorizationDeniedError): + _resolve(read_port=port, policy=_policy(purpose_code="audit_review")) + assert port.calls == [] + + +def test_missing_or_noncanonical_owner_evidence_fails_closed() -> None: + """Reject absent and non-canonical owner evidence.""" + with pytest.raises(TrimmingBoundingSupersessionAuthorityNotFound): + _resolve(read_port=_ReadPort(None)) + with pytest.raises(TrimmingBoundingSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(object())) + + +@pytest.mark.parametrize( + "record_overrides", + [ + {"tenant_record_id": OTHER_TENANT}, + {"validity_study_id": OTHER_STUDY}, + {"adjustment_receipt_reference": OTHER_RECEIPT}, + {"adjustment_receipt_digest": "a" * 64}, + {"owner_contract_reference": OTHER_OWNER}, + {"owner_contract_version": 2}, + {"owner_contract_digest": "b" * 64}, + ], +) +def test_owner_evidence_must_match_every_requested_coordinate( + record_overrides: dict[str, object] +) -> None: + """Fail closed if owner evidence differs from any requested coordinate.""" + with pytest.raises(TrimmingBoundingSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(**record_overrides))) + + +def test_release_chronology_and_historical_use_are_distinct() -> None: + """Reject pre-release use while preserving history before a later cutover.""" + with pytest.raises(TrimmingBoundingSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(_record(released_at=USED_AT + timedelta(seconds=1)))) + + record = _record( + superseded_at=CUTOVER, + successor_adjustment_receipt_reference=SUCCESSOR, + successor_adjustment_receipt_digest=SUCCESSOR_DIGEST, + successor_evidence_version=1, + successor_released_at=CUTOVER, + ) + assert dict(_resolve(read_port=_ReadPort(record)).fields)[ + "adjustment_receipt_digest" + ] == RECEIPT_DIGEST + with pytest.raises(TrimmingBoundingSupersessionAuthorityIntegrityError): + _resolve(read_port=_ReadPort(record), used_at=CUTOVER) + + +@pytest.mark.parametrize( + ("key", "value", "error"), + [ + ("principal", object(), TypeError), + ("policy", object(), TypeError), + ("read_port", _NoReadMethod(), TypeError), + ("read_port", _ProtocolOnly(), TypeError), + ("read_port", _DescriptorReadPort(), TypeError), + ("tenant_record_id", "not-a-uuid", ValueError), + ("validity_study_id", UUID(int=0), ValueError), + ("adjustment_receipt_reference", "wrong:receipt", ValueError), + ("adjustment_receipt_digest", "ABC", ValueError), + ("evidence_version", 2, ValueError), + ("owner_contract_reference", "wrong:contract", ValueError), + ("owner_contract_version", 0, ValueError), + ("owner_contract_digest", "2" * 63, ValueError), + ("used_at", datetime(2026, 9, 17), ValueError), + ("purpose_code", "Selection Validity Analysis", ValueError), + ], +) +def test_invalid_request_or_dependency_fails_before_owner_resolution( + key: str, value: object, error: type[Exception] +) -> None: + """Validate caller-controlled coordinates before touching the owner port.""" + port: object = _ReadPort(_record()) + overrides = {key: value} + if key == "read_port": + port = value + overrides = {} + with pytest.raises(error): + _resolve(read_port=port, **overrides) + if isinstance(port, _ReadPort): + assert port.calls == [] + + +def test_record_rejects_invalid_chronology_schema_and_public_view() -> None: + """Keep chronology atomic, evidence v1, and minimized views issuer-only.""" + with pytest.raises(ValueError, match="evidence_version must remain 1"): + _record(evidence_version=2) + with pytest.raises(ValueError, match="owner contract"): + _record(owner_contract_released_at=RELEASED_AT + timedelta(seconds=1)) + with pytest.raises(ValueError, match="later than trimming"): + _record( + superseded_at=RELEASED_AT, + successor_adjustment_receipt_reference=SUCCESSOR, + successor_adjustment_receipt_digest=SUCCESSOR_DIGEST, + successor_evidence_version=1, + successor_released_at=RELEASED_AT, + ) + with pytest.raises(ValueError, match="successor_evidence_version"): + _record( + superseded_at=CUTOVER, + successor_adjustment_receipt_reference=SUCCESSOR, + successor_adjustment_receipt_digest=SUCCESSOR_DIGEST, + successor_evidence_version=2, + successor_released_at=CUTOVER, + ) + with pytest.raises(ValueError, match="released after"): + _record( + superseded_at=RELEASED_AT + timedelta(seconds=1), + successor_adjustment_receipt_reference=SUCCESSOR, + successor_adjustment_receipt_digest=SUCCESSOR_DIGEST, + successor_evidence_version=1, + successor_released_at=RELEASED_AT, + ) + with pytest.raises(TypeError, match="issued only by"): + TrimmingBoundingSupersessionAuthorityView( + tenant_record_id=TENANT, + validity_study_id=STUDY, + fields=(), + ) + + +def test_record_and_view_are_immutable_and_uuid_views_detached() -> None: + """Detach UUIDs and reject mutation of owner records and minimized views.""" + tenant = UUID(str(TENANT)) + record = _record(tenant_record_id=tenant) + object.__setattr__(tenant, "int", OTHER_TENANT.int) + assert record.tenant_record_id == TENANT + assert record.validity_study_id == STUDY + assert record.released_at == RELEASED_AT + assert record.superseded_at is None + assert record.successor_fields is None + with pytest.raises(AttributeError): + object.__setattr__(record, "released_at", USED_AT) + + view = _resolve(read_port=_ReadPort(record)) + returned_tenant = view.tenant_record_id + object.__setattr__(returned_tenant, "int", OTHER_TENANT.int) + assert view.tenant_record_id == TENANT + with pytest.raises(AttributeError): + object.__setattr__(view, "fields", ()) diff --git a/services/workforce-validation-api/tests/test_validation_result_authority.py b/services/workforce-validation-api/tests/test_validation_result_authority.py index cb2ce6c62..c075bf942 100644 --- a/services/workforce-validation-api/tests/test_validation_result_authority.py +++ b/services/workforce-validation-api/tests/test_validation_result_authority.py @@ -237,6 +237,8 @@ def test_distinct_evidence_digests_and_non_authorizing_status_are_required() -> _record(verification_status=1) with pytest.raises(ValueError): _record(verification_status="verified") + with pytest.raises(ValueError, match="superseded_at"): + _record(superseded_at=RELEASED_AT) def test_invalid_dependencies_and_pre_release_use_fail_closed() -> None: diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py index 49b760859..a99afeeab 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_edges.py @@ -316,6 +316,8 @@ def test_record_rejects_non_v1_and_public_view_construction() -> None: validity_study_id=STUDY, fields=(), ) + with pytest.raises(ValueError, match="digests must be distinct"): + _record(owner_contract_digest=RESULT_DIGEST) def test_record_rejects_naive_chronology_and_malformed_successor() -> None: diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py index 84b52ab6e..77df81a38 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_edges.py @@ -4,9 +4,12 @@ from datetime import datetime, timedelta, timezone from uuid import UUID +from types import SimpleNamespace import pytest +import orgmetra_workforce_validation_api.result_nonverifiability_supersession_v2_authority as v2_module + from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy from orgmetra_workforce_validation_api.registry import ValidationPrincipal from orgmetra_workforce_validation_api.result_nonverifiability import ( @@ -441,6 +444,22 @@ def test_record_requires_exact_non_reproducible_predecessor_and_v2() -> None: ) +def test_record_rechecks_exact_failed_artifact_after_predecessor_revalidation( + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Retain the constructor guard if predecessor revalidation ever regresses.""" + incomplete = SimpleNamespace( + failure_mode="non_reproducible", + failed_evidence_reference=None, + failed_evidence_digest=FAILED_DIGEST, + failed_evidence_released_at=FAILED_RELEASED_AT, + ) + monkeypatch.setattr(v2_module, "_revalidate_predecessor", lambda _value: incomplete) + + with pytest.raises(ValueError, match="retain exact failed-artifact evidence"): + _record() + + def test_incomplete_successor_tuple_fails_closed() -> None: """Never accept a cutover without every exact-artifact successor coordinate.""" values = _successor_overrides() @@ -531,3 +550,18 @@ def test_v2_rejects_structurally_forged_non_reproducible_predecessor() -> None: forged = tuple.__new__(ValidationResultNonVerifiabilityRecord, forged_values) with pytest.raises(ValueError, match="failed evidence reference and digest"): _record(predecessor=forged) + + +def test_owner_record_rejects_hidden_v2_structure() -> None: + """Reject hidden tuple coordinates even when visible owner evidence is valid.""" + record = _record() + forged = tuple.__new__( + ValidationResultNonVerifiabilitySupersessionV2AuthorityRecord, + tuple(record) + ("hidden-coordinate",), + ) + + with pytest.raises( + ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError, + match="non-canonical", + ): + _resolve(read_port=_ReadPort(forged)) diff --git a/services/workforce-validation-api/tests/test_weight_variance_authority_edges.py b/services/workforce-validation-api/tests/test_weight_variance_authority_edges.py index cd1700f01..c36d7c6d9 100644 --- a/services/workforce-validation-api/tests/test_weight_variance_authority_edges.py +++ b/services/workforce-validation-api/tests/test_weight_variance_authority_edges.py @@ -217,6 +217,10 @@ def test_approximation_mode_accepts_only_explicit_approximate_semantics() -> Non record = _record(variance_evidence_mode="approximation", variance_semantics="approximate") assert record.variance_evidence_mode == "approximation" assert record.variance_semantics == "approximate" + with pytest.raises(ValueError, match="approximation evidence"): + _record(variance_evidence_mode="approximation", variance_semantics="exact") + with pytest.raises(ValueError, match="approximation evidence"): + _resolve(variance_evidence_mode="approximation", variance_semantics="exact") @pytest.mark.parametrize( diff --git a/services/workforce-validation-api/tests/test_weight_variance_supersession_authority.py b/services/workforce-validation-api/tests/test_weight_variance_supersession_authority.py index 668756a0c..e4ffa29ca 100644 --- a/services/workforce-validation-api/tests/test_weight_variance_supersession_authority.py +++ b/services/workforce-validation-api/tests/test_weight_variance_supersession_authority.py @@ -130,6 +130,8 @@ def _resolve(*, read_port: object, used_at: datetime, **overrides: object): def test_successor_edge_requires_complete_atomic_released_coordinates() -> None: + with pytest.raises(ValueError, match="evidence_version must remain 1"): + _record(evidence_version=2) with pytest.raises(ValueError, match="complete released successor coordinates"): _record(successor_released_at=None) with pytest.raises(ValueError, match="later than compatibility authority release"): @@ -164,6 +166,8 @@ def test_historical_use_is_allowed_but_cutover_use_fails_closed() -> None: port = _ReadPort(record) view = _resolve(read_port=port, used_at=CUTOVER - timedelta(microseconds=1)) + assert view.validity_study_id == STUDY + assert isinstance(port, WeightVarianceSupersessionAuthorityReadPort) assert port.calls == [ { From 30100d8421451adc3cda4dddb7fe69bc3e778b09 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 23:06:51 +0900 Subject: [PATCH 472/603] test(workforce-validation): expose registry view tuple-constructor bypass --- .../tests/test_view_issuance_integrity.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/services/workforce-validation-api/tests/test_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_view_issuance_integrity.py index a44fce40c..ea84a593d 100644 --- a/services/workforce-validation-api/tests/test_view_issuance_integrity.py +++ b/services/workforce-validation-api/tests/test_view_issuance_integrity.py @@ -21,6 +21,25 @@ def test_direct_authorized_view_construction_fails_closed() -> None: ) +def test_low_level_tuple_construction_cannot_expose_authorized_view() -> None: + """Reject a caller-authored exact runtime view created through tuple.__new__.""" + forged = tuple.__new__( + registry.ValidityStudyView, + ( + TENANT.int, + STUDY.int, + (("study_status_code", "study_closed"),), + ), + ) + + for attribute in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + registry.ValidityStudyIntegrityError, + match="was not issued by read_validity_study", + ): + getattr(forged, attribute) + + def test_registry_module_exposes_no_unconditional_view_issuer() -> None: """Keep ordinary view issuance inside the authorized read application path.""" assert not hasattr(registry, "_issue_validity_study_view") From 11af877e06c70ce15fb9d37f4fab02a6bd5a361f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 23:08:26 +0900 Subject: [PATCH 473/603] fix(workforce-validation): seal registry view property access --- .../registry.py | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py index ef3374f96..1b8a0b4e6 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -37,6 +37,7 @@ "recorded_to", } ) +_VALIDITY_STUDY_VIEW_ISSUANCE_MARKER = object() class ValidityStudyNotFound(LookupError): @@ -299,11 +300,10 @@ class ValidityStudyView(tuple): """Structurally immutable field-minimized view returned after authorization. Tuple-backed storage keeps target UUIDs and UUID-valued projected evidence as - immutable integers, so downstream gateway, audit, or workspace code cannot - rewrite authorized identity through retained UUID objects. The public - constructor is deliberately non-issuing: callers obtain this data-only - projection from ``read_validity_study`` and must re-authorize consequential - actions rather than treating the Python runtime type as a durable credential. + immutable integers. An internal issuance marker additionally prevents a plain + base-class tuple construction from exposing caller-authored data through the + authorized-view properties. The view remains data, not a reusable credential; + consequential actions must re-authorize and re-resolve owner truth. """ __slots__ = () @@ -318,20 +318,33 @@ def __new__( """Reject public construction so only the authorized read path issues views.""" raise TypeError("ValidityStudyView is issued only by read_validity_study.") + def _require_issued(self) -> None: + """Reject a tuple-shaped value that was not sealed by the authorized read path.""" + if ( + tuple.__len__(self) != 4 + or tuple.__getitem__(self, 0) is not _VALIDITY_STUDY_VIEW_ISSUANCE_MARKER + ): + raise ValidityStudyIntegrityError( + "validity-study view was not issued by read_validity_study" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh tenant identity authorized for this view.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid("tenant_record_id", tuple.__getitem__(self, 1)) @property def validity_study_id(self) -> UUID: """Return a fresh validity-study identity authorized for this view.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid("validity_study_id", tuple.__getitem__(self, 2)) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return ordered field-minimized evidence with fresh UUID-valued projections.""" - return _restore_view_fields(self[2]) + self._require_issued() + return _restore_view_fields(tuple.__getitem__(self, 3)) @runtime_checkable @@ -453,6 +466,7 @@ def read_validity_study( return tuple.__new__( ValidityStudyView, ( + _VALIDITY_STUDY_VIEW_ISSUANCE_MARKER, tenant_identity, study_identity, _store_view_fields(projected_fields), From fcfdf222a6d04ddb801542692429f883c85dfd28 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 23:08:56 +0900 Subject: [PATCH 474/603] test(workforce-validation): cover forged registry view marker shape --- .../tests/test_view_issuance_integrity.py | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/services/workforce-validation-api/tests/test_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_view_issuance_integrity.py index ea84a593d..44e7e9268 100644 --- a/services/workforce-validation-api/tests/test_view_issuance_integrity.py +++ b/services/workforce-validation-api/tests/test_view_issuance_integrity.py @@ -22,22 +22,29 @@ def test_direct_authorized_view_construction_fails_closed() -> None: def test_low_level_tuple_construction_cannot_expose_authorized_view() -> None: - """Reject a caller-authored exact runtime view created through tuple.__new__.""" - forged = tuple.__new__( - registry.ValidityStudyView, + """Reject base-constructor views even when a caller mimics the sealed tuple shape.""" + payloads = ( ( TENANT.int, STUDY.int, (("study_status_code", "study_closed"),), ), + ( + object(), + TENANT.int, + STUDY.int, + (("study_status_code", "study_closed"),), + ), ) - for attribute in ("tenant_record_id", "validity_study_id", "fields"): - with pytest.raises( - registry.ValidityStudyIntegrityError, - match="was not issued by read_validity_study", - ): - getattr(forged, attribute) + for payload in payloads: + forged = tuple.__new__(registry.ValidityStudyView, payload) + for attribute in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + registry.ValidityStudyIntegrityError, + match="was not issued by read_validity_study", + ): + getattr(forged, attribute) def test_registry_module_exposes_no_unconditional_view_issuer() -> None: From dcd437a8a9c869164990562a5e83988fcae82132 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 23:10:52 +0900 Subject: [PATCH 475/603] test(workforce-validation): require registry view seal after raw allocation --- .../tests/test_view_issuance_integrity.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/tests/test_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_view_issuance_integrity.py index 44e7e9268..5a24c6256 100644 --- a/services/workforce-validation-api/tests/test_view_issuance_integrity.py +++ b/services/workforce-validation-api/tests/test_view_issuance_integrity.py @@ -22,7 +22,7 @@ def test_direct_authorized_view_construction_fails_closed() -> None: def test_low_level_tuple_construction_cannot_expose_authorized_view() -> None: - """Reject base-constructor views even when a caller mimics the sealed tuple shape.""" + """Reject base-constructor views before or at public projection access.""" payloads = ( ( TENANT.int, @@ -38,7 +38,10 @@ def test_low_level_tuple_construction_cannot_expose_authorized_view() -> None: ) for payload in payloads: - forged = tuple.__new__(registry.ValidityStudyView, payload) + try: + forged = tuple.__new__(registry.ValidityStudyView, payload) + except TypeError: + continue for attribute in ("tenant_record_id", "validity_study_id", "fields"): with pytest.raises( registry.ValidityStudyIntegrityError, @@ -47,6 +50,18 @@ def test_low_level_tuple_construction_cannot_expose_authorized_view() -> None: getattr(forged, attribute) +def test_unsealed_object_allocation_cannot_expose_authorized_view() -> None: + """Require the read-path seal even for a raw exact-runtime object allocation.""" + unsealed = object.__new__(registry.ValidityStudyView) + + for attribute in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + registry.ValidityStudyIntegrityError, + match="was not issued by read_validity_study", + ): + getattr(unsealed, attribute) + + def test_registry_module_exposes_no_unconditional_view_issuer() -> None: """Keep ordinary view issuance inside the authorized read application path.""" assert not hasattr(registry, "_issue_validity_study_view") From b5f76a14f3625a5583e84039c78c0264ce114787 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 23:11:41 +0900 Subject: [PATCH 476/603] fix(workforce-validation): make registry view non-tuple sealed data --- .../registry.py | 64 +++++++++++-------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py index 1b8a0b4e6..d1f6fca18 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -40,7 +40,7 @@ _VALIDITY_STUDY_VIEW_ISSUANCE_MARKER = object() -class ValidityStudyNotFound(LookupError): +class ValidityStudyNotFound(LookError): """Indicate that an authorized study identity has no visible registry record.""" @@ -296,17 +296,17 @@ def _restore_view_fields(fields: tuple[tuple[str, object], ...]) -> tuple[tuple[ ) -class ValidityStudyView(tuple): - """Structurally immutable field-minimized view returned after authorization. +class ValidityStudyView: + """Sealed field-minimized data view returned only after authorization. - Tuple-backed storage keeps target UUIDs and UUID-valued projected evidence as - immutable integers. An internal issuance marker additionally prevents a plain - base-class tuple construction from exposing caller-authored data through the - authorized-view properties. The view remains data, not a reusable credential; - consequential actions must re-authorize and re-resolve owner truth. + The public constructor is deliberately non-issuing. A raw object allocation + remains unusable because every public property verifies the private read-path + seal before exposing detached projection state. The runtime type is still + data, not a reusable authorization credential; consequential actions must + re-authorize and re-resolve owner truth. """ - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -318,12 +318,23 @@ def __new__( """Reject public construction so only the authorized read path issues views.""" raise TypeError("ValidityStudyView is issued only by read_validity_study.") + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError("ValidityStudyView is immutable.") + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError("ValidityStudyView is immutable.") + def _require_issued(self) -> None: - """Reject a tuple-shaped value that was not sealed by the authorized read path.""" - if ( - tuple.__len__(self) != 4 - or tuple.__getitem__(self, 0) is not _VALIDITY_STUDY_VIEW_ISSUANCE_MARKER - ): + """Reject raw exact-runtime allocations that were not sealed by the read path.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise ValidityStudyIntegrityError( + "validity-study view was not issued by read_validity_study" + ) from exc + if marker is not _VALIDITY_STUDY_VIEW_ISSUANCE_MARKER: raise ValidityStudyIntegrityError( "validity-study view was not issued by read_validity_study" ) @@ -332,19 +343,23 @@ def _require_issued(self) -> None: def tenant_record_id(self) -> UUID: """Return a fresh tenant identity authorized for this view.""" self._require_issued() - return _restore_operational_uuid("tenant_record_id", tuple.__getitem__(self, 1)) + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh validity-study identity authorized for this view.""" self._require_issued() - return _restore_operational_uuid("validity_study_id", tuple.__getitem__(self, 2)) + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return ordered field-minimized evidence with fresh UUID-valued projections.""" self._require_issued() - return _restore_view_fields(tuple.__getitem__(self, 3)) + return _restore_view_fields(object.__getattribute__(self, "_fields")) @runtime_checkable @@ -463,12 +478,9 @@ def read_validity_study( "recorded_to": record.recorded_to, } projected_fields = tuple((field_name, values[field_name]) for field_name in sorted(fields)) - return tuple.__new__( - ValidityStudyView, - ( - _VALIDITY_STUDY_VIEW_ISSUANCE_MARKER, - tenant_identity, - study_identity, - _store_view_fields(projected_fields), - ), - ) + view = object.__new__(ValidityStudyView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", _store_view_fields(projected_fields)) + object.__setattr__(view, "_issuance_marker", _VALIDITY_STUDY_VIEW_ISSUANCE_MARKER) + return view From 086ef714cc1434bfb8dbb787bd6541a48cc273e0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 23:12:29 +0900 Subject: [PATCH 477/603] fix(workforce-validation): restore registry not-found base type --- .../src/orgmetra_workforce_validation_api/registry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py index d1f6fca18..f7825de3f 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -40,7 +40,7 @@ _VALIDITY_STUDY_VIEW_ISSUANCE_MARKER = object() -class ValidityStudyNotFound(LookError): +class ValidityStudyNotFound(LookupError): """Indicate that an authorized study identity has no visible registry record.""" From bb98e90394d8d47f83c6f75c01c50429b5c2caff Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 23:20:22 +0900 Subject: [PATCH 478/603] fix(workforce-validation): seal auxiliary authority view --- .../scientific_authority.py | 51 +++++++++++++++---- .../test_calibration_auxiliary_authority.py | 28 ++++++++++ 2 files changed, 70 insertions(+), 9 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py index c62120f52..99241c0e8 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py @@ -35,6 +35,7 @@ _REFERENCE_PATTERN = re.compile(r"^[a-z][a-z0-9_]*:[A-Za-z0-9][A-Za-z0-9._~-]*$") _RESOURCE_KIND = "calibration_auxiliary_authority" _OPERATION = "read" +_CALIBRATION_AUXILIARY_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "authority_reference", @@ -333,10 +334,10 @@ def authorized_to(self) -> datetime | None: return self[19] -class CalibrationAuxiliaryAuthorityView(tuple): - """Field-minimized owner evidence issued only after authorization and resolution.""" +class CalibrationAuxiliaryAuthorityView: + """Sealed field-minimized data view issued only after owner resolution.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -351,20 +352,48 @@ def __new__( "resolve_calibration_auxiliary_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError("CalibrationAuxiliaryAuthorityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError("CalibrationAuxiliaryAuthorityView is immutable.") + + def _require_issued(self) -> None: + """Reject raw allocations not sealed by the authorized resolver path.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise CalibrationAuxiliaryAuthorityIntegrityError( + "calibration auxiliary authority view was not issued by the resolver" + ) from exc + if marker is not _CALIBRATION_AUXILIARY_VIEW_ISSUANCE_MARKER: + raise CalibrationAuxiliaryAuthorityIntegrityError( + "calibration auxiliary authority view was not issued by the resolver" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return immutable corroborating authority fields without protected values.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -621,7 +650,11 @@ def resolve_calibration_auxiliary_authority( "authorized_to": record.authorized_to, } fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) - return tuple.__new__( - CalibrationAuxiliaryAuthorityView, - (tenant_identity, study_identity, fields), + view = object.__new__(CalibrationAuxiliaryAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, "_issuance_marker", _CALIBRATION_AUXILIARY_VIEW_ISSUANCE_MARKER ) + return view diff --git a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py index df11b9ce2..482b59b7c 100644 --- a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py +++ b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py @@ -475,3 +475,31 @@ def test_record_and_view_are_structurally_immutable_and_uuid_views_are_detached( validity_study_id=STUDY, fields=(), ) + + +def test_low_level_view_allocation_cannot_expose_caller_authored_projection() -> None: + """Reject exact-runtime views that bypass the authorized resolver path.""" + with pytest.raises((TypeError, CalibrationAuxiliaryAuthorityIntegrityError)): + forged_tuple = tuple.__new__( + CalibrationAuxiliaryAuthorityView, + (TENANT.int, STUDY.int, (("authority_reference", AUTHORITY_REFERENCE),)), + ) + _ = forged_tuple.tenant_record_id + + with pytest.raises((TypeError, CalibrationAuxiliaryAuthorityIntegrityError)): + raw_view = object.__new__(CalibrationAuxiliaryAuthorityView) + _ = raw_view.fields + + wrong_marker_view = object.__new__(CalibrationAuxiliaryAuthorityView) + object.__setattr__(wrong_marker_view, "_issuance_marker", object()) + with pytest.raises(CalibrationAuxiliaryAuthorityIntegrityError): + _ = wrong_marker_view.validity_study_id + + +def test_issued_view_rejects_attribute_deletion() -> None: + """Keep authorized projection state immutable after resolver issuance.""" + view = _resolve(read_port=_ReadPort(_record())) + with pytest.raises(AttributeError, match="immutable"): + view._fields = () + with pytest.raises(AttributeError, match="immutable"): + del view._fields From 403296d1f20930ac412bfa3b1fb5be15e1b33b5b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 19 Sep 2026 23:22:55 +0900 Subject: [PATCH 479/603] docs(workforce-validation): record sealed-view repair --- CHANGELOG.md | 1 + manifest.json | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f87677de8..ab79d9e70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ All notable changes to Orgmetra will be documented in this file. ### Security +- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry and calibration auxiliary projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 22 other tuple-backed public views. - Predictive-validity cases fail closed when selection evidence, Job scope, study criterion, converted worker, or system-recorded visibility does not match; the normalized case relation is tenant-qualified, append-only, TRUNCATE-protected, and forced through row-level security. - Purpose-bound PII authorization now fails closed across active tenant, authenticated actor tenant, resource tenant, resource kind, purpose, operation, operation-specific Keyverse scope, and requested-field subset; malformed/wildcard-like attributes, mutable field/scope collections, reserved UUID sentinels, and cross-tenant confused-deputy contexts are rejected before protected values are returned. Authorization requests and allow/deny evidence now also require and preserve one namespaced opaque target-resource reference, so immutable audit correlation identifies the exact HR record without copying its protected values. Authorization evidence otherwise contains governance metadata and field names only, with stable denial reasons and actionable next steps rather than PII. - LLM output constrained to draft evidence. diff --git a/manifest.json b/manifest.json index 223408b5f..ccf1a2662 100644 --- a/manifest.json +++ b/manifest.json @@ -29,9 +29,9 @@ }, { "path": "CHANGELOG.md", - "sha256": "0b5ce1897d82ed815627658a57cbfcb6a1c65425e119aaffa2d194b79f6b15d7", - "bytes": 18288, - "lines": 79 + "sha256": "ddf47c709a7616adecbce16f261effc763d98e15120ee58171146af346ab2427", + "bytes": 18714, + "lines": 80 }, { "path": "CLAUDE.md", From c0d94a04415a284f70e3d0617c4baa76f9c184c5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 00:04:04 +0900 Subject: [PATCH 480/603] test(workforce-validation): expose base-weight view issuance bypass --- ...eight_authority_view_issuance_integrity.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_base_weight_authority_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_base_weight_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_base_weight_authority_view_issuance_integrity.py new file mode 100644 index 000000000..ee69baacc --- /dev/null +++ b/services/workforce-validation-api/tests/test_base_weight_authority_view_issuance_integrity.py @@ -0,0 +1,61 @@ +"""Regression contract for base-weight authorized-view issuance integrity.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.base_weight_authority import ( + BaseWeightAuthorityIntegrityError, + BaseWeightAuthorityView, +) + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") + + +def test_low_level_tuple_construction_cannot_issue_base_weight_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + BaseWeightAuthorityView, + ( + TENANT.int, + STUDY.int, + (("base_weight_artifact_digest", "6" * 64),), + ), + ) + + +def test_unsealed_object_allocation_cannot_expose_base_weight_view() -> None: + """Require the resolver seal before any raw exact-runtime object exposes state.""" + unsealed = object.__new__(BaseWeightAuthorityView) + + for attribute in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + BaseWeightAuthorityIntegrityError, + match="was not issued by resolve_base_weight_authority", + ): + getattr(unsealed, attribute) + + +def test_wrong_issuance_marker_cannot_expose_base_weight_view() -> None: + """Reject marker-shaped raw objects that did not originate from the resolver.""" + forged = object.__new__(BaseWeightAuthorityView) + object.__setattr__(forged, "_issuance_marker", object()) + + with pytest.raises( + BaseWeightAuthorityIntegrityError, + match="was not issued by resolve_base_weight_authority", + ): + _ = forged.fields + + +def test_raw_base_weight_view_rejects_public_mutation_and_deletion() -> None: + """Keep projection state immutable even when callers allocate the exact runtime type.""" + raw = object.__new__(BaseWeightAuthorityView) + + with pytest.raises(AttributeError, match="immutable"): + raw._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw._fields From 6b1591d68eb2ae57f40c6a050d8c7a7b9d375559 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 00:05:25 +0900 Subject: [PATCH 481/603] fix(workforce-validation): seal base-weight authority views --- .../base_weight_authority.py | 67 +++++++++++++++---- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py index 8b99e5075..6b50844dd 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py @@ -72,6 +72,7 @@ "owner_contract_released_at", } ) +_BASE_WEIGHT_AUTHORITY_VIEW_ISSUANCE_MARKER = object() class BaseWeightAuthorityNotFound(LookupError): @@ -255,10 +256,16 @@ def superseded_at(self) -> datetime | None: return self[4] -class BaseWeightAuthorityView(tuple): - """Field-minimized base-weight evidence issued only after authorization.""" +class BaseWeightAuthorityView: + """Sealed field-minimized base-weight evidence issued only after authorization. - __slots__ = () + The public constructor is deliberately non-issuing. Raw exact-runtime + allocations remain unusable because each public property verifies the private + resolver seal before exposing detached projection state. Consequential actions + must still re-authorize and re-resolve owner truth rather than trusting a view. + """ + + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -272,20 +279,48 @@ def __new__( "BaseWeightAuthorityView is issued only by resolve_base_weight_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError("BaseWeightAuthorityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError("BaseWeightAuthorityView is immutable.") + + def _require_issued(self) -> None: + """Reject exact-runtime allocations that were not sealed by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise BaseWeightAuthorityIntegrityError( + "base-weight authority view was not issued by resolve_base_weight_authority" + ) from exc + if marker is not _BASE_WEIGHT_AUTHORITY_VIEW_ISSUANCE_MARKER: + raise BaseWeightAuthorityIntegrityError( + "base-weight authority view was not issued by resolve_base_weight_authority" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return released base-weight provenance without row-level probabilities.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -522,14 +557,20 @@ def resolve_base_weight_authority( values["released_at"] = record.released_at values["superseded_at"] = record.superseded_at fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) - return tuple.__new__( - BaseWeightAuthorityView, - ( - _store_operational_uuid("tenant_record_id", record.tenant_record_id), - _store_operational_uuid("validity_study_id", record.validity_study_id), - fields, - ), + view = object.__new__(BaseWeightAuthorityView) + object.__setattr__( + view, + "_tenant_identity", + _store_operational_uuid("tenant_record_id", record.tenant_record_id), + ) + object.__setattr__( + view, + "_study_identity", + _store_operational_uuid("validity_study_id", record.validity_study_id), ) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", _BASE_WEIGHT_AUTHORITY_VIEW_ISSUANCE_MARKER) + return view __all__ = [ From d78d9a9c25531fa74458dbf1d966aabe70da4bb2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 00:14:54 +0900 Subject: [PATCH 482/603] test(workforce-validation): expose base-weight supersession view bypass --- ...ssion_authority_view_issuance_integrity.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_base_weight_supersession_authority_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_base_weight_supersession_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_base_weight_supersession_authority_view_issuance_integrity.py new file mode 100644 index 000000000..91c660461 --- /dev/null +++ b/services/workforce-validation-api/tests/test_base_weight_supersession_authority_view_issuance_integrity.py @@ -0,0 +1,61 @@ +"""Regression contract for base-weight supersession view issuance integrity.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.base_weight_supersession_authority import ( + BaseWeightSupersessionAuthorityIntegrityError, + BaseWeightSupersessionAuthorityView, +) + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") + + +def test_low_level_tuple_construction_cannot_issue_supersession_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + BaseWeightSupersessionAuthorityView, + ( + TENANT.int, + STUDY.int, + (("base_weight_evidence_receipt_digest", "6" * 64),), + ), + ) + + +def test_unsealed_object_allocation_cannot_expose_supersession_view() -> None: + """Require the resolver seal before raw exact-runtime objects expose state.""" + unsealed = object.__new__(BaseWeightSupersessionAuthorityView) + + for attribute_name in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + BaseWeightSupersessionAuthorityIntegrityError, + match="was not issued by resolve_base_weight_supersession_authority", + ): + getattr(unsealed, attribute_name) + + +def test_wrong_issuance_marker_cannot_expose_supersession_view() -> None: + """Reject marker-shaped objects that did not originate from the resolver.""" + forged_view = object.__new__(BaseWeightSupersessionAuthorityView) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises( + BaseWeightSupersessionAuthorityIntegrityError, + match="was not issued by resolve_base_weight_supersession_authority", + ): + _ = forged_view.fields + + +def test_raw_supersession_view_rejects_mutation_and_deletion() -> None: + """Keep projection state immutable after raw exact-runtime allocation.""" + raw_view = object.__new__(BaseWeightSupersessionAuthorityView) + + with pytest.raises(AttributeError, match="immutable"): + raw_view._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw_view._fields From 06b98499eabc0830aec5bd929344a7d34a93313d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 00:14:55 +0900 Subject: [PATCH 483/603] fix(workforce-validation): seal base-weight supersession views --- .../base_weight_supersession_authority.py | 67 +++++++++++++++---- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_supersession_authority.py index 534cdc42e..048f1ae26 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_supersession_authority.py @@ -37,6 +37,7 @@ _RESOURCE_KIND = "base_weight_supersession_authority" _OPERATION = "read" +_BASE_WEIGHT_SUPERSESSION_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "base_weight_evidence_receipt_reference", @@ -231,10 +232,10 @@ def successor_fields(self) -> tuple[tuple[str, object], ...] | None: return self[5] -class BaseWeightSupersessionAuthorityView(tuple): - """Minimized current-receipt authority issued only after authorization.""" +class BaseWeightSupersessionAuthorityView: + """Sealed current-receipt authority issued only after authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -249,20 +250,50 @@ def __new__( "resolve_base_weight_supersession_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError("BaseWeightSupersessionAuthorityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError("BaseWeightSupersessionAuthorityView is immutable.") + + def _require_issued(self) -> None: + """Reject exact-runtime allocations not sealed by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise BaseWeightSupersessionAuthorityIntegrityError( + "base-weight supersession view was not issued by " + "resolve_base_weight_supersession_authority" + ) from exc + if marker is not _BASE_WEIGHT_SUPERSESSION_VIEW_ISSUANCE_MARKER: + raise BaseWeightSupersessionAuthorityIntegrityError( + "base-weight supersession view was not issued by " + "resolve_base_weight_supersession_authority" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return current receipt authority without successor disclosure.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -472,14 +503,24 @@ def resolve_base_weight_supersession_authority( ("released_at", record.released_at), ("superseded_at", record.superseded_at), ) - return tuple.__new__( - BaseWeightSupersessionAuthorityView, - ( - _store_operational_uuid("tenant_record_id", record.tenant_record_id), - _store_operational_uuid("validity_study_id", record.validity_study_id), - fields, - ), + view = object.__new__(BaseWeightSupersessionAuthorityView) + object.__setattr__( + view, + "_tenant_identity", + _store_operational_uuid("tenant_record_id", record.tenant_record_id), + ) + object.__setattr__( + view, + "_study_identity", + _store_operational_uuid("validity_study_id", record.validity_study_id), + ) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, + "_issuance_marker", + _BASE_WEIGHT_SUPERSESSION_VIEW_ISSUANCE_MARKER, ) + return view __all__ = [ From 213bbfd88388a3e2befb664eccc54b025ba71cb0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 00:17:03 +0900 Subject: [PATCH 484/603] docs(workforce-validation): record supersession view repair evidence --- CHANGELOG.md | 2 +- manifest.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab79d9e70..bd0817dbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ All notable changes to Orgmetra will be documented in this file. ### Security -- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry and calibration auxiliary projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 22 other tuple-backed public views. +- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry, calibration auxiliary, base-weight, and base-weight supersession projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 20 other tuple-backed public views. - Predictive-validity cases fail closed when selection evidence, Job scope, study criterion, converted worker, or system-recorded visibility does not match; the normalized case relation is tenant-qualified, append-only, TRUNCATE-protected, and forced through row-level security. - Purpose-bound PII authorization now fails closed across active tenant, authenticated actor tenant, resource tenant, resource kind, purpose, operation, operation-specific Keyverse scope, and requested-field subset; malformed/wildcard-like attributes, mutable field/scope collections, reserved UUID sentinels, and cross-tenant confused-deputy contexts are rejected before protected values are returned. Authorization requests and allow/deny evidence now also require and preserve one namespaced opaque target-resource reference, so immutable audit correlation identifies the exact HR record without copying its protected values. Authorization evidence otherwise contains governance metadata and field names only, with stable denial reasons and actionable next steps rather than PII. - LLM output constrained to draft evidence. diff --git a/manifest.json b/manifest.json index ccf1a2662..27cf20d05 100644 --- a/manifest.json +++ b/manifest.json @@ -29,8 +29,8 @@ }, { "path": "CHANGELOG.md", - "sha256": "ddf47c709a7616adecbce16f261effc763d98e15120ee58171146af346ab2427", - "bytes": 18714, + "sha256": "3868425e4161481a1d473189b31ae3501a44a281a70fc02d7888bb289450d619", + "bytes": 18754, "lines": 80 }, { From 38c261180177b37080fd9ee957030f2fc451a810 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 01:01:48 +0900 Subject: [PATCH 485/603] test(workforce-validation): prove calibration benchmark view issuance bypass --- ...hmark_authority_view_issuance_integrity.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_benchmark_authority_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_calibration_benchmark_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_calibration_benchmark_authority_view_issuance_integrity.py new file mode 100644 index 000000000..6ff6ef0a6 --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_benchmark_authority_view_issuance_integrity.py @@ -0,0 +1,61 @@ +"""Regression contract for calibration-benchmark authorized-view issuance integrity.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.benchmark_authority import ( + CalibrationBenchmarkAuthorityIntegrityError, + CalibrationBenchmarkAuthorityView, +) + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") + + +def test_low_level_tuple_construction_cannot_issue_calibration_benchmark_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + CalibrationBenchmarkAuthorityView, + ( + TENANT.int, + STUDY.int, + (("benchmark_receipt_digest", "6" * 64),), + ), + ) + + +def test_unsealed_object_allocation_cannot_expose_calibration_benchmark_view() -> None: + """Require the resolver seal before any raw exact-runtime object exposes state.""" + unsealed = object.__new__(CalibrationBenchmarkAuthorityView) + + for attribute in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + CalibrationBenchmarkAuthorityIntegrityError, + match="was not issued by resolve_calibration_benchmark_authority", + ): + getattr(unsealed, attribute) + + +def test_wrong_issuance_marker_cannot_expose_calibration_benchmark_view() -> None: + """Reject marker-shaped raw objects that did not originate from the resolver.""" + forged = object.__new__(CalibrationBenchmarkAuthorityView) + object.__setattr__(forged, "_issuance_marker", object()) + + with pytest.raises( + CalibrationBenchmarkAuthorityIntegrityError, + match="was not issued by resolve_calibration_benchmark_authority", + ): + _ = forged.fields + + +def test_raw_calibration_benchmark_view_rejects_public_mutation_and_deletion() -> None: + """Keep projection state immutable even when callers allocate the exact runtime type.""" + raw = object.__new__(CalibrationBenchmarkAuthorityView) + + with pytest.raises(AttributeError, match="immutable"): + raw._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw._fields From fbb3b7407f2f4c149373dc91f7221b1ae978659f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 01:02:43 +0900 Subject: [PATCH 486/603] fix(workforce-validation): seal calibration benchmark authority view --- .../benchmark_authority.py | 75 +++++++++++++++---- 1 file changed, 61 insertions(+), 14 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py index 379686e00..a45435b80 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py @@ -47,6 +47,7 @@ "owner_contract_released_at", } ) +_CALIBRATION_BENCHMARK_AUTHORITY_VIEW_ISSUANCE_MARKER = object() class CalibrationBenchmarkAuthorityNotFound(LookupError): @@ -313,10 +314,16 @@ def successor_benchmark_receipt_released_at(self) -> datetime | None: return self[15] -class CalibrationBenchmarkAuthorityView(tuple): - """Field-minimized benchmark evidence issued only after authorization.""" +class CalibrationBenchmarkAuthorityView: + """Sealed field-minimized benchmark evidence issued only after authorization. - __slots__ = () + The public constructor is deliberately non-issuing. Raw exact-runtime + allocations remain unusable because each public property verifies the private + resolver seal before exposing detached projection state. Consequential actions + must still re-authorize and re-resolve owner truth rather than trusting a view. + """ + + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -325,26 +332,56 @@ def __new__( validity_study_id: UUID, fields: tuple[tuple[str, object], ...], ) -> CalibrationBenchmarkAuthorityView: - """Reject direct construction; only the resolver may issue this view.""" + """Reject public construction; only the resolver may issue this view.""" raise TypeError( "CalibrationBenchmarkAuthorityView is issued only by " "resolve_calibration_benchmark_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError("CalibrationBenchmarkAuthorityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError("CalibrationBenchmarkAuthorityView is immutable.") + + def _require_issued(self) -> None: + """Reject exact-runtime allocations that were not sealed by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise CalibrationBenchmarkAuthorityIntegrityError( + "calibration benchmark authority view was not issued by " + "resolve_calibration_benchmark_authority" + ) from exc + if marker is not _CALIBRATION_BENCHMARK_AUTHORITY_VIEW_ISSUANCE_MARKER: + raise CalibrationBenchmarkAuthorityIntegrityError( + "calibration benchmark authority view was not issued by " + "resolve_calibration_benchmark_authority" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return immutable released benchmark evidence without benchmark values.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -574,11 +611,21 @@ def resolve_calibration_benchmark_authority( ("benchmark_reference_at", record.benchmark_reference_at), ("owner_contract_released_at", record.owner_contract_released_at), ) - return tuple.__new__( - CalibrationBenchmarkAuthorityView, - ( - _store_operational_uuid("tenant_record_id", tenant_id), - _store_operational_uuid("validity_study_id", study_id), - fields, - ), + view = object.__new__(CalibrationBenchmarkAuthorityView) + object.__setattr__( + view, + "_tenant_identity", + _store_operational_uuid("tenant_record_id", tenant_id), + ) + object.__setattr__( + view, + "_study_identity", + _store_operational_uuid("validity_study_id", study_id), + ) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, + "_issuance_marker", + _CALIBRATION_BENCHMARK_AUTHORITY_VIEW_ISSUANCE_MARKER, ) + return view From 3cff6e59b0c62af2a1d6956623bf882661a68d5a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 01:08:51 +0900 Subject: [PATCH 487/603] docs(workforce-validation): record calibration benchmark view hardening --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd0817dbf..3e2573c41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ All notable changes to Orgmetra will be documented in this file. - `employment_record_version.employment_concurrency_code` constrained to `exclusive` or `concurrent`. - ADR 0005 for exclusive employment and staffable seats. - `orgmetra_hris_kernel` 0.3.0 with identity-scoped bitemporal resolution, assignment-employment coverage, allocation-portfolio checks, and a Memorial Hospital RN correction case at 100% statement and branch coverage. -- `employment_record_version` and `position_record_version` so employment and position identity stay stable across retroactive corrections. +- `employment_record_version` and `position_record_version` so corrections no longer mint a new employment or position identifier. - `assignment_record.employment_record_id` bound to the same person as the covering employment. - `orgmetra_keyverse_adapter` that binds an opaque Keyverse subject to a person and rejects passwords, passkeys, and tokens. - Design tokens for the repeating HR actions: approve, review, correct, request evidence, compare, export, and escalate. @@ -59,7 +59,7 @@ All notable changes to Orgmetra will be documented in this file. ### Security -- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry, calibration auxiliary, base-weight, and base-weight supersession projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 20 other tuple-backed public views. +- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry, calibration auxiliary, base-weight, base-weight supersession, and calibration benchmark projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 19 other tuple-backed public views. - Predictive-validity cases fail closed when selection evidence, Job scope, study criterion, converted worker, or system-recorded visibility does not match; the normalized case relation is tenant-qualified, append-only, TRUNCATE-protected, and forced through row-level security. - Purpose-bound PII authorization now fails closed across active tenant, authenticated actor tenant, resource tenant, resource kind, purpose, operation, operation-specific Keyverse scope, and requested-field subset; malformed/wildcard-like attributes, mutable field/scope collections, reserved UUID sentinels, and cross-tenant confused-deputy contexts are rejected before protected values are returned. Authorization requests and allow/deny evidence now also require and preserve one namespaced opaque target-resource reference, so immutable audit correlation identifies the exact HR record without copying its protected values. Authorization evidence otherwise contains governance metadata and field names only, with stable denial reasons and actionable next steps rather than PII. - LLM output constrained to draft evidence. From fc2ae49412102f97f698303aaae5aa710ea29c43 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 01:09:51 +0900 Subject: [PATCH 488/603] build(provenance): reseal changelog manifest after benchmark hardening --- manifest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manifest.json b/manifest.json index 27cf20d05..a32065099 100644 --- a/manifest.json +++ b/manifest.json @@ -29,8 +29,8 @@ }, { "path": "CHANGELOG.md", - "sha256": "3868425e4161481a1d473189b31ae3501a44a281a70fc02d7888bb289450d619", - "bytes": 18754, + "sha256": "0245887b71d1b8dc68e25c16c212fc2231c0312bb19e873d6cdee4270207a388", + "bytes": 18777, "lines": 80 }, { From 634958a88b932f9aa5a4384bc37ff5cca004941e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 01:14:22 +0900 Subject: [PATCH 489/603] test(workforce-validation): expose calibration adjustment view bypass --- .../test_calibration_adjustment_authority.py | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py b/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py index 4b375b771..9ba1804e2 100644 --- a/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py @@ -521,3 +521,46 @@ def test_record_and_view_are_structurally_immutable_and_uuid_views_are_detached( validity_study_id=STUDY, fields=(), ) + + +def test_view_rejects_tuple_base_constructor_forgery() -> None: + """Reject caller-authored instances created through the tuple base class.""" + with pytest.raises(TypeError): + tuple.__new__( + CalibrationAdjustmentAuthorityView, + (TENANT, STUDY, (("termination_code", "converged"),)), + ) + + +def test_raw_view_allocation_cannot_expose_projection_state() -> None: + """Keep an unissued raw allocation unusable through every public property.""" + forged = object.__new__(CalibrationAdjustmentAuthorityView) + + with pytest.raises(CalibrationAdjustmentAuthorityIntegrityError): + _ = forged.tenant_record_id + with pytest.raises(CalibrationAdjustmentAuthorityIntegrityError): + _ = forged.validity_study_id + with pytest.raises(CalibrationAdjustmentAuthorityIntegrityError): + _ = forged.fields + + +def test_view_rejects_caller_authored_issuance_marker() -> None: + """Reject a raw allocation even when a caller invents a marker value.""" + forged = object.__new__(CalibrationAdjustmentAuthorityView) + object.__setattr__(forged, "_tenant_identity", TENANT) + object.__setattr__(forged, "_study_identity", STUDY) + object.__setattr__(forged, "_fields", ()) + object.__setattr__(forged, "_issuance_marker", object()) + + with pytest.raises(CalibrationAdjustmentAuthorityIntegrityError): + _ = forged.fields + + +def test_issued_view_rejects_mutation_and_deletion() -> None: + """Keep a resolver-issued view immutable after all owner checks complete.""" + view = _resolve(read_port=_ReadPort(_record())) + + with pytest.raises(AttributeError): + view._fields = () + with pytest.raises(AttributeError): + del view._fields From d7983d1a4ceb2a570992256dc22ac1fdea3f789c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 01:15:58 +0900 Subject: [PATCH 490/603] fix(workforce-validation): seal calibration adjustment views --- .../calibration_adjustment_authority.py | 57 +++++++++++++++---- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py index 58f4b4a7e..87cbd790d 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py @@ -38,6 +38,7 @@ _RESOURCE_KIND = "calibration_adjustment_authority" _OPERATION = "read" +_CALIBRATION_ADJUSTMENT_VIEW_ISSUANCE_MARKER = object() _TERMINATION_CODES = frozenset({"converged", "fallback_applied"}) _READ_FIELDS = frozenset( { @@ -643,10 +644,10 @@ def superseded_at(self) -> datetime | None: return self[46] -class CalibrationAdjustmentAuthorityView(tuple): +class CalibrationAdjustmentAuthorityView: """Field-minimized typed calibration evidence issued only after authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -661,20 +662,48 @@ def __new__( "resolve_calibration_adjustment_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Reject mutation after resolver-controlled issuance.""" + raise AttributeError("CalibrationAdjustmentAuthorityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Reject deletion after resolver-controlled issuance.""" + raise AttributeError("CalibrationAdjustmentAuthorityView is immutable.") + + def _require_issued(self) -> None: + """Require the exact in-process marker written by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise CalibrationAdjustmentAuthorityIntegrityError( + "calibration-adjustment authority view was not issued by the resolver" + ) from exc + if marker is not _CALIBRATION_ADJUSTMENT_VIEW_ISSUANCE_MARKER: + raise CalibrationAdjustmentAuthorityIntegrityError( + "calibration-adjustment authority view has an invalid issuance marker" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return immutable typed calibration provenance without source values.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -1062,11 +1091,15 @@ def resolve_calibration_adjustment_authority( ("fallback_rule_digest", record.fallback_rule_digest), ("fallback_rule_reference", record.fallback_rule_reference), ) - return tuple.__new__( - CalibrationAdjustmentAuthorityView, - ( - _store_operational_uuid("tenant_record_id", tenant_id), - _store_operational_uuid("validity_study_id", study_id), - fields, - ), + view = object.__new__(CalibrationAdjustmentAuthorityView) + object.__setattr__( + view, "_tenant_identity", _store_operational_uuid("tenant_record_id", tenant_id) + ) + object.__setattr__( + view, "_study_identity", _store_operational_uuid("validity_study_id", study_id) + ) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, "_issuance_marker", _CALIBRATION_ADJUSTMENT_VIEW_ISSUANCE_MARKER ) + return view From 70c82573191cd86d172d80ebf56e82f319ef25f5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 01:18:08 +0900 Subject: [PATCH 491/603] docs(workforce-validation): record calibration adjustment repair evidence --- CHANGELOG.md | 2 +- manifest.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e2573c41..8239efbe6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ All notable changes to Orgmetra will be documented in this file. ### Security -- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry, calibration auxiliary, base-weight, base-weight supersession, and calibration benchmark projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 19 other tuple-backed public views. +- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry, calibration auxiliary, base-weight, base-weight supersession, calibration benchmark, and calibration adjustment projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 18 other tuple-backed public views. - Predictive-validity cases fail closed when selection evidence, Job scope, study criterion, converted worker, or system-recorded visibility does not match; the normalized case relation is tenant-qualified, append-only, TRUNCATE-protected, and forced through row-level security. - Purpose-bound PII authorization now fails closed across active tenant, authenticated actor tenant, resource tenant, resource kind, purpose, operation, operation-specific Keyverse scope, and requested-field subset; malformed/wildcard-like attributes, mutable field/scope collections, reserved UUID sentinels, and cross-tenant confused-deputy contexts are rejected before protected values are returned. Authorization requests and allow/deny evidence now also require and preserve one namespaced opaque target-resource reference, so immutable audit correlation identifies the exact HR record without copying its protected values. Authorization evidence otherwise contains governance metadata and field names only, with stable denial reasons and actionable next steps rather than PII. - LLM output constrained to draft evidence. diff --git a/manifest.json b/manifest.json index a32065099..aae250680 100644 --- a/manifest.json +++ b/manifest.json @@ -29,8 +29,8 @@ }, { "path": "CHANGELOG.md", - "sha256": "0245887b71d1b8dc68e25c16c212fc2231c0312bb19e873d6cdee4270207a388", - "bytes": 18777, + "sha256": "ff614ee477897fce6bfa7eeb61d932f9a666d336c03d3dd6757010fddf1c026d", + "bytes": 18792, "lines": 80 }, { From e77882395de9781a4544ceff454c0e5c747af250 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 01:20:24 +0900 Subject: [PATCH 492/603] test(workforce-validation): expose weight eligibility view bypass --- .../test_weight_eligibility_authority.py | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/services/workforce-validation-api/tests/test_weight_eligibility_authority.py b/services/workforce-validation-api/tests/test_weight_eligibility_authority.py index 805e63dd2..4b976d826 100644 --- a/services/workforce-validation-api/tests/test_weight_eligibility_authority.py +++ b/services/workforce-validation-api/tests/test_weight_eligibility_authority.py @@ -301,3 +301,46 @@ def test_record_and_view_are_structurally_immutable_and_uuid_views_are_detached( validity_study_id=STUDY, fields=(), ) + + +def test_view_rejects_tuple_base_constructor_forgery() -> None: + """Reject caller-authored instances created through the tuple base class.""" + with pytest.raises(TypeError): + tuple.__new__( + WeightEligibilityAuthorityView, + (TENANT, STUDY, (("weight_scope_code", "longitudinal"),)), + ) + + +def test_raw_view_allocation_cannot_expose_projection_state() -> None: + """Keep an unissued raw allocation unusable through every public property.""" + forged = object.__new__(WeightEligibilityAuthorityView) + + with pytest.raises(WeightEligibilityAuthorityIntegrityError): + _ = forged.tenant_record_id + with pytest.raises(WeightEligibilityAuthorityIntegrityError): + _ = forged.validity_study_id + with pytest.raises(WeightEligibilityAuthorityIntegrityError): + _ = forged.fields + + +def test_view_rejects_caller_authored_issuance_marker() -> None: + """Reject a raw allocation even when a caller invents a marker value.""" + forged = object.__new__(WeightEligibilityAuthorityView) + object.__setattr__(forged, "_tenant_identity", TENANT) + object.__setattr__(forged, "_study_identity", STUDY) + object.__setattr__(forged, "_fields", ()) + object.__setattr__(forged, "_issuance_marker", object()) + + with pytest.raises(WeightEligibilityAuthorityIntegrityError): + _ = forged.fields + + +def test_issued_view_rejects_mutation_and_deletion() -> None: + """Keep a resolver-issued view immutable after all owner checks complete.""" + view = _resolve(read_port=_ReadPort(_record())) + + with pytest.raises(AttributeError): + view._fields = () + with pytest.raises(AttributeError): + del view._fields From f35f1dc9496f9db4e6711e844a9fdd7eb0d5b037 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 01:21:19 +0900 Subject: [PATCH 493/603] fix(workforce-validation): seal weight eligibility views --- .../weight_eligibility_authority.py | 57 +++++++++++++++---- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py index 31c51eefa..45df5b2a6 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py @@ -35,6 +35,7 @@ _RESOURCE_KIND = "weight_eligibility_authority" _OPERATION = "read" +_WEIGHT_ELIGIBILITY_VIEW_ISSUANCE_MARKER = object() _WEIGHT_SCOPE_CODES = frozenset({"cross_sectional", "longitudinal"}) _READ_FIELDS = frozenset( { @@ -285,10 +286,10 @@ def superseded_at(self) -> datetime | None: return self[18] -class WeightEligibilityAuthorityView(tuple): +class WeightEligibilityAuthorityView: """Field-minimized eligibility evidence issued only after authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -303,20 +304,48 @@ def __new__( "resolve_weight_eligibility_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Reject mutation after resolver-controlled issuance.""" + raise AttributeError("WeightEligibilityAuthorityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Reject deletion after resolver-controlled issuance.""" + raise AttributeError("WeightEligibilityAuthorityView is immutable.") + + def _require_issued(self) -> None: + """Require the exact in-process marker written by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise WeightEligibilityAuthorityIntegrityError( + "weight-eligibility authority view was not issued by the resolver" + ) from exc + if marker is not _WEIGHT_ELIGIBILITY_VIEW_ISSUANCE_MARKER: + raise WeightEligibilityAuthorityIntegrityError( + "weight-eligibility authority view has an invalid issuance marker" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return immutable eligibility provenance without row-level values.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -526,11 +555,15 @@ def resolve_weight_eligibility_authority( ("weight_artifact_digest", record.weight_artifact_digest), ("weight_scope_code", record.weight_scope_code), ) - return tuple.__new__( - WeightEligibilityAuthorityView, - ( - _store_operational_uuid("tenant_record_id", tenant_id), - _store_operational_uuid("validity_study_id", study_id), - fields, - ), + view = object.__new__(WeightEligibilityAuthorityView) + object.__setattr__( + view, "_tenant_identity", _store_operational_uuid("tenant_record_id", tenant_id) + ) + object.__setattr__( + view, "_study_identity", _store_operational_uuid("validity_study_id", study_id) + ) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, "_issuance_marker", _WEIGHT_ELIGIBILITY_VIEW_ISSUANCE_MARKER ) + return view From eeba73da3cbc04ee471086bea15dc9b216accc82 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 01:22:24 +0900 Subject: [PATCH 494/603] docs(workforce-validation): record weight eligibility repair evidence --- CHANGELOG.md | 2 +- manifest.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8239efbe6..e2abd19d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ All notable changes to Orgmetra will be documented in this file. ### Security -- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry, calibration auxiliary, base-weight, base-weight supersession, calibration benchmark, and calibration adjustment projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 18 other tuple-backed public views. +- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry, calibration auxiliary, base-weight, base-weight supersession, calibration benchmark, calibration adjustment, and weight eligibility projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 17 other tuple-backed public views. - Predictive-validity cases fail closed when selection evidence, Job scope, study criterion, converted worker, or system-recorded visibility does not match; the normalized case relation is tenant-qualified, append-only, TRUNCATE-protected, and forced through row-level security. - Purpose-bound PII authorization now fails closed across active tenant, authenticated actor tenant, resource tenant, resource kind, purpose, operation, operation-specific Keyverse scope, and requested-field subset; malformed/wildcard-like attributes, mutable field/scope collections, reserved UUID sentinels, and cross-tenant confused-deputy contexts are rejected before protected values are returned. Authorization requests and allow/deny evidence now also require and preserve one namespaced opaque target-resource reference, so immutable audit correlation identifies the exact HR record without copying its protected values. Authorization evidence otherwise contains governance metadata and field names only, with stable denial reasons and actionable next steps rather than PII. - LLM output constrained to draft evidence. diff --git a/manifest.json b/manifest.json index aae250680..6c90b7234 100644 --- a/manifest.json +++ b/manifest.json @@ -29,8 +29,8 @@ }, { "path": "CHANGELOG.md", - "sha256": "ff614ee477897fce6bfa7eeb61d932f9a666d336c03d3dd6757010fddf1c026d", - "bytes": 18792, + "sha256": "cd56fa69509d0ba8a4725b6a568c06a198fbe57f780afc73c576fddf71b175dc", + "bytes": 18812, "lines": 80 }, { From 9a3294f5e862c749f1aab2269dd146ae4f56f210 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 01:24:19 +0900 Subject: [PATCH 495/603] test(workforce-validation): expose trimming bounding view bypass --- .../tests/test_trimming_bounding_authority.py | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/services/workforce-validation-api/tests/test_trimming_bounding_authority.py b/services/workforce-validation-api/tests/test_trimming_bounding_authority.py index 2b3734079..a7a4062fa 100644 --- a/services/workforce-validation-api/tests/test_trimming_bounding_authority.py +++ b/services/workforce-validation-api/tests/test_trimming_bounding_authority.py @@ -309,3 +309,46 @@ def test_record_and_view_are_structurally_immutable_and_uuid_views_are_detached( validity_study_id=STUDY, fields=(), ) + + +def test_view_rejects_tuple_base_constructor_forgery() -> None: + """Reject caller-authored instances created through the tuple base class.""" + with pytest.raises(TypeError): + tuple.__new__( + TrimmingBoundingAuthorityView, + (TENANT, STUDY, (("affected_case_count", 17),)), + ) + + +def test_raw_view_allocation_cannot_expose_projection_state() -> None: + """Keep an unissued raw allocation unusable through every public property.""" + forged = object.__new__(TrimmingBoundingAuthorityView) + + with pytest.raises(TrimmingBoundingAuthorityIntegrityError): + _ = forged.tenant_record_id + with pytest.raises(TrimmingBoundingAuthorityIntegrityError): + _ = forged.validity_study_id + with pytest.raises(TrimmingBoundingAuthorityIntegrityError): + _ = forged.fields + + +def test_view_rejects_caller_authored_issuance_marker() -> None: + """Reject a raw allocation even when a caller invents a marker value.""" + forged = object.__new__(TrimmingBoundingAuthorityView) + object.__setattr__(forged, "_tenant_identity", TENANT) + object.__setattr__(forged, "_study_identity", STUDY) + object.__setattr__(forged, "_fields", ()) + object.__setattr__(forged, "_issuance_marker", object()) + + with pytest.raises(TrimmingBoundingAuthorityIntegrityError): + _ = forged.fields + + +def test_issued_view_rejects_mutation_and_deletion() -> None: + """Keep a resolver-issued view immutable after all owner checks complete.""" + view = _resolve(read_port=_ReadPort(_record())) + + with pytest.raises(AttributeError): + view._fields = () + with pytest.raises(AttributeError): + del view._fields From 9d3e08b53adf835cebed7947859c6ddbe8801ae9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 01:25:19 +0900 Subject: [PATCH 496/603] fix(workforce-validation): seal trimming bounding views --- .../trimming_bounding_authority.py | 57 +++++++++++++++---- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py index 898b9e1ab..a22657ef3 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py @@ -35,6 +35,7 @@ _RESOURCE_KIND = "trimming_bounding_authority" _OPERATION = "read" +_TRIMMING_BOUNDING_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "adjustment_receipt_reference", @@ -278,10 +279,10 @@ def superseded_at(self) -> datetime | None: return self[18] -class TrimmingBoundingAuthorityView(tuple): +class TrimmingBoundingAuthorityView: """Field-minimized adjustment evidence issued only after authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -296,20 +297,48 @@ def __new__( "resolve_trimming_bounding_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Reject mutation after resolver-controlled issuance.""" + raise AttributeError("TrimmingBoundingAuthorityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Reject deletion after resolver-controlled issuance.""" + raise AttributeError("TrimmingBoundingAuthorityView is immutable.") + + def _require_issued(self) -> None: + """Require the exact in-process marker written by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise TrimmingBoundingAuthorityIntegrityError( + "trimming/bounding authority view was not issued by the resolver" + ) from exc + if marker is not _TRIMMING_BOUNDING_VIEW_ISSUANCE_MARKER: + raise TrimmingBoundingAuthorityIntegrityError( + "trimming/bounding authority view has an invalid issuance marker" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return immutable adjustment provenance without case identities.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -524,11 +553,15 @@ def resolve_trimming_bounding_authority( ("rule_version", record.rule_version), ("superseded_at", record.superseded_at), ) - return tuple.__new__( - TrimmingBoundingAuthorityView, - ( - _store_operational_uuid("tenant_record_id", tenant_id), - _store_operational_uuid("validity_study_id", study_id), - fields, - ), + view = object.__new__(TrimmingBoundingAuthorityView) + object.__setattr__( + view, "_tenant_identity", _store_operational_uuid("tenant_record_id", tenant_id) + ) + object.__setattr__( + view, "_study_identity", _store_operational_uuid("validity_study_id", study_id) + ) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, "_issuance_marker", _TRIMMING_BOUNDING_VIEW_ISSUANCE_MARKER ) + return view From cc4b6b2ea7c2a4b98c336851bc346492399aae6d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 01:26:21 +0900 Subject: [PATCH 497/603] docs(workforce-validation): record trimming bounding repair evidence --- CHANGELOG.md | 2 +- manifest.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2abd19d6..79adcac80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ All notable changes to Orgmetra will be documented in this file. ### Security -- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry, calibration auxiliary, base-weight, base-weight supersession, calibration benchmark, calibration adjustment, and weight eligibility projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 17 other tuple-backed public views. +- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry, calibration auxiliary, base-weight, base-weight supersession, calibration benchmark, calibration adjustment, weight eligibility, and trimming/bounding projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 16 other tuple-backed public views. - Predictive-validity cases fail closed when selection evidence, Job scope, study criterion, converted worker, or system-recorded visibility does not match; the normalized case relation is tenant-qualified, append-only, TRUNCATE-protected, and forced through row-level security. - Purpose-bound PII authorization now fails closed across active tenant, authenticated actor tenant, resource tenant, resource kind, purpose, operation, operation-specific Keyverse scope, and requested-field subset; malformed/wildcard-like attributes, mutable field/scope collections, reserved UUID sentinels, and cross-tenant confused-deputy contexts are rejected before protected values are returned. Authorization requests and allow/deny evidence now also require and preserve one namespaced opaque target-resource reference, so immutable audit correlation identifies the exact HR record without copying its protected values. Authorization evidence otherwise contains governance metadata and field names only, with stable denial reasons and actionable next steps rather than PII. - LLM output constrained to draft evidence. diff --git a/manifest.json b/manifest.json index 6c90b7234..4af82f8a9 100644 --- a/manifest.json +++ b/manifest.json @@ -29,8 +29,8 @@ }, { "path": "CHANGELOG.md", - "sha256": "cd56fa69509d0ba8a4725b6a568c06a198fbe57f780afc73c576fddf71b175dc", - "bytes": 18812, + "sha256": "df4dd39c0eac6847b7f96bd1b7a958e589628c755cf6c440b80df718ba1c6596", + "bytes": 18831, "lines": 80 }, { From 5bd0404cdabd660585fcafaf61e6393f0530a49f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:02:58 +0900 Subject: [PATCH 498/603] test(workforce-validation): RED calibration adjustment supersession view issuance --- ...ssion_authority_view_issuance_integrity.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_adjustment_supersession_authority_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_authority_view_issuance_integrity.py new file mode 100644 index 000000000..cc6726854 --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_authority_view_issuance_integrity.py @@ -0,0 +1,61 @@ +"""Regression contract for calibration-adjustment supersession view issuance integrity.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.calibration_adjustment_supersession_authority import ( + CalibrationAdjustmentSupersessionAuthorityIntegrityError, + CalibrationAdjustmentSupersessionAuthorityView, +) + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") + + +def test_low_level_tuple_construction_cannot_issue_supersession_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + CalibrationAdjustmentSupersessionAuthorityView, + ( + TENANT.int, + STUDY.int, + (("calibration_receipt_digest", "6" * 64),), + ), + ) + + +def test_unsealed_object_allocation_cannot_expose_supersession_view() -> None: + """Require the resolver seal before raw exact-runtime objects expose state.""" + unsealed = object.__new__(CalibrationAdjustmentSupersessionAuthorityView) + + for attribute_name in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + CalibrationAdjustmentSupersessionAuthorityIntegrityError, + match="was not issued by resolve_calibration_adjustment_supersession_authority", + ): + getattr(unsealed, attribute_name) + + +def test_wrong_issuance_marker_cannot_expose_supersession_view() -> None: + """Reject marker-shaped objects that did not originate from the resolver.""" + forged_view = object.__new__(CalibrationAdjustmentSupersessionAuthorityView) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises( + CalibrationAdjustmentSupersessionAuthorityIntegrityError, + match="was not issued by resolve_calibration_adjustment_supersession_authority", + ): + _ = forged_view.fields + + +def test_raw_supersession_view_rejects_mutation_and_deletion() -> None: + """Keep projection state immutable after raw exact-runtime allocation.""" + raw_view = object.__new__(CalibrationAdjustmentSupersessionAuthorityView) + + with pytest.raises(AttributeError, match="immutable"): + raw_view._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw_view._fields From e50fb9614282686fc2a79c3560a0564b7b26338a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:04:25 +0900 Subject: [PATCH 499/603] fix(workforce-validation): seal calibration adjustment supersession view issuance --- ...ation_adjustment_supersession_authority.py | 67 +++++++++++++++---- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_supersession_authority.py index 092af5606..1902b36b3 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_supersession_authority.py @@ -37,6 +37,7 @@ _RESOURCE_KIND = "calibration_adjustment_supersession_authority" _OPERATION = "read" +_CALIBRATION_ADJUSTMENT_SUPERSESSION_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "calibration_receipt_reference", @@ -231,10 +232,10 @@ def successor_fields(self) -> tuple[tuple[str, object], ...] | None: return self[5] -class CalibrationAdjustmentSupersessionAuthorityView(tuple): - """Minimized current-receipt authority issued only after authorization.""" +class CalibrationAdjustmentSupersessionAuthorityView: + """Sealed current-receipt authority issued only after authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -249,20 +250,50 @@ def __new__( "resolve_calibration_adjustment_supersession_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError("CalibrationAdjustmentSupersessionAuthorityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError("CalibrationAdjustmentSupersessionAuthorityView is immutable.") + + def _require_issued(self) -> None: + """Reject exact-runtime allocations not sealed by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise CalibrationAdjustmentSupersessionAuthorityIntegrityError( + "calibration-adjustment supersession view was not issued by " + "resolve_calibration_adjustment_supersession_authority" + ) from exc + if marker is not _CALIBRATION_ADJUSTMENT_SUPERSESSION_VIEW_ISSUANCE_MARKER: + raise CalibrationAdjustmentSupersessionAuthorityIntegrityError( + "calibration-adjustment supersession view was not issued by " + "resolve_calibration_adjustment_supersession_authority" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return current receipt authority without successor disclosure.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -469,11 +500,21 @@ def resolve_calibration_adjustment_supersession_authority( ("released_at", record.released_at), ("superseded_at", record.superseded_at), ) - return tuple.__new__( - CalibrationAdjustmentSupersessionAuthorityView, - ( - _store_operational_uuid("tenant_record_id", tenant_id), - _store_operational_uuid("validity_study_id", study_id), - fields, - ), + view = object.__new__(CalibrationAdjustmentSupersessionAuthorityView) + object.__setattr__( + view, + "_tenant_identity", + _store_operational_uuid("tenant_record_id", tenant_id), + ) + object.__setattr__( + view, + "_study_identity", + _store_operational_uuid("validity_study_id", study_id), + ) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, + "_issuance_marker", + _CALIBRATION_ADJUSTMENT_SUPERSESSION_VIEW_ISSUANCE_MARKER, ) + return view From 613d7eb2034e03cee8a6116dd5317fd47f24f47b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:06:59 +0900 Subject: [PATCH 500/603] test(workforce-validation): RED final weight supersession view issuance --- ...ssion_authority_view_issuance_integrity.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_supersession_authority_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_final_weight_supersession_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_final_weight_supersession_authority_view_issuance_integrity.py new file mode 100644 index 000000000..d2d769a9c --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_supersession_authority_view_issuance_integrity.py @@ -0,0 +1,61 @@ +"""Regression contract for final-weight supersession view issuance integrity.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.final_weight_supersession_authority import ( + FinalWeightSupersessionAuthorityIntegrityError, + FinalWeightSupersessionAuthorityView, +) + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") + + +def test_low_level_tuple_construction_cannot_issue_supersession_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + FinalWeightSupersessionAuthorityView, + ( + TENANT.int, + STUDY.int, + (("analysis_weight_receipt_digest", "6" * 64),), + ), + ) + + +def test_unsealed_object_allocation_cannot_expose_supersession_view() -> None: + """Require the resolver seal before raw exact-runtime objects expose state.""" + unsealed = object.__new__(FinalWeightSupersessionAuthorityView) + + for attribute_name in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + FinalWeightSupersessionAuthorityIntegrityError, + match="was not issued by resolve_final_weight_supersession_authority", + ): + getattr(unsealed, attribute_name) + + +def test_wrong_issuance_marker_cannot_expose_supersession_view() -> None: + """Reject marker-shaped objects that did not originate from the resolver.""" + forged_view = object.__new__(FinalWeightSupersessionAuthorityView) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises( + FinalWeightSupersessionAuthorityIntegrityError, + match="was not issued by resolve_final_weight_supersession_authority", + ): + _ = forged_view.fields + + +def test_raw_supersession_view_rejects_mutation_and_deletion() -> None: + """Keep projection state immutable after raw exact-runtime allocation.""" + raw_view = object.__new__(FinalWeightSupersessionAuthorityView) + + with pytest.raises(AttributeError, match="immutable"): + raw_view._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw_view._fields From 6bc1048837c69d4c3e29ad77705daf8f13bec75a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:07:46 +0900 Subject: [PATCH 501/603] fix(workforce-validation): seal final weight supersession view issuance --- .../final_weight_supersession_authority.py | 67 +++++++++++++++---- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py index e39545870..c09ac3a4b 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py @@ -36,6 +36,7 @@ _RESOURCE_KIND = "final_weight_supersession_authority" _OPERATION = "read" +_FINAL_WEIGHT_SUPERSESSION_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "analysis_weight_receipt_reference", @@ -249,10 +250,10 @@ def successor_fields(self) -> tuple[tuple[str, object], ...] | None: return self[5] -class FinalWeightSupersessionAuthorityView(tuple): - """Minimized current-receipt authority issued only after purpose authorization.""" +class FinalWeightSupersessionAuthorityView: + """Sealed current-receipt authority issued only after purpose authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -267,20 +268,50 @@ def __new__( "resolve_final_weight_supersession_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError("FinalWeightSupersessionAuthorityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError("FinalWeightSupersessionAuthorityView is immutable.") + + def _require_issued(self) -> None: + """Reject exact-runtime allocations not sealed by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise FinalWeightSupersessionAuthorityIntegrityError( + "final-weight supersession view was not issued by " + "resolve_final_weight_supersession_authority" + ) from exc + if marker is not _FINAL_WEIGHT_SUPERSESSION_VIEW_ISSUANCE_MARKER: + raise FinalWeightSupersessionAuthorityIntegrityError( + "final-weight supersession view was not issued by " + "resolve_final_weight_supersession_authority" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return released current-receipt provenance without successor disclosure.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -480,14 +511,24 @@ def resolve_final_weight_supersession_authority( values = dict(record.fields) values["released_at"] = record.released_at fields = tuple((field_name, values[field_name]) for field_name in sorted(_VIEW_FIELDS)) - return tuple.__new__( - FinalWeightSupersessionAuthorityView, - ( - _store_operational_uuid("tenant_record_id", record.tenant_record_id), - _store_operational_uuid("validity_study_id", record.validity_study_id), - fields, - ), + view = object.__new__(FinalWeightSupersessionAuthorityView) + object.__setattr__( + view, + "_tenant_identity", + _store_operational_uuid("tenant_record_id", record.tenant_record_id), + ) + object.__setattr__( + view, + "_study_identity", + _store_operational_uuid("validity_study_id", record.validity_study_id), + ) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, + "_issuance_marker", + _FINAL_WEIGHT_SUPERSESSION_VIEW_ISSUANCE_MARKER, ) + return view __all__ = [ From 6b3ceda2821428186fafa52e8013ec188b9d26aa Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:08:09 +0900 Subject: [PATCH 502/603] test(workforce-validation): RED weight eligibility supersession view issuance --- ...ssion_authority_view_issuance_integrity.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority_view_issuance_integrity.py new file mode 100644 index 000000000..082401c4a --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority_view_issuance_integrity.py @@ -0,0 +1,61 @@ +"""Regression contract for weight-eligibility supersession view issuance integrity.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.weight_eligibility_supersession_authority import ( + WeightEligibilitySupersessionAuthorityIntegrityError, + WeightEligibilitySupersessionAuthorityView, +) + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") + + +def test_low_level_tuple_construction_cannot_issue_supersession_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + WeightEligibilitySupersessionAuthorityView, + ( + TENANT.int, + STUDY.int, + (("eligibility_receipt_digest", "6" * 64),), + ), + ) + + +def test_unsealed_object_allocation_cannot_expose_supersession_view() -> None: + """Require the resolver seal before raw exact-runtime objects expose state.""" + unsealed = object.__new__(WeightEligibilitySupersessionAuthorityView) + + for attribute_name in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + WeightEligibilitySupersessionAuthorityIntegrityError, + match="was not issued by resolve_weight_eligibility_supersession_authority", + ): + getattr(unsealed, attribute_name) + + +def test_wrong_issuance_marker_cannot_expose_supersession_view() -> None: + """Reject marker-shaped objects that did not originate from the resolver.""" + forged_view = object.__new__(WeightEligibilitySupersessionAuthorityView) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises( + WeightEligibilitySupersessionAuthorityIntegrityError, + match="was not issued by resolve_weight_eligibility_supersession_authority", + ): + _ = forged_view.fields + + +def test_raw_supersession_view_rejects_mutation_and_deletion() -> None: + """Keep projection state immutable after raw exact-runtime allocation.""" + raw_view = object.__new__(WeightEligibilitySupersessionAuthorityView) + + with pytest.raises(AttributeError, match="immutable"): + raw_view._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw_view._fields From 04387a61604fd3f945ea2c5b2166d3d505b7b15a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:09:00 +0900 Subject: [PATCH 503/603] fix(workforce-validation): seal weight eligibility supersession view issuance --- ...ight_eligibility_supersession_authority.py | 67 +++++++++++++++---- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_supersession_authority.py index 54218cf82..9723240d8 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_supersession_authority.py @@ -37,6 +37,7 @@ _RESOURCE_KIND = "weight_eligibility_supersession_authority" _OPERATION = "read" +_WEIGHT_ELIGIBILITY_SUPERSESSION_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "eligibility_receipt_reference", @@ -243,10 +244,10 @@ def successor_fields(self) -> tuple[tuple[str, object], ...] | None: return self[5] -class WeightEligibilitySupersessionAuthorityView(tuple): - """Minimized current-receipt authority issued only after authorization.""" +class WeightEligibilitySupersessionAuthorityView: + """Sealed current-receipt authority issued only after authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -261,20 +262,50 @@ def __new__( "resolve_weight_eligibility_supersession_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError("WeightEligibilitySupersessionAuthorityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError("WeightEligibilitySupersessionAuthorityView is immutable.") + + def _require_issued(self) -> None: + """Reject exact-runtime allocations not sealed by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise WeightEligibilitySupersessionAuthorityIntegrityError( + "weight-eligibility supersession view was not issued by " + "resolve_weight_eligibility_supersession_authority" + ) from exc + if marker is not _WEIGHT_ELIGIBILITY_SUPERSESSION_VIEW_ISSUANCE_MARKER: + raise WeightEligibilitySupersessionAuthorityIntegrityError( + "weight-eligibility supersession view was not issued by " + "resolve_weight_eligibility_supersession_authority" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return current eligibility authority without successor disclosure.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -467,14 +498,24 @@ def resolve_weight_eligibility_supersession_authority( values = dict(record.fields) values["released_at"] = record.released_at fields = tuple((field_name, values[field_name]) for field_name in sorted(_VIEW_FIELDS)) - return tuple.__new__( - WeightEligibilitySupersessionAuthorityView, - ( - _store_operational_uuid("tenant_record_id", record.tenant_record_id), - _store_operational_uuid("validity_study_id", record.validity_study_id), - fields, - ), + view = object.__new__(WeightEligibilitySupersessionAuthorityView) + object.__setattr__( + view, + "_tenant_identity", + _store_operational_uuid("tenant_record_id", record.tenant_record_id), + ) + object.__setattr__( + view, + "_study_identity", + _store_operational_uuid("validity_study_id", record.validity_study_id), + ) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, + "_issuance_marker", + _WEIGHT_ELIGIBILITY_SUPERSESSION_VIEW_ISSUANCE_MARKER, ) + return view __all__ = [ From f7fbff7bbeac22d6ff3e7d65997645b5f3de265f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:09:16 +0900 Subject: [PATCH 504/603] test(workforce-validation): RED trimming bounding supersession view issuance --- ...ssion_authority_view_issuance_integrity.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_trimming_bounding_supersession_authority_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_trimming_bounding_supersession_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_trimming_bounding_supersession_authority_view_issuance_integrity.py new file mode 100644 index 000000000..6541776ab --- /dev/null +++ b/services/workforce-validation-api/tests/test_trimming_bounding_supersession_authority_view_issuance_integrity.py @@ -0,0 +1,61 @@ +"""Regression contract for trimming/bounding supersession view issuance integrity.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.trimming_bounding_supersession_authority import ( + TrimmingBoundingSupersessionAuthorityIntegrityError, + TrimmingBoundingSupersessionAuthorityView, +) + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") + + +def test_low_level_tuple_construction_cannot_issue_supersession_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + TrimmingBoundingSupersessionAuthorityView, + ( + TENANT.int, + STUDY.int, + (("adjustment_receipt_digest", "6" * 64),), + ), + ) + + +def test_unsealed_object_allocation_cannot_expose_supersession_view() -> None: + """Require the resolver seal before raw exact-runtime objects expose state.""" + unsealed = object.__new__(TrimmingBoundingSupersessionAuthorityView) + + for attribute_name in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + TrimmingBoundingSupersessionAuthorityIntegrityError, + match="was not issued by resolve_trimming_bounding_supersession_authority", + ): + getattr(unsealed, attribute_name) + + +def test_wrong_issuance_marker_cannot_expose_supersession_view() -> None: + """Reject marker-shaped objects that did not originate from the resolver.""" + forged_view = object.__new__(TrimmingBoundingSupersessionAuthorityView) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises( + TrimmingBoundingSupersessionAuthorityIntegrityError, + match="was not issued by resolve_trimming_bounding_supersession_authority", + ): + _ = forged_view.fields + + +def test_raw_supersession_view_rejects_mutation_and_deletion() -> None: + """Keep projection state immutable after raw exact-runtime allocation.""" + raw_view = object.__new__(TrimmingBoundingSupersessionAuthorityView) + + with pytest.raises(AttributeError, match="immutable"): + raw_view._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw_view._fields From 3c8cd1b4d67a77ff95fa4ae1d11fedda9df775a1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:09:54 +0900 Subject: [PATCH 505/603] fix(workforce-validation): seal trimming bounding supersession view issuance --- ...rimming_bounding_supersession_authority.py | 67 +++++++++++++++---- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_supersession_authority.py index 8f9f5e02b..178265fb5 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_supersession_authority.py @@ -36,6 +36,7 @@ _RESOURCE_KIND = "trimming_bounding_supersession_authority" _OPERATION = "read" +_TRIMMING_BOUNDING_SUPERSESSION_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "adjustment_receipt_reference", @@ -230,10 +231,10 @@ def successor_fields(self) -> tuple[tuple[str, object], ...] | None: return self[5] -class TrimmingBoundingSupersessionAuthorityView(tuple): - """Minimized current-receipt authority issued only after authorization.""" +class TrimmingBoundingSupersessionAuthorityView: + """Sealed current-receipt authority issued only after authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -248,20 +249,50 @@ def __new__( "resolve_trimming_bounding_supersession_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError("TrimmingBoundingSupersessionAuthorityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError("TrimmingBoundingSupersessionAuthorityView is immutable.") + + def _require_issued(self) -> None: + """Reject exact-runtime allocations not sealed by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise TrimmingBoundingSupersessionAuthorityIntegrityError( + "trimming/bounding supersession view was not issued by " + "resolve_trimming_bounding_supersession_authority" + ) from exc + if marker is not _TRIMMING_BOUNDING_SUPERSESSION_VIEW_ISSUANCE_MARKER: + raise TrimmingBoundingSupersessionAuthorityIntegrityError( + "trimming/bounding supersession view was not issued by " + "resolve_trimming_bounding_supersession_authority" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return current receipt authority without successor disclosure.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -465,11 +496,21 @@ def resolve_trimming_bounding_supersession_authority( "released_at", ) ) - return tuple.__new__( - TrimmingBoundingSupersessionAuthorityView, - ( - _store_operational_uuid("tenant_record_id", tenant_id), - _store_operational_uuid("validity_study_id", study_id), - fields, - ), + view = object.__new__(TrimmingBoundingSupersessionAuthorityView) + object.__setattr__( + view, + "_tenant_identity", + _store_operational_uuid("tenant_record_id", tenant_id), + ) + object.__setattr__( + view, + "_study_identity", + _store_operational_uuid("validity_study_id", study_id), + ) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, + "_issuance_marker", + _TRIMMING_BOUNDING_SUPERSESSION_VIEW_ISSUANCE_MARKER, ) + return view From f8b0512c0186cd7ea89a94ea7adc6e221acb81f0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:12:40 +0900 Subject: [PATCH 506/603] docs(workforce-validation): seal supersession view repair evidence --- CHANGELOG.md | 2 +- manifest.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79adcac80..48b92fbc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ All notable changes to Orgmetra will be documented in this file. ### Security -- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry, calibration auxiliary, base-weight, base-weight supersession, calibration benchmark, calibration adjustment, weight eligibility, and trimming/bounding projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 16 other tuple-backed public views. +- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry, calibration auxiliary, base-weight, base-weight supersession, calibration benchmark, calibration adjustment, calibration-adjustment supersession, final-weight supersession, weight eligibility, weight-eligibility supersession, trimming/bounding, and trimming/bounding supersession projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 12 other tuple-backed public views. - Predictive-validity cases fail closed when selection evidence, Job scope, study criterion, converted worker, or system-recorded visibility does not match; the normalized case relation is tenant-qualified, append-only, TRUNCATE-protected, and forced through row-level security. - Purpose-bound PII authorization now fails closed across active tenant, authenticated actor tenant, resource tenant, resource kind, purpose, operation, operation-specific Keyverse scope, and requested-field subset; malformed/wildcard-like attributes, mutable field/scope collections, reserved UUID sentinels, and cross-tenant confused-deputy contexts are rejected before protected values are returned. Authorization requests and allow/deny evidence now also require and preserve one namespaced opaque target-resource reference, so immutable audit correlation identifies the exact HR record without copying its protected values. Authorization evidence otherwise contains governance metadata and field names only, with stable denial reasons and actionable next steps rather than PII. - LLM output constrained to draft evidence. diff --git a/manifest.json b/manifest.json index 4af82f8a9..7d0165c8d 100644 --- a/manifest.json +++ b/manifest.json @@ -29,8 +29,8 @@ }, { "path": "CHANGELOG.md", - "sha256": "df4dd39c0eac6847b7f96bd1b7a958e589628c755cf6c440b80df718ba1c6596", - "bytes": 18831, + "sha256": "fdba0e7ed2556daae2d59e8638eda387ec8c6eb2213dc910732f5d69c18c28a2", + "bytes": 18960, "lines": 80 }, { From 81c2238654c9dc52863f3a05b4a0b5b4d17152b2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:15:44 +0900 Subject: [PATCH 507/603] test(workforce-validation): RED weight variance supersession view issuance --- ...ssion_authority_view_issuance_integrity.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_variance_supersession_authority_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_weight_variance_supersession_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_weight_variance_supersession_authority_view_issuance_integrity.py new file mode 100644 index 000000000..8891b0da4 --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_variance_supersession_authority_view_issuance_integrity.py @@ -0,0 +1,61 @@ +"""Regression contract for weight/variance supersession view issuance integrity.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.weight_variance_supersession_authority import ( + WeightVarianceSupersessionAuthorityIntegrityError, + WeightVarianceSupersessionAuthorityView, +) + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") + + +def test_low_level_tuple_construction_cannot_issue_supersession_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + WeightVarianceSupersessionAuthorityView, + ( + TENANT.int, + STUDY.int, + (("authority_reference", "variance_compatibility_authority:test"),), + ), + ) + + +def test_unsealed_object_allocation_cannot_expose_supersession_view() -> None: + """Require the resolver seal before raw exact-runtime objects expose state.""" + unsealed = object.__new__(WeightVarianceSupersessionAuthorityView) + + for attribute_name in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + WeightVarianceSupersessionAuthorityIntegrityError, + match="was not issued by resolve_weight_variance_supersession_authority", + ): + getattr(unsealed, attribute_name) + + +def test_wrong_issuance_marker_cannot_expose_supersession_view() -> None: + """Reject marker-shaped objects that did not originate from the resolver.""" + forged_view = object.__new__(WeightVarianceSupersessionAuthorityView) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises( + WeightVarianceSupersessionAuthorityIntegrityError, + match="was not issued by resolve_weight_variance_supersession_authority", + ): + _ = forged_view.fields + + +def test_raw_supersession_view_rejects_mutation_and_deletion() -> None: + """Keep projection state immutable after raw exact-runtime allocation.""" + raw_view = object.__new__(WeightVarianceSupersessionAuthorityView) + + with pytest.raises(AttributeError, match="immutable"): + raw_view._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw_view._fields From 3d659cca10b3262e29019fc337b646b9e98e40ae Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:16:20 +0900 Subject: [PATCH 508/603] fix(workforce-validation): seal weight variance supersession view issuance --- .../weight_variance_supersession_authority.py | 67 +++++++++++++++---- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_variance_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_variance_supersession_authority.py index 011a38d7e..ba616068e 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_variance_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_variance_supersession_authority.py @@ -37,6 +37,7 @@ _RESOURCE_KIND = "weight_variance_supersession_authority" _OPERATION = "read" +_WEIGHT_VARIANCE_SUPERSESSION_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "authority_reference", @@ -214,10 +215,10 @@ def successor_fields(self) -> tuple[tuple[str, object], ...] | None: return self[5] -class WeightVarianceSupersessionAuthorityView(tuple): - """Minimized current compatibility authority issued after authorization.""" +class WeightVarianceSupersessionAuthorityView: + """Sealed current compatibility authority issued only after authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -232,20 +233,50 @@ def __new__( "resolve_weight_variance_supersession_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError("WeightVarianceSupersessionAuthorityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError("WeightVarianceSupersessionAuthorityView is immutable.") + + def _require_issued(self) -> None: + """Reject exact-runtime allocations not sealed by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise WeightVarianceSupersessionAuthorityIntegrityError( + "weight/variance supersession view was not issued by " + "resolve_weight_variance_supersession_authority" + ) from exc + if marker is not _WEIGHT_VARIANCE_SUPERSESSION_VIEW_ISSUANCE_MARKER: + raise WeightVarianceSupersessionAuthorityIntegrityError( + "weight/variance supersession view was not issued by " + "resolve_weight_variance_supersession_authority" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return current authority without successor disclosure.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -424,14 +455,24 @@ def resolve_weight_variance_supersession_authority( ("released_at", record.released_at), ("superseded_at", record.superseded_at), ) - return tuple.__new__( - WeightVarianceSupersessionAuthorityView, - ( - _store_operational_uuid("tenant_record_id", record.tenant_record_id), - _store_operational_uuid("validity_study_id", record.validity_study_id), - fields, - ), + view = object.__new__(WeightVarianceSupersessionAuthorityView) + object.__setattr__( + view, + "_tenant_identity", + _store_operational_uuid("tenant_record_id", record.tenant_record_id), + ) + object.__setattr__( + view, + "_study_identity", + _store_operational_uuid("validity_study_id", record.validity_study_id), + ) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, + "_issuance_marker", + _WEIGHT_VARIANCE_SUPERSESSION_VIEW_ISSUANCE_MARKER, ) + return view __all__ = [ From d1c333dc804ab7411190ab534949419be09c2fac Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:17:14 +0900 Subject: [PATCH 509/603] test(workforce-validation): RED calibration support view issuance --- ...pport_authority_view_issuance_integrity.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_support_authority_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_calibration_support_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_calibration_support_authority_view_issuance_integrity.py new file mode 100644 index 000000000..6b75bf2e6 --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_support_authority_view_issuance_integrity.py @@ -0,0 +1,61 @@ +"""Regression contract for calibration-support view issuance integrity.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.calibration_support_authority import ( + CalibrationSupportAuthorityIntegrityError, + CalibrationSupportAuthorityView, +) + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f2") + + +def test_low_level_tuple_construction_cannot_issue_support_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + CalibrationSupportAuthorityView, + ( + TENANT.int, + STUDY.int, + (("support_authority_digest", "0" * 64),), + ), + ) + + +def test_unsealed_object_allocation_cannot_expose_support_view() -> None: + """Require the resolver seal before raw exact-runtime objects expose state.""" + unsealed = object.__new__(CalibrationSupportAuthorityView) + + for attribute_name in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + CalibrationSupportAuthorityIntegrityError, + match="was not issued by resolve_calibration_support_authority", + ): + getattr(unsealed, attribute_name) + + +def test_wrong_issuance_marker_cannot_expose_support_view() -> None: + """Reject marker-shaped objects that did not originate from the resolver.""" + forged_view = object.__new__(CalibrationSupportAuthorityView) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises( + CalibrationSupportAuthorityIntegrityError, + match="was not issued by resolve_calibration_support_authority", + ): + _ = forged_view.fields + + +def test_raw_support_view_rejects_mutation_and_deletion() -> None: + """Keep projection state immutable after raw exact-runtime allocation.""" + raw_view = object.__new__(CalibrationSupportAuthorityView) + + with pytest.raises(AttributeError, match="immutable"): + raw_view._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw_view._fields From b8d3b0fdbe63206e7ab9c3a2ba7f2ca81ae73a1a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:18:17 +0900 Subject: [PATCH 510/603] fix(workforce-validation): seal calibration support view issuance --- .../calibration_support_authority.py | 55 ++++++++++++++++--- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py index 9c81de86e..a3e6d9cf0 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py @@ -37,6 +37,7 @@ _RESOURCE_KIND = "calibration_support_authority" _OPERATION = "read" +_CALIBRATION_SUPPORT_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "support_authority_reference", @@ -419,10 +420,10 @@ def validity_study_id(self) -> UUID: released_at = _tuple_property(40, "Return when this support proof became released application evidence.") -class CalibrationSupportAuthorityView(tuple): - """Field-minimized support evidence issued only after purpose-bound authorization.""" +class CalibrationSupportAuthorityView: + """Sealed support evidence issued only after purpose-bound authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -436,20 +437,50 @@ def __new__( "CalibrationSupportAuthorityView is issued only by resolve_calibration_support_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError("CalibrationSupportAuthorityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError("CalibrationSupportAuthorityView is immutable.") + + def _require_issued(self) -> None: + """Reject exact-runtime allocations not sealed by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise CalibrationSupportAuthorityIntegrityError( + "calibration support view was not issued by " + "resolve_calibration_support_authority" + ) from exc + if marker is not _CALIBRATION_SUPPORT_VIEW_ISSUANCE_MARKER: + raise CalibrationSupportAuthorityIntegrityError( + "calibration support view was not issued by " + "resolve_calibration_support_authority" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return immutable corroborating support evidence without source values.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -812,7 +843,13 @@ def resolve_calibration_support_authority( values = {field_name: getattr(record, field_name) for field_name in _READ_FIELDS} fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) - return tuple.__new__( - CalibrationSupportAuthorityView, - (tenant_identity, study_identity, fields), + view = object.__new__(CalibrationSupportAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, + "_issuance_marker", + _CALIBRATION_SUPPORT_VIEW_ISSUANCE_MARKER, ) + return view From 01f3aaa678cbe700078953ddc7c5460dd78480b3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:19:15 +0900 Subject: [PATCH 511/603] docs(workforce-validation): seal remaining view repair evidence --- CHANGELOG.md | 2 +- manifest.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48b92fbc4..f98def358 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ All notable changes to Orgmetra will be documented in this file. ### Security -- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry, calibration auxiliary, base-weight, base-weight supersession, calibration benchmark, calibration adjustment, calibration-adjustment supersession, final-weight supersession, weight eligibility, weight-eligibility supersession, trimming/bounding, and trimming/bounding supersession projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 12 other tuple-backed public views. +- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry, calibration auxiliary, calibration support, base-weight, base-weight supersession, calibration benchmark, calibration adjustment, calibration-adjustment supersession, final-weight supersession, weight eligibility, weight-eligibility supersession, weight/variance supersession, trimming/bounding, and trimming/bounding supersession projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 10 other tuple-backed public views. - Predictive-validity cases fail closed when selection evidence, Job scope, study criterion, converted worker, or system-recorded visibility does not match; the normalized case relation is tenant-qualified, append-only, TRUNCATE-protected, and forced through row-level security. - Purpose-bound PII authorization now fails closed across active tenant, authenticated actor tenant, resource tenant, resource kind, purpose, operation, operation-specific Keyverse scope, and requested-field subset; malformed/wildcard-like attributes, mutable field/scope collections, reserved UUID sentinels, and cross-tenant confused-deputy contexts are rejected before protected values are returned. Authorization requests and allow/deny evidence now also require and preserve one namespaced opaque target-resource reference, so immutable audit correlation identifies the exact HR record without copying its protected values. Authorization evidence otherwise contains governance metadata and field names only, with stable denial reasons and actionable next steps rather than PII. - LLM output constrained to draft evidence. diff --git a/manifest.json b/manifest.json index 7d0165c8d..c9d8ad51a 100644 --- a/manifest.json +++ b/manifest.json @@ -29,8 +29,8 @@ }, { "path": "CHANGELOG.md", - "sha256": "fdba0e7ed2556daae2d59e8638eda387ec8c6eb2213dc910732f5d69c18c28a2", - "bytes": 18960, + "sha256": "f9679d85199d1e8313887acd986a9865eea87d057546fe4c6f4ddb1d9a579a76", + "bytes": 19011, "lines": 80 }, { From 01cca629139cf8dd09a5c85bc0c0b924bad65d34 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:20:52 +0900 Subject: [PATCH 512/603] test(workforce-validation): RED final analysis weight view issuance --- ...eight_authority_view_issuance_integrity.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_analysis_weight_authority_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_final_analysis_weight_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_final_analysis_weight_authority_view_issuance_integrity.py new file mode 100644 index 000000000..7afd3602c --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_analysis_weight_authority_view_issuance_integrity.py @@ -0,0 +1,61 @@ +"""Regression contract for final analysis-weight view issuance integrity.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.final_weight_authority import ( + FinalAnalysisWeightAuthorityIntegrityError, + FinalAnalysisWeightAuthorityView, +) + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") + + +def test_low_level_tuple_construction_cannot_issue_final_weight_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + FinalAnalysisWeightAuthorityView, + ( + TENANT.int, + STUDY.int, + (("analysis_weight_receipt_digest", "6" * 64),), + ), + ) + + +def test_unsealed_object_allocation_cannot_expose_final_weight_view() -> None: + """Require the resolver seal before raw exact-runtime objects expose state.""" + unsealed = object.__new__(FinalAnalysisWeightAuthorityView) + + for attribute_name in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + FinalAnalysisWeightAuthorityIntegrityError, + match="was not issued by resolve_final_analysis_weight_authority", + ): + getattr(unsealed, attribute_name) + + +def test_wrong_issuance_marker_cannot_expose_final_weight_view() -> None: + """Reject marker-shaped objects that did not originate from the resolver.""" + forged_view = object.__new__(FinalAnalysisWeightAuthorityView) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises( + FinalAnalysisWeightAuthorityIntegrityError, + match="was not issued by resolve_final_analysis_weight_authority", + ): + _ = forged_view.fields + + +def test_raw_final_weight_view_rejects_mutation_and_deletion() -> None: + """Keep projection state immutable after raw exact-runtime allocation.""" + raw_view = object.__new__(FinalAnalysisWeightAuthorityView) + + with pytest.raises(AttributeError, match="immutable"): + raw_view._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw_view._fields From acb265463dee145592b7d9a45c5cad87bee4fa96 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:22:35 +0900 Subject: [PATCH 513/603] fix(workforce-validation): seal final analysis weight view issuance --- .../final_weight_authority.py | 67 +++++++++++++++---- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py index 63b37a29f..a978e99f2 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py @@ -36,6 +36,7 @@ _RESOURCE_KIND = "final_analysis_weight_authority" _OPERATION = "read" +_FINAL_ANALYSIS_WEIGHT_VIEW_ISSUANCE_MARKER = object() _WEIGHT_SCOPE_CODES = frozenset({"cross_sectional", "longitudinal"}) _SPECIALIZED_EVIDENCE_KIND_BY_ADJUSTMENT_CODE = { "nonresponse_adjustment": "nonresponse_adjustment_receipt", @@ -497,10 +498,10 @@ def superseded_at(self) -> datetime | None: return self[5] -class FinalAnalysisWeightAuthorityView(tuple): - """Field-minimized final-weight evidence issued only after authorization.""" +class FinalAnalysisWeightAuthorityView: + """Sealed field-minimized final-weight evidence issued only after authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -515,20 +516,50 @@ def __new__( "resolve_final_analysis_weight_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError("FinalAnalysisWeightAuthorityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError("FinalAnalysisWeightAuthorityView is immutable.") + + def _require_issued(self) -> None: + """Reject exact-runtime allocations not sealed by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise FinalAnalysisWeightAuthorityIntegrityError( + "final analysis-weight view was not issued by " + "resolve_final_analysis_weight_authority" + ) from exc + if marker is not _FINAL_ANALYSIS_WEIGHT_VIEW_ISSUANCE_MARKER: + raise FinalAnalysisWeightAuthorityIntegrityError( + "final analysis-weight view was not issued by " + "resolve_final_analysis_weight_authority" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return immutable final-weight provenance.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -827,11 +858,21 @@ def resolve_final_analysis_weight_authority( values["released_at"] = record.released_at values["superseded_at"] = record.superseded_at fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) - return tuple.__new__( - FinalAnalysisWeightAuthorityView, - ( - _store_operational_uuid("tenant_record_id", record.tenant_record_id), - _store_operational_uuid("validity_study_id", record.validity_study_id), - fields, - ), + view = object.__new__(FinalAnalysisWeightAuthorityView) + object.__setattr__( + view, + "_tenant_identity", + _store_operational_uuid("tenant_record_id", record.tenant_record_id), + ) + object.__setattr__( + view, + "_study_identity", + _store_operational_uuid("validity_study_id", record.validity_study_id), + ) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, + "_issuance_marker", + _FINAL_ANALYSIS_WEIGHT_VIEW_ISSUANCE_MARKER, ) + return view From 74a9f6323f1717a25ef1ad4cfd31bfc6d15472e5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:23:26 +0900 Subject: [PATCH 514/603] docs(workforce-validation): seal final analysis weight evidence --- CHANGELOG.md | 2 +- manifest.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f98def358..e19768044 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ All notable changes to Orgmetra will be documented in this file. ### Security -- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry, calibration auxiliary, calibration support, base-weight, base-weight supersession, calibration benchmark, calibration adjustment, calibration-adjustment supersession, final-weight supersession, weight eligibility, weight-eligibility supersession, weight/variance supersession, trimming/bounding, and trimming/bounding supersession projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 10 other tuple-backed public views. +- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry, calibration auxiliary, calibration support, base-weight, base-weight supersession, calibration benchmark, calibration adjustment, calibration-adjustment supersession, final analysis-weight, final-weight supersession, weight eligibility, weight-eligibility supersession, weight/variance supersession, trimming/bounding, and trimming/bounding supersession projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 9 other tuple-backed public views. - Predictive-validity cases fail closed when selection evidence, Job scope, study criterion, converted worker, or system-recorded visibility does not match; the normalized case relation is tenant-qualified, append-only, TRUNCATE-protected, and forced through row-level security. - Purpose-bound PII authorization now fails closed across active tenant, authenticated actor tenant, resource tenant, resource kind, purpose, operation, operation-specific Keyverse scope, and requested-field subset; malformed/wildcard-like attributes, mutable field/scope collections, reserved UUID sentinels, and cross-tenant confused-deputy contexts are rejected before protected values are returned. Authorization requests and allow/deny evidence now also require and preserve one namespaced opaque target-resource reference, so immutable audit correlation identifies the exact HR record without copying its protected values. Authorization evidence otherwise contains governance metadata and field names only, with stable denial reasons and actionable next steps rather than PII. - LLM output constrained to draft evidence. diff --git a/manifest.json b/manifest.json index c9d8ad51a..cc4cc0621 100644 --- a/manifest.json +++ b/manifest.json @@ -29,8 +29,8 @@ }, { "path": "CHANGELOG.md", - "sha256": "f9679d85199d1e8313887acd986a9865eea87d057546fe4c6f4ddb1d9a579a76", - "bytes": 19011, + "sha256": "46c0bc8e802d7b1462169bbb5b8af069e526c61098ace786025921c47d77d92a", + "bytes": 19033, "lines": 80 }, { From 6c000450d32da43727c102fad66dadcb082e9adc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:24:26 +0900 Subject: [PATCH 515/603] test(workforce-validation): RED final weight component binding view issuance --- ...nding_authority_view_issuance_integrity.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_component_binding_authority_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_final_weight_component_binding_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_final_weight_component_binding_authority_view_issuance_integrity.py new file mode 100644 index 000000000..a5761dbef --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_component_binding_authority_view_issuance_integrity.py @@ -0,0 +1,61 @@ +"""Regression contract for final-weight component-binding view issuance integrity.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.final_weight_component_binding_authority import ( + FinalWeightComponentBindingAuthorityIntegrityError, + FinalWeightComponentBindingAuthorityView, +) + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") + + +def test_low_level_tuple_construction_cannot_issue_component_binding_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + FinalWeightComponentBindingAuthorityView, + ( + TENANT.int, + STUDY.int, + (("binding_digest", "6" * 64),), + ), + ) + + +def test_unsealed_object_allocation_cannot_expose_component_binding_view() -> None: + """Require the resolver seal before raw exact-runtime objects expose state.""" + unsealed = object.__new__(FinalWeightComponentBindingAuthorityView) + + for attribute_name in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + FinalWeightComponentBindingAuthorityIntegrityError, + match="was not issued by resolve_final_weight_component_binding_authority", + ): + getattr(unsealed, attribute_name) + + +def test_wrong_issuance_marker_cannot_expose_component_binding_view() -> None: + """Reject marker-shaped objects that did not originate from the resolver.""" + forged_view = object.__new__(FinalWeightComponentBindingAuthorityView) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises( + FinalWeightComponentBindingAuthorityIntegrityError, + match="was not issued by resolve_final_weight_component_binding_authority", + ): + _ = forged_view.fields + + +def test_raw_component_binding_view_rejects_mutation_and_deletion() -> None: + """Keep projection state immutable after raw exact-runtime allocation.""" + raw_view = object.__new__(FinalWeightComponentBindingAuthorityView) + + with pytest.raises(AttributeError, match="immutable"): + raw_view._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw_view._fields From 3a1eb6829fa5a183c87cf96633979f5b3e34a983 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:26:29 +0900 Subject: [PATCH 516/603] fix(workforce-validation): seal final weight component binding view --- ...inal_weight_component_binding_authority.py | 67 +++++++++++++++---- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_binding_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_binding_authority.py index 606010d88..44f2ec58a 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_binding_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_binding_authority.py @@ -37,6 +37,7 @@ _RESOURCE_KIND = "final_weight_component_binding_authority" _OPERATION = "read" +_FINAL_WEIGHT_COMPONENT_BINDING_VIEW_ISSUANCE_MARKER = object() _EVIDENCE_REFERENCE_NAMESPACE_BY_KIND = { "nonresponse_adjustment_receipt": "nonresponse_adjustment_receipt", "calibration_adjustment_receipt": "calibration_adjustment_receipt", @@ -294,10 +295,10 @@ def superseded_at(self) -> datetime | None: return self[5] -class FinalWeightComponentBindingAuthorityView(tuple): - """Field-minimized component locator issued only after purpose authorization.""" +class FinalWeightComponentBindingAuthorityView: + """Sealed component locator issued only after purpose authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -312,20 +313,50 @@ def __new__( "resolve_final_weight_component_binding_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError("FinalWeightComponentBindingAuthorityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError("FinalWeightComponentBindingAuthorityView is immutable.") + + def _require_issued(self) -> None: + """Reject exact-runtime allocations not sealed by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise FinalWeightComponentBindingAuthorityIntegrityError( + "final-weight component binding view was not issued by " + "resolve_final_weight_component_binding_authority" + ) from exc + if marker is not _FINAL_WEIGHT_COMPONENT_BINDING_VIEW_ISSUANCE_MARKER: + raise FinalWeightComponentBindingAuthorityIntegrityError( + "final-weight component binding view was not issued by " + "resolve_final_weight_component_binding_authority" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return immutable component receipt locators and owner chronology.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -478,11 +509,21 @@ def resolve_final_weight_component_binding_authority( values["released_at"] = record.released_at values["superseded_at"] = record.superseded_at fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) - return tuple.__new__( - FinalWeightComponentBindingAuthorityView, - ( - _store_operational_uuid("tenant_record_id", record.tenant_record_id), - _store_operational_uuid("validity_study_id", record.validity_study_id), - fields, - ), + view = object.__new__(FinalWeightComponentBindingAuthorityView) + object.__setattr__( + view, + "_tenant_identity", + _store_operational_uuid("tenant_record_id", record.tenant_record_id), + ) + object.__setattr__( + view, + "_study_identity", + _store_operational_uuid("validity_study_id", record.validity_study_id), + ) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, + "_issuance_marker", + _FINAL_WEIGHT_COMPONENT_BINDING_VIEW_ISSUANCE_MARKER, ) + return view From 9e555eed99c94024de1112d581218f83a27e52a4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:27:18 +0900 Subject: [PATCH 517/603] docs(workforce-validation): seal component binding evidence --- CHANGELOG.md | 2 +- manifest.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e19768044..1ab7b93c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ All notable changes to Orgmetra will be documented in this file. ### Security -- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry, calibration auxiliary, calibration support, base-weight, base-weight supersession, calibration benchmark, calibration adjustment, calibration-adjustment supersession, final analysis-weight, final-weight supersession, weight eligibility, weight-eligibility supersession, weight/variance supersession, trimming/bounding, and trimming/bounding supersession projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 9 other tuple-backed public views. +- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry, calibration auxiliary, calibration support, base-weight, base-weight supersession, calibration benchmark, calibration adjustment, calibration-adjustment supersession, final analysis-weight, final-weight component binding, final-weight supersession, weight eligibility, weight-eligibility supersession, weight/variance supersession, trimming/bounding, and trimming/bounding supersession projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 8 other tuple-backed public views. - Predictive-validity cases fail closed when selection evidence, Job scope, study criterion, converted worker, or system-recorded visibility does not match; the normalized case relation is tenant-qualified, append-only, TRUNCATE-protected, and forced through row-level security. - Purpose-bound PII authorization now fails closed across active tenant, authenticated actor tenant, resource tenant, resource kind, purpose, operation, operation-specific Keyverse scope, and requested-field subset; malformed/wildcard-like attributes, mutable field/scope collections, reserved UUID sentinels, and cross-tenant confused-deputy contexts are rejected before protected values are returned. Authorization requests and allow/deny evidence now also require and preserve one namespaced opaque target-resource reference, so immutable audit correlation identifies the exact HR record without copying its protected values. Authorization evidence otherwise contains governance metadata and field names only, with stable denial reasons and actionable next steps rather than PII. - LLM output constrained to draft evidence. diff --git a/manifest.json b/manifest.json index cc4cc0621..d4f24b65a 100644 --- a/manifest.json +++ b/manifest.json @@ -29,8 +29,8 @@ }, { "path": "CHANGELOG.md", - "sha256": "46c0bc8e802d7b1462169bbb5b8af069e526c61098ace786025921c47d77d92a", - "bytes": 19033, + "sha256": "d09d9e02cf8f952518ac2f03bb2826bec32fe219c136347803cceebc98144ea8", + "bytes": 19065, "lines": 80 }, { From d26a9ff561b912de44e16dca366297ece5b4721d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:29:39 +0900 Subject: [PATCH 518/603] test(workforce-validation): expose nonresponse view issuance bypass --- ...tment_authority_view_issuance_integrity.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_view_issuance_integrity.py new file mode 100644 index 000000000..6a42f6306 --- /dev/null +++ b/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_view_issuance_integrity.py @@ -0,0 +1,61 @@ +"""Regression contract for nonresponse-adjustment view issuance integrity.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.nonresponse_adjustment_authority import ( + NonresponseAdjustmentAuthorityIntegrityError, + NonresponseAdjustmentAuthorityView, +) + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f2") + + +def test_low_level_tuple_construction_cannot_issue_nonresponse_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + NonresponseAdjustmentAuthorityView, + ( + TENANT.int, + STUDY.int, + (("nonresponse_receipt_digest", "0" * 64),), + ), + ) + + +def test_unsealed_object_allocation_cannot_expose_nonresponse_view() -> None: + """Require the resolver seal before raw exact-runtime objects expose state.""" + unsealed = object.__new__(NonresponseAdjustmentAuthorityView) + + for attribute_name in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + NonresponseAdjustmentAuthorityIntegrityError, + match="was not issued by resolve_nonresponse_adjustment_authority", + ): + getattr(unsealed, attribute_name) + + +def test_wrong_issuance_marker_cannot_expose_nonresponse_view() -> None: + """Reject marker-shaped objects that did not originate from the resolver.""" + forged_view = object.__new__(NonresponseAdjustmentAuthorityView) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises( + NonresponseAdjustmentAuthorityIntegrityError, + match="was not issued by resolve_nonresponse_adjustment_authority", + ): + _ = forged_view.fields + + +def test_raw_nonresponse_view_rejects_mutation_and_deletion() -> None: + """Keep projection state immutable after raw exact-runtime allocation.""" + raw_view = object.__new__(NonresponseAdjustmentAuthorityView) + + with pytest.raises(AttributeError, match="immutable"): + raw_view._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw_view._fields From 25cd572ad285695ecc9ee6ad2a73dde42084a367 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:30:29 +0900 Subject: [PATCH 519/603] fix(workforce-validation): seal nonresponse authority views --- .../nonresponse_adjustment_authority.py | 67 +++++++++++++++---- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py index f348f2959..8fad7ae9b 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py @@ -37,6 +37,7 @@ _RESOURCE_KIND = "nonresponse_adjustment_authority" _OPERATION = "read" +_NONRESPONSE_ADJUSTMENT_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "nonresponse_receipt_reference", @@ -349,10 +350,10 @@ def superseded_at(self) -> datetime | None: return self[24] -class NonresponseAdjustmentAuthorityView(tuple): - """Field-minimized nonresponse evidence issued only after authorization.""" +class NonresponseAdjustmentAuthorityView: + """Sealed nonresponse evidence issued only after purpose-bound authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -367,20 +368,50 @@ def __new__( "resolve_nonresponse_adjustment_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError("NonresponseAdjustmentAuthorityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError("NonresponseAdjustmentAuthorityView is immutable.") + + def _require_issued(self) -> None: + """Reject exact-runtime allocations not sealed by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise NonresponseAdjustmentAuthorityIntegrityError( + "nonresponse adjustment view was not issued by " + "resolve_nonresponse_adjustment_authority" + ) from exc + if marker is not _NONRESPONSE_ADJUSTMENT_VIEW_ISSUANCE_MARKER: + raise NonresponseAdjustmentAuthorityIntegrityError( + "nonresponse adjustment view was not issued by " + "resolve_nonresponse_adjustment_authority" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return immutable nonresponse provenance without response values.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -632,11 +663,21 @@ def resolve_nonresponse_adjustment_authority( ("unavailable_treatment_code", record.unavailable_treatment_code), ("unknown_treatment_code", record.unknown_treatment_code), ) - return tuple.__new__( - NonresponseAdjustmentAuthorityView, - ( - _store_operational_uuid("tenant_record_id", tenant_id), - _store_operational_uuid("validity_study_id", study_id), - fields, - ), + view = object.__new__(NonresponseAdjustmentAuthorityView) + object.__setattr__( + view, + "_tenant_identity", + _store_operational_uuid("tenant_record_id", tenant_id), + ) + object.__setattr__( + view, + "_study_identity", + _store_operational_uuid("validity_study_id", study_id), + ) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, + "_issuance_marker", + _NONRESPONSE_ADJUSTMENT_VIEW_ISSUANCE_MARKER, ) + return view From 1ed785d8fb886fde9c2bb2f7341a95d9704bdac8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:31:06 +0900 Subject: [PATCH 520/603] test(workforce-validation): expose nonresponse supersession view bypass --- ...ssion_authority_view_issuance_integrity.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_authority_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_authority_view_issuance_integrity.py new file mode 100644 index 000000000..c4a6b6bc4 --- /dev/null +++ b/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_authority_view_issuance_integrity.py @@ -0,0 +1,61 @@ +"""Regression contract for nonresponse-supersession view issuance integrity.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.nonresponse_adjustment_supersession_authority import ( + NonresponseAdjustmentSupersessionAuthorityIntegrityError, + NonresponseAdjustmentSupersessionAuthorityView, +) + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f2") + + +def test_low_level_tuple_construction_cannot_issue_nonresponse_supersession_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + NonresponseAdjustmentSupersessionAuthorityView, + ( + TENANT.int, + STUDY.int, + (("nonresponse_receipt_digest", "0" * 64),), + ), + ) + + +def test_unsealed_object_allocation_cannot_expose_nonresponse_supersession_view() -> None: + """Require the resolver seal before raw exact-runtime objects expose state.""" + unsealed = object.__new__(NonresponseAdjustmentSupersessionAuthorityView) + + for attribute_name in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + NonresponseAdjustmentSupersessionAuthorityIntegrityError, + match="was not issued by resolve_nonresponse_adjustment_supersession_authority", + ): + getattr(unsealed, attribute_name) + + +def test_wrong_issuance_marker_cannot_expose_nonresponse_supersession_view() -> None: + """Reject marker-shaped objects that did not originate from the resolver.""" + forged_view = object.__new__(NonresponseAdjustmentSupersessionAuthorityView) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises( + NonresponseAdjustmentSupersessionAuthorityIntegrityError, + match="was not issued by resolve_nonresponse_adjustment_supersession_authority", + ): + _ = forged_view.fields + + +def test_raw_nonresponse_supersession_view_rejects_mutation_and_deletion() -> None: + """Keep projection state immutable after raw exact-runtime allocation.""" + raw_view = object.__new__(NonresponseAdjustmentSupersessionAuthorityView) + + with pytest.raises(AttributeError, match="immutable"): + raw_view._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw_view._fields From 563518a8edb30731959403a9437f6b33ef5820eb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:31:42 +0900 Subject: [PATCH 521/603] fix(workforce-validation): seal nonresponse supersession views --- ...ponse_adjustment_supersession_authority.py | 71 +++++++++++++++---- 1 file changed, 58 insertions(+), 13 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_supersession_authority.py index e9cb4022d..d9e06f03f 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_supersession_authority.py @@ -37,6 +37,7 @@ _RESOURCE_KIND = "nonresponse_adjustment_supersession_authority" _OPERATION = "read" +_NONRESPONSE_ADJUSTMENT_SUPERSESSION_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "nonresponse_receipt_reference", @@ -231,10 +232,10 @@ def successor_fields(self) -> tuple[tuple[str, object], ...] | None: return self[5] -class NonresponseAdjustmentSupersessionAuthorityView(tuple): - """Minimized current-receipt authority issued only after authorization.""" +class NonresponseAdjustmentSupersessionAuthorityView: + """Sealed current-receipt authority issued only after authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -249,20 +250,54 @@ def __new__( "resolve_nonresponse_adjustment_supersession_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError( + "NonresponseAdjustmentSupersessionAuthorityView is immutable." + ) + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError( + "NonresponseAdjustmentSupersessionAuthorityView is immutable." + ) + + def _require_issued(self) -> None: + """Reject exact-runtime allocations not sealed by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise NonresponseAdjustmentSupersessionAuthorityIntegrityError( + "nonresponse supersession view was not issued by " + "resolve_nonresponse_adjustment_supersession_authority" + ) from exc + if marker is not _NONRESPONSE_ADJUSTMENT_SUPERSESSION_VIEW_ISSUANCE_MARKER: + raise NonresponseAdjustmentSupersessionAuthorityIntegrityError( + "nonresponse supersession view was not issued by " + "resolve_nonresponse_adjustment_supersession_authority" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return current receipt authority without successor disclosure.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -467,11 +502,21 @@ def resolve_nonresponse_adjustment_supersession_authority( "released_at", ) ) - return tuple.__new__( - NonresponseAdjustmentSupersessionAuthorityView, - ( - _store_operational_uuid("tenant_record_id", tenant_id), - _store_operational_uuid("validity_study_id", study_id), - fields, - ), + view = object.__new__(NonresponseAdjustmentSupersessionAuthorityView) + object.__setattr__( + view, + "_tenant_identity", + _store_operational_uuid("tenant_record_id", tenant_id), + ) + object.__setattr__( + view, + "_study_identity", + _store_operational_uuid("validity_study_id", study_id), + ) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, + "_issuance_marker", + _NONRESPONSE_ADJUSTMENT_SUPERSESSION_VIEW_ISSUANCE_MARKER, ) + return view From cce459b8919c45ff79a4c2a1089901a46bbdacfd Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:32:10 +0900 Subject: [PATCH 522/603] test(workforce-validation): expose validation result view bypass --- ...esult_authority_view_issuance_integrity.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_authority_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_validation_result_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_validation_result_authority_view_issuance_integrity.py new file mode 100644 index 000000000..1dc285fa2 --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_authority_view_issuance_integrity.py @@ -0,0 +1,61 @@ +"""Regression contract for validation-result view issuance integrity.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.result_authority import ( + ValidationResultAuthorityIntegrityError, + ValidationResultAuthorityView, +) + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f2") + + +def test_low_level_tuple_construction_cannot_issue_validation_result_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + ValidationResultAuthorityView, + ( + TENANT.int, + STUDY.int, + (("result_digest", "0" * 64),), + ), + ) + + +def test_unsealed_object_allocation_cannot_expose_validation_result_view() -> None: + """Require the resolver seal before raw exact-runtime objects expose state.""" + unsealed = object.__new__(ValidationResultAuthorityView) + + for attribute_name in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + ValidationResultAuthorityIntegrityError, + match="was not issued by resolve_validation_result_authority", + ): + getattr(unsealed, attribute_name) + + +def test_wrong_issuance_marker_cannot_expose_validation_result_view() -> None: + """Reject marker-shaped objects that did not originate from the resolver.""" + forged_view = object.__new__(ValidationResultAuthorityView) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises( + ValidationResultAuthorityIntegrityError, + match="was not issued by resolve_validation_result_authority", + ): + _ = forged_view.fields + + +def test_raw_validation_result_view_rejects_mutation_and_deletion() -> None: + """Keep projection state immutable after raw exact-runtime allocation.""" + raw_view = object.__new__(ValidationResultAuthorityView) + + with pytest.raises(AttributeError, match="immutable"): + raw_view._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw_view._fields From 43b46fdce8535492babc99d8b6706f36fd8e1a95 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:32:47 +0900 Subject: [PATCH 523/603] fix(workforce-validation): seal validation result authority views --- .../result_authority.py | 55 ++++++++++++++++--- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py index 02cf6aa70..cc3d37772 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py @@ -37,6 +37,7 @@ _RESOURCE_KIND = "validation_result_authority" _OPERATION = "read" +_VALIDATION_RESULT_VIEW_ISSUANCE_MARKER = object() _VERIFICATION_STATUSES = frozenset({"verification_pending", "not_verifiable"}) _READ_FIELDS = frozenset( { @@ -250,10 +251,10 @@ def superseded_at(self) -> datetime | None: return self[14] -class ValidationResultAuthorityView(tuple): - """Field-minimized released result evidence issued only after authorization.""" +class ValidationResultAuthorityView: + """Sealed released result evidence issued only after purpose-bound authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -268,20 +269,50 @@ def __new__( "resolve_validation_result_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError("ValidationResultAuthorityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError("ValidationResultAuthorityView is immutable.") + + def _require_issued(self) -> None: + """Reject exact-runtime allocations not sealed by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise ValidationResultAuthorityIntegrityError( + "validation result view was not issued by " + "resolve_validation_result_authority" + ) from exc + if marker is not _VALIDATION_RESULT_VIEW_ISSUANCE_MARKER: + raise ValidationResultAuthorityIntegrityError( + "validation result view was not issued by " + "resolve_validation_result_authority" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return immutable corroborating fields without row-level scientific data.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -517,7 +548,13 @@ def resolve_validation_result_authority( "superseded_at": record.superseded_at, } fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) - return tuple.__new__( - ValidationResultAuthorityView, - (tenant_identity, study_identity, fields), + view = object.__new__(ValidationResultAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, + "_issuance_marker", + _VALIDATION_RESULT_VIEW_ISSUANCE_MARKER, ) + return view From e6dd59ff84509a77e20085118246b456e6df6ba3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:33:05 +0900 Subject: [PATCH 524/603] test(workforce-validation): expose non-verifiability view bypass --- ...onverifiability_view_issuance_integrity.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_view_issuance_integrity.py new file mode 100644 index 000000000..5e9d4ffb3 --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_view_issuance_integrity.py @@ -0,0 +1,61 @@ +"""Regression contract for validation-result non-verifiability view issuance integrity.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.result_nonverifiability import ( + ValidationResultNonVerifiabilityIntegrityError, + ValidationResultNonVerifiabilityView, +) + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f2") + + +def test_low_level_tuple_construction_cannot_issue_nonverifiability_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + ValidationResultNonVerifiabilityView, + ( + TENANT.int, + STUDY.int, + (("result_digest", "0" * 64),), + ), + ) + + +def test_unsealed_object_allocation_cannot_expose_nonverifiability_view() -> None: + """Require the resolver seal before raw exact-runtime objects expose state.""" + unsealed = object.__new__(ValidationResultNonVerifiabilityView) + + for attribute_name in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + ValidationResultNonVerifiabilityIntegrityError, + match="was not issued by resolve_validation_result_nonverifiability", + ): + getattr(unsealed, attribute_name) + + +def test_wrong_issuance_marker_cannot_expose_nonverifiability_view() -> None: + """Reject marker-shaped objects that did not originate from the resolver.""" + forged_view = object.__new__(ValidationResultNonVerifiabilityView) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises( + ValidationResultNonVerifiabilityIntegrityError, + match="was not issued by resolve_validation_result_nonverifiability", + ): + _ = forged_view.fields + + +def test_raw_nonverifiability_view_rejects_mutation_and_deletion() -> None: + """Keep projection state immutable after raw exact-runtime allocation.""" + raw_view = object.__new__(ValidationResultNonVerifiabilityView) + + with pytest.raises(AttributeError, match="immutable"): + raw_view._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw_view._fields From bc508bbf91cb8efd781060b1e785c8f447e0e30e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:33:53 +0900 Subject: [PATCH 525/603] fix(workforce-validation): seal non-verifiability views --- .../result_nonverifiability.py | 55 ++++++++++++++++--- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py index 32a5b0fc1..82bc65ba0 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py @@ -38,6 +38,7 @@ _RESOURCE_KIND = "validation_result_nonverifiability" _OPERATION = "read" _VERIFICATION_STATUS = "not_verifiable" +_VALIDATION_RESULT_NONVERIFIABILITY_VIEW_ISSUANCE_MARKER = object() _FAILED_REFERENCE_KIND_BY_EVIDENCE_KIND = { "analysis_weight_receipt": "analysis_weight_receipt", "weight_variance_compatibility_receipt": "weight_variance_compatibility_receipt", @@ -357,10 +358,10 @@ def verification_attempt_released_at(self) -> datetime: return self[18] -class ValidationResultNonVerifiabilityView(tuple): - """Field-minimized non-authorizing outcome issued only after authorization.""" +class ValidationResultNonVerifiabilityView: + """Sealed non-authorizing outcome issued only after purpose-bound authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -375,20 +376,50 @@ def __new__( "resolve_validation_result_nonverifiability." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError("ValidationResultNonVerifiabilityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError("ValidationResultNonVerifiabilityView is immutable.") + + def _require_issued(self) -> None: + """Reject exact-runtime allocations not sealed by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise ValidationResultNonVerifiabilityIntegrityError( + "validation result non-verifiability view was not issued by " + "resolve_validation_result_nonverifiability" + ) from exc + if marker is not _VALIDATION_RESULT_NONVERIFIABILITY_VIEW_ISSUANCE_MARKER: + raise ValidationResultNonVerifiabilityIntegrityError( + "validation result non-verifiability view was not issued by " + "resolve_validation_result_nonverifiability" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return immutable reason/evidence fields without scientific row values.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -646,7 +677,13 @@ def resolve_validation_result_nonverifiability( "superseded_at": record.superseded_at, } fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) - return tuple.__new__( - ValidationResultNonVerifiabilityView, - (tenant_identity, study_identity, fields), + view = object.__new__(ValidationResultNonVerifiabilityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, + "_issuance_marker", + _VALIDATION_RESULT_NONVERIFIABILITY_VIEW_ISSUANCE_MARKER, ) + return view From 98a0afae7960c5a47173aadcece6e5e3cb8fcf35 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:35:23 +0900 Subject: [PATCH 526/603] test(workforce-validation): expose non-verifiability supersession view bypass --- ...ssion_authority_view_issuance_integrity.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_view_issuance_integrity.py new file mode 100644 index 000000000..867325b2e --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_view_issuance_integrity.py @@ -0,0 +1,61 @@ +"""Regression contract for non-verifiability supersession view issuance integrity.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.result_nonverifiability_supersession_authority import ( + ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError, + ValidationResultNonVerifiabilitySupersessionAuthorityView, +) + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f2") + + +def test_low_level_tuple_construction_cannot_issue_nonverifiability_supersession_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + ValidationResultNonVerifiabilitySupersessionAuthorityView, + ( + TENANT.int, + STUDY.int, + (("result_digest", "0" * 64),), + ), + ) + + +def test_unsealed_object_allocation_cannot_expose_nonverifiability_supersession_view() -> None: + """Require the resolver seal before raw exact-runtime objects expose state.""" + unsealed = object.__new__(ValidationResultNonVerifiabilitySupersessionAuthorityView) + + for attribute_name in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError, + match="was not issued by resolve_validation_result_nonverifiability_supersession_authority", + ): + getattr(unsealed, attribute_name) + + +def test_wrong_issuance_marker_cannot_expose_nonverifiability_supersession_view() -> None: + """Reject marker-shaped objects that did not originate from the resolver.""" + forged_view = object.__new__(ValidationResultNonVerifiabilitySupersessionAuthorityView) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises( + ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError, + match="was not issued by resolve_validation_result_nonverifiability_supersession_authority", + ): + _ = forged_view.fields + + +def test_raw_nonverifiability_supersession_view_rejects_mutation_and_deletion() -> None: + """Keep projection state immutable after raw exact-runtime allocation.""" + raw_view = object.__new__(ValidationResultNonVerifiabilitySupersessionAuthorityView) + + with pytest.raises(AttributeError, match="immutable"): + raw_view._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw_view._fields From 8cffb9b19d819011fbb54a92c58327021a892055 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:36:22 +0900 Subject: [PATCH 527/603] fix(workforce-validation): seal non-verifiability supersession views --- ...nonverifiability_supersession_authority.py | 71 +++++++++++++++---- 1 file changed, 58 insertions(+), 13 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py index a976b8bc0..6bba59a08 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py @@ -40,6 +40,7 @@ _RESOURCE_KIND = "validation_result_nonverifiability_supersession_authority" _OPERATION = "read" +_VALIDATION_RESULT_NONVERIFIABILITY_SUPERSESSION_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "result_reference", @@ -305,10 +306,10 @@ def successor_fields(self) -> tuple[tuple[str, object], ...] | None: return self[5] -class ValidationResultNonVerifiabilitySupersessionAuthorityView(tuple): - """Minimized predecessor authority issued only after purpose authorization.""" +class ValidationResultNonVerifiabilitySupersessionAuthorityView: + """Sealed predecessor authority issued only after purpose authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -323,20 +324,54 @@ def __new__( "resolve_validation_result_nonverifiability_supersession_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError( + "ValidationResultNonVerifiabilitySupersessionAuthorityView is immutable." + ) + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError( + "ValidationResultNonVerifiabilitySupersessionAuthorityView is immutable." + ) + + def _require_issued(self) -> None: + """Reject exact-runtime allocations not sealed by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError( + "validation result non-verifiability supersession view was not issued by " + "resolve_validation_result_nonverifiability_supersession_authority" + ) from exc + if marker is not _VALIDATION_RESULT_NONVERIFIABILITY_SUPERSESSION_VIEW_ISSUANCE_MARKER: + raise ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError( + "validation result non-verifiability supersession view was not issued by " + "resolve_validation_result_nonverifiability_supersession_authority" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return predecessor provenance without cutover or successor disclosure.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -580,14 +615,24 @@ def resolve_validation_result_nonverifiability_supersession_authority( values = {**record_values, "released_at": record.released_at} fields = tuple((field_name, values[field_name]) for field_name in sorted(_VIEW_FIELDS)) - return tuple.__new__( - ValidationResultNonVerifiabilitySupersessionAuthorityView, - ( - _store_operational_uuid("tenant_record_id", tenant_id), - _store_operational_uuid("validity_study_id", study_id), - fields, - ), + view = object.__new__(ValidationResultNonVerifiabilitySupersessionAuthorityView) + object.__setattr__( + view, + "_tenant_identity", + _store_operational_uuid("tenant_record_id", tenant_id), + ) + object.__setattr__( + view, + "_study_identity", + _store_operational_uuid("validity_study_id", study_id), + ) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, + "_issuance_marker", + _VALIDATION_RESULT_NONVERIFIABILITY_SUPERSESSION_VIEW_ISSUANCE_MARKER, ) + return view __all__ = [ From b96d2e851a0135599844ad83ca75f91d29e63b41 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:36:39 +0900 Subject: [PATCH 528/603] test(workforce-validation): expose v2 non-verifiability view bypass --- ...on_v2_authority_view_issuance_integrity.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_view_issuance_integrity.py new file mode 100644 index 000000000..afc040eb3 --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_view_issuance_integrity.py @@ -0,0 +1,61 @@ +"""Regression contract for v2 non-verifiability supersession view issuance integrity.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.result_nonverifiability_supersession_v2_authority import ( + ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError, + ValidationResultNonVerifiabilitySupersessionV2AuthorityView, +) + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f2") + + +def test_low_level_tuple_construction_cannot_issue_v2_nonverifiability_supersession_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + ValidationResultNonVerifiabilitySupersessionV2AuthorityView, + ( + TENANT.int, + STUDY.int, + (("result_digest", "0" * 64),), + ), + ) + + +def test_unsealed_object_allocation_cannot_expose_v2_nonverifiability_supersession_view() -> None: + """Require the resolver seal before raw exact-runtime objects expose state.""" + unsealed = object.__new__(ValidationResultNonVerifiabilitySupersessionV2AuthorityView) + + for attribute_name in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError, + match="was not issued by resolve_validation_result_nonverifiability_supersession_v2_authority", + ): + getattr(unsealed, attribute_name) + + +def test_wrong_issuance_marker_cannot_expose_v2_nonverifiability_supersession_view() -> None: + """Reject marker-shaped objects that did not originate from the resolver.""" + forged_view = object.__new__(ValidationResultNonVerifiabilitySupersessionV2AuthorityView) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises( + ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError, + match="was not issued by resolve_validation_result_nonverifiability_supersession_v2_authority", + ): + _ = forged_view.fields + + +def test_raw_v2_nonverifiability_supersession_view_rejects_mutation_and_deletion() -> None: + """Keep projection state immutable after raw exact-runtime allocation.""" + raw_view = object.__new__(ValidationResultNonVerifiabilitySupersessionV2AuthorityView) + + with pytest.raises(AttributeError, match="immutable"): + raw_view._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw_view._fields From b058e6c696c034f075c1fb37cc133f355ad3c121 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:37:28 +0900 Subject: [PATCH 529/603] fix(workforce-validation): seal v2 non-verifiability supersession views --- ...verifiability_supersession_v2_authority.py | 71 +++++++++++++++---- 1 file changed, 58 insertions(+), 13 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py index 44e091c36..189a2dcd8 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py @@ -32,6 +32,7 @@ _RESOURCE_KIND = "validation_result_nonverifiability_supersession_authority" _OPERATION = "read" _VERSION = 2 +_VALIDATION_RESULT_NONVERIFIABILITY_SUPERSESSION_V2_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "result_reference", @@ -324,10 +325,10 @@ def successor_fields(self) -> tuple[tuple[str, object], ...] | None: return self[3] -class ValidationResultNonVerifiabilitySupersessionV2AuthorityView(tuple): - """Expose minimized predecessor provenance without reusable successor authority.""" +class ValidationResultNonVerifiabilitySupersessionV2AuthorityView: + """Sealed minimized predecessor provenance issued only after authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -342,20 +343,54 @@ def __new__( "resolve_validation_result_nonverifiability_supersession_v2_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError( + "ValidationResultNonVerifiabilitySupersessionV2AuthorityView is immutable." + ) + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError( + "ValidationResultNonVerifiabilitySupersessionV2AuthorityView is immutable." + ) + + def _require_issued(self) -> None: + """Reject exact-runtime allocations not sealed by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError( + "validation result non-verifiability supersession v2 view was not issued by " + "resolve_validation_result_nonverifiability_supersession_v2_authority" + ) from exc + if marker is not _VALIDATION_RESULT_NONVERIFIABILITY_SUPERSESSION_V2_VIEW_ISSUANCE_MARKER: + raise ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError( + "validation result non-verifiability supersession v2 view was not issued by " + "resolve_validation_result_nonverifiability_supersession_v2_authority" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return predecessor provenance without cutover or successor coordinates.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -564,14 +599,24 @@ def resolve_validation_result_nonverifiability_supersession_v2_authority( ) projection_values = {**values, "released_at": persisted.released_at} fields = tuple((name, projection_values[name]) for name in sorted(_VIEW_FIELDS)) - return tuple.__new__( - ValidationResultNonVerifiabilitySupersessionV2AuthorityView, - ( - _store_operational_uuid("tenant_record_id", tenant_id), - _store_operational_uuid("validity_study_id", study_id), - fields, - ), + view = object.__new__(ValidationResultNonVerifiabilitySupersessionV2AuthorityView) + object.__setattr__( + view, + "_tenant_identity", + _store_operational_uuid("tenant_record_id", tenant_id), + ) + object.__setattr__( + view, + "_study_identity", + _store_operational_uuid("validity_study_id", study_id), + ) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, + "_issuance_marker", + _VALIDATION_RESULT_NONVERIFIABILITY_SUPERSESSION_V2_VIEW_ISSUANCE_MARKER, ) + return view __all__ = [ From 405c86ac5b848cd665011c1163bffeefb56a2a08 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:37:50 +0900 Subject: [PATCH 530/603] test(workforce-validation): expose validation result supersession view bypass --- ...ssion_authority_view_issuance_integrity.py | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_supersession_authority_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_validation_result_supersession_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_validation_result_supersession_authority_view_issuance_integrity.py new file mode 100644 index 000000000..57b8a82b7 --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_supersession_authority_view_issuance_integrity.py @@ -0,0 +1,57 @@ +"""Regression contract for validation-result supersession view issuance integrity.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.result_supersession_authority import ( + ValidationResultSupersessionAuthorityIntegrityError, + ValidationResultSupersessionAuthorityView, +) + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f2") + + +def test_low_level_tuple_construction_cannot_issue_validation_result_supersession_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + ValidationResultSupersessionAuthorityView, + (TENANT.int, STUDY.int, (("result_digest", "0" * 64),)), + ) + + +def test_unsealed_object_allocation_cannot_expose_validation_result_supersession_view() -> None: + """Require the resolver seal before raw exact-runtime objects expose state.""" + unsealed = object.__new__(ValidationResultSupersessionAuthorityView) + + for attribute_name in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + ValidationResultSupersessionAuthorityIntegrityError, + match="was not issued by resolve_validation_result_supersession_authority", + ): + getattr(unsealed, attribute_name) + + +def test_wrong_issuance_marker_cannot_expose_validation_result_supersession_view() -> None: + """Reject marker-shaped objects that did not originate from the resolver.""" + forged_view = object.__new__(ValidationResultSupersessionAuthorityView) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises( + ValidationResultSupersessionAuthorityIntegrityError, + match="was not issued by resolve_validation_result_supersession_authority", + ): + _ = forged_view.fields + + +def test_raw_validation_result_supersession_view_rejects_mutation_and_deletion() -> None: + """Keep projection state immutable after raw exact-runtime allocation.""" + raw_view = object.__new__(ValidationResultSupersessionAuthorityView) + + with pytest.raises(AttributeError, match="immutable"): + raw_view._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw_view._fields From 10875a4e0879369ca7389d986f9ea6468a8b2a74 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:38:27 +0900 Subject: [PATCH 531/603] fix(workforce-validation): seal validation result supersession views --- .../result_supersession_authority.py | 67 +++++++++++++++---- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py index 7cd306d87..a976bfc40 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py @@ -36,6 +36,7 @@ _RESOURCE_KIND = "validation_result_supersession_authority" _OPERATION = "read" +_VALIDATION_RESULT_SUPERSESSION_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "result_reference", @@ -244,10 +245,10 @@ def successor_fields(self) -> tuple[tuple[str, object], ...] | None: return self[5] -class ValidationResultSupersessionAuthorityView(tuple): - """Minimized current-result authority issued only after purpose authorization.""" +class ValidationResultSupersessionAuthorityView: + """Sealed current-result authority issued only after purpose authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -262,20 +263,50 @@ def __new__( "resolve_validation_result_supersession_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError("ValidationResultSupersessionAuthorityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError("ValidationResultSupersessionAuthorityView is immutable.") + + def _require_issued(self) -> None: + """Reject exact-runtime allocations not sealed by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise ValidationResultSupersessionAuthorityIntegrityError( + "validation result supersession view was not issued by " + "resolve_validation_result_supersession_authority" + ) from exc + if marker is not _VALIDATION_RESULT_SUPERSESSION_VIEW_ISSUANCE_MARKER: + raise ValidationResultSupersessionAuthorityIntegrityError( + "validation result supersession view was not issued by " + "resolve_validation_result_supersession_authority" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return released current-result provenance without successor disclosure.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -483,14 +514,24 @@ def resolve_validation_result_supersession_authority( "released_at": record.released_at, } fields = tuple((field_name, values[field_name]) for field_name in sorted(_VIEW_FIELDS)) - return tuple.__new__( - ValidationResultSupersessionAuthorityView, - ( - _store_operational_uuid("tenant_record_id", tenant_id), - _store_operational_uuid("validity_study_id", study_id), - fields, - ), + view = object.__new__(ValidationResultSupersessionAuthorityView) + object.__setattr__( + view, + "_tenant_identity", + _store_operational_uuid("tenant_record_id", tenant_id), + ) + object.__setattr__( + view, + "_study_identity", + _store_operational_uuid("validity_study_id", study_id), + ) + object.__setattr__(view, "_fields", fields) + object.__setattr__( + view, + "_issuance_marker", + _VALIDATION_RESULT_SUPERSESSION_VIEW_ISSUANCE_MARKER, ) + return view __all__ = [ From 89483e92e0282ae5168a8257f86fcd973314665c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:38:55 +0900 Subject: [PATCH 532/603] test(workforce-validation): expose weight variance view bypass --- ...iance_authority_view_issuance_integrity.py | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_variance_authority_view_issuance_integrity.py diff --git a/services/workforce-validation-api/tests/test_weight_variance_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_weight_variance_authority_view_issuance_integrity.py new file mode 100644 index 000000000..6d61fc55d --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_variance_authority_view_issuance_integrity.py @@ -0,0 +1,57 @@ +"""Regression contract for point-weight/variance authority view issuance integrity.""" + +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.variance_authority import ( + WeightVarianceAuthorityIntegrityError, + WeightVarianceAuthorityView, +) + + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f2") + + +def test_low_level_tuple_construction_cannot_issue_weight_variance_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + WeightVarianceAuthorityView, + (TENANT.int, STUDY.int, (("authority_reference", "x"),)), + ) + + +def test_unsealed_object_allocation_cannot_expose_weight_variance_view() -> None: + """Require the resolver seal before raw exact-runtime objects expose state.""" + unsealed = object.__new__(WeightVarianceAuthorityView) + + for attribute_name in ("tenant_record_id", "validity_study_id", "fields"): + with pytest.raises( + WeightVarianceAuthorityIntegrityError, + match="was not issued by resolve_weight_variance_authority", + ): + getattr(unsealed, attribute_name) + + +def test_wrong_issuance_marker_cannot_expose_weight_variance_view() -> None: + """Reject marker-shaped objects that did not originate from the resolver.""" + forged_view = object.__new__(WeightVarianceAuthorityView) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises( + WeightVarianceAuthorityIntegrityError, + match="was not issued by resolve_weight_variance_authority", + ): + _ = forged_view.fields + + +def test_raw_weight_variance_view_rejects_mutation_and_deletion() -> None: + """Keep projection state immutable after raw exact-runtime allocation.""" + raw_view = object.__new__(WeightVarianceAuthorityView) + + with pytest.raises(AttributeError, match="immutable"): + raw_view._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw_view._fields From 0c6de75b79fddf3cf58ed16ed3dcee866a4a1b77 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 02:39:45 +0900 Subject: [PATCH 533/603] fix(workforce-validation): seal weight variance authority views --- .../variance_authority.py | 48 ++++++++++++++++--- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py index c1e2e737c..6305d255a 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py @@ -35,6 +35,7 @@ _REFERENCE_PATTERN = re.compile(r"^[a-z][a-z0-9_]*:[A-Za-z0-9][A-Za-z0-9._~-]*$") _RESOURCE_KIND = "weight_variance_authority" _OPERATION = "read" +_WEIGHT_VARIANCE_VIEW_ISSUANCE_MARKER = object() _VARIANCE_EVIDENCE_MODES = frozenset( { "joint_inclusion", @@ -370,10 +371,10 @@ def superseded_at(self) -> datetime | None: return self[23] -class WeightVarianceAuthorityView(tuple): - """Field-minimized compatibility evidence issued only after authorization.""" +class WeightVarianceAuthorityView: + """Sealed compatibility evidence issued only after purpose-bound authorization.""" - __slots__ = () + __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") def __new__( cls, @@ -387,20 +388,48 @@ def __new__( "WeightVarianceAuthorityView is issued only by resolve_weight_variance_authority." ) + def __setattr__(self, name: str, value: object) -> None: + """Keep ordinary callers from mutating issued projection state.""" + raise AttributeError("WeightVarianceAuthorityView is immutable.") + + def __delattr__(self, name: str) -> None: + """Keep ordinary callers from deleting issued projection state.""" + raise AttributeError("WeightVarianceAuthorityView is immutable.") + + def _require_issued(self) -> None: + """Reject exact-runtime allocations not sealed by the resolver.""" + try: + marker = object.__getattribute__(self, "_issuance_marker") + except AttributeError as exc: + raise WeightVarianceAuthorityIntegrityError( + "weight variance view was not issued by resolve_weight_variance_authority" + ) from exc + if marker is not _WEIGHT_VARIANCE_VIEW_ISSUANCE_MARKER: + raise WeightVarianceAuthorityIntegrityError( + "weight variance view was not issued by resolve_weight_variance_authority" + ) + @property def tenant_record_id(self) -> UUID: """Return a fresh authorized tenant identity.""" - return _restore_operational_uuid("tenant_record_id", self[0]) + self._require_issued() + return _restore_operational_uuid( + "tenant_record_id", object.__getattribute__(self, "_tenant_identity") + ) @property def validity_study_id(self) -> UUID: """Return a fresh authorized validity-study identity.""" - return _restore_operational_uuid("validity_study_id", self[1]) + self._require_issued() + return _restore_operational_uuid( + "validity_study_id", object.__getattribute__(self, "_study_identity") + ) @property def fields(self) -> tuple[tuple[str, object], ...]: """Return immutable corroborating fields without row-level scientific data.""" - return self[2] + self._require_issued() + return object.__getattribute__(self, "_fields") @runtime_checkable @@ -675,4 +704,9 @@ def resolve_weight_variance_authority( "superseded_at": record.superseded_at, } fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) - return tuple.__new__(WeightVarianceAuthorityView, (tenant_identity, study_identity, fields)) + view = object.__new__(WeightVarianceAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", _WEIGHT_VARIANCE_VIEW_ISSUANCE_MARKER) + return view From 18ff2136d82060bdf6e789df540025512bc313a2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 03:05:42 +0900 Subject: [PATCH 534/603] test(workforce-validation): bind authorized view export census --- .../test_public_authorized_view_census.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_public_authorized_view_census.py diff --git a/services/workforce-validation-api/tests/test_public_authorized_view_census.py b/services/workforce-validation-api/tests/test_public_authorized_view_census.py new file mode 100644 index 000000000..279cb5835 --- /dev/null +++ b/services/workforce-validation-api/tests/test_public_authorized_view_census.py @@ -0,0 +1,61 @@ +"""Regression contract for the complete public authorized-view export census.""" + +from __future__ import annotations + +import orgmetra_workforce_validation_api as api + + +_EXPECTED_AUTHORIZED_VIEW_NAMES = frozenset( + { + "BaseWeightAuthorityView", + "BaseWeightSupersessionAuthorityView", + "CalibrationAdjustmentAuthorityView", + "CalibrationAdjustmentSupersessionAuthorityView", + "CalibrationAuxiliaryAuthorityView", + "CalibrationBenchmarkAuthorityView", + "CalibrationSupportAuthorityView", + "FinalAnalysisWeightAuthorityView", + "FinalWeightComponentBindingAuthorityView", + "FinalWeightSupersessionAuthorityView", + "NonresponseAdjustmentAuthorityView", + "NonresponseAdjustmentSupersessionAuthorityView", + "TrimmingBoundingAuthorityView", + "TrimmingBoundingSupersessionAuthorityView", + "ValidationResultAuthorityView", + "ValidationResultNonVerifiabilitySupersessionAuthorityView", + "ValidationResultNonVerifiabilitySupersessionV2AuthorityView", + "ValidationResultNonVerifiabilityView", + "ValidationResultSupersessionAuthorityView", + "ValidityStudyView", + "WeightEligibilityAuthorityView", + "WeightEligibilitySupersessionAuthorityView", + "WeightVarianceAuthorityView", + "WeightVarianceSupersessionAuthorityView", + } +) + + +def test_public_authorized_view_export_census_is_explicit_and_non_tuple() -> None: + """Keep every public authorized projection inside the sealed non-tuple contract.""" + observed = frozenset(name for name in api.__all__ if name.endswith("View")) + + assert observed == _EXPECTED_AUTHORIZED_VIEW_NAMES + for name in sorted(observed): + view_type = getattr(api, name) + assert type(view_type) is type + assert not issubclass(view_type, tuple) + + +def test_public_authorized_views_retain_local_sealing_and_mutation_guards() -> None: + """Require each public authorized projection to keep its local issuance boundary.""" + for name in sorted(_EXPECTED_AUTHORIZED_VIEW_NAMES): + view_type = getattr(api, name) + slots = view_type.__dict__.get("__slots__") + + assert type(slots) is tuple + assert "_issuance_marker" in slots + assert "__dict__" not in slots + assert "__new__" in view_type.__dict__ + assert "__setattr__" in view_type.__dict__ + assert "__delattr__" in view_type.__dict__ + assert "_require_issued" in view_type.__dict__ From 728f8c90814993150006c1023abe0bd6ddf875fe Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 03:18:46 +0900 Subject: [PATCH 535/603] fix(workforce-validation): seal calibration benchmark view --- .../benchmark_authority.py | 22 ++++------ ...hmark_authority_view_issuance_integrity.py | 40 +++++++++---------- 2 files changed, 26 insertions(+), 36 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py index a45435b80..0830e5030 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py @@ -47,7 +47,7 @@ "owner_contract_released_at", } ) -_CALIBRATION_BENCHMARK_AUTHORITY_VIEW_ISSUANCE_MARKER = object() +_CALIBRATION_BENCHMARK_VIEW_ISSUANCE_MARKER = object() class CalibrationBenchmarkAuthorityNotFound(LookupError): @@ -315,13 +315,7 @@ def successor_benchmark_receipt_released_at(self) -> datetime | None: class CalibrationBenchmarkAuthorityView: - """Sealed field-minimized benchmark evidence issued only after authorization. - - The public constructor is deliberately non-issuing. Raw exact-runtime - allocations remain unusable because each public property verifies the private - resolver seal before exposing detached projection state. Consequential actions - must still re-authorize and re-resolve owner truth rather than trusting a view. - """ + """Sealed field-minimized benchmark evidence issued after authorization.""" __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") @@ -332,7 +326,7 @@ def __new__( validity_study_id: UUID, fields: tuple[tuple[str, object], ...], ) -> CalibrationBenchmarkAuthorityView: - """Reject public construction; only the resolver may issue this view.""" + """Reject direct construction; only the resolver may issue this view.""" raise TypeError( "CalibrationBenchmarkAuthorityView is issued only by " "resolve_calibration_benchmark_authority." @@ -347,17 +341,17 @@ def __delattr__(self, name: str) -> None: raise AttributeError("CalibrationBenchmarkAuthorityView is immutable.") def _require_issued(self) -> None: - """Reject exact-runtime allocations that were not sealed by the resolver.""" + """Reject exact-runtime allocations not sealed by the resolver.""" try: marker = object.__getattribute__(self, "_issuance_marker") except AttributeError as exc: raise CalibrationBenchmarkAuthorityIntegrityError( - "calibration benchmark authority view was not issued by " + "calibration benchmark view was not issued by " "resolve_calibration_benchmark_authority" ) from exc - if marker is not _CALIBRATION_BENCHMARK_AUTHORITY_VIEW_ISSUANCE_MARKER: + if marker is not _CALIBRATION_BENCHMARK_VIEW_ISSUANCE_MARKER: raise CalibrationBenchmarkAuthorityIntegrityError( - "calibration benchmark authority view was not issued by " + "calibration benchmark view was not issued by " "resolve_calibration_benchmark_authority" ) @@ -626,6 +620,6 @@ def resolve_calibration_benchmark_authority( object.__setattr__( view, "_issuance_marker", - _CALIBRATION_BENCHMARK_AUTHORITY_VIEW_ISSUANCE_MARKER, + _CALIBRATION_BENCHMARK_VIEW_ISSUANCE_MARKER, ) return view diff --git a/services/workforce-validation-api/tests/test_calibration_benchmark_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_calibration_benchmark_authority_view_issuance_integrity.py index 6ff6ef0a6..895e60f9b 100644 --- a/services/workforce-validation-api/tests/test_calibration_benchmark_authority_view_issuance_integrity.py +++ b/services/workforce-validation-api/tests/test_calibration_benchmark_authority_view_issuance_integrity.py @@ -1,4 +1,4 @@ -"""Regression contract for calibration-benchmark authorized-view issuance integrity.""" +"""Regression contract for calibration-benchmark view issuance integrity.""" from uuid import UUID @@ -11,51 +11,47 @@ TENANT = UUID("10000000-0000-7000-8000-000000000001") -STUDY = UUID("00000000-0000-7000-8000-0000000000f1") +STUDY = UUID("00000000-0000-7000-8000-0000000000f2") -def test_low_level_tuple_construction_cannot_issue_calibration_benchmark_view() -> None: +def test_low_level_tuple_construction_cannot_issue_benchmark_view() -> None: """Remove tuple's base constructor as an alternate authorized-view issuer.""" with pytest.raises(TypeError): tuple.__new__( CalibrationBenchmarkAuthorityView, - ( - TENANT.int, - STUDY.int, - (("benchmark_receipt_digest", "6" * 64),), - ), + (TENANT.int, STUDY.int, (("benchmark_receipt_digest", "0" * 64),)), ) -def test_unsealed_object_allocation_cannot_expose_calibration_benchmark_view() -> None: - """Require the resolver seal before any raw exact-runtime object exposes state.""" +def test_unsealed_object_allocation_cannot_expose_benchmark_view() -> None: + """Require the resolver seal before raw exact-runtime objects expose state.""" unsealed = object.__new__(CalibrationBenchmarkAuthorityView) - for attribute in ("tenant_record_id", "validity_study_id", "fields"): + for attribute_name in ("tenant_record_id", "validity_study_id", "fields"): with pytest.raises( CalibrationBenchmarkAuthorityIntegrityError, match="was not issued by resolve_calibration_benchmark_authority", ): - getattr(unsealed, attribute) + getattr(unsealed, attribute_name) -def test_wrong_issuance_marker_cannot_expose_calibration_benchmark_view() -> None: - """Reject marker-shaped raw objects that did not originate from the resolver.""" - forged = object.__new__(CalibrationBenchmarkAuthorityView) - object.__setattr__(forged, "_issuance_marker", object()) +def test_wrong_issuance_marker_cannot_expose_benchmark_view() -> None: + """Reject marker-shaped objects that did not originate from the resolver.""" + forged_view = object.__new__(CalibrationBenchmarkAuthorityView) + object.__setattr__(forged_view, "_issuance_marker", object()) with pytest.raises( CalibrationBenchmarkAuthorityIntegrityError, match="was not issued by resolve_calibration_benchmark_authority", ): - _ = forged.fields + _ = forged_view.fields -def test_raw_calibration_benchmark_view_rejects_public_mutation_and_deletion() -> None: - """Keep projection state immutable even when callers allocate the exact runtime type.""" - raw = object.__new__(CalibrationBenchmarkAuthorityView) +def test_raw_benchmark_view_rejects_mutation_and_deletion() -> None: + """Keep projection state immutable after raw exact-runtime allocation.""" + raw_view = object.__new__(CalibrationBenchmarkAuthorityView) with pytest.raises(AttributeError, match="immutable"): - raw._fields = () + raw_view._fields = () with pytest.raises(AttributeError, match="immutable"): - del raw._fields + del raw_view._fields From 5dba6630408e39891ec8b7bdac7e2bd0d9f58ab5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 03:24:50 +0900 Subject: [PATCH 536/603] test(workforce-validation): complete authorized view census evidence --- CHANGELOG.md | 2 +- manifest.json | 4 +- .../tests/test_view_issuance_integrity.py | 74 ++++++++++--------- 3 files changed, 41 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ab7b93c8..0b17589ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ All notable changes to Orgmetra will be documented in this file. ### Security -- Active-PR Workforce Validation authorized evidence views now reject low-level base-constructor forging: the registry, calibration auxiliary, calibration support, base-weight, base-weight supersession, calibration benchmark, calibration adjustment, calibration-adjustment supersession, final analysis-weight, final-weight component binding, final-weight supersession, weight eligibility, weight-eligibility supersession, weight/variance supersession, trimming/bounding, and trimming/bounding supersession projections are sealed non-tuple data views whose public constructors reject, whose raw allocations cannot expose state, and whose supported issuers remain purpose-authorized owner-resolution paths. The systematic sibling audit remains open for 8 other tuple-backed public views. +- Active-PR Workforce Validation authorized evidence views reject low-level base-constructor forging across the complete 24-class public export census. Every exported `*View` is a sealed non-tuple data object whose public constructor rejects, whose raw allocations cannot expose state, and whose only supported issuer remains its purpose-authorized owner-resolution path. The executable package-surface census now fails closed on an added, removed, tuple-backed, unsealed, or mutable public view; `CalibrationBenchmarkAuthorityView` was the final omission exposed by that census and is covered by its own issuance-integrity regression. - Predictive-validity cases fail closed when selection evidence, Job scope, study criterion, converted worker, or system-recorded visibility does not match; the normalized case relation is tenant-qualified, append-only, TRUNCATE-protected, and forced through row-level security. - Purpose-bound PII authorization now fails closed across active tenant, authenticated actor tenant, resource tenant, resource kind, purpose, operation, operation-specific Keyverse scope, and requested-field subset; malformed/wildcard-like attributes, mutable field/scope collections, reserved UUID sentinels, and cross-tenant confused-deputy contexts are rejected before protected values are returned. Authorization requests and allow/deny evidence now also require and preserve one namespaced opaque target-resource reference, so immutable audit correlation identifies the exact HR record without copying its protected values. Authorization evidence otherwise contains governance metadata and field names only, with stable denial reasons and actionable next steps rather than PII. - LLM output constrained to draft evidence. diff --git a/manifest.json b/manifest.json index d4f24b65a..a5e906cff 100644 --- a/manifest.json +++ b/manifest.json @@ -29,8 +29,8 @@ }, { "path": "CHANGELOG.md", - "sha256": "d09d9e02cf8f952518ac2f03bb2826bec32fe219c136347803cceebc98144ea8", - "bytes": 19065, + "sha256": "58342a98de09c87f2af451be4ba7426674dabb0cc993bd9d247168596b0402fc", + "bytes": 18915, "lines": 80 }, { diff --git a/services/workforce-validation-api/tests/test_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_view_issuance_integrity.py index 5a24c6256..a935bcd18 100644 --- a/services/workforce-validation-api/tests/test_view_issuance_integrity.py +++ b/services/workforce-validation-api/tests/test_view_issuance_integrity.py @@ -21,47 +21,49 @@ def test_direct_authorized_view_construction_fails_closed() -> None: ) -def test_low_level_tuple_construction_cannot_expose_authorized_view() -> None: - """Reject base-constructor views before or at public projection access.""" - payloads = ( - ( - TENANT.int, - STUDY.int, - (("study_status_code", "study_closed"),), - ), - ( - object(), - TENANT.int, - STUDY.int, - (("study_status_code", "study_closed"),), - ), - ) - - for payload in payloads: - try: - forged = tuple.__new__(registry.ValidityStudyView, payload) - except TypeError: - continue - for attribute in ("tenant_record_id", "validity_study_id", "fields"): - with pytest.raises( - registry.ValidityStudyIntegrityError, - match="was not issued by read_validity_study", - ): - getattr(forged, attribute) - - -def test_unsealed_object_allocation_cannot_expose_authorized_view() -> None: - """Require the read-path seal even for a raw exact-runtime object allocation.""" +def test_registry_module_exposes_no_unconditional_view_issuer() -> None: + """Keep ordinary view issuance inside the authorized read application path.""" + assert not hasattr(registry, "_issue_validity_study_view") + + +def test_low_level_tuple_construction_cannot_issue_study_view() -> None: + """Remove tuple's base constructor as an alternate authorized-view issuer.""" + with pytest.raises(TypeError): + tuple.__new__( + registry.ValidityStudyView, + (TENANT.int, STUDY.int, (("study_status_code", "study_draft"),)), + ) + + +def test_unsealed_object_allocation_cannot_expose_study_view() -> None: + """Require the read-path seal before raw exact-runtime objects expose state.""" unsealed = object.__new__(registry.ValidityStudyView) - for attribute in ("tenant_record_id", "validity_study_id", "fields"): + for attribute_name in ("tenant_record_id", "validity_study_id", "fields"): with pytest.raises( registry.ValidityStudyIntegrityError, match="was not issued by read_validity_study", ): - getattr(unsealed, attribute) + getattr(unsealed, attribute_name) -def test_registry_module_exposes_no_unconditional_view_issuer() -> None: - """Keep ordinary view issuance inside the authorized read application path.""" - assert not hasattr(registry, "_issue_validity_study_view") +def test_wrong_issuance_marker_cannot_expose_study_view() -> None: + """Reject marker-shaped objects that did not originate from the read path.""" + forged_view = object.__new__(registry.ValidityStudyView) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises( + registry.ValidityStudyIntegrityError, + match="was not issued by read_validity_study", + ): + _ = forged_view.fields + + +def test_raw_study_view_rejects_mutation_and_deletion() -> None: + """Keep projection state immutable after raw exact-runtime allocation.""" + raw_view = object.__new__(registry.ValidityStudyView) + + with pytest.raises(AttributeError, match="immutable"): + raw_view._fields = () + with pytest.raises(AttributeError, match="immutable"): + del raw_view._fields From 721f847a018e3a0cf52cd008aa70d86396dea5c6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 04:03:54 +0900 Subject: [PATCH 537/603] test(workforce-validation): expose module-level view sealing capability --- .../test_authorized_view_seal_capability.py | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_authorized_view_seal_capability.py diff --git a/services/workforce-validation-api/tests/test_authorized_view_seal_capability.py b/services/workforce-validation-api/tests/test_authorized_view_seal_capability.py new file mode 100644 index 000000000..8a273ac34 --- /dev/null +++ b/services/workforce-validation-api/tests/test_authorized_view_seal_capability.py @@ -0,0 +1,51 @@ +"""Reject module-exposed capabilities that can mint authorized public views.""" + +from __future__ import annotations + +from inspect import getmodule +from uuid import UUID + +import pytest + +import orgmetra_workforce_validation_api as api +from orgmetra_workforce_validation_api import registry + + +TENANT = UUID("11111111-1111-4111-8111-111111111111") +STUDY = UUID("22222222-2222-4222-8222-222222222222") + + +def test_public_authorized_view_modules_expose_no_issuance_marker_capability() -> None: + """Keep view-sealing write capabilities out of ordinary module state.""" + for name in sorted(item for item in api.__all__ if item.endswith("View")): + view_type = getattr(api, name) + module = getmodule(view_type) + assert module is not None + exposed = tuple( + sorted(key for key in vars(module) if key.endswith("_ISSUANCE_MARKER")) + ) + assert exposed == (), f"{name} owner module exposes issuance markers: {exposed!r}" + + +def test_registry_module_marker_cannot_mint_authorized_projection() -> None: + """Reject a raw view whose caller fills slots with any importable marker-like value.""" + forged = object.__new__(registry.ValidityStudyView) + object.__setattr__(forged, "_tenant_identity", TENANT.int) + object.__setattr__(forged, "_study_identity", STUDY.int) + object.__setattr__( + forged, + "_fields", + (("study_status_code", "study_closed"),), + ) + caller_marker = getattr( + registry, + "_VALIDITY_STUDY_VIEW_ISSUANCE_MARKER", + object(), + ) + object.__setattr__(forged, "_issuance_marker", caller_marker) + + with pytest.raises( + registry.ValidityStudyIntegrityError, + match="was not issued by read_validity_study", + ): + _ = forged.fields From d5d847e1baa7142f0ed5422aad777be44424fd0f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 04:05:20 +0900 Subject: [PATCH 538/603] fix(workforce-validation): hide registry view sealing capability --- .../registry.py | 88 +++++++++++++------ 1 file changed, 63 insertions(+), 25 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py index f7825de3f..8c08bb2c3 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -37,7 +37,6 @@ "recorded_to", } ) -_VALIDITY_STUDY_VIEW_ISSUANCE_MARKER = object() class ValidityStudyNotFound(LookupError): @@ -300,10 +299,10 @@ class ValidityStudyView: """Sealed field-minimized data view returned only after authorization. The public constructor is deliberately non-issuing. A raw object allocation - remains unusable because every public property verifies the private read-path - seal before exposing detached projection state. The runtime type is still - data, not a reusable authorization credential; consequential actions must - re-authorize and re-resolve owner truth. + remains unusable because every public property verifies closure-private + read-path issuance before exposing detached projection state. The runtime type + is still data, not a reusable authorization credential; consequential actions + must re-authorize and re-resolve owner truth. """ __slots__ = ("_tenant_identity", "_study_identity", "_fields", "_issuance_marker") @@ -328,16 +327,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject raw exact-runtime allocations that were not sealed by the read path.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise ValidityStudyIntegrityError( - "validity-study view was not issued by read_validity_study" - ) from exc - if marker is not _VALIDITY_STUDY_VIEW_ISSUANCE_MARKER: - raise ValidityStudyIntegrityError( - "validity-study view was not issued by read_validity_study" - ) + _require_validity_study_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -379,7 +369,7 @@ def read_validity_study( _PROTOCOL_READ_CAPABILITY = getattr_static(ValidityStudyReadPort, "read_validity_study") -def read_validity_study( +def _read_validity_study_authorized_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -388,8 +378,8 @@ def read_validity_study( requested_fields: frozenset[str], policy: PurposeBoundAccessPolicy, read_port: ValidityStudyReadPort, -) -> ValidityStudyView: - """Authorize and read one validity-study header through the canonical owner port. +) -> tuple[int, int, tuple[tuple[str, object], ...]]: + """Authorize and resolve one study into inert state without issuing a public view. Authorization is completed before persistence. The exact ordinary repository method is captured inertly before authorization and that same function is @@ -397,7 +387,7 @@ def read_validity_study( validated capability. Immutable integer snapshots preserve the authorized target across the executable repository call. The persistence result is reconstructed into an exact immutable value and must match those snapshots - before any field is returned. + before projected state is returned to the closure-private issuer. """ if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") @@ -478,9 +468,57 @@ def read_validity_study( "recorded_to": record.recorded_to, } projected_fields = tuple((field_name, values[field_name]) for field_name in sorted(fields)) - view = object.__new__(ValidityStudyView) - object.__setattr__(view, "_tenant_identity", tenant_identity) - object.__setattr__(view, "_study_identity", study_identity) - object.__setattr__(view, "_fields", _store_view_fields(projected_fields)) - object.__setattr__(view, "_issuance_marker", _VALIDITY_STUDY_VIEW_ISSUANCE_MARKER) - return view + return tenant_identity, study_identity, _store_view_fields(projected_fields) + + +def _build_validity_study_view_runtime(): + """Create closure-private sealing state and the only supported public issuer.""" + issuance_marker = object() + + def require_issued(view: ValidityStudyView) -> None: + """Verify one view against the closure-private issuance capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise ValidityStudyIntegrityError( + "validity-study view was not issued by read_validity_study" + ) from exc + if marker is not issuance_marker: + raise ValidityStudyIntegrityError( + "validity-study view was not issued by read_validity_study" + ) + + def issue_after_authorized_read( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + purpose_code: str, + requested_fields: frozenset[str], + policy: PurposeBoundAccessPolicy, + read_port: ValidityStudyReadPort, + ) -> ValidityStudyView: + """Issue one sealed view only after the canonical authorized owner read succeeds.""" + tenant_identity, study_identity, projected_fields = ( + _read_validity_study_authorized_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + purpose_code=purpose_code, + requested_fields=requested_fields, + policy=policy, + read_port=read_port, + ) + ) + view = object.__new__(ValidityStudyView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", projected_fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, issue_after_authorized_read + + +_require_validity_study_view_issued, read_validity_study = _build_validity_study_view_runtime() +del _build_validity_study_view_runtime From a27f50d12ccca27ca3b6c0e4a184fc32e1a31888 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 04:09:58 +0900 Subject: [PATCH 539/603] test(workforce-validation): expose component-resolution seal capability --- ...nent_evidence_issuance_marker_integrity.py | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_issuance_marker_integrity.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_issuance_marker_integrity.py index 91d404cd3..6eb5c73b2 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_issuance_marker_integrity.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_issuance_marker_integrity.py @@ -12,6 +12,37 @@ from test_final_weight_component_evidence_resolution_low_level_issuance import _base_evidence +def test_resolution_module_exposes_no_issuance_marker_capability() -> None: + """Keep proof-result sealing authority out of ordinary module state.""" + assert not hasattr(resolution_module, "_RESOLUTION_ISSUANCE_MARKER") + + +def test_importable_marker_cannot_mint_proof_bearing_resolution() -> None: + """Reject caller-populated proof slots even when a module marker is obtainable.""" + forged = object.__new__(FinalWeightComponentEvidenceResolution) + object.__setattr__( + forged, + "_FinalWeightComponentEvidenceResolution__base_weight", + _base_evidence(), + ) + object.__setattr__( + forged, + "_FinalWeightComponentEvidenceResolution__adjustments", + (), + ) + caller_marker = getattr(resolution_module, "_RESOLUTION_ISSUANCE_MARKER", object()) + object.__setattr__( + forged, + "_FinalWeightComponentEvidenceResolution__issuance_marker", + caller_marker, + ) + + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="not issued"): + _ = forged.base_weight + with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="not issued"): + _ = forged.adjustments + + def test_wrong_private_issuance_marker_cannot_expose_proof_properties() -> None: """Fail closed when hostile allocation populates a marker that is not the canonical seal.""" forged = object.__new__(FinalWeightComponentEvidenceResolution) From dbc2f013062f1aba7b95c316e88f3dfcddfdd079 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 04:15:33 +0900 Subject: [PATCH 540/603] fix(workforce-validation): hide component proof sealing capability Move component-resolution issuance state into a closure whose public entry point performs the complete purpose-bound authorization and canonical owner corroboration. Remove the importable seal and generic module-level proof issuer; retain fail-closed raw allocation and immutable result semantics. Refs #422. --- ...al_weight_component_evidence_resolution.py | 129 ++++++++++-------- ...nent_evidence_issuance_marker_integrity.py | 25 +--- 2 files changed, 76 insertions(+), 78 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py index a679d7928..44e821ab2 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py @@ -82,9 +82,6 @@ "superseded_at", } ) -_RESOLUTION_ISSUANCE_MARKER = object() - - class FinalWeightComponentEvidenceNotFound(LookupError): """Indicate that exact authoritative evidence cannot be deterministically resolved.""" @@ -368,19 +365,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Fail closed when generic allocation produced an unsealed exact runtime object.""" - try: - marker = object.__getattribute__( - self, - "_FinalWeightComponentEvidenceResolution__issuance_marker", - ) - except AttributeError as exc: - raise FinalWeightComponentEvidenceIntegrityError( - "component evidence resolution was not issued by canonical corroboration" - ) from exc - if marker is not _RESOLUTION_ISSUANCE_MARKER: - raise FinalWeightComponentEvidenceIntegrityError( - "component evidence resolution was not issued by canonical corroboration" - ) + _require_component_evidence_resolution_issued(self) @property def base_weight(self) -> BaseWeightComponentEvidence: @@ -532,39 +517,6 @@ def _canonical_base_evidence(value: object) -> BaseWeightComponentEvidence: return canonical -def _issue_component_evidence_resolution( - *, - base_weight: BaseWeightComponentEvidence, - adjustments: tuple[AdjustmentComponentEvidence, ...], -) -> FinalWeightComponentEvidenceResolution: - """Issue a sealed proof-bearing aggregate only from already corroborated canonical evidence.""" - canonical_base = _canonical_base_evidence(base_weight) - if type(adjustments) is not tuple: - raise FinalWeightComponentEvidenceIntegrityError( - "corroborated adjustments must be an immutable tuple" - ) - canonical_adjustments = tuple( - _canonical_adjustment_evidence(adjustment) for adjustment in adjustments - ) - resolution = object.__new__(FinalWeightComponentEvidenceResolution) - object.__setattr__( - resolution, - "_FinalWeightComponentEvidenceResolution__base_weight", - canonical_base, - ) - object.__setattr__( - resolution, - "_FinalWeightComponentEvidenceResolution__adjustments", - canonical_adjustments, - ) - object.__setattr__( - resolution, - "_FinalWeightComponentEvidenceResolution__issuance_marker", - _RESOLUTION_ISSUANCE_MARKER, - ) - return resolution - - def _canonical_final_weight(value: object) -> FinalAnalysisWeightAuthorityRecord: """Reconstruct final-weight authority before any cross-owner comparison.""" if type(value) is not FinalAnalysisWeightAuthorityRecord: @@ -662,7 +614,7 @@ def _require_component_current_at_use( ) -def corroborate_final_weight_component_evidence( +def _corroborate_final_weight_component_evidence_state( *, principal: ValidationPrincipal, final_weight: FinalAnalysisWeightAuthorityRecord, @@ -671,8 +623,8 @@ def corroborate_final_weight_component_evidence( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: FinalWeightComponentEvidenceReadPort, -) -> FinalWeightComponentEvidenceResolution: - """Authorize, owner-resolve final/binding authority, and corroborate component evidence.""" +) -> tuple[BaseWeightComponentEvidence, tuple[AdjustmentComponentEvidence, ...]]: + """Authorize and corroborate canonical component evidence into inert state.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") if type(policy) is not PurposeBoundAccessPolicy: @@ -945,7 +897,72 @@ def corroborate_final_weight_component_evidence( ) resolved_adjustments.append(component) - return _issue_component_evidence_resolution( - base_weight=base, - adjustments=tuple(resolved_adjustments), - ) + return base, tuple(resolved_adjustments) + + +def _build_component_evidence_resolution_runtime(): + """Create closure-private sealing state and the authorized public corroborator.""" + issuance_marker = object() + + def require_issued(resolution: FinalWeightComponentEvidenceResolution) -> None: + """Verify one proof result against the closure-private issuance capability.""" + try: + marker = object.__getattribute__( + resolution, + "_FinalWeightComponentEvidenceResolution__issuance_marker", + ) + except AttributeError as exc: + raise FinalWeightComponentEvidenceIntegrityError( + "component evidence resolution was not issued by canonical corroboration" + ) from exc + if marker is not issuance_marker: + raise FinalWeightComponentEvidenceIntegrityError( + "component evidence resolution was not issued by canonical corroboration" + ) + + def corroborate( + *, + principal: ValidationPrincipal, + final_weight: FinalAnalysisWeightAuthorityRecord, + binding: FinalWeightComponentBindingAuthorityRecord, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: FinalWeightComponentEvidenceReadPort, + ) -> FinalWeightComponentEvidenceResolution: + """Authorize, owner-resolve authority, and issue sealed component evidence.""" + base_weight, adjustments = _corroborate_final_weight_component_evidence_state( + principal=principal, + final_weight=final_weight, + binding=binding, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + resolution = object.__new__(FinalWeightComponentEvidenceResolution) + object.__setattr__( + resolution, + "_FinalWeightComponentEvidenceResolution__base_weight", + base_weight, + ) + object.__setattr__( + resolution, + "_FinalWeightComponentEvidenceResolution__adjustments", + adjustments, + ) + object.__setattr__( + resolution, + "_FinalWeightComponentEvidenceResolution__issuance_marker", + issuance_marker, + ) + return resolution + + return require_issued, corroborate + + +( + _require_component_evidence_resolution_issued, + corroborate_final_weight_component_evidence, +) = _build_component_evidence_resolution_runtime() +del _build_component_evidence_resolution_runtime diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_issuance_marker_integrity.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_issuance_marker_integrity.py index 6eb5c73b2..3d219d849 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_issuance_marker_integrity.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_issuance_marker_integrity.py @@ -58,25 +58,6 @@ def test_wrong_private_issuance_marker_cannot_expose_proof_properties() -> None: _ = forged.adjustments -def test_private_issuer_rejects_mutable_adjustment_collection() -> None: - """Keep the internal proof issuer fail-closed if a future caller passes mutable state.""" - with pytest.raises( - FinalWeightComponentEvidenceIntegrityError, - match="immutable tuple", - ): - resolution_module._issue_component_evidence_resolution( - base_weight=_base_evidence(), - adjustments=[], # type: ignore[arg-type] - ) - - -def test_private_issuer_rejects_noncanonical_adjustment_member() -> None: - """Reject an immutable container whose member is not canonical adjustment evidence.""" - with pytest.raises( - FinalWeightComponentEvidenceIntegrityError, - match="non-canonical specialized evidence", - ): - resolution_module._issue_component_evidence_resolution( - base_weight=_base_evidence(), - adjustments=(object(),), # type: ignore[arg-type] - ) +def test_resolution_module_exposes_no_generic_private_issuer() -> None: + """Keep generic proof-result minting outside ordinary module state.""" + assert not hasattr(resolution_module, "_issue_component_evidence_resolution") From e190f686f42ffa4abad17b7867b7165cab49c832 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 04:19:11 +0900 Subject: [PATCH 541/603] fix(workforce-validation): hide base-weight view seal Move BaseWeightAuthorityView issuance state into a closure-private runtime and keep the public resolver as the only issuer after its existing authorization and canonical owner corroboration. Add a marker-copy regression contract. Refs #421. --- .../base_weight_authority.py | 125 ++++++++++++++---- ...eight_authority_view_issuance_integrity.py | 29 ++++ 2 files changed, 127 insertions(+), 27 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py index 6b50844dd..580a1fd70 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_authority.py @@ -72,9 +72,6 @@ "owner_contract_released_at", } ) -_BASE_WEIGHT_AUTHORITY_VIEW_ISSUANCE_MARKER = object() - - class BaseWeightAuthorityNotFound(LookupError): """Indicate that no released owner evidence corroborates the base weight.""" @@ -289,16 +286,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject exact-runtime allocations that were not sealed by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise BaseWeightAuthorityIntegrityError( - "base-weight authority view was not issued by resolve_base_weight_authority" - ) from exc - if marker is not _BASE_WEIGHT_AUTHORITY_VIEW_ISSUANCE_MARKER: - raise BaseWeightAuthorityIntegrityError( - "base-weight authority view was not issued by resolve_base_weight_authority" - ) + _require_base_weight_authority_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -361,7 +349,7 @@ def read_base_weight_authority( ) -def resolve_base_weight_authority( +def _resolve_base_weight_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -389,8 +377,8 @@ def resolve_base_weight_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: BaseWeightAuthorityReadPort, -) -> BaseWeightAuthorityView: - """Authorize then corroborate released stage-wise base-weight evidence.""" +) -> tuple[int, int, tuple[tuple[str, object], ...]]: + """Authorize and corroborate base-weight evidence into inert projection state.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") if type(policy) is not PurposeBoundAccessPolicy: @@ -557,20 +545,103 @@ def resolve_base_weight_authority( values["released_at"] = record.released_at values["superseded_at"] = record.superseded_at fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) - view = object.__new__(BaseWeightAuthorityView) - object.__setattr__( - view, - "_tenant_identity", + return ( _store_operational_uuid("tenant_record_id", record.tenant_record_id), - ) - object.__setattr__( - view, - "_study_identity", _store_operational_uuid("validity_study_id", record.validity_study_id), + fields, ) - object.__setattr__(view, "_fields", fields) - object.__setattr__(view, "_issuance_marker", _BASE_WEIGHT_AUTHORITY_VIEW_ISSUANCE_MARKER) - return view + + +def _build_base_weight_authority_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: BaseWeightAuthorityView) -> None: + """Verify one base-weight view against the closure-private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise BaseWeightAuthorityIntegrityError( + "base-weight authority view was not issued by resolve_base_weight_authority" + ) from exc + if marker is not issuance_marker: + raise BaseWeightAuthorityIntegrityError( + "base-weight authority view was not issued by resolve_base_weight_authority" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + base_weight_evidence_receipt_reference: str, + base_weight_evidence_receipt_digest: str, + evidence_version: int, + source_universe_receipt_reference: str, + source_universe_receipt_version: int, + source_universe_receipt_digest: str, + sampling_design_receipt_reference: str, + sampling_design_receipt_version: int, + sampling_design_receipt_digest: str, + sampled_occurrence_set_digest: str, + selection_probability_set_digest: str, + selection_stage_count: int, + base_weight_method_code: str, + base_weight_method_version: int, + base_weight_artifact_digest: str, + constructed_at: datetime, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: BaseWeightAuthorityReadPort, + ) -> BaseWeightAuthorityView: + """Authorize then corroborate released stage-wise base-weight evidence.""" + tenant_identity, study_identity, fields = _resolve_base_weight_authority_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + base_weight_evidence_receipt_reference=base_weight_evidence_receipt_reference, + base_weight_evidence_receipt_digest=base_weight_evidence_receipt_digest, + evidence_version=evidence_version, + source_universe_receipt_reference=source_universe_receipt_reference, + source_universe_receipt_version=source_universe_receipt_version, + source_universe_receipt_digest=source_universe_receipt_digest, + sampling_design_receipt_reference=sampling_design_receipt_reference, + sampling_design_receipt_version=sampling_design_receipt_version, + sampling_design_receipt_digest=sampling_design_receipt_digest, + sampled_occurrence_set_digest=sampled_occurrence_set_digest, + selection_probability_set_digest=selection_probability_set_digest, + selection_stage_count=selection_stage_count, + base_weight_method_code=base_weight_method_code, + base_weight_method_version=base_weight_method_version, + base_weight_artifact_digest=base_weight_artifact_digest, + constructed_at=constructed_at, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + view = object.__new__(BaseWeightAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_base_weight_authority_view_issued, + resolve_base_weight_authority, +) = _build_base_weight_authority_view_runtime() +del _build_base_weight_authority_view_runtime __all__ = [ diff --git a/services/workforce-validation-api/tests/test_base_weight_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_base_weight_authority_view_issuance_integrity.py index ee69baacc..1a181adaa 100644 --- a/services/workforce-validation-api/tests/test_base_weight_authority_view_issuance_integrity.py +++ b/services/workforce-validation-api/tests/test_base_weight_authority_view_issuance_integrity.py @@ -4,6 +4,7 @@ import pytest +import orgmetra_workforce_validation_api.base_weight_authority as authority_module from orgmetra_workforce_validation_api.base_weight_authority import ( BaseWeightAuthorityIntegrityError, BaseWeightAuthorityView, @@ -51,6 +52,34 @@ def test_wrong_issuance_marker_cannot_expose_base_weight_view() -> None: _ = forged.fields +def test_importable_marker_cannot_mint_base_weight_view() -> None: + """Reject a caller-populated view and keep its sealing capability out of module state.""" + assert not hasattr(authority_module, "_BASE_WEIGHT_AUTHORITY_VIEW_ISSUANCE_MARKER") + forged = object.__new__(BaseWeightAuthorityView) + object.__setattr__(forged, "_tenant_identity", TENANT.int) + object.__setattr__(forged, "_study_identity", STUDY.int) + object.__setattr__( + forged, + "_fields", + (("base_weight_artifact_digest", "6" * 64),), + ) + object.__setattr__( + forged, + "_issuance_marker", + getattr( + authority_module, + "_BASE_WEIGHT_AUTHORITY_VIEW_ISSUANCE_MARKER", + object(), + ), + ) + + with pytest.raises( + BaseWeightAuthorityIntegrityError, + match="was not issued by resolve_base_weight_authority", + ): + _ = forged.fields + + def test_raw_base_weight_view_rejects_public_mutation_and_deletion() -> None: """Keep projection state immutable even when callers allocate the exact runtime type.""" raw = object.__new__(BaseWeightAuthorityView) From 90e99e2469bd40cc5fb8d523408d1c496bcc3546 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 04:22:12 +0900 Subject: [PATCH 542/603] fix(workforce-validation): hide base-weight supersession seal Move BaseWeightSupersessionAuthorityView issuance state into a closure-private runtime while preserving the authorized canonical owner resolution path. Add a hostile marker-copy regression contract. Refs #421. --- .../base_weight_supersession_authority.py | 109 +++++++++++++----- ...ssion_authority_view_issuance_integrity.py | 32 +++++ 2 files changed, 110 insertions(+), 31 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_supersession_authority.py index 048f1ae26..ee04e7867 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/base_weight_supersession_authority.py @@ -37,7 +37,6 @@ _RESOURCE_KIND = "base_weight_supersession_authority" _OPERATION = "read" -_BASE_WEIGHT_SUPERSESSION_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "base_weight_evidence_receipt_reference", @@ -260,18 +259,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject exact-runtime allocations not sealed by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise BaseWeightSupersessionAuthorityIntegrityError( - "base-weight supersession view was not issued by " - "resolve_base_weight_supersession_authority" - ) from exc - if marker is not _BASE_WEIGHT_SUPERSESSION_VIEW_ISSUANCE_MARKER: - raise BaseWeightSupersessionAuthorityIntegrityError( - "base-weight supersession view was not issued by " - "resolve_base_weight_supersession_authority" - ) + _require_base_weight_supersession_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -322,7 +310,7 @@ def read_base_weight_supersession_authority( ) -def resolve_base_weight_supersession_authority( +def _resolve_base_weight_supersession_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -337,8 +325,8 @@ def resolve_base_weight_supersession_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: BaseWeightSupersessionAuthorityReadPort, -) -> BaseWeightSupersessionAuthorityView: - """Authorize then resolve the base-weight receipt's append-only authority interval.""" +) -> tuple[int, int, tuple[tuple[str, object], ...]]: + """Authorize and resolve base-weight supersession into inert projection state.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") if type(policy) is not PurposeBoundAccessPolicy: @@ -503,24 +491,83 @@ def resolve_base_weight_supersession_authority( ("released_at", record.released_at), ("superseded_at", record.superseded_at), ) - view = object.__new__(BaseWeightSupersessionAuthorityView) - object.__setattr__( - view, - "_tenant_identity", + return ( _store_operational_uuid("tenant_record_id", record.tenant_record_id), - ) - object.__setattr__( - view, - "_study_identity", _store_operational_uuid("validity_study_id", record.validity_study_id), + fields, ) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, - "_issuance_marker", - _BASE_WEIGHT_SUPERSESSION_VIEW_ISSUANCE_MARKER, - ) - return view + + +def _build_base_weight_supersession_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: BaseWeightSupersessionAuthorityView) -> None: + """Verify one supersession view against the closure-private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise BaseWeightSupersessionAuthorityIntegrityError( + "base-weight supersession view was not issued by " + "resolve_base_weight_supersession_authority" + ) from exc + if marker is not issuance_marker: + raise BaseWeightSupersessionAuthorityIntegrityError( + "base-weight supersession view was not issued by " + "resolve_base_weight_supersession_authority" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + base_weight_evidence_receipt_reference: str, + base_weight_evidence_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: BaseWeightSupersessionAuthorityReadPort, + ) -> BaseWeightSupersessionAuthorityView: + """Authorize then resolve the base-weight receipt authority interval.""" + tenant_identity, study_identity, fields = ( + _resolve_base_weight_supersession_authority_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + base_weight_evidence_receipt_reference=( + base_weight_evidence_receipt_reference + ), + base_weight_evidence_receipt_digest=base_weight_evidence_receipt_digest, + evidence_version=evidence_version, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + ) + view = object.__new__(BaseWeightSupersessionAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_base_weight_supersession_view_issued, + resolve_base_weight_supersession_authority, +) = _build_base_weight_supersession_view_runtime() +del _build_base_weight_supersession_view_runtime __all__ = [ diff --git a/services/workforce-validation-api/tests/test_base_weight_supersession_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_base_weight_supersession_authority_view_issuance_integrity.py index 91c660461..77359e337 100644 --- a/services/workforce-validation-api/tests/test_base_weight_supersession_authority_view_issuance_integrity.py +++ b/services/workforce-validation-api/tests/test_base_weight_supersession_authority_view_issuance_integrity.py @@ -4,6 +4,7 @@ import pytest +import orgmetra_workforce_validation_api.base_weight_supersession_authority as authority_module from orgmetra_workforce_validation_api.base_weight_supersession_authority import ( BaseWeightSupersessionAuthorityIntegrityError, BaseWeightSupersessionAuthorityView, @@ -51,6 +52,37 @@ def test_wrong_issuance_marker_cannot_expose_supersession_view() -> None: _ = forged_view.fields +def test_importable_marker_cannot_mint_supersession_view() -> None: + """Keep view-sealing authority out of ordinary module state.""" + assert not hasattr( + authority_module, + "_BASE_WEIGHT_SUPERSESSION_VIEW_ISSUANCE_MARKER", + ) + forged_view = object.__new__(BaseWeightSupersessionAuthorityView) + object.__setattr__(forged_view, "_tenant_identity", TENANT.int) + object.__setattr__(forged_view, "_study_identity", STUDY.int) + object.__setattr__( + forged_view, + "_fields", + (("base_weight_evidence_receipt_digest", "6" * 64),), + ) + object.__setattr__( + forged_view, + "_issuance_marker", + getattr( + authority_module, + "_BASE_WEIGHT_SUPERSESSION_VIEW_ISSUANCE_MARKER", + object(), + ), + ) + + with pytest.raises( + BaseWeightSupersessionAuthorityIntegrityError, + match="was not issued by resolve_base_weight_supersession_authority", + ): + _ = forged_view.fields + + def test_raw_supersession_view_rejects_mutation_and_deletion() -> None: """Keep projection state immutable after raw exact-runtime allocation.""" raw_view = object.__new__(BaseWeightSupersessionAuthorityView) From f4606c914832c226aa0c26cbebd4c9b9c889d1cc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 04:59:37 +0900 Subject: [PATCH 543/603] test(workforce-validation): prove calibration supersession seal leak --- ...rsession_authority_view_seal_capability.py | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_calibration_adjustment_supersession_authority_view_seal_capability.py diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_authority_view_seal_capability.py b/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_authority_view_seal_capability.py new file mode 100644 index 000000000..1c4aad7a5 --- /dev/null +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_supersession_authority_view_seal_capability.py @@ -0,0 +1,58 @@ +"""Hostile sealing-capability regression for calibration supersession views.""" + +from uuid import UUID + +import pytest + +import orgmetra_workforce_validation_api.calibration_adjustment_supersession_authority as authority_module +from orgmetra_workforce_validation_api.calibration_adjustment_supersession_authority import ( + CalibrationAdjustmentSupersessionAuthorityIntegrityError, + CalibrationAdjustmentSupersessionAuthorityView, +) + +TENANT = UUID("00000000-0000-0000-0000-000000000421") +STUDY = UUID("00000000-0000-0000-0000-000000000422") + + +def _raw_view_with_module_marker() -> CalibrationAdjustmentSupersessionAuthorityView: + """Build the strongest caller-owned exact-runtime forgery available from module state.""" + view = object.__new__(CalibrationAdjustmentSupersessionAuthorityView) + object.__setattr__(view, "_tenant_identity", TENANT.int) + object.__setattr__(view, "_study_identity", STUDY.int) + object.__setattr__( + view, + "_fields", + (("calibration_receipt_digest", "a" * 64),), + ) + object.__setattr__( + view, + "_issuance_marker", + getattr( + authority_module, + "_CALIBRATION_ADJUSTMENT_SUPERSESSION_VIEW_ISSUANCE_MARKER", + object(), + ), + ) + return view + + +def test_module_exposes_no_calibration_supersession_view_seal() -> None: + """Keep the write capability out of ordinary importable module state.""" + assert not hasattr( + authority_module, + "_CALIBRATION_ADJUSTMENT_SUPERSESSION_VIEW_ISSUANCE_MARKER", + ) + + +def test_importable_marker_cannot_mint_calibration_supersession_view() -> None: + """Require caller-populated exact objects to remain unreadable.""" + forged_view = _raw_view_with_module_marker() + + with pytest.raises( + CalibrationAdjustmentSupersessionAuthorityIntegrityError, + match=( + "calibration-adjustment supersession view was not issued by " + "resolve_calibration_adjustment_supersession_authority" + ), + ): + _ = forged_view.fields From 5779384da2cbdb7b325ff851963c2407301f851d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 05:00:37 +0900 Subject: [PATCH 544/603] fix(workforce-validation): hide calibration supersession seal --- ...ation_adjustment_supersession_authority.py | 111 ++++++++++++------ 1 file changed, 78 insertions(+), 33 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_supersession_authority.py index 1902b36b3..fe29d7caf 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_supersession_authority.py @@ -37,7 +37,6 @@ _RESOURCE_KIND = "calibration_adjustment_supersession_authority" _OPERATION = "read" -_CALIBRATION_ADJUSTMENT_SUPERSESSION_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "calibration_receipt_reference", @@ -260,18 +259,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject exact-runtime allocations not sealed by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise CalibrationAdjustmentSupersessionAuthorityIntegrityError( - "calibration-adjustment supersession view was not issued by " - "resolve_calibration_adjustment_supersession_authority" - ) from exc - if marker is not _CALIBRATION_ADJUSTMENT_SUPERSESSION_VIEW_ISSUANCE_MARKER: - raise CalibrationAdjustmentSupersessionAuthorityIntegrityError( - "calibration-adjustment supersession view was not issued by " - "resolve_calibration_adjustment_supersession_authority" - ) + _require_calibration_adjustment_supersession_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -322,7 +310,7 @@ def read_calibration_adjustment_supersession_authority( ) -def resolve_calibration_adjustment_supersession_authority( +def _resolve_calibration_adjustment_supersession_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -337,8 +325,8 @@ def resolve_calibration_adjustment_supersession_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: CalibrationAdjustmentSupersessionAuthorityReadPort, -) -> CalibrationAdjustmentSupersessionAuthorityView: - """Authorize then resolve the receipt's half-open append-only authority interval.""" +) -> tuple[int, int, tuple[tuple[str, object], ...]]: + """Authorize and resolve calibration supersession into inert projection state.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") if type(policy) is not PurposeBoundAccessPolicy: @@ -500,21 +488,78 @@ def resolve_calibration_adjustment_supersession_authority( ("released_at", record.released_at), ("superseded_at", record.superseded_at), ) - view = object.__new__(CalibrationAdjustmentSupersessionAuthorityView) - object.__setattr__( - view, - "_tenant_identity", - _store_operational_uuid("tenant_record_id", tenant_id), - ) - object.__setattr__( - view, - "_study_identity", - _store_operational_uuid("validity_study_id", study_id), + return ( + _store_operational_uuid("tenant_record_id", record.tenant_record_id), + _store_operational_uuid("validity_study_id", record.validity_study_id), + fields, ) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, - "_issuance_marker", - _CALIBRATION_ADJUSTMENT_SUPERSESSION_VIEW_ISSUANCE_MARKER, - ) - return view + + +def _build_calibration_adjustment_supersession_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: CalibrationAdjustmentSupersessionAuthorityView) -> None: + """Verify one supersession view against the closure-private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise CalibrationAdjustmentSupersessionAuthorityIntegrityError( + "calibration-adjustment supersession view was not issued by " + "resolve_calibration_adjustment_supersession_authority" + ) from exc + if marker is not issuance_marker: + raise CalibrationAdjustmentSupersessionAuthorityIntegrityError( + "calibration-adjustment supersession view was not issued by " + "resolve_calibration_adjustment_supersession_authority" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + calibration_receipt_reference: str, + calibration_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: CalibrationAdjustmentSupersessionAuthorityReadPort, + ) -> CalibrationAdjustmentSupersessionAuthorityView: + """Authorize then resolve the calibration receipt authority interval.""" + tenant_identity, study_identity, fields = ( + _resolve_calibration_adjustment_supersession_authority_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + calibration_receipt_reference=calibration_receipt_reference, + calibration_receipt_digest=calibration_receipt_digest, + evidence_version=evidence_version, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + ) + view = object.__new__(CalibrationAdjustmentSupersessionAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_calibration_adjustment_supersession_view_issued, + resolve_calibration_adjustment_supersession_authority, +) = _build_calibration_adjustment_supersession_view_runtime() +del _build_calibration_adjustment_supersession_view_runtime From 025c5ac08c0c5955c6c8e0fe63e6506800f6225c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 05:02:32 +0900 Subject: [PATCH 545/603] test(workforce-validation): prove nonresponse supersession seal leak --- ...rsession_authority_view_seal_capability.py | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_authority_view_seal_capability.py diff --git a/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_authority_view_seal_capability.py b/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_authority_view_seal_capability.py new file mode 100644 index 000000000..600bd0002 --- /dev/null +++ b/services/workforce-validation-api/tests/test_nonresponse_adjustment_supersession_authority_view_seal_capability.py @@ -0,0 +1,58 @@ +"""Hostile sealing-capability regression for nonresponse supersession views.""" + +from uuid import UUID + +import pytest + +import orgmetra_workforce_validation_api.nonresponse_adjustment_supersession_authority as authority_module +from orgmetra_workforce_validation_api.nonresponse_adjustment_supersession_authority import ( + NonresponseAdjustmentSupersessionAuthorityIntegrityError, + NonresponseAdjustmentSupersessionAuthorityView, +) + +TENANT = UUID("00000000-0000-0000-0000-000000000423") +STUDY = UUID("00000000-0000-0000-0000-000000000424") + + +def _raw_view_with_module_marker() -> NonresponseAdjustmentSupersessionAuthorityView: + """Build the strongest caller-owned exact-runtime forgery available from module state.""" + view = object.__new__(NonresponseAdjustmentSupersessionAuthorityView) + object.__setattr__(view, "_tenant_identity", TENANT.int) + object.__setattr__(view, "_study_identity", STUDY.int) + object.__setattr__( + view, + "_fields", + (("nonresponse_receipt_digest", "b" * 64),), + ) + object.__setattr__( + view, + "_issuance_marker", + getattr( + authority_module, + "_NONRESPONSE_ADJUSTMENT_SUPERSESSION_VIEW_ISSUANCE_MARKER", + object(), + ), + ) + return view + + +def test_module_exposes_no_nonresponse_supersession_view_seal() -> None: + """Keep the write capability out of ordinary importable module state.""" + assert not hasattr( + authority_module, + "_NONRESPONSE_ADJUSTMENT_SUPERSESSION_VIEW_ISSUANCE_MARKER", + ) + + +def test_importable_marker_cannot_mint_nonresponse_supersession_view() -> None: + """Require caller-populated exact objects to remain unreadable.""" + forged_view = _raw_view_with_module_marker() + + with pytest.raises( + NonresponseAdjustmentSupersessionAuthorityIntegrityError, + match=( + "nonresponse supersession view was not issued by " + "resolve_nonresponse_adjustment_supersession_authority" + ), + ): + _ = forged_view.fields From 7fae1d0342633c715dbd3e336637a86f802facef Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 05:03:14 +0900 Subject: [PATCH 546/603] fix(workforce-validation): hide nonresponse supersession seal --- ...ponse_adjustment_supersession_authority.py | 111 ++++++++++++------ 1 file changed, 78 insertions(+), 33 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_supersession_authority.py index d9e06f03f..73e7e8d29 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_supersession_authority.py @@ -37,7 +37,6 @@ _RESOURCE_KIND = "nonresponse_adjustment_supersession_authority" _OPERATION = "read" -_NONRESPONSE_ADJUSTMENT_SUPERSESSION_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "nonresponse_receipt_reference", @@ -264,18 +263,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject exact-runtime allocations not sealed by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise NonresponseAdjustmentSupersessionAuthorityIntegrityError( - "nonresponse supersession view was not issued by " - "resolve_nonresponse_adjustment_supersession_authority" - ) from exc - if marker is not _NONRESPONSE_ADJUSTMENT_SUPERSESSION_VIEW_ISSUANCE_MARKER: - raise NonresponseAdjustmentSupersessionAuthorityIntegrityError( - "nonresponse supersession view was not issued by " - "resolve_nonresponse_adjustment_supersession_authority" - ) + _require_nonresponse_adjustment_supersession_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -326,7 +314,7 @@ def read_nonresponse_adjustment_supersession_authority( ) -def resolve_nonresponse_adjustment_supersession_authority( +def _resolve_nonresponse_adjustment_supersession_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -341,8 +329,8 @@ def resolve_nonresponse_adjustment_supersession_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: NonresponseAdjustmentSupersessionAuthorityReadPort, -) -> NonresponseAdjustmentSupersessionAuthorityView: - """Authorize then resolve the receipt's half-open append-only authority interval.""" +) -> tuple[int, int, tuple[tuple[str, object], ...]]: + """Authorize and resolve nonresponse supersession into inert projection state.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") if type(policy) is not PurposeBoundAccessPolicy: @@ -502,21 +490,78 @@ def resolve_nonresponse_adjustment_supersession_authority( "released_at", ) ) - view = object.__new__(NonresponseAdjustmentSupersessionAuthorityView) - object.__setattr__( - view, - "_tenant_identity", - _store_operational_uuid("tenant_record_id", tenant_id), - ) - object.__setattr__( - view, - "_study_identity", - _store_operational_uuid("validity_study_id", study_id), + return ( + _store_operational_uuid("tenant_record_id", record.tenant_record_id), + _store_operational_uuid("validity_study_id", record.validity_study_id), + fields, ) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, - "_issuance_marker", - _NONRESPONSE_ADJUSTMENT_SUPERSESSION_VIEW_ISSUANCE_MARKER, - ) - return view + + +def _build_nonresponse_adjustment_supersession_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: NonresponseAdjustmentSupersessionAuthorityView) -> None: + """Verify one supersession view against the closure-private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise NonresponseAdjustmentSupersessionAuthorityIntegrityError( + "nonresponse supersession view was not issued by " + "resolve_nonresponse_adjustment_supersession_authority" + ) from exc + if marker is not issuance_marker: + raise NonresponseAdjustmentSupersessionAuthorityIntegrityError( + "nonresponse supersession view was not issued by " + "resolve_nonresponse_adjustment_supersession_authority" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + nonresponse_receipt_reference: str, + nonresponse_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: NonresponseAdjustmentSupersessionAuthorityReadPort, + ) -> NonresponseAdjustmentSupersessionAuthorityView: + """Authorize then resolve the nonresponse receipt authority interval.""" + tenant_identity, study_identity, fields = ( + _resolve_nonresponse_adjustment_supersession_authority_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + nonresponse_receipt_reference=nonresponse_receipt_reference, + nonresponse_receipt_digest=nonresponse_receipt_digest, + evidence_version=evidence_version, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + ) + view = object.__new__(NonresponseAdjustmentSupersessionAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_nonresponse_adjustment_supersession_view_issued, + resolve_nonresponse_adjustment_supersession_authority, +) = _build_nonresponse_adjustment_supersession_view_runtime() +del _build_nonresponse_adjustment_supersession_view_runtime From 77ed65984b59e575a97c6662cc9ccf64fb422da6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 05:13:08 +0900 Subject: [PATCH 547/603] fix(workforce-validation): hide calibration adjustment seal Move CalibrationAdjustmentAuthorityView issuance into closure-private runtime state while preserving the purpose-bound canonical owner resolver. Add a concrete importable-marker forgery regression. Refs #421. --- .../calibration_adjustment_authority.py | 129 ++++++++++++++---- .../test_calibration_adjustment_authority.py | 25 ++++ 2 files changed, 129 insertions(+), 25 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py index 87cbd790d..f90941d19 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_adjustment_authority.py @@ -38,7 +38,6 @@ _RESOURCE_KIND = "calibration_adjustment_authority" _OPERATION = "read" -_CALIBRATION_ADJUSTMENT_VIEW_ISSUANCE_MARKER = object() _TERMINATION_CODES = frozenset({"converged", "fallback_applied"}) _READ_FIELDS = frozenset( { @@ -672,16 +671,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Require the exact in-process marker written by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise CalibrationAdjustmentAuthorityIntegrityError( - "calibration-adjustment authority view was not issued by the resolver" - ) from exc - if marker is not _CALIBRATION_ADJUSTMENT_VIEW_ISSUANCE_MARKER: - raise CalibrationAdjustmentAuthorityIntegrityError( - "calibration-adjustment authority view has an invalid issuance marker" - ) + _require_calibration_adjustment_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -772,7 +762,7 @@ def _coordinate_tuple(record: CalibrationAdjustmentAuthorityRecord) -> tuple[obj return record[:23] + record[25:46] -def resolve_calibration_adjustment_authority( +def _resolve_calibration_adjustment_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -823,8 +813,8 @@ def resolve_calibration_adjustment_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: CalibrationAdjustmentAuthorityReadPort, -) -> CalibrationAdjustmentAuthorityView: - """Authorize then corroborate the exact released calibration receipt.""" +) -> tuple[int, int, tuple[tuple[str, object], ...]]: + """Authorize and corroborate calibration evidence into inert projection state.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") if type(policy) is not PurposeBoundAccessPolicy: @@ -1091,15 +1081,104 @@ def resolve_calibration_adjustment_authority( ("fallback_rule_digest", record.fallback_rule_digest), ("fallback_rule_reference", record.fallback_rule_reference), ) - view = object.__new__(CalibrationAdjustmentAuthorityView) - object.__setattr__( - view, "_tenant_identity", _store_operational_uuid("tenant_record_id", tenant_id) - ) - object.__setattr__( - view, "_study_identity", _store_operational_uuid("validity_study_id", study_id) - ) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, "_issuance_marker", _CALIBRATION_ADJUSTMENT_VIEW_ISSUANCE_MARKER + return ( + _store_operational_uuid("tenant_record_id", tenant_id), + _store_operational_uuid("validity_study_id", study_id), + fields, ) - return view + + +def _build_calibration_adjustment_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: CalibrationAdjustmentAuthorityView) -> None: + """Verify one calibration view against the closure-private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise CalibrationAdjustmentAuthorityIntegrityError( + "calibration-adjustment authority view was not issued by the resolver" + ) from exc + if marker is not issuance_marker: + raise CalibrationAdjustmentAuthorityIntegrityError( + "calibration-adjustment authority view has an invalid issuance marker" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + calibration_receipt_reference: str, + calibration_receipt_digest: str, + evidence_version: int, + target_population_digest: str, + analysis_window_reference: str, + auxiliary_authority_reference: str, + auxiliary_projection_reference: str, + auxiliary_projection_version: int, + auxiliary_projection_digest: str, + auxiliary_purpose_reference: str, + auxiliary_purpose_digest: str, + auxiliary_owner_contract_reference: str, + auxiliary_owner_contract_version: int, + auxiliary_owner_contract_digest: str, + auxiliary_authorization_receipt_reference: str, + auxiliary_authorization_receipt_digest: str, + auxiliary_scientific_use_receipt_reference: str, + auxiliary_scientific_use_receipt_digest: str, + auxiliary_scientific_use_at: datetime, + benchmark_receipt_reference: str, + benchmark_receipt_version: int, + benchmark_receipt_digest: str, + benchmark_owner_contract_reference: str, + benchmark_owner_contract_version: int, + benchmark_owner_contract_digest: str, + benchmark_reference_at: datetime, + algorithm_reference: str, + algorithm_version: int, + constraints_digest: str, + termination_code: str, + input_weight_artifact_digest: str, + output_weight_artifact_digest: str, + constructed_at: datetime, + fallback_reason_code: str | None, + fallback_rule_reference: str | None, + fallback_rule_digest: str | None, + fallback_algorithm_reference: str | None, + fallback_algorithm_version: int | None, + fallback_configuration_digest: str | None, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: CalibrationAdjustmentAuthorityReadPort, + ) -> CalibrationAdjustmentAuthorityView: + """Authorize then corroborate the exact released calibration receipt.""" + tenant_identity, study_identity, fields = ( + _resolve_calibration_adjustment_authority_state( + **{ + name: value + for name, value in locals().items() + if name != "issuance_marker" + } + ) + ) + view = object.__new__(CalibrationAdjustmentAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_calibration_adjustment_view_issued, + resolve_calibration_adjustment_authority, +) = _build_calibration_adjustment_view_runtime() +del _build_calibration_adjustment_view_runtime diff --git a/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py b/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py index 9ba1804e2..0f094f516 100644 --- a/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py +++ b/services/workforce-validation-api/tests/test_calibration_adjustment_authority.py @@ -7,6 +7,7 @@ import pytest +import orgmetra_workforce_validation_api.calibration_adjustment_authority as authority_module from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy from orgmetra_workforce_validation_api import ValidationPrincipal from orgmetra_workforce_validation_api.calibration_adjustment_authority import ( @@ -556,6 +557,30 @@ def test_view_rejects_caller_authored_issuance_marker() -> None: _ = forged.fields +def test_importable_marker_cannot_mint_calibration_adjustment_view() -> None: + """Keep the resolver's view-sealing capability out of ordinary module state.""" + assert not hasattr( + authority_module, + "_CALIBRATION_ADJUSTMENT_VIEW_ISSUANCE_MARKER", + ) + forged = object.__new__(CalibrationAdjustmentAuthorityView) + object.__setattr__(forged, "_tenant_identity", TENANT.int) + object.__setattr__(forged, "_study_identity", STUDY.int) + object.__setattr__(forged, "_fields", (("termination_code", "converged"),)) + object.__setattr__( + forged, + "_issuance_marker", + getattr( + authority_module, + "_CALIBRATION_ADJUSTMENT_VIEW_ISSUANCE_MARKER", + object(), + ), + ) + + with pytest.raises(CalibrationAdjustmentAuthorityIntegrityError): + _ = forged.fields + + def test_issued_view_rejects_mutation_and_deletion() -> None: """Keep a resolver-issued view immutable after all owner checks complete.""" view = _resolve(read_port=_ReadPort(_record())) From ba878fe982a0f8dbebaa3b5aa18d069d2920a6df Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 05:16:14 +0900 Subject: [PATCH 548/603] fix(workforce-validation): hide calibration auxiliary seal --- .../scientific_authority.py | 92 ++++++++++++++----- .../test_calibration_auxiliary_authority.py | 29 ++++++ 2 files changed, 100 insertions(+), 21 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py index 99241c0e8..757457cb8 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/scientific_authority.py @@ -35,7 +35,6 @@ _REFERENCE_PATTERN = re.compile(r"^[a-z][a-z0-9_]*:[A-Za-z0-9][A-Za-z0-9._~-]*$") _RESOURCE_KIND = "calibration_auxiliary_authority" _OPERATION = "read" -_CALIBRATION_AUXILIARY_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "authority_reference", @@ -362,16 +361,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject raw allocations not sealed by the authorized resolver path.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise CalibrationAuxiliaryAuthorityIntegrityError( - "calibration auxiliary authority view was not issued by the resolver" - ) from exc - if marker is not _CALIBRATION_AUXILIARY_VIEW_ISSUANCE_MARKER: - raise CalibrationAuxiliaryAuthorityIntegrityError( - "calibration auxiliary authority view was not issued by the resolver" - ) + _require_calibration_auxiliary_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -428,7 +418,7 @@ def read_calibration_auxiliary_authority( ) -def resolve_calibration_auxiliary_authority( +def _resolve_calibration_auxiliary_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -450,7 +440,7 @@ def resolve_calibration_auxiliary_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: CalibrationAuxiliaryAuthorityReadPort, -) -> CalibrationAuxiliaryAuthorityView: +) -> tuple[int, int, tuple[tuple[str, object], ...]]: """Authorize and corroborate one exact calibration auxiliary-use authority tuple. The exact owner capability is captured inertly before authorization and the @@ -650,11 +640,71 @@ def resolve_calibration_auxiliary_authority( "authorized_to": record.authorized_to, } fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) - view = object.__new__(CalibrationAuxiliaryAuthorityView) - object.__setattr__(view, "_tenant_identity", tenant_identity) - object.__setattr__(view, "_study_identity", study_identity) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, "_issuance_marker", _CALIBRATION_AUXILIARY_VIEW_ISSUANCE_MARKER - ) - return view + return tenant_identity, study_identity, fields + + +def _build_calibration_auxiliary_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: CalibrationAuxiliaryAuthorityView) -> None: + """Verify one auxiliary view against the closure-private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise CalibrationAuxiliaryAuthorityIntegrityError( + "calibration auxiliary authority view was not issued by the resolver" + ) from exc + if marker is not issuance_marker: + raise CalibrationAuxiliaryAuthorityIntegrityError( + "calibration auxiliary authority view was not issued by the resolver" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + authority_reference: str, + auxiliary_projection_reference: str, + auxiliary_projection_version: int, + auxiliary_projection_digest: str, + scientific_purpose_reference: str, + scientific_purpose_digest: str, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + authorization_receipt_reference: str, + authorization_receipt_digest: str, + scientific_use_receipt_reference: str, + scientific_use_receipt_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: CalibrationAuxiliaryAuthorityReadPort, + ) -> CalibrationAuxiliaryAuthorityView: + """Authorize and corroborate one exact calibration auxiliary authority tuple.""" + tenant_identity, study_identity, fields = ( + _resolve_calibration_auxiliary_authority_state( + **{ + name: value + for name, value in locals().items() + if name != "issuance_marker" + } + ) + ) + view = object.__new__(CalibrationAuxiliaryAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_calibration_auxiliary_view_issued, + resolve_calibration_auxiliary_authority, +) = _build_calibration_auxiliary_view_runtime() +del _build_calibration_auxiliary_view_runtime diff --git a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py index 482b59b7c..7f5baaf61 100644 --- a/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py +++ b/services/workforce-validation-api/tests/test_calibration_auxiliary_authority.py @@ -7,6 +7,7 @@ import pytest +import orgmetra_workforce_validation_api.scientific_authority as authority_module from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy from orgmetra_workforce_validation_api import ValidationPrincipal from orgmetra_workforce_validation_api.scientific_authority import ( @@ -496,6 +497,34 @@ def test_low_level_view_allocation_cannot_expose_caller_authored_projection() -> _ = wrong_marker_view.validity_study_id +def test_importable_marker_cannot_mint_calibration_auxiliary_view() -> None: + """Keep auxiliary view-sealing authority out of ordinary module state.""" + assert not hasattr( + authority_module, + "_CALIBRATION_AUXILIARY_VIEW_ISSUANCE_MARKER", + ) + forged_view = object.__new__(CalibrationAuxiliaryAuthorityView) + object.__setattr__(forged_view, "_tenant_identity", TENANT.int) + object.__setattr__(forged_view, "_study_identity", STUDY.int) + object.__setattr__( + forged_view, + "_fields", + (("authority_reference", AUTHORITY_REFERENCE),), + ) + object.__setattr__( + forged_view, + "_issuance_marker", + getattr( + authority_module, + "_CALIBRATION_AUXILIARY_VIEW_ISSUANCE_MARKER", + object(), + ), + ) + + with pytest.raises(CalibrationAuxiliaryAuthorityIntegrityError): + _ = forged_view.fields + + def test_issued_view_rejects_attribute_deletion() -> None: """Keep authorized projection state immutable after resolver issuance.""" view = _resolve(read_port=_ReadPort(_record())) From 4276ae996ee2bd81687684c0602c7b0763805378 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 05:18:31 +0900 Subject: [PATCH 549/603] fix(workforce-validation): hide calibration benchmark seal --- .../benchmark_authority.py | 98 +++++++++++++------ ...hmark_authority_view_issuance_integrity.py | 16 +++ 2 files changed, 84 insertions(+), 30 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py index 0830e5030..6dc695dde 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/benchmark_authority.py @@ -47,7 +47,6 @@ "owner_contract_released_at", } ) -_CALIBRATION_BENCHMARK_VIEW_ISSUANCE_MARKER = object() class CalibrationBenchmarkAuthorityNotFound(LookupError): @@ -342,18 +341,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject exact-runtime allocations not sealed by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise CalibrationBenchmarkAuthorityIntegrityError( - "calibration benchmark view was not issued by " - "resolve_calibration_benchmark_authority" - ) from exc - if marker is not _CALIBRATION_BENCHMARK_VIEW_ISSUANCE_MARKER: - raise CalibrationBenchmarkAuthorityIntegrityError( - "calibration benchmark view was not issued by " - "resolve_calibration_benchmark_authority" - ) + _require_calibration_benchmark_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -404,7 +392,7 @@ def read_calibration_benchmark_authority( ) -def resolve_calibration_benchmark_authority( +def _resolve_calibration_benchmark_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -420,7 +408,7 @@ def resolve_calibration_benchmark_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: CalibrationBenchmarkAuthorityReadPort, -) -> CalibrationBenchmarkAuthorityView: +) -> tuple[int, int, tuple[tuple[str, object], ...]]: """Authorize then corroborate the exact released benchmark tuple. The owner must independently resolve immutable release coordinates, release @@ -605,21 +593,71 @@ def resolve_calibration_benchmark_authority( ("benchmark_reference_at", record.benchmark_reference_at), ("owner_contract_released_at", record.owner_contract_released_at), ) - view = object.__new__(CalibrationBenchmarkAuthorityView) - object.__setattr__( - view, - "_tenant_identity", + return ( _store_operational_uuid("tenant_record_id", tenant_id), - ) - object.__setattr__( - view, - "_study_identity", _store_operational_uuid("validity_study_id", study_id), + fields, ) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, - "_issuance_marker", - _CALIBRATION_BENCHMARK_VIEW_ISSUANCE_MARKER, - ) - return view + + +def _build_calibration_benchmark_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: CalibrationBenchmarkAuthorityView) -> None: + """Verify one benchmark view against the closure-private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise CalibrationBenchmarkAuthorityIntegrityError( + "calibration benchmark view was not issued by " + "resolve_calibration_benchmark_authority" + ) from exc + if marker is not issuance_marker: + raise CalibrationBenchmarkAuthorityIntegrityError( + "calibration benchmark view was not issued by " + "resolve_calibration_benchmark_authority" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + benchmark_receipt_reference: str, + benchmark_receipt_version: int, + benchmark_receipt_digest: str, + benchmark_owner_contract_reference: str, + benchmark_owner_contract_version: int, + benchmark_owner_contract_digest: str, + benchmark_reference_at: datetime, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: CalibrationBenchmarkAuthorityReadPort, + ) -> CalibrationBenchmarkAuthorityView: + """Authorize and corroborate one exact released calibration benchmark.""" + tenant_identity, study_identity, fields = ( + _resolve_calibration_benchmark_authority_state( + **{ + name: value + for name, value in locals().items() + if name != "issuance_marker" + } + ) + ) + view = object.__new__(CalibrationBenchmarkAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_calibration_benchmark_view_issued, + resolve_calibration_benchmark_authority, +) = _build_calibration_benchmark_view_runtime() +del _build_calibration_benchmark_view_runtime diff --git a/services/workforce-validation-api/tests/test_calibration_benchmark_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_calibration_benchmark_authority_view_issuance_integrity.py index 895e60f9b..1750ecb26 100644 --- a/services/workforce-validation-api/tests/test_calibration_benchmark_authority_view_issuance_integrity.py +++ b/services/workforce-validation-api/tests/test_calibration_benchmark_authority_view_issuance_integrity.py @@ -4,6 +4,7 @@ import pytest +import orgmetra_workforce_validation_api.benchmark_authority as authority_module from orgmetra_workforce_validation_api.benchmark_authority import ( CalibrationBenchmarkAuthorityIntegrityError, CalibrationBenchmarkAuthorityView, @@ -14,6 +15,21 @@ STUDY = UUID("00000000-0000-7000-8000-0000000000f2") +def test_importable_marker_cannot_mint_calibration_benchmark_view() -> None: + """Keep the benchmark view seal outside importable module state.""" + marker_name = "_CALIBRATION_BENCHMARK_VIEW_ISSUANCE_MARKER" + assert not hasattr(authority_module, marker_name) + + forged_view = object.__new__(CalibrationBenchmarkAuthorityView) + object.__setattr__(forged_view, "_tenant_identity", TENANT.int) + object.__setattr__(forged_view, "_study_identity", STUDY.int) + object.__setattr__(forged_view, "_fields", ()) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises(CalibrationBenchmarkAuthorityIntegrityError): + _ = forged_view.fields + + def test_low_level_tuple_construction_cannot_issue_benchmark_view() -> None: """Remove tuple's base constructor as an alternate authorized-view issuer.""" with pytest.raises(TypeError): From 4ae6a9489fac4a60e6f34925bfab86eda14578f0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 05:21:47 +0900 Subject: [PATCH 550/603] fix(workforce-validation): hide calibration support seal --- .../calibration_support_authority.py | 112 ++++++++++++++---- ...pport_authority_view_issuance_integrity.py | 16 +++ 2 files changed, 103 insertions(+), 25 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py index a3e6d9cf0..315ecd8bd 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/calibration_support_authority.py @@ -37,7 +37,6 @@ _RESOURCE_KIND = "calibration_support_authority" _OPERATION = "read" -_CALIBRATION_SUPPORT_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "support_authority_reference", @@ -447,18 +446,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject exact-runtime allocations not sealed by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise CalibrationSupportAuthorityIntegrityError( - "calibration support view was not issued by " - "resolve_calibration_support_authority" - ) from exc - if marker is not _CALIBRATION_SUPPORT_VIEW_ISSUANCE_MARKER: - raise CalibrationSupportAuthorityIntegrityError( - "calibration support view was not issued by " - "resolve_calibration_support_authority" - ) + _require_calibration_support_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -564,7 +552,7 @@ def _caller_coordinates(record: CalibrationSupportAuthorityRecord) -> tuple[obje ) -def resolve_calibration_support_authority( +def _resolve_calibration_support_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -600,7 +588,7 @@ def resolve_calibration_support_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: CalibrationSupportAuthorityReadPort, -) -> CalibrationSupportAuthorityView: +) -> tuple[int, int, tuple[tuple[str, object], ...]]: """Authorize and resolve released support chronology for one calibration receipt.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") @@ -843,13 +831,87 @@ def resolve_calibration_support_authority( values = {field_name: getattr(record, field_name) for field_name in _READ_FIELDS} fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) - view = object.__new__(CalibrationSupportAuthorityView) - object.__setattr__(view, "_tenant_identity", tenant_identity) - object.__setattr__(view, "_study_identity", study_identity) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, - "_issuance_marker", - _CALIBRATION_SUPPORT_VIEW_ISSUANCE_MARKER, - ) - return view + return tenant_identity, study_identity, fields + + +def _build_calibration_support_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: CalibrationSupportAuthorityView) -> None: + """Verify one support view against the closure-private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise CalibrationSupportAuthorityIntegrityError( + "calibration support view was not issued by " + "resolve_calibration_support_authority" + ) from exc + if marker is not issuance_marker: + raise CalibrationSupportAuthorityIntegrityError( + "calibration support view was not issued by " + "resolve_calibration_support_authority" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + calibration_receipt_reference: str, + calibration_receipt_digest: str, + auxiliary_authority_reference: str, + auxiliary_projection_reference: str, + auxiliary_projection_version: int, + auxiliary_projection_digest: str, + auxiliary_purpose_reference: str, + auxiliary_purpose_digest: str, + auxiliary_owner_contract_reference: str, + auxiliary_owner_contract_version: int, + auxiliary_owner_contract_digest: str, + auxiliary_authorization_receipt_reference: str, + auxiliary_authorization_receipt_digest: str, + auxiliary_scientific_use_receipt_reference: str, + auxiliary_scientific_use_receipt_digest: str, + auxiliary_scientific_use_at: datetime, + benchmark_receipt_reference: str, + benchmark_receipt_version: int, + benchmark_receipt_digest: str, + benchmark_owner_contract_reference: str, + benchmark_owner_contract_version: int, + benchmark_owner_contract_digest: str, + benchmark_reference_at: datetime, + constructed_at: datetime, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: CalibrationSupportAuthorityReadPort, + ) -> CalibrationSupportAuthorityView: + """Authorize and resolve released support chronology for one calibration receipt.""" + tenant_identity, study_identity, fields = ( + _resolve_calibration_support_authority_state( + **{ + name: value + for name, value in locals().items() + if name != "issuance_marker" + } + ) + ) + view = object.__new__(CalibrationSupportAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_calibration_support_view_issued, + resolve_calibration_support_authority, +) = _build_calibration_support_view_runtime() +del _build_calibration_support_view_runtime diff --git a/services/workforce-validation-api/tests/test_calibration_support_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_calibration_support_authority_view_issuance_integrity.py index 6b75bf2e6..06ee7ea4d 100644 --- a/services/workforce-validation-api/tests/test_calibration_support_authority_view_issuance_integrity.py +++ b/services/workforce-validation-api/tests/test_calibration_support_authority_view_issuance_integrity.py @@ -4,6 +4,7 @@ import pytest +import orgmetra_workforce_validation_api.calibration_support_authority as authority_module from orgmetra_workforce_validation_api.calibration_support_authority import ( CalibrationSupportAuthorityIntegrityError, CalibrationSupportAuthorityView, @@ -14,6 +15,21 @@ STUDY = UUID("00000000-0000-7000-8000-0000000000f2") +def test_importable_marker_cannot_mint_calibration_support_view() -> None: + """Keep the calibration-support view seal outside importable module state.""" + marker_name = "_CALIBRATION_SUPPORT_VIEW_ISSUANCE_MARKER" + assert not hasattr(authority_module, marker_name) + + forged_view = object.__new__(CalibrationSupportAuthorityView) + object.__setattr__(forged_view, "_tenant_identity", TENANT.int) + object.__setattr__(forged_view, "_study_identity", STUDY.int) + object.__setattr__(forged_view, "_fields", ()) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises(CalibrationSupportAuthorityIntegrityError): + _ = forged_view.fields + + def test_low_level_tuple_construction_cannot_issue_support_view() -> None: """Remove tuple's base constructor as an alternate authorized-view issuer.""" with pytest.raises(TypeError): From 264e416d528433a90b0f0d0efa203f0a3558a5c3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 06:04:16 +0900 Subject: [PATCH 551/603] test(workforce-validation): expose final-weight supersession seal forgery --- ...rsession_authority_view_seal_capability.py | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_supersession_authority_view_seal_capability.py diff --git a/services/workforce-validation-api/tests/test_final_weight_supersession_authority_view_seal_capability.py b/services/workforce-validation-api/tests/test_final_weight_supersession_authority_view_seal_capability.py new file mode 100644 index 000000000..b6135a209 --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_supersession_authority_view_seal_capability.py @@ -0,0 +1,58 @@ +"""Hostile sealing-capability regression for final-weight supersession views.""" + +from uuid import UUID + +import pytest + +import orgmetra_workforce_validation_api.final_weight_supersession_authority as authority_module +from orgmetra_workforce_validation_api.final_weight_supersession_authority import ( + FinalWeightSupersessionAuthorityIntegrityError, + FinalWeightSupersessionAuthorityView, +) + +TENANT = UUID("00000000-0000-0000-0000-000000000421") +STUDY = UUID("00000000-0000-0000-0000-000000000422") + + +def _raw_view_with_module_marker() -> FinalWeightSupersessionAuthorityView: + """Build the strongest caller-owned exact-runtime forgery available from module state.""" + view = object.__new__(FinalWeightSupersessionAuthorityView) + object.__setattr__(view, "_tenant_identity", TENANT.int) + object.__setattr__(view, "_study_identity", STUDY.int) + object.__setattr__( + view, + "_fields", + (("analysis_weight_receipt_digest", "a" * 64),), + ) + object.__setattr__( + view, + "_issuance_marker", + getattr( + authority_module, + "_FINAL_WEIGHT_SUPERSESSION_VIEW_ISSUANCE_MARKER", + object(), + ), + ) + return view + + +def test_module_exposes_no_final_weight_supersession_view_seal() -> None: + """Keep the write capability out of ordinary importable module state.""" + assert not hasattr( + authority_module, + "_FINAL_WEIGHT_SUPERSESSION_VIEW_ISSUANCE_MARKER", + ) + + +def test_importable_marker_cannot_mint_final_weight_supersession_view() -> None: + """Require caller-populated exact objects to remain unreadable.""" + forged_view = _raw_view_with_module_marker() + + with pytest.raises( + FinalWeightSupersessionAuthorityIntegrityError, + match=( + "final-weight supersession view was not issued by " + "resolve_final_weight_supersession_authority" + ), + ): + _ = forged_view.fields From c320c6251df11f452afa835ba7fffc550646426d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 06:05:58 +0900 Subject: [PATCH 552/603] fix(workforce-validation): hide final-weight supersession seal --- .../final_weight_supersession_authority.py | 119 ++++++++++++------ 1 file changed, 80 insertions(+), 39 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py index c09ac3a4b..aa61ec801 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_supersession_authority.py @@ -36,7 +36,6 @@ _RESOURCE_KIND = "final_weight_supersession_authority" _OPERATION = "read" -_FINAL_WEIGHT_SUPERSESSION_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "analysis_weight_receipt_reference", @@ -278,18 +277,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject exact-runtime allocations not sealed by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise FinalWeightSupersessionAuthorityIntegrityError( - "final-weight supersession view was not issued by " - "resolve_final_weight_supersession_authority" - ) from exc - if marker is not _FINAL_WEIGHT_SUPERSESSION_VIEW_ISSUANCE_MARKER: - raise FinalWeightSupersessionAuthorityIntegrityError( - "final-weight supersession view was not issued by " - "resolve_final_weight_supersession_authority" - ) + _require_final_weight_supersession_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -341,7 +329,7 @@ def read_final_weight_supersession_authority( ) -def resolve_final_weight_supersession_authority( +def _resolve_final_weight_supersession_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -357,7 +345,7 @@ def resolve_final_weight_supersession_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: FinalWeightSupersessionAuthorityReadPort, -) -> FinalWeightSupersessionAuthorityView: +) -> tuple[int, int, tuple[tuple[str, object], ...]]: """Authorize then resolve the receipt's half-open append-only authority interval.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") @@ -375,12 +363,10 @@ def resolve_final_weight_supersession_authority( "read_final_weight_supersession_authority." ) - tenant_id = _restore_operational_uuid( - "tenant_record_id", _store_operational_uuid("tenant_record_id", tenant_record_id) - ) - study_id = _restore_operational_uuid( - "validity_study_id", _store_operational_uuid("validity_study_id", validity_study_id) - ) + tenant_identity = _store_operational_uuid("tenant_record_id", tenant_record_id) + study_identity = _store_operational_uuid("validity_study_id", validity_study_id) + tenant_id = _restore_operational_uuid("tenant_record_id", tenant_identity) + study_id = _restore_operational_uuid("validity_study_id", study_identity) receipt_ref = _require_reference( "analysis_weight_receipt_reference", analysis_weight_receipt_reference, @@ -511,24 +497,79 @@ def resolve_final_weight_supersession_authority( values = dict(record.fields) values["released_at"] = record.released_at fields = tuple((field_name, values[field_name]) for field_name in sorted(_VIEW_FIELDS)) - view = object.__new__(FinalWeightSupersessionAuthorityView) - object.__setattr__( - view, - "_tenant_identity", - _store_operational_uuid("tenant_record_id", record.tenant_record_id), - ) - object.__setattr__( - view, - "_study_identity", - _store_operational_uuid("validity_study_id", record.validity_study_id), - ) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, - "_issuance_marker", - _FINAL_WEIGHT_SUPERSESSION_VIEW_ISSUANCE_MARKER, - ) - return view + return tenant_identity, study_identity, fields + + +def _build_final_weight_supersession_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: FinalWeightSupersessionAuthorityView) -> None: + """Verify one final-weight supersession view against the private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise FinalWeightSupersessionAuthorityIntegrityError( + "final-weight supersession view was not issued by " + "resolve_final_weight_supersession_authority" + ) from exc + if marker is not issuance_marker: + raise FinalWeightSupersessionAuthorityIntegrityError( + "final-weight supersession view was not issued by " + "resolve_final_weight_supersession_authority" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + analysis_weight_receipt_reference: str, + analysis_weight_receipt_digest: str, + evidence_version: int, + correction_sequence: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: FinalWeightSupersessionAuthorityReadPort, + ) -> FinalWeightSupersessionAuthorityView: + """Authorize then issue the current final-weight supersession projection.""" + tenant_identity, study_identity, fields = ( + _resolve_final_weight_supersession_authority_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + analysis_weight_receipt_reference=analysis_weight_receipt_reference, + analysis_weight_receipt_digest=analysis_weight_receipt_digest, + evidence_version=evidence_version, + correction_sequence=correction_sequence, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + ) + view = object.__new__(FinalWeightSupersessionAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_final_weight_supersession_view_issued, + resolve_final_weight_supersession_authority, +) = _build_final_weight_supersession_view_runtime() +del _build_final_weight_supersession_view_runtime __all__ = [ From f44a11402bc9f887553626c7206b9e105d6b7309 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 06:16:26 +0900 Subject: [PATCH 553/603] test(workforce-validation): expose final-weight view seal forgery --- ...s_weight_authority_view_issuance_integrity.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/services/workforce-validation-api/tests/test_final_analysis_weight_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_final_analysis_weight_authority_view_issuance_integrity.py index 7afd3602c..b0ea547b2 100644 --- a/services/workforce-validation-api/tests/test_final_analysis_weight_authority_view_issuance_integrity.py +++ b/services/workforce-validation-api/tests/test_final_analysis_weight_authority_view_issuance_integrity.py @@ -4,6 +4,7 @@ import pytest +import orgmetra_workforce_validation_api.final_weight_authority as authority_module from orgmetra_workforce_validation_api.final_weight_authority import ( FinalAnalysisWeightAuthorityIntegrityError, FinalAnalysisWeightAuthorityView, @@ -14,6 +15,21 @@ STUDY = UUID("00000000-0000-7000-8000-0000000000f1") +def test_importable_marker_cannot_mint_final_weight_view() -> None: + """Keep the final-weight view seal outside importable module state.""" + marker_name = "_FINAL_ANALYSIS_WEIGHT_VIEW_ISSUANCE_MARKER" + assert not hasattr(authority_module, marker_name) + + forged_view = object.__new__(FinalAnalysisWeightAuthorityView) + object.__setattr__(forged_view, "_tenant_identity", TENANT.int) + object.__setattr__(forged_view, "_study_identity", STUDY.int) + object.__setattr__(forged_view, "_fields", ()) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises(FinalAnalysisWeightAuthorityIntegrityError): + _ = forged_view.fields + + def test_low_level_tuple_construction_cannot_issue_final_weight_view() -> None: """Remove tuple's base constructor as an alternate authorized-view issuer.""" with pytest.raises(TypeError): From d61deb6ff170d9a8be22d776ec6e8c441a59b6cf Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 06:18:05 +0900 Subject: [PATCH 554/603] fix(workforce-validation): hide final-weight authority seal --- .../final_weight_authority.py | 163 ++++++++++++++---- 1 file changed, 133 insertions(+), 30 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py index a978e99f2..1fa57a811 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py @@ -36,7 +36,6 @@ _RESOURCE_KIND = "final_analysis_weight_authority" _OPERATION = "read" -_FINAL_ANALYSIS_WEIGHT_VIEW_ISSUANCE_MARKER = object() _WEIGHT_SCOPE_CODES = frozenset({"cross_sectional", "longitudinal"}) _SPECIALIZED_EVIDENCE_KIND_BY_ADJUSTMENT_CODE = { "nonresponse_adjustment": "nonresponse_adjustment_receipt", @@ -526,18 +525,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject exact-runtime allocations not sealed by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise FinalAnalysisWeightAuthorityIntegrityError( - "final analysis-weight view was not issued by " - "resolve_final_analysis_weight_authority" - ) from exc - if marker is not _FINAL_ANALYSIS_WEIGHT_VIEW_ISSUANCE_MARKER: - raise FinalAnalysisWeightAuthorityIntegrityError( - "final analysis-weight view was not issued by " - "resolve_final_analysis_weight_authority" - ) + _require_final_analysis_weight_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -616,7 +604,7 @@ def read_final_analysis_weight_authority( ) -def resolve_final_analysis_weight_authority( +def _resolve_final_analysis_weight_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -660,7 +648,7 @@ def resolve_final_analysis_weight_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: FinalAnalysisWeightAuthorityReadPort, -) -> FinalAnalysisWeightAuthorityView: +) -> tuple[int, int, tuple[tuple[str, object], ...]]: """Authorize then corroborate the complete released final-weight lineage.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") @@ -858,21 +846,136 @@ def resolve_final_analysis_weight_authority( values["released_at"] = record.released_at values["superseded_at"] = record.superseded_at fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) - view = object.__new__(FinalAnalysisWeightAuthorityView) - object.__setattr__( - view, - "_tenant_identity", + return ( _store_operational_uuid("tenant_record_id", record.tenant_record_id), - ) - object.__setattr__( - view, - "_study_identity", _store_operational_uuid("validity_study_id", record.validity_study_id), + fields, ) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, - "_issuance_marker", - _FINAL_ANALYSIS_WEIGHT_VIEW_ISSUANCE_MARKER, - ) - return view + + +def _build_final_analysis_weight_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: FinalAnalysisWeightAuthorityView) -> None: + """Verify one final analysis-weight view against the private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise FinalAnalysisWeightAuthorityIntegrityError( + "final analysis-weight view was not issued by " + "resolve_final_analysis_weight_authority" + ) from exc + if marker is not issuance_marker: + raise FinalAnalysisWeightAuthorityIntegrityError( + "final analysis-weight view was not issued by " + "resolve_final_analysis_weight_authority" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + analysis_weight_receipt_reference: str, + analysis_weight_receipt_digest: str, + evidence_version: int, + estimand_reference: str, + estimand_digest: str, + estimand_scope_code: str, + target_population_reference: str, + target_population_digest: str, + analysis_unit_code: str, + analysis_window_reference: str, + reference_duration_reference: str, + reference_duration_digest: str, + eligible_case_set_digest: str, + analytic_case_occurrence_set_digest: str, + source_universe_receipt_reference: str, + source_universe_receipt_version: int, + source_universe_receipt_digest: str, + sampling_design_receipt_reference: str, + sampling_design_receipt_version: int, + sampling_design_receipt_digest: str, + base_weight_method_code: str, + base_weight_method_version: int, + base_weight_evidence_digest: str, + base_weight_artifact_digest: str, + adjustments: tuple[FinalWeightAdjustmentCoordinate, ...], + final_weight_artifact_digest: str, + weight_eligibility_receipt_reference: str, + weight_eligibility_receipt_digest: str, + analytic_case_count: int, + constructed_at: datetime, + correction_sequence: int, + supersedes_receipt_digest: str | None, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: FinalAnalysisWeightAuthorityReadPort, + ) -> FinalAnalysisWeightAuthorityView: + """Authorize then issue the complete released final-weight projection.""" + tenant_identity, study_identity, fields = ( + _resolve_final_analysis_weight_authority_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + analysis_weight_receipt_reference=analysis_weight_receipt_reference, + analysis_weight_receipt_digest=analysis_weight_receipt_digest, + evidence_version=evidence_version, + estimand_reference=estimand_reference, + estimand_digest=estimand_digest, + estimand_scope_code=estimand_scope_code, + target_population_reference=target_population_reference, + target_population_digest=target_population_digest, + analysis_unit_code=analysis_unit_code, + analysis_window_reference=analysis_window_reference, + reference_duration_reference=reference_duration_reference, + reference_duration_digest=reference_duration_digest, + eligible_case_set_digest=eligible_case_set_digest, + analytic_case_occurrence_set_digest=analytic_case_occurrence_set_digest, + source_universe_receipt_reference=source_universe_receipt_reference, + source_universe_receipt_version=source_universe_receipt_version, + source_universe_receipt_digest=source_universe_receipt_digest, + sampling_design_receipt_reference=sampling_design_receipt_reference, + sampling_design_receipt_version=sampling_design_receipt_version, + sampling_design_receipt_digest=sampling_design_receipt_digest, + base_weight_method_code=base_weight_method_code, + base_weight_method_version=base_weight_method_version, + base_weight_evidence_digest=base_weight_evidence_digest, + base_weight_artifact_digest=base_weight_artifact_digest, + adjustments=adjustments, + final_weight_artifact_digest=final_weight_artifact_digest, + weight_eligibility_receipt_reference=weight_eligibility_receipt_reference, + weight_eligibility_receipt_digest=weight_eligibility_receipt_digest, + analytic_case_count=analytic_case_count, + constructed_at=constructed_at, + correction_sequence=correction_sequence, + supersedes_receipt_digest=supersedes_receipt_digest, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + ) + view = object.__new__(FinalAnalysisWeightAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_final_analysis_weight_view_issued, + resolve_final_analysis_weight_authority, +) = _build_final_analysis_weight_view_runtime() +del _build_final_analysis_weight_view_runtime From 1cffaea161ad456776498dce4535cf65a6718b7a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 06:18:52 +0900 Subject: [PATCH 555/603] test(workforce-validation): expose component-binding seal forgery --- ..._binding_authority_view_issuance_integrity.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_binding_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_final_weight_component_binding_authority_view_issuance_integrity.py index a5761dbef..a13018cb4 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_binding_authority_view_issuance_integrity.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_binding_authority_view_issuance_integrity.py @@ -4,6 +4,7 @@ import pytest +import orgmetra_workforce_validation_api.final_weight_component_binding_authority as authority_module from orgmetra_workforce_validation_api.final_weight_component_binding_authority import ( FinalWeightComponentBindingAuthorityIntegrityError, FinalWeightComponentBindingAuthorityView, @@ -14,6 +15,21 @@ STUDY = UUID("00000000-0000-7000-8000-0000000000f1") +def test_importable_marker_cannot_mint_component_binding_view() -> None: + """Keep the component-binding view seal outside importable module state.""" + marker_name = "_FINAL_WEIGHT_COMPONENT_BINDING_VIEW_ISSUANCE_MARKER" + assert not hasattr(authority_module, marker_name) + + forged_view = object.__new__(FinalWeightComponentBindingAuthorityView) + object.__setattr__(forged_view, "_tenant_identity", TENANT.int) + object.__setattr__(forged_view, "_study_identity", STUDY.int) + object.__setattr__(forged_view, "_fields", ()) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises(FinalWeightComponentBindingAuthorityIntegrityError): + _ = forged_view.fields + + def test_low_level_tuple_construction_cannot_issue_component_binding_view() -> None: """Remove tuple's base constructor as an alternate authorized-view issuer.""" with pytest.raises(TypeError): From 77012bb0024bf0a650314cddef8a7a864bcd5c17 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 06:19:53 +0900 Subject: [PATCH 556/603] fix(workforce-validation): hide component-binding seal --- ...inal_weight_component_binding_authority.py | 99 +++++++++++++------ 1 file changed, 69 insertions(+), 30 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_binding_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_binding_authority.py index 44f2ec58a..580c8ad7b 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_binding_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_binding_authority.py @@ -37,7 +37,6 @@ _RESOURCE_KIND = "final_weight_component_binding_authority" _OPERATION = "read" -_FINAL_WEIGHT_COMPONENT_BINDING_VIEW_ISSUANCE_MARKER = object() _EVIDENCE_REFERENCE_NAMESPACE_BY_KIND = { "nonresponse_adjustment_receipt": "nonresponse_adjustment_receipt", "calibration_adjustment_receipt": "calibration_adjustment_receipt", @@ -323,18 +322,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject exact-runtime allocations not sealed by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise FinalWeightComponentBindingAuthorityIntegrityError( - "final-weight component binding view was not issued by " - "resolve_final_weight_component_binding_authority" - ) from exc - if marker is not _FINAL_WEIGHT_COMPONENT_BINDING_VIEW_ISSUANCE_MARKER: - raise FinalWeightComponentBindingAuthorityIntegrityError( - "final-weight component binding view was not issued by " - "resolve_final_weight_component_binding_authority" - ) + _require_final_weight_component_binding_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -382,7 +370,7 @@ def read_final_weight_component_binding_authority( ) -def resolve_final_weight_component_binding_authority( +def _resolve_final_weight_component_binding_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -394,7 +382,7 @@ def resolve_final_weight_component_binding_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: FinalWeightComponentBindingAuthorityReadPort, -) -> FinalWeightComponentBindingAuthorityView: +) -> tuple[int, int, tuple[tuple[str, object], ...]]: """Authorize and resolve deterministic typed-component locators for a final weight.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") @@ -509,21 +497,72 @@ def resolve_final_weight_component_binding_authority( values["released_at"] = record.released_at values["superseded_at"] = record.superseded_at fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) - view = object.__new__(FinalWeightComponentBindingAuthorityView) - object.__setattr__( - view, - "_tenant_identity", + return ( _store_operational_uuid("tenant_record_id", record.tenant_record_id), - ) - object.__setattr__( - view, - "_study_identity", _store_operational_uuid("validity_study_id", record.validity_study_id), + fields, ) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, - "_issuance_marker", - _FINAL_WEIGHT_COMPONENT_BINDING_VIEW_ISSUANCE_MARKER, - ) - return view + + +def _build_final_weight_component_binding_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: FinalWeightComponentBindingAuthorityView) -> None: + """Verify one component-binding view against the private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise FinalWeightComponentBindingAuthorityIntegrityError( + "final-weight component binding view was not issued by " + "resolve_final_weight_component_binding_authority" + ) from exc + if marker is not issuance_marker: + raise FinalWeightComponentBindingAuthorityIntegrityError( + "final-weight component binding view was not issued by " + "resolve_final_weight_component_binding_authority" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + analysis_weight_receipt_reference: str, + analysis_weight_receipt_digest: str, + analysis_weight_evidence_version: int, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: FinalWeightComponentBindingAuthorityReadPort, + ) -> FinalWeightComponentBindingAuthorityView: + """Authorize then issue deterministic typed-component locators.""" + tenant_identity, study_identity, fields = ( + _resolve_final_weight_component_binding_authority_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + analysis_weight_receipt_reference=analysis_weight_receipt_reference, + analysis_weight_receipt_digest=analysis_weight_receipt_digest, + analysis_weight_evidence_version=analysis_weight_evidence_version, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + ) + view = object.__new__(FinalWeightComponentBindingAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_final_weight_component_binding_view_issued, + resolve_final_weight_component_binding_authority, +) = _build_final_weight_component_binding_view_runtime() +del _build_final_weight_component_binding_view_runtime From 8ef4eb4abe72d8942d001609123d5b798a36c2c0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 06:20:58 +0900 Subject: [PATCH 557/603] docs(workforce-validation): record private view seals --- CHANGELOG.md | 1 + manifest.json | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b17589ff..e95e3803c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ All notable changes to Orgmetra will be documented in this file. ### Security +- Active-PR Workforce Validation final-analysis-weight and final-weight-component-binding views now keep their issuance seals in closure-private runtime state. Importable module markers can no longer mint an authorized projection; purpose authorization, canonical owner reconstruction, effective-time currentness, field minimization, detached identities, and marker-last issuance remain unchanged. - Active-PR Workforce Validation authorized evidence views reject low-level base-constructor forging across the complete 24-class public export census. Every exported `*View` is a sealed non-tuple data object whose public constructor rejects, whose raw allocations cannot expose state, and whose only supported issuer remains its purpose-authorized owner-resolution path. The executable package-surface census now fails closed on an added, removed, tuple-backed, unsealed, or mutable public view; `CalibrationBenchmarkAuthorityView` was the final omission exposed by that census and is covered by its own issuance-integrity regression. - Predictive-validity cases fail closed when selection evidence, Job scope, study criterion, converted worker, or system-recorded visibility does not match; the normalized case relation is tenant-qualified, append-only, TRUNCATE-protected, and forced through row-level security. - Purpose-bound PII authorization now fails closed across active tenant, authenticated actor tenant, resource tenant, resource kind, purpose, operation, operation-specific Keyverse scope, and requested-field subset; malformed/wildcard-like attributes, mutable field/scope collections, reserved UUID sentinels, and cross-tenant confused-deputy contexts are rejected before protected values are returned. Authorization requests and allow/deny evidence now also require and preserve one namespaced opaque target-resource reference, so immutable audit correlation identifies the exact HR record without copying its protected values. Authorization evidence otherwise contains governance metadata and field names only, with stable denial reasons and actionable next steps rather than PII. diff --git a/manifest.json b/manifest.json index a5e906cff..81291fb6f 100644 --- a/manifest.json +++ b/manifest.json @@ -29,9 +29,9 @@ }, { "path": "CHANGELOG.md", - "sha256": "58342a98de09c87f2af451be4ba7426674dabb0cc993bd9d247168596b0402fc", - "bytes": 18915, - "lines": 80 + "sha256": "89e4dbffec24369895ffcdd2fe42b0088dbe8f4000322569fbe67ec01b2c9f6c", + "bytes": 19313, + "lines": 81 }, { "path": "CLAUDE.md", From 18fa575979fd6ad1829d30f87d45ca2183c14a6d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 07:02:33 +0900 Subject: [PATCH 558/603] test(workforce-validation): expose nonresponse view seal forgery --- ...justment_authority_view_seal_capability.py | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_view_seal_capability.py diff --git a/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_view_seal_capability.py b/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_view_seal_capability.py new file mode 100644 index 000000000..373316d07 --- /dev/null +++ b/services/workforce-validation-api/tests/test_nonresponse_adjustment_authority_view_seal_capability.py @@ -0,0 +1,58 @@ +"""Hostile sealing-capability regression for nonresponse-adjustment views.""" + +from uuid import UUID + +import pytest + +import orgmetra_workforce_validation_api.nonresponse_adjustment_authority as authority_module +from orgmetra_workforce_validation_api.nonresponse_adjustment_authority import ( + NonresponseAdjustmentAuthorityIntegrityError, + NonresponseAdjustmentAuthorityView, +) + +TENANT = UUID("00000000-0000-0000-0000-000000000425") +STUDY = UUID("00000000-0000-0000-0000-000000000426") + + +def _raw_view_with_module_marker() -> NonresponseAdjustmentAuthorityView: + """Build the strongest caller-owned exact-runtime forgery available from module state.""" + view = object.__new__(NonresponseAdjustmentAuthorityView) + object.__setattr__(view, "_tenant_identity", TENANT.int) + object.__setattr__(view, "_study_identity", STUDY.int) + object.__setattr__( + view, + "_fields", + (("nonresponse_receipt_digest", "b" * 64),), + ) + object.__setattr__( + view, + "_issuance_marker", + getattr( + authority_module, + "_NONRESPONSE_ADJUSTMENT_VIEW_ISSUANCE_MARKER", + object(), + ), + ) + return view + + +def test_module_exposes_no_nonresponse_adjustment_view_seal() -> None: + """Keep the write capability out of ordinary importable module state.""" + assert not hasattr( + authority_module, + "_NONRESPONSE_ADJUSTMENT_VIEW_ISSUANCE_MARKER", + ) + + +def test_importable_marker_cannot_mint_nonresponse_adjustment_view() -> None: + """Require caller-populated exact objects to remain unreadable.""" + forged_view = _raw_view_with_module_marker() + + with pytest.raises( + NonresponseAdjustmentAuthorityIntegrityError, + match=( + "nonresponse adjustment view was not issued by " + "resolve_nonresponse_adjustment_authority" + ), + ): + _ = forged_view.fields From bfb76208395b4778da65b027ac6a54ccb001a8cc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 07:04:36 +0900 Subject: [PATCH 559/603] fix(workforce-validation): hide nonresponse view seal capability --- .../nonresponse_adjustment_authority.py | 129 ++++++++++++++---- 1 file changed, 99 insertions(+), 30 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py index 8fad7ae9b..134e22fd2 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/nonresponse_adjustment_authority.py @@ -37,7 +37,6 @@ _RESOURCE_KIND = "nonresponse_adjustment_authority" _OPERATION = "read" -_NONRESPONSE_ADJUSTMENT_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "nonresponse_receipt_reference", @@ -378,18 +377,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject exact-runtime allocations not sealed by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise NonresponseAdjustmentAuthorityIntegrityError( - "nonresponse adjustment view was not issued by " - "resolve_nonresponse_adjustment_authority" - ) from exc - if marker is not _NONRESPONSE_ADJUSTMENT_VIEW_ISSUANCE_MARKER: - raise NonresponseAdjustmentAuthorityIntegrityError( - "nonresponse adjustment view was not issued by " - "resolve_nonresponse_adjustment_authority" - ) + _require_nonresponse_adjustment_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -457,7 +445,7 @@ def _coordinate_tuple(record: NonresponseAdjustmentAuthorityRecord) -> tuple[obj return record[:8] + record[9:22] -def resolve_nonresponse_adjustment_authority( +def _resolve_nonresponse_adjustment_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -485,7 +473,7 @@ def resolve_nonresponse_adjustment_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: NonresponseAdjustmentAuthorityReadPort, -) -> NonresponseAdjustmentAuthorityView: +) -> tuple[int, int, tuple[tuple[str, object], ...]]: """Authorize then corroborate the exact released nonresponse receipt.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") @@ -663,21 +651,102 @@ def resolve_nonresponse_adjustment_authority( ("unavailable_treatment_code", record.unavailable_treatment_code), ("unknown_treatment_code", record.unknown_treatment_code), ) - view = object.__new__(NonresponseAdjustmentAuthorityView) - object.__setattr__( - view, - "_tenant_identity", + return ( _store_operational_uuid("tenant_record_id", tenant_id), - ) - object.__setattr__( - view, - "_study_identity", _store_operational_uuid("validity_study_id", study_id), + fields, ) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, - "_issuance_marker", - _NONRESPONSE_ADJUSTMENT_VIEW_ISSUANCE_MARKER, - ) - return view + + +def _build_nonresponse_adjustment_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: NonresponseAdjustmentAuthorityView) -> None: + """Verify one nonresponse-adjustment view against the private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise NonresponseAdjustmentAuthorityIntegrityError( + "nonresponse adjustment view was not issued by " + "resolve_nonresponse_adjustment_authority" + ) from exc + if marker is not issuance_marker: + raise NonresponseAdjustmentAuthorityIntegrityError( + "nonresponse adjustment view was not issued by " + "resolve_nonresponse_adjustment_authority" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + nonresponse_receipt_reference: str, + nonresponse_receipt_digest: str, + evidence_version: int, + response_disposition_receipt_reference: str, + response_disposition_receipt_version: int, + response_disposition_receipt_digest: str, + adjustment_population_digest: str, + method_reference: str, + method_version: int, + configuration_digest: str, + ineligible_treatment_code: str, + unknown_treatment_code: str, + unavailable_treatment_code: str, + input_weight_artifact_digest: str, + output_weight_artifact_digest: str, + constructed_at: datetime, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: NonresponseAdjustmentAuthorityReadPort, + ) -> NonresponseAdjustmentAuthorityView: + """Authorize then issue the exact released nonresponse receipt projection.""" + tenant_identity, study_identity, fields = _resolve_nonresponse_adjustment_authority_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + nonresponse_receipt_reference=nonresponse_receipt_reference, + nonresponse_receipt_digest=nonresponse_receipt_digest, + evidence_version=evidence_version, + response_disposition_receipt_reference=response_disposition_receipt_reference, + response_disposition_receipt_version=response_disposition_receipt_version, + response_disposition_receipt_digest=response_disposition_receipt_digest, + adjustment_population_digest=adjustment_population_digest, + method_reference=method_reference, + method_version=method_version, + configuration_digest=configuration_digest, + ineligible_treatment_code=ineligible_treatment_code, + unknown_treatment_code=unknown_treatment_code, + unavailable_treatment_code=unavailable_treatment_code, + input_weight_artifact_digest=input_weight_artifact_digest, + output_weight_artifact_digest=output_weight_artifact_digest, + constructed_at=constructed_at, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + view = object.__new__(NonresponseAdjustmentAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_nonresponse_adjustment_view_issued, + resolve_nonresponse_adjustment_authority, +) = _build_nonresponse_adjustment_view_runtime() +del _build_nonresponse_adjustment_view_runtime From 35b8420522d605cad0ee9857f66e09e5603d5eab Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 07:12:53 +0900 Subject: [PATCH 560/603] test(workforce-validation): expose result view seal forgery --- ...n_result_authority_view_issuance_integrity.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/services/workforce-validation-api/tests/test_validation_result_authority_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_validation_result_authority_view_issuance_integrity.py index 1dc285fa2..49645366c 100644 --- a/services/workforce-validation-api/tests/test_validation_result_authority_view_issuance_integrity.py +++ b/services/workforce-validation-api/tests/test_validation_result_authority_view_issuance_integrity.py @@ -4,6 +4,7 @@ import pytest +import orgmetra_workforce_validation_api.result_authority as authority_module from orgmetra_workforce_validation_api.result_authority import ( ValidationResultAuthorityIntegrityError, ValidationResultAuthorityView, @@ -14,6 +15,21 @@ STUDY = UUID("00000000-0000-7000-8000-0000000000f2") +def test_importable_marker_cannot_mint_validation_result_view() -> None: + """Keep the validation-result view seal outside importable module state.""" + marker_name = "_VALIDATION_RESULT_VIEW_ISSUANCE_MARKER" + assert not hasattr(authority_module, marker_name) + + forged_view = object.__new__(ValidationResultAuthorityView) + object.__setattr__(forged_view, "_tenant_identity", TENANT.int) + object.__setattr__(forged_view, "_study_identity", STUDY.int) + object.__setattr__(forged_view, "_fields", ()) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises(ValidationResultAuthorityIntegrityError): + _ = forged_view.fields + + def test_low_level_tuple_construction_cannot_issue_validation_result_view() -> None: """Remove tuple's base constructor as an alternate authorized-view issuer.""" with pytest.raises(TypeError): From 99ef4c06c9f3fb3ba0787abd229fd797e67640cb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 07:14:00 +0900 Subject: [PATCH 561/603] fix(workforce-validation): hide validation-result view seal --- .../result_authority.py | 107 ++++++++++++++---- 1 file changed, 82 insertions(+), 25 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py index cc3d37772..463cedf20 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_authority.py @@ -37,7 +37,6 @@ _RESOURCE_KIND = "validation_result_authority" _OPERATION = "read" -_VALIDATION_RESULT_VIEW_ISSUANCE_MARKER = object() _VERIFICATION_STATUSES = frozenset({"verification_pending", "not_verifiable"}) _READ_FIELDS = frozenset( { @@ -279,18 +278,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject exact-runtime allocations not sealed by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise ValidationResultAuthorityIntegrityError( - "validation result view was not issued by " - "resolve_validation_result_authority" - ) from exc - if marker is not _VALIDATION_RESULT_VIEW_ISSUANCE_MARKER: - raise ValidationResultAuthorityIntegrityError( - "validation result view was not issued by " - "resolve_validation_result_authority" - ) + _require_validation_result_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -344,7 +332,7 @@ def read_validation_result_authority( ) -def resolve_validation_result_authority( +def _resolve_validation_result_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -363,7 +351,7 @@ def resolve_validation_result_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: ValidationResultAuthorityReadPort, -) -> ValidationResultAuthorityView: +) -> tuple[int, int, tuple[tuple[str, object], ...]]: """Authorize then corroborate one exact released scientific-result binding.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") @@ -548,13 +536,82 @@ def resolve_validation_result_authority( "superseded_at": record.superseded_at, } fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) - view = object.__new__(ValidationResultAuthorityView) - object.__setattr__(view, "_tenant_identity", tenant_identity) - object.__setattr__(view, "_study_identity", study_identity) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, - "_issuance_marker", - _VALIDATION_RESULT_VIEW_ISSUANCE_MARKER, - ) - return view + return tenant_identity, study_identity, fields + + +def _build_validation_result_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: ValidationResultAuthorityView) -> None: + """Verify one validation-result view against the private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise ValidationResultAuthorityIntegrityError( + "validation result view was not issued by " + "resolve_validation_result_authority" + ) from exc + if marker is not issuance_marker: + raise ValidationResultAuthorityIntegrityError( + "validation result view was not issued by " + "resolve_validation_result_authority" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + compatibility_receipt_reference: str, + compatibility_receipt_digest: str, + analysis_weight_receipt_digest: str, + variance_design_receipt_digest: str, + verification_status: str, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: ValidationResultAuthorityReadPort, + ) -> ValidationResultAuthorityView: + """Authorize then issue one exact released scientific-result binding.""" + tenant_identity, study_identity, fields = ( + _resolve_validation_result_authority_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + result_reference=result_reference, + result_digest=result_digest, + compatibility_receipt_reference=compatibility_receipt_reference, + compatibility_receipt_digest=compatibility_receipt_digest, + analysis_weight_receipt_digest=analysis_weight_receipt_digest, + variance_design_receipt_digest=variance_design_receipt_digest, + verification_status=verification_status, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + ) + view = object.__new__(ValidationResultAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_validation_result_view_issued, + resolve_validation_result_authority, +) = _build_validation_result_view_runtime() +del _build_validation_result_view_runtime From a417e7cbe4062b145c24a56ee657c0d3a9df88a6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 07:14:46 +0900 Subject: [PATCH 562/603] test(workforce-validation): expose non-verifiability seal forgery --- ...t_nonverifiability_view_issuance_integrity.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_view_issuance_integrity.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_view_issuance_integrity.py index 5e9d4ffb3..6154f3af6 100644 --- a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_view_issuance_integrity.py +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_view_issuance_integrity.py @@ -4,6 +4,7 @@ import pytest +import orgmetra_workforce_validation_api.result_nonverifiability as authority_module from orgmetra_workforce_validation_api.result_nonverifiability import ( ValidationResultNonVerifiabilityIntegrityError, ValidationResultNonVerifiabilityView, @@ -14,6 +15,21 @@ STUDY = UUID("00000000-0000-7000-8000-0000000000f2") +def test_importable_marker_cannot_mint_nonverifiability_view() -> None: + """Keep the non-verifiability view seal outside importable module state.""" + marker_name = "_VALIDATION_RESULT_NONVERIFIABILITY_VIEW_ISSUANCE_MARKER" + assert not hasattr(authority_module, marker_name) + + forged_view = object.__new__(ValidationResultNonVerifiabilityView) + object.__setattr__(forged_view, "_tenant_identity", TENANT.int) + object.__setattr__(forged_view, "_study_identity", STUDY.int) + object.__setattr__(forged_view, "_fields", ()) + object.__setattr__(forged_view, "_issuance_marker", object()) + + with pytest.raises(ValidationResultNonVerifiabilityIntegrityError): + _ = forged_view.fields + + def test_low_level_tuple_construction_cannot_issue_nonverifiability_view() -> None: """Remove tuple's base constructor as an alternate authorized-view issuer.""" with pytest.raises(TypeError): From 484bfe609ef3998150950acfb9ccda5ca8a87107 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 07:18:06 +0900 Subject: [PATCH 563/603] fix(workforce-validation): hide non-verifiability view seal --- .../result_nonverifiability.py | 109 ++++++++++++++---- 1 file changed, 84 insertions(+), 25 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py index 82bc65ba0..653848342 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability.py @@ -38,7 +38,6 @@ _RESOURCE_KIND = "validation_result_nonverifiability" _OPERATION = "read" _VERIFICATION_STATUS = "not_verifiable" -_VALIDATION_RESULT_NONVERIFIABILITY_VIEW_ISSUANCE_MARKER = object() _FAILED_REFERENCE_KIND_BY_EVIDENCE_KIND = { "analysis_weight_receipt": "analysis_weight_receipt", "weight_variance_compatibility_receipt": "weight_variance_compatibility_receipt", @@ -386,18 +385,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject exact-runtime allocations not sealed by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise ValidationResultNonVerifiabilityIntegrityError( - "validation result non-verifiability view was not issued by " - "resolve_validation_result_nonverifiability" - ) from exc - if marker is not _VALIDATION_RESULT_NONVERIFIABILITY_VIEW_ISSUANCE_MARKER: - raise ValidationResultNonVerifiabilityIntegrityError( - "validation result non-verifiability view was not issued by " - "resolve_validation_result_nonverifiability" - ) + _require_validation_result_nonverifiability_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -453,7 +441,7 @@ def read_validation_result_nonverifiability( ) -def resolve_validation_result_nonverifiability( +def _resolve_validation_result_nonverifiability_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -473,7 +461,7 @@ def resolve_validation_result_nonverifiability( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: ValidationResultNonVerifiabilityReadPort, -) -> ValidationResultNonVerifiabilityView: +) -> tuple[int, int, tuple[tuple[str, object], ...]]: """Authorize then corroborate one exact released, non-authorizing verification attempt.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") @@ -677,13 +665,84 @@ def resolve_validation_result_nonverifiability( "superseded_at": record.superseded_at, } fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) - view = object.__new__(ValidationResultNonVerifiabilityView) - object.__setattr__(view, "_tenant_identity", tenant_identity) - object.__setattr__(view, "_study_identity", study_identity) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, - "_issuance_marker", - _VALIDATION_RESULT_NONVERIFIABILITY_VIEW_ISSUANCE_MARKER, - ) - return view + return tenant_identity, study_identity, fields + + +def _build_validation_result_nonverifiability_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: ValidationResultNonVerifiabilityView) -> None: + """Verify one non-verifiability view against the private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise ValidationResultNonVerifiabilityIntegrityError( + "validation result non-verifiability view was not issued by " + "resolve_validation_result_nonverifiability" + ) from exc + if marker is not issuance_marker: + raise ValidationResultNonVerifiabilityIntegrityError( + "validation result non-verifiability view was not issued by " + "resolve_validation_result_nonverifiability" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + failed_evidence_kind: str, + failure_mode: str, + failed_evidence_reference: str | None = None, + failed_evidence_digest: str | None = None, + verification_attempt_reference: str, + verification_attempt_digest: str, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: ValidationResultNonVerifiabilityReadPort, + ) -> ValidationResultNonVerifiabilityView: + """Authorize then issue one exact non-authorizing verification attempt.""" + tenant_identity, study_identity, fields = ( + _resolve_validation_result_nonverifiability_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + result_reference=result_reference, + result_digest=result_digest, + failed_evidence_kind=failed_evidence_kind, + failure_mode=failure_mode, + failed_evidence_reference=failed_evidence_reference, + failed_evidence_digest=failed_evidence_digest, + verification_attempt_reference=verification_attempt_reference, + verification_attempt_digest=verification_attempt_digest, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + ) + view = object.__new__(ValidationResultNonVerifiabilityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_validation_result_nonverifiability_view_issued, + resolve_validation_result_nonverifiability, +) = _build_validation_result_nonverifiability_view_runtime() +del _build_validation_result_nonverifiability_view_runtime From 906361bddf4b2fa0528cc273e910599b3a1c02e3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 07:21:02 +0900 Subject: [PATCH 564/603] docs(workforce-validation): reseal authorized-view provenance --- CHANGELOG.md | 2 +- manifest.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e95e3803c..02025b05c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ All notable changes to Orgmetra will be documented in this file. ### Security -- Active-PR Workforce Validation final-analysis-weight and final-weight-component-binding views now keep their issuance seals in closure-private runtime state. Importable module markers can no longer mint an authorized projection; purpose authorization, canonical owner reconstruction, effective-time currentness, field minimization, detached identities, and marker-last issuance remain unchanged. +- Active-PR Workforce Validation final-analysis-weight, final-weight-component-binding, nonresponse-adjustment, validation-result, and validation-result non-verifiability views now keep their issuance seals in closure-private runtime state. Importable module markers can no longer mint an authorized projection; purpose authorization, canonical owner reconstruction, effective-time currentness, field minimization, detached identities, and marker-last issuance remain unchanged. - Active-PR Workforce Validation authorized evidence views reject low-level base-constructor forging across the complete 24-class public export census. Every exported `*View` is a sealed non-tuple data object whose public constructor rejects, whose raw allocations cannot expose state, and whose only supported issuer remains its purpose-authorized owner-resolution path. The executable package-surface census now fails closed on an added, removed, tuple-backed, unsealed, or mutable public view; `CalibrationBenchmarkAuthorityView` was the final omission exposed by that census and is covered by its own issuance-integrity regression. - Predictive-validity cases fail closed when selection evidence, Job scope, study criterion, converted worker, or system-recorded visibility does not match; the normalized case relation is tenant-qualified, append-only, TRUNCATE-protected, and forced through row-level security. - Purpose-bound PII authorization now fails closed across active tenant, authenticated actor tenant, resource tenant, resource kind, purpose, operation, operation-specific Keyverse scope, and requested-field subset; malformed/wildcard-like attributes, mutable field/scope collections, reserved UUID sentinels, and cross-tenant confused-deputy contexts are rejected before protected values are returned. Authorization requests and allow/deny evidence now also require and preserve one namespaced opaque target-resource reference, so immutable audit correlation identifies the exact HR record without copying its protected values. Authorization evidence otherwise contains governance metadata and field names only, with stable denial reasons and actionable next steps rather than PII. diff --git a/manifest.json b/manifest.json index 81291fb6f..a91d69d9d 100644 --- a/manifest.json +++ b/manifest.json @@ -29,8 +29,8 @@ }, { "path": "CHANGELOG.md", - "sha256": "89e4dbffec24369895ffcdd2fe42b0088dbe8f4000322569fbe67ec01b2c9f6c", - "bytes": 19313, + "sha256": "11f4a7b4b99d026a246024ec7c542063762dfcfb56746cf88e06afcd657e0bcf", + "bytes": 19394, "lines": 81 }, { From d5ae65ee959bfe5c4485dd42e3837ae226802494 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 07:24:24 +0900 Subject: [PATCH 565/603] test(workforce-validation): expose trimming view seal forgery --- .../tests/test_trimming_bounding_authority.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/services/workforce-validation-api/tests/test_trimming_bounding_authority.py b/services/workforce-validation-api/tests/test_trimming_bounding_authority.py index a7a4062fa..089be20d3 100644 --- a/services/workforce-validation-api/tests/test_trimming_bounding_authority.py +++ b/services/workforce-validation-api/tests/test_trimming_bounding_authority.py @@ -9,6 +9,7 @@ from orgmetra_keyverse_adapter import AuthorizationDeniedError, PurposeBoundAccessPolicy from orgmetra_workforce_validation_api import ValidationPrincipal +import orgmetra_workforce_validation_api.trimming_bounding_authority as authority_module from orgmetra_workforce_validation_api.trimming_bounding_authority import ( TrimmingBoundingAuthorityIntegrityError, TrimmingBoundingAuthorityNotFound, @@ -344,6 +345,21 @@ def test_view_rejects_caller_authored_issuance_marker() -> None: _ = forged.fields +def test_importable_marker_cannot_mint_trimming_bounding_view() -> None: + """Keep the trimming/bounding view seal outside importable module state.""" + marker_name = "_TRIMMING_BOUNDING_VIEW_ISSUANCE_MARKER" + assert not hasattr(authority_module, marker_name) + + forged = object.__new__(TrimmingBoundingAuthorityView) + object.__setattr__(forged, "_tenant_identity", TENANT.int) + object.__setattr__(forged, "_study_identity", STUDY.int) + object.__setattr__(forged, "_fields", ()) + object.__setattr__(forged, "_issuance_marker", object()) + + with pytest.raises(TrimmingBoundingAuthorityIntegrityError): + _ = forged.fields + + def test_issued_view_rejects_mutation_and_deletion() -> None: """Keep a resolver-issued view immutable after all owner checks complete.""" view = _resolve(read_port=_ReadPort(_record())) From 4fb57705278337e79090f8781691b474a05c09c7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 07:25:54 +0900 Subject: [PATCH 566/603] fix(workforce-validation): hide trimming view seal --- .../trimming_bounding_authority.py | 117 ++++++++++++++---- 1 file changed, 92 insertions(+), 25 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py index a22657ef3..2edb93698 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_authority.py @@ -35,7 +35,6 @@ _RESOURCE_KIND = "trimming_bounding_authority" _OPERATION = "read" -_TRIMMING_BOUNDING_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "adjustment_receipt_reference", @@ -307,16 +306,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Require the exact in-process marker written by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise TrimmingBoundingAuthorityIntegrityError( - "trimming/bounding authority view was not issued by the resolver" - ) from exc - if marker is not _TRIMMING_BOUNDING_VIEW_ISSUANCE_MARKER: - raise TrimmingBoundingAuthorityIntegrityError( - "trimming/bounding authority view has an invalid issuance marker" - ) + _require_trimming_bounding_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -379,7 +369,7 @@ def _coordinate_tuple(record: TrimmingBoundingAuthorityRecord) -> tuple[object, return record[:16] -def resolve_trimming_bounding_authority( +def _resolve_trimming_bounding_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -402,8 +392,8 @@ def resolve_trimming_bounding_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: TrimmingBoundingAuthorityReadPort, -) -> TrimmingBoundingAuthorityView: - """Authorize then corroborate exact released trimming/bounding evidence.""" +) -> tuple[int, int, tuple[tuple[str, object], ...]]: + """Authorize and corroborate exact released trimming/bounding evidence.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") if type(policy) is not PurposeBoundAccessPolicy: @@ -553,15 +543,92 @@ def resolve_trimming_bounding_authority( ("rule_version", record.rule_version), ("superseded_at", record.superseded_at), ) - view = object.__new__(TrimmingBoundingAuthorityView) - object.__setattr__( - view, "_tenant_identity", _store_operational_uuid("tenant_record_id", tenant_id) - ) - object.__setattr__( - view, "_study_identity", _store_operational_uuid("validity_study_id", study_id) + return ( + _store_operational_uuid("tenant_record_id", tenant_id), + _store_operational_uuid("validity_study_id", study_id), + fields, ) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, "_issuance_marker", _TRIMMING_BOUNDING_VIEW_ISSUANCE_MARKER - ) - return view + + +def _build_trimming_bounding_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: TrimmingBoundingAuthorityView) -> None: + """Verify one trimming/bounding view against the private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise TrimmingBoundingAuthorityIntegrityError( + "trimming/bounding authority view was not issued by the resolver" + ) from exc + if marker is not issuance_marker: + raise TrimmingBoundingAuthorityIntegrityError( + "trimming/bounding authority view has an invalid issuance marker" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + adjustment_receipt_reference: str, + adjustment_receipt_digest: str, + evidence_version: int, + rule_reference: str, + rule_version: int, + rule_configuration_digest: str, + affected_case_occurrence_set_digest: str, + affected_case_count: int, + input_weight_artifact_digest: str, + output_weight_artifact_digest: str, + constructed_at: datetime, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: TrimmingBoundingAuthorityReadPort, + ) -> TrimmingBoundingAuthorityView: + """Authorize then issue exact released trimming/bounding evidence.""" + tenant_identity, study_identity, fields = ( + _resolve_trimming_bounding_authority_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + adjustment_receipt_reference=adjustment_receipt_reference, + adjustment_receipt_digest=adjustment_receipt_digest, + evidence_version=evidence_version, + rule_reference=rule_reference, + rule_version=rule_version, + rule_configuration_digest=rule_configuration_digest, + affected_case_occurrence_set_digest=affected_case_occurrence_set_digest, + affected_case_count=affected_case_count, + input_weight_artifact_digest=input_weight_artifact_digest, + output_weight_artifact_digest=output_weight_artifact_digest, + constructed_at=constructed_at, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + ) + view = object.__new__(TrimmingBoundingAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_trimming_bounding_view_issued, + resolve_trimming_bounding_authority, +) = _build_trimming_bounding_view_runtime() +del _build_trimming_bounding_view_runtime From fccb76ecd1e4edf0053d9d33e81e6625c46725a4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 07:26:38 +0900 Subject: [PATCH 567/603] docs(workforce-validation): reseal trimming-view provenance --- CHANGELOG.md | 2 +- manifest.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02025b05c..e57a783eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ All notable changes to Orgmetra will be documented in this file. ### Security -- Active-PR Workforce Validation final-analysis-weight, final-weight-component-binding, nonresponse-adjustment, validation-result, and validation-result non-verifiability views now keep their issuance seals in closure-private runtime state. Importable module markers can no longer mint an authorized projection; purpose authorization, canonical owner reconstruction, effective-time currentness, field minimization, detached identities, and marker-last issuance remain unchanged. +- Active-PR Workforce Validation final-analysis-weight, final-weight-component-binding, nonresponse-adjustment, trimming/bounding, validation-result, and validation-result non-verifiability views now keep their issuance seals in closure-private runtime state. Importable module markers can no longer mint an authorized projection; purpose authorization, canonical owner reconstruction, effective-time currentness, field minimization, detached identities, and marker-last issuance remain unchanged. - Active-PR Workforce Validation authorized evidence views reject low-level base-constructor forging across the complete 24-class public export census. Every exported `*View` is a sealed non-tuple data object whose public constructor rejects, whose raw allocations cannot expose state, and whose only supported issuer remains its purpose-authorized owner-resolution path. The executable package-surface census now fails closed on an added, removed, tuple-backed, unsealed, or mutable public view; `CalibrationBenchmarkAuthorityView` was the final omission exposed by that census and is covered by its own issuance-integrity regression. - Predictive-validity cases fail closed when selection evidence, Job scope, study criterion, converted worker, or system-recorded visibility does not match; the normalized case relation is tenant-qualified, append-only, TRUNCATE-protected, and forced through row-level security. - Purpose-bound PII authorization now fails closed across active tenant, authenticated actor tenant, resource tenant, resource kind, purpose, operation, operation-specific Keyverse scope, and requested-field subset; malformed/wildcard-like attributes, mutable field/scope collections, reserved UUID sentinels, and cross-tenant confused-deputy contexts are rejected before protected values are returned. Authorization requests and allow/deny evidence now also require and preserve one namespaced opaque target-resource reference, so immutable audit correlation identifies the exact HR record without copying its protected values. Authorization evidence otherwise contains governance metadata and field names only, with stable denial reasons and actionable next steps rather than PII. diff --git a/manifest.json b/manifest.json index a91d69d9d..af0f31d51 100644 --- a/manifest.json +++ b/manifest.json @@ -29,8 +29,8 @@ }, { "path": "CHANGELOG.md", - "sha256": "11f4a7b4b99d026a246024ec7c542063762dfcfb56746cf88e06afcd657e0bcf", - "bytes": 19394, + "sha256": "7f7904b197f61a6378b30b43f475198dace84397a60de431edd007580a2da30a", + "bytes": 19413, "lines": 81 }, { From 5d84a12eac39adc35e5429dbb072fc57396d2aea Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 07:59:41 +0900 Subject: [PATCH 568/603] test(workforce-validation): expose trimming supersession seal forgery --- ...rsession_authority_view_seal_capability.py | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_trimming_bounding_supersession_authority_view_seal_capability.py diff --git a/services/workforce-validation-api/tests/test_trimming_bounding_supersession_authority_view_seal_capability.py b/services/workforce-validation-api/tests/test_trimming_bounding_supersession_authority_view_seal_capability.py new file mode 100644 index 000000000..5989078b2 --- /dev/null +++ b/services/workforce-validation-api/tests/test_trimming_bounding_supersession_authority_view_seal_capability.py @@ -0,0 +1,58 @@ +"""Hostile sealing-capability regression for trimming/bounding supersession views.""" + +from uuid import UUID + +import pytest + +import orgmetra_workforce_validation_api.trimming_bounding_supersession_authority as authority_module +from orgmetra_workforce_validation_api.trimming_bounding_supersession_authority import ( + TrimmingBoundingSupersessionAuthorityIntegrityError, + TrimmingBoundingSupersessionAuthorityView, +) + +TENANT = UUID("00000000-0000-0000-0000-000000000425") +STUDY = UUID("00000000-0000-0000-0000-000000000426") + + +def _raw_view_with_module_marker() -> TrimmingBoundingSupersessionAuthorityView: + """Build the strongest caller-owned exact-runtime forgery available from module state.""" + view = object.__new__(TrimmingBoundingSupersessionAuthorityView) + object.__setattr__(view, "_tenant_identity", TENANT.int) + object.__setattr__(view, "_study_identity", STUDY.int) + object.__setattr__( + view, + "_fields", + (("adjustment_receipt_digest", "b" * 64),), + ) + object.__setattr__( + view, + "_issuance_marker", + getattr( + authority_module, + "_TRIMMING_BOUNDING_SUPERSESSION_VIEW_ISSUANCE_MARKER", + object(), + ), + ) + return view + + +def test_module_exposes_no_trimming_bounding_supersession_view_seal() -> None: + """Keep the write capability out of ordinary importable module state.""" + assert not hasattr( + authority_module, + "_TRIMMING_BOUNDING_SUPERSESSION_VIEW_ISSUANCE_MARKER", + ) + + +def test_importable_marker_cannot_mint_trimming_bounding_supersession_view() -> None: + """Require caller-populated exact objects to remain unreadable.""" + forged_view = _raw_view_with_module_marker() + + with pytest.raises( + TrimmingBoundingSupersessionAuthorityIntegrityError, + match=( + "trimming/bounding supersession view was not issued by " + "resolve_trimming_bounding_supersession_authority" + ), + ): + _ = forged_view.fields From ec650728902f2a18e740cbe01f955f91aad51662 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:01:18 +0900 Subject: [PATCH 569/603] fix(workforce-validation): privatize trimming supersession view seal --- ...rimming_bounding_supersession_authority.py | 111 ++++++++++++------ 1 file changed, 78 insertions(+), 33 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_supersession_authority.py index 178265fb5..aa9f60b55 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/trimming_bounding_supersession_authority.py @@ -36,7 +36,6 @@ _RESOURCE_KIND = "trimming_bounding_supersession_authority" _OPERATION = "read" -_TRIMMING_BOUNDING_SUPERSESSION_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "adjustment_receipt_reference", @@ -259,18 +258,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject exact-runtime allocations not sealed by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise TrimmingBoundingSupersessionAuthorityIntegrityError( - "trimming/bounding supersession view was not issued by " - "resolve_trimming_bounding_supersession_authority" - ) from exc - if marker is not _TRIMMING_BOUNDING_SUPERSESSION_VIEW_ISSUANCE_MARKER: - raise TrimmingBoundingSupersessionAuthorityIntegrityError( - "trimming/bounding supersession view was not issued by " - "resolve_trimming_bounding_supersession_authority" - ) + _require_trimming_bounding_supersession_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -321,7 +309,7 @@ def read_trimming_bounding_supersession_authority( ) -def resolve_trimming_bounding_supersession_authority( +def _resolve_trimming_bounding_supersession_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -336,8 +324,8 @@ def resolve_trimming_bounding_supersession_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: TrimmingBoundingSupersessionAuthorityReadPort, -) -> TrimmingBoundingSupersessionAuthorityView: - """Authorize then resolve the receipt's half-open append-only authority interval.""" +) -> tuple[int, int, tuple[tuple[str, object], ...]]: + """Authorize and resolve trimming supersession into inert projection state.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") if type(policy) is not PurposeBoundAccessPolicy: @@ -496,21 +484,78 @@ def resolve_trimming_bounding_supersession_authority( "released_at", ) ) - view = object.__new__(TrimmingBoundingSupersessionAuthorityView) - object.__setattr__( - view, - "_tenant_identity", - _store_operational_uuid("tenant_record_id", tenant_id), - ) - object.__setattr__( - view, - "_study_identity", - _store_operational_uuid("validity_study_id", study_id), + return ( + _store_operational_uuid("tenant_record_id", record.tenant_record_id), + _store_operational_uuid("validity_study_id", record.validity_study_id), + fields, ) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, - "_issuance_marker", - _TRIMMING_BOUNDING_SUPERSESSION_VIEW_ISSUANCE_MARKER, - ) - return view + + +def _build_trimming_bounding_supersession_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: TrimmingBoundingSupersessionAuthorityView) -> None: + """Verify one supersession view against the closure-private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise TrimmingBoundingSupersessionAuthorityIntegrityError( + "trimming/bounding supersession view was not issued by " + "resolve_trimming_bounding_supersession_authority" + ) from exc + if marker is not issuance_marker: + raise TrimmingBoundingSupersessionAuthorityIntegrityError( + "trimming/bounding supersession view was not issued by " + "resolve_trimming_bounding_supersession_authority" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + adjustment_receipt_reference: str, + adjustment_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: TrimmingBoundingSupersessionAuthorityReadPort, + ) -> TrimmingBoundingSupersessionAuthorityView: + """Authorize then resolve the trimming receipt authority interval.""" + tenant_identity, study_identity, fields = ( + _resolve_trimming_bounding_supersession_authority_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + adjustment_receipt_reference=adjustment_receipt_reference, + adjustment_receipt_digest=adjustment_receipt_digest, + evidence_version=evidence_version, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + ) + view = object.__new__(TrimmingBoundingSupersessionAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_trimming_bounding_supersession_view_issued, + resolve_trimming_bounding_supersession_authority, +) = _build_trimming_bounding_supersession_view_runtime() +del _build_trimming_bounding_supersession_view_runtime From 47601be56ab3dc66846338b221d97d649076ae81 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:01:50 +0900 Subject: [PATCH 570/603] test(workforce-validation): expose result supersession seal forgery --- ...rsession_authority_view_seal_capability.py | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_supersession_authority_view_seal_capability.py diff --git a/services/workforce-validation-api/tests/test_validation_result_supersession_authority_view_seal_capability.py b/services/workforce-validation-api/tests/test_validation_result_supersession_authority_view_seal_capability.py new file mode 100644 index 000000000..fd9367834 --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_supersession_authority_view_seal_capability.py @@ -0,0 +1,58 @@ +"""Hostile sealing-capability regression for validation-result supersession views.""" + +from uuid import UUID + +import pytest + +import orgmetra_workforce_validation_api.result_supersession_authority as authority_module +from orgmetra_workforce_validation_api.result_supersession_authority import ( + ValidationResultSupersessionAuthorityIntegrityError, + ValidationResultSupersessionAuthorityView, +) + +TENANT = UUID("00000000-0000-0000-0000-000000000427") +STUDY = UUID("00000000-0000-0000-0000-000000000428") + + +def _raw_view_with_module_marker() -> ValidationResultSupersessionAuthorityView: + """Build the strongest caller-owned exact-runtime forgery available from module state.""" + view = object.__new__(ValidationResultSupersessionAuthorityView) + object.__setattr__(view, "_tenant_identity", TENANT.int) + object.__setattr__(view, "_study_identity", STUDY.int) + object.__setattr__( + view, + "_fields", + (("result_digest", "b" * 64),), + ) + object.__setattr__( + view, + "_issuance_marker", + getattr( + authority_module, + "_VALIDATION_RESULT_SUPERSESSION_VIEW_ISSUANCE_MARKER", + object(), + ), + ) + return view + + +def test_module_exposes_no_validation_result_supersession_view_seal() -> None: + """Keep the write capability out of ordinary importable module state.""" + assert not hasattr( + authority_module, + "_VALIDATION_RESULT_SUPERSESSION_VIEW_ISSUANCE_MARKER", + ) + + +def test_importable_marker_cannot_mint_validation_result_supersession_view() -> None: + """Require caller-populated exact objects to remain unreadable.""" + forged_view = _raw_view_with_module_marker() + + with pytest.raises( + ValidationResultSupersessionAuthorityIntegrityError, + match=( + "validation result supersession view was not issued by " + "resolve_validation_result_supersession_authority" + ), + ): + _ = forged_view.fields From 83d2623c565afc1d25565952079280844f083d19 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:02:27 +0900 Subject: [PATCH 571/603] fix(workforce-validation): privatize result supersession view seal --- .../result_supersession_authority.py | 113 +++++++++++++----- 1 file changed, 80 insertions(+), 33 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py index a976bfc40..08895fa5c 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_supersession_authority.py @@ -36,7 +36,6 @@ _RESOURCE_KIND = "validation_result_supersession_authority" _OPERATION = "read" -_VALIDATION_RESULT_SUPERSESSION_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "result_reference", @@ -273,18 +272,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject exact-runtime allocations not sealed by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise ValidationResultSupersessionAuthorityIntegrityError( - "validation result supersession view was not issued by " - "resolve_validation_result_supersession_authority" - ) from exc - if marker is not _VALIDATION_RESULT_SUPERSESSION_VIEW_ISSUANCE_MARKER: - raise ValidationResultSupersessionAuthorityIntegrityError( - "validation result supersession view was not issued by " - "resolve_validation_result_supersession_authority" - ) + _require_validation_result_supersession_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -336,7 +324,7 @@ def read_validation_result_supersession_authority( ) -def resolve_validation_result_supersession_authority( +def _resolve_validation_result_supersession_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -352,8 +340,8 @@ def resolve_validation_result_supersession_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: ValidationResultSupersessionAuthorityReadPort, -) -> ValidationResultSupersessionAuthorityView: - """Authorize then resolve the result's half-open append-only authority interval.""" +) -> tuple[int, int, tuple[tuple[str, object], ...]]: + """Authorize and resolve validation-result supersession into inert projection state.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") if type(policy) is not PurposeBoundAccessPolicy: @@ -514,24 +502,83 @@ def resolve_validation_result_supersession_authority( "released_at": record.released_at, } fields = tuple((field_name, values[field_name]) for field_name in sorted(_VIEW_FIELDS)) - view = object.__new__(ValidationResultSupersessionAuthorityView) - object.__setattr__( - view, - "_tenant_identity", - _store_operational_uuid("tenant_record_id", tenant_id), - ) - object.__setattr__( - view, - "_study_identity", - _store_operational_uuid("validity_study_id", study_id), + return ( + _store_operational_uuid("tenant_record_id", record.tenant_record_id), + _store_operational_uuid("validity_study_id", record.validity_study_id), + fields, ) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, - "_issuance_marker", - _VALIDATION_RESULT_SUPERSESSION_VIEW_ISSUANCE_MARKER, - ) - return view + + +def _build_validation_result_supersession_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: ValidationResultSupersessionAuthorityView) -> None: + """Verify one supersession view against the closure-private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise ValidationResultSupersessionAuthorityIntegrityError( + "validation result supersession view was not issued by " + "resolve_validation_result_supersession_authority" + ) from exc + if marker is not issuance_marker: + raise ValidationResultSupersessionAuthorityIntegrityError( + "validation result supersession view was not issued by " + "resolve_validation_result_supersession_authority" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + evidence_version: int, + correction_sequence: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: ValidationResultSupersessionAuthorityReadPort, + ) -> ValidationResultSupersessionAuthorityView: + """Authorize then resolve the validation-result authority interval.""" + tenant_identity, study_identity, fields = ( + _resolve_validation_result_supersession_authority_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + result_reference=result_reference, + result_digest=result_digest, + evidence_version=evidence_version, + correction_sequence=correction_sequence, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + ) + view = object.__new__(ValidationResultSupersessionAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_validation_result_supersession_view_issued, + resolve_validation_result_supersession_authority, +) = _build_validation_result_supersession_view_runtime() +del _build_validation_result_supersession_view_runtime __all__ = [ From 2b282cf241996386bc796e8e4ac9c6644c3e6270 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:03:01 +0900 Subject: [PATCH 572/603] test(workforce-validation): expose nonverifiability supersession seal forgery --- ...rsession_authority_view_seal_capability.py | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_view_seal_capability.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_view_seal_capability.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_view_seal_capability.py new file mode 100644 index 000000000..0aac2f43d --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_authority_view_seal_capability.py @@ -0,0 +1,58 @@ +"""Hostile sealing-capability regression for non-verifiability supersession views.""" + +from uuid import UUID + +import pytest + +import orgmetra_workforce_validation_api.result_nonverifiability_supersession_authority as authority_module +from orgmetra_workforce_validation_api.result_nonverifiability_supersession_authority import ( + ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError, + ValidationResultNonVerifiabilitySupersessionAuthorityView, +) + +TENANT = UUID("00000000-0000-0000-0000-000000000429") +STUDY = UUID("00000000-0000-0000-0000-000000000430") + + +def _raw_view_with_module_marker() -> ValidationResultNonVerifiabilitySupersessionAuthorityView: + """Build the strongest caller-owned exact-runtime forgery available from module state.""" + view = object.__new__(ValidationResultNonVerifiabilitySupersessionAuthorityView) + object.__setattr__(view, "_tenant_identity", TENANT.int) + object.__setattr__(view, "_study_identity", STUDY.int) + object.__setattr__( + view, + "_fields", + (("result_digest", "b" * 64),), + ) + object.__setattr__( + view, + "_issuance_marker", + getattr( + authority_module, + "_VALIDATION_RESULT_NONVERIFIABILITY_SUPERSESSION_VIEW_ISSUANCE_MARKER", + object(), + ), + ) + return view + + +def test_module_exposes_no_nonverifiability_supersession_view_seal() -> None: + """Keep the write capability out of ordinary importable module state.""" + assert not hasattr( + authority_module, + "_VALIDATION_RESULT_NONVERIFIABILITY_SUPERSESSION_VIEW_ISSUANCE_MARKER", + ) + + +def test_importable_marker_cannot_mint_nonverifiability_supersession_view() -> None: + """Require caller-populated exact objects to remain unreadable.""" + forged_view = _raw_view_with_module_marker() + + with pytest.raises( + ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError, + match=( + "validation result non-verifiability supersession view was not issued by " + "resolve_validation_result_nonverifiability_supersession_authority" + ), + ): + _ = forged_view.fields From 64477a500a99c14de85a16c2d060b919421377e0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:03:45 +0900 Subject: [PATCH 573/603] fix(workforce-validation): privatize nonverifiability supersession seal --- ...nonverifiability_supersession_authority.py | 121 +++++++++++++----- 1 file changed, 88 insertions(+), 33 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py index 6bba59a08..39e822259 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_authority.py @@ -40,7 +40,6 @@ _RESOURCE_KIND = "validation_result_nonverifiability_supersession_authority" _OPERATION = "read" -_VALIDATION_RESULT_NONVERIFIABILITY_SUPERSESSION_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "result_reference", @@ -338,18 +337,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject exact-runtime allocations not sealed by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError( - "validation result non-verifiability supersession view was not issued by " - "resolve_validation_result_nonverifiability_supersession_authority" - ) from exc - if marker is not _VALIDATION_RESULT_NONVERIFIABILITY_SUPERSESSION_VIEW_ISSUANCE_MARKER: - raise ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError( - "validation result non-verifiability supersession view was not issued by " - "resolve_validation_result_nonverifiability_supersession_authority" - ) + _require_validation_result_nonverifiability_supersession_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -404,7 +392,7 @@ def read_validation_result_nonverifiability_supersession_authority( ) -def resolve_validation_result_nonverifiability_supersession_authority( +def _resolve_validation_result_nonverifiability_supersession_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -423,8 +411,8 @@ def resolve_validation_result_nonverifiability_supersession_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: ValidationResultNonVerifiabilitySupersessionAuthorityReadPort, -) -> ValidationResultNonVerifiabilitySupersessionAuthorityView: - """Authorize then resolve one negative outcome's append-only authority interval.""" +) -> tuple[int, int, tuple[tuple[str, object], ...]]: + """Authorize and resolve non-verifiability supersession into inert view state.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") if type(policy) is not PurposeBoundAccessPolicy: @@ -615,24 +603,91 @@ def resolve_validation_result_nonverifiability_supersession_authority( values = {**record_values, "released_at": record.released_at} fields = tuple((field_name, values[field_name]) for field_name in sorted(_VIEW_FIELDS)) - view = object.__new__(ValidationResultNonVerifiabilitySupersessionAuthorityView) - object.__setattr__( - view, - "_tenant_identity", - _store_operational_uuid("tenant_record_id", tenant_id), - ) - object.__setattr__( - view, - "_study_identity", - _store_operational_uuid("validity_study_id", study_id), - ) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, - "_issuance_marker", - _VALIDATION_RESULT_NONVERIFIABILITY_SUPERSESSION_VIEW_ISSUANCE_MARKER, + return ( + _store_operational_uuid("tenant_record_id", record.tenant_record_id), + _store_operational_uuid("validity_study_id", record.validity_study_id), + fields, ) - return view + + +def _build_validation_result_nonverifiability_supersession_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued( + view: ValidationResultNonVerifiabilitySupersessionAuthorityView, + ) -> None: + """Verify one supersession view against the closure-private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError( + "validation result non-verifiability supersession view was not issued by " + "resolve_validation_result_nonverifiability_supersession_authority" + ) from exc + if marker is not issuance_marker: + raise ValidationResultNonVerifiabilitySupersessionAuthorityIntegrityError( + "validation result non-verifiability supersession view was not issued by " + "resolve_validation_result_nonverifiability_supersession_authority" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + failed_evidence_kind: str, + failure_mode: str, + verification_attempt_reference: str, + verification_attempt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: ValidationResultNonVerifiabilitySupersessionAuthorityReadPort, + ) -> ValidationResultNonVerifiabilitySupersessionAuthorityView: + """Authorize then resolve one negative outcome's authority interval.""" + tenant_identity, study_identity, fields = ( + _resolve_validation_result_nonverifiability_supersession_authority_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + result_reference=result_reference, + result_digest=result_digest, + failed_evidence_kind=failed_evidence_kind, + failure_mode=failure_mode, + verification_attempt_reference=verification_attempt_reference, + verification_attempt_digest=verification_attempt_digest, + evidence_version=evidence_version, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + ) + view = object.__new__(ValidationResultNonVerifiabilitySupersessionAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_validation_result_nonverifiability_supersession_view_issued, + resolve_validation_result_nonverifiability_supersession_authority, +) = _build_validation_result_nonverifiability_supersession_view_runtime() +del _build_validation_result_nonverifiability_supersession_view_runtime __all__ = [ From 73b027cbfcd3cc781430a875711f45124ecd1ee8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:05:10 +0900 Subject: [PATCH 574/603] test(workforce-validation): expose v2 nonverifiability supersession seal forgery --- ...ssion_v2_authority_view_seal_capability.py | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_view_seal_capability.py diff --git a/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_view_seal_capability.py b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_view_seal_capability.py new file mode 100644 index 000000000..e5d4fda7a --- /dev/null +++ b/services/workforce-validation-api/tests/test_validation_result_nonverifiability_supersession_v2_authority_view_seal_capability.py @@ -0,0 +1,54 @@ +"""Hostile sealing-capability regression for v2 non-verifiability supersession views.""" + +from uuid import UUID + +import pytest + +import orgmetra_workforce_validation_api.result_nonverifiability_supersession_v2_authority as authority_module +from orgmetra_workforce_validation_api.result_nonverifiability_supersession_v2_authority import ( + ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError, + ValidationResultNonVerifiabilitySupersessionV2AuthorityView, +) + +TENANT = UUID("00000000-0000-0000-0000-000000000431") +STUDY = UUID("00000000-0000-0000-0000-000000000432") + + +def _raw_view_with_module_marker() -> ValidationResultNonVerifiabilitySupersessionV2AuthorityView: + """Build the strongest caller-owned exact-runtime forgery available from module state.""" + view = object.__new__(ValidationResultNonVerifiabilitySupersessionV2AuthorityView) + object.__setattr__(view, "_tenant_identity", TENANT.int) + object.__setattr__(view, "_study_identity", STUDY.int) + object.__setattr__(view, "_fields", (("result_digest", "b" * 64),)) + object.__setattr__( + view, + "_issuance_marker", + getattr( + authority_module, + "_VALIDATION_RESULT_NONVERIFIABILITY_SUPERSESSION_V2_VIEW_ISSUANCE_MARKER", + object(), + ), + ) + return view + + +def test_module_exposes_no_nonverifiability_supersession_v2_view_seal() -> None: + """Keep the write capability out of ordinary importable module state.""" + assert not hasattr( + authority_module, + "_VALIDATION_RESULT_NONVERIFIABILITY_SUPERSESSION_V2_VIEW_ISSUANCE_MARKER", + ) + + +def test_importable_marker_cannot_mint_nonverifiability_supersession_v2_view() -> None: + """Require caller-populated exact objects to remain unreadable.""" + forged_view = _raw_view_with_module_marker() + + with pytest.raises( + ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError, + match=( + "validation result non-verifiability supersession v2 view was not issued by " + "resolve_validation_result_nonverifiability_supersession_v2_authority" + ), + ): + _ = forged_view.fields From 3355c3593e16ca79230b0ed9bb7a443c204192de Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:05:55 +0900 Subject: [PATCH 575/603] fix(workforce-validation): privatize v2 nonverifiability supersession seal --- ...verifiability_supersession_v2_authority.py | 123 +++++++++++++----- 1 file changed, 90 insertions(+), 33 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py index 189a2dcd8..6e7aa5886 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/result_nonverifiability_supersession_v2_authority.py @@ -32,7 +32,6 @@ _RESOURCE_KIND = "validation_result_nonverifiability_supersession_authority" _OPERATION = "read" _VERSION = 2 -_VALIDATION_RESULT_NONVERIFIABILITY_SUPERSESSION_V2_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "result_reference", @@ -357,18 +356,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject exact-runtime allocations not sealed by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError( - "validation result non-verifiability supersession v2 view was not issued by " - "resolve_validation_result_nonverifiability_supersession_v2_authority" - ) from exc - if marker is not _VALIDATION_RESULT_NONVERIFIABILITY_SUPERSESSION_V2_VIEW_ISSUANCE_MARKER: - raise ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError( - "validation result non-verifiability supersession v2 view was not issued by " - "resolve_validation_result_nonverifiability_supersession_v2_authority" - ) + _require_validation_result_nonverifiability_supersession_v2_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -424,7 +412,7 @@ def read_validation_result_nonverifiability_supersession_v2_authority( ) -def resolve_validation_result_nonverifiability_supersession_v2_authority( +def _resolve_validation_result_nonverifiability_supersession_v2_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -444,8 +432,8 @@ def resolve_validation_result_nonverifiability_supersession_v2_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: ValidationResultNonVerifiabilitySupersessionV2AuthorityReadPort, -) -> ValidationResultNonVerifiabilitySupersessionV2AuthorityView: - """Authorize then resolve one exact-artifact non-reproducible correction interval.""" +) -> tuple[int, int, tuple[tuple[str, object], ...]]: + """Authorize and resolve exact-artifact supersession into inert view state.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") if type(policy) is not PurposeBoundAccessPolicy: @@ -599,24 +587,93 @@ def resolve_validation_result_nonverifiability_supersession_v2_authority( ) projection_values = {**values, "released_at": persisted.released_at} fields = tuple((name, projection_values[name]) for name in sorted(_VIEW_FIELDS)) - view = object.__new__(ValidationResultNonVerifiabilitySupersessionV2AuthorityView) - object.__setattr__( - view, - "_tenant_identity", - _store_operational_uuid("tenant_record_id", tenant_id), - ) - object.__setattr__( - view, - "_study_identity", - _store_operational_uuid("validity_study_id", study_id), - ) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, - "_issuance_marker", - _VALIDATION_RESULT_NONVERIFIABILITY_SUPERSESSION_V2_VIEW_ISSUANCE_MARKER, + return ( + _store_operational_uuid("tenant_record_id", predecessor.tenant_record_id), + _store_operational_uuid("validity_study_id", predecessor.validity_study_id), + fields, ) - return view + + +def _build_validation_result_nonverifiability_supersession_v2_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued( + view: ValidationResultNonVerifiabilitySupersessionV2AuthorityView, + ) -> None: + """Verify one v2 supersession view against the closure-private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError( + "validation result non-verifiability supersession v2 view was not issued by " + "resolve_validation_result_nonverifiability_supersession_v2_authority" + ) from exc + if marker is not issuance_marker: + raise ValidationResultNonVerifiabilitySupersessionV2AuthorityIntegrityError( + "validation result non-verifiability supersession v2 view was not issued by " + "resolve_validation_result_nonverifiability_supersession_v2_authority" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + result_reference: str, + result_digest: str, + failed_evidence_kind: str, + failed_evidence_reference: str, + failed_evidence_digest: str, + verification_attempt_reference: str, + verification_attempt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: ValidationResultNonVerifiabilitySupersessionV2AuthorityReadPort, + ) -> ValidationResultNonVerifiabilitySupersessionV2AuthorityView: + """Authorize then resolve one exact-artifact correction interval.""" + tenant_identity, study_identity, fields = ( + _resolve_validation_result_nonverifiability_supersession_v2_authority_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + result_reference=result_reference, + result_digest=result_digest, + failed_evidence_kind=failed_evidence_kind, + failed_evidence_reference=failed_evidence_reference, + failed_evidence_digest=failed_evidence_digest, + verification_attempt_reference=verification_attempt_reference, + verification_attempt_digest=verification_attempt_digest, + evidence_version=evidence_version, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + ) + view = object.__new__(ValidationResultNonVerifiabilitySupersessionV2AuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_validation_result_nonverifiability_supersession_v2_view_issued, + resolve_validation_result_nonverifiability_supersession_v2_authority, +) = _build_validation_result_nonverifiability_supersession_v2_view_runtime() +del _build_validation_result_nonverifiability_supersession_v2_view_runtime __all__ = [ From d2bcec78c9985f0ecf09fb5560665f7ca65f1e46 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:06:08 +0900 Subject: [PATCH 576/603] test(workforce-validation): expose weight eligibility seal forgery --- ...gibility_authority_view_seal_capability.py | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_eligibility_authority_view_seal_capability.py diff --git a/services/workforce-validation-api/tests/test_weight_eligibility_authority_view_seal_capability.py b/services/workforce-validation-api/tests/test_weight_eligibility_authority_view_seal_capability.py new file mode 100644 index 000000000..9cb39e1a8 --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_eligibility_authority_view_seal_capability.py @@ -0,0 +1,44 @@ +"""Hostile sealing-capability regression for weight-eligibility views.""" + +from uuid import UUID + +import pytest + +import orgmetra_workforce_validation_api.weight_eligibility_authority as authority_module +from orgmetra_workforce_validation_api.weight_eligibility_authority import ( + WeightEligibilityAuthorityIntegrityError, + WeightEligibilityAuthorityView, +) + +TENANT = UUID("00000000-0000-0000-0000-000000000433") +STUDY = UUID("00000000-0000-0000-0000-000000000434") + + +def _raw_view_with_module_marker() -> WeightEligibilityAuthorityView: + """Build the strongest caller-owned exact-runtime forgery available from module state.""" + view = object.__new__(WeightEligibilityAuthorityView) + object.__setattr__(view, "_tenant_identity", TENANT.int) + object.__setattr__(view, "_study_identity", STUDY.int) + object.__setattr__(view, "_fields", (("weight_artifact_digest", "b" * 64),)) + object.__setattr__( + view, + "_issuance_marker", + getattr(authority_module, "_WEIGHT_ELIGIBILITY_VIEW_ISSUANCE_MARKER", object()), + ) + return view + + +def test_module_exposes_no_weight_eligibility_view_seal() -> None: + """Keep the write capability out of ordinary importable module state.""" + assert not hasattr(authority_module, "_WEIGHT_ELIGIBILITY_VIEW_ISSUANCE_MARKER") + + +def test_importable_marker_cannot_mint_weight_eligibility_view() -> None: + """Require caller-populated exact objects to remain unreadable.""" + forged_view = _raw_view_with_module_marker() + + with pytest.raises( + WeightEligibilityAuthorityIntegrityError, + match="weight-eligibility authority view was not issued by the resolver", + ): + _ = forged_view.fields From c3d361a051c35534e1df6daddd11e4e8d4eaa41a Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:06:44 +0900 Subject: [PATCH 577/603] fix(workforce-validation): privatize weight eligibility view seal --- .../weight_eligibility_authority.py | 115 ++++++++++++++---- 1 file changed, 90 insertions(+), 25 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py index 45df5b2a6..fec54f29a 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_authority.py @@ -35,7 +35,6 @@ _RESOURCE_KIND = "weight_eligibility_authority" _OPERATION = "read" -_WEIGHT_ELIGIBILITY_VIEW_ISSUANCE_MARKER = object() _WEIGHT_SCOPE_CODES = frozenset({"cross_sectional", "longitudinal"}) _READ_FIELDS = frozenset( { @@ -314,16 +313,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Require the exact in-process marker written by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise WeightEligibilityAuthorityIntegrityError( - "weight-eligibility authority view was not issued by the resolver" - ) from exc - if marker is not _WEIGHT_ELIGIBILITY_VIEW_ISSUANCE_MARKER: - raise WeightEligibilityAuthorityIntegrityError( - "weight-eligibility authority view has an invalid issuance marker" - ) + _require_weight_eligibility_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -381,7 +371,7 @@ def read_weight_eligibility_authority( ) -def resolve_weight_eligibility_authority( +def _resolve_weight_eligibility_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -404,8 +394,8 @@ def resolve_weight_eligibility_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: WeightEligibilityAuthorityReadPort, -) -> WeightEligibilityAuthorityView: - """Authorize then corroborate exact released weight-eligibility evidence.""" +) -> tuple[int, int, tuple[tuple[str, object], ...]]: + """Authorize and corroborate released eligibility into inert projection state.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") if type(policy) is not PurposeBoundAccessPolicy: @@ -555,15 +545,90 @@ def resolve_weight_eligibility_authority( ("weight_artifact_digest", record.weight_artifact_digest), ("weight_scope_code", record.weight_scope_code), ) - view = object.__new__(WeightEligibilityAuthorityView) - object.__setattr__( - view, "_tenant_identity", _store_operational_uuid("tenant_record_id", tenant_id) - ) - object.__setattr__( - view, "_study_identity", _store_operational_uuid("validity_study_id", study_id) - ) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, "_issuance_marker", _WEIGHT_ELIGIBILITY_VIEW_ISSUANCE_MARKER + return ( + _store_operational_uuid("tenant_record_id", tenant_id), + _store_operational_uuid("validity_study_id", study_id), + fields, ) - return view + + +def _build_weight_eligibility_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: WeightEligibilityAuthorityView) -> None: + """Verify one eligibility view against the closure-private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise WeightEligibilityAuthorityIntegrityError( + "weight-eligibility authority view was not issued by the resolver" + ) from exc + if marker is not issuance_marker: + raise WeightEligibilityAuthorityIntegrityError( + "weight-eligibility authority view was not issued by the resolver" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + eligibility_receipt_reference: str, + eligibility_receipt_digest: str, + evidence_version: int, + weight_scope_code: str, + target_population_reference: str, + target_population_digest: str, + reference_duration_reference: str, + reference_duration_digest: str, + eligible_case_set_digest: str, + weight_artifact_digest: str, + constructed_at: datetime, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: WeightEligibilityAuthorityReadPort, + ) -> WeightEligibilityAuthorityView: + """Authorize then corroborate exact released weight-eligibility evidence.""" + tenant_identity, study_identity, fields = _resolve_weight_eligibility_authority_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + eligibility_receipt_reference=eligibility_receipt_reference, + eligibility_receipt_digest=eligibility_receipt_digest, + evidence_version=evidence_version, + weight_scope_code=weight_scope_code, + target_population_reference=target_population_reference, + target_population_digest=target_population_digest, + reference_duration_reference=reference_duration_reference, + reference_duration_digest=reference_duration_digest, + eligible_case_set_digest=eligible_case_set_digest, + weight_artifact_digest=weight_artifact_digest, + constructed_at=constructed_at, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + view = object.__new__(WeightEligibilityAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_weight_eligibility_view_issued, + resolve_weight_eligibility_authority, +) = _build_weight_eligibility_view_runtime() +del _build_weight_eligibility_view_runtime From 2b39434501078d33998c10daa97394332803db84 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:07:12 +0900 Subject: [PATCH 578/603] test(workforce-validation): expose eligibility supersession seal forgery --- ...rsession_authority_view_seal_capability.py | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority_view_seal_capability.py diff --git a/services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority_view_seal_capability.py b/services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority_view_seal_capability.py new file mode 100644 index 000000000..efef0f268 --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_eligibility_supersession_authority_view_seal_capability.py @@ -0,0 +1,54 @@ +"""Hostile sealing-capability regression for weight-eligibility supersession views.""" + +from uuid import UUID + +import pytest + +import orgmetra_workforce_validation_api.weight_eligibility_supersession_authority as authority_module +from orgmetra_workforce_validation_api.weight_eligibility_supersession_authority import ( + WeightEligibilitySupersessionAuthorityIntegrityError, + WeightEligibilitySupersessionAuthorityView, +) + +TENANT = UUID("00000000-0000-0000-0000-000000000435") +STUDY = UUID("00000000-0000-0000-0000-000000000436") + + +def _raw_view_with_module_marker() -> WeightEligibilitySupersessionAuthorityView: + """Build the strongest caller-owned exact-runtime forgery available from module state.""" + view = object.__new__(WeightEligibilitySupersessionAuthorityView) + object.__setattr__(view, "_tenant_identity", TENANT.int) + object.__setattr__(view, "_study_identity", STUDY.int) + object.__setattr__(view, "_fields", (("eligibility_receipt_digest", "b" * 64),)) + object.__setattr__( + view, + "_issuance_marker", + getattr( + authority_module, + "_WEIGHT_ELIGIBILITY_SUPERSESSION_VIEW_ISSUANCE_MARKER", + object(), + ), + ) + return view + + +def test_module_exposes_no_weight_eligibility_supersession_view_seal() -> None: + """Keep the write capability out of ordinary importable module state.""" + assert not hasattr( + authority_module, + "_WEIGHT_ELIGIBILITY_SUPERSESSION_VIEW_ISSUANCE_MARKER", + ) + + +def test_importable_marker_cannot_mint_weight_eligibility_supersession_view() -> None: + """Require caller-populated exact objects to remain unreadable.""" + forged_view = _raw_view_with_module_marker() + + with pytest.raises( + WeightEligibilitySupersessionAuthorityIntegrityError, + match=( + "weight-eligibility supersession view was not issued by " + "resolve_weight_eligibility_supersession_authority" + ), + ): + _ = forged_view.fields From f7b5d3eae6094ba11ad7442ba7d51f754033c512 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:07:49 +0900 Subject: [PATCH 579/603] fix(workforce-validation): privatize eligibility supersession seal --- ...ight_eligibility_supersession_authority.py | 107 +++++++++++++----- 1 file changed, 76 insertions(+), 31 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_supersession_authority.py index 9723240d8..56a139fca 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_eligibility_supersession_authority.py @@ -37,7 +37,6 @@ _RESOURCE_KIND = "weight_eligibility_supersession_authority" _OPERATION = "read" -_WEIGHT_ELIGIBILITY_SUPERSESSION_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "eligibility_receipt_reference", @@ -272,18 +271,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject exact-runtime allocations not sealed by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise WeightEligibilitySupersessionAuthorityIntegrityError( - "weight-eligibility supersession view was not issued by " - "resolve_weight_eligibility_supersession_authority" - ) from exc - if marker is not _WEIGHT_ELIGIBILITY_SUPERSESSION_VIEW_ISSUANCE_MARKER: - raise WeightEligibilitySupersessionAuthorityIntegrityError( - "weight-eligibility supersession view was not issued by " - "resolve_weight_eligibility_supersession_authority" - ) + _require_weight_eligibility_supersession_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -334,7 +322,7 @@ def read_weight_eligibility_supersession_authority( ) -def resolve_weight_eligibility_supersession_authority( +def _resolve_weight_eligibility_supersession_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -349,8 +337,8 @@ def resolve_weight_eligibility_supersession_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: WeightEligibilitySupersessionAuthorityReadPort, -) -> WeightEligibilitySupersessionAuthorityView: - """Authorize then resolve the receipt's half-open append-only authority interval.""" +) -> tuple[int, int, tuple[tuple[str, object], ...]]: + """Authorize and resolve eligibility supersession into inert view state.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") if type(policy) is not PurposeBoundAccessPolicy: @@ -498,24 +486,81 @@ def resolve_weight_eligibility_supersession_authority( values = dict(record.fields) values["released_at"] = record.released_at fields = tuple((field_name, values[field_name]) for field_name in sorted(_VIEW_FIELDS)) - view = object.__new__(WeightEligibilitySupersessionAuthorityView) - object.__setattr__( - view, - "_tenant_identity", + return ( _store_operational_uuid("tenant_record_id", record.tenant_record_id), - ) - object.__setattr__( - view, - "_study_identity", _store_operational_uuid("validity_study_id", record.validity_study_id), + fields, ) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, - "_issuance_marker", - _WEIGHT_ELIGIBILITY_SUPERSESSION_VIEW_ISSUANCE_MARKER, - ) - return view + + +def _build_weight_eligibility_supersession_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: WeightEligibilitySupersessionAuthorityView) -> None: + """Verify one supersession view against the closure-private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise WeightEligibilitySupersessionAuthorityIntegrityError( + "weight-eligibility supersession view was not issued by " + "resolve_weight_eligibility_supersession_authority" + ) from exc + if marker is not issuance_marker: + raise WeightEligibilitySupersessionAuthorityIntegrityError( + "weight-eligibility supersession view was not issued by " + "resolve_weight_eligibility_supersession_authority" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + eligibility_receipt_reference: str, + eligibility_receipt_digest: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: WeightEligibilitySupersessionAuthorityReadPort, + ) -> WeightEligibilitySupersessionAuthorityView: + """Authorize then resolve the eligibility receipt authority interval.""" + tenant_identity, study_identity, fields = ( + _resolve_weight_eligibility_supersession_authority_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + eligibility_receipt_reference=eligibility_receipt_reference, + eligibility_receipt_digest=eligibility_receipt_digest, + evidence_version=evidence_version, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + ) + view = object.__new__(WeightEligibilitySupersessionAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_weight_eligibility_supersession_view_issued, + resolve_weight_eligibility_supersession_authority, +) = _build_weight_eligibility_supersession_view_runtime() +del _build_weight_eligibility_supersession_view_runtime __all__ = [ From f5698308f6c4e6d8433c6d97222fd733784b4a35 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:08:06 +0900 Subject: [PATCH 580/603] test(workforce-validation): expose weight variance seal forgery --- ...variance_authority_view_seal_capability.py | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_variance_authority_view_seal_capability.py diff --git a/services/workforce-validation-api/tests/test_weight_variance_authority_view_seal_capability.py b/services/workforce-validation-api/tests/test_weight_variance_authority_view_seal_capability.py new file mode 100644 index 000000000..0ebb7532e --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_variance_authority_view_seal_capability.py @@ -0,0 +1,44 @@ +"""Hostile sealing-capability regression for weight/variance authority views.""" + +from uuid import UUID + +import pytest + +import orgmetra_workforce_validation_api.variance_authority as authority_module +from orgmetra_workforce_validation_api.variance_authority import ( + WeightVarianceAuthorityIntegrityError, + WeightVarianceAuthorityView, +) + +TENANT = UUID("00000000-0000-0000-0000-000000000437") +STUDY = UUID("00000000-0000-0000-0000-000000000438") + + +def _raw_view_with_module_marker() -> WeightVarianceAuthorityView: + """Build the strongest caller-owned exact-runtime forgery available from module state.""" + view = object.__new__(WeightVarianceAuthorityView) + object.__setattr__(view, "_tenant_identity", TENANT.int) + object.__setattr__(view, "_study_identity", STUDY.int) + object.__setattr__(view, "_fields", (("variance_design_receipt_digest", "b" * 64),)) + object.__setattr__( + view, + "_issuance_marker", + getattr(authority_module, "_WEIGHT_VARIANCE_VIEW_ISSUANCE_MARKER", object()), + ) + return view + + +def test_module_exposes_no_weight_variance_view_seal() -> None: + """Keep the write capability out of ordinary importable module state.""" + assert not hasattr(authority_module, "_WEIGHT_VARIANCE_VIEW_ISSUANCE_MARKER") + + +def test_importable_marker_cannot_mint_weight_variance_view() -> None: + """Require caller-populated exact objects to remain unreadable.""" + forged_view = _raw_view_with_module_marker() + + with pytest.raises( + WeightVarianceAuthorityIntegrityError, + match="weight variance view was not issued by resolve_weight_variance_authority", + ): + _ = forged_view.fields From af6badae32dd45a17789911b03f13c6a9ecce6da Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:08:56 +0900 Subject: [PATCH 581/603] fix(workforce-validation): privatize weight variance view seal --- .../variance_authority.py | 113 ++++++++++++++---- 1 file changed, 93 insertions(+), 20 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py index 6305d255a..577043e79 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/variance_authority.py @@ -35,7 +35,6 @@ _REFERENCE_PATTERN = re.compile(r"^[a-z][a-z0-9_]*:[A-Za-z0-9][A-Za-z0-9._~-]*$") _RESOURCE_KIND = "weight_variance_authority" _OPERATION = "read" -_WEIGHT_VARIANCE_VIEW_ISSUANCE_MARKER = object() _VARIANCE_EVIDENCE_MODES = frozenset( { "joint_inclusion", @@ -398,16 +397,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject exact-runtime allocations not sealed by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise WeightVarianceAuthorityIntegrityError( - "weight variance view was not issued by resolve_weight_variance_authority" - ) from exc - if marker is not _WEIGHT_VARIANCE_VIEW_ISSUANCE_MARKER: - raise WeightVarianceAuthorityIntegrityError( - "weight variance view was not issued by resolve_weight_variance_authority" - ) + _require_weight_variance_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -468,7 +458,7 @@ def read_weight_variance_authority( ) -def resolve_weight_variance_authority( +def _resolve_weight_variance_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -494,8 +484,8 @@ def resolve_weight_variance_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: WeightVarianceAuthorityReadPort, -) -> WeightVarianceAuthorityView: - """Authorize then corroborate one released point-weight/variance compatibility tuple.""" +) -> tuple[int, int, tuple[tuple[str, object], ...]]: + """Authorize and corroborate point/variance compatibility into inert view state.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") if type(policy) is not PurposeBoundAccessPolicy: @@ -704,9 +694,92 @@ def resolve_weight_variance_authority( "superseded_at": record.superseded_at, } fields = tuple((field_name, values[field_name]) for field_name in sorted(_READ_FIELDS)) - view = object.__new__(WeightVarianceAuthorityView) - object.__setattr__(view, "_tenant_identity", tenant_identity) - object.__setattr__(view, "_study_identity", study_identity) - object.__setattr__(view, "_fields", fields) - object.__setattr__(view, "_issuance_marker", _WEIGHT_VARIANCE_VIEW_ISSUANCE_MARKER) - return view + return tenant_identity, study_identity, fields + + +def _build_weight_variance_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: WeightVarianceAuthorityView) -> None: + """Verify one weight/variance view against the closure-private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise WeightVarianceAuthorityIntegrityError( + "weight variance view was not issued by resolve_weight_variance_authority" + ) from exc + if marker is not issuance_marker: + raise WeightVarianceAuthorityIntegrityError( + "weight variance view was not issued by resolve_weight_variance_authority" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + sampling_receipt_reference: str, + sampling_receipt_version: int, + sampling_receipt_digest: str, + analysis_weight_receipt_digest: str, + analytic_case_occurrence_set_digest: str, + weight_eligibility_receipt_digest: str, + weight_correction_sequence: int, + final_weight_artifact_digest: str, + variance_design_receipt_reference: str, + variance_design_receipt_version: int, + variance_design_receipt_digest: str, + variance_method_reference: str, + variance_method_version: int, + variance_evidence_mode: str, + variance_semantics: str, + owner_contract_reference: str, + owner_contract_version: int, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: WeightVarianceAuthorityReadPort, + ) -> WeightVarianceAuthorityView: + """Authorize then corroborate one released point/variance compatibility tuple.""" + tenant_identity, study_identity, fields = _resolve_weight_variance_authority_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + sampling_receipt_reference=sampling_receipt_reference, + sampling_receipt_version=sampling_receipt_version, + sampling_receipt_digest=sampling_receipt_digest, + analysis_weight_receipt_digest=analysis_weight_receipt_digest, + analytic_case_occurrence_set_digest=analytic_case_occurrence_set_digest, + weight_eligibility_receipt_digest=weight_eligibility_receipt_digest, + weight_correction_sequence=weight_correction_sequence, + final_weight_artifact_digest=final_weight_artifact_digest, + variance_design_receipt_reference=variance_design_receipt_reference, + variance_design_receipt_version=variance_design_receipt_version, + variance_design_receipt_digest=variance_design_receipt_digest, + variance_method_reference=variance_method_reference, + variance_method_version=variance_method_version, + variance_evidence_mode=variance_evidence_mode, + variance_semantics=variance_semantics, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + view = object.__new__(WeightVarianceAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_weight_variance_view_issued, + resolve_weight_variance_authority, +) = _build_weight_variance_view_runtime() +del _build_weight_variance_view_runtime From bb46047b5e81f6bd6634681d81cf1b8f50e40ef3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:09:16 +0900 Subject: [PATCH 582/603] test(workforce-validation): expose variance supersession seal forgery --- ...rsession_authority_view_seal_capability.py | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_weight_variance_supersession_authority_view_seal_capability.py diff --git a/services/workforce-validation-api/tests/test_weight_variance_supersession_authority_view_seal_capability.py b/services/workforce-validation-api/tests/test_weight_variance_supersession_authority_view_seal_capability.py new file mode 100644 index 000000000..eb3e57ab0 --- /dev/null +++ b/services/workforce-validation-api/tests/test_weight_variance_supersession_authority_view_seal_capability.py @@ -0,0 +1,54 @@ +"""Hostile sealing-capability regression for weight/variance supersession views.""" + +from uuid import UUID + +import pytest + +import orgmetra_workforce_validation_api.weight_variance_supersession_authority as authority_module +from orgmetra_workforce_validation_api.weight_variance_supersession_authority import ( + WeightVarianceSupersessionAuthorityIntegrityError, + WeightVarianceSupersessionAuthorityView, +) + +TENANT = UUID("00000000-0000-0000-0000-000000000439") +STUDY = UUID("00000000-0000-0000-0000-000000000440") + + +def _raw_view_with_module_marker() -> WeightVarianceSupersessionAuthorityView: + """Build the strongest caller-owned exact-runtime forgery available from module state.""" + view = object.__new__(WeightVarianceSupersessionAuthorityView) + object.__setattr__(view, "_tenant_identity", TENANT.int) + object.__setattr__(view, "_study_identity", STUDY.int) + object.__setattr__(view, "_fields", (("authority_reference", "variance_compatibility_authority:x"),)) + object.__setattr__( + view, + "_issuance_marker", + getattr( + authority_module, + "_WEIGHT_VARIANCE_SUPERSESSION_VIEW_ISSUANCE_MARKER", + object(), + ), + ) + return view + + +def test_module_exposes_no_weight_variance_supersession_view_seal() -> None: + """Keep the write capability out of ordinary importable module state.""" + assert not hasattr( + authority_module, + "_WEIGHT_VARIANCE_SUPERSESSION_VIEW_ISSUANCE_MARKER", + ) + + +def test_importable_marker_cannot_mint_weight_variance_supersession_view() -> None: + """Require caller-populated exact objects to remain unreadable.""" + forged_view = _raw_view_with_module_marker() + + with pytest.raises( + WeightVarianceSupersessionAuthorityIntegrityError, + match=( + "weight/variance supersession view was not issued by " + "resolve_weight_variance_supersession_authority" + ), + ): + _ = forged_view.fields From 1cf907c30e7d9837ec25f2a860791fdaeb1af1fa Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:09:52 +0900 Subject: [PATCH 583/603] fix(workforce-validation): privatize variance supersession seal --- .../weight_variance_supersession_authority.py | 105 ++++++++++++------ 1 file changed, 74 insertions(+), 31 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_variance_supersession_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_variance_supersession_authority.py index ba616068e..80b714cf5 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_variance_supersession_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/weight_variance_supersession_authority.py @@ -37,7 +37,6 @@ _RESOURCE_KIND = "weight_variance_supersession_authority" _OPERATION = "read" -_WEIGHT_VARIANCE_SUPERSESSION_VIEW_ISSUANCE_MARKER = object() _READ_FIELDS = frozenset( { "authority_reference", @@ -243,18 +242,7 @@ def __delattr__(self, name: str) -> None: def _require_issued(self) -> None: """Reject exact-runtime allocations not sealed by the resolver.""" - try: - marker = object.__getattribute__(self, "_issuance_marker") - except AttributeError as exc: - raise WeightVarianceSupersessionAuthorityIntegrityError( - "weight/variance supersession view was not issued by " - "resolve_weight_variance_supersession_authority" - ) from exc - if marker is not _WEIGHT_VARIANCE_SUPERSESSION_VIEW_ISSUANCE_MARKER: - raise WeightVarianceSupersessionAuthorityIntegrityError( - "weight/variance supersession view was not issued by " - "resolve_weight_variance_supersession_authority" - ) + _require_weight_variance_supersession_view_issued(self) @property def tenant_record_id(self) -> UUID: @@ -304,7 +292,7 @@ def read_weight_variance_supersession_authority( ) -def resolve_weight_variance_supersession_authority( +def _resolve_weight_variance_supersession_authority_state( *, principal: ValidationPrincipal, tenant_record_id: UUID, @@ -318,8 +306,8 @@ def resolve_weight_variance_supersession_authority( purpose_code: str, policy: PurposeBoundAccessPolicy, read_port: WeightVarianceSupersessionAuthorityReadPort, -) -> WeightVarianceSupersessionAuthorityView: - """Authorize then resolve the compatibility authority's append-only interval.""" +) -> tuple[int, int, tuple[tuple[str, object], ...]]: + """Authorize and resolve compatibility supersession into inert view state.""" if type(principal) is not ValidationPrincipal: raise TypeError("principal must be an exact ValidationPrincipal.") if type(policy) is not PurposeBoundAccessPolicy: @@ -455,24 +443,79 @@ def resolve_weight_variance_supersession_authority( ("released_at", record.released_at), ("superseded_at", record.superseded_at), ) - view = object.__new__(WeightVarianceSupersessionAuthorityView) - object.__setattr__( - view, - "_tenant_identity", + return ( _store_operational_uuid("tenant_record_id", record.tenant_record_id), - ) - object.__setattr__( - view, - "_study_identity", _store_operational_uuid("validity_study_id", record.validity_study_id), + fields, ) - object.__setattr__(view, "_fields", fields) - object.__setattr__( - view, - "_issuance_marker", - _WEIGHT_VARIANCE_SUPERSESSION_VIEW_ISSUANCE_MARKER, - ) - return view + + +def _build_weight_variance_supersession_view_runtime(): + """Create closure-private sealing state and the authorized public resolver.""" + issuance_marker = object() + + def require_issued(view: WeightVarianceSupersessionAuthorityView) -> None: + """Verify one supersession view against the closure-private capability.""" + try: + marker = object.__getattribute__(view, "_issuance_marker") + except AttributeError as exc: + raise WeightVarianceSupersessionAuthorityIntegrityError( + "weight/variance supersession view was not issued by " + "resolve_weight_variance_supersession_authority" + ) from exc + if marker is not issuance_marker: + raise WeightVarianceSupersessionAuthorityIntegrityError( + "weight/variance supersession view was not issued by " + "resolve_weight_variance_supersession_authority" + ) + + def resolve( + *, + principal: ValidationPrincipal, + tenant_record_id: UUID, + validity_study_id: UUID, + authority_reference: str, + evidence_version: int, + owner_contract_reference: str, + owner_contract_version: int, + owner_contract_digest: str, + used_at: datetime, + purpose_code: str, + policy: PurposeBoundAccessPolicy, + read_port: WeightVarianceSupersessionAuthorityReadPort, + ) -> WeightVarianceSupersessionAuthorityView: + """Authorize then resolve the compatibility authority's append-only interval.""" + tenant_identity, study_identity, fields = ( + _resolve_weight_variance_supersession_authority_state( + principal=principal, + tenant_record_id=tenant_record_id, + validity_study_id=validity_study_id, + authority_reference=authority_reference, + evidence_version=evidence_version, + owner_contract_reference=owner_contract_reference, + owner_contract_version=owner_contract_version, + owner_contract_digest=owner_contract_digest, + used_at=used_at, + purpose_code=purpose_code, + policy=policy, + read_port=read_port, + ) + ) + view = object.__new__(WeightVarianceSupersessionAuthorityView) + object.__setattr__(view, "_tenant_identity", tenant_identity) + object.__setattr__(view, "_study_identity", study_identity) + object.__setattr__(view, "_fields", fields) + object.__setattr__(view, "_issuance_marker", issuance_marker) + return view + + return require_issued, resolve + + +( + _require_weight_variance_supersession_view_issued, + resolve_weight_variance_supersession_authority, +) = _build_weight_variance_supersession_view_runtime() +del _build_weight_variance_supersession_view_runtime __all__ = [ From 76d1300deddc8433cd236ada11e41edc9c00831d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:18:04 +0900 Subject: [PATCH 584/603] docs(workforce-validation): currentize view sealing and exact-head evidence --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e57a783eb..ca2735f56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,7 +37,7 @@ All notable changes to Orgmetra will be documented in this file. ### Changed -- Active-PR Workforce Validation coverage recovery now exercises exact owner-capability admission, immutable release-view identities, version and chronology rejection, digest independence, approximation semantics, final-weight component corroboration, and base/nonresponse/trimming supersession edge contracts. The Python 3.12 pinned suite passes all 1,306 tests with 4,487/4,487 owned statements and 1,070/1,070 owned branches covered. +- Active-PR Workforce Validation coverage recovery now exercises exact owner-capability admission, immutable release-view identities, version and chronology rejection, digest independence, approximation semantics, final-weight component corroboration, and base/nonresponse/trimming supersession edge contracts. An earlier exact head passed 1,306 tests with 4,487/4,487 owned statements and 1,070/1,070 owned branches covered; subsequent authorized-view sealing repairs add new production and hostile-regression branches, so that verdict does not transfer and final exact-head functional, statement, branch, docstring, and edge evidence must be reacquired before integration. - Active-PR Workforce Validation acceptance fixtures now track released owner contracts, supersession cutovers, owner-read field sets, and standard-library timezone-provider failures exactly; wheel acceptance validates every owned wheel's internal identity and metadata before producing any outer artifact hash. - Consolidated repository-owned PR validation from twelve workflows into one Foundation CI job, while keeping the dual-cluster recovery rehearsal separately path-scoped. Central required review and security workflows remain organization-owned. - New predictive-validity membership must use one normalized worker-level case; the three independent validity-study decision/evidence/outcome link relations are historical read surfaces only and can no longer accept new rows. A case insert also rejects a criterion observation whose recorded interval is already closed at `linked_at`. @@ -59,7 +59,7 @@ All notable changes to Orgmetra will be documented in this file. ### Security -- Active-PR Workforce Validation final-analysis-weight, final-weight-component-binding, nonresponse-adjustment, trimming/bounding, validation-result, and validation-result non-verifiability views now keep their issuance seals in closure-private runtime state. Importable module markers can no longer mint an authorized projection; purpose authorization, canonical owner reconstruction, effective-time currentness, field minimization, detached identities, and marker-last issuance remain unchanged. +- Active-PR Workforce Validation all 24 exported resolver-issued evidence views now keep their issuance seals in closure-private runtime state. Package-wide hostile marker-copy regressions reject importable module sealing capabilities and caller-populated raw exact-runtime objects; purpose authorization, canonical owner reconstruction, scientific-coordinate matching, effective-time currentness, field minimization, detached identities, and marker-last issuance remain unchanged. Runtime view type or seal is not durable authorization. - Active-PR Workforce Validation authorized evidence views reject low-level base-constructor forging across the complete 24-class public export census. Every exported `*View` is a sealed non-tuple data object whose public constructor rejects, whose raw allocations cannot expose state, and whose only supported issuer remains its purpose-authorized owner-resolution path. The executable package-surface census now fails closed on an added, removed, tuple-backed, unsealed, or mutable public view; `CalibrationBenchmarkAuthorityView` was the final omission exposed by that census and is covered by its own issuance-integrity regression. - Predictive-validity cases fail closed when selection evidence, Job scope, study criterion, converted worker, or system-recorded visibility does not match; the normalized case relation is tenant-qualified, append-only, TRUNCATE-protected, and forced through row-level security. - Purpose-bound PII authorization now fails closed across active tenant, authenticated actor tenant, resource tenant, resource kind, purpose, operation, operation-specific Keyverse scope, and requested-field subset; malformed/wildcard-like attributes, mutable field/scope collections, reserved UUID sentinels, and cross-tenant confused-deputy contexts are rejected before protected values are returned. Authorization requests and allow/deny evidence now also require and preserve one namespaced opaque target-resource reference, so immutable audit correlation identifies the exact HR record without copying its protected values. Authorization evidence otherwise contains governance metadata and field names only, with stable denial reasons and actionable next steps rather than PII. @@ -78,4 +78,4 @@ All notable changes to Orgmetra will be documented in this file. ### Notes -- Protected `develop` at `e7ddb7a78a5e1460410005d10f43ebf18c5e12e4` includes normalized validity-study and criterion integrity, bitemporal workforce composition, governed candidate-to-worker conversion, purpose-bound PII authorization, GET-only People reads, governed People mutation/idempotency API, and the accepted ADR 0001–0003 source expansion integrated by #37. Job Analysis persistence/API and the selection-review packet remain active-PR truth until their unchanged exact heads satisfy fresh gates and merge. +- Protected `develop` at `eb9757f8649aaad026a9865508d9aad50c1a7a4f` includes normalized validity-study and criterion integrity, bitemporal workforce composition, governed candidate-to-worker conversion, purpose-bound PII authorization, GET-only People reads, governed People mutation/idempotency API, and the accepted ADR 0001–0003 source expansion integrated by #37. Job Analysis persistence/API and the selection-review packet remain active-PR truth until their unchanged exact heads satisfy fresh gates and merge. From 89b1334c1a036437ae1f0e37a7058fca8f7aeb82 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:18:56 +0900 Subject: [PATCH 585/603] fix(provenance): reseal changelog after workforce validation currentization --- manifest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manifest.json b/manifest.json index af0f31d51..af6f7c942 100644 --- a/manifest.json +++ b/manifest.json @@ -29,8 +29,8 @@ }, { "path": "CHANGELOG.md", - "sha256": "7f7904b197f61a6378b30b43f475198dace84397a60de431edd007580a2da30a", - "bytes": 19413, + "sha256": "5e71ae06e61eca5738fd62158272ad0eee235584ae48851114ef041da6737a8d", + "bytes": 19691, "lines": 81 }, { From d7aa67c6d2550a0b3ff8d790e845667009d02438 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:30:32 +0900 Subject: [PATCH 586/603] test(workforce-validation): reject unresolvable generic weight adjustment --- ...al_weight_generic_adjustment_resolution.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_generic_adjustment_resolution.py diff --git a/services/workforce-validation-api/tests/test_final_weight_generic_adjustment_resolution.py b/services/workforce-validation-api/tests/test_final_weight_generic_adjustment_resolution.py new file mode 100644 index 000000000..9a9f02b56 --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_generic_adjustment_resolution.py @@ -0,0 +1,25 @@ +"""Fail closed when a final-weight adjustment has no released owner resolver contract.""" + +from __future__ import annotations + +import pytest + +from orgmetra_workforce_validation_api.final_weight_authority import ( + FinalWeightAdjustmentCoordinate, +) + + +def test_generic_adjustment_without_governed_receipt_locator_is_rejected() -> None: + """Do not admit a material transform that cannot be re-resolved from owner truth.""" + with pytest.raises(ValueError, match="governed adjustment_code"): + FinalWeightAdjustmentCoordinate( + sequence_number=1, + adjustment_code="custom_transform", + method_reference="weight_method:custom-transform", + method_version=1, + input_weight_artifact_digest="a" * 64, + output_weight_artifact_digest="b" * 64, + configuration_digest="c" * 64, + evidence_receipt_digest="d" * 64, + evidence_kind="custom_transform_receipt", + ) From 17b80f9e360dc82bf93c6831c2c6d3504af50a90 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:31:38 +0900 Subject: [PATCH 587/603] fix(workforce-validation): reject unresolvable generic weight adjustments --- .../final_weight_authority.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py index 1fa57a811..045b943f2 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py @@ -138,7 +138,11 @@ def __new__( evidence_digest = _require_digest("evidence_receipt_digest", evidence_receipt_digest) kind = _require_code("evidence_kind", evidence_kind) required_kind = _SPECIALIZED_EVIDENCE_KIND_BY_ADJUSTMENT_CODE.get(code) - if required_kind is not None and kind != required_kind: + if required_kind is None: + raise ValueError( + "adjustment_code must identify a governed adjustment with released owner evidence." + ) + if kind != required_kind: raise ValueError(f"{code} requires evidence_kind {required_kind}.") if input_digest == output_digest: raise ValueError( From 9625f95dc3b90ba119c462a7587accf2c4f068e1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:32:44 +0900 Subject: [PATCH 588/603] test(workforce-validation): align generic adjustment contract with governed evidence --- .../tests/test_final_analysis_weight_authority.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/services/workforce-validation-api/tests/test_final_analysis_weight_authority.py b/services/workforce-validation-api/tests/test_final_analysis_weight_authority.py index c3f674f81..b6b40c6fa 100644 --- a/services/workforce-validation-api/tests/test_final_analysis_weight_authority.py +++ b/services/workforce-validation-api/tests/test_final_analysis_weight_authority.py @@ -332,11 +332,11 @@ def test_adjustment_semantics_are_typed_and_no_op_transform_is_rejected() -> Non _adjustment(evidence_kind="generic_weight_evidence") with pytest.raises(ValueError): _adjustment(output_weight_artifact_digest=BASE_ARTIFACT_DIGEST) - generic = _adjustment( - adjustment_code="custom_transform", - evidence_kind="custom_transform_receipt", - ) - assert generic.evidence_kind == "custom_transform_receipt" + with pytest.raises(ValueError, match="governed adjustment_code"): + _adjustment( + adjustment_code="custom_transform", + evidence_kind="custom_transform_receipt", + ) @pytest.mark.parametrize( From e4945f0bcea20aff5cc5dee3f86a9964ddbb3107 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:40:43 +0900 Subject: [PATCH 589/603] docs: record governed final-weight adjustment admission --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca2735f56..1f2c56029 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ All notable changes to Orgmetra will be documented in this file. ### Security +- Active-PR Workforce Validation final-weight adjustment admission now fails closed for any material adjustment code without a released governed owner-evidence family. Evidence digests are integrity coordinates, not owner-record locators; adding a future adjustment family requires a versioned receipt namespace, exact reference/version/digest identity, purpose-bound deterministic owner resolution, canonical reconstruction, and binding/corroboration of transform semantics plus release/currentness before it can enter a released final-weight lineage. - Active-PR Workforce Validation all 24 exported resolver-issued evidence views now keep their issuance seals in closure-private runtime state. Package-wide hostile marker-copy regressions reject importable module sealing capabilities and caller-populated raw exact-runtime objects; purpose authorization, canonical owner reconstruction, scientific-coordinate matching, effective-time currentness, field minimization, detached identities, and marker-last issuance remain unchanged. Runtime view type or seal is not durable authorization. - Active-PR Workforce Validation authorized evidence views reject low-level base-constructor forging across the complete 24-class public export census. Every exported `*View` is a sealed non-tuple data object whose public constructor rejects, whose raw allocations cannot expose state, and whose only supported issuer remains its purpose-authorized owner-resolution path. The executable package-surface census now fails closed on an added, removed, tuple-backed, unsealed, or mutable public view; `CalibrationBenchmarkAuthorityView` was the final omission exposed by that census and is covered by its own issuance-integrity regression. - Predictive-validity cases fail closed when selection evidence, Job scope, study criterion, converted worker, or system-recorded visibility does not match; the normalized case relation is tenant-qualified, append-only, TRUNCATE-protected, and forced through row-level security. From 57214b4968c5968a4009cad56ea9d23a186ee9d9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 08:43:19 +0900 Subject: [PATCH 590/603] fix(provenance): reseal changelog for final-weight admission --- manifest.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/manifest.json b/manifest.json index af6f7c942..e40666cde 100644 --- a/manifest.json +++ b/manifest.json @@ -29,9 +29,9 @@ }, { "path": "CHANGELOG.md", - "sha256": "5e71ae06e61eca5738fd62158272ad0eee235584ae48851114ef041da6737a8d", - "bytes": 19691, - "lines": 81 + "sha256": "026289e0ff0131a081786e4029999292c72e1e2e08c4675c7ec96c4617b93049", + "bytes": 20244, + "lines": 82 }, { "path": "CLAUDE.md", From 8f04f48f0f6a3a0ea9f69fb826c78d590bccf8f8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 09:00:15 +0900 Subject: [PATCH 591/603] test(workforce-validation): reject skipped component binding sequences --- ...t_component_binding_sequence_contiguity.py | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 services/workforce-validation-api/tests/test_final_weight_component_binding_sequence_contiguity.py diff --git a/services/workforce-validation-api/tests/test_final_weight_component_binding_sequence_contiguity.py b/services/workforce-validation-api/tests/test_final_weight_component_binding_sequence_contiguity.py new file mode 100644 index 000000000..72ad8f409 --- /dev/null +++ b/services/workforce-validation-api/tests/test_final_weight_component_binding_sequence_contiguity.py @@ -0,0 +1,98 @@ +"""Regression contract for contiguous final-weight component receipt bindings.""" + +from __future__ import annotations + +from datetime import datetime, timezone +from uuid import UUID + +import pytest + +from orgmetra_workforce_validation_api.final_weight_component_binding_authority import ( + FinalWeightAdjustmentEvidenceBinding, + FinalWeightComponentBindingAuthorityRecord, +) + +TENANT = UUID("10000000-0000-7000-8000-000000000001") +STUDY = UUID("00000000-0000-7000-8000-0000000000f1") +OWNER_RELEASED_AT = datetime(2026, 9, 19, 4, 0, tzinfo=timezone.utc) +RELEASED_AT = datetime(2026, 9, 19, 4, 10, tzinfo=timezone.utc) + + +def _binding( + *, + sequence_number: int, + evidence_kind: str, + evidence_receipt_reference: str, + evidence_receipt_digest: str, +) -> FinalWeightAdjustmentEvidenceBinding: + return FinalWeightAdjustmentEvidenceBinding( + sequence_number=sequence_number, + evidence_kind=evidence_kind, + evidence_receipt_reference=evidence_receipt_reference, + evidence_version=1, + evidence_receipt_digest=evidence_receipt_digest, + ) + + +def _record( + adjustment_bindings: tuple[FinalWeightAdjustmentEvidenceBinding, ...], +) -> FinalWeightComponentBindingAuthorityRecord: + return FinalWeightComponentBindingAuthorityRecord( + tenant_record_id=TENANT, + validity_study_id=STUDY, + analysis_weight_receipt_reference=( + "analysis_weight_receipt:aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa" + ), + analysis_weight_receipt_digest="1" * 64, + analysis_weight_evidence_version=1, + binding_reference=( + "final_weight_component_binding:bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb" + ), + binding_digest="2" * 64, + binding_version=1, + base_weight_evidence_receipt_reference=( + "base_weight_evidence_receipt:cccccccc-cccc-4ccc-8ccc-cccccccccccc" + ), + base_weight_evidence_receipt_digest="3" * 64, + base_weight_evidence_version=1, + adjustment_bindings=adjustment_bindings, + owner_contract_reference=( + "released_owner_contract:dddddddd-dddd-4ddd-8ddd-dddddddddddd" + ), + owner_contract_version=1, + owner_contract_digest="4" * 64, + owner_contract_released_at=OWNER_RELEASED_AT, + released_at=RELEASED_AT, + ) + + +def test_component_binding_sequences_must_start_at_one_and_remain_contiguous() -> None: + first = _binding( + sequence_number=1, + evidence_kind="nonresponse_adjustment_receipt", + evidence_receipt_reference=( + "nonresponse_adjustment_receipt:11111111-1111-4111-8111-111111111111" + ), + evidence_receipt_digest="a" * 64, + ) + third = _binding( + sequence_number=3, + evidence_kind="trimming_bounding_adjustment_receipt", + evidence_receipt_reference=( + "trimming_bounding_adjustment_receipt:33333333-3333-4333-8333-333333333333" + ), + evidence_receipt_digest="b" * 64, + ) + second = _binding( + sequence_number=2, + evidence_kind="calibration_adjustment_receipt", + evidence_receipt_reference=( + "calibration_adjustment_receipt:22222222-2222-4222-8222-222222222222" + ), + evidence_receipt_digest="c" * 64, + ) + + with pytest.raises(ValueError, match="contiguous"): + _record((first, third)) + with pytest.raises(ValueError, match="contiguous"): + _record((second,)) From d83d0ebd03df8c3730cc60bf54c260755910a7b6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 09:01:27 +0900 Subject: [PATCH 592/603] fix(workforce-validation): require contiguous component bindings --- .../final_weight_component_binding_authority.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_binding_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_binding_authority.py index 580c8ad7b..09c4aee2f 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_binding_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_binding_authority.py @@ -199,8 +199,7 @@ def __new__( if type(adjustment_bindings) is not tuple: raise ValueError("adjustment_bindings must be an immutable tuple.") detached_bindings: list[FinalWeightAdjustmentEvidenceBinding] = [] - previous_sequence = 0 - for binding in adjustment_bindings: + for expected_sequence, binding in enumerate(adjustment_bindings, start=1): if type(binding) is not FinalWeightAdjustmentEvidenceBinding: raise ValueError( "adjustment_bindings must contain exact FinalWeightAdjustmentEvidenceBinding values." @@ -214,10 +213,11 @@ def __new__( ) if detached != binding: raise ValueError("adjustment_bindings must contain canonical receipt locators.") - if detached.sequence_number <= previous_sequence: - raise ValueError("adjustment binding sequence numbers must be strictly increasing.") + if detached.sequence_number != expected_sequence: + raise ValueError( + "adjustment binding sequence numbers must be contiguous starting at 1." + ) detached_bindings.append(detached) - previous_sequence = detached.sequence_number owner_reference = _require_reference( "owner_contract_reference", owner_contract_reference, "released_owner_contract" ) From 54594601e41e32786ca002f63ab3c8a364805af2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 09:01:59 +0900 Subject: [PATCH 593/603] test(workforce-validation): align binding sequence contract --- .../test_final_weight_component_binding_authority.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/workforce-validation-api/tests/test_final_weight_component_binding_authority.py b/services/workforce-validation-api/tests/test_final_weight_component_binding_authority.py index 2504e7d9f..4848678af 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_binding_authority.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_binding_authority.py @@ -191,7 +191,7 @@ def test_resolver_returns_exact_component_locator_and_uses_final_receipt_key_onl ] -def test_binding_sequence_may_skip_generic_adjustments_but_must_increase() -> None: +def test_binding_sequences_must_be_contiguous_after_governed_adjustment_admission() -> None: bindings = ( _binding(), _binding( @@ -203,10 +203,10 @@ def test_binding_sequence_may_skip_generic_adjustments_but_must_increase() -> No evidence_receipt_digest="b" * 64, ), ) - record = _record(adjustment_bindings=bindings) - assert dict(record.fields)["adjustment_bindings"] == bindings + with pytest.raises(ValueError, match="contiguous"): + _record(adjustment_bindings=bindings) - with pytest.raises(ValueError, match="strictly increasing"): + with pytest.raises(ValueError, match="contiguous"): _record(adjustment_bindings=(bindings[1], bindings[0])) From a5d24fc926042da970b4c443e2984f72d0398ed8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 09:07:07 +0900 Subject: [PATCH 594/603] docs(workforce-validation): record contiguous binding invariant --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f2c56029..878cad0dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ All notable changes to Orgmetra will be documented in this file. ### Added - Accepted ADRs 0001–0003 now include buyer-facing Context, Decision, and Consequences grounded in verified ISO 30400:2022, ISO 30414:2025, Uniform Guidelines (29 C.F.R. Part 1607), SIOP (2018), OpenAPI Specification v3.2.0, OpenID Connect Core 1.0 errata set 2, CloudEvents v1.0.2, Jensen and Snodgrass (1999), Snodgrass (1999), and Allen (1983) records already listed in `docs/doctoring/REFERENCES.md`. ADRs 0004 and 0005 gained APA 7th References pointers to that same bibliography without changing their Decision bodies. -- Active-PR governed Job Analysis persistence/API on the canonical `JobAnalysisSnapshot` model: migration `0013_job_analysis_snapshot.sql` stores immutable tenant-scoped snapshot, Task, KSAO, Task–KSAO, FJA and write-command evidence; `POST /v1/tenants/{tenant_record_id}/job-analysis-snapshots` and matching GET enforce purpose-bound Keyverse scope, authenticated-principal actor authority, bounded/strict JSON handling, transactional Idempotency-Key serialization, parent-scope fail-closed integrity, forced RLS, and atomic audit/outbox evidence. ADR 0014 records the persistence decision while ADR 0007 remains the domain/evidence authority; validated evidence still requires accountable human review and non-LLM provenance, and the service does not make a high-impact employment decision. +- Active-PR governed Job Analysis persistence/API on the canonical `JobAnalysisSnapshot` model: migration `0013_job_analysis_snapshot.sql` stores immutable tenant-scoped snapshot, Task, KSAO, FJA and write-command evidence; `POST /v1/tenants/{tenant_record_id}/job-analysis-snapshots` and matching GET enforce purpose-bound Keyverse scope, authenticated-principal actor authority, bounded/strict JSON handling, transactional Idempotency-Key serialization, parent-scope fail-closed integrity, forced RLS, and atomic audit/outbox evidence. ADR 0014 records the persistence decision while ADR 0007 remains the domain/evidence authority; validated evidence still requires accountable human review and non-LLM provenance, and the service does not make a high-impact employment decision. - Active-PR `orgmetra_selection_review` packet for PII-minimized, evidence-bound human selection review: canonical operational tenant identity, UUID-backed opaque candidate/Job/sealed-evidence/reviewer references, explicit purpose/reason/evidence version, deterministic canonical JSON and SHA-256 correlation, mandatory human decision state, redacted packet repr, and provenance-paired model evidence that remains `untrusted_draft`, with exact 100% owned statement and branch coverage required by its quality gate. - Active performance-criterion scope hardening: `criterion_observation_scope_guard` rejects criterion outcomes for a Job the worker did not effectively hold at the observation date, observations before the relevant assignment, and observations outside the referenced performance cycle while preserving valid multiple-assignment cases and existing bitemporal correction semantics. The guard evaluates current-recorded facts, derives the date coordinate from `observed_at` in UTC so session `TimeZone` cannot alter the result, uses a trusted function search path, and adds no PII or automated employment decision authority. The Foundation PostgreSQL contract also rejects a closed `recorded_to` on each time-coordinate lookup and proves UTC midnight plus non-UTC session `TimeZone` boundaries. - Bitemporal tenant-scoped organization hierarchy validation that rejects visible indirect parent cycles and reuses single-valued recorded-time reconstruction before graph traversal. @@ -59,7 +59,7 @@ All notable changes to Orgmetra will be documented in this file. ### Security -- Active-PR Workforce Validation final-weight adjustment admission now fails closed for any material adjustment code without a released governed owner-evidence family. Evidence digests are integrity coordinates, not owner-record locators; adding a future adjustment family requires a versioned receipt namespace, exact reference/version/digest identity, purpose-bound deterministic owner resolution, canonical reconstruction, and binding/corroboration of transform semantics plus release/currentness before it can enter a released final-weight lineage. +- Active-PR Workforce Validation final-weight adjustment admission now fails closed for any material adjustment code without a released governed owner-evidence family. Evidence digests are integrity coordinates, not owner-record locators; adding a future adjustment family requires a versioned receipt namespace, exact reference/version/digest identity, purpose-bound deterministic owner resolution, canonical reconstruction, and binding/corroboration of transform semantics plus release/currentness before it can enter a released final-weight lineage. The component-binding owner now also requires every governed adjustment receipt binding to be contiguous and one-based, so an intrinsically incomplete sequence such as `(1, 3)` cannot be persisted and deferred to the later corroboration service. - Active-PR Workforce Validation all 24 exported resolver-issued evidence views now keep their issuance seals in closure-private runtime state. Package-wide hostile marker-copy regressions reject importable module sealing capabilities and caller-populated raw exact-runtime objects; purpose authorization, canonical owner reconstruction, scientific-coordinate matching, effective-time currentness, field minimization, detached identities, and marker-last issuance remain unchanged. Runtime view type or seal is not durable authorization. - Active-PR Workforce Validation authorized evidence views reject low-level base-constructor forging across the complete 24-class public export census. Every exported `*View` is a sealed non-tuple data object whose public constructor rejects, whose raw allocations cannot expose state, and whose only supported issuer remains its purpose-authorized owner-resolution path. The executable package-surface census now fails closed on an added, removed, tuple-backed, unsealed, or mutable public view; `CalibrationBenchmarkAuthorityView` was the final omission exposed by that census and is covered by its own issuance-integrity regression. - Predictive-validity cases fail closed when selection evidence, Job scope, study criterion, converted worker, or system-recorded visibility does not match; the normalized case relation is tenant-qualified, append-only, TRUNCATE-protected, and forced through row-level security. From 36fd262754421cd8000be42ab25df09b7cfe2044 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 09:10:29 +0900 Subject: [PATCH 595/603] fix(provenance): reseal contiguous binding changelog --- manifest.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manifest.json b/manifest.json index e40666cde..02eda4ce1 100644 --- a/manifest.json +++ b/manifest.json @@ -29,8 +29,8 @@ }, { "path": "CHANGELOG.md", - "sha256": "026289e0ff0131a081786e4029999292c72e1e2e08c4675c7ec96c4617b93049", - "bytes": 20244, + "sha256": "53e2f768cb62f7540ad6971476eb5cb81309d9d2e0dd1ae372d48d13d99d6bb6", + "bytes": 20490, "lines": 82 }, { From 731b5e9605f0d4d8f27e45920c68b73da2d44be0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 09:19:50 +0900 Subject: [PATCH 596/603] fix(workforce-validation): align governed adjustment corroboration --- CHANGELOG.md | 2 +- manifest.json | 4 +-- .../final_weight_authority.py | 2 +- ...al_weight_component_evidence_resolution.py | 12 ++------ ...ght_component_evidence_resolution_edges.py | 28 ------------------- 5 files changed, 7 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 878cad0dc..7e2deefb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ All notable changes to Orgmetra will be documented in this file. ### Security -- Active-PR Workforce Validation final-weight adjustment admission now fails closed for any material adjustment code without a released governed owner-evidence family. Evidence digests are integrity coordinates, not owner-record locators; adding a future adjustment family requires a versioned receipt namespace, exact reference/version/digest identity, purpose-bound deterministic owner resolution, canonical reconstruction, and binding/corroboration of transform semantics plus release/currentness before it can enter a released final-weight lineage. The component-binding owner now also requires every governed adjustment receipt binding to be contiguous and one-based, so an intrinsically incomplete sequence such as `(1, 3)` cannot be persisted and deferred to the later corroboration service. +- Active-PR Workforce Validation final-weight adjustment admission now fails closed for any material adjustment code without a released governed owner-evidence family. Evidence digests are integrity coordinates, not owner-record locators; adding a future adjustment family requires a versioned receipt namespace, exact reference/version/digest identity, purpose-bound deterministic owner resolution, canonical reconstruction, and binding/corroboration of transform semantics plus release/currentness before it can enter a released final-weight lineage. The component-binding owner now also requires every governed adjustment receipt binding to be contiguous and one-based, so an intrinsically incomplete sequence such as `(1, 3)` cannot be persisted and deferred to the later corroboration service. The corroborator requires a binding for every admitted adjustment and removes the obsolete path that treated an ungoverned generic transform as owner-local. - Active-PR Workforce Validation all 24 exported resolver-issued evidence views now keep their issuance seals in closure-private runtime state. Package-wide hostile marker-copy regressions reject importable module sealing capabilities and caller-populated raw exact-runtime objects; purpose authorization, canonical owner reconstruction, scientific-coordinate matching, effective-time currentness, field minimization, detached identities, and marker-last issuance remain unchanged. Runtime view type or seal is not durable authorization. - Active-PR Workforce Validation authorized evidence views reject low-level base-constructor forging across the complete 24-class public export census. Every exported `*View` is a sealed non-tuple data object whose public constructor rejects, whose raw allocations cannot expose state, and whose only supported issuer remains its purpose-authorized owner-resolution path. The executable package-surface census now fails closed on an added, removed, tuple-backed, unsealed, or mutable public view; `CalibrationBenchmarkAuthorityView` was the final omission exposed by that census and is covered by its own issuance-integrity regression. - Predictive-validity cases fail closed when selection evidence, Job scope, study criterion, converted worker, or system-recorded visibility does not match; the normalized case relation is tenant-qualified, append-only, TRUNCATE-protected, and forced through row-level security. diff --git a/manifest.json b/manifest.json index 02eda4ce1..a1cac9e48 100644 --- a/manifest.json +++ b/manifest.json @@ -29,8 +29,8 @@ }, { "path": "CHANGELOG.md", - "sha256": "53e2f768cb62f7540ad6971476eb5cb81309d9d2e0dd1ae372d48d13d99d6bb6", - "bytes": 20490, + "sha256": "ec2120f23ca8c729022cb90da1f3e303b2040ddf76c7d2e244524db3c4b574a0", + "bytes": 20634, "lines": 82 }, { diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py index 045b943f2..fcab8ec96 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_authority.py @@ -140,7 +140,7 @@ def __new__( required_kind = _SPECIALIZED_EVIDENCE_KIND_BY_ADJUSTMENT_CODE.get(code) if required_kind is None: raise ValueError( - "adjustment_code must identify a governed adjustment with released owner evidence." + "governed adjustment_code must identify released owner evidence." ) if kind != required_kind: raise ValueError(f"{code} requires evidence_kind {required_kind}.") diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py index 44e821ab2..5db747945 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/final_weight_component_evidence_resolution.py @@ -823,14 +823,10 @@ def _corroborate_final_weight_component_evidence_state( "component adjustment bindings are not canonical immutable coordinates" ) binding_by_sequence = {item.sequence_number: item for item in adjustment_bindings} - specialized_sequences = { - item.sequence_number - for item in adjustments - if item.evidence_kind in _EVIDENCE_REFERENCE_NAMESPACE_BY_KIND - } - if set(binding_by_sequence) != specialized_sequences: + adjustment_sequences = {item.sequence_number for item in adjustments} + if set(binding_by_sequence) != adjustment_sequences: raise FinalWeightComponentEvidenceIntegrityError( - "component binding must cover every and only specialized final-weight adjustment" + "component binding must cover every governed specialized final-weight adjustment" ) resolved_adjustments: list[AdjustmentComponentEvidence] = [] @@ -839,8 +835,6 @@ def _corroborate_final_weight_component_evidence_state( raise FinalWeightComponentEvidenceIntegrityError( "final-weight adjustment coordinates must remain canonical" ) - if adjustment.sequence_number not in specialized_sequences: - continue locator = binding_by_sequence[adjustment.sequence_number] if ( locator.evidence_kind != adjustment.evidence_kind diff --git a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_edges.py b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_edges.py index b2826e08c..66f3b5eaa 100644 --- a/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_edges.py +++ b/services/workforce-validation-api/tests/test_final_weight_component_evidence_resolution_edges.py @@ -10,7 +10,6 @@ import orgmetra_workforce_validation_api.final_weight_component_evidence_resolution as resolution_module from orgmetra_workforce_validation_api.final_weight_authority import ( FinalAnalysisWeightAuthorityRecord, - FinalWeightAdjustmentCoordinate, ) from orgmetra_workforce_validation_api.final_weight_component_binding_authority import ( FinalWeightAdjustmentEvidenceBinding, @@ -307,30 +306,3 @@ def test_post_canonicalization_adjustment_coordinate_type_remains_exact( with pytest.raises(FinalWeightComponentEvidenceIntegrityError, match="coordinates"): _corroborate(read_port=_ReadPort(), final_weight=final_weight) - - -def test_non_specialized_adjustment_needs_no_cross_owner_locator() -> None: - """Resolve base evidence while leaving a non-specialized transform owner-local.""" - local_adjustment = FinalWeightAdjustmentCoordinate( - sequence_number=1, - adjustment_code="replicate_weight_projection", - method_reference="weight_method:dddddddd-dddd-4ddd-8ddd-dddddddddddd", - method_version=1, - input_weight_artifact_digest=BASE_ARTIFACT_DIGEST, - output_weight_artifact_digest="c" * 64, - configuration_digest="d" * 64, - evidence_receipt_digest="e" * 64, - evidence_kind="replicate_weight_receipt", - ) - final_weight = _final_weight( - adjustments=(local_adjustment,), - final_weight_artifact_digest="c" * 64, - ) - binding = _binding(adjustment_bindings=()) - resolution = _corroborate( - read_port=_ReadPort(), - final_weight=final_weight, - binding=binding, - ) - - assert resolution.adjustments == () From 03bf5040e7eb307c4df55ebd01453dcbd1ae0cef Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 10:07:02 +0900 Subject: [PATCH 597/603] docs(workforce-validation): align final-weight binding invariants --- services/workforce-validation-api/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/workforce-validation-api/README.md b/services/workforce-validation-api/README.md index 543c6eea4..fa1f7666d 100644 --- a/services/workforce-validation-api/README.md +++ b/services/workforce-validation-api/README.md @@ -94,7 +94,7 @@ The owner read is keyed by the complete caller-known reproducibility tuple. Owne ## Final analysis-weight component binding authority -`resolve_final_weight_component_binding_authority(...)` closes the #411 locator gap without silently redefining the existing v1 final-weight receipt. It is keyed only by the immutable final analysis-weight receipt reference/digest/evidence-version and returns one released owner binding containing the exact base-weight evidence receipt reference/version/digest plus the exact receipt reference/version/digest for every governed specialized adjustment represented in the final-weight chain. Generic adjustment steps need not appear in the specialized binding tuple, so recorded sequence numbers are strictly increasing but need not be contiguous. +`resolve_final_weight_component_binding_authority(...)` closes the #411 locator gap and the #423/#424 admission/completeness gap without redefining the existing v1 final-weight receipt. It is keyed only by the immutable final analysis-weight receipt reference/digest/evidence-version and returns one released owner binding containing the exact base-weight evidence receipt reference/version/digest plus the exact receipt reference/version/digest for every admitted governed adjustment in the final-weight chain. Ungoverned adjustment codes fail closed, so `adjustment_bindings` is one-to-one with the ordered adjustment chain: sequence numbers must be contiguous and one-based, and a hole or a sequence starting after 1 is malformed. The binding is its own immutable released owner evidence with reference/digest/version and owner-resolved `[released_at, superseded_at)` chronology. A digest is integrity evidence but is not treated as an implicit reverse-lookup API. Durable persistence must make the final-weight receipt identity select one canonical binding deterministically and fail closed on absence, ambiguity, conflicting receipt identity or non-canonical structure. This companion contract does not copy row-level weights, response values, calibration auxiliary values or foreign application tables; it supplies the owner coordinates required to re-resolve those existing typed authorities. @@ -142,7 +142,7 @@ The schema owner is NOLOGIN and is not a runtime isolation control. PostgreSQL r Protected foundation migrations still hold validity-study relations in the legacy foundation schema. PR #248 or a verified successor owns forward owner-schema adoption after this application owner reaches normal protected integration. It must preserve valid persistence/FK/RLS/ACL evidence and implement durable released-evidence ports for all **twenty-two** current application-owner families: calibration auxiliary, calibration benchmark, typed calibration adjustment, calibration support chronology, calibration-adjustment supersession, typed nonresponse adjustment, nonresponse-adjustment supersession, trimming/bounding adjustment, trimming/bounding supersession, weight eligibility, weight-eligibility supersession, base/design-weight provenance, base/design-weight supersession, complete final analysis-weight lineage, final-weight typed-component binding, final-weight supersession, point-weight/variance compatibility, point-weight/variance supersession, validation-result binding, validation-result supersession, validation-result non-verifiability, and validation-result non-verifiability supersession. -The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Final-weight component-binding persistence must key only the exact final receipt identity, return exactly one canonical released binding, preserve exact base/specialized adjustment receipt reference-version-digest locators, and reject ambiguous digest-only reverse lookup. Non-verifiability persistence must key the exact immutable predecessor verification-attempt reference/digest; for `non_reproducible` it must additionally key the exact failed-evidence reference/digest, while failed-evidence and attempt-release instants remain owner chronology. Missing-evidence correction uses the v1 same-result/same-obligation successor graph. Non-reproducible correction uses v2 and must preserve the same predecessor failed-evidence reference/digest in addition to result, evidence family, verification attempt and owner contract; it must persist/recover the failed-evidence release instant as owner chronology and require the successor target tuple to equal the same exact artifact. V2 must also cross-check the explicit correction cutover against the ordinary predecessor's owner-resolved `superseded_at`; neither side may manufacture or hide the other. Both versions require successor verification-attempt release exactly at the predecessor cutover. No durable adapter may infer currentness from mutable current rows, unrelated result attempts, different-evidence-family attempts, different artifacts in the same family, or caller-supplied timestamps. +The typed-calibration adapter must exact-key the complete target-population/window and auxiliary/benchmark/generating-method/artifact/application-owner tuple. Calibration auxiliary persistence must recover the authorization-receipt release instant from immutable owner evidence and enforce `owner_contract_released_at <= authorization_receipt_released_at <= authorized_from`; it must never manufacture that chronology from a mutable authorization row or caller timestamp. Calibration support persistence must separately bind the exact typed calibration receipt to those auxiliary and benchmark identities, recover release/effective/cutover chronology from owner evidence, enforce authorization release before effective start and scientific use, reject benchmark evidence released after calibration construction, and reject benchmark evidence superseded at or before construction. Calibration, eligibility, nonresponse, trimming/bounding, base-weight and point-weight/variance compatibility ordinary cutovers must agree with their explicit successor graph on one atomic correction instant: `predecessor.superseded_at == successor.released_at`. Calibration-benchmark, final-weight and validation-result correction adapters have the same atomic release-at-cutover invariant. Base-weight and final-analysis-weight persistence must select evidence by their complete caller-known reproducibility tuples. Final-weight component-binding persistence must key only the exact final receipt identity, return exactly one canonical released binding, preserve exact base and every governed adjustment receipt reference-version-digest locator in contiguous one-based sequence, and reject ambiguous digest-only reverse lookup. Non-verifiability persistence must key the exact immutable predecessor verification-attempt reference/digest; for `non_reproducible` it must additionally key the exact failed-evidence reference/digest, while failed-evidence and attempt-release instants remain owner chronology. Missing-evidence correction uses the v1 same-result/same-obligation successor graph. Non-reproducible correction uses v2 and must preserve the same predecessor failed-evidence reference/digest in addition to result, evidence family, verification attempt and owner contract; it must persist/recover the failed-evidence release instant as owner chronology and require the successor target tuple to equal the same exact artifact. V2 must also cross-check the explicit correction cutover against the ordinary predecessor's owner-resolved `superseded_at`; neither side may manufacture or hide the other. Both versions require successor verification-attempt release exactly at the predecessor cutover. No durable adapter may infer currentness from mutable current rows, unrelated result attempts, different-evidence-family attempts, different artifacts in the same family, or caller-supplied timestamps. ## Test contract @@ -163,4 +163,4 @@ PYTHONPATH=services/workforce-validation-api/src:packages/keyverse-adapter/src \ Scientific-authority tests cover authorization-before-owner-read, static port validation, malformed references/digests/versions/timestamps, exact owner-coordinate matching, UUID detachment/alias attacks, structural immutability, non-public view issuance, calibration-auxiliary owner-contract and authorization-receipt release chronology, benchmark correction chronology, complete typed-calibration context and fallback provenance, calibration-support release/effective/currentness chronology including retroactive-authorization rejection and stale benchmark rejection, typed-calibration owner-resolved currentness and explicit predecessor/successor correction authority with exact release-at-cutover, typed nonresponse currentness and supersession, trimming/bounding currentness and supersession, eligibility currentness and supersession, complete base/design-weight lookup coordinates plus owner-resolved currentness and explicit predecessor/successor correction authority, complete final-analysis-weight lineage/currentness/supersession, deterministic final-weight-to-component receipt binding/currentness including malformed nested and outer record rejection, complete point-weight/variance compatibility/currentness and explicit supersession authority, validation-result currentness/supersession, explicit missing/non-reproducible evidence with exact verification-attempt identity and chronology, ordinary exact failed-artifact lookup for non-reproducible outcomes, v1 same-result/same-failed-evidence-obligation correction for missing predecessors, and v2 exact failed-artifact correction for non-reproducible predecessors including exact failed-artifact lookup identity, ordinary-cutover alignment, hostile mismatched-artifact, chronology, authorization, owner-port and structural-integrity cases. -These source contracts are not terminal acceptance by themselves. The PR remains Draft until the exact current head executes with 100% owned statement/branch coverage, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. +These source contracts are not terminal acceptance by themselves. Review admission remains non-authorizing until the exact current head executes with 100% owned statement/branch/docstring/edge evidence, the PostgreSQL owner-schema contract is GREEN, applicable security workflows are terminal, and normal independent review/governance requirements are satisfied. Only protected/released owner evidence may be consumed as durable scientific authority. From 01c3da48b1d013b57ea749bfb4284d314e3ff3a6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 20:11:29 +0900 Subject: [PATCH 598/603] docs(workforce-validation): neutralize lifecycle overclaim --- .../src/orgmetra_workforce_validation_api/registry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py index 8c08bb2c3..c2a1985a8 100644 --- a/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py +++ b/services/workforce-validation-api/src/orgmetra_workforce_validation_api/registry.py @@ -255,7 +255,7 @@ def criterion_blueprint_id(self) -> UUID: @property def study_status_code(self) -> str: - """Return the governed study lifecycle status code.""" + """Return the stored study status code without inferring lifecycle governance.""" return self[3] @property From 202d9d87d6a45529497279b881169aab127727f8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 20 Sep 2026 20:16:49 +0900 Subject: [PATCH 599/603] test(workforce-validation): keep wheel builds off checkout --- .../test_package_metadata_compatibility.py | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py index 0b78da633..187577f37 100644 --- a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py +++ b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py @@ -10,6 +10,7 @@ import io import os from pathlib import Path, PurePosixPath +import shutil import subprocess import sys import tomllib @@ -541,8 +542,24 @@ def test_built_distribution_closure_installs_without_checkout_imports(tmp_path: wheelhouse = tmp_path / "wheelhouse" wheelhouse.mkdir() + build_sources = tmp_path / "build-sources" + build_sources.mkdir() environment = _subprocess_environment() for source_root in (_KEYVERSE_ROOT, _SERVICE_ROOT): + build_root = build_sources / source_root.name + shutil.copytree( + source_root, + build_root, + ignore=shutil.ignore_patterns( + "__pycache__", + ".pytest_cache", + ".coverage", + "build", + "dist", + "*.egg-info", + "*.pyc", + ), + ) subprocess.run( [ sys.executable, @@ -555,9 +572,9 @@ def test_built_distribution_closure_installs_without_checkout_imports(tmp_path: "--no-build-isolation", "--wheel-dir", str(wheelhouse), - str(source_root), + str(build_root), ], - cwd=_REPOSITORY_ROOT, + cwd=tmp_path, env=environment, check=True, ) From a9d3f11d3037dcf46857837e04838fda552e5f4c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 1 Oct 2026 15:28:37 +0900 Subject: [PATCH 600/603] test(workforce-validation): reject checkout-mutating wheel builds --- .../tests/test_built_wheel_record_integrity.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/tests/test_built_wheel_record_integrity.py b/services/workforce-validation-api/tests/test_built_wheel_record_integrity.py index a72fae2aa..342f3075d 100644 --- a/services/workforce-validation-api/tests/test_built_wheel_record_integrity.py +++ b/services/workforce-validation-api/tests/test_built_wheel_record_integrity.py @@ -33,10 +33,11 @@ def test_built_owned_wheels_have_complete_verified_records(tmp_path: Path) -> No wheelhouse = tmp_path / "wheelhouse" wheelhouse.mkdir() environment = _METADATA_CONTRACT._subprocess_environment() - for source_root in ( + source_roots = ( _METADATA_CONTRACT._KEYVERSE_ROOT, _METADATA_CONTRACT._SERVICE_ROOT, - ): + ) + for source_root in source_roots: subprocess.run( [ sys.executable, @@ -60,3 +61,6 @@ def test_built_owned_wheels_have_complete_verified_records(tmp_path: Path) -> No assert len(wheel_paths) == 2, "RECORD acceptance must inspect both owned built wheels" for wheel_path in wheel_paths: _METADATA_CONTRACT._validate_wheel_record(wheel_path) + assert all(not (source_root / "build").exists() for source_root in source_roots), ( + "wheel RECORD acceptance must not mutate repository source roots" + ) From a00a896486c889312b74c3049c2826553b41e344 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 1 Oct 2026 15:28:38 +0900 Subject: [PATCH 601/603] test(workforce-validation): isolate RECORD wheel builds --- .../test_built_wheel_record_integrity.py | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/services/workforce-validation-api/tests/test_built_wheel_record_integrity.py b/services/workforce-validation-api/tests/test_built_wheel_record_integrity.py index 342f3075d..4e08e9092 100644 --- a/services/workforce-validation-api/tests/test_built_wheel_record_integrity.py +++ b/services/workforce-validation-api/tests/test_built_wheel_record_integrity.py @@ -5,6 +5,7 @@ import importlib.util from importlib.metadata import version as installed_version from pathlib import Path +import shutil import subprocess import sys @@ -32,12 +33,28 @@ def test_built_owned_wheels_have_complete_verified_records(tmp_path: Path) -> No wheelhouse = tmp_path / "wheelhouse" wheelhouse.mkdir() + build_sources = tmp_path / "build-sources" + build_sources.mkdir() environment = _METADATA_CONTRACT._subprocess_environment() source_roots = ( _METADATA_CONTRACT._KEYVERSE_ROOT, _METADATA_CONTRACT._SERVICE_ROOT, ) for source_root in source_roots: + build_root = build_sources / source_root.name + shutil.copytree( + source_root, + build_root, + ignore=shutil.ignore_patterns( + "__pycache__", + ".pytest_cache", + ".coverage", + "build", + "dist", + "*.egg-info", + "*.pyc", + ), + ) subprocess.run( [ sys.executable, @@ -50,9 +67,9 @@ def test_built_owned_wheels_have_complete_verified_records(tmp_path: Path) -> No "--no-build-isolation", "--wheel-dir", str(wheelhouse), - str(source_root), + str(build_root), ], - cwd=_METADATA_CONTRACT._REPOSITORY_ROOT, + cwd=tmp_path, env=environment, check=True, ) From 42ef22e78a279c5a5e4812b0d76dbb2f01d5cce6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 1 Oct 2026 15:28:39 +0900 Subject: [PATCH 602/603] test(workforce-validation): fail wheel builds on deprecations --- .../tests/test_package_metadata_compatibility.py | 1 + 1 file changed, 1 insertion(+) diff --git a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py index 187577f37..b49432414 100644 --- a/services/workforce-validation-api/tests/test_package_metadata_compatibility.py +++ b/services/workforce-validation-api/tests/test_package_metadata_compatibility.py @@ -88,6 +88,7 @@ def _subprocess_environment() -> dict[str, str]: environment["PIP_CONFIG_FILE"] = os.devnull environment["PIP_NO_INDEX"] = "1" environment["PIP_DISABLE_PIP_VERSION_CHECK"] = "1" + environment["PYTHONWARNINGS"] = "error" return environment From 630e2c0a771f6dff0748307ea22b72c0ef9d0f51 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 1 Oct 2026 15:28:40 +0900 Subject: [PATCH 603/603] fix(workforce-validation): make wheel acceptance warnings-fatal --- CHANGELOG.md | 1 + manifest.json | 6 +++--- services/workforce-validation-api/pyproject.toml | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e2deefb0..508ecab81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ All notable changes to Orgmetra will be documented in this file. ### Changed +- Active-PR Workforce Validation wheel acceptance now builds both owned distributions from temporary source copies, proving RECORD integrity without mutating the checkout. Offline wheel subprocesses also treat Python warnings as errors, and the service publishes its Apache-2.0 license through the current SPDX string form instead of deprecated setuptools table metadata. - Active-PR Workforce Validation coverage recovery now exercises exact owner-capability admission, immutable release-view identities, version and chronology rejection, digest independence, approximation semantics, final-weight component corroboration, and base/nonresponse/trimming supersession edge contracts. An earlier exact head passed 1,306 tests with 4,487/4,487 owned statements and 1,070/1,070 owned branches covered; subsequent authorized-view sealing repairs add new production and hostile-regression branches, so that verdict does not transfer and final exact-head functional, statement, branch, docstring, and edge evidence must be reacquired before integration. - Active-PR Workforce Validation acceptance fixtures now track released owner contracts, supersession cutovers, owner-read field sets, and standard-library timezone-provider failures exactly; wheel acceptance validates every owned wheel's internal identity and metadata before producing any outer artifact hash. - Consolidated repository-owned PR validation from twelve workflows into one Foundation CI job, while keeping the dual-cluster recovery rehearsal separately path-scoped. Central required review and security workflows remain organization-owned. diff --git a/manifest.json b/manifest.json index a1cac9e48..b253f4b8f 100644 --- a/manifest.json +++ b/manifest.json @@ -29,9 +29,9 @@ }, { "path": "CHANGELOG.md", - "sha256": "ec2120f23ca8c729022cb90da1f3e303b2040ddf76c7d2e244524db3c4b574a0", - "bytes": 20634, - "lines": 82 + "sha256": "42ef89549edf4aa0d7dd03eece2a386895a2561df06f277761c45f575c4c21e5", + "bytes": 21006, + "lines": 83 }, { "path": "CLAUDE.md", diff --git a/services/workforce-validation-api/pyproject.toml b/services/workforce-validation-api/pyproject.toml index 6d2039634..ff81b4f6d 100644 --- a/services/workforce-validation-api/pyproject.toml +++ b/services/workforce-validation-api/pyproject.toml @@ -8,7 +8,7 @@ version = "0.1.0" description = "Purpose-bound owner boundary for Orgmetra workforce-validation studies." readme = "README.md" requires-python = ">=3.12" -license = { text = "Apache-2.0" } +license = "Apache-2.0" authors = [{ name = "ContextualWisdomLab" }] dependencies = [ "orgmetra-keyverse-adapter==0.1.0",