-- Terdut Server schema. One baseline: the project has not shipped, so the -- migration history that led here (SQLite import, a Default team, per-team -- deadman configs later replaced by switches) is not carried. Later changes are -- new numbered files after this one. -- -- Timestamps are Unix epoch seconds in BIGINT columns throughout. CREATE TABLE alerts ( id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, fingerprint text NOT NULL, name text NOT NULL, status text NOT NULL, labels jsonb DEFAULT '{}'::jsonb NOT NULL, annotations jsonb DEFAULT '{}'::jsonb NOT NULL, starts_at bigint NOT NULL, ends_at bigint, generator_url text DEFAULT ''::text NOT NULL, received_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, archived_at bigint, resolution_source text, team_id bigint NOT NULL, integration_id bigint, CONSTRAINT alerts_status_check CHECK ((status = ANY (ARRAY['firing'::text, 'resolved'::text]))) ); CREATE TABLE api_keys ( id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, user_id bigint NOT NULL, key_hash text NOT NULL, name text NOT NULL, created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, last_used_at bigint, expires_at bigint ); CREATE TABLE deadman_switches ( id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, team_id bigint NOT NULL, name text NOT NULL, matcher text NOT NULL, timeout_seconds bigint NOT NULL, severity text DEFAULT 'critical'::text NOT NULL, created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, CONSTRAINT deadman_switches_timeout_seconds_check CHECK ((timeout_seconds > 0)) ); CREATE TABLE device_logins ( device_hash text NOT NULL, user_code text NOT NULL, status text DEFAULT 'pending'::text NOT NULL, user_id bigint, expires_at bigint NOT NULL, last_polled_at bigint DEFAULT 0 NOT NULL, CONSTRAINT device_logins_status_check CHECK ((status = ANY (ARRAY['pending'::text, 'approved'::text, 'denied'::text]))) ); CREATE TABLE escalation_levels ( id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, team_id bigint NOT NULL, "position" bigint NOT NULL, timeout_seconds bigint NOT NULL, CONSTRAINT escalation_levels_timeout_seconds_check CHECK ((timeout_seconds > 0)) ); CREATE TABLE escalation_policies ( team_id bigint NOT NULL, repeat_count bigint DEFAULT 0 NOT NULL, fallback_topic text DEFAULT ''::text NOT NULL, updated_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, CONSTRAINT escalation_policies_repeat_count_check CHECK (((repeat_count >= 0) AND (repeat_count <= 10))) ); CREATE TABLE escalation_targets ( id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, level_id bigint NOT NULL, kind text NOT NULL, user_id bigint, CONSTRAINT escalation_targets_check CHECK ((((kind = 'user'::text) AND (user_id IS NOT NULL)) OR ((kind = 'oncall'::text) AND (user_id IS NULL)))), CONSTRAINT escalation_targets_kind_check CHECK ((kind = ANY (ARRAY['user'::text, 'oncall'::text]))) ); CREATE TABLE incident_ack_tokens ( token_hash text NOT NULL, incident_id bigint NOT NULL, user_id bigint NOT NULL, created_at bigint NOT NULL, expires_at bigint NOT NULL ); CREATE TABLE incident_alerts ( incident_id bigint NOT NULL, alert_id bigint NOT NULL, added_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL ); CREATE TABLE incident_events ( id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, incident_id bigint NOT NULL, type text NOT NULL, user_id bigint, alert_id bigint, detail text, created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, service_account_id bigint, actor_user_id bigint, actor_service_account_id bigint, CONSTRAINT incident_events_actor_xor_chk CHECK (((user_id IS NULL) OR (service_account_id IS NULL))), CONSTRAINT incident_events_assign_actor_xor_chk CHECK (((actor_user_id IS NULL) OR (actor_service_account_id IS NULL))) ); CREATE TABLE incidents ( id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, group_key text NOT NULL, title text NOT NULL, group_labels jsonb DEFAULT '{}'::jsonb NOT NULL, status text NOT NULL, severity text, triggered_at bigint NOT NULL, acknowledged_by bigint, acknowledged_at bigint, assigned_to bigint, snoozed_until bigint, resolved_at bigint, resolution_source text, archived_at bigint, team_id bigint NOT NULL, escalation_level bigint DEFAULT 0 NOT NULL, escalation_level_at bigint, escalation_round bigint DEFAULT 0 NOT NULL, signature text DEFAULT ''::text NOT NULL, acknowledged_by_service_account_id bigint, CONSTRAINT incidents_ack_actor_xor_chk CHECK (((acknowledged_by IS NULL) OR (acknowledged_by_service_account_id IS NULL))), CONSTRAINT incidents_status_check CHECK ((status = ANY (ARRAY['triggered'::text, 'acknowledged'::text, 'resolved'::text]))) ); CREATE TABLE integrations ( id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, team_id bigint NOT NULL, kind text NOT NULL, name text NOT NULL, key_hash text NOT NULL, created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, last_used_at bigint, CONSTRAINT integrations_kind_check CHECK ((kind = 'alertmanager'::text)) ); CREATE TABLE invites ( id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, token_hash text NOT NULL, team_id bigint NOT NULL, role text NOT NULL, created_by bigint, created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, expires_at bigint NOT NULL, max_uses bigint DEFAULT 1 NOT NULL, uses bigint DEFAULT 0 NOT NULL, revoked_at bigint, CONSTRAINT invites_max_uses_check CHECK (((max_uses > 0) AND (max_uses <= 100))), CONSTRAINT invites_role_check CHECK ((role = ANY (ARRAY['owner'::text, 'member'::text]))) ); CREATE TABLE notifications ( id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, incident_id bigint NOT NULL, user_id bigint, topic text NOT NULL, kind text NOT NULL, created_at bigint NOT NULL, send_after bigint NOT NULL, attempts bigint DEFAULT 0 NOT NULL, sent_at bigint, last_error text, CONSTRAINT notifications_kind_check CHECK ((kind = ANY (ARRAY['triggered'::text, 'reminder'::text, 'resolved'::text, 'escalated'::text]))) ); CREATE TABLE oidc_logins ( state_hash text NOT NULL, nonce text NOT NULL, pkce_verifier text NOT NULL, expires_at bigint NOT NULL, next text DEFAULT '/'::text NOT NULL ); CREATE TABLE rate_limit_counters ( key text NOT NULL, window_start bigint NOT NULL, count integer NOT NULL ); CREATE TABLE schedule_entries ( id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, user_id bigint NOT NULL, date text NOT NULL, created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, team_id bigint NOT NULL ); CREATE TABLE service_account_keys ( id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, service_account_id bigint NOT NULL, key_hash text NOT NULL, name text NOT NULL, created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, last_used_at bigint ); CREATE TABLE service_accounts ( id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, name text NOT NULL, scope text NOT NULL, team_id bigint, created_by bigint, created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, CONSTRAINT service_accounts_scope_check CHECK ((scope = ANY (ARRAY['instance'::text, 'team'::text]))), CONSTRAINT service_accounts_scope_team_id_chk CHECK ((((scope = 'team'::text) AND (team_id IS NOT NULL)) OR ((scope = 'instance'::text) AND (team_id IS NULL)))) ); CREATE TABLE sessions ( id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, token_hash text NOT NULL, user_id bigint NOT NULL, created_at bigint NOT NULL, last_seen_at bigint NOT NULL, expires_at bigint NOT NULL, user_agent text, max_expires_at bigint ); CREATE TABLE settings ( key text NOT NULL, value text NOT NULL, updated_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL ); CREATE TABLE team_members ( team_id bigint NOT NULL, user_id bigint NOT NULL, role text NOT NULL, joined_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, source text DEFAULT 'manual'::text NOT NULL, CONSTRAINT team_members_role_check CHECK ((role = ANY (ARRAY['owner'::text, 'member'::text]))), CONSTRAINT team_members_source_check CHECK ((source = ANY (ARRAY['manual'::text, 'oidc'::text]))) ); CREATE TABLE teams ( id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, name text NOT NULL, created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, oidc_member_group text, oidc_owner_group text, -- A stable identity for a team managed by automation (terdut-operator: -- "/" of its TerdutTeam), so it can find or recreate its own -- team without trusting a display name. NULL for a team a person made. external_id text ); CREATE TABLE user_identities ( id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, user_id bigint NOT NULL, issuer text NOT NULL, subject text NOT NULL, created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, last_login_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL ); CREATE TABLE users ( id bigint GENERATED BY DEFAULT AS IDENTITY NOT NULL, username text NOT NULL, email text NOT NULL, created_at bigint DEFAULT (floor(EXTRACT(epoch FROM now())))::bigint NOT NULL, ntfy_topic text, password_hash text, is_admin boolean DEFAULT false NOT NULL, disabled_at bigint, invited_via bigint, onboarding_dismissed_at bigint, admin_source text DEFAULT 'manual'::text NOT NULL, CONSTRAINT users_admin_source_check CHECK ((admin_source = ANY (ARRAY['manual'::text, 'oidc'::text]))) ); ALTER TABLE alerts ADD CONSTRAINT alerts_pkey PRIMARY KEY (id); ALTER TABLE api_keys ADD CONSTRAINT api_keys_key_hash_key UNIQUE (key_hash); ALTER TABLE api_keys ADD CONSTRAINT api_keys_pkey PRIMARY KEY (id); ALTER TABLE deadman_switches ADD CONSTRAINT deadman_switches_pkey PRIMARY KEY (id); ALTER TABLE device_logins ADD CONSTRAINT device_logins_pkey PRIMARY KEY (device_hash); ALTER TABLE device_logins ADD CONSTRAINT device_logins_user_code_key UNIQUE (user_code); ALTER TABLE escalation_levels ADD CONSTRAINT escalation_levels_pkey PRIMARY KEY (id); ALTER TABLE escalation_levels ADD CONSTRAINT escalation_levels_team_id_position_key UNIQUE (team_id, "position"); ALTER TABLE escalation_policies ADD CONSTRAINT escalation_policies_pkey PRIMARY KEY (team_id); ALTER TABLE escalation_targets ADD CONSTRAINT escalation_targets_pkey PRIMARY KEY (id); ALTER TABLE incident_ack_tokens ADD CONSTRAINT incident_ack_tokens_pkey PRIMARY KEY (token_hash); ALTER TABLE incident_alerts ADD CONSTRAINT incident_alerts_pkey PRIMARY KEY (incident_id, alert_id); ALTER TABLE incident_events ADD CONSTRAINT incident_events_pkey PRIMARY KEY (id); ALTER TABLE incidents ADD CONSTRAINT incidents_pkey PRIMARY KEY (id); ALTER TABLE integrations ADD CONSTRAINT integrations_key_hash_key UNIQUE (key_hash); ALTER TABLE integrations ADD CONSTRAINT integrations_pkey PRIMARY KEY (id); ALTER TABLE invites ADD CONSTRAINT invites_pkey PRIMARY KEY (id); ALTER TABLE invites ADD CONSTRAINT invites_token_hash_key UNIQUE (token_hash); ALTER TABLE notifications ADD CONSTRAINT notifications_pkey PRIMARY KEY (id); ALTER TABLE oidc_logins ADD CONSTRAINT oidc_logins_pkey PRIMARY KEY (state_hash); ALTER TABLE rate_limit_counters ADD CONSTRAINT rate_limit_counters_pkey PRIMARY KEY (key); ALTER TABLE schedule_entries ADD CONSTRAINT schedule_entries_pkey PRIMARY KEY (id); ALTER TABLE service_account_keys ADD CONSTRAINT service_account_keys_key_hash_key UNIQUE (key_hash); ALTER TABLE service_account_keys ADD CONSTRAINT service_account_keys_pkey PRIMARY KEY (id); ALTER TABLE service_accounts ADD CONSTRAINT service_accounts_name_key UNIQUE (name); ALTER TABLE service_accounts ADD CONSTRAINT service_accounts_pkey PRIMARY KEY (id); ALTER TABLE sessions ADD CONSTRAINT sessions_pkey PRIMARY KEY (id); ALTER TABLE sessions ADD CONSTRAINT sessions_token_hash_key UNIQUE (token_hash); ALTER TABLE settings ADD CONSTRAINT settings_pkey PRIMARY KEY (key); ALTER TABLE team_members ADD CONSTRAINT team_members_pkey PRIMARY KEY (team_id, user_id); ALTER TABLE teams ADD CONSTRAINT teams_name_key UNIQUE (name); ALTER TABLE teams ADD CONSTRAINT teams_external_id_key UNIQUE (external_id); ALTER TABLE teams ADD CONSTRAINT teams_pkey PRIMARY KEY (id); ALTER TABLE user_identities ADD CONSTRAINT user_identities_issuer_subject_key UNIQUE (issuer, subject); ALTER TABLE user_identities ADD CONSTRAINT user_identities_pkey PRIMARY KEY (id); ALTER TABLE users ADD CONSTRAINT users_email_key UNIQUE (email); ALTER TABLE users ADD CONSTRAINT users_pkey PRIMARY KEY (id); ALTER TABLE users ADD CONSTRAINT users_username_key UNIQUE (username); CREATE INDEX alerts_archived_at_idx ON alerts USING btree (archived_at); CREATE INDEX alerts_integration_idx ON alerts USING btree (integration_id, received_at) WHERE (integration_id IS NOT NULL); CREATE INDEX alerts_name_idx ON alerts USING btree (name); CREATE INDEX alerts_received_at_idx ON alerts USING btree (received_at DESC); CREATE INDEX alerts_status_idx ON alerts USING btree (status); CREATE UNIQUE INDEX alerts_team_fingerprint_idx ON alerts USING btree (team_id, fingerprint); CREATE INDEX alerts_team_received_idx ON alerts USING btree (team_id, received_at DESC); CREATE INDEX deadman_switches_team_idx ON deadman_switches USING btree (team_id); CREATE INDEX device_logins_expires_idx ON device_logins USING btree (expires_at); CREATE INDEX escalation_targets_level_idx ON escalation_targets USING btree (level_id); CREATE INDEX idx_sessions_user ON sessions USING btree (user_id); CREATE INDEX incident_ack_tokens_expires_idx ON incident_ack_tokens USING btree (expires_at); CREATE INDEX incident_alerts_alert_id_idx ON incident_alerts USING btree (alert_id); CREATE INDEX incident_events_actor_service_account_id_idx ON incident_events USING btree (actor_service_account_id); CREATE INDEX incident_events_actor_user_id_idx ON incident_events USING btree (actor_user_id); CREATE INDEX incident_events_incident_idx ON incident_events USING btree (incident_id, created_at); CREATE INDEX incident_events_service_account_id_idx ON incident_events USING btree (service_account_id); CREATE INDEX incidents_acknowledged_by_service_account_id_idx ON incidents USING btree (acknowledged_by_service_account_id); CREATE INDEX incidents_archived_at_idx ON incidents USING btree (archived_at); CREATE INDEX incidents_escalation_idx ON incidents USING btree (escalation_level_at) WHERE ((resolved_at IS NULL) AND (status = 'triggered'::text)); CREATE UNIQUE INDEX incidents_open_group_key_idx ON incidents USING btree (team_id, group_key) WHERE (resolved_at IS NULL); CREATE INDEX incidents_signature_idx ON incidents USING btree (team_id, signature, triggered_at DESC); CREATE INDEX incidents_status_idx ON incidents USING btree (status); CREATE INDEX incidents_team_triggered_idx ON incidents USING btree (team_id, triggered_at DESC); CREATE INDEX incidents_triggered_at_idx ON incidents USING btree (triggered_at DESC); CREATE INDEX integrations_team_idx ON integrations USING btree (team_id); -- A name identifies an integration (and a switch) within its team, so a client -- that manages them declaratively can look one up by name instead of listing -- and matching. CREATE UNIQUE INDEX integrations_team_name_key ON integrations (team_id, name); CREATE UNIQUE INDEX deadman_switches_team_name_key ON deadman_switches (team_id, name); CREATE INDEX invites_team_idx ON invites USING btree (team_id); CREATE INDEX notifications_incident_idx ON notifications USING btree (incident_id, id DESC); CREATE INDEX notifications_pending_idx ON notifications USING btree (send_after) WHERE (sent_at IS NULL); CREATE INDEX oidc_logins_expires_idx ON oidc_logins USING btree (expires_at); CREATE INDEX schedule_entries_date_idx ON schedule_entries USING btree (date); CREATE UNIQUE INDEX schedule_entries_team_date_idx ON schedule_entries USING btree (team_id, date); CREATE INDEX service_account_keys_service_account_id_idx ON service_account_keys USING btree (service_account_id); CREATE INDEX service_accounts_team_id_idx ON service_accounts USING btree (team_id); CREATE INDEX team_members_user_idx ON team_members USING btree (user_id); CREATE INDEX user_identities_user_idx ON user_identities USING btree (user_id); CREATE INDEX users_is_admin_idx ON users USING btree (is_admin) WHERE is_admin; ALTER TABLE alerts ADD CONSTRAINT alerts_integration_id_fkey FOREIGN KEY (integration_id) REFERENCES integrations(id) ON DELETE SET NULL; ALTER TABLE alerts ADD CONSTRAINT alerts_team_id_fkey FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE; ALTER TABLE api_keys ADD CONSTRAINT api_keys_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; ALTER TABLE deadman_switches ADD CONSTRAINT deadman_switches_team_id_fkey FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE; ALTER TABLE device_logins ADD CONSTRAINT device_logins_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; ALTER TABLE escalation_levels ADD CONSTRAINT escalation_levels_team_id_fkey FOREIGN KEY (team_id) REFERENCES escalation_policies(team_id) ON DELETE CASCADE; ALTER TABLE escalation_policies ADD CONSTRAINT escalation_policies_team_id_fkey FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE; ALTER TABLE escalation_targets ADD CONSTRAINT escalation_targets_level_id_fkey FOREIGN KEY (level_id) REFERENCES escalation_levels(id) ON DELETE CASCADE; ALTER TABLE escalation_targets ADD CONSTRAINT escalation_targets_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; ALTER TABLE incident_ack_tokens ADD CONSTRAINT incident_ack_tokens_incident_id_fkey FOREIGN KEY (incident_id) REFERENCES incidents(id) ON DELETE CASCADE; ALTER TABLE incident_ack_tokens ADD CONSTRAINT incident_ack_tokens_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; ALTER TABLE incident_alerts ADD CONSTRAINT incident_alerts_alert_id_fkey FOREIGN KEY (alert_id) REFERENCES alerts(id) ON DELETE CASCADE; ALTER TABLE incident_alerts ADD CONSTRAINT incident_alerts_incident_id_fkey FOREIGN KEY (incident_id) REFERENCES incidents(id) ON DELETE CASCADE; ALTER TABLE incident_events ADD CONSTRAINT incident_events_actor_service_account_id_fkey FOREIGN KEY (actor_service_account_id) REFERENCES service_accounts(id) ON DELETE SET NULL; ALTER TABLE incident_events ADD CONSTRAINT incident_events_actor_user_id_fkey FOREIGN KEY (actor_user_id) REFERENCES users(id) ON DELETE SET NULL; ALTER TABLE incident_events ADD CONSTRAINT incident_events_alert_id_fkey FOREIGN KEY (alert_id) REFERENCES alerts(id) ON DELETE SET NULL; ALTER TABLE incident_events ADD CONSTRAINT incident_events_incident_id_fkey FOREIGN KEY (incident_id) REFERENCES incidents(id) ON DELETE CASCADE; ALTER TABLE incident_events ADD CONSTRAINT incident_events_service_account_id_fkey FOREIGN KEY (service_account_id) REFERENCES service_accounts(id) ON DELETE SET NULL; ALTER TABLE incident_events ADD CONSTRAINT incident_events_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL; ALTER TABLE incidents ADD CONSTRAINT incidents_acknowledged_by_fkey FOREIGN KEY (acknowledged_by) REFERENCES users(id) ON DELETE SET NULL; ALTER TABLE incidents ADD CONSTRAINT incidents_acknowledged_by_service_account_id_fkey FOREIGN KEY (acknowledged_by_service_account_id) REFERENCES service_accounts(id) ON DELETE SET NULL; ALTER TABLE incidents ADD CONSTRAINT incidents_assigned_to_fkey FOREIGN KEY (assigned_to) REFERENCES users(id) ON DELETE SET NULL; ALTER TABLE incidents ADD CONSTRAINT incidents_team_id_fkey FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE; ALTER TABLE integrations ADD CONSTRAINT integrations_team_id_fkey FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE; ALTER TABLE invites ADD CONSTRAINT invites_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL; ALTER TABLE invites ADD CONSTRAINT invites_team_id_fkey FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE; ALTER TABLE notifications ADD CONSTRAINT notifications_incident_id_fkey FOREIGN KEY (incident_id) REFERENCES incidents(id) ON DELETE CASCADE; ALTER TABLE notifications ADD CONSTRAINT notifications_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL; ALTER TABLE schedule_entries ADD CONSTRAINT schedule_entries_team_id_fkey FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE; ALTER TABLE schedule_entries ADD CONSTRAINT schedule_entries_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; ALTER TABLE service_account_keys ADD CONSTRAINT service_account_keys_service_account_id_fkey FOREIGN KEY (service_account_id) REFERENCES service_accounts(id) ON DELETE CASCADE; ALTER TABLE service_accounts ADD CONSTRAINT service_accounts_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL; ALTER TABLE service_accounts ADD CONSTRAINT service_accounts_team_id_fkey FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE; ALTER TABLE sessions ADD CONSTRAINT sessions_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; ALTER TABLE team_members ADD CONSTRAINT team_members_team_id_fkey FOREIGN KEY (team_id) REFERENCES teams(id) ON DELETE CASCADE; ALTER TABLE team_members ADD CONSTRAINT team_members_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; ALTER TABLE user_identities ADD CONSTRAINT user_identities_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; ALTER TABLE users ADD CONSTRAINT users_invited_via_fkey FOREIGN KEY (invited_via) REFERENCES invites(id) ON DELETE SET NULL;