informed-decision/tests/test_sitting_requester_registration.py
tegwick 12311d196c Sitting requester: allow approval:read, keep approve/consume refused
key-cape 82b471f prepares approval:read on informed-decision-sitting-requester
for present_existing intake reads (INFD-WP-0010). The registration doc, JSON
and test no longer forbid read (applied state stays create-only; read is
recorded as preparedScopes), and create_sitting_approvals checks only
approve and consume, so it keeps working once read is live.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 5502@bnt-lap001
Assistant-Session: 68b3b02f-5d0f-4e71-8421-796f62e50196
2026-11-01 04:02:50 +01:00

76 lines
3.7 KiB
Python

import json
import sys
from pathlib import Path
from informed_decision.records import memo_from
ROOT = Path(__file__).resolve().parents[1]
REG = json.loads((ROOT / "docs" / "keycape-sitting-requester-registration.json").read_text())
INTENTS = json.loads((ROOT / "docs" / "batches" / "2026-09-14" / "approval-create-intents.json").read_text())
def test_sitting_requester_never_approves_or_consumes_and_is_applied():
assert REG["clientId"] == "informed-decision-sitting-requester"
assert REG["audience"] == "approval-engine"
# approval:read is prepared in key-cape 82b471f (source only) for present_existing reads.
assert REG["allowedScopes"] in (["approval:create"], ["approval:create", "approval:read"])
assert REG["preparedScopes"] == ["approval:read"]
assert REG["grantTypes"] == ["client_credentials"]
assert REG["clientType"] == "confidential"
assert REG["serviceSubject"] == "informed-decision"
assert REG["tenant"] == "tenant:platform"
assert REG["applied"] is True
assert REG["ccrs"] == ["CCR-2026-0026", "CCR-2026-0027"]
assert "redirect" not in json.dumps(REG).lower()
forbidden = {"approval:approve", "approval:consume", "openid"}
assert forbidden.isdisjoint(REG["allowedScopes"])
assert forbidden.isdisjoint(REG["preparedScopes"])
assert not REG["secretRef"].startswith("s.") and ":" in REG["secretRef"]
def test_create_intents_cover_the_sitting_and_are_not_posted():
assert INTENTS["posted"] is True
assert INTENTS["status"] == "created-unapproved"
assert INTENTS["human_control"] is True
assert INTENTS["pdp_path"] is False
ids = [row["memo_id"] for row in INTENTS["intents"]]
sitting_ids = []
batch_root = ROOT / "docs" / "batches" / "2026-09-14"
for name in ("credentials", "decisions"):
index = json.loads((batch_root / name / "index.json").read_text())
sitting_ids.extend(row["memo_id"] for row in index["ordinal"])
assert ids == sitting_ids
undecided = [row for row in INTENTS["intents"] if row["create_client"] == "undecided"]
assert [row["memo_id"] for row in undecided] == ["infd-20260914-c01"]
for row in INTENTS["intents"]:
binding = row["binding"]
assert set(binding) == {"action", "actor", "principal", "purpose", "target"}
assert binding["actor"] == "informed-decision"
assert "digest" not in binding
batch = "credentials" if "-c0" in row["memo_id"] else "decisions"
memo = memo_from(json.loads((batch_root / batch / f"{row['memo_id']}.memo.json").read_text()))
assert binding["target"]["id"] == memo.binding.target.id
assert memo.question.startswith(binding["purpose"][:20]) or binding["purpose"] in memo.question or memo.question.rstrip("?") in binding["purpose"]
def test_create_intents_match_approval_engine_canonical_binding():
engine = Path("/home/worsch/approval-engine")
sys.path.insert(0, str(engine))
from approval_engine.binding import BINDING_FIELDS, binding_digest, canonical_binding
for row in INTENTS["intents"]:
canon = canonical_binding(row["binding"])
assert tuple(canon) == BINDING_FIELDS
digest = binding_digest(canon)
assert digest.startswith("sha256:") and len(digest) == 71
def test_custody_request_is_unallocated_and_does_not_widen_t03_path():
text = (ROOT / "docs" / "sitting-requester-custody-request.yaml").read_text()
assert "status: requested" in text
assert "id: unallocated" in text
assert "kv_path: platform/workloads/informed-decision/sitting-requester" in text
assert "kv_path: platform/workloads/secrets-engine/approval-requester" not in text
md = (ROOT / "docs" / "sitting-requester-custody-request.md").read_text()
assert "Do not widen" in md
assert "No secret" in md