Security Scan (SIAX Cloud) / security (push) Successful in 21s
CI (SIAX Cloud) / security (push) Successful in 21s
CI (SIAX Cloud) / quality (push) Successful in 41s
CI (SIAX Cloud) / security (pull_request) Successful in 22s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 21s
CI (SIAX Cloud) / quality (pull_request) Successful in 41s
BACKLOG P0-3: /api/health only ever checked *presence* of DATABASE_URL/
REDIS_URL and always returned ok:true regardless of whether anything was
reachable -- ARCHITECTURE.md's own words, "an uptime monitor watching HTTP
200 would show green for a dying instance".
lib/health-checks.ts adds real dependency probes:
- db: a live `select 1` round trip (not just DATABASE_URL presence)
- engine: a real HTTP call to the FastAPI engine's own GET /health
- stripe: Stripe's documented lightweight balance.retrieve() liveness call
- queue: honestly reports "not_integrated" when REDIS_URL is set but
unused -- no Redis client is wired anywhere in this repo, so reporting
"ok" would fabricate a check that doesn't exist
/api/health stays a liveness check (always 200 while the process can
respond; the body's `ok` field is the honest signal). New GET /api/ready
fails closed with 503 when the load-bearing dependency (db) isn't both
configured and reachable -- the "no /ready route" gap.
contracts/openapi.yaml, docs/architecture/ARCHITECTURE.md, and docs/slo.md
updated to match. 17 new unit tests (dependency-injected fakes, no real
network/DB) + 5 route-level tests.
33 lines
1.1 KiB
TypeScript
33 lines
1.1 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { checkAllDependencies, isReady } from "@/lib/health-checks";
|
|
|
|
// GET /api/ready — readiness (BACKLOG P0-3, CD-04/OBS-04: "no /ready route
|
|
// existed at all").
|
|
//
|
|
// Unlike GET /api/health (liveness -- always 200 while the process can
|
|
// respond), this fails closed: 503 whenever a load-bearing dependency isn't
|
|
// both configured AND actually reachable. Point a load balancer / Coolify
|
|
// readiness probe at this route, not /api/health, to stop routing traffic to
|
|
// an instance whose database is down without restarting it.
|
|
//
|
|
// Today the only load-bearing dependency is the database (see
|
|
// `lib/health-checks.ts#isReady`) -- engine/stripe/queue are optional
|
|
// integrations 0pt is designed to run without.
|
|
export async function GET() {
|
|
const deps = await checkAllDependencies();
|
|
const ready = isReady(deps);
|
|
|
|
return NextResponse.json(
|
|
{
|
|
ready,
|
|
service: "0pt-web",
|
|
db: deps.db.status,
|
|
queue: deps.queue.status,
|
|
engine: deps.engine.status,
|
|
stripe: deps.stripe.status,
|
|
ts: new Date().toISOString(),
|
|
},
|
|
{ status: ready ? 200 : 503 },
|
|
);
|
|
}
|