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_handler base class handles per-request context creation.
  • Type-safe tenant_id wrapper.
  • 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

Emacs 29.1 (Org mode 9.6.6)