--- name: edr-db description: Query, EXPLAIN-validate, and inspect the remote EDR freight dev database. Use whenever you need to check data, verify a raw SQL statement before shipping it, list a table's columns, check schema drift, or see which migrations are recorded. psql is NOT installed on this machine — this runner is the sanctioned path. Triggers - "check the db", "query edr_dev", "does column X exist", "validate this SQL", "is migration recorded", "seed check", diagnosing a 400/500 whose cause may be data or schema. --- # EDR dev-DB runner One script, runs from anywhere in the repo (resolves `pg` from `apps/edr-freight-api`): ```bash node .claude/skills/edr-db/query.cjs "SELECT ... " # run SQL, console.table output node .claude/skills/edr-db/query.cjs explain "SELECT ..." # EXPLAIN-validate only (no rows touched) node .claude/skills/edr-db/query.cjs columns # freight.
column list node .claude/skills/edr-db/query.cjs migrations [like] # public.migrations rows (newest first) node .claude/skills/edr-db/query.cjs drift
# bare column names, for diffing vs the entity ``` Connection comes from `DB_HOST` / `DB_PORT` / `DB_USER` / `DB_PASSWORD` / `DB_NAME`, defaulting to the shared dev database (`edr_dev`). ## Rules that go with it - **HARD RULE: every raw SQL statement you write into a service must pass `explain` here before you ship it.** A typo'd column is a runtime 500 the type-checker cannot catch. - Never assume a recorded migration applied — check `migrations ` **and** `columns
` together. Recorded-but-absent = schema drift; fix with a NEW repair migration (idempotent DDL, no-op `down()`), never by editing the recorded one. - Writes to dev data are fine for seeding/diagnosis but keep them idempotent (`WHERE NOT EXISTS` guards) — watch-mode API instances race `migrationsRun`, and non-idempotent statements have double-run here before. - Timestamps for new migrations: must be unique across `src/migrations/` AND higher than `SELECT max(timestamp) FROM public.migrations`. ## Diagnosing a pasted 400/500 (the recurring loop) 1. Find the route: grep the path segment in `apps/edr-freight-api/src/modules/*/**.controller.ts`. 2. Read the service method — list its guard `throw`s. Most "bugs" are a guard working as designed (handover unsigned, fee unpaid, not PAID, wrong direction). 3. Check the actual DB state for that record with this runner. 4. Only then decide: guard doing its job (fix the UI affordance) vs real defect.