Files

210 lines
8.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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"
---
<objective>
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).
</objective>
<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>
<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
<interfaces>
<!-- Extracted from codebase. Executor uses these directly. -->
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<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).
</interfaces>
</context>
<tasks>
<task type="auto" tdd="true">
<name>Task 1: Extend FieldDef and add validate rules to 3 registry entries</name>
<files>src/schemas/registry.ts</files>
<behavior>
- 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
</behavior>
<action>
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.
</action>
<verify>
<automated>npx vitest run src/components/wizard/RemoteConfigStep.test.tsx</automated>
</verify>
<done>FieldDef has validate and tooltipText properties. 3 registry entries have validate rules. TypeScript compiles without errors (npx tsc --noEmit).</done>
</task>
<task type="auto" tdd="true">
<name>Task 2: Extend buildZodSchema() to chain .regex() from field.validate</name>
<files>src/schemas/index.ts</files>
<behavior>
- 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
</behavior>
<action>
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.
</action>
<verify>
<automated>npx vitest run src/components/wizard/RemoteConfigStep.test.tsx</automated>
</verify>
<done>VALID-01 tests from Plan 00 all pass (GREEN). Full suite still at 147+ pass with 0 failures: `npx vitest run`.</done>
</task>
</tasks>
<verification>
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
</verification>
<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>
<output>
After completion, create `.planning/phases/07-validation-ux-polish/07-01-SUMMARY.md`
</output>