Files
familysync/.planning/quick/260610-cr8-adopt-drizzle-generate-migrate-workflow-/260610-cr8-PLAN.md
T
Lucas Berger 982438dc10 style(13-03): apply Prettier formatting across repo
Mechanical reformat — no logic changes. 398 files changed, 19125
insertions(+), 16457 deletions(-). Prettier 3.8.4 with .prettierrc
(singleQuote:true, semi:true, tabWidth:2, trailingComma:all,
printWidth:100). Isolated per D-13-08 for reviewability.
2026-06-11 20:35:18 -04:00

121 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
phase: quick-260610-cr8
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- apps/api/package.json
- docs/deployment.md
autonomous: true
requirements: []
must_haves:
truths:
- 'Running `pnpm --filter @familysync/api run db:push` fails — the script no longer exists'
- 'docs/deployment.md instructs operators to apply schema via `drizzle-kit migrate`, not `drizzle-kit push`'
- 'docs/deployment.md warns operators NOT to use `drizzle-kit push` on MariaDB and explains why (false destructive diff)'
- "`drizzle-kit generate` against the current schema produces no spurious destructive diff (reports 'No schema changes' or only an intended additive delta — never a truncate/drop)"
artifacts:
- path: 'apps/api/package.json'
provides: 'API scripts with db:push removed; db:generate + db:migrate retained as canonical workflow'
contains: 'db:migrate'
- path: 'docs/deployment.md'
provides: 'Schema-apply step + prod step repointed to generate/migrate with anti-push warning'
contains: 'drizzle-kit migrate'
key_links:
- from: 'docs/deployment.md Step 3'
to: 'apps/api/src/db/migrations'
via: 'drizzle-kit migrate applies committed migration SQL'
pattern: 'drizzle-kit migrate'
---
<objective>
Retire the `drizzle-kit push` foot-gun and make `drizzle-kit generate``drizzle-kit migrate` the only documented schema workflow.
`drizzle-kit push` produces a FALSE destructive diff against the populated MariaDB (mysql dialect misreads MariaDB 11.8 metadata → schedules truncate/recreate). The generate+migrate workflow is already in practical use (migrations `0000``0004` are committed and applied), so this task is cleanup, not adoption: remove the dangling `db:push` script and repoint the two `drizzle-kit push` instructions in the deployment docs, adding an explicit warning so a future operator does not reintroduce push.
Purpose: Prevent accidental data loss; lock in the mandated MariaDB-safe migration workflow (see memory drizzle-mariadb-push-unsafe; STATE decision D-Task5-DDL).
Output: `apps/api/package.json` with `db:push` removed; `docs/deployment.md` Steps 3 and 6 repointed to migrate with an anti-push warning; verified that `drizzle-kit generate` emits no spurious destructive diff.
</objective>
<execution_context>
@$HOME/.claude/gsd-core/workflows/execute-plan.md
@$HOME/.claude/gsd-core/templates/summary.md
</execution_context>
<context>
@.planning/STATE.md
@apps/api/package.json
@apps/api/drizzle.config.ts
@docs/deployment.md
@.planning/todos/pending/adopt-drizzle-migrations-workflow.md
# Hard constraints (do NOT violate):
# - Do NOT renumber, delete, or regenerate any existing migration SQL file or snapshot in
# apps/api/src/db/migrations/ (including the orphan 0001_calendars_user_url_unique.sql).
# - Do NOT run `db:migrate` or `db:push` against the live/dev DB — it holds real data.
# - `drizzle-kit generate` is safe: it diffs schema.ts against the JSON snapshots in meta/,
# never the live DB. It needs no DB connection.
</context>
<tasks>
<task type="auto">
<name>Task 1: Remove the db:push script from apps/api/package.json</name>
<files>apps/api/package.json</files>
<action>Delete the `"db:push": "drizzle-kit push"` line (currently line 13) from the `scripts` block. Leave `db:generate` and `db:migrate` untouched — they are the canonical workflow. Do not change any dependency versions. Ensure the resulting JSON is valid (no trailing comma where db:push was removed; db:generate becomes the entry following test:watch/typecheck).</action>
<verify>
<automated>cd /home/luc/Projects/familysync && node -e "const p=require('./apps/api/package.json'); if(p.scripts['db:push']) process.exit(1); if(!p.scripts['db:generate']||!p.scripts['db:migrate']) process.exit(2); console.log('ok: db:push removed, generate+migrate intact')"</automated>
</verify>
<done>apps/api/package.json parses as valid JSON; `scripts.db:push` is absent; `scripts.db:generate` and `scripts.db:migrate` are present and unchanged.</done>
</task>
<task type="auto">
<name>Task 2: Repoint deployment.md to generate+migrate and warn against push</name>
<files>docs/deployment.md</files>
<action>Two edits, plus an inline warning.
(1) Step 3 "Apply the database schema" (around lines 143-152): replace the `drizzle-kit push` command on line 150 with the migrate command. The body currently reads "Bring up MariaDB and push the Drizzle schema once" — rewrite to apply committed migrations instead. The new command, preserving the existing host-side env prefix, is: `pnpm --filter @familysync/api exec drizzle-kit migrate`. Add one sentence noting that schema CHANGES are authored with `pnpm --filter @familysync/api run db:generate` (diffs schema.ts against committed snapshots, never the live DB) and committed as SQL, then applied with `db:migrate`. Keep the existing `# verify: SHOW TABLES;` line.
(2) Step 6 line 206: change "then `drizzle-kit push` once (Step 3) against the prod DB" to "then `drizzle-kit migrate` once (Step 3) against the prod DB".
(3) Add a short warning callout near Step 3 stating: do NOT use `drizzle-kit push` on this MariaDB — the mysql dialect misreads MariaDB metadata and schedules a false truncate/recreate that wipes data; always use the committed-migration path (`db:generate` to author, `db:migrate` to apply). This addresses the root-cause foot-gun so the script is not reintroduced. Do NOT alter the line "The image does not auto-migrate." — programmatic migrate-on-boot is out of scope.</action>
<verify>
<automated>cd /home/luc/Projects/familysync && grep -q 'drizzle-kit migrate' docs/deployment.md && grep -q 'db:generate' docs/deployment.md && ! grep -Eq 'drizzle-kit push|db:push' docs/deployment.md && grep -iEq 'do not.*push|never.*push|not use .*push' docs/deployment.md && echo 'ok: migrate path + warning present, no push references remain'</automated>
</verify>
<done>docs/deployment.md contains no `drizzle-kit push` / `db:push` reference; both Step 3 and Step 6 reference `drizzle-kit migrate`; an explicit warning against using push on MariaDB is present with the data-loss rationale; the "image does not auto-migrate" sentence is unchanged.</done>
</task>
<task type="auto">
<name>Task 3: Dry-verify generate produces no spurious destructive diff</name>
<files>apps/api/src/db/migrations/</files>
<action>Run `pnpm --filter @familysync/api exec drizzle-kit generate` from the repo root. This is a DRY check: generate diffs schema.ts against the committed JSON snapshots (latest is meta/0004_snapshot.json), never the live DB, so it is safe and needs no DB connection. Expected outcome against the current synced schema: "No schema changes, nothing to migrate" and NO new SQL file written. If generate DOES emit a new throwaway migration file (e.g. a fresh NNNN_*.sql plus its snapshot), inspect it: it must contain only additive DDL (CREATE TABLE / ADD COLUMN / CREATE INDEX) and NEVER `truncate`/`DROP TABLE`/`DROP COLUMN`. Whether empty or additive, this generated file is a throwaway for the dry check — delete the newly created SQL file (and its newly created snapshot in meta/, if one was added) so migration history is left exactly as found. Do NOT commit any file this step produces. Do NOT renumber or touch the pre-existing 00000004 files or their snapshots. Do NOT run db:migrate.</action>
<verify>
<automated>cd /home/luc/Projects/familysync && before=$(ls apps/api/src/db/migrations/*.sql | wc -l) && out=$(pnpm --filter @familysync/api exec drizzle-kit generate 2>&1) && echo "$out" && echo "$out" | grep -iqE 'truncate|drop table|drop column' && { echo 'FAIL: destructive diff detected'; exit 1; }; after=$(ls apps/api/src/db/migrations/*.sql | wc -l); if [ "$after" -gt "$before" ]; then newfile=$(ls -t apps/api/src/db/migrations/*.sql | head -1); echo "throwaway generated: $newfile — removing"; rm -f "$newfile"; newsnap=$(ls -t apps/api/src/db/migrations/meta/*_snapshot.json | head -1); fi; git -C /home/luc/Projects/familysync status --porcelain apps/api/src/db/migrations/ | grep -q . && { echo 'FAIL: migration dir left dirty'; git -C /home/luc/Projects/familysync checkout -- apps/api/src/db/migrations/; exit 1; }; echo 'ok: no destructive diff; migration history unchanged'</automated>
</verify>
<done>`drizzle-kit generate` ran and produced no truncate/drop DDL; any throwaway output was removed; `git status` on apps/api/src/db/migrations/ is clean (history identical to pre-task state). The live DB was never contacted.</done>
</task>
</tasks>
<verification>
- `git diff` touches only apps/api/package.json and docs/deployment.md.
- No file under apps/api/src/db/migrations/ is added, deleted, renumbered, or modified.
- `grep -rn "db:push\|drizzle-kit push" apps/api/package.json docs/` returns nothing.
- `pnpm --filter @familysync/api run db:generate` and `db:migrate` remain the documented path.
</verification>
<success_criteria>
- `db:push` script removed from apps/api/package.json; JSON valid; generate+migrate scripts intact.
- docs/deployment.md Steps 3 and 6 apply schema via `drizzle-kit migrate`; an explicit anti-push warning with data-loss rationale is present; no remaining push references.
- Dry `drizzle-kit generate` confirmed to emit no spurious destructive diff, with migration history left byte-identical and the live DB never touched.
</success_criteria>
<output>
Create `.planning/quick/260610-cr8-adopt-drizzle-generate-migrate-workflow-/260610-cr8-SUMMARY.md` when done
</output>