Story: Per-request tenant context
Table of Contents
This page documents a story in Sprint 11. It captures the goal, current status, acceptance criteria, and the tasks that compose it.
Goal
Close the cross-tenant data-leakage risk: message handlers must build
their database context from the session's tenant_id per request,
not at construction time.
Status
| Field | Value |
|---|---|
| State | DONE |
| Parent sprint | Sprint 11 |
| Now | Completed 2026-02-06. |
| Waiting on | None. |
| Next | None. |
| Last touched | 2026-02-06 |
Acceptance
- Tenant lookup functions take
const context&. tenant_aware_handlerbase class handles per-request context creation.- Type-safe
tenant_idwrapper. - System tenant identifier changed from nil UUID to max UUID.
- All handlers refactored; ThreadSanitizer green.
Tasks
| Task | State | Start | End | Description |
|---|---|---|---|---|
| Refactor tenant lookup functions to accept const context | DONE | 2026-05-19 | 2026-02-05 | resolve_tenant_id, lookup_by_code, lookup_by_hostname take const context& (they're read-only); eliminates unnecessary mutable copies. |
| Refactor message handlers for per-request tenant context | DONE | 2026-05-19 | 2026-02-06 | tenant_aware_handler base class; per-request database contexts from session.tenant_id; type-safe utility::uuid::tenant_id wrapper; system tenant changes from nil UUID to max UUID (RFC 9562); fixes cross-tenant data leakage. |
Decisions
- Per-request context, not construction-time
- real security bug — the cached construction-time context could leak data from one tenant to another.
- System tenant = max UUID, not nil UUID
- nil UUID is the default-construct value; using it as the system tenant invited accidental confusion. RFC 9562's max UUID is the right pick.
- Strong-typed tenant_id wrapper
- refuses to construct from a nil UUID; catches a category of bugs at the type system.
Out of scope
- Pool-per-tenant — pool is shared; tenant context lives on the connection.
See also
- Tenancy foundation — supplies the session.tenant_id this story consumes.