Commit 607e35a
committed
feat(plugin-security): extract tenant isolation as Layer 0 (ADR-0095 D1)
Tenant isolation is now Layer 0 — an independent, always-first, AND-composed
filter (`tenant-layer.ts`), not a wildcard `tenant_isolation` RLS policy
OR-merged with business RLS. Effective filter = Layer0(tenant) AND Layer1(RLS);
the two share no compiler, merge step, or bypass bit (closes W1 by construction,
W2 structurally). The superuser bypass now exempts the tenant wall only as a
Layer 0 rule (platform-admin posture + object posture permits), never via a
business-RLS short-circuit.
Layer 0 decides "tenant object?" directly from the field set + tenancy posture
(NOT via extractTargetField's `=`-only shape match), so a `tenancy.enabled:false`
global object correctly contributes nothing. `tenant_isolation` retired from the
seeded organization_admin / member_default / viewer_readonly sets; the `_self` /
`_org` identity carve-outs and owner_only_writes/deletes are kept. Driver-level
`applyTenantScope` untouched.
Four accepted behavior deltas (multi-org only; single mode inert), all W1-class
toward stronger isolation — see ADR-0095 D1 behavior contract:
(a) permissive business policy no longer OR-widens tenant scope (cross-org
read leak closed);
(b) member by-id writes narrow to owner-only (owner_only_writes no longer
OR-diluted) — release-notes BREAKING;
(c) members see `tenancy.enabled:false` global catalogs (no phantom org filter);
(e) no-active-org writes on a tenant object fail closed.
computeWriteCheckFilter gains no tenant post-image check by design (tenant_isolation
had only a `using` clause; insert placement is the enterprise auto-stamp's job) —
avoids an insert-breaking regression.
Also expands ADR-0095 D1 to enumerate the four deltas as-built; updates the
matrix gate to post-extraction expectations; updates the dogfood conformance
matrix's multi-tenant enforcement site; retitles/adjusts existing tests that
hard-coded the retired policy.
The extractTargetField `==` blind spot this exposes (still affecting Layer-1
business policies) is tracked in #2936.
Verified: plugin-security 355 tests + matrix gate 6 cells green; tsc + build
clean; dogfood authz-conformance + single-tenant RLS proofs green (multi-org
dogfood requires the enterprise package and is skipped in open-core).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019QRUvVfpvSycAHMMF2xTxs1 parent cb2abc5 commit 607e35a
9 files changed
Lines changed: 405 additions & 188 deletions
File tree
- .changeset
- docs/adr
- packages
- dogfood/test
- plugins/plugin-security/src
- objects
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
Lines changed: 49 additions & 12 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
136 | 136 | | |
137 | 137 | | |
138 | 138 | | |
139 | | - | |
140 | | - | |
141 | | - | |
142 | | - | |
143 | | - | |
144 | | - | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
145 | 176 | | |
146 | 177 | | |
147 | 178 | | |
| |||
224 | 255 | | |
225 | 256 | | |
226 | 257 | | |
227 | | - | |
228 | | - | |
229 | | - | |
230 | | - | |
231 | | - | |
232 | | - | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
233 | 270 | | |
234 | 271 | | |
235 | 272 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
41 | 41 | | |
42 | 42 | | |
43 | 43 | | |
44 | | - | |
| 44 | + | |
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
| |||
0 commit comments