--- phase: 01-foundation plan: 03 type: execute wave: 3 depends_on: - 01-02 files_modified: - src/schemas/index.ts autonomous: true requirements: [] must_haves: truths: - "BACKEND_SCHEMAS['azureblob'].safeParse({account: 'x'}) returns success: true" - "BACKEND_SCHEMAS['azureblob'].safeParse({account: ''}) returns success: false" - "BACKEND_SCHEMAS['s3-compatible'].safeParse({...without endpoint}) returns success: false" - "Zod schemas are derived programmatically from BACKEND_REGISTRY — no hand-written z.object() calls" - "All 12 tests in src/schemas/index.test.ts pass" artifacts: - path: "src/schemas/index.ts" provides: "BACKEND_SCHEMAS constant and BackendFormValues utility type" exports: ["BACKEND_SCHEMAS", "BackendFormValues"] key_links: - from: "src/schemas/index.ts" to: "src/schemas/registry.ts" via: "imports BACKEND_REGISTRY and BackendType to build schemas programmatically" pattern: "import.*BACKEND_REGISTRY.*registry" --- Implement the Zod schema builder that derives runtime validation schemas programmatically from the Backend Schema Registry. Purpose: Schema and registry must never drift — if someone adds a field to the registry, validation automatically covers it. Writing Zod schemas by hand separate from the registry breaks this invariant. Output: src/schemas/index.ts with BACKEND_SCHEMAS and BackendFormValues type — all 12 tests in src/schemas/index.test.ts pass. @C:/Users/SebastienQUEROL/.claude/get-shit-done/workflows/execute-plan.md @C:/Users/SebastienQUEROL/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/phases/01-foundation/01-02-SUMMARY.md ```typescript export type BackendType = 'azureblob' | 's3' | 's3-compatible'; export interface FieldDef { key: string; label: string; inputType: 'text' | 'password' | 'select' | 'toggle'; required: boolean; placeholder?: string; helpText?: string; options?: { value: string; label: string }[]; } export const BACKEND_REGISTRY: Record; // azureblob fields: account (required), key (optional), sas_url (optional) // s3 fields: provider (required), access_key_id (required), secret_access_key (required), region (required) // s3-compatible fields: provider (required), access_key_id (required), secret_access_key (required), endpoint (required), region (optional) ``` Task 1: Implement schema builder and BACKEND_SCHEMAS src/schemas/index.ts - buildZodSchema(backendType) constructs a z.object() from BACKEND_REGISTRY[backendType] - required fields → z.string().min(1, '{label} is required') - optional fields → z.string().optional() - BACKEND_SCHEMAS is a const object keyed by BackendType - BackendFormValues infers the TypeScript type from the schema using z.infer - No z.object() calls hardcoded with field names — all field shapes derived from the registry loop Run the failing test first to confirm RED state: ``` npx vitest run src/schemas/index.test.ts ``` Expected: "Cannot find module './index'" error. Create src/schemas/index.ts: ```typescript // src/schemas/index.ts // Zod schemas derived programmatically from the Backend Schema Registry. // DO NOT hand-write z.object() calls with hardcoded field names — all shapes come from the registry. // Adding a field to BACKEND_REGISTRY automatically adds it to validation. import { z } from 'zod'; import { BACKEND_REGISTRY, BackendType } from './registry'; function buildZodSchema(backendType: BackendType): z.ZodObject> { const fields = BACKEND_REGISTRY[backendType]; const shape: Record = {}; for (const field of fields) { shape[field.key] = field.required ? z.string().min(1, `${field.label} is required`) : z.string().optional(); } return z.object(shape); } export const BACKEND_SCHEMAS = { azureblob: buildZodSchema('azureblob'), s3: buildZodSchema('s3'), 's3-compatible': buildZodSchema('s3-compatible'), } as const; // Utility type: infer TypeScript type from a backend's Zod schema export type BackendFormValues = z.infer; ``` Run the tests: ``` npx vitest run src/schemas/index.test.ts ``` All tests must pass (GREEN). If any fail, diagnose and fix — do not move on with failing tests. Run the full test suite to confirm no regressions: ``` npx vitest run ``` npx vitest run src/schemas/index.test.ts 2>&1 All tests in src/schemas/index.test.ts pass. BACKEND_SCHEMAS exported with entries for all three backends. BackendFormValues type exported. npx vitest run (full suite) exits 0 with registry and schema tests green. 1. `npx vitest run src/schemas/index.test.ts` — all tests pass (12 tests green) 2. `npx vitest run src/schemas/registry.test.ts` — still passing (no regression) 3. `npx vitest run` — full suite green for all schema tests 4. Confirm src/schemas/index.ts has no hardcoded field names in z.object() — only the loop over BACKEND_REGISTRY - src/schemas/index.ts creates Zod schemas by looping over BACKEND_REGISTRY field definitions - All 12 tests in src/schemas/index.test.ts pass - BACKEND_SCHEMAS and BackendFormValues are exported - Full test suite (registry + index) exits 0 After completion, create `.planning/phases/01-foundation/01-03-SUMMARY.md` using the summary template.