Repository navigation
Database: document tags, sections and memory cards must belong to your own document - #3558
Conversation
Adds tests/sql/two-user-privacy.sql, which signs in as two synthetic doctors and proves browser roles hold no access to any public table, the callable function allowlist, administrator functions refusing a doctor, and every browser-facing owner policy isolating the two doctors. Adds npm run test:sql (bare-image replay) and runs tests/sql in the Migration replay CI job. Repairs enrichment-repair.sql fixtures for the newer lease-tuple checks. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhogQUCHgdtFBHFtpjnd1n
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhogQUCHgdtFBHFtpjnd1n
…he coverage guard Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhogQUCHgdtFBHFtpjnd1n
- Prevent administrator refusal helper from swallowing privacy leaks - Probe cross-owner inserts explicitly - Use valid storage columns for update probes
…e owner_rule rows Qodo's insert probe only touched documents and storage objects, which have no insert policy, so it could not catch a permissive one. Clone one of the actor's own rows, point it at the other doctor and require a row-level security refusal on every covered table. Also gives every owner_rule row the new update_col value, which Qodo's commit left mismatched (VALUES lists must all be the same length). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhogQUCHgdtFBHFtpjnd1n
A new overload reusing an allowed name is now caught. Proven by planting is_visible_document_page(integer) granted to authenticated: the test fails. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhogQUCHgdtFBHFtpjnd1n
…st6n' into claude/two-user-privacy-tests-ahst6n
The insert probe now also keeps the owner column as yours and moves only the parent document. Three owner policies (document_labels, document_sections, document_memory_cards) check owner_id but not the parent document's owner. Browser roles have no grant on these tables and the server routes check document ownership first, so this is unreachable today. The test records the three tables as a known gap and fails if the list stops matching in either direction. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhogQUCHgdtFBHFtpjnd1n
A permissive insert policy scoped to one bucket is now caught; proven by planting one on clinical-images only. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhogQUCHgdtFBHFtpjnd1n
The two-user privacy test found that document_labels (manual insert and update), document_sections and document_memory_cards checked the row's owner_id but not the parent document's owner. Only WITH CHECK changes, so reads and deletes are unchanged, and the service role bypasses RLS, so app behaviour is unchanged. The test's known-gap list is now empty. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhogQUCHgdtFBHFtpjnd1n
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
🏁 CodeAnt Quality Gate ResultsCommit: ✅ Overall Status: PASSEDQuality Gate Details
|
There was a problem hiding this comment.
BigSimmo has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
🤖 CodeAnt AI — Review Status
|
Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
PR Summary by QodoRequire document ownership for child-row writes
AI Description
Diagram
High-Level Assessment
Files changed (12)
|
|
Claude encountered an error after 2s —— View job I'll analyze this and get back to you. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a7d1fc87aa
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
… row per table A direct psql -f run without -1 now rolls the roster fixtures back too. distinct on uses a typed constant, so non-storage tables probe one row. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KhogQUCHgdtFBHFtpjnd1n
…ent-child-policy-owner-ahst6n
Code Review by Qodo
No findings for this group No findings for this group No findings for this group Resolved findings 1.
|
…er-ahst6n' into claude/document-child-policy-owner-ahst6n
CodeAnt Nitpicks2 code suggestions1.
|
CodeAnt PR Risk: Low Risk
Assessed commit: |
|
Code review by qodo was updated up to the latest commit 683e94e |
…-policy-owner-ahst6n # Conflicts: # tests/sql/two-user-privacy.sql
The merge-base changed after approval.
Code Review ✅ Approved🔴 High risk · Tightening RLS checks for child rows changes authorization; incorrect owner/document matching could reject legitimate tag, section, or memory-card writes. Adds parent-document ownership checks to the WITH CHECK clauses of four row-level security policies (manual labels insert/update, document sections, document memory cards), so a doctor can no longer attach their own tag, section, or memory card to another doctor's document. Includes a two-user privacy SQL test wired into CI. No issues found. VerificationRules No rules evaluated Functional validation Not enabledAuto-approval Approved For more verification details, comment OptionsAuto-apply is off → Gitar will not commit updates to this branch. Comment with these commands to change the behavior for this request:
Important Your trial ends in 6 days — upgrade now to keep code review, CI analysis, auto-apply, custom automations, and more. Was this helpful? React with 👍 / 👎 | Gitar |
Summary
Before: three database privacy rules (manual document tags, document sections and document memory cards) checked that a row was yours, but not that the document it hangs off was yours. In principle, a signed-in doctor could attach their own tag, section or memory card to another doctor's document.
After: those rules also require the parent document to be yours. The two-user privacy test's known-gap list is now empty, so the test fails if any of these rules loosens again.
Nothing could reach the gap before this change. Browser roles have no grant on these tables, and the server routes check document ownership before they write. This closes the gap at the database as well.
How: one new migration uses
alter policy ... with checkon four policies (labels owner manual insert,labels owner manual update,document sections owner all,document memory cards owner all). It adds anexistscheck againstpublic.documents.owner_id. Only WITH CHECK changes, so reads and deletes are unchanged. The server's service role bypasses row-level security, so app behaviour is unchanged.supabase/schema.sqlmirrors the change, and the drift manifest and migration seal are regenerated. The privacy test also probes moving a tag, section or memory card onto the other doctor's document.#3556 (the two-user privacy test) has merged, and main is merged in here, so the diff is now only this change.
Areas touched: Data platform and access, Delivery and assurance, Knowledge and records, Source intake and indexing
Verification
npm run test:sqlafter merging main:All 5 SQL behaviour tests passed.schema.sql, then the privacy test:TWO_USER_PRIVACY_SQL_PASS.npm run check:migration-role:Hosted migration-role guard passednpm run check:migration-immutability:Migration immutability guard passed: 310 shipped migrations unchanged.npm run drift:manifestregenerated from the newschema.sql.Risk and rollout
🤖 Generated with Claude Code
https://claude.ai/code/session_01KhogQUCHgdtFBHFtpjnd1n
Generated by Claude Code
Summary by CodeRabbit