Files

8.1 KiB
Raw Permalink Blame History

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
07-validation-ux-polish 01 execute 2
07-00
src/schemas/registry.ts
src/schemas/index.ts
true
VALID-01
truths artifacts key_links
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
path provides contains
src/schemas/registry.ts FieldDef interface with validate property; 3 registry entries with validate rules validate?: { regex: RegExp; message: string }
path provides contains
src/schemas/index.ts buildZodSchema() chains .regex() when field.validate is present field.validate
from to via pattern
BACKEND_REGISTRY azureblob.account buildZodSchema('azureblob') field.validate.regex applied as .regex() on ZodString field.validate
from to via
buildZodSchema() BACKEND_SCHEMAS 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).

<execution_context> @C:/Users/SebastienQUEROL/.claude/get-shit-done/workflows/execute-plan.md @C:/Users/SebastienQUEROL/.claude/get-shit-done/templates/summary.md </execution_context>

@.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):

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):

function buildZodSchema(backendType: BackendType): z.ZodObject<Record<string, z.ZodTypeAny>> {
  const fields = BACKEND_REGISTRY[backendType].fields;
  const shape: Record<string, z.ZodTypeAny> = {};
  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 324 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 324 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<Record<string, z.ZodTypeAny>> {
  const fields = BACKEND_REGISTRY[backendType].fields;
  const shape: Record<string, z.ZodTypeAny> = {};
  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

<success_criteria>

  • 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 </success_criteria>
After completion, create `.planning/phases/07-validation-ux-polish/07-01-SUMMARY.md`