+++
title = "Document D1 schema migration workflow — how to apply SQL schema changes to D1 in CI/CD"
priority = 7
status = "todo"
ticket_type = "task"
dependencies = ["d0da0b", "bb1514"]
+++
Infrastructure is managed with OpenTofu using the Cloudflare provider. Configuration lives in `infra/`. Resources include a Cloudflare Worker (API), Cloudflare D1 database (bound to the worker), and a Cloudflare Pages project (UI frontend).
Cloudflare D1 uses SQL migrations. Because the Worker runs in the Cloudflare runtime (not a standard server), migrations must be applied via a separate mechanism.
TRIAGE 5c0c64 resolved: the chosen strategy is **Option 2 — separate wrangler step**. Schema SQL lives at `infra/schema.sql` (ticket bb1514). No `null_resource`, no startup migration from the Workers handler.
For local dev/tests, `NativeRepository::run_migrations()` (ticket 00aff0) calls `execute_batch` via rusqlite — no manual step needed there.
Document the D1 schema migration workflow in `infra/README.md`:
1. The canonical schema file location: `infra/schema.sql`
2. How to apply the initial schema SQL to D1 after first `tofu apply`:
`wrangler d1 execute quotesdb --file infra/schema.sql --remote`
3. How to apply incremental migrations (numbered files under `infra/migrations/`)
4. How to apply migrations in CI/CD (two-step: `tofu apply` then `wrangler d1 execute`)
5. How local dev/tests work (NativeRepository handles this automatically, no manual step)
6. Cross-reference: TRIAGE decisions from 5c0c64 and 580e66
- TRIAGE 5c0c64 is resolved — the strategy is a separate wrangler step. Document accordingly.
- `infra/schema.sql` must exist (ticket bb1514) before writing the exact wrangler command.
- D1 resource must be defined (ticket d0da0b) to confirm the database name "quotesdb".
- Do NOT document `null_resource` or startup migrations from the Workers handler.
`docs(quotesdb): document D1 schema migration workflow in infra/README.md`