48 lines
2.1 KiB
TypeScript
48 lines
2.1 KiB
TypeScript
// DES1GN ADR D3 (§31): bulk-import dispatch-policy — ETT objekt, en sanning.
|
|
//
|
|
// Import-routen (/api/orders/import) är inline-exekvering med hårt tak. Rader
|
|
// över maxRows är DES1GN D3:s signal för N0D-dispatch (job_type
|
|
// 0pt.import_execute_job / capability 0pt.import_execute i n0d:s
|
|
// JOB_TYPE_REGISTRY). TILLS descriptor-gaten släpper (N0D-worker
|
|
// UNVERIFIED) svarar routen 413 med n0d_dispatch_required + hint — aldrig
|
|
// tyst trunkering, aldrig tyst dispatch.
|
|
export const IMPORT_DISPATCH_POLICY = {
|
|
/** Inline-tak i import-routen (oförändrat beteendekontrakt, 0pt#53). */
|
|
maxInlineRows: 500,
|
|
/** N0D-dispatch-signal: rader över detta är ett N0D-jobb, inget HTTP-anrop. */
|
|
maxRows: 5000,
|
|
/** Byte-tak för hela CSV-kroppen (UTF-8). */
|
|
maxBytes: 1_000_000,
|
|
/** Format-allowlist — endast RFC 4180 CSV i dag. */
|
|
allowedFormats: ["csv"] as readonly string[],
|
|
} as const;
|
|
|
|
export type ImportDispatchPolicy = typeof IMPORT_DISPATCH_POLICY;
|
|
|
|
export type ImportDispatchVerdict =
|
|
| { verdict: "inline" }
|
|
| { verdict: "unsupported_format"; format: string }
|
|
| { verdict: "byte_cap_exceeded"; bytes: number; maxBytes: number }
|
|
| { verdict: "row_cap_exceeded"; rows: number; maxInlineRows: number }
|
|
| { verdict: "dispatch_n0d"; rows: number; maxRows: number };
|
|
|
|
/** Ren funktion — inga I/O, fullt deterministisk, testad per kombination. */
|
|
export function evaluateImportDispatch(
|
|
input: { format: string; bytes: number; rows: number },
|
|
policy: ImportDispatchPolicy = IMPORT_DISPATCH_POLICY,
|
|
): ImportDispatchVerdict {
|
|
if (!policy.allowedFormats.includes(input.format)) {
|
|
return { verdict: "unsupported_format", format: input.format };
|
|
}
|
|
if (input.bytes > policy.maxBytes) {
|
|
return { verdict: "byte_cap_exceeded", bytes: input.bytes, maxBytes: policy.maxBytes };
|
|
}
|
|
if (input.rows > policy.maxRows) {
|
|
return { verdict: "dispatch_n0d", rows: input.rows, maxRows: policy.maxRows };
|
|
}
|
|
if (input.rows > policy.maxInlineRows) {
|
|
return { verdict: "row_cap_exceeded", rows: input.rows, maxInlineRows: policy.maxInlineRows };
|
|
}
|
|
return { verdict: "inline" };
|
|
}
|