fix: normalised determination envelope for orchestrator signature verification (medicaid signatures broken in transit)
Context
The orchestrator (services/canopy-eligibility/src/orchestrator.rs) re-serialises ProgramDeterminationResponse and verifies against the persisted JWS. canopy-medicaid signs MedicaidDetermination — which carries fields NOT present on the response shape: assigned_coa_track, benefit_type, denial_reason, denial_reason_codes, fmap_rate, continuous_eligibility_end, medicaid_application_id, person_id, created_at.
Result: re-serialised bytes differ from signed bytes. Medicaid signatures verify as invalid on the orchestrator side today. The current band-aid is the sig_verified branch wrapping all Medicaid capture — quarantined determinations don't propagate medicaid_assigned_group into combined results, so the bug is contained but the program-service signing is effectively load-bearing waste for medicaid.
The medicaid-orchestrator-ee15-wiring plan (now archived, line 249 of its Errata) called this out and explicitly punted the fix to a follow-up plan — "File as determination-envelope-normalisation.adoc when the orchestrator signature-verification pipeline is reworked." That plan was never filed.
This is acknowledged broken in the CHANGELOG (line 184). Surfaced by the multi-agent audit 2026-05-05 as the highest-priority untracked correctness gap.
Acceptance criteria
- Design doc / plan filed at
docs/modules/ROOT/pages/plans/determination-envelope-normalisation.adocwith at least: aSignableDeterminationenvelope (or equivalent) shared between program services and orchestrator, the byte-stable serialisation policy, and migration-or-coexistence path for in-flight quarantined determinations. - All 5 program services (snap / tanf / medicaid / caps / wic) sign the normalised envelope rather than their internal
*Determinationstruct. - Orchestrator verifies the same envelope; signature-quarantine becomes a real failure mode rather than a per-program design choice.
- Integration test: a Medicaid determination at every COA path reaches
approvedstatus in the combined result (nosignature_quarantinedmasking the bug). - CHANGELOG entry flips the "known issue" line under canopy-medicaid signature verification.
Why priority::high
Without this, Medicaid determinations cannot pass the orchestrator's signature gate — every single Medicaid case requires the quarantine band-aid. ADR-002 (signed determinations as the trust boundary) is effectively unenforceable for Medicaid. This blocks Pub 1075 ATO-quality evidence for the Medicaid path and any production deployment that would actually rely on per-program signing.
Surfaced by
Multi-agent plan-vs-code audit, 2026-05-05.