Production hardening: CSP, rate limit, env validation, health gating, Render blueprint, DEPLOYMENT.md

This commit is contained in:
Joel Brock
2026-05-09 21:43:43 -07:00
parent da3e48a874
commit dcdf315244
8 changed files with 343 additions and 2 deletions

View File

@@ -21,6 +21,7 @@
import { NextResponse } from "next/server";
import { civi, verifyChecksum } from "@/lib/civicrm";
import { ACTIVITY_TYPE_NAME, FORM_CONTACT_RELATIONSHIP } from "@/config/form";
import { appEnv } from "@/lib/env";
interface CheckResult {
check: string;
@@ -353,6 +354,20 @@ async function probeContactRelationships(cid: string): Promise<CheckResult> {
}
export async function GET(req: Request) {
// In production: require ?token=<HEALTH_TOKEN>. If HEALTH_TOKEN is unset
// in production, the endpoint is disabled entirely (404). In development
// / non-prod, anyone can read it.
const e = appEnv();
const url = new URL(req.url);
if (e.isProduction) {
if (!e.healthToken) {
return new NextResponse("Not Found", { status: 404 });
}
if (url.searchParams.get("token") !== e.healthToken) {
return new NextResponse("Not Found", { status: 404 });
}
}
const env = envSummary();
const summary = { mode: env.ok ? "live" : "stub" };
@@ -361,7 +376,6 @@ export async function GET(req: Request) {
return NextResponse.json({ ...summary, checks: [env] });
}
const url = new URL(req.url);
const cid = url.searchParams.get("cid");
const cs = url.searchParams.get("cs");