--- phase: 07-validation-ux-polish plan: "01" type: execute wave: 2 depends_on: - "07-00" files_modified: - src/schemas/registry.ts - src/schemas/index.ts autonomous: true requirements: - VALID-01 must_haves: truths: - "User who enters 'MyStorage' in the Azure account name field sees an inline error before advancing" - "User who enters 'us east 1' in the S3 region field sees an inline error" - "User who enters 'abc' in the GCS project_number field sees an inline error" - "Valid values ('mystorageaccount', 'us-east-1', '123456789') produce no format error" - "Empty required fields still show 'required' error (not the regex error) — empty string hits min(1) before regex" - "All 147 pre-existing tests still pass after adding validation" artifacts: - path: "src/schemas/registry.ts" provides: "FieldDef interface with validate property; 3 registry entries with validate rules" contains: "validate\\?: \\{ regex: RegExp; message: string \\}" - path: "src/schemas/index.ts" provides: "buildZodSchema() chains .regex() when field.validate is present" contains: "field\\.validate" key_links: - from: "BACKEND_REGISTRY azureblob.account" to: "buildZodSchema('azureblob')" via: "field.validate.regex applied as .regex() on ZodString" pattern: "field\\.validate" - from: "buildZodSchema()" to: "BACKEND_SCHEMAS" via: "Zod schema exported, consumed by zodResolver in RemoteConfigStep" --- Implement VALID-01: extend FieldDef with a validate property, add regex rules to 3 registry entries (azureblob account, s3 region, gcs project_number), and extend buildZodSchema() to chain .regex() when the property is present. Purpose: Users see inline format errors on malformed credential fields before they can advance in the wizard. Output: Modified registry.ts (FieldDef + 3 validate rules) and index.ts (buildZodSchema regex chaining). @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/ROADMAP.md @.planning/phases/07-validation-ux-polish/07-CONTEXT.md @.planning/phases/07-validation-ux-polish/07-RESEARCH.md @.planning/phases/07-validation-ux-polish/07-00-SUMMARY.md Current FieldDef (src/schemas/registry.ts): ```typescript export interface FieldDef { key: string; label: string; inputType: 'text' | 'password' | 'select' | 'toggle'; required: boolean; placeholder?: string; helpText?: string; options?: { value: string; label: string }[]; // validate and tooltipText DO NOT EXIST YET } ``` Current buildZodSchema (src/schemas/index.ts): ```typescript function buildZodSchema(backendType: BackendType): z.ZodObject> { const fields = BACKEND_REGISTRY[backendType].fields; 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); } ``` Zod v4 important: cast to (schema as z.ZodString).regex(...) because schema variable is typed ZodTypeAny. Zod v4 chaining order: .min(1).regex() is correct for required fields. .regex().optional() for optional (not needed here — all 3 validated fields are required). Task 1: Extend FieldDef and add validate rules to 3 registry entries src/schemas/registry.ts - Adding validate to azureblob.account and submitting 'ABC' produces Zod error 'Must be 3–24 lowercase alphanumeric characters' - Adding validate to s3.region and submitting 'us east 1' produces Zod error matching region format - Adding validate to gcs.project_number and submitting 'abc' produces Zod error 'digits only' (or similar) - Submitting '' on account still produces the required error (not the regex error) — min(1) fires first 1. Add two optional properties to FieldDef interface: ```typescript validate?: { regex: RegExp; message: string }; tooltipText?: string; // also add here for Plan 02 — it's just an interface addition, no behavior yet ``` Note: Adding tooltipText here avoids a second interface-only edit in Plan 02. 2. In BACKEND_REGISTRY, locate the azureblob `account` field entry and add: ```typescript validate: { regex: /^[a-z0-9]{3,24}$/, message: 'Must be 3–24 lowercase alphanumeric characters (no hyphens or uppercase)', }, ``` 3. Locate the s3 `region` field entry and add: ```typescript validate: { regex: /^[a-z][a-z0-9-]+[a-z0-9]$/, message: 'Must be a valid AWS region format (e.g. us-east-1)', }, ``` 4. Locate the gcs `project_number` field entry and add: ```typescript validate: { regex: /^\d+$/, message: 'Must contain digits only', }, ``` No other fields get validate rules — user decision is explicit on scope. npx vitest run src/components/wizard/RemoteConfigStep.test.tsx FieldDef has validate and tooltipText properties. 3 registry entries have validate rules. TypeScript compiles without errors (npx tsc --noEmit). Task 2: Extend buildZodSchema() to chain .regex() from field.validate src/schemas/index.ts - buildZodSchema('azureblob') produces a schema where the account field rejects 'ABC' with the registry message - buildZodSchema('s3') produces a schema where the region field rejects 'us east 1' - buildZodSchema('gcs') produces a schema where project_number rejects 'abc' - buildZodSchema('onedrive') and others without validate are unaffected - VALID-01 failing tests from Plan 00 now PASS Replace the buildZodSchema loop body with the regex-aware version: ```typescript function buildZodSchema(backendType: BackendType): z.ZodObject> { const fields = BACKEND_REGISTRY[backendType].fields; const shape: Record = {}; for (const field of fields) { let schema: z.ZodTypeAny = field.required ? z.string().min(1, `${field.label} is required`) : z.string(); if (field.validate) { schema = (schema as z.ZodString).regex(field.validate.regex, field.validate.message); } if (!field.required) { schema = (schema as z.ZodString).optional(); } shape[field.key] = schema; } return z.object(shape); } ``` Critical: cast to (schema as z.ZodString) before .regex() — ZodTypeAny does not expose .regex() in TypeScript but it is present at runtime. This pattern is verified. Do NOT touch BACKEND_SCHEMAS export or anything else in the file. npx vitest run src/components/wizard/RemoteConfigStep.test.tsx VALID-01 tests from Plan 00 all pass (GREEN). Full suite still at 147+ pass with 0 failures: `npx vitest run`. 1. `npx tsc --noEmit` — no TypeScript errors 2. `npx vitest run src/components/wizard/RemoteConfigStep.test.tsx` — VALID-01 tests pass (GREEN), UX-01 stubs still fail (expected — UX-01 is Plan 02) 3. `npx vitest run` — all pre-existing 147 tests pass, no regressions - FieldDef has validate and tooltipText properties - 3 registry entries (azureblob.account, s3.region, gcs.project_number) have validate rules with the exact regexes from CONTEXT.md - buildZodSchema() chains .regex() when field.validate is present - VALID-01 test stubs from Plan 00 all pass - Full test suite passes After completion, create `.planning/phases/07-validation-ux-polish/07-01-SUMMARY.md`