Retain verified tenant provenance and reconcile production blockers

Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a1046e-fdbf-7b93-a267-5f72b9b24526
This commit is contained in:
tegwick 2026-10-04 11:26:32 +02:00
parent 931e0b3249
commit c9ad5c2dd7
12 changed files with 274 additions and 25 deletions

View file

@ -28,6 +28,7 @@ class Identity:
scopes: frozenset[str]
assurance: dict[str, Any]
evidence_ref: str
tenant_source: str | None = None
def require(self, scope: str) -> "Identity":
if scope not in self.scopes:
@ -76,6 +77,12 @@ def identity_from_claims(claims: Mapping[str, Any], token: str) -> Identity:
raise Unauthenticated("token identity claims are invalid")
if not tenant or not isinstance(assurance, dict):
raise Unauthenticated("token tenant or assurance claim is invalid")
tenant_source = claims.get("tenant_source")
if "tenant_source" in claims and (
not isinstance(tenant_source, str)
or tenant_source not in {"directory", "registration", "default"}
):
raise Unauthenticated("token tenant_source claim is invalid")
audiences = _texts(claims.get("aud"), "aud")
roles = frozenset(_texts(claims.get("roles"), "roles", allow_empty=True))
scopes = frozenset(_texts(claims.get("scope", claims.get("scp")), "scope"))
@ -90,6 +97,7 @@ def identity_from_claims(claims: Mapping[str, Any], token: str) -> Identity:
scopes=scopes,
assurance=dict(assurance),
evidence_ref=f"jwt-sha256:{fingerprint}",
tenant_source=tenant_source,
)