Skip to content

fix(devtools): expose POST /admin/db-migrate/resolve route (fixes #626)#627

Merged
d-klotz merged 4 commits into
nextfrom
fix/expose-db-migrate-resolve-route
Jul 14, 2026
Merged

fix(devtools): expose POST /admin/db-migrate/resolve route (fixes #626)#627
d-klotz merged 4 commits into
nextfrom
fix/expose-db-migrate-resolve-route

Conversation

@d-klotz

@d-klotz d-klotz commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #626. Adds the missing POST /admin/db-migrate/resolve API Gateway route in migration-builder, so it matches the routes core's migration router actually serves.

Problem

packages/core/handlers/routers/db-migration.js registers POST /admin/db-migrate/resolve to recover from a Prisma P3009 (a failed migration blocks all subsequent migrations). But migration-builder.js only emitted three httpApi events (GET .../status, POST /admin/db-migrate, GET .../{processId}) — the resolve route was never exposed. On any deployed app it returns 404, so P3009 recovery via the admin API is impossible; operators are forced into direct DB writes (prisma migrate resolve / manual _prisma_migrations SQL) requiring DB creds + VPC access.

Hit in production: a stale duplicate create_process_table migration failed months earlier; every deploy since silently no-op'd on migrations, with no API path to resolve it.

Change

  • migration-builder.js: add { httpApi: { path: '/admin/db-migrate/resolve', method: 'POST' } } to the dbMigrationRouter events (no new handler needed — core's router already serves it; the route just wasn't mapped to API Gateway).
  • migration-builder.test.js: assert the 4th route (length 3 → 4).

Test plan

  • npx jest infrastructure/domains/database/migration-builder.test.js → 23 passed.
  • Minimal diff (+13/-1); no unrelated reformatting.

🤖 Generated with Claude Code

📦 Published PR as canary version: 2.0.0--canary.627.ce32cdc.0

✨ Test out this PR locally via:

npm install @friggframework/admin-scripts@2.0.0--canary.627.ce32cdc.0
npm install @friggframework/core@2.0.0--canary.627.ce32cdc.0
npm install @friggframework/devtools@2.0.0--canary.627.ce32cdc.0
npm install @friggframework/eslint-config@2.0.0--canary.627.ce32cdc.0
npm install @friggframework/prettier-config@2.0.0--canary.627.ce32cdc.0
npm install @friggframework/schemas@2.0.0--canary.627.ce32cdc.0
npm install @friggframework/serverless-plugin@2.0.0--canary.627.ce32cdc.0
npm install @friggframework/test@2.0.0--canary.627.ce32cdc.0
npm install @friggframework/ui@2.0.0--canary.627.ce32cdc.0
# or 
yarn add @friggframework/admin-scripts@2.0.0--canary.627.ce32cdc.0
yarn add @friggframework/core@2.0.0--canary.627.ce32cdc.0
yarn add @friggframework/devtools@2.0.0--canary.627.ce32cdc.0
yarn add @friggframework/eslint-config@2.0.0--canary.627.ce32cdc.0
yarn add @friggframework/prettier-config@2.0.0--canary.627.ce32cdc.0
yarn add @friggframework/schemas@2.0.0--canary.627.ce32cdc.0
yarn add @friggframework/serverless-plugin@2.0.0--canary.627.ce32cdc.0
yarn add @friggframework/test@2.0.0--canary.627.ce32cdc.0
yarn add @friggframework/ui@2.0.0--canary.627.ce32cdc.0

@d-klotz d-klotz added release Create a release when this pr is merged prerelease This change is available in a prerelease. labels Jul 14, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 63910130c9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// and there is no admin-API path to resolve it.
{
httpApi: {
path: '/admin/db-migrate/resolve',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Run resolve on a Lambda with Prisma available

When an operator calls this newly exposed route in the default usePrismaLambdaLayer deployment, the router Lambda cannot execute it: db-migration.js handles /admin/db-migrate/resolve by calling runPrismaMigrateResolve() (packages/core/handlers/routers/db-migration.js:267-269), but this function is configured with no Prisma layer and its router package excludes node_modules/prisma/** and all WASM files (lines 343-398). The request will reach API Gateway but fail inside the Lambda instead of resolving the P3009 state; attach/package the Prisma runtime for this route or dispatch the resolve work to the migration worker.

Useful? React with 👍 / 👎.

The core migration router registers POST /admin/db-migrate/resolve
(db-migration.js) to recover from a Prisma P3009 (failed migration), but
migration-builder only emitted API Gateway routes for status, POST migrate,
and GET {processId}. So the resolve endpoint 404'd on every deployed app —
a single failed migration blocked all subsequent migrations for that stage
with no admin-API path to resolve it (recovery required direct DB writes).

Adds the missing httpApi event so the generated routes match the router.

Fixes #626.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@d-klotz
d-klotz force-pushed the fix/expose-db-migrate-resolve-route branch from 6391013 to 9cf8622 Compare July 14, 2026 11:57
d-klotz and others added 3 commits July 14, 2026 09:14
Exposing the resolve route (previous commit) wasn't enough: the route
handler ran runPrismaMigrateResolve() synchronously in the ROUTER Lambda,
which is packaged without Prisma (no layer, node_modules/prisma + WASM
excluded). So a real call would 500 at runtime instead of resolving.

Delegate to the worker Lambda (which has the Prisma CLI), mirroring the
existing checkStatus direct-invoke pattern (GetDatabaseStateViaWorkerUseCase):
- New ResolveMigrationViaWorkerUseCase invokes the worker with a resolve payload.
- Worker gains a `resolve` action that runs runPrismaMigrateResolve + returns
  its result (validates migrationName + applied|rolled-back).
- Router resolve route delegates via the use case; stays Prisma-free and
  synchronous (200 body from the worker, 500 on failure).

Addresses the P1 review on #627.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- prisma-runner: capture resolve stderr/stdout and return it in the error
  (was stdio:'inherit' → Prisma's real failure, e.g. P3011 for a mistyped
  migration, went only to CloudWatch; the HTTP client got "exited with
  code 1"). The point of #626 is HTTP recovery without console access.
- Validate migrationName shape (^\d{14}_[a-z0-9_]+$) in router + worker so a
  value like "--schema" can't be handed to the Prisma CLI as a flag.
- Router maps a worker-side 400 (LambdaInvocationError.statusCode===400) to a
  client 400 instead of a generic 500.
- Worker guards dbType !== 'postgresql' → 400 (resolve is postgres-only)
  instead of dying on a schema-not-found error.
- Tests: worker resolve branch (malformed name, non-postgres dbType, error
  passthrough) + router resolve route registration.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The rationale lives in the commit history / PR; the code is self-explanatory.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@d-klotz
d-klotz merged commit 7588ea6 into next Jul 14, 2026
7 of 8 checks passed
@sonarqubecloud

Copy link
Copy Markdown

@seanspeaks

Copy link
Copy Markdown
Contributor

🚀 PR was released in v2.0.0-next.104 🚀

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

Labels

prerelease This change is available in a prerelease. release Create a release when this pr is merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants