From b7700b766a6a8fb6b20065f5e56d006d07fedb4f Mon Sep 17 00:00:00 2001 From: Talha Ahmed Date: Wed, 2 Sep 2026 21:59:08 +0500 Subject: [PATCH] Roles: prune unused seeded staff roles down to the org's four The organisation runs four staff roles - system_administrator, recruiter, hiring_manager, department_head. Migration 026 soft-deletes hr_administrator, interviewer and ceo (listings filter on is_deleted, so they vanish from Access Control and every role picker). candidate stays: it is the applicant account type every candidate user sits on, not a staff role. Guarded: a role that still has live members is left untouched until they are reassigned, and the idempotent migration picks it up on a later boot. Co-Authored-By: Claude Fable 5 --- .../manual/026_prune_unused_staff_roles.sql | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 backend/migrations/manual/026_prune_unused_staff_roles.sql diff --git a/backend/migrations/manual/026_prune_unused_staff_roles.sql b/backend/migrations/manual/026_prune_unused_staff_roles.sql new file mode 100644 index 0000000..687a8e1 --- /dev/null +++ b/backend/migrations/manual/026_prune_unused_staff_roles.sql @@ -0,0 +1,24 @@ +-- 026: The organisation runs four staff roles — system_administrator, +-- recruiter, hiring_manager, department_head. Soft-delete the unused seeded +-- staff roles (hr_administrator, interviewer, ceo) so they stop appearing in +-- the Access Control screen and every role picker (listings filter on +-- is_deleted). +-- +-- NOT touched: +-- * candidate — not a staff role: every applicant account is a role-8 user +-- and the Candidates screen is keyed to it. +-- * any role that still has live members — pruning a role out from under a +-- user would strand their permissions; such a role keeps working until +-- the members are reassigned by hand, and this migration (idempotent) +-- picks it up on a later boot. +UPDATE app.roles r +SET is_deleted = TRUE, + is_active = FALSE, + updated_at = NOW() +WHERE r.role_name IN ('hr_administrator', 'interviewer', 'ceo') + AND r.is_deleted = FALSE + AND NOT EXISTS ( + SELECT 1 FROM app.users u + WHERE u.role_id = r.id + AND COALESCE(u.is_deleted, FALSE) = FALSE + ); -- 2.40.1