-- Service-account actors on incident mutations (terdut-server#25). A -- team-scoped service account acknowledging/resolving/snoozing/noting an -- incident is not a users row, so it cannot be written into -- acknowledged_by/incident_events.user_id — doing so either violates the -- users(id) FK (new rows) or, for incident_events.user_id, silently matches -- zero rows on delete. These columns are the service-account-shaped parallel -- to the existing human ones: nullable, mutually exclusive with their human -- counterpart, ON DELETE SET NULL so a deleted service account doesn't take -- the incident history with it. ALTER TABLE incidents ADD COLUMN acknowledged_by_service_account_id BIGINT REFERENCES service_accounts(id) ON DELETE SET NULL; ALTER TABLE incident_events ADD COLUMN service_account_id BIGINT REFERENCES service_accounts(id) ON DELETE SET NULL; -- At most one actor kind per row: both NULL ("the server acted") is valid, -- exactly one set is valid, both set is a bug this constraint refuses to -- store rather than silently accepting. ALTER TABLE incidents ADD CONSTRAINT incidents_ack_actor_xor_chk CHECK ( acknowledged_by IS NULL OR acknowledged_by_service_account_id IS NULL ); ALTER TABLE incident_events ADD CONSTRAINT incident_events_actor_xor_chk CHECK ( user_id IS NULL OR service_account_id IS NULL ); CREATE INDEX incidents_acknowledged_by_service_account_id_idx ON incidents(acknowledged_by_service_account_id); CREATE INDEX incident_events_service_account_id_idx ON incident_events(service_account_id); -- assigned_to_service_account_id is deliberately not added here: it would sit -- unpopulated until handleIncidentAssign itself tracks an actor, which is a -- separate, pre-existing gap (it records the assignee today, never the -- actor, for humans either) tracked in its own follow-up issue.