-- 005_tasks_rbac_restrict.sql -- Manual one-shot: restrict task CREATION in the permission database to -- system_administrator / hr_administrator / recruiter. 004 attached the full -- tasks_management bundle (all 8 tags) to six roles; here hiring_manager, -- department_head and ceo swap it for a view-only bundle so the permission DB -- itself says who may create — the tasks service additionally enforces the -- creator-role check at request time. Idempotent; auto-applied at startup by -- alembic_setup.run_manual_sql(). -- ============================================================================= -- 1. View-only bundle (tasks.view, tasks.export) -- ============================================================================= INSERT INTO app.permissions (name, description, permission_tags, is_system, created_at, updated_at, is_active, is_deleted) SELECT 'tasks_viewer', 'Recruiting task list: read-only access', ( SELECT COALESCE(jsonb_agg(id ORDER BY id), '[]'::jsonb) FROM app.permission_tags WHERE is_deleted = false AND tag_name IN ('tasks.view', 'tasks.export') ), true, NOW(), NOW(), true, false WHERE NOT EXISTS ( SELECT 1 FROM app.permissions WHERE name = 'tasks_viewer' ); -- ============================================================================= -- 2. Remove the full tasks_management bundle from the non-creator roles -- (jsonb arrays hold numbers, so `-` text removal does not apply — rebuild) -- ============================================================================= UPDATE app.roles r SET permissions = ( SELECT COALESCE(jsonb_agg(elem), '[]'::jsonb) FROM jsonb_array_elements(COALESCE(r.permissions, '[]'::jsonb)) elem WHERE elem <> to_jsonb(p.id) ), updated_at = NOW() FROM app.permissions p WHERE p.name = 'tasks_management' AND r.role_name IN ('hiring_manager', 'department_head', 'ceo') AND COALESCE(r.permissions, '[]'::jsonb) @> jsonb_build_array(p.id); -- ============================================================================= -- 3. Attach the view-only bundle to those roles -- ============================================================================= UPDATE app.roles r SET permissions = COALESCE(r.permissions, '[]'::jsonb) || jsonb_build_array(p.id), updated_at = NOW() FROM app.permissions p WHERE p.name = 'tasks_viewer' AND r.role_name IN ( 'hiring_manager', 'department_head', 'ceo' ) AND NOT (COALESCE(r.permissions, '[]'::jsonb) @> jsonb_build_array(p.id));