-- Copyright (c) Microsoft Corporation.
-- Licensed under the PostgreSQL License.

-- Merged from: 37_rls, 38_rls_vars
-- Tests: RLS enforcement on df.instances and df.nodes (per-user isolation),
--        cross-user cancel/signal blocked, monitoring functions respect RLS,
--        RLS on df.vars (per-user variable isolation), df.clearvars/unsetvar scoping
-- Runs as postgres throughout (creates/drops roles and uses SET SESSION AUTHORIZATION)

-- === Test: 37_rls ===

-- Setup: Create two test users
DO $setup$
BEGIN
    PERFORM pg_terminate_backend(pid)
      FROM pg_stat_activity
      WHERE usename IN ('rls_alice', 'rls_bob')
        AND pid <> pg_backend_pid();

    BEGIN DROP OWNED BY rls_alice; EXCEPTION WHEN undefined_object THEN NULL; END;
    BEGIN DROP OWNED BY rls_bob;   EXCEPTION WHEN undefined_object THEN NULL; END;
    BEGIN DROP ROLE rls_alice;     EXCEPTION WHEN undefined_object THEN NULL; END;
    BEGIN DROP ROLE rls_bob;       EXCEPTION WHEN undefined_object THEN NULL; END;
END $setup$;

CREATE ROLE rls_alice LOGIN;
CREATE ROLE rls_bob   LOGIN;

SELECT df.grant_usage('rls_alice');
SELECT df.grant_usage('rls_bob');

GRANT TEMPORARY ON DATABASE postgres TO rls_alice, rls_bob;

-- Submit instances as each user
SET SESSION AUTHORIZATION rls_alice;
CREATE TEMP TABLE _rls_alice_state (instance_id TEXT);
INSERT INTO _rls_alice_state SELECT df.start(df.sql('SELECT 1 AS alice_result'), 'rls-alice-job');
RESET SESSION AUTHORIZATION;

SET SESSION AUTHORIZATION rls_bob;
CREATE TEMP TABLE _rls_bob_state (instance_id TEXT);
INSERT INTO _rls_bob_state SELECT df.start(df.sql('SELECT 2 AS bob_result'), 'rls-bob-job');
RESET SESSION AUTHORIZATION;

DO $$
DECLARE
    alice_id TEXT;
    bob_id TEXT;
    s TEXT;
BEGIN
    SELECT instance_id INTO alice_id FROM _rls_alice_state;
    SELECT instance_id INTO bob_id FROM _rls_bob_state;

    SELECT df.await_instance(alice_id, 30) INTO s;
    IF s != 'completed' THEN
        RAISE EXCEPTION 'Setup failed: Alice job status = %', s;
    END IF;

    SELECT df.await_instance(bob_id, 30) INTO s;
    IF s != 'completed' THEN
        RAISE EXCEPTION 'Setup failed: Bob job status = %', s;
    END IF;
END $$;

-- Test 1: User can only see own instances
DO $$
DECLARE
    alice_id TEXT;
    bob_id TEXT;
    cnt INT;
BEGIN
    SELECT instance_id INTO alice_id FROM _rls_alice_state;
    SELECT instance_id INTO bob_id FROM _rls_bob_state;

    SET SESSION AUTHORIZATION rls_alice;

    SELECT count(*) INTO cnt FROM df.instances WHERE id = alice_id;
    IF cnt != 1 THEN
        RAISE EXCEPTION 'TEST 1 FAILED: Alice cannot see her own instance (count=%, expected 1)', cnt;
    END IF;

    SELECT count(*) INTO cnt FROM df.instances WHERE id = bob_id;
    IF cnt != 0 THEN
        RAISE EXCEPTION 'TEST 1 FAILED: Alice can see Bob''s instance (count=%, expected 0)', cnt;
    END IF;

    RESET SESSION AUTHORIZATION;

    SET SESSION AUTHORIZATION rls_bob;

    SELECT count(*) INTO cnt FROM df.instances WHERE id = bob_id;
    IF cnt != 1 THEN
        RAISE EXCEPTION 'TEST 1 FAILED: Bob cannot see his own instance (count=%, expected 1)', cnt;
    END IF;

    SELECT count(*) INTO cnt FROM df.instances WHERE id = alice_id;
    IF cnt != 0 THEN
        RAISE EXCEPTION 'TEST 1 FAILED: Bob can see Alice''s instance (count=%, expected 0)', cnt;
    END IF;

    RESET SESSION AUTHORIZATION;

    RAISE NOTICE 'Test 1 PASSED: Users can only see own instances';
END $$;

-- Test 2: User cannot see another user's nodes
DO $$
DECLARE
    alice_id TEXT;
    bob_id TEXT;
    cnt INT;
BEGIN
    SELECT instance_id INTO alice_id FROM _rls_alice_state;
    SELECT instance_id INTO bob_id FROM _rls_bob_state;

    SET SESSION AUTHORIZATION rls_alice;

    SELECT count(*) INTO cnt FROM df.nodes WHERE instance_id = bob_id;
    IF cnt != 0 THEN
        RAISE EXCEPTION 'TEST 2 FAILED: Alice can see Bob''s nodes (count=%, expected 0)', cnt;
    END IF;

    SELECT count(*) INTO cnt FROM df.nodes WHERE instance_id = alice_id;
    IF cnt < 1 THEN
        RAISE EXCEPTION 'TEST 2 FAILED: Alice cannot see her own nodes (count=%, expected >= 1)', cnt;
    END IF;

    RESET SESSION AUTHORIZATION;

    SET SESSION AUTHORIZATION rls_bob;

    SELECT count(*) INTO cnt FROM df.nodes WHERE instance_id = alice_id;
    IF cnt != 0 THEN
        RAISE EXCEPTION 'TEST 2 FAILED: Bob can see Alice''s nodes (count=%, expected 0)', cnt;
    END IF;

    RESET SESSION AUTHORIZATION;

    RAISE NOTICE 'Test 2 PASSED: Users cannot see other users'' nodes';
END $$;

-- Test 3: User cannot cancel another user's instance
SET SESSION AUTHORIZATION rls_alice;
CREATE TEMP TABLE _rls_cancel_state (instance_id TEXT);
INSERT INTO _rls_cancel_state SELECT df.start(df.sql('SELECT pg_sleep(30)'), 'rls-cancel-target');
RESET SESSION AUTHORIZATION;

DO $$
DECLARE
    alice_cancel_id TEXT;
    err_msg TEXT;
BEGIN
    SELECT instance_id INTO alice_cancel_id FROM _rls_cancel_state;

    SET SESSION AUTHORIZATION rls_bob;

    BEGIN
        PERFORM df.cancel(alice_cancel_id);
        RAISE EXCEPTION 'TEST 3 FAILED: Bob was able to cancel Alice''s instance';
    EXCEPTION
        WHEN OTHERS THEN
            GET STACKED DIAGNOSTICS err_msg = MESSAGE_TEXT;
            IF err_msg LIKE '%not found or access denied%' THEN
                RAISE NOTICE 'Test 3 PASSED: Bob cannot cancel Alice''s instance';
            ELSE
                RAISE EXCEPTION 'TEST 3 FAILED: Unexpected error: %', err_msg;
            END IF;
    END;

    RESET SESSION AUTHORIZATION;

    PERFORM df.cancel(alice_cancel_id);
END $$;

DROP TABLE _rls_cancel_state;

-- Test 4: User cannot signal another user's instance
DO $$
DECLARE
    alice_id TEXT;
    err_msg TEXT;
BEGIN
    SELECT instance_id INTO alice_id FROM _rls_alice_state;

    SET SESSION AUTHORIZATION rls_bob;

    BEGIN
        PERFORM df.signal(alice_id, 'test-signal', '{}');
        RAISE EXCEPTION 'TEST 4 FAILED: Bob was able to signal Alice''s instance';
    EXCEPTION
        WHEN OTHERS THEN
            GET STACKED DIAGNOSTICS err_msg = MESSAGE_TEXT;
            IF err_msg LIKE '%not found or access denied%' THEN
                RAISE NOTICE 'Test 4 PASSED: Bob cannot signal Alice''s instance';
            ELSE
                RAISE EXCEPTION 'TEST 4 FAILED: Unexpected error: %', err_msg;
            END IF;
    END;

    RESET SESSION AUTHORIZATION;
END $$;

-- Test 5: Monitoring functions respect RLS
DO $$
DECLARE
    alice_id TEXT;
    bob_id TEXT;
    cnt INT;
BEGIN
    SELECT instance_id INTO alice_id FROM _rls_alice_state;
    SELECT instance_id INTO bob_id FROM _rls_bob_state;

    SET SESSION AUTHORIZATION rls_alice;

    SELECT count(*) INTO cnt FROM df.list_instances();
    IF cnt < 1 THEN
        RAISE EXCEPTION 'TEST 5 FAILED: Alice sees no instances from list_instances';
    END IF;

    SELECT count(*) INTO cnt FROM df.list_instances() li WHERE li.instance_id = bob_id;
    IF cnt != 0 THEN
        RAISE EXCEPTION 'TEST 5 FAILED: Alice can see Bob''s instance in list_instances';
    END IF;

    SELECT count(*) INTO cnt FROM df.instance_info(bob_id);
    IF cnt != 0 THEN
        RAISE EXCEPTION 'TEST 5 FAILED: Alice can see Bob''s instance_info';
    END IF;

    SELECT count(*) INTO cnt FROM df.instance_info(alice_id);
    IF cnt != 1 THEN
        RAISE EXCEPTION 'TEST 5 FAILED: Alice cannot see her own instance_info (count=%)', cnt;
    END IF;

    RESET SESSION AUTHORIZATION;

    RAISE NOTICE 'Test 5 PASSED: Monitoring functions respect RLS';
END $$;

-- Test 6: Superuser can see all instances (RLS bypassed)
DO $$
DECLARE
    alice_id TEXT;
    bob_id TEXT;
    cnt INT;
BEGIN
    SELECT instance_id INTO alice_id FROM _rls_alice_state;
    SELECT instance_id INTO bob_id FROM _rls_bob_state;

    SELECT count(*) INTO cnt FROM df.instances WHERE id IN (alice_id, bob_id);
    IF cnt != 2 THEN
        RAISE EXCEPTION 'TEST 6 FAILED: Superuser cannot see both instances (count=%, expected 2)', cnt;
    END IF;

    RAISE NOTICE 'Test 6 PASSED: Superuser can see all instances';
END $$;

-- Test 7: User can UPDATE allowed columns on own rows
DO $$
DECLARE
    alice_id TEXT;
    bob_id TEXT;
    cnt INT;
BEGIN
    SELECT instance_id INTO alice_id FROM _rls_alice_state;
    SELECT instance_id INTO bob_id FROM _rls_bob_state;

    SET SESSION AUTHORIZATION rls_alice;

    UPDATE df.instances SET status = 'completed', updated_at = now() WHERE id = alice_id;
    GET DIAGNOSTICS cnt = ROW_COUNT;
    IF cnt != 1 THEN
        RAISE EXCEPTION 'TEST 7 FAILED: Alice could not UPDATE status on her own instance (rows=%)', cnt;
    END IF;

    UPDATE df.instances SET status = 'cancelled' WHERE id = bob_id;
    GET DIAGNOSTICS cnt = ROW_COUNT;
    IF cnt != 0 THEN
        RAISE EXCEPTION 'TEST 7 FAILED: Alice was able to UPDATE Bob''s instance (rows=%)', cnt;
    END IF;

    RESET SESSION AUTHORIZATION;

    RAISE NOTICE 'Test 7 PASSED: Column-level UPDATE on status works, RLS enforced';
END $$;

-- Test 8: User cannot DELETE instances
DO $$
DECLARE
    alice_id TEXT;
BEGIN
    SELECT instance_id INTO alice_id FROM _rls_alice_state;

    SET SESSION AUTHORIZATION rls_alice;

    BEGIN
        DELETE FROM df.instances WHERE id = alice_id;
        RAISE EXCEPTION 'TEST 8 FAILED: Alice was able to DELETE her own instance';
    EXCEPTION
        WHEN insufficient_privilege THEN
            RAISE NOTICE 'Test 8 PASSED: DELETE on df.instances denied (no DELETE grant)';
    END;

    RESET SESSION AUTHORIZATION;
END $$;

-- Test 9: User cannot UPDATE identity columns
DO $$
DECLARE
    alice_id TEXT;
BEGIN
    SELECT instance_id INTO alice_id FROM _rls_alice_state;

    SET SESSION AUTHORIZATION rls_alice;

    BEGIN
        UPDATE df.instances SET submitted_by = 'postgres'::regrole WHERE id = alice_id;
        RAISE EXCEPTION 'TEST 9 FAILED: Alice was able to tamper with submitted_by';
    EXCEPTION
        WHEN insufficient_privilege THEN
            NULL;
    END;

    RESET SESSION AUTHORIZATION;

    RAISE NOTICE 'Test 9 PASSED: Cannot UPDATE identity columns (column-level grant restricts)';
END $$;

-- Test 10: User cannot INSERT runtime-owned columns directly
DO $$
BEGIN
    SET SESSION AUTHORIZATION rls_alice;

    BEGIN
        INSERT INTO df.instances (id, root_node, status, submitted_by)
        VALUES ('deadbeef', 'cafebabe', 'completed', current_user::regrole);
        RAISE EXCEPTION 'TEST 10 FAILED: Alice was able to INSERT status into df.instances';
    EXCEPTION
        WHEN insufficient_privilege THEN
            NULL;
    END;

    BEGIN
        INSERT INTO df.nodes (id, instance_id, node_type, query, status, submitted_by)
        VALUES ('deadbeef', 'cafebabe', 'SQL', 'SELECT 1', 'completed', current_user::regrole);
        RAISE EXCEPTION 'TEST 10 FAILED: Alice was able to INSERT status into df.nodes';
    EXCEPTION
        WHEN insufficient_privilege THEN
            NULL;
    END;

    RESET SESSION AUTHORIZATION;

    RAISE NOTICE 'Test 10 PASSED: INSERT is limited to df.start()-shaped columns';
END $$;

-- Test 11: Direct INSERT still respects shape constraints
DO $$
BEGIN
    SET SESSION AUTHORIZATION rls_alice;

    BEGIN
        INSERT INTO df.instances (id, root_node, submitted_by)
        VALUES ('not_hex!', 'cafebabe', current_user::regrole);
        RAISE EXCEPTION 'TEST 11 FAILED: Alice was able to INSERT malformed instance metadata';
    EXCEPTION
        WHEN check_violation THEN
            NULL;
    END;

    BEGIN
        INSERT INTO df.nodes (id, instance_id, node_type, query, result_name, submitted_by)
        VALUES ('deadbeef', 'cafebabe', 'SQL', 'SELECT 1', 'bad-name', current_user::regrole);
        RAISE EXCEPTION 'TEST 11 FAILED: Alice was able to INSERT malformed node metadata';
    EXCEPTION
        WHEN check_violation THEN
            NULL;
    END;

    RESET SESSION AUTHORIZATION;

    RAISE NOTICE 'Test 11 PASSED: Direct INSERT must satisfy metadata shape constraints';
END $$;

-- Cleanup 37_rls
DROP TABLE IF EXISTS _rls_alice_state;
DROP TABLE IF EXISTS _rls_bob_state;

DO $cleanup_rls$
BEGIN
    BEGIN DROP OWNED BY rls_alice; EXCEPTION WHEN undefined_object THEN NULL; END;
    BEGIN DROP OWNED BY rls_bob;   EXCEPTION WHEN undefined_object THEN NULL; END;
    BEGIN DROP ROLE rls_alice;     EXCEPTION WHEN undefined_object THEN NULL; END;
    BEGIN DROP ROLE rls_bob;       EXCEPTION WHEN undefined_object THEN NULL; END;
END $cleanup_rls$;

-- === Test: 38_rls_vars ===

-- Setup: Create two test users
DO $setup$
BEGIN
    PERFORM pg_terminate_backend(pid)
      FROM pg_stat_activity
      WHERE usename IN ('vars_alice', 'vars_bob')
        AND pid <> pg_backend_pid();

    BEGIN DROP OWNED BY vars_alice; EXCEPTION WHEN undefined_object THEN NULL; END;
    BEGIN DROP OWNED BY vars_bob;   EXCEPTION WHEN undefined_object THEN NULL; END;
    BEGIN DROP ROLE vars_alice;     EXCEPTION WHEN undefined_object THEN NULL; END;
    BEGIN DROP ROLE vars_bob;       EXCEPTION WHEN undefined_object THEN NULL; END;
END $setup$;

CREATE ROLE vars_alice LOGIN;
CREATE ROLE vars_bob   LOGIN;

SELECT df.grant_usage('vars_alice');
SELECT df.grant_usage('vars_bob');

GRANT TEMPORARY ON DATABASE postgres TO vars_alice, vars_bob;

DROP TABLE IF EXISTS vars_test_results;
CREATE TABLE vars_test_results (id SERIAL PRIMARY KEY, username TEXT, msg TEXT);
GRANT SELECT, INSERT ON vars_test_results TO PUBLIC;
GRANT USAGE ON SEQUENCE vars_test_results_id_seq TO PUBLIC;

-- Test 1: Per-user variable isolation via direct table access
SET SESSION AUTHORIZATION vars_alice;
SELECT df.setvar('color', 'red');
RESET SESSION AUTHORIZATION;

SET SESSION AUTHORIZATION vars_bob;
SELECT df.setvar('color', 'blue');
RESET SESSION AUTHORIZATION;

DO $$
DECLARE
    alice_val TEXT;
    bob_val TEXT;
    alice_count INT;
    bob_count INT;
BEGIN
    SET SESSION AUTHORIZATION vars_alice;
    SELECT df.getvar('color') INTO alice_val;
    SELECT count(*) INTO alice_count FROM df.vars;
    RESET SESSION AUTHORIZATION;

    SET SESSION AUTHORIZATION vars_bob;
    SELECT df.getvar('color') INTO bob_val;
    SELECT count(*) INTO bob_count FROM df.vars;
    RESET SESSION AUTHORIZATION;

    IF alice_val != 'red' THEN
        RAISE EXCEPTION 'TEST 1 FAILED: Alice expected "red", got "%"', alice_val;
    END IF;

    IF bob_val != 'blue' THEN
        RAISE EXCEPTION 'TEST 1 FAILED: Bob expected "blue", got "%"', bob_val;
    END IF;

    IF alice_count != 1 THEN
        RAISE EXCEPTION 'TEST 1 FAILED: Alice should see 1 var, saw %', alice_count;
    END IF;

    IF bob_count != 1 THEN
        RAISE EXCEPTION 'TEST 1 FAILED: Bob should see 1 var, saw %', bob_count;
    END IF;

    RAISE NOTICE 'Test 1 PASSED: Per-user variable isolation (same key, different values)';
END $$;

-- Test 2: df.start() captures only the calling user's variables
SET SESSION AUTHORIZATION vars_alice;
CREATE TEMP TABLE _vars_alice_state (instance_id TEXT);
INSERT INTO _vars_alice_state SELECT df.start(
    'INSERT INTO vars_test_results (username, msg) VALUES (''alice'', ''{color}'')' ::text,
    'vars-alice-color'
);
RESET SESSION AUTHORIZATION;

SET SESSION AUTHORIZATION vars_bob;
CREATE TEMP TABLE _vars_bob_state (instance_id TEXT);
INSERT INTO _vars_bob_state SELECT df.start(
    'INSERT INTO vars_test_results (username, msg) VALUES (''bob'', ''{color}'')' ::text,
    'vars-bob-color'
);
RESET SESSION AUTHORIZATION;

DO $$
DECLARE
    alice_id TEXT;
    bob_id TEXT;
    s TEXT;
BEGIN
    SELECT instance_id INTO alice_id FROM _vars_alice_state;
    SELECT instance_id INTO bob_id FROM _vars_bob_state;

    SELECT df.await_instance(alice_id, 30) INTO s;
    IF s != 'completed' THEN
        RAISE EXCEPTION 'TEST 2 FAILED: Alice workflow status = %', s;
    END IF;

    SELECT df.await_instance(bob_id, 30) INTO s;
    IF s != 'completed' THEN
        RAISE EXCEPTION 'TEST 2 FAILED: Bob workflow status = %', s;
    END IF;
END $$;

DO $$
DECLARE
    alice_msg TEXT;
    bob_msg TEXT;
BEGIN
    SELECT msg INTO alice_msg FROM vars_test_results WHERE username = 'alice' ORDER BY id DESC LIMIT 1;
    SELECT msg INTO bob_msg FROM vars_test_results WHERE username = 'bob' ORDER BY id DESC LIMIT 1;

    IF alice_msg != 'red' THEN
        RAISE EXCEPTION 'TEST 2 FAILED: Alice workflow should have used "red", got "%"', alice_msg;
    END IF;

    IF bob_msg != 'blue' THEN
        RAISE EXCEPTION 'TEST 2 FAILED: Bob workflow should have used "blue", got "%"', bob_msg;
    END IF;

    RAISE NOTICE 'Test 2 PASSED: df.start() captures only the calling user''s vars';
END $$;

-- Test 3: df.clearvars() only clears the calling user's variables
SET SESSION AUTHORIZATION vars_alice;
SELECT df.clearvars();
RESET SESSION AUTHORIZATION;

DO $$
DECLARE
    alice_val TEXT;
    bob_val TEXT;
BEGIN
    SET SESSION AUTHORIZATION vars_alice;
    SELECT df.getvar('color') INTO alice_val;
    RESET SESSION AUTHORIZATION;

    SET SESSION AUTHORIZATION vars_bob;
    SELECT df.getvar('color') INTO bob_val;
    RESET SESSION AUTHORIZATION;

    IF alice_val IS NOT NULL THEN
        RAISE EXCEPTION 'TEST 3 FAILED: Alice''s var should be gone after clearvars, got "%"', alice_val;
    END IF;

    IF bob_val != 'blue' THEN
        RAISE EXCEPTION 'TEST 3 FAILED: Bob''s var should survive Alice''s clearvars, got "%"', bob_val;
    END IF;

    RAISE NOTICE 'Test 3 PASSED: df.clearvars() only clears the calling user''s variables';
END $$;

-- Test 4: df.unsetvar() only removes the calling user's variable
SET SESSION AUTHORIZATION vars_alice;
SELECT df.setvar('shared_key', 'alice_value');
RESET SESSION AUTHORIZATION;

SET SESSION AUTHORIZATION vars_bob;
SELECT df.setvar('shared_key', 'bob_value');
SELECT df.unsetvar('shared_key');
RESET SESSION AUTHORIZATION;

DO $$
DECLARE
    alice_val TEXT;
    bob_val TEXT;
BEGIN
    SET SESSION AUTHORIZATION vars_alice;
    SELECT df.getvar('shared_key') INTO alice_val;
    RESET SESSION AUTHORIZATION;

    SET SESSION AUTHORIZATION vars_bob;
    SELECT df.getvar('shared_key') INTO bob_val;
    RESET SESSION AUTHORIZATION;

    IF alice_val != 'alice_value' THEN
        RAISE EXCEPTION 'TEST 4 FAILED: Alice''s shared_key should survive Bob''s unsetvar, got "%"', alice_val;
    END IF;

    IF bob_val IS NOT NULL THEN
        RAISE EXCEPTION 'TEST 4 FAILED: Bob''s shared_key should be removed, got "%"', bob_val;
    END IF;

    RAISE NOTICE 'Test 4 PASSED: df.unsetvar() only removes the calling user''s variable';
END $$;

-- Test 5: Superuser sees all variables (RLS bypass) but df.start() captures only its own vars
SET SESSION AUTHORIZATION vars_bob;
SELECT df.clearvars();
RESET SESSION AUTHORIZATION;

SELECT df.setvar('su_var', 'superuser_value');

DO $$
DECLARE
    total_count INT;
BEGIN
    SELECT count(*) INTO total_count FROM df.vars;

    IF total_count != 2 THEN
        RAISE EXCEPTION 'TEST 5 FAILED: Superuser should see exactly 2 vars (alice + su), saw %', total_count;
    END IF;

    RAISE NOTICE 'Test 5 PASSED: Superuser sees all variables (% total)', total_count;
END $$;

TRUNCATE vars_test_results;

CREATE TEMP TABLE _vars_su_state (instance_id TEXT);
INSERT INTO _vars_su_state SELECT df.start(
    'INSERT INTO vars_test_results (username, msg) VALUES (''superuser'', ''{su_var}'')' ::text,
    'vars-su-test'
);

DO $$
DECLARE
    su_id TEXT;
    s TEXT;
    su_msg TEXT;
BEGIN
    SELECT instance_id INTO su_id FROM _vars_su_state;
    SELECT df.await_instance(su_id, 30) INTO s;

    IF s != 'completed' THEN
        RAISE EXCEPTION 'TEST 5b FAILED: Superuser workflow status = %', s;
    END IF;

    SELECT msg INTO su_msg FROM vars_test_results WHERE username = 'superuser' ORDER BY id DESC LIMIT 1;

    IF su_msg != 'superuser_value' THEN
        RAISE EXCEPTION 'TEST 5b FAILED: Superuser workflow should use "superuser_value", got "%"', su_msg;
    END IF;

    RAISE NOTICE 'Test 5b PASSED: Superuser df.start() captures only its own vars';
END $$;

-- Cleanup
DROP TABLE IF EXISTS _vars_alice_state;
DROP TABLE IF EXISTS _vars_bob_state;
DROP TABLE IF EXISTS _vars_su_state;
DROP TABLE IF EXISTS vars_test_results;

DELETE FROM df.vars WHERE owner IN ('vars_alice'::regrole, 'vars_bob'::regrole);
SELECT df.clearvars();

DO $cleanup$
BEGIN
    BEGIN DROP OWNED BY vars_alice; EXCEPTION WHEN undefined_object THEN NULL; END;
    BEGIN DROP OWNED BY vars_bob;   EXCEPTION WHEN undefined_object THEN NULL; END;
    BEGIN DROP ROLE vars_alice;     EXCEPTION WHEN undefined_object THEN NULL; END;
    BEGIN DROP ROLE vars_bob;       EXCEPTION WHEN undefined_object THEN NULL; END;
END $cleanup$;

SELECT 'TEST PASSED' AS result;
