-- Row-Level Security (RLS) for Auth Tables
-- This migration adds FORCE ROW LEVEL SECURITY and policies to accounts and sessions tables
-- to ensure users can only access their own authentication data.
--
-- Related: #350 - Add RLS policies to auth tables with FORCE enforcement
-- Design: docs/design/credential-security.md (Phase 1a)

-- =============================================================================
-- ENABLE FORCE RLS ON AUTH TABLES
-- =============================================================================
-- FORCE means the table owner (mosaic) is also subject to RLS policies.
-- This prevents Prisma (connecting as owner) from bypassing policies.

ALTER TABLE accounts ENABLE ROW LEVEL SECURITY;
ALTER TABLE accounts FORCE ROW LEVEL SECURITY;

ALTER TABLE sessions ENABLE ROW LEVEL SECURITY;
ALTER TABLE sessions FORCE ROW LEVEL SECURITY;

-- =============================================================================
-- ACCOUNTS TABLE POLICIES
-- =============================================================================

-- Owner bypass policy: Allow access to all rows ONLY when no RLS context is set
-- This is required for:
-- 1. Prisma migrations that run without RLS context
-- 2. BetterAuth internal operations during authentication flow (when no user context)
-- 3. Database maintenance operations
-- When RLS context IS set (current_user_id() returns non-NULL), this policy does not apply
--
-- NOTE: If connecting as a PostgreSQL superuser (like the default 'mosaic' role),
-- RLS policies are bypassed entirely. For full RLS enforcement, the application
-- should connect as a non-superuser role. See docs/design/credential-security.md
CREATE POLICY accounts_owner_bypass ON accounts
  FOR ALL
  USING (current_user_id() IS NULL);

-- User access policy: Users can only access their own accounts
-- Uses current_user_id() helper from migration 20260129221004_add_rls_policies
-- This policy applies to all operations: SELECT, INSERT, UPDATE, DELETE
CREATE POLICY accounts_user_access ON accounts
  FOR ALL
  USING (user_id = current_user_id());

-- =============================================================================
-- SESSIONS TABLE POLICIES
-- =============================================================================

-- Owner bypass policy: Allow access to all rows ONLY when no RLS context is set
-- See note on accounts_owner_bypass policy about superuser limitations
CREATE POLICY sessions_owner_bypass ON sessions
  FOR ALL
  USING (current_user_id() IS NULL);

-- User access policy: Users can only access their own sessions
CREATE POLICY sessions_user_access ON sessions
  FOR ALL
  USING (user_id = current_user_id());

-- =============================================================================
-- VERIFICATION TABLE ANALYSIS
-- =============================================================================
-- The verifications table does NOT need RLS policies because:
-- 1. It stores ephemeral verification tokens (email verification, password reset)
-- 2. It has no user_id column - only identifier (email) and value (token)
-- 3. Tokens are short-lived and accessed by token value, not user context
-- 4. BetterAuth manages access control through token validation, not RLS
-- 5. No cross-user data leakage risk since tokens are random and expire
--
-- Therefore, we intentionally do NOT add RLS to verifications table.

-- =============================================================================
-- IMPORTANT: SUPERUSER LIMITATION
-- =============================================================================
-- PostgreSQL superusers (including the default 'mosaic' role) ALWAYS bypass
-- Row-Level Security policies, even with FORCE ROW LEVEL SECURITY enabled.
-- This is a fundamental PostgreSQL security design.
--
-- For production deployments with full RLS enforcement, create a dedicated
-- non-superuser application role:
--
--   CREATE ROLE mosaic_app WITH LOGIN PASSWORD 'secure-password';
--   GRANT CONNECT ON DATABASE mosaic TO mosaic_app;
--   GRANT USAGE ON SCHEMA public TO mosaic_app;
--   GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO mosaic_app;
--   GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO mosaic_app;
--
-- Then update DATABASE_URL to connect as mosaic_app instead of mosaic.
-- The RLS policies will then be properly enforced for application queries.
--
-- See: https://www.postgresql.org/docs/current/ddl-rowsecurity.html
