The same incident identifier can belong to two customers
Our incident-response assistant serves two organizations that both have an incident named INC-1. One organization investigates a failed payment API; the other investigates an internal directory service. If a retrieval cache uses only the incident identifier, a correct-looking answer can contain another customer's evidence. The defect is in the system boundary, even when the language model faithfully summarizes the returned text.
This original design binds every operation to a principal, an authorized tenant, and an operation scope. Tenant selection is a policy decision based on verified identity. A user message saying 'switch to the other organization' cannot modify that binding. The model adapter receives already scoped evidence and returns a proposal; it cannot grant itself membership or invent access rights.
Architecture and request sequence
Read the architecture as text
- Verified identity: Server constructs principal
- Tenant policy gateway: Membership and operation scope
- Scoped cache: Tenant and incident key
- Evidence repository: Partitioned records and limits
- Model adapter seam: Receives permitted evidence only
- Verified identity → Tenant policy gateway: Principal
- Tenant policy gateway → Scoped cache: Authorized lookup
- Scoped cache → Evidence repository: Scoped miss
- Evidence repository → Scoped cache: Evidence
- Scoped cache → Model adapter seam: Permitted context
Read the sequence as text
- Caller → Gateway: Request incident
- Gateway → Policy: Check tenant and scope
- Policy → Gateway: Allow or deny
- Gateway → Store: Scoped evidence lookup
- Store → Gateway: Tenant evidence
- Gateway → Caller: Authorized response
Choose the isolation unit for each resource
Evidence rows use a tenant-and-incident key. Cache entries use the same scope, and production cache designs also need policy and data revisions when those affect results. Object storage paths, search filters, background jobs, and tool credentials need equivalent ownership. A task queue that preserves incident identifier but drops tenant identity can undo an otherwise careful request handler.
The proposed service records the tenant context in an authenticated job envelope generated by the server. A worker revalidates that context before fetching evidence. Logging includes a safe tenant correlation key rather than full customer data. Export and support tooling receive the same review as the main API; a debugging endpoint that bypasses the normal repository methods can become the easiest path across the boundary.
Database policy can strengthen but not replace the application
PostgreSQL row-security policies can restrict rows by role and command; enabling row security without a policy produces default denial. Owners normally bypass these policies, and superusers or roles with BYPASSRLS do so as well. Source: row security policies. These documented exceptions matter when selecting the application's database identity.
For a proposed database deployment, test the exact role used by the running service and include both reads and writes. Do not validate the policy as a privileged administrator and assume the result describes ordinary access. The Python example uses dictionaries, not PostgreSQL, so it demonstrates explicit application checks only. A database integration would require migrations, connection-context handling, and tests for pooled connections reusing stale tenant settings.
Isolate capacity as well as data
A tenant can harm another tenant without reading its records. A burst of expensive incident investigations can exhaust shared model concurrency, queue slots, or storage connections. For this original capacity assumption, reserve a bounded per-tenant admission budget alongside a global cap. The local exercise uses a small record limit to demonstrate independent accounting; it does not simulate model throughput or scheduler fairness.
Decide which resource is actually scarce. Requests per minute can be a poor proxy when one investigation contains a hundred tool calls and another contains one. Track estimated work and actual resource use while keeping the admission policy explainable. A rejected tenant should receive a retry or escalation path rather than a misleading claim that the incident was analyzed successfully.
Make the isolation claim testable
Acceptance should include same identifiers in different tenants, unauthorized cache hits, membership changes, cross-tenant write attempts, and noisy-neighbor pressure. Test background processing and exports as well as interactive requests. A single happy-path test with two different incident names cannot expose a cache collision because the identifiers never compete.
The architecture is an original reference for an incident assistant, not a certification of a multi-tenant platform. Stronger isolation can require separate databases, encryption keys, worker pools, or deployments depending on the threat model and customer contract. Those choices trade operational cost for a smaller shared boundary. Document the selected level and residual shared resources so reviewers know exactly what 'isolated' means in this service.