towerops/priv/repo/migrations/20260305152524_fix_agent_cascade_deletes.exs
Graham McIntire a230f1bfb5
fix: prevent silent data loss from cascade deletes on agent tokens
Changed foreign key constraints from CASCADE to RESTRICT for:
- agent_tokens.organization_id
- agent_assignments.agent_token_id

**Problem:**
Deleting an organization would cascade delete all agent tokens, which
would then cascade delete all agent assignments, causing silent data
loss without any audit trail.

**Solution:**
Use RESTRICT instead of CASCADE - this prevents deletion if there are
dependent records, forcing explicit cleanup and preventing accidental
data loss.

**Impact:**
- Organizations cannot be deleted if they have agent tokens
- Agent tokens cannot be deleted if they have active assignments
- User must explicitly clean up dependencies first

This provides better data integrity and prevents accidental data loss.

Fixes Medium Bug #15 from reliability audit.
2026-03-05 09:25:55 -06:00

64 lines
1.7 KiB
Elixir

defmodule Towerops.Repo.Migrations.FixAgentCascadeDeletes do
use Ecto.Migration
def up do
# Drop and recreate the foreign key constraint on agent_tokens.organization_id
# Change from :delete_all to :restrict to prevent accidental data loss
execute """
ALTER TABLE agent_tokens
DROP CONSTRAINT agent_tokens_organization_id_fkey
"""
execute """
ALTER TABLE agent_tokens
ADD CONSTRAINT agent_tokens_organization_id_fkey
FOREIGN KEY (organization_id)
REFERENCES organizations(id)
ON DELETE RESTRICT
"""
# Drop and recreate the foreign key constraint on agent_assignments.agent_token_id
# Change from :delete_all to :restrict to prevent orphaned assignments
execute """
ALTER TABLE agent_assignments
DROP CONSTRAINT agent_assignments_agent_token_id_fkey
"""
execute """
ALTER TABLE agent_assignments
ADD CONSTRAINT agent_assignments_agent_token_id_fkey
FOREIGN KEY (agent_token_id)
REFERENCES agent_tokens(id)
ON DELETE RESTRICT
"""
end
def down do
# Restore original cascade delete behavior
execute """
ALTER TABLE agent_assignments
DROP CONSTRAINT agent_assignments_agent_token_id_fkey
"""
execute """
ALTER TABLE agent_assignments
ADD CONSTRAINT agent_assignments_agent_token_id_fkey
FOREIGN KEY (agent_token_id)
REFERENCES agent_tokens(id)
ON DELETE CASCADE
"""
execute """
ALTER TABLE agent_tokens
DROP CONSTRAINT agent_tokens_organization_id_fkey
"""
execute """
ALTER TABLE agent_tokens
ADD CONSTRAINT agent_tokens_organization_id_fkey
FOREIGN KEY (organization_id)
REFERENCES organizations(id)
ON DELETE CASCADE
"""
end
end