| 1234567891011121314151617181920212223242526272829303132 |
- -- 0042_account_purge_fk_set_null — unblock GDPR hard-deletion.
- --
- -- `hardDeleteExpiredAccounts` (services/account-deletion.ts) runs
- -- DELETE FROM users WHERE deleted_at < now() - 30 days
- -- which ALWAYS failed with FK violation 23503 (silently swallowed by the
- -- account-deletion-gc worker) because two FKs onto users.id were ON DELETE
- -- NO ACTION:
- -- * organizations.created_by (and NOT NULL)
- -- * audit_logs.actor_id (already nullable)
- -- Net effect: no expired account was ever purged.
- --
- -- Fix: make organizations.created_by nullable and flip both FKs to
- -- ON DELETE SET NULL. A surviving shared org keeps its row (creator nulls
- -- out); audit rows keep their action + timestamp (actor nulls out). The
- -- purge transaction hard-deletes the user's own sole-owner soft-deleted
- -- orgs first (their projects cascade via projects.org_id ON DELETE CASCADE),
- -- then deletes the user — which now succeeds instead of raising 23503.
- --
- -- DROP CONSTRAINT statements list both the drizzle-style name and the
- -- postgres-default `_fkey` name with IF EXISTS so the migration is robust
- -- whichever name the live constraint carries.
- -- organizations.created_by: drop NOT NULL, recreate FK as ON DELETE SET NULL.
- ALTER TABLE "organizations" ALTER COLUMN "created_by" DROP NOT NULL;
- ALTER TABLE "organizations" DROP CONSTRAINT IF EXISTS "organizations_created_by_fkey";
- ALTER TABLE "organizations" DROP CONSTRAINT IF EXISTS "organizations_created_by_users_id_fk";
- ALTER TABLE "organizations" ADD CONSTRAINT "organizations_created_by_users_id_fk" FOREIGN KEY ("created_by") REFERENCES "users"("id") ON DELETE set null ON UPDATE no action;
- -- audit_logs.actor_id: already nullable; recreate FK as ON DELETE SET NULL.
- ALTER TABLE "audit_logs" DROP CONSTRAINT IF EXISTS "audit_logs_actor_id_users_id_fk";
- ALTER TABLE "audit_logs" DROP CONSTRAINT IF EXISTS "audit_logs_actor_id_fkey";
- ALTER TABLE "audit_logs" ADD CONSTRAINT "audit_logs_actor_id_users_id_fk" FOREIGN KEY ("actor_id") REFERENCES "users"("id") ON DELETE set null ON UPDATE no action;
|