diff --git a/middleware.ts b/middleware.ts index b26b22a..d439dda 100644 --- a/middleware.ts +++ b/middleware.ts @@ -2,9 +2,9 @@ * Next.js auth seam for the complete /api/0pt capability surface. * * Customer calls use verified Zitadel bearer identity and receive immutable - * x-0pt-verified-* headers. Explicit machine-only routes may instead use the - * shared X-Internal-Token convention; those routes must also verify that token - * in their own handler for defence in depth. + * x-0pt-verified-* headers. Explicit machine routes may instead use the + * shared X-Internal-Token convention; mutation handlers verify it again for + * defence in depth. */ import { NextResponse, type NextRequest } from 'next/server'; import { assertAuthConfigSafe, resolveAuthContext } from '@/src/auth/context'; @@ -22,22 +22,21 @@ const EXEMPT_PATTERNS: RegExp[] = [ /^\/api\/admin\/metrics(\/|$)/, ]; -/** Machine-to-machine surfaces. A valid internal token is required. */ -const INTERNAL_ONLY_ROUTES: RegExp[] = [ +/** Routes that may be reached with a service token instead of end-user bearer auth. */ +const INTERNAL_SERVICE_ROUTES: RegExp[] = [ /^\/api\/0pt\/quality\/bridge-run$/, /^\/api\/0pt\/internal\/evidence-outbox\/dispatch$/, /^\/api\/0pt\/internal\/er\/candidates$/, + /^\/api\/0pt\/search\/definitions$/, ]; let _authDiagCount = 0; export async function middleware(req: NextRequest): Promise { const path = req.nextUrl.pathname; - if (EXEMPT_PATTERNS.some((re) => re.test(path))) { - return NextResponse.next(); - } + if (EXEMPT_PATTERNS.some((re) => re.test(path))) return NextResponse.next(); - if (INTERNAL_ONLY_ROUTES.some((re) => re.test(path)) && verifyInternalServiceToken(req.headers)) { + if (INTERNAL_SERVICE_ROUTES.some((re) => re.test(path)) && verifyInternalServiceToken(req.headers)) { return NextResponse.next(); } @@ -52,7 +51,6 @@ export async function middleware(req: NextRequest): Promise { } const decision = await resolveAuthContext(req.headers); - if (!decision.ok) { return NextResponse.json( { error: decision.code, message: decision.message, ...(decision.details ? { details: decision.details } : {}) },