ADR-0003 — reset-demo-data on prod: schema-safe reset (supersedes GRO-2705 removal)
- Status: Accepted (2026-08-16)
- Context tickets: GRO-2721 (this), GRO-2720 (CEO correction), GRO-2705 / infra PR #735 (superseded), GRO-2678 (original outage). Related: ADR-0002.
- Decider: CTO (Dogfather).
Context
demo.groombook.dev is a demo site; it relies on the reset-demo-data CronJob to periodically restore demo state. That CronJob runs the git.farh.net/groombook/reset image, whose entrypoint is pnpm --filter @groombook/db reset:
node ./scripts/wait-for-db.mjs && tsx src/reset.ts && drizzle-kit migrate && tsx src/seed.ts
packages/db/src/reset.ts was written local-dev-only and is destructive: DROP TABLE ... CASCADE (all public tables), DROP TYPE (all enums), DROP TABLE drizzle.__drizzle_migrations, and DROP SCHEMA IF EXISTS drizzle CASCADE. In GRO-2678 it dropped the PROD schema; the following drizzle-kit migrate no-op'd (journal-driven, GRO-2672 class bug) → empty DB → outage.
GRO-2705 (PR #735) removed the CronJob from the prod overlay entirely. That was a correct interim safety measure but the wrong permanent fix — it left the demo site with no reset path.
Decision
Re-add reset-demo-data to prod, but only after making the reset path schema-safe:
reset.tsresets data only viaTRUNCATE ... RESTART IDENTITY CASCADEof public tables, then reseeds.- It issues no
DROP TABLE/DROP TYPE/DROP SCHEMA/DROP DATABASEin any schema. Thedrizzleschema + migrations table are left intact, sodrizzle-kit migratestays a no-op on an already-migrated DB and the schema is never torn down — even if a later step fails. - Production guard (
NODE_ENV=production && ALLOW_RESET!=true→ exit) retained.
Sequencing (hard dependency)
Re-adding the CronJob against the current/:latest destructive image would reproduce GRO-2678. Therefore:
- GRO-2722 (api) — make
packages/db/src/reset.tsschema-safe. Full SDLC; UAT must actually run the uat reset CronJob and prove the schema survives. Ships a newreset:<CalVer>-<sha>image. - GRO-2723 (infra) — re-add
reset-cronjob.yaml+ kustomization entry toapps/overlays/prod, image pinned to GRO-2722's tag (never:latest). Blocked by GRO-2722.
Prod DB creds for the CronJob: secret groombook-postgres-credentials, key uri.
Consequences
- Demo site regains automated reset with no schema-drop blast radius.
- Reset image path is no longer "local-dev-only"; the destructive full-drop behavior, if still wanted for local dev, moves to a separate
db:nukescript. - Overlay pins the reset image to CalVer (per DevOps no-
:latest, no-image-automation policy); future reset changes require a new pin.
Guardrail
Any job/script that runs against the prod groombook schema must be additive or truncate-only. DROP SCHEMA / DROP TABLE / DROP DATABASE against prod is prohibited outside an explicit, board-approved, backup-gated migration.