"""The seam to `approval-engine`. A Protocol plus a fake, because the engine is not deployed (`APPROVAL-WP-0002-T01` is `progress`, no pods). When it deploys this becomes a wiring change rather than a build. Hard rules, from `approval-engine/docs/approver-surface-requirements.md`: - `GET /v1/approvals/{id}` and `/claim` need ``approval:read``; `POST …/entries` needs ``approval:approve``. - **Never** ``/consume``. Human principals are refused there in code, and consumption belongs to the PEP causing the side effect (`GH-DEC-2026-003`). - No path containing ``check`` or ending ``/authorize`` exists to call. - ``POST /entries`` **discards its request body** — identity, assurance and ``evidence_ref`` come only from the verified token. So ``view_hash`` does not ride into the entry; correlation is ``(approval_id, subject, approved_at)``. - **No inbox.** Get-by-id only. Never poll for work. - `approved` is a state of an object, never permission to act. """ from __future__ import annotations from dataclasses import dataclass from typing import Protocol FORBIDDEN_SCOPE = "approval:consume" REQUIRED_SCOPES = ("openid", "approval:read", "approval:approve") class ApprovalEngineError(Exception): def __init__(self, status: int, reason: str) -> None: super().__init__(f"{status} {reason}") self.status = status self.reason = reason @dataclass(frozen=True) class EntryResult: """What comes back after a successful entry. These three fields are the correlation triple that ties the entry back to our presentation record — `GOAL.md` DoD-3. """ approval_id: str subject: str approved_at: str status: str duplicate: bool = False @property def correlation(self) -> tuple[str, str, str]: return (self.approval_id, self.subject, self.approved_at) class ApprovalEngine(Protocol): def get_approval(self, approval_id: str) -> dict: ... def add_entry(self, approval_id: str) -> EntryResult: ... def assert_scopes_permissible(scopes: tuple[str, ...]) -> None: """Refuse ``approval:consume`` before a token is ever requested.""" if FORBIDDEN_SCOPE in scopes: raise ValueError( f"{FORBIDDEN_SCOPE} must never be requested: approval-engine refuses it " "for human principals and consumption belongs to the PEP causing the " "side effect (GH-DEC-2026-003)" ) def is_success(err: ApprovalEngineError) -> bool: """`409 duplicate_approver` is SUCCESS, not failure. A browser double-submit is routine and the first entry stands. Rendering it as an error is a lie to the approver. """ return err.status == 409 and err.reason == "duplicate_approver" class FakeApprovalEngine: """In-process stand-in with the engine's actual refusal semantics.""" def __init__(self, approvals: dict[str, dict] | None = None) -> None: self._approvals = approvals or {} self._entries: dict[str, set[str]] = {} self.available = True def get_approval(self, approval_id: str) -> dict: if not self.available: raise ApprovalEngineError(503, "store_unavailable") if approval_id not in self._approvals: raise ApprovalEngineError(404, "not_found") return dict(self._approvals[approval_id]) def add_entry(self, approval_id: str, subject: str = "approver") -> EntryResult: if not self.available: raise ApprovalEngineError(503, "store_unavailable") approval = self._approvals.get(approval_id) if approval is None: raise ApprovalEngineError(404, "not_found") if approval.get("status") in ("revoked", "superseded", "consumed", "expired"): raise ApprovalEngineError(409, "conflict") seen = self._entries.setdefault(approval_id, set()) duplicate = subject in seen seen.add(subject) if not duplicate and len(seen) >= approval.get("required_count", 1): approval["status"] = "approved" return EntryResult( approval_id=approval_id, subject=subject, approved_at="2026-09-10T15:00:00Z", status=approval.get("status", "requested"), duplicate=duplicate, )