CI (SIAX Cloud) / integration (push) Has been skipped
masterplan-lock / check (pull_request) Successful in 3s
masterplan-lock / check (push) Successful in 3s
CI (SIAX Cloud) / security (push) Successful in 15s
Security Scan (SIAX Cloud) / security (push) Successful in 14s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 18s
CI (SIAX Cloud) / quality (pull_request) Successful in 31s
CI (SIAX Cloud) / quality (push) Successful in 40s
CI (SIAX Cloud) / security (pull_request) Successful in 42s
CI (SIAX Cloud) / integration (pull_request) Successful in 45s
getSqlForDurableStore throws SiaxError(DEPENDENCY_UNAVAILABLE, httpStatus 503, retryable) when a money-bearing store would fall back to an in-memory Map in a production runtime (the durable-store guard). The /api/0pt/* surface already maps it via src/http/siax-error-response.ts; the seven legacy routes outside the middleware matcher did not — the documented 503 leaked as Next's opaque 500 with no body. - app/api/siax-error-mapping.ts: shared isSiaxError + siaxErrorResponseForLegacy - orders (POST/GET), orders/[id] (GET/PATCH), subscriptions (GET/POST), payments/deposit, payments/release, admin/metrics: try/catch -> mapper, each route's own typed error contract preserved (idempotency conflict 409 etc.) - webhooks/stripe: store outage -> 503 received:false reason:store_unavailable so Stripe's delivery retry path stays open (never a silent received:true) - tests/api/legacy-routes-siax-error-mapping.test.ts: pins the 503 + body
29 lines
1.3 KiB
TypeScript
29 lines
1.3 KiB
TypeScript
/**
|
|
* app/api/siax-error-mapping.ts — shared error mapper for the LEGACY routes
|
|
* outside the /api/0pt matcher (`app/api/orders*`, `/subscriptions`,
|
|
* `/payments/*`, `/webhooks/stripe`, `/admin/metrics`).
|
|
*
|
|
* 0pt#53: `getSqlForDurableStore` (lib/db.ts) throws
|
|
* `SiaxError("DEPENDENCY_UNAVAILABLE")` (httpStatus 503, retryable) when a
|
|
* money-bearing store would otherwise fall back to an in-memory Map in a
|
|
* production runtime. The /api/0pt/* surface already maps that error via
|
|
* src/http/siax-error-response.ts; these legacy routes did not, so the
|
|
* documented 503 DEPENDENCY_UNAVAILABLE leaked as Next's opaque 500.
|
|
*
|
|
* The helpers preserve each route's OWN typed error contract
|
|
* (IdempotencyKeyConflictError -> 409, etc.) and only ADD the SiaxError
|
|
* branch — a plain rethrow is deliberately avoided because App Router turns
|
|
* any uncaught thrown SiaxError into a generic 500 with no error body.
|
|
*/
|
|
import { NextResponse } from "next/server";
|
|
import { SiaxError } from "@/src/platform/errors";
|
|
|
|
export function isSiaxError(error: unknown): error is SiaxError {
|
|
return error instanceof SiaxError;
|
|
}
|
|
|
|
/** Map a caught error to a NextResponse: SiaxError -> its pinned status/body. */
|
|
export function siaxErrorResponseForLegacy(error: SiaxError): NextResponse {
|
|
return NextResponse.json(error.toJSON(), { status: error.httpStatus });
|
|
}
|