feat(schema): foreign keys for every alerts relation (changesets 30-53, after #32) #35

Merged
KofTwentyTwo merged 5 commits from feature/foreign-keys into develop 2026-10-14 23:00:43 +00:00
5 Commits
Author SHA1 Message Date
james.maesandClaude Opus 5.5 adb7fd7cec Merge feature/alerts-join-indexes (now with develop) into feature/foreign-keys
develop owns qbit-alerts:29 and the join indexes are now :30, so the
foreign-key changesets move from 30-53 to 31-54. Constraint and index
names are unchanged. Changesets 32-54 use PostgreSQL-only SQL
(row_to_json), so they carry dbms:postgresql and the H2 tests skip them.
The H2 digest test and AlertsForeignKeysTest's pre-FK cut now stop
before :31.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:52:37 -05:00
james.maesandClaude Opus 5.5 28545fa126 Merge origin/develop into feature/alerts-join-indexes
develop now owns qbit-alerts:29 (in_app_min_severity), so the join-index
changeset becomes qbit-alerts:30. Index names are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:50:41 -05:00
james.maesandClaude Opus 5.5 6e70e02623 test(schema): PostgreSQL guardrail for foreign keys on every declared relation
AlertsForeignKeysTest applies the shipped changelog with Liquibase to
PostgreSQL 17 (Testcontainers) and asserts every one-to-many join and table
possible-value field has a foreign key with the decided ON DELETE rule (or
an exemption with a reason), every FK column leads an index, orphans are
quarantined then nulled or deleted, re-runs are no-ops, and a constraint a
host already added is skipped. The H2 digest-migration test stops before
the PostgreSQL-only FK changesets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 16:18:31 -05:00
james.maesandClaude Opus 5.5 2e1e22cdd4 feat(schema): foreign keys for every alerts relation, orphan-safe (changesets 30-53)
Changeset 30 indexes the FK columns no earlier index leads with. Changesets
31-53 add one constraint each, fk_<child_table>_<child_column>, guarded by a
precondition on the name so a host that already added it marks it ran. Each
first records orphans in qqq_fk_quarantine, then nulls a nullable column or
deletes a row whose column is NOT NULL (full row kept in row_data).

ON DELETE: CASCADE for owned detail rows (timeline, record refs, delivery
log of an alert, team members, notification recipients, escalation steps);
SET NULL for optional pointers (group, parent group, owner/assigned team,
monitor, subscription, alert event, escalation policy); RESTRICT for config
that must not vanish under live data (alert type, a channel or team that a
subscription, delivery or escalation step uses).

The H2 test schema carries the same constraints and indexes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 16:18:30 -05:00
james.maesandClaude Opus 5.5 b54d8d103c fix(schema): index the join child columns monitor_id, alert_type_id and group_id
Changeset 29 adds alerts_alert (monitor_id, status), alerts_monitor
(alert_type_id) and alerts_type (group_id). MonitorEvaluator looks up a
per-record monitor's open alerts by monitor_id + status on every
evaluation, and the type and group record pages list children by these
columns. A new test checks that every one-to-many join's child column
leads an index in the shipped changelog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 15:18:11 -05:00