Production hardening: CSP, rate limit, env validation, health gating, Render blueprint, DEPLOYMENT.md
This commit is contained in:
@@ -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");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user