/**
* 制御盤のログの API のルートが共有する前処理と応答(指示書AY 段階7-3。M12)。
*
* ★ルートは薄く保つ★。★ファイルシステム/OS のモジュールを import しない★(D3。段階7-4 の静的な検査の対象)。
*/
import { NextResponse } from "next/server";
import { parsePathCommandId } from "@/lib/ds-logs/validate";
import { requireAgent } from "@/lib/ds-agent/require-agent";
import type { ApiError, ErrorCode } from "@/lib/types";
export function errorBody(
code: ErrorCode,
message: string,
details: Record<string, string[]> | null = null
): ApiError {
return { error: { code, message, details } };
}
export function jsonError(
status: number,
code: ErrorCode,
message: string,
details: Record<string, string[]> | null = null
): Response {
return NextResponse.json(errorBody(code, message, details), { status });
}
export function noContent(): Response {
return new Response(null, { status: 204 });
}
/**
* `[command_id]` を持つ制御盤向けの5本の前処理: ★`requireAgent()`(再検証・最終接続日時の更新)→ `command_id` の検証★。
* 本体はこの後にルートが `request.text()` で読む(JSON でない・オブジェクトでないは 400 `result_invalid`。R43・R44)。
*/
export async function agentCommandPreamble(
request: Request,
commandIdRaw: string
): Promise<{ ok: true; serial: string; commandId: string } | { ok: false; response: Response }> {
const auth = await requireAgent(request);
if (!auth.ok) return auth;
const parsed = parsePathCommandId(commandIdRaw);
if (!parsed.ok) return { ok: false, response: NextResponse.json(parsed.error, { status: parsed.status }) };
return { ok: true, serial: auth.serial, commandId: parsed.query };
}
/** 制御盤向け: 指示が無い・別の制御盤の指示・種類の違う指示(403 にしない。R35) */
export function commandNotFound(): Response {
return jsonError(404, "not_found", "指示が見つかりません");
}