1import { z } from "zod"; 2 3/** 4 * Test-only AI seam bodies (TASK-0122 — `INTERNAL_TEST_SEAM`). 5 * 6 * - `MockFailDto`: arm a deterministic provider outage on the NEXT mock 7 * chat call (mid-stream, after `deltas` deltas — see `armMockFailures`). 8 * `status` must be a retryable one (429/5xx): a 4xx would be non-retryable 9 * and the panel would show a dead-end banner, which is not what the E2E 10 * error-state spec exercises. 11 * - `AiUsageLimitsDto`: set (or clear, via `null`) the per-workspace 12 * `usageLimits.aiMonthlyTokens` — the monthly token budget the AI budget 13 * guard enforces (a value < 2×maxOutputTokens trips the pre-stream 402 14 * on a fresh workspace). No PUBLIC API writes this column, which is why 15 * the seam exists. 16 */ 17export const MockFailDto = z.object({ 18 status: z.union([z.literal(429), z.literal(500), z.literal(502), z.literal(503), z.literal(504)]).default(500), 19 deltas: z.number().int().min(0).max(100).default(2) 20}); 21 22export type MockFailInput = z.infer<typeof MockFailDto>; 23 24export const AiUsageLimitsDto = z.object({ 25 aiMonthlyTokens: z.number().int().min(0).max(1_000_000_000).nullable().default(null) 26}); 27 28export type AiUsageLimitsInput = z.infer<typeof AiUsageLimitsDto>; 29 30/** 31 * TASK-0123: arm the NEXT mock WRITING call to append a forged blockId the 32 * prompt never contained (the "unknown ID → drop + note" validation seam). 33 */ 34export const MockUnknownBlockIdDto = z.object({ 35 unknownId: z.string().min(1).max(100) 36}); 37 38export type MockUnknownBlockIdInput = z.infer<typeof MockUnknownBlockIdDto>; 39 40/** 41 * TASK-0124: arm the NEXT mock DATABASE-GENERATION call to emit a 42 * deliberately invalid tool call (the "zod/engine validation fails → retry 43 * once → 422, no partial write" seam). `action` selects which feature's 44 * invalid shape to emit (default `generate`). 45 */ 46export const MockDbInvalidDto = z.object({ 47 action: z.enum(["generate", "extract", "formula"]).default("generate") 48}); 49 50export type MockDbInvalidInput = z.infer<typeof MockDbInvalidDto>; 51 52/** 53 * TASK-0126: arm the NEXT mock PAGE-GENERATION call for a workspace: 54 * - `failStep` (1-based): inject a plan step that references an unknown ref 55 * (the executor's step-failure → rollback path); 56 * - `slowMs`: make the plan fetch take this long (the service's total-timeout 57 * watchdog fires → the `ai_timeout` path). 58 * Both optional; omit to arm neither (a no-op arming). 59 */ 60export const MockGenerateSeamDto = z.object({ 61 failStep: z.number().int().min(1).max(50).optional(), 62 slowMs: z.number().int().min(1).max(600_000).optional() 63}); 64 65export type MockGenerateSeamInput = z.infer<typeof MockGenerateSeamDto>; 66 67/** 68 * T-172…T-175 (A-010): arm the mock ASSISTANT calls for `workspaceId` to 69 * emit a deliberately INVALID tool call (`hostile` → retry-once → 422, no 70 * write) and/or a forged candidate id (`forgeId` → the no-fabricated-refs 71 * drop path). Both flags optional; omit both = no-op arming. 72 */ 73export const MockAssistantDto = z.object({ 74 hostile: z.boolean().default(false), 75 forgeId: z.boolean().default(false) 76}); 77 78export type MockAssistantInput = z.infer<typeof MockAssistantDto>; 79