Add production trust v2 contracts and offline authority - #16
Conversation
|
Triaged during the 2026-08-27 queue drain. This PR is parked with its cluster, not queue debt. Two of its three checks pass. The failing one is a real defect, and it is now tracked separately as #17: It was deliberately not fixed here. |
validate_production_lifecycle.py still enforced the v1 policy contract while production-lifecycle-policy.json and its schema moved to v2, so check_profile.py refused the repository. Two v1 anchors had to go together: the pinned POLICY_SCHEMA, and a closed key set naming maximum_admission_days and summary_authority. Neither key exists in v2. summary_authority was not renamed. v2 moved the certificate identity that signs Production evidence into production-evidence-policy.json, keyed by evidence kind, for v2 objects. The ledger this module reads is the retained v1 ledger, so its records stay verifiable only against the authority, target map, policy revision and policy digest that issued them. Those move from policy data to pinned module constants, and _validate_summary_authority keeps every check the v1 policy path ran, now applied to the pinned trust root. Deleting the field without that replacement would have left the validator reporting success while nothing checked who signed the evidence. maximum_admission_days split in two. production_trust.validate_release enforces 30 days on openadapt.qualification-release/v1 and validate_qualification_admission enforces 7 days on openadapt.qualification-admission/v3. The retained ledger holds release admissions on the production channel, so maximum_release_admission_days governs its expiry. Both maximums keep the 1-to-30 bound and must now equal the window the trust core actually applies, so neither number can drift unnoticed. The v2 target contract is cross-checked against production_trust.TARGET_CONTRACTS for claim scope, source repository and repository id, and a target may not require an artifact kind that contract does not define. The tests now read the published policy instead of a fixture mirroring the validator's own constants, which is why 135 tests passed while check_profile failed. New tests cover the published document, both admission windows, and the certificate-identity binding: a refactor that empties the authority or removes the verification path fails rather than passing quietly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
What this draft contains
This branch replaces URL-based trust decisions with content-addressed v2 references. A consumer verifies the repository and registry commit, raw object bytes, object size, semantic identity, adjacent signature bundle, signed issuer, active signer registry, authority state, revocation state, and validity window.
The branch also defines the seven Production release profiles and the separate Support release family. Support admissions cannot enter the seven-target Production projection. The registry contains 34 fixed regular and bundle kinds.
The new offline public-trust profile checks canonical object and bundle bytes, v2 references, current state identities, the selected registry key, the signed profile, and the signature. The policy marks this profile inactive until every consumer pins the exact verifier.
No workflow in this draft changes a live setting or publishes a release.
Checks
python -m pytest -q tests: 129 passed, with 177 schema subtestsactionlint .github/workflows/*.ymlgit diff --checkRetained v1 files
This first draft keeps nine v1 files. The follow-up will delete them after Web, Evals, Ops, Internal, and each release caller passes against the same v2 head. Git history remains the recovery source.
production-lifecycle-admissions.jsonevidence-registry.jsonplus the signed lifecycle feed and checkpoint chainscripts/validate_production_lifecycle.pyscripts/production_trust.pyandscripts/validate_production_lifecycle_ref.pyscripts/prepare_lifecycle_change.pytests/test_production_lifecycle.pytests/test_production_trust.pyand the full-chain reference teststests/test_governance_workflows.pyschemas/production-lifecycle-admissions.schema.json.github/workflows/production-lifecycle-activation.yml.github/workflows/production-lifecycle-ref.yml.github/workflows/qualification-authority-state.yml.github/workflows/qualification-revocation-state.ymlThe retained v1 tests use a private test fixture for their own closed contract. The v2 runtime does not accept a v1 fallback.
Draft limits
The new trust profile stays inactive. Existing publication and lifecycle paths must fail closed until the required roots and pinned consumers exist.