Skip to content

Fix #33: adopt a Prisma migrations workflow#76

Merged
TusharW4ni merged 3 commits into
mainfrom
fix/33-adopt-migrations
Jul 13, 2026
Merged

Fix #33: adopt a Prisma migrations workflow#76
TusharW4ni merged 3 commits into
mainfrom
fix/33-adopt-migrations

Conversation

@TusharW4ni

Copy link
Copy Markdown
Contributor

Fixes #33.

Adopts a real Prisma migrations workflow so the schema has reproducible history in version control and prod can be advanced with prisma migrate deploy — unblocking #14, #27, #28, #5.

⚠️ Human review + one manual prod step required (do NOT auto-merge)

This PR touches risk files (prisma/migrations, dockerfile, package.json) and changes the deploy process. Before/right-after merging you must run once against the live prod DB (which already has this schema from the old db push process):

DATABASE_URL="<prod db url>" npx prisma migrate resolve --applied 20260710023845_init

This marks the baseline as already-applied without re-running it, so the entrypoint's prisma migrate deploy sees the DB as up-to-date and is a no-op. Skipping this step would make migrate deploy try to CREATE tables that already exist and fail. After that one-time resolve, all future schema changes ship as new migrations applied automatically at container start.

What changed

  • .gitignore — removed /prisma/migrations; added !prisma/migrations/**/*.sql to carve migration SQL out of the *.sql dump-block from Production Database Dump with Real PII and Session Tokens in Public Repo #29 (so migrations are tracked, but prod.sql-style dumps stay ignored — verified both).
  • prisma/migrations/20260710023845_init/ — squashed baseline migration (all 10 tables + indexes) generated from the current prisma/schema/.
  • dockerfile — final stage now also copies prisma.config.ts, installs the pinned prisma CLI (+dotenv, which the config loads) into the app root, and copies the entrypoint. CMD is now the entrypoint.
  • docker-entrypoint.sh (new) — runs prisma migrate deploy (via npx --no-install, so no runtime network fetch), then exec node .output/server/index.mjs. set -e fails fast if a migration errors.
  • package.json — replaced the stale prisma:reset (which regenerated an init migration) with prisma:migrate (migrate dev), prisma:deploy (migrate deploy), and a migration-aware prisma:reset (migrate reset --force). No dependency changes.
  • CLAUDE.md — documented the new workflow and the .gitignore carve-out.

Verification done

  • Baseline schema is byte-identical to db push: created one DB via prisma db push and one via prisma migrate deploy, diffed .schema — the 105 application-schema lines match exactly; the only delta is Prisma's own _prisma_migrations bookkeeping table (expected). This is what makes the migrate resolve --applied step safe on prod.
  • Seed works against a migrate deploy DB.
  • migrate deploy is idempotent — a second run reports "No pending migrations to apply", so container restarts are safe.
  • Runtime path validated in isolation — a clean dir with only prisma/ + prisma.config.ts + a freshly-installed prisma CLI runs migrate deploy successfully (mirrors what the final image does).
  • e2e suite green — 29 files / 111 tests; the harness still uses db push and is unaffected by the committed migrations.

Not validated here (please confirm in CI)

  • 🔶 The Docker image build was not run locally (the dev sandbox has no container-registry network, so node:22-slim couldn't be pulled). The Dockerfile changes are standard COPY/RUN/CMD steps and the migrate-deploy logic they invoke is validated above, but the actual linux/arm64 image build + a container-start smoke test should be confirmed by the CI build (and ideally a staging run) before this reaches prod. Because merging main builds+pushes the prod image, consider building the image from this branch first if you want belt-and-suspenders.

Notes

  • migrate deploy at container start (not CI) is deliberate: the prod DB is a runtime SQLite file (persistent volume), which CI's build environment can't reach.
  • Image size grows modestly (prisma CLI + engine in the final stage) — the cost of runtime migrations.

🤖 Generated with Claude Code

Un-gitignore prisma/migrations and commit a squashed `init` baseline that
exactly reproduces the current db-push schema, so the schema history lives in
version control and prod can be brought forward with `prisma migrate deploy`.

- .gitignore: drop `/prisma/migrations`; carve `!prisma/migrations/**/*.sql`
  out of the `*.sql` dump-block (#29) so migration SQL is tracked but raw
  dumps stay ignored.
- prisma/migrations/20260710023845_init: baseline migration; verified its
  applied schema is byte-identical to `prisma db push` (only Prisma's own
  _prisma_migrations table differs).
- dockerfile + docker-entrypoint.sh: install the pinned prisma CLI (+dotenv)
  into the final image and run `prisma migrate deploy` at container start
  before booting the server (idempotent no-op once up to date).
- package.json: replace the broken `prisma:reset` with migration-aware
  scripts (prisma:migrate / prisma:deploy / prisma:reset).
- CLAUDE.md: document the new workflow.

The e2e harness still provisions its throwaway DB with `db push` (unchanged);
full suite green (29 files / 111 tests).

Requires a one-time human step against the LIVE prod DB (see PR body):
`prisma migrate resolve --applied 20260710023845_init`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
TusharW4ni and others added 2 commits July 13, 2026 16:55
* Fix #27: soft deletes for auditability

Add deletedAt to Ride/User/Client/Volunteer (plus deletedEmail/deletedPhone
on User to preserve released contact values). DELETE endpoints now archive
rows instead of destroying them, releasing the unique email/phone so records
can be re-added. Active read paths filter deletedAt: null; metrics endpoints
deliberately do not, preserving historical totals. Soft-deleted users are
blocked from logging in.

Migration 20260710035425_add_soft_deletes is additive (nullable ADD COLUMN).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Guard PUT/estimate paths against soft-deleted records (#27 review)

Address code-review follow-ups: PUT clients/volunteers and the ride estimate
endpoint now treat an archived record as 404 (findFirst with deletedAt: null),
so soft-deleted rows can't be edited or re-surfaced.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Revoke sessions on soft-delete; filter deletedAt on all volunteer lookups (#27 review)

Address independent-review HIGH findings:
- Session revocation: hard delete used to cascade to the session table (auth
  onDelete: Cascade), logging the user out. Soft-delete now deletes the user's
  session rows in the same transaction (admins/clients/volunteers), so an
  archived user's live cookie no longer retains API access — closing the gap in
  the decision-#1 login block.
- Filter deletedAt: null on the volunteer lookups that resolve by userId from a
  session (signup, unsignup, bySession status/reminders/notifications) so a
  stale session can't act as an archived volunteer.
- Guard the soft-delete update where-clauses (clients/volunteers) with
  deletedAt: null so a double-delete can't overwrite deletedEmail/deletedPhone.

New regression test: "revokes sessions on soft-delete" — a previously valid
volunteer cookie is rejected with 401 on GET /api/get/rides after the volunteer
is archived, and no session rows remain. Fails pre-fix (expected 200 to be 401).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@TusharW4ni

Copy link
Copy Markdown
Contributor Author

🔀 Merge conflict resolved

Merged origin/main (which now includes #75 repo-hygiene) into this branch. Two conflicts, both resolved cleanly and validated:

Validated the merged result: pnpm test30 files / 116 tests passing. Branch is now mergeable.

Note: this branch now carries #33 (migrations) and #27 (soft deletes), since #79 was merged into this base branch. PRs #77 (#5) and #78 (#14) are still based on the earlier tip and will retarget to main once this merges — they may need a trivial rebase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-human-review Automated gate declined to auto-merge — see PR comment for which gates failed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Prisma Migrations Are Gitignored — No Reproducible Schema History

1 participant