fix(audit): retain authenticated consume identity and exact binding

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a140c4-354a-7823-8f0d-8f717397f786
This commit is contained in:
tegwick 2026-10-16 07:51:39 +02:00
parent 9491d1d3a7
commit 477c683991
6 changed files with 221 additions and 0 deletions

View file

@ -176,6 +176,7 @@ class App:
approval_id,
data.get("request_digest"),
decision_id=data.get("decision_id"),
consumer=identity,
)
if "check" in path or path.endswith("/authorize"):
return 404, {"error": "not_found", "message": "no such surface"}

View file

@ -18,6 +18,7 @@ from pathlib import Path
from typing import Any, Callable
from uuid import uuid4
from .auth import Identity
from .binding import binding_digest, canonical_binding, require_digest
from .errors import (
Conflict,
@ -750,6 +751,7 @@ class Engine:
request_digest: str | None,
*,
decision_id: str | None = None,
consumer: Identity | None = None,
) -> dict[str, Any]:
"""Atomically spend an approval for one decision-bound request.
@ -819,6 +821,19 @@ class Engine:
actor=row["actor"],
extra={
"binding_digest": row["binding_digest"],
"binding": json.loads(row["binding_json"]),
"pdp_digest": row["pdp_digest"],
"pdp_path": bool(row["pdp_path"]),
# Only the HTTP boundary supplies an authenticated identity.
# Internal/legacy calls explicitly leave provenance unknown.
"consumer": ({
"subject_id": consumer.subject,
"issuer": consumer.issuer,
"principal_type": consumer.principal_type,
"tenant": consumer.tenant,
"tenant_source": consumer.tenant_source,
"evidence_ref": consumer.evidence_ref,
} if consumer is not None else None),
"request_digest": digest,
**({"decision_id": decision_id} if decision_id else {}),
"threshold": self._threshold_evidence(