Repository navigation
authority(0.7.1g1P2-Step3b): wire the canonical certificate ledger to the real transport - #474
Conversation
… the real transport Step 3a proved the consumption semantics on fixtures. This proves the transport: the real committed certificate ledger and the real committed admission ledger, loaded through the real loaders from the repository root, fed to the real consumption verifier. This closes the load path P1M reported as unwired - until now nothing loaded config/quality/mutation-authority-digest-certificates.yml from the repository root, so the ledger's own load was only ever exercised against fixtures. Six discriminators, all against committed authority rather than fixtures: - the canonical ledger loads through the real loader and holds exactly one certificate; - that certificate's admissionSetDigest equals the digest of the real committed identities, so adding or removing an admission from the real ledger changes this outcome; - its fromDigest equals the single populationDigest the real committed admissions are bound to, which is M41's real binding rather than a fixture's; - real base authority produces a Valid consumption, so the positive fact is reachable from the committed ledgers end to end; - a certificate absent from the real base ledger is refused by M43, and one whose target digest was not this transition's measurement is refused by M40. The negative cases matter as much as the positive one: they show the verifier is fed real base authority and real measured data, not values arranged to agree with the certificate. No production code changed. The remaining Step 3b work is certificate-aware M34 and the T1-T19 matrix at both levels. Verification: 39 tests / 0 failures (transport 6, consumption 13, loader 12, ceremony 8); spotless clean; Detekt baseline 4792 -> 4792 with 0 added; verifyChangePolicy PASSED.
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
The change is correct and low-risk on its own, but it touches the authority/governance machinery where final transport-vs-task guarantees warrant a human sign-off.
Review effort: Balanced
Findings: None
What changed in this PR
This PR adds a single test file, CertificateLedgerTransportTest.kt, that proves the authority-transport half of certificate consumption (Step 3b). Where the earlier Step 3a PR (#473) proved consumption semantics against fixtures, this PR feeds the real committed certificate ledger and admission ledger — loaded through the real loaders from the repository root — into the real verifyCertificateConsumption verifier. It fits into the build-logic mutation-authority governance machinery, satisfying the AGENTS.md requirement that authority rules be proven at both the verifier level and against real committed state. No production code changes.
Changes:
- Adds six transport-level discriminators: the canonical ledger loads with exactly one certificate; its
admissionSetDigestmatches the real admissions' digest; itsfromDigestmatches the singlepopulationDigestthe real admissions are bound to; a valid end-to-end consumption; an M43 refusal for a certificate absent from the base ledger; and an M40 refusal for a target digest this transition did not measure. - Reuses the established
gradlew-marker walk-up idiom to locate the repository root, consistent with the Step‑2 loader test.
| File | Description |
|---|---|
| build-logic/src/test/kotlin/dev/tramai/build/quality/CertificateLedgerTransportTest.kt | New real-ledger transport test wiring the committed certificate/admission ledgers through the real loaders into the consumption verifier, with positive and negative (M43/M40) discriminators. |
I verified that every referenced API is used correctly (verifyCertificateConsumption, both loaders, the MutationAuthorityDigestCertificate constructor, admissionSetDigest, and the CertificateConsumption.Valid/Invalid + diagnostic.message surface), that the committed ledger exists with exactly one raw-v1 → authority-v2 certificate, and that each test's control flow reaches the asserted rule code (M43 fires before M40 via the verifier's refusal order; M40 fires on the overridden fresh projection). The repositoryRoot() idiom matches the existing loader test, and the assertions are exact (sizes, digests, rule codes) in line with the repository's test-rigor standard. I found no objective issues to raise.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
a2c6c3a
into
epic/0.7.1-control-plane-authority
…the instance Review finding: there was one fact-production function but three fact-production events. MutationRatchetVerifier recomputed base.admissionAuthority(...) for the outcome-ratchet context and again for the certificate ceremony, and MutationPopulationAdmissionCeremony recomputed it once more inside its own consumption loop for the appearing-identity verdicts. The three results were value-equal, which is not the property the contract asks for: deterministic recomputation is not shared evidence, and value equality lets a later change drift one consumer away from the others without any test noticing. Now: val admissionAuthority = base.admissionAuthority(freshAuthorityProjectionHash) // once and that exact instance is threaded to every consumer - the evolution context (M34 and the appearing-identity path), the admission lifecycle ceremony, and the certificate ceremony (M44/M47) via .certifiedConsumptions. - MutationPopulationAdmissionCeremony.checks/lifecycleChecks/consumptionChecks now take the AdmissionAuthority instead of the raw projection hash and pass it through unchanged; the internal recomputation at the consumption loop is gone. Public signature change: checks() has exactly one caller, the verifier. - The AdmissionAuthority KDoc states the invariant: produced once, never re-derived. - CertificateCustodyTransportTest pins it with a source-level wiring assertion, the form the review sanctioned where a runtime === check would require exposing internals: exactly one admissionAuthority( production call in the verifier, zero in the ceremony, and the certificate ceremony consuming the shared local. Rebased onto the post-#474 epic tip a2c6c3a; diff scope verified as exactly 9 files, and #474's merged CertificateLedgerTransportTest.kt is present at the tip and absent from this diff. Verification: 172 tests / 0 failures (certificate, admission and ratchet suites); spotless clean; Detekt baseline 4792 -> 4792 with 0 added; verifyChangePolicy PASSED against base a2c6c3a, class build-logic.
…epts certified migration + M44/M47 on the same facts (#475) * authority(0.7.1g1P2-Step3b): read the certificate ledger at the base revision M43/M47 are judged against the certificate ledger as it exists in the BASE, but the only loader read the working tree. So the base side had no way to see a certificate at all, and M34 had no facts it could ever consult. This closes that gap. The base-side read now goes through the same path the population, classifications, enrollments and admissions already use: git show "<baseSha>:<path>" into the temp tree, then the ledger's own loader. One authority snapshot (MutationRatchetAuthority) therefore carries the whole base context - population, classifications, enrollments, admissions and now certificates - which is what one coherent transition context means. Absent at base is handled like the other optional ledgers: a base that predates the certificate ledger has none, which is the most restrictive state, since no certified migration exists and every raw-v1 admission still fails M34. A present ledger is validated by its own loader, so a malformed one fails hard rather than degrading into "no certificates". Two discriminators, both against real immutable history rather than fixtures: - at 9ebe7b4 (the P1M merge that minted the certificate) the authority snapshot exposes exactly one certificate, and its fromDigest is the single populationDigest the base's own admissions are bound to; - at 64d0545 (the base P1M was proposed against, which predates the ledger) the snapshot exposes no certificates, while the same snapshot's admissions are non-empty - so the test isolates the certificate ledger instead of showing that some empty snapshot is empty. The default on MutationRatchetAuthority.certificates is the conservative NONE for fixtures; the loader always passes it explicitly from the base revision. Verification: 40 tests / 0 failures (base-revision transport 2, ratchet authority, population admission suites); spotless clean; Detekt baseline 4792 -> 4792 with 0 added; verifyChangePolicy PASSED, 2 changed files, class build-logic. Next: M34 consults these facts at the verifier's decision points, then the T1-T19 matrix. * authority(0.7.1g1P2-Step3b): M34 accepts certified digest migration Completes the certified-migration path: the base snapshot now carries the certificate ledger, and M34 consumes the facts it proves. - MutationRatchetAuthority gains the base-revision certificate read, using the same git-show-into- temp-tree path as the population, classifications, enrollments and admissions. Absent at base is the most restrictive state, as for the other optional ledgers. - appearanceVerdict's M34 branch rejects a raw-v1 admission only when no certified consumption covers that admission's own historical digest. The facts come from one production site, certifiedConsumptions(...), which runs the real verification for each distinct historical digest against the base ledger and the exact base authorization set. A Valid exists only if M43-M42 passed, so the branch cannot be reached by asserting anything. - AdmissionAuthority carries the fresh projection plus the consumptions it certifies as one value. That is what makes the two judgment paths - the lifecycle scan and the appearing-identity path - receive the same object. Feeding one without the other would have made P2's diagnostics contradict themselves for the same 67 rows: admitted in the scan, M34-rejected in the appearing path. It also keeps both signatures inside the parameter budget without suppressing anything. Without a certificate the M34 condition is exactly as before, and AdmissionAuthority(null) is the fail-closed default everywhere. M36/M37 are untouched. Verification: 158 tests / 0 failures, including the new discriminators - certifiedConsumptions yields one fact from a real base certificate and none for an uncertified projection or no certificate; M34 accepts the certified raw-v1 admission and still fails the uncertified one. Plus the base-revision cases: the certificate is present at 9ebe7b4 (the P1M merge) and absent at 64d0545 (P1M's base) while that base's admissions remain non-empty. spotless clean; Detekt baseline 4792 -> 4792 with 0 added; verifyChangePolicy PASSED, 6 changed files, class build-logic. Four genuine Detekt findings fixed by hand - the two LongParameterList ones by introducing the carrier, not by suppressing them. Next: M44/M47 consume the same fact set, and the T1-T19 matrix at both levels. * authority(0.7.1g1P2-Step3b): M44/M47 consume the same Valid facts Last row of the Step 3b path: the certificate lifecycle is now driven by the facts M34 already uses, produced at one site. - MutationRatchetCandidate gains the transition's own certificate ledger, loaded from the repository like the candidate admissions. It is validated (M45 mint binding, M46 retained immutability) but can never authorize a consumption: only the base ledger is consulted, so a candidate that both mints and consumes fails M43. - The verifier now calls MutationAuthorityDigestCertificateCeremony.checks with the base and candidate certificate ledgers and validConsumptions taken from base.admissionAuthority(...).certifiedConsumptions - the same object M34 decides on, so M44 (single use) and M47 (removal custody) cannot disagree with the admission verdicts about what was consumed. - M47's consuming half is now exercised end to end: a certificate may disappear only because a consumption was independently proven in the same transition, never because it was absent. Two existing test fixtures were corrected rather than the rules relaxed: - MutationRatchetAuthorityTest's identity-transition candidate now retains the base's certificate, exactly as it retains the base's admissions. Passing NONE asserted a transition that removes the certificate with no proven consumption, which M47 rightly refuses. This is the same class of fixture defect (and the same fix) as the admissions case in Step 1. - CertificateCustodyTransportTest drives the real committed ledger through the real ceremony: unchanged, it survives; dropped without a proven consumption, M47 fails; dropped with the facts produced from the real ledgers, removal is permitted. M47 firing on that fixture is the evidence that the consuming half is genuinely live, rather than a branch nobody reaches. Verification: 162 tests / 0 failures across the certificate, admission and ratchet suites; spotless clean; Detekt baseline 4792 -> 4792 with 0 added; verifyChangePolicy PASSED, class build-logic. A full :build-logic:test run reached 855 tests with zero genuine test failures before the console call was truncated (its only entry was an infrastructure pseudo-failure from the kill itself); CI runs the complete suite. Remaining: the T1-T19 matrix at verifier and real-task level. * authority(0.7.1g1P2-Step3b): T14/T17/T18 at the transport level, over the real ledger Audited the discriminator matrix against the rules that actually have tests: every rule M01-M47 is exercised somewhere, but three certificate-lifecycle attacks had only rule-level coverage, not the real-task transport coverage the design requires. All three now run against the committed certificate ledger loaded through the real loader. - T18: a retained certificate whose enforced payload was rewritten (here its reason, which is in the payload) fails M46. The rewrite is derived from the real certificate's own fields, so the test cannot pass by accident of a fixture mismatch. - T17: a certificate introduced with a fromBaseSha other than the transition's base fails M45, even alongside the legitimate retained certificate. - T14: a certificate absent from the real base ledger cannot be consumed, however it is cited - the verifier refuses it as M43 rather than accepting the citation. Together with the earlier cases this gives the certificate lifecycle transport coverage for introduction (M45), retention (M46), consumption (M40-M43), single use (M44) and removal custody (M47), all against the real committed ledger. Verification: 165 tests / 0 failures; spotless clean; Detekt baseline 4792 -> 4792 with 0 added; verifyChangePolicy PASSED, 9 changed files, class build-logic. * authority(0.7.1g1P2-Step3b): produce the authority facts once, share the instance Review finding: there was one fact-production function but three fact-production events. MutationRatchetVerifier recomputed base.admissionAuthority(...) for the outcome-ratchet context and again for the certificate ceremony, and MutationPopulationAdmissionCeremony recomputed it once more inside its own consumption loop for the appearing-identity verdicts. The three results were value-equal, which is not the property the contract asks for: deterministic recomputation is not shared evidence, and value equality lets a later change drift one consumer away from the others without any test noticing. Now: val admissionAuthority = base.admissionAuthority(freshAuthorityProjectionHash) // once and that exact instance is threaded to every consumer - the evolution context (M34 and the appearing-identity path), the admission lifecycle ceremony, and the certificate ceremony (M44/M47) via .certifiedConsumptions. - MutationPopulationAdmissionCeremony.checks/lifecycleChecks/consumptionChecks now take the AdmissionAuthority instead of the raw projection hash and pass it through unchanged; the internal recomputation at the consumption loop is gone. Public signature change: checks() has exactly one caller, the verifier. - The AdmissionAuthority KDoc states the invariant: produced once, never re-derived. - CertificateCustodyTransportTest pins it with a source-level wiring assertion, the form the review sanctioned where a runtime === check would require exposing internals: exactly one admissionAuthority( production call in the verifier, zero in the ceremony, and the certificate ceremony consuming the shared local. Rebased onto the post-#474 epic tip a2c6c3a; diff scope verified as exactly 9 files, and #474's merged CertificateLedgerTransportTest.kt is present at the tip and absent from this diff. Verification: 172 tests / 0 failures (certificate, admission and ratchet suites); spotless clean; Detekt baseline 4792 -> 4792 with 0 added; verifyChangePolicy PASSED against base a2c6c3a, class build-logic.
Base: d192e2e (post-#473 epic tip; branch parent verified).
Step 3a proved the consumption semantics on fixtures. This proves the transport: the real committed certificate ledger and the real committed admission ledger, loaded through the real loaders from the repository root, fed to the real consumption verifier. This is the load path P1M reported as unwired.
Six discriminators against committed authority, not fixtures:
The negative cases are as load-bearing as the positive one: they show the verifier is fed real base authority and real measured data, rather than values arranged to agree with the certificate.
Verification: 39 tests / 0 failures (transport 6, consumption 13, loader 12, ceremony 8); spotless clean; Detekt baseline 4792 -> 4792 with 0 added; verifyChangePolicy PASSED, 1 changed file, class build-logic.
Not in this PR: certificate-aware M34, and the T1-T19 matrix at verifier and real-task level. No production code changed. Not merged by the agent.