Multi-tenant retrieval must enforce isolation before similarity ranking. Application predicates are useful but easy to omit; PostgreSQL row-level security (RLS) adds database-enforced policies tied to trusted session or transaction identity. Use a non-owner runtime role, force RLS where appropriate, set identity transaction-locally, and test every read/write, cache, reranker, citation, export, and maintenance path.
The application opens a transaction and sets app.tenant_id from authenticated server context:
Use a runtime role that neither owns the table nor has BYPASSRLS. Missing settings should fail closed; handle casts deliberately. Harden function search paths and privileges.
Choose from risk, regulation, noisy-neighbor behavior, scale, and operational maturity.
Run tests as the exact runtime role, not an owner. Attempt SELECT, vector search, lexical search, insert, update, delete, foreign-key references, prepared statements, COPY, functions, views, caches, and citation resolution across tenants. Inspect policies with \d+ and catalog queries.
Audit this PostgreSQL multi-tenant design [DDL, roles, policies, app transaction]. Find owner/BYPASSRLS paths, missing WITH CHECK, null setting behavior, pool leakage, function/view risks, background-job scope, cache boundaries, and denial tests.
Verification contract: Execute the adversarial suite using production-equivalent roles; zero unauthorized rows is a release gate.