Summary
JS already ships subdomain tenant routing; Python adopters hand-roll it (salesagent's domain_routing.py is ~250 LOC). Ship a Starlette middleware that resolves Host header → tenant, populates a contextvar, hands down to AccountStore/TaskStore/etc.
Design
Surface
SubdomainTenantRouter Protocol with resolve(host: str) -> Tenant | None method
- Starlette middleware that:
- Reads
Host header
- Calls the resolver
- Populates a contextvar with the resolved tenant
- 404s on unknown hosts
- Reference implementation backed by a static dict mapping (development/test)
- Production adopters back the Protocol with their tenant table
Composition
Tenant-scoped contextvar threads down to AccountStore, TaskStore, BuyerAgentRegistry, etc., letting all downstream stores filter by tenant without explicit plumbing.
Cross-references
🤖 Generated with Claude Code
Summary
JS already ships subdomain tenant routing; Python adopters hand-roll it (salesagent's
domain_routing.pyis ~250 LOC). Ship a Starlette middleware that resolvesHostheader → tenant, populates a contextvar, hands down toAccountStore/TaskStore/etc.Design
Surface
SubdomainTenantRouterProtocol withresolve(host: str) -> Tenant | NonemethodHostheaderComposition
Tenant-scoped contextvar threads down to
AccountStore,TaskStore,BuyerAgentRegistry, etc., letting all downstream stores filter by tenant without explicit plumbing.Cross-references
🤖 Generated with Claude Code