Problem
The usual “chat with your documents” integration works in a demo and starts failing at scale: retrieval misses the relevant chunk, answers drift into the wrong document, latency climbs. And nothing stops one customer’s query from reaching another’s data if a filter is ever forgotten in a code path someone adds later.
System
Every query arrives with a bearer token that resolves to a tenant, and the tenant filter is part of the retrieval query itself, not a parameter a caller could omit. Retrieval returns chunks with document, page and section metadata; generation is constrained to cite them; a found: false path returns “not in your documents” when nothing scores well enough. Responses carry per-stage timings and a cache-hit flag so performance is visible per request, not guessed at in aggregate.
Worth knowing
The tenant boundary being in SQL is the whole design. An application-layer filter is one refactor away from being missing; a database-level scope means a bug can produce a wrong answer but not a leak. That’s the property a SaaS buyer actually needs before they’ll put customer documents into it.