8.1 KiB
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 |
|
|
true |
|
|
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.mdCurrent 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 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.
```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.
<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>