+++ title = "Document D1 schema migration workflow — how to apply SQL schema changes to D1 in CI/CD" priority = 7 status = "done" 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`