Skip to content

feat(dogfood): owner-isolated RLS fixture — hard, revert-provable #1994 gate - #2037

Merged
os-zhuang merged 1 commit into
mainfrom
feat/dogfood-rls-fixture
Jun 18, 2026
Merged

feat(dogfood): owner-isolated RLS fixture — hard, revert-provable #1994 gate#2037
os-zhuang merged 1 commit into
mainfrom
feat/dogfood-rls-fixture

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Why

The cross-owner RLS proof runner (src/rls.ts, from #2032) was unit-proven but had nothing live to exercise it. The harness boots single-tenant, so the org tenant_isolation policy is stripped and a fresh member falls back to member_default (broad read) — every object reports member-visible, so the #1994 invariant ("a user who cannot READ a record must not be able to WRITE it") never actually fired against an app.

Note: #2032's branch was removed before this work, so this PR also carries the #2032 runner commit (c3492faee) it builds on.

What

Two faithful ways to create real cross-owner isolation, both now live:

1. Owner-scoped fixture — the hard gate

test/rls-fixture.dogfood.test.ts + test/fixtures/rls-owner-fixture.ts: a one-object app (rls_note) whose member fallback permission set carries RLS.ownerPolicy('rls_note','created_by'). The predicate keys on created_by/current_user.id (not organization_id), so it survives single-tenant stripping — a fresh member genuinely can't read the admin's note.

2. Org-scoped / multi-tenant

test/rls-multitenant.dogfood.test.ts: bootDogfoodStack now takes { multiTenant: true }, registering plugin-org-scopingbeforeSecurityPlugin so organization_id policies apply. CRM flips from every object member-visible (single-tenant) to 4 consistent / 0 holes / 0 member-visible — confirming the member-visible result was single-tenant RLS-stripping, not a broad-read default (the model real apps like hotcrm rely on). hotcrm isn't in this repo, so this validates against the in-repo CRM example and documents the path.

Harness

BootOptions gains security? (SecurityPlugin override for the fixture fallback) and multiTenant?. README documents both gates + the revert proof; the stale "next step" note in the single-tenant smoke now points at the two new tests.

Verification

🤖 Generated with Claude Code

@vercel

vercelBot commented Jun 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJun 18, 2026 12:53pm

Request Review

… gate
The cross-owner RLS proof runner (src/rls.ts, #2032) was unit-proven but had
nothing live to exercise it: the harness boots single-tenant, so the org
tenant_isolation policy is stripped and a fresh member falls back to
member_default (broad read) — every object reports `member-visible`, so the
#1994 by-id-write invariant ("can't read ⇒ can't write") never fired live.
Two faithful ways to create real isolation, both now live:
1. Owner-scoped fixture (test/rls-fixture.dogfood.test.ts + fixtures/):
one object `rls_note` whose member fallback permission set carries
RLS.ownerPolicy('rls_note','created_by'). Keyed on created_by/current_user.id
(not organization_id), so it survives single-tenant stripping — a fresh
member genuinely can't read the admin's note.
- GREEN: owner policy on `all` ops → rls-consistent (pre-image check denies
the by-id write).
- AUTOMATED RED: owner policy on `select` only → rls-hole (read scoped, no
write policy applies, by-id write lands) — #1994 hole class every CI run.
- MANUAL REVERT PROOF (README): disabling the pre-image check flips the green
fixture to "GET 404 yet MUTATED it by id (PATCH 200)". Verified, restored.
2. Multi-tenant org-scoped (test/rls-multitenant.dogfood.test.ts):
bootDogfoodStack gains `{ multiTenant: true }` → registers plugin-org-scoping
before SecurityPlugin so organization_id policies APPLY. CRM flips from
every-object-member-visible (single-tenant) to 4 consistent / 0 holes /
0 member-visible — confirming member-visible was single-tenant RLS-stripping,
not a broad-read default (the model real apps like hotcrm rely on).
harness: BootOptions gains `security?` (SecurityPlugin override for the fixture
fallback) and `multiTenant?`. README documents both paths + the revert proof.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@os-zhuang
os-zhuangforce-pushed the feat/dogfood-rls-fixture branch from 1e1413a to a2316e6CompareJune 18, 2026 12:49
@github-actionsgithub-actionsBot added size/m documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file tests labels Jun 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

No hand-written docs reference the 1 changed package(s). ✅

@os-zhuang
os-zhuang merged commit a2316e6 into mainJun 18, 2026
15 of 16 checks passed
@os-zhuang
os-zhuang deleted the feat/dogfood-rls-fixture branch June 18, 2026 12:50
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependenciesPull requests that update a dependency filedocumentationImprovements or additions to documentationsize/mtests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@os-zhuang