-- AwoooP RLS Canary Wave 1.2: projects table with explicit operator list path
-- Date: 2026-05-12
--
-- Scope:
--   - awooop_projects
--
-- Safety model:
--   - normal app access is tenant-scoped by app.project_id.
--   - Operator Console cross-tenant list uses a fixed SECURITY DEFINER
--     function owned by the migration/operator role.
--   - no NULL/empty-string/__platform__ policy bypass.

BEGIN;

SET LOCAL lock_timeout = '5s';
SET LOCAL statement_timeout = '30s';

DO $$
DECLARE
    total_rows bigint;
    null_project_rows bigint;
BEGIN
    IF to_regclass('public.awooop_projects') IS NULL THEN
        RAISE EXCEPTION 'RLS canary target table does not exist: awooop_projects';
    END IF;

    IF NOT EXISTS (
        SELECT 1
        FROM information_schema.columns
        WHERE table_schema = 'public'
          AND table_name = 'awooop_projects'
          AND column_name = 'project_id'
    ) THEN
        RAISE EXCEPTION 'RLS canary target missing project_id: awooop_projects';
    END IF;

    SELECT COUNT(*), COUNT(*) FILTER (WHERE project_id IS NULL)
    INTO total_rows, null_project_rows
    FROM awooop_projects;

    IF null_project_rows <> 0 THEN
        RAISE EXCEPTION 'RLS canary target has NULL project_id rows: %, nulls=%',
            'awooop_projects', null_project_rows;
    END IF;

    IF total_rows > 20 THEN
        RAISE EXCEPTION 'RLS canary wave1.2 reviewed cap exceeded: %, rows=%',
            'awooop_projects', total_rows;
    END IF;
END
$$;

CREATE OR REPLACE FUNCTION public.awooop_operator_list_projects()
RETURNS TABLE (
    project_id varchar,
    display_name varchar,
    migration_mode varchar,
    budget_limit_usd numeric,
    is_active boolean,
    created_at timestamp without time zone
)
LANGUAGE sql
STABLE
SECURITY DEFINER
SET search_path = public, pg_catalog
AS $$
    SELECT
        p.project_id,
        p.display_name,
        p.migration_mode,
        p.budget_limit_usd,
        p.is_active,
        p.created_at
    FROM public.awooop_projects AS p
    ORDER BY p.created_at ASC;
$$;

REVOKE ALL ON FUNCTION public.awooop_operator_list_projects() FROM PUBLIC;
GRANT EXECUTE ON FUNCTION public.awooop_operator_list_projects() TO awooop_app;

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

DROP POLICY IF EXISTS awooop_projects_select_tenant ON awooop_projects;
DROP POLICY IF EXISTS awooop_projects_insert_tenant ON awooop_projects;
DROP POLICY IF EXISTS awooop_projects_update_tenant ON awooop_projects;
DROP POLICY IF EXISTS awooop_projects_delete_tenant ON awooop_projects;
DROP POLICY IF EXISTS projects_tenant_isolation ON awooop_projects;

CREATE POLICY awooop_projects_select_tenant ON awooop_projects
    FOR SELECT TO awooop_app
    USING (project_id = current_setting('app.project_id', TRUE));

CREATE POLICY awooop_projects_insert_tenant ON awooop_projects
    FOR INSERT TO awooop_app
    WITH CHECK (project_id = current_setting('app.project_id', TRUE));

CREATE POLICY awooop_projects_update_tenant ON awooop_projects
    FOR UPDATE TO awooop_app
    USING (project_id = current_setting('app.project_id', TRUE))
    WITH CHECK (project_id = current_setting('app.project_id', TRUE));

CREATE POLICY awooop_projects_delete_tenant ON awooop_projects
    FOR DELETE TO awooop_app
    USING (project_id = current_setting('app.project_id', TRUE));

COMMIT;
