--- phase: 07-validation-ux-polish plan: "01" subsystem: validation tags: [zod, regex, form-validation, registry, tdd] # Dependency graph requires: - phase: 07-validation-ux-polish plan: "00" provides: VALID-01 RED test stubs (4 reject tests + 3 acceptance tests) provides: - FieldDef interface with validate and tooltipText properties - 3 registry entries with validate regex rules (azureblob.account, s3.region, gcs.project_number) - buildZodSchema() chains .regex() when field.validate is present affects: - src/schemas/registry.ts - src/schemas/index.ts - RemoteConfigStep validation (via BACKEND_SCHEMAS consumed by zodResolver) # Tech tracking tech-stack: added: [] patterns: - "Zod v4 cast pattern: (schema as z.ZodString).regex() — ZodTypeAny does not expose .regex() at type level" - "let schema + conditional .regex() + conditional .optional() allows optional validated fields in future" - "Registry-driven validation: validate property on FieldDef flows through buildZodSchema() automatically" key-files: created: [] modified: - src/schemas/registry.ts - src/schemas/index.ts key-decisions: - "Cast (schema as z.ZodString).regex() — ZodTypeAny does not expose .regex() in TypeScript but it is present at runtime in Zod v4" - "tooltipText added to FieldDef in this plan (interface-only, no behavior) to avoid a second interface-only edit in Plan 07-02" - "Optional field chaining order: z.string() first, then .regex() if present, then .optional() — ensures regex fires before optional short-circuit" # Metrics duration: 5min completed: 2026-03-31 --- # Phase 7 Plan 01: VALID-01 Format Validation — FieldDef + Registry + Zod Chaining Summary **Regex validation wired from BACKEND_REGISTRY through buildZodSchema() to zodResolver: azureblob account, s3 region, and gcs project_number now reject malformed values with inline error messages** ## Performance - **Duration:** ~5 min - **Started:** 2026-03-31T09:48:00Z - **Completed:** 2026-03-31T09:53:00Z - **Tasks:** 2 - **Files modified:** 2 ## Accomplishments - Extended `FieldDef` interface with `validate?: { regex: RegExp; message: string }` and `tooltipText?: string` - Added validate rules to 3 registry entries: - `azureblob.account`: `/^[a-z0-9]{3,24}$/` — "Must be 3–24 lowercase alphanumeric characters (no hyphens or uppercase)" - `s3.region`: `/^[a-z][a-z0-9-]+[a-z0-9]$/` — "Must be a valid AWS region format (e.g. us-east-1)" - `gcs.project_number`: `/^\d+$/` — "Must contain digits only" - Extended `buildZodSchema()` to chain `.regex()` via `(schema as z.ZodString).regex()` when `field.validate` is present - VALID-01 test suite: 4 reject tests GREEN, 3 acceptance tests remain GREEN - Full suite: 154 passing, 5 failing (all UX-01 tooltip tests — Plan 07-02 scope) ## Task Commits 1. **Task 1: Extend FieldDef and add validate rules to 3 registry entries** - `3dea5c8` 2. **Task 2: Extend buildZodSchema() to chain .regex() from field.validate** - `c6d38fa` ## Files Created/Modified - `src/schemas/registry.ts` — FieldDef interface extended with validate/tooltipText; 3 registry entries enriched with validate rules; 14 lines added - `src/schemas/index.ts` — buildZodSchema() loop body replaced with let schema + conditional regex + conditional optional pattern; 12 lines added, 2 removed ## Decisions Made - `(schema as z.ZodString).regex()` cast is required because `schema` is typed `ZodTypeAny` but Zod v4 exposes `.regex()` at runtime. TypeScript type cast is the correct approach here — verified working. - `tooltipText?: string` added to `FieldDef` in this plan (interface-only, no behavior rendered yet) to avoid a second interface-only touch in Plan 07-02. This is a zero-risk addition. - Optional fields use `z.string()` as base (not `z.string().optional()`) before regex chaining, then `.optional()` is appended last. This ensures regex validation fires for non-empty optional fields while still allowing empty strings to pass. ## Deviations from Plan None — plan executed exactly as written. ## Issues Encountered None — TDD cycle completed cleanly. RED confirmed (9 failing before Task 2), GREEN achieved after Task 2 (4 VALID-01 reject tests now pass, 5 UX-01 tooltip tests remain failing as expected). ## Next Phase Readiness - Plan 07-02 (UX-01 tooltip toggle) has clear targets: all 5 UX-01 tests must turn green by adding `tooltipText?` content to sas_url/SFTP/OneDrive registry entries, adding ⓘ button to FieldRenderer, and adding SftpAuthToggle standalone tooltip - `tooltipText` is already on `FieldDef` interface — Plan 07-02 only needs to populate values and render the UI --- *Phase: 07-validation-ux-polish* *Completed: 2026-03-31*