feat(store): migration 003 — enforce per-user isolation via forced RLS
Enable AND FORCE row-level security on every user-owned table (users, videos, transcripts, summaries, summary_actions, sink_deliveries) per ADR-012. Each policy keys off the per-request GUC tapir.current_user_id; an unset GUC yields NULL → deny-all (the safe default). FORCE is load-bearing: the app connects as the table owner (tapir), and owners bypass RLS unless forced. Without FORCE the policies are dead for the prod user. sink_deliveries has no user_id; its policy derives ownership from the summary it belongs to via EXISTS against the GUC, so it is self-contained rather than silently depending on summaries' own RLS being applied to a subquery. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
DROP POLICY IF EXISTS sink_deliveries_isolation ON sink_deliveries;
|
||||
ALTER TABLE sink_deliveries NO FORCE ROW LEVEL SECURITY;
|
||||
ALTER TABLE sink_deliveries DISABLE ROW LEVEL SECURITY;
|
||||
|
||||
DROP POLICY IF EXISTS summary_actions_isolation ON summary_actions;
|
||||
ALTER TABLE summary_actions NO FORCE ROW LEVEL SECURITY;
|
||||
ALTER TABLE summary_actions DISABLE ROW LEVEL SECURITY;
|
||||
|
||||
DROP POLICY IF EXISTS summaries_isolation ON summaries;
|
||||
ALTER TABLE summaries NO FORCE ROW LEVEL SECURITY;
|
||||
ALTER TABLE summaries DISABLE ROW LEVEL SECURITY;
|
||||
|
||||
DROP POLICY IF EXISTS transcripts_isolation ON transcripts;
|
||||
ALTER TABLE transcripts NO FORCE ROW LEVEL SECURITY;
|
||||
ALTER TABLE transcripts DISABLE ROW LEVEL SECURITY;
|
||||
|
||||
DROP POLICY IF EXISTS videos_isolation ON videos;
|
||||
ALTER TABLE videos NO FORCE ROW LEVEL SECURITY;
|
||||
ALTER TABLE videos DISABLE ROW LEVEL SECURITY;
|
||||
|
||||
DROP POLICY IF EXISTS users_isolation ON users;
|
||||
ALTER TABLE users NO FORCE ROW LEVEL SECURITY;
|
||||
ALTER TABLE users DISABLE ROW LEVEL SECURITY;
|
||||
Reference in New Issue
Block a user