Skip to content

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.