BE-M0-21 · Row-level security for every table, from one spec
ID BE-M0-21 · Level L0 · Pack Pack C · Row-level security · Run order row 20 · Issue #12
The policies for all 70 tables, written by tools/db/gen_rls.py from one spec, pass their tests with every earlier test (260 in 11 files). The rules they prove are marked built, and pack C is merged into main.
Before
Section titled “Before”- Timeline row 19 (pack B) is Done: pack B is merged into main.
- be-pack-c.zip, sent in the BE chat on 2026-10-07, is in ~/Downloads.
- You are in ~/opleet-v2/opleet,
git status --shortprints nothing, and the stack is running.
1 · Check the zip, unzip it next to the repository, and check every file in it
Section titled “1 · Check the zip, unzip it next to the repository, and check every file in it”shasum -a 256 ~/Downloads/be-pack-c.zipunzip -q -o ~/Downloads/be-pack-c.zip -d ~/opleet-v2/packs(cd ~/opleet-v2/packs/be-pack-c && shasum -a 256 -c SHA256SUMS)2 · A branch for pack C, with its files
Section titled “2 · A branch for pack C, with its files”cd ~/opleet-v2/opleetgit switch main && git pullgit switch -c supabase/rlscp -R ~/opleet-v2/packs/be-pack-c/BE-M0-21/. .git status --short3 · Run the generator, and confirm it writes the file the pack holds
Section titled “3 · Run the generator, and confirm it writes the file the pack holds”python3 tools/db/gen_rls.pycmp supabase/migrations/20261006001100_rls.sql ~/opleet-v2/packs/be-pack-c/BE-M0-21/supabase/migrations/20261006001100_rls.sql && echo "same as the pack"4 · Rebuild the local database from every migration, then run every test
Section titled “4 · Rebuild the local database from every migration, then run every test”pnpm supabase db resetpnpm supabase test db5 · Mark the rules this pack proves as built, then run the rule check
Section titled “5 · Mark the rules this pack proves as built, then run the rule check”node ~/opleet-v2/packs/be-pack-c/mark-built.mjs ~/opleet-v2/packs/be-pack-c/BUILT-IDS.txtpnpm docs:rulesgit status --short apps/docs6 · Commit
Section titled “6 · Commit”git add supabase tools/db apps/docsgit commit -m "feat(supabase): row-level security for every table, from one spec"7 · Push, open the pull request and wait for its checks
Section titled “7 · Push, open the pull request and wait for its checks”git push -u origin supabase/rlsgh pr create --title "feat(supabase): row-level security for every table" --body "BE pack C (BE-M0-21), timeline row 20. Closes #12."gh pr checks --watch8 · Log the run on #12, then merge
Section titled “8 · Log the run on #12, then merge”Comment on #12 with the date, what you ran and the output of blocks 3 to 5. Then:
gh pr merge --squash --delete-branchgit switch maingit pullExpect
Section titled “Expect”- Block 1: be-pack-c.zip's SHA-256 as written under Pack C, then 8 lines ending in “: OK”.
- Block 2: “Switched to a new branch 'supabase/rls'”, then
?? supabase/migrations/20261006001000_access_helpers.sql,?? supabase/migrations/20261006001100_rls.sql,?? supabase/tests/database/21_rls.test.sqland?? tools/db/gen_rls.py. - Block 3:
supabase/migrations/20261006001100_rls.sql: 70 tables, 184 policies, then “same as the pack”. - Block 4: db reset applies 20261006001100_rls.sql last and ends with “Finished supabase db reset”; test db ends with “All tests successful.”, “Files=11, Tests=260” and “Result: PASS”.
- Block 5: “Marked built: 65. Already built: 0.”, then the rule check's “Rules: …” line with no line under it, then one
Mline for each rule page that changed. - Block 6: Lefthook skips Biome (no files it checks) and shows ✔️ commitlint, then the commit line.
- Block 7: the pull request's URL; checks and pr-title pass.
- Block 8: “✓ Squashed and merged pull request #…”, and main moves to that commit.
git log --oneline -1docker exec supabase_db_opleet psql -U postgres -At -c "select count(*) from pg_policies where schemaname = 'public'"pnpm supabase test dbOn main: “feat(supabase): row-level security for every table (#…)”, then 184, then “Files=11, Tests=260” and “Result: PASS”.
If it fails
Section titled “If it fails”- Block 1's hash differs, or a line says FAILED: the download is incomplete or isn't this zip. Download it again; if it still differs, stop and tell the BE session.
- Block 3 prints “differ” instead of “same as the pack”: the generator and the pack disagree. Don't commit; paste the output and the output of
python3 --version. - db reset stops at a migration: the error names the file and the line. Paste it into the BE chat; don't edit the file.
- test db prints “not ok”: paste every “not ok” line and the lines under it. Don't commit.
- Block 5 prints “Not found in apps/docs” or “Retired”, or docs:rules prints a line under its “Rules:” line: a rule ID changed in apps/docs after this pack was built. Paste the output; BE rebuilds the pack.
- A check fails on the pull request: paste the failing job's log.
Before merging: gh pr close --delete-branch, then git switch main and pnpm supabase db reset. After merging: revert it with a new pull request.
Not run yet. Log each run as a comment on #12.