Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func MiddlewareWithBareHosts ¶
MiddlewareWithBareHosts is TenantMiddleware for a server that KNOWS its own hostnames (the fleet runtimes: an app's manifest `domains`). A request whose Host is EXACTLY one of bare (no tenant label in front) passes through with no TenantCtx — like a bare "localhost" — instead of mis-reading the domain's first label as a tenant. Before this, `GET erp.example.com/admin` recorded a phantom tenant "erp" in observability (the S1 finding); the domain's OWN first label is not a tenant.
With bare empty this is byte-identical to the historical middleware — the single-engine chain (which has no domain knowledge) is unchanged, and the fleet chain adds one map lookup on a pre-parsed string (~ns, pre-auth).
func RequireForTenantAPI ¶ added in v0.1.3
RequireForTenantAPI answers the tenant-scoped surfaces (/api/*, /graphql, /auth/*) with a NAMED 400 when the request carries no tenant — field report T3: `curl localhost:8080/api/x` used to reach the generated handlers, panic in MustFromCtx and surface as a masked `500 {"error":"internal error"}`, blaming the server for a malformed request (ADR-024: a bad input is a named 400, never a 500). Tenant-agnostic surfaces (/admin, /editor, /docs, probes, the fleet console) keep passing through untouched, which is why the tenant middleware itself must NOT reject a dotless host.
Install it AFTER MiddlewareWithBareHosts in the chain.
func TenantMiddleware ¶
TenantMiddleware extracts the tenant from the request's Host subdomain.
- "acme.localhost:8080" → injects TenantCtx{ID:"acme", PGSchema:"tenant_acme"}
- "ACME.localhost:8080" → the same tenant (the host is case-insensitive)
- "localhost:8080" → passes through with no TenantCtx (health / control plane)
- anything invalid → 400 naming the offending label and the rule
Types ¶
type SchemaCache ¶
type SchemaCache struct {
// contains filtered or unexported fields
}
SchemaCache holds the compiled API schemas for active tenants in memory. Updated by the migration worker after a successful migration; invalidated by pg_notify events so the data plane reloads on the next request.
func NewSchemaCache ¶
func NewSchemaCache() *SchemaCache
func (*SchemaCache) Invalidate ¶
func (c *SchemaCache) Invalidate(tenantID string)
Invalidate removes a tenant's cached schema so the next request reloads it from DB.
type TenantCtx ¶
TenantCtx holds the resolved tenant identity for a request.
func MustFromCtx ¶
MustFromCtx returns the TenantCtx from ctx, panicking if none was set. Use in handlers that are guaranteed to run after TenantMiddleware.