feat(evidence): add protected AUD0 outbox dispatch endpoint

This commit is contained in:
2026-09-07 17:15:36 +02:00
parent 9f46e12447
commit 56b1ce01b3
@@ -0,0 +1,65 @@
import { NextRequest, NextResponse } from "next/server";
import { verifyInternalServiceToken } from "@/src/auth/internal-token";
import { createAud0Client } from "@/src/clients/aud0-client";
import {
Aud0OutboxDispatcher,
createAud0OutboxRepositoryFromEnv,
} from "@/src/evidence/aud0-outbox";
import { siaxErrorResponse } from "@/src/http/siax-error-response";
import { SiaxError } from "@/src/platform/errors";
function assertInternal(request: NextRequest): NextResponse | undefined {
if (verifyInternalServiceToken(request.headers)) return undefined;
return NextResponse.json(
{ error: "UNAUTHENTICATED", message: "valid X-Internal-Token is required" },
{ status: 401 },
);
}
function repository() {
const repo = createAud0OutboxRepositoryFromEnv();
if (!repo) {
throw new SiaxError(
"DEPENDENCY_UNAVAILABLE",
"0pt.aud0_outbox",
"DATABASE_URL is required for durable evidence dispatch",
);
}
return repo;
}
export async function POST(request: NextRequest) {
const denied = assertInternal(request);
if (denied) return denied;
try {
const raw = await request.json().catch(() => ({})) as { limit?: unknown };
const limit = raw.limit === undefined ? 100 : Number(raw.limit);
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 500) {
return NextResponse.json(
{ error: "INVALID_REQUEST", message: "limit must be an integer between 1 and 500" },
{ status: 400 },
);
}
const repo = repository();
const dispatcher = new Aud0OutboxDispatcher(repo, createAud0Client());
const result = await dispatcher.sweep(limit);
const stats = await repo.stats();
return NextResponse.json({ result, stats });
} catch (error: unknown) {
return siaxErrorResponse(error);
}
}
export async function GET(request: NextRequest) {
const denied = assertInternal(request);
if (denied) return denied;
try {
return NextResponse.json(await repository().stats());
} catch (error: unknown) {
return siaxErrorResponse(error);
}
}