Task 1.5 — Event-participation collections
Five collections + 10 relations + 5 composite unique constraints,
captured into snapshots/schema.yaml (now 105 KB, up from 53 KB).
Collections:
- events — 11 fields incl. organization_id M2O, discipline enum
(rally / time-trial / regatta / trail-run / hike),
starts_at/ends_at required.
- classes — 8 fields incl. event_id M2O, code unique within event.
- entries — 11 fields incl. event_id/vehicle_id (nullable for foot
races) /class_id M2O, race_number, status enum with
8 lifecycle values, archive on `withdrawn`.
team_id deliberately omitted (Phase 2+).
- entry_crew — junction with role enum
(pilot/co-pilot/navigator/mechanic/rider/runner/hiker).
- entry_devices — junction with optional assigned_user_id (panic button
body-wear); ON DELETE SET NULL on that field since
user removal shouldn't block the device record.
10 M2O relations wired, all ON DELETE RESTRICT except
entry_devices.assigned_user_id (SET NULL).
db-init/005_event_participation_unique_constraints.sql adds composite
UNIQUE on:
events (organization_id, slug)
classes (event_id, code)
entries (event_id, race_number)
entry_crew (entry_id, user_id)
entry_devices (entry_id, device_id)
---
Destructive-apply incident (recovered):
First attempt at this task hit a real foot-gun. After creating the 5
collections via MCP, we ran `compose build && up -d`. The image rebuild
baked in the snapshot from task 1.4 (only 7 collections). Boot's
schema-apply step ran `directus schema apply --yes` against that stale
snapshot — saw the 5 new collections in the DB but not in the snapshot
— DELETED THEM, taking the constraints with them.
Recovery: re-created the 5 collections + 10 relations via MCP, ran the
ALTER TABLE statements directly via psql to restore the constraints,
ran schema:snapshot BEFORE any further restart so the YAML reflects
the live state. Documented the operator rule (never rebuild with
uncommitted schema changes) inline in the task spec and in the
directus wiki entity page (separate commit in trm/docs).
Phase 3 hardening on the radar: DIRECTUS_SCHEMA_APPLY_MODE env var
with auto/dry-run/skip modes so dev environments default to non-
destructive behavior.
ROADMAP marks 1.5 done. Phase 1 progress: 7/9 tasks complete (1.1–1.7);
1.8, 1.9 remain.
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
-- 005_event_participation_unique_constraints.sql
|
||||
-- Composite UNIQUE constraints on the event-participation collections.
|
||||
--
|
||||
-- Same rationale as 004: Directus's `is_unique` flag is single-column only;
|
||||
-- composite uniqueness lives in db-init/ because the snapshot YAML format
|
||||
-- does not capture multi-column unique constraints.
|
||||
--
|
||||
-- Owned by: task 1.5 (event-participation collections).
|
||||
|
||||
ALTER TABLE events
|
||||
ADD CONSTRAINT events_org_slug_unique
|
||||
UNIQUE (organization_id, slug);
|
||||
|
||||
ALTER TABLE classes
|
||||
ADD CONSTRAINT classes_event_code_unique
|
||||
UNIQUE (event_id, code);
|
||||
|
||||
ALTER TABLE entries
|
||||
ADD CONSTRAINT entries_event_race_number_unique
|
||||
UNIQUE (event_id, race_number);
|
||||
|
||||
ALTER TABLE entry_crew
|
||||
ADD CONSTRAINT entry_crew_entry_user_unique
|
||||
UNIQUE (entry_id, user_id);
|
||||
|
||||
ALTER TABLE entry_devices
|
||||
ADD CONSTRAINT entry_devices_entry_device_unique
|
||||
UNIQUE (entry_id, device_id);
|
||||
|
||||
-- -------------------------------------------------------------------------
|
||||
-- Assertion block: verify all five constraints landed.
|
||||
-- -------------------------------------------------------------------------
|
||||
DO $$ BEGIN
|
||||
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'events_org_slug_unique'
|
||||
) THEN
|
||||
RAISE EXCEPTION 'events composite unique constraint (org, slug) missing';
|
||||
END IF;
|
||||
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'classes_event_code_unique'
|
||||
) THEN
|
||||
RAISE EXCEPTION 'classes composite unique constraint (event, code) missing';
|
||||
END IF;
|
||||
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'entries_event_race_number_unique'
|
||||
) THEN
|
||||
RAISE EXCEPTION 'entries composite unique constraint (event, race_number) missing';
|
||||
END IF;
|
||||
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'entry_crew_entry_user_unique'
|
||||
) THEN
|
||||
RAISE EXCEPTION 'entry_crew composite unique constraint (entry, user) missing';
|
||||
END IF;
|
||||
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'entry_devices_entry_device_unique'
|
||||
) THEN
|
||||
RAISE EXCEPTION 'entry_devices composite unique constraint (entry, device) missing';
|
||||
END IF;
|
||||
|
||||
END $$;
|
||||
Reference in New Issue
Block a user