NK-WP-0056-T19: executor approval exercise; parse approval-engine's stored assurance object
The exercise runs the real request phase, KeyCape client credentials, preflight and consume against KeyCape's pinned image and approval-engine's source with synthetic keys. It found that approval-engine stores an entry's assurance as the verified token's JSON object (KeyCape assuranceClaim), so the executor's comparison with a bare "aal2" refused every real founder approval. entry_is_aal2 now requires level aal2/aal3 with mfa true and fails closed otherwise. Fakes use the real shape. The request-phase tests freeze the clock inside the example admission's window (they had expired on 2026-11-03T11:00Z). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 523928@bnt-lap001 Assistant-Session: 6c737afb-9c14-4152-9f02-477214b9c350
This commit is contained in:
parent
338483f621
commit
625ad652b9
6 changed files with 458 additions and 6 deletions
|
|
@ -106,6 +106,20 @@ class Deps:
|
|||
sleep: Callable[[float], None] = time.sleep
|
||||
|
||||
|
||||
def entry_is_aal2(assurance) -> bool:
|
||||
"""An approval entry's assurance as approval-engine stores it: the approver token's verified `assurance` claim,
|
||||
serialized as JSON (approval-engine api.py, POST .../entries). KeyCape mints {"level", "methods", "mfa", "source",
|
||||
"at"} (token.go assuranceClaim). The pilot requires level aal2 with MFA verified in that login; aal3 also passes.
|
||||
Anything else, including a bare "aal2" string that no real carrier produces, fails closed (NK-WP-0056-T19)."""
|
||||
if isinstance(assurance, str):
|
||||
try:
|
||||
assurance = json.loads(assurance)
|
||||
except ValueError:
|
||||
return False
|
||||
return (isinstance(assurance, dict) and assurance.get("level") in ("aal2", "aal3")
|
||||
and assurance.get("mfa") is True)
|
||||
|
||||
|
||||
def iso(t: dt.datetime) -> str:
|
||||
return t.astimezone(dt.UTC).isoformat(timespec="seconds").replace("+00:00", "Z")
|
||||
|
||||
|
|
@ -177,7 +191,8 @@ class Run:
|
|||
raise Refused("approval_no_entries")
|
||||
for entry in entries: # aal2 is recorded, not enforced, by approval-engine today: check every entry
|
||||
if (entry.get("subject_id") not in allowed or str(entry.get("principal_type", "")).lower() != "human"
|
||||
or entry.get("assurance") != "aal2" or entry.get("subject_id") == self.cfg.executor_identity):
|
||||
or not entry_is_aal2(entry.get("assurance"))
|
||||
or entry.get("subject_id") == self.cfg.executor_identity):
|
||||
raise Refused("approval_entry")
|
||||
self.approver_subject = entries[0]["subject_id"]
|
||||
window_end = bea.parse_time(spec["window"]["not_after"])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue