diff --git a/crates/manager-core/migrations/0046_trigger_name.sql b/crates/manager-core/migrations/0046_trigger_name.sql new file mode 100644 index 0000000..a941aa8 --- /dev/null +++ b/crates/manager-core/migrations/0046_trigger_name.sql @@ -0,0 +1,29 @@ +-- Trigger `name` (§4.5): an explicit per-app identifier that becomes the +-- manifest merge/upsert key (Step B switches the apply diff to key on it). +-- Until now triggers were identified only by their per-kind semantic tuple, +-- so the declarative tool could only Create/Delete them, never Update. +-- +-- Backfill existing rows with `{kind}-{n}` (n = per-(app,kind) sequence by +-- creation order) — the spec-sanctioned fallback when there's no cleaner +-- entity token. Then enforce NOT NULL + UNIQUE(app_id, name). + +-- A `gen_random_uuid()` default keeps existing INSERTs (which don't yet +-- supply a name) valid and unique — the manager-core write paths start +-- providing meaningful names in the follow-up; new rows until then get a +-- harmless unique placeholder. +ALTER TABLE triggers + ADD COLUMN name TEXT NOT NULL DEFAULT gen_random_uuid()::text; + +-- Rewrite the just-defaulted existing rows to the readable `{kind}-{n}` form. +UPDATE triggers t +SET name = sub.nm +FROM ( + SELECT id, + kind || '-' || row_number() OVER ( + PARTITION BY app_id, kind ORDER BY created_at, id + ) AS nm + FROM triggers +) sub +WHERE t.id = sub.id; + +CREATE UNIQUE INDEX triggers_app_name_uniq ON triggers (app_id, name);