Files
edr-platform/.claude/skills/edr-db/SKILL.md
2026-07-09 15:37:06 +00:00

2.5 KiB

name, description
name description
edr-db 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):

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 <table>       # freight.<table> column list
node .claude/skills/edr-db/query.cjs migrations [like]     # public.migrations rows (newest first)
node .claude/skills/edr-db/query.cjs drift <table>         # 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 <name> and columns <table> 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 throws. 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.