Section 8
Security
Authorisation is enforced inside the retrieval query using PostgreSQL row-level security, not applied to results afterwards.
Tenant partitioning is structural, so cross-tenant retrieval is not merely unlikely. The application role is neither superuser nor exempt, and every table carrying a policy forces row-level security on its owner as well.
8.1 Red-team results
- Attacks attempted
- 246
- Withstood
- 246
- Succeeded
- 0
across 7 categories
100.0% · 4.95s
none in this suite
| category | attempted | withstood | result |
|---|---|---|---|
| Cross-tenant retrieval | 141 | 141 | all withstood |
| Prompt injection | 37 | 37 | all withstood |
| Role escalation | 23 | 23 | all withstood |
| Citation forgery | 17 | 17 | all withstood |
| Defence in depth | 15 | 15 | all withstood |
| Policy configuration | 9 | 9 | all withstood |
| Abstention bypass | 4 | 4 | all withstood |
Proof the suite can fail
A suite that always passes is indistinguishable from one that tests nothing. Each silent-bypass path the policy was written to close is deliberately reintroduced, the suite re-run, and the policy restored.
- policy always true
- detected — the suite failed, as it must
- row level security disabled
- detected — the suite failed, as it must
- force disabled (owner bypass path)
- detected — the suite failed, as it must
The third was NOT detected on the first run. FORCE ROW LEVEL SECURITY only changes what the table owner sees, and the suite connects as the application role — correctly. Nine configuration invariants were added to close it, rather than having a test connect as the owner.
What this number does not mean
- A 100% pass rate means every attack in this suite was withstood, not that the system is secure. It bounds what was tried.
- Cross-tenant coverage is exhaustive over the current matrix: every role against every tenant. Adding a tenant adds cases automatically.
- Citation and abstention cases exercise the verification logic directly rather than a live model, so they test the checker rather than any particular model's behaviour.
- The suite runs against a populated database. In CI it runs against a small synthetic corpus, because the properties tested belong to the policy and not to the data volume.
Produced by run.py · commit 74cbff4 · 2026-08-26 · 3 roles x 47 tenants on corpus edgar-cuad-rfc-v1
8.2 What will be reported
The pass rate as measured, including failures. A security section showing a perfect score with no failures shown is the least believable thing this site could publish, so failures are reported rather than quietly fixed before publication.
The suite is verified by deliberately introducing a row-level security bug and confirming it fails. A suite that has never failed has not been shown to work.