feat: complete and prove the authorization chain end to end
Implements step 2 (access-engine POST /v1/check) and wires the whole GH-DEC-2026-003 sequence together, then proves it against a live throwaway OpenBao rather than only unit-level fakes. - decision_check.check_decision performs the PDP call; an unreachable or non-200 PDP raises, since silence is never permission. - approval_consume.authorize_action coordinates steps 1 and 2 and returns an AuthorizedAction. Both steps build the same CheckRequest via a shared _expected_request, since two descriptions of the action cannot produce corresponding digests. - apply_unreachable_engine_stance takes authorized=. The published map defines fail_closed as no side effect WITHOUT a durable decision record, so holding a validated one means the residue does not apply. Not a bypass: both steps must have succeeded and CAS consume still precedes OpenBao. Unconfigured still returns None and fails closed. The end-to-end test caught one more instance of the cross-vocabulary bug: a leftover comparison of the claim's binding.action against ours. The claim says secrets.kv.destroy where we say destroy, so it would have failed against every real claim. Removed; the tie is pdp_digest. Integration coverage asserts PIP-then-PDP ordering, that consume is the last step before the backend, and that an unreachable PDP, denied decision, invalid claim, missing pdp_digest, consume conflict and action mismatch each stop before OpenBao. 284 tests pass; production still fails closed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M65ovP3eiiPHubibvWs9mD Assistant: claude-code Assistant-Model: opus Assistant-Process: 393550@bnt-lap001 Assistant-Session: 4bb359f9-1f12-4410-9e76-079cf23c82e4
This commit is contained in:
parent
e8144f315c
commit
f62d3fe789
9 changed files with 675 additions and 44 deletions
|
|
@ -36,12 +36,14 @@ class StanceApplication:
|
|||
action: str
|
||||
demo_exception: bool = False
|
||||
decision_id: str = ""
|
||||
authorized: bool = False
|
||||
|
||||
def as_evidence(self) -> dict[str, object]:
|
||||
payload: dict[str, object] = {
|
||||
"stance_stage": self.stage,
|
||||
"stance_failure_mode": self.failure_mode,
|
||||
"stance_demo_exception": self.demo_exception,
|
||||
"stance_authorized": self.authorized,
|
||||
}
|
||||
if self.decision_id:
|
||||
payload["stance_decision_id"] = self.decision_id
|
||||
|
|
@ -111,12 +113,20 @@ def apply_unreachable_engine_stance(
|
|||
action: str,
|
||||
*,
|
||||
stance_map: PepStanceMap | None = None,
|
||||
authorized: bool = False,
|
||||
) -> StanceApplication:
|
||||
"""Apply the published unreachable-engine residue for a live action.
|
||||
|
||||
``fail_closed`` without the demo exception raises ``DecisionError`` carrying
|
||||
named stance fields. ``fail_open`` is the documented residue: continue to
|
||||
the existing lane-approval check, which is itself a gap until T02.
|
||||
``fail_closed`` is the *unreachable-engine* residue, not a blanket ban: the
|
||||
published map defines it as no protected side effect without a durable
|
||||
access-engine decision record. ``authorized=True`` means the caller already
|
||||
obtained and validated that record for this exact action, so the engine was
|
||||
reachable and the residue does not apply. It is never a bypass -- the caller
|
||||
must have completed steps 1 and 2, and GH-DEC-2026-003 still requires a
|
||||
successful CAS consume before any OpenBao call.
|
||||
|
||||
Without such a record, ``fail_closed`` raises ``DecisionError`` carrying
|
||||
named stance fields. ``fail_open`` is the documented residue for build/test.
|
||||
"""
|
||||
loaded = stance_map or load_pep_stance()
|
||||
stage, mode = loaded.for_stage(getattr(entry, "stage", "unknown"))
|
||||
|
|
@ -126,8 +136,9 @@ def apply_unreachable_engine_stance(
|
|||
failure_mode=mode,
|
||||
action=action or "unknown",
|
||||
demo_exception=bool(demo and mode == "fail_closed"),
|
||||
authorized=bool(authorized),
|
||||
)
|
||||
if mode == "fail_closed" and not demo:
|
||||
if mode == "fail_closed" and not demo and not authorized:
|
||||
raise DecisionError(
|
||||
f"production action '{applied.action}' requires a durable "
|
||||
"access-engine decision record; live production remains disabled",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue