symfonic.platform.ports¶
ports ¶
Platform port-registry rows 16 and 3: the resolver and the audit seam.
There is deliberately no PlatformServices object here. Interface
segregation, and the plan's forbidden pattern "service-locator lookups where a
narrow constructor-injected protocol is sufficient": a registry that handed out
services on demand would pass every layering check and rebuild the monolith one
indirection down.
AuditSink ¶
Bases: Protocol
Registry row 3 — narrow, append-only, and never constructed in a handler.
ScopeResolver ¶
Bases: Protocol
Registry row 16 — credentials to an authenticated principal.
The single derivation point (SEC-AUTHZ-1). Returns a whole principal or
raises; there is no third outcome, because a resolver that could return
None would make "no principal" a value a handler might forget to check.
TenantAuthVerifier ¶
Bases: Protocol
The deployment's own answer to "is this caller allowed in this tenant?".
Returns a mapping of principal facts (principal_id, is_admin) or
None for a bare allow, and raises to deny. The admin bit comes from
here and nowhere else (SCOPE-7): the shipped X-Admin-Override header
convention is trusted only when a verifier has already authenticated the
caller, which makes it a verifier-side deployment convention — the one
place it can actually be reasoned about — rather than a transport rule.