OPT-GOV Phase 4 — passport chaining + SIG-042 harness; treasury gate verified, not rebuilt
Branch: claude/opt-gov-phase4-treasury-passport · Session: 7pjhmg · Date: 2026-08-22
Authority: OPT-GOV_PRE_APPROVAL_2026-08-21 (standing GATE-1, conditions verified below) + owner in-session triple release 2026-08-22 (approved:merge/commit/deploy) ruling the Prompt-0 collisions as recommended. This phase adds no flags.
BUILD 2 — ValidationPassport: per-tenant chaining + chain-walk verifier (extend-in-place)
The shipped package machinery (assemble / persist / sha256 seal / KMS signature) proves one document unchanged and its origin; neither proves the series — a whole package could be deleted or re-sealed-and-rewritten with no surviving artifact saying so. Landed in contracts/mizoki_contracts/passport_package.py + services/service-audit-replay/main.py:
- Chain block inside the sealed body: every persisted package version carries
chain(schema_versionpassport-chain-v1,seq,prev_link_hash,prev_package_id,prev_package_sha256) — genesis-anchored per tenant (the series a customer audits; never cross-tenant). Chain is embedded before signing, so an armed signer's signature covers it. - Append-only link mirror: persist writes the package + a
passport_chain_linksrecord atomically (transact_write); the link's own hash covers tenant, seq, package/decision ids, package sha256, predecessor hash. Registered in the erasure-posture store registry (ledger-retention, no person identity by construction — the machine-derived scan enforces registration). - Reads grow nothing: persist is substance-aware — a re-read whose body (minus
assembled_at/seal/signature/chain position) matches the stored version serves the stored document and appends no link. Signing state is substantive: arming the signer produces and chains a signed version. Substantive change (e.g. realized-outcome backfill) appends the next link. - Chain-walk verifier:
verify_passport_chain+ routeGET /api/v1/passport-chain/{tenant}/verify(verify_caller + tenant-resolved). Checks seq contiguity from 0, link-hash recomputation, predecessor linkage, cross-tenant splice, and — per latest link of each package — stored-document existence, seal, sha agreement, embedded position. Every failure is a named break;links: 0reads "no chain yet", never "verified". The load-bearing case is pinned in test: a re-sealed rewrite fools the seal and only the chain names it. model_versionin the sealed payload: propose-time passthrough (ProposeRequest.model_version→decision_requests→ package), declared by the proposer, honest-absent otherwise — never inferred. Added toSPEC_FIELDS.- Invariants preserved: no ninth decision object (links are storage records of the read-model layer; the module still defines zero pydantic contracts — pinned by the existing test); the decision ledger stays append-only; single-writer seq assignment stated honestly in the docstring (concurrent-writer collision surfaces as a verifier break, not silent loss).
- Skill delta (logged, not edited — Boss skill process owns bodies): SKILL.md/boss skillpack say "16 fields";
SPEC_FIELDSwas already 17 and is now 18 withmodel_version, and packages now carrychain. Needs a skill-process update.
SIG-042 e2e harness
tests/governance/test_passport_chain.py::TestSig042Harness drives the J-02 CPA-spike narrative through the real six in-process governance services (synthetic-labeled; the illustrative demo fixture stays separate) and asserts the Phase-4 contract: recommendation produced (eligible decision, stage-3-recommend-only authorization, chosen path = hold-bids-route-repair) · no dispatch at the L0/L1 posture (outcome records intent, executed=False) · valid chained passport (seal verifies, chain.seq=0 genesis-anchored, link persisted, chain-walk route returns valid with zero breaks, signature verdict stays fail-closed while signing is unarmed).
13 further tests pin the chain contract: growth + linkage across decisions, re-reads append nothing, backfill appends, naive vs re-sealed rewrite, link rewrite, seq gap, empty chain, tenant isolation, signature-covers-chain (LocalPemSigner, real keys), model_version both directions, direct-persist callers chained too.
BUILD 1 — treasury liquidity gate: VERIFY-ONLY (collision ruling: skip)
Measured, no code delta: the F5 liquidity-floor gate is live in services/service-policy-engine/main.py (fail-closed, veto reasons, TBR human-review queue that is deliberately not an approvals queue, /reload) with DCP transactional reservations (contracts/mizoki_contracts/treasury*.py). DEL_TREASURY_GATE was NOT retrofitted: F5 arms by config-presence; wrapping the live gate in a default-false flag would DARK a shipped fail-closed control — the rule-01 "never weaken a guard" case. Documented here as the owner-ruled skip; the stockout/supply veto half of the original P4 wording is Phase 3's DEL-side build.
Gate results (pre-push, fresh venv)
governance suite 434 passed (420 baseline + 14 new, 0 failed) · remediation suite 294 passed (after adding google-auth/google-cloud-firestore to the venv — two pre-existing environment gaps, not diff effects) · skill_sync.py --audit, skills_sync --check, ontology_skills_sync --check, rule-03 V1–V3 greps, claude_memory.py check --strict: see commit gate line · no new flags · no protected or site-visible paths · no registry change needed (no new service or ingress surface — the verifier route rides audit-replay behind verify_caller).