research: verify pgrls directly; add maturity caveat before recommending adoption

Checked the repo rather than trusting the search snippet. Confirms the
capability claims (MIT, 67 rules, 54 of them security, Z3 isolation proofs,
SAFE/BREAKING policy-diff for CI gating, pytest plugin, PG 15-17) and corrects
the auto-fixable count from 20 to 19.

It is also 26 stars and self-described beta. That does not change the
recommendation to adopt the approach, but it does change the recommendation to
adopt the tool: it is a supply-chain decision, not a free win. pgTAP is
long-established and carries no such caveat. Saying so now is cheaper than
having a reviewer discover it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
codex 2026-08-17 13:07:41 +02:00
parent d710888dc6
commit 7c69153da9
2 changed files with 20 additions and 5 deletions

View file

@ -55,7 +55,7 @@ Ranked by how badly they mislead.
| # | Finding | Effect |
|---|---|---|
| O1 | **pgTAP + pgrls** (67 RLS lint rules, semantic policy-diff for CI gating, pytest isolation plugin) exist off the shelf. `rapp-postgres` already runs a 15-probe harness of the same shape. | The E3 half of open question §18.3 is far cheaper than assumed. Splits the question into a tractable mechanical half and a human half. |
| O1 | **pgTAP + pgrls** exist off the shelf; `rapp-postgres` already runs a 15-probe harness of the same shape. pgrls **verified directly** 2026-08-17: MIT, 67 rules (54 security, incl. BYPASSRLS / LEAKPROOF / `SECURITY DEFINER` / cross-tenant leaks), 19 auto-fixable, Z3 isolation proofs, SAFE/BREAKING policy-diff for CI gating, pytest plugin, PG 1517. **But it is a 26-star beta project** — adopt the approach with confidence, treat the dependency as a supply-chain decision. pgTAP is long-established and carries no such caveat. | The E3 half of open question §18.3 is far cheaper than assumed. Splits the question into a tractable mechanical half and a human half. |
| O2 | **OWASP Multi-Tenant Security Cheat Sheet** is the closest external baseline to our framework and is referenced nowhere in the estate. | Adopt as the named external baseline in ADR §15. |
| O3 | **OpenID AuthZEN Authorization API 1.0** reached Final Specification January 2026; Keycloak shipped experimental support May 2026. Demonstrated PDP interoperability across 5+ engines. | `flex-auth`'s bespoke `CheckRequest` is pre-standard. Propose an `A4` rung for standard-interface PDP delegation. |
| O4 | **Token versioning** as a middle rung between cached claim and live re-query. | Cheap global invalidation without a hot-path lookup. |

View file

@ -143,10 +143,25 @@ expected.
cross-tenant isolation tests are the only reliable guard"
([Blair Jordan — testing RLS policies with pgTAP](https://blair-devmode.medium.com/testing-row-level-security-rls-policies-in-postgresql-with-pgtap-a-supabase-example-b435c1852602),
[MakerKit — database testing with pgTAP](https://makerkit.dev/docs/next-supabase-turbo/development/database-tests)).
- **pgrls** is a purpose-built static analyzer: 67 lint rules for tenant and
per-user row-scoping bugs, performance traps and hygiene, 20 auto-fixable, a
semantic policy-diff command for CI gating, and a pytest plugin for isolation
tests ([pgrls on GitHub](https://github.com/pgrls/pgrls)).
- **pgrls** is a purpose-built static analyzer, **verified directly 2026-08-17**
rather than taken from a search snippet
([pgrls on GitHub](https://github.com/pgrls/pgrls)). Confirmed: MIT licence;
67 rules across SEC (54), PERF (5), HYG (4) and VIEW (4); 19 auto-fixable;
Z3 SMT-solver verification of isolation properties; a policy-diff command
classifying changes SAFE / BREAKING / REQUIRES_REVIEW / DANGEROUS; a
`pgrls.testing` pytest plugin with role-switching and per-test transactions;
SARIF, JUnit XML and GitHub-annotation output; tested against PostgreSQL
1517. Its SEC rules cover exactly the traps in §3 — BYPASSRLS, LEAKPROOF,
`SECURITY DEFINER`, cross-tenant leaks.
**Maturity caveat, stated because this digest recommends adoption.** It is
26 stars, 2 forks, 527 commits, self-described "Beta — actively maintained".
The engineering is serious (Z3 proofs, a precision corpus) but this is a
small project, not an established dependency. Adopt the *approach* with
confidence; treat the *tool* as a supply-chain decision requiring the estate's
normal SBOM and pinning discipline, and be prepared to reimplement its
handful of load-bearing rules if it goes unmaintained. pgTAP, by contrast, is
long-established and carries no such caveat.
The named common failures match ours exactly: "a forgotten role, a pool reusing
connections with the wrong tenant context, or an admin path bypassing RLS