Problem
Independent exact-head review of #651e0c124 found one remaining authority-minting path after #170. _decision(...) was fail closed and _DECISION_ISSUANCE_IDS was gone, but _DECISION_SNAPSHOT_REGISTRY was still a mutable module attribute. Consumer code could allocate an exact uninitialized AuthorizationDecision, build a valid snapshot with _validated_decision_snapshot(...), insert (weakref.ref(decision), snapshot) under id(decision), and make decision.allowed expose forged allow authority without evaluate_purpose_bound_access(...).
This is not a claim of absolute tamper resistance against arbitrary interpreter memory/reflection. It is the narrower executable boundary already claimed by #170: ordinary consumer code must not receive a module-level authority-storage mutation capability merely by importing the adapter.
Test-first repair in #65
RED 98ad797a8374925d20091d2885a2224cce337970 adds the direct registry-insertion attack. fc4fb5c330f10bfd1eb0f8be27420d0703790aa1 refines that regression so a read-only replacement may reject mutation while a forged exact decision must remain unreadable. Initial production 3ea988edf6bf50d15765784b8b85725d055f4af5 moved backing mutation to closure state and exposed only a read-only mapping view.
A further owner-side RED 05d54aff528c6bfa9d0e23199e1297608a33e70e tightened the boundary: there is no product need to expose even a read-only final-decision registry to module consumers. Final production repair a5d598300cbc804f71a17bf5c0aacb899ded00ed removes _DECISION_SNAPSHOT_REGISTRY from module state entirely. _build_decision_runtime() now retains the registry only in closure state and returns a lookup-only closure plus the evaluator. AuthorizationDecision._snapshot() can read issued evidence through that lookup closure, while ordinary consumers receive neither the backing registry nor a registration function. Direct construction and legacy _decision(...) remain fail closed; valid registration remains evaluator-local after issued request/policy validation.
Acceptance
Keep this issue open. Current canonical #65 head is a5d598300cbc804f71a17bf5c0aacb899ded00ed on protected develop@ef1b143368cb6249c9520ca8cae10ebe844a5aa1. Require fresh terminal Keyverse package, People API, repository-integrity/security evidence at the owned 100% statement/branch contract and independent current-head review before ordinary protected integration. Predecessor checks/reviews do not transfer.
Do not copy this repair into #163/#165 or consume mutable #65 as a released dependency. Descendants adopt only ordinary protected truth through non-force integration.
Problem
Independent exact-head review of #651e0c124 found one remaining authority-minting path after #170.
_decision(...)was fail closed and_DECISION_ISSUANCE_IDSwas gone, but_DECISION_SNAPSHOT_REGISTRYwas still a mutable module attribute. Consumer code could allocate an exact uninitializedAuthorizationDecision, build a valid snapshot with_validated_decision_snapshot(...), insert(weakref.ref(decision), snapshot)underid(decision), and makedecision.allowedexpose forged allow authority withoutevaluate_purpose_bound_access(...).This is not a claim of absolute tamper resistance against arbitrary interpreter memory/reflection. It is the narrower executable boundary already claimed by #170: ordinary consumer code must not receive a module-level authority-storage mutation capability merely by importing the adapter.
Test-first repair in #65
RED
98ad797a8374925d20091d2885a2224cce337970adds the direct registry-insertion attack.fc4fb5c330f10bfd1eb0f8be27420d0703790aa1refines that regression so a read-only replacement may reject mutation while a forged exact decision must remain unreadable. Initial production3ea988edf6bf50d15765784b8b85725d055f4af5moved backing mutation to closure state and exposed only a read-only mapping view.A further owner-side RED
05d54aff528c6bfa9d0e23199e1297608a33e70etightened the boundary: there is no product need to expose even a read-only final-decision registry to module consumers. Final production repaira5d598300cbc804f71a17bf5c0aacb899ded00edremoves_DECISION_SNAPSHOT_REGISTRYfrom module state entirely._build_decision_runtime()now retains the registry only in closure state and returns a lookup-only closure plus the evaluator.AuthorizationDecision._snapshot()can read issued evidence through that lookup closure, while ordinary consumers receive neither the backing registry nor a registration function. Direct construction and legacy_decision(...)remain fail closed; valid registration remains evaluator-local after issued request/policy validation.Acceptance
Keep this issue open. Current canonical #65 head is
a5d598300cbc804f71a17bf5c0aacb899ded00edon protecteddevelop@ef1b143368cb6249c9520ca8cae10ebe844a5aa1. Require fresh terminal Keyverse package, People API, repository-integrity/security evidence at the owned 100% statement/branch contract and independent current-head review before ordinary protected integration. Predecessor checks/reviews do not transfer.Do not copy this repair into #163/#165 or consume mutable #65 as a released dependency. Descendants adopt only ordinary protected truth through non-force integration.