Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 55x 55x 55x 55x 55x | // Shared client/server batch schema (spec §2.1) — no server-only imports. The
// client pre-validates with this exact module, so the two sides can never
// drift. Regexes are the spec's, verbatim — lowercase Crockford base32 ULIDs,
// items carrying the repository's `item_` prefix.
import { z } from "zod";
export const ClientKey = z
.string()
.length(26)
.regex(/^[0-9a-hjkmnp-tv-z]{26}$/);
export const ItemId = z
.string()
.max(64)
.regex(/^item_[0-9a-hjkmnp-tv-z]{26}$/);
export const BatchEntrySchema = z.discriminatedUnion("type", [
z.object({
type: z.literal("triage"),
decision: z.object({
itemId: ItemId,
result: z.enum(["top", "high", "medium", "low"]),
}),
clientKey: ClientKey,
}),
z.object({
type: z.literal("pairwise_compare"),
decision: z.object({
itemAId: ItemId,
itemBId: ItemId,
result: z.enum(["item_a", "item_b", "tie", "skip"]),
}),
clientKey: ClientKey,
}),
z.object({
type: z.literal("usage"),
decision: z.object({ itemId: ItemId, result: z.enum(["uses", "not_uses"]) }),
clientKey: ClientKey,
}),
]);
export const BatchRequestSchema = z.object({
decisions: z.array(BatchEntrySchema).min(1).max(50),
});
export type BatchEntry = z.infer<typeof BatchEntrySchema>;
export type BatchResultStatus = "created" | "duplicate" | "rejected";
export interface BatchResult {
clientKey: string;
status: BatchResultStatus;
reason?: "unknown_item";
}
export const MAX_BATCH_BYTES = 65_536;
|