# 2026-05-03 — CI + Reminder Lead Configurability > Companion to `BuildLog.md`. Predecessor: `2026-05-03-production-prep.md`. ## Milestone CI workflow at `.github/workflows/ci.yml` runs on every push/PR — lint, typecheck, tests against a real Postgres service container, plus a parallel docker-build job that exercises the `Dockerfile`. Reminder lead time is now env-configurable via `REMINDER_LEAD_MIN` (defaults to 1440 = 24h). ## What landed | Path | Role | |---|---| | `.github/workflows/ci.yml` | Two jobs: **test** (Postgres 16 service container with btree_gist + pgcrypto, prisma generate, prisma migrate deploy, lint, tsc, test) and **docker** (buildx with GHA cache, builds the runtime image without pushing). Concurrency-cancelled on superseded refs. | | `src/lib/reminders.ts` | `REMINDER_LEAD_MS` constant replaced with `reminderLeadMs()` reading `REMINDER_LEAD_MIN` env (default 1440). Set on both web and worker so producer-side scheduling and handler agree. | | `.env.example` | Added `REMINDER_LEAD_MIN=1440` example. | | `docs/deploy.md` | Documented `REMINDER_LEAD_MIN` in the optional env-vars table. | ## What's verified - `pnpm test` — **92/92 green** - `pnpm lint` — clean - `pnpm exec tsc --noEmit` — clean - CI workflow YAML is syntactically valid (Next.js / pnpm versions match repo). Live verification awaits a push to GitHub. ## Decisions ratified | Decision | Resolution | |---|---| | CI runner | `ubuntu-latest`. Standard, fast, free for public repos and reasonable for private. | | Postgres in CI | Service container `postgres:16` (matches our prod image), btree_gist + pgcrypto installed via a `psql` step. | | Test DB strategy in CI | One DB (`touchbase_test`); migrations applied via `prisma migrate deploy`; tests run against the same connection. Reason: simplest possible setup. Per-test parallel DBs is overkill at our test count. | | Docker job | Builds the image but **doesn't push**. Reason: no registry yet. Push gets added when we have a release process. | | Cache strategy | `pnpm` action caches the store via Node setup; `docker/build-push-action` uses GHA cache backend. Reason: keeps CI under 2 min on warm cache. | | Concurrency | Superseded runs cancelled on the same ref. Reason: avoid wasting CI minutes on stale commits. | | `REMINDER_LEAD_MIN` default | 1440 (24h) — same as the previous hardcoded value. Reason: behavior unchanged absent override. | | `REMINDER_LEAD_MIN` validation | Falls back to 1440 if env value is invalid (NaN, negative, missing). Reason: don't crash on a typo; do something reasonable. | | Where to set `REMINDER_LEAD_MIN` | Both web tier (producer) AND worker (handler reads via the same module). Documented in deploy.md. | ## Gotchas hit None. ## Open questions 1. Customer-visible brand name (still pending) 2. Currency 3. Stripe account ownership 4. Real domain + Caddy config 5. Image registry choice (still deferred) 6. **NEW**: When should CI start running — push to GitHub now, or wait until you cut a v1 branch? Doesn't affect code; just operational. ## Roadmap status - v1 feature-complete - Production prep done - **CI done 2026-05-03 (this session)** - Reminder lead time now configurable Outstanding gates before opening to real customers (operational, not code): 1. Live Stripe verification in test mode (when keys arrive) 2. Brand + policy decisions 3. First production deploy ## Recommended next step The remaining code-track polish items are all genuinely optional: - **Sentry / GlitchTip integration** for production error tracking. Half-day, more if we want sourcemaps uploaded by CI. Useful once we're live; not before. - **CSP / security headers** via Next config or Caddy. Half-day. Worth doing before opening to real customers. - **Rate limiting** on `/api/auth/*` and the booking endpoint. We currently rely on Postgres exclusion constraints to prevent double-booking races, but a determined caller could spam magic-link emails (Resend has its own quota, but still). Half-day to wire `@upstash/ratelimit` or a simple in-memory limiter. - **Audit logging for admin actions**. We have an `AuditLog` table from §4 of BuildLog.md but no calls to it. Half-day to wire into the admin CRUD actions. My pick if continuing: **rate limiting** (concrete safety win) or **audit logging** (load-bearing for any compliance conversation later). Sentry is high-value but easier to add post-launch when we know what kinds of errors occur. If pausing: this is a clean stopping point. ## How to resume ```bash cd /Users/noise/Documents/code/touchbase pnpm test # 92/92 pnpm lint # clean pnpm exec tsc --noEmit # clean # CI will run on push: git push origin main # then check Actions tab on GitHub ```