--- phase: 05-tech-debt plan: "01" type: execute wave: 1 depends_on: - "05-00" files_modified: - src/schemas/registry.ts - src/schemas/index.ts - src/components/wizard/RemoteConfigStep.tsx - src/components/wizard/BackendSelectionStep.tsx autonomous: true requirements: - TECH-03 - TECH-04 must_haves: truths: - "BACKEND_REGISTRY entries each have displayName, description, and fields properties" - "BackendSelectionStep renders cards using Object.entries(BACKEND_REGISTRY) — no hardcoded BACKENDS array" - "All consumers of BACKEND_REGISTRY access field arrays via .fields" - "BackendFormValues export is absent from src/schemas/index.ts" - "TypeScript compiles with zero errors after changes" artifacts: - path: "src/schemas/registry.ts" provides: "Enriched BACKEND_REGISTRY with displayName, description, fields" contains: "displayName" - path: "src/components/wizard/BackendSelectionStep.tsx" provides: "Registry-driven card list" contains: "Object.entries(BACKEND_REGISTRY)" key_links: - from: "src/schemas/registry.ts" to: "src/schemas/index.ts" via: "buildZodSchema accesses BACKEND_REGISTRY[backendType].fields" pattern: "\\.fields" - from: "src/schemas/registry.ts" to: "src/components/wizard/RemoteConfigStep.tsx" via: "field iteration uses BACKEND_REGISTRY[backendType].fields" pattern: "BACKEND_REGISTRY\\[backendType\\]\\.fields" - from: "src/schemas/registry.ts" to: "src/components/wizard/BackendSelectionStep.tsx" via: "Object.entries(BACKEND_REGISTRY) replaces BACKENDS const" pattern: "Object\\.entries\\(BACKEND_REGISTRY\\)" --- Enrich BACKEND_REGISTRY with display metadata, wire BackendSelectionStep to derive its card list from the registry, update all consumers to use .fields access, and remove the dead BackendFormValues export. Purpose: TECH-03 makes the registry the single source of truth for both field definitions AND display metadata — Phase 6 backend additions auto-surface with zero additional UI code. TECH-04 removes dead code. Output: registry.ts with new shape, BackendSelectionStep.tsx driven by registry, schemas/index.ts clean. @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/05-tech-debt/05-CONTEXT.md @.planning/phases/05-tech-debt/05-RESEARCH.md @.planning/phases/05-tech-debt/05-00-SUMMARY.md From src/schemas/registry.ts (CURRENT shape — executor REPLACES this): ```typescript export type BackendType = 'azureblob' | 's3' | 's3-compatible'; export interface FieldDef { key, label, inputType, required, placeholder?, helpText?, options? } export const BACKEND_REGISTRY: Record = { ... } ``` New shape (TECH-03 target): ```typescript export const BACKEND_REGISTRY: Record = { azureblob: { displayName: 'Azure Blob Storage', description: 'Microsoft Azure cloud storage', fields: [ /* existing FieldDef[] content unchanged */ ], }, s3: { displayName: 'Amazon S3', description: 'AWS Simple Storage Service', fields: [ /* existing FieldDef[] content unchanged */ ], }, 's3-compatible': { displayName: 'S3-Compatible', description: 'Wasabi, MinIO, Cloudflare R2, and others', fields: [ /* existing FieldDef[] content unchanged */ ], }, }; ``` Display strings MUST match existing BackendSelectionStep card text exactly (test assertions check these strings). From src/schemas/index.ts line 10 (consumer 1 — must update): ```typescript const fields = BACKEND_REGISTRY[backendType]; // CHANGE TO: BACKEND_REGISTRY[backendType].fields ``` From src/components/wizard/RemoteConfigStep.tsx (consumers 2 and 3 — must update): ```typescript // Line 58: BACKEND_REGISTRY.azureblob.find(f => f.key === 'account') // CHANGE TO: BACKEND_REGISTRY.azureblob.fields.find(f => f.key === 'account') // Line 73: BACKEND_REGISTRY[backendType].map(field => ...) // CHANGE TO: BACKEND_REGISTRY[backendType].fields.map(field => ...) ``` From src/components/wizard/BackendSelectionStep.tsx (TECH-03 — replace hardcoded BACKENDS): ```typescript // Remove: const BACKENDS: { type: BackendType; name: string; description: string }[] = [...] // Replace rendering with: import { BACKEND_REGISTRY } from '../../schemas/registry'; // ... {Object.entries(BACKEND_REGISTRY).map(([type, entry]) => ( handleCardClick(type as BackendType)} /> ))} ``` From src/schemas/index.ts lines 27-28 (TECH-04 — remove entirely): ```typescript // REMOVE these two lines: export type BackendFormValues = z.infer; ``` Task 1: Enrich BACKEND_REGISTRY and update all consumers src/schemas/registry.ts, src/schemas/index.ts, src/components/wizard/RemoteConfigStep.tsx - registry.test.ts 'each backend entry has displayName and description metadata' passes - registry.test.ts 'each backend has at least one field definition' passes (via .fields.length) - registry.test.ts 'Azure Blob has account field' passes (via .fields.find) - schemas/index.ts buildZodSchema receives FieldDef[] from .fields — all BACKEND_SCHEMAS build correctly - RemoteConfigStep renders fields correctly (existing RemoteConfigStep.test.tsx passes) 1. Edit src/schemas/registry.ts: - Change BACKEND_REGISTRY value type from `FieldDef[]` to `{ displayName: string; description: string; fields: FieldDef[] }` - Wrap each backend's existing FieldDef array in the new object shape, adding displayName and description - displayName and description strings MUST match the existing BACKENDS array in BackendSelectionStep.tsx exactly: - azureblob: displayName='Azure Blob Storage', description='Microsoft Azure cloud storage' - s3: displayName='Amazon S3', description='AWS Simple Storage Service' - s3-compatible: displayName='S3-Compatible', description='Wasabi, MinIO, Cloudflare R2, and others' - All existing FieldDef content is preserved unchanged inside fields 2. Edit src/schemas/index.ts line 10: - Change `const fields = BACKEND_REGISTRY[backendType];` to `const fields = BACKEND_REGISTRY[backendType].fields;` 3. Edit src/components/wizard/RemoteConfigStep.tsx: - Line 58: Change `BACKEND_REGISTRY.azureblob.find(f => f.key === 'account')` to `BACKEND_REGISTRY.azureblob.fields.find(f => f.key === 'account')` - Line 73: Change `BACKEND_REGISTRY[backendType].map(field =>` to `BACKEND_REGISTRY[backendType].fields.map(field =>` cd /c/Users/SebastienQUEROL/Documents/projets/Ready2Blob && npx vitest run src/schemas/registry.test.ts src/components/wizard/RemoteConfigStep.test.tsx 2>&1 | tail -15 registry.test.ts passes with all tests green (including new displayName/description test and .fields access tests). RemoteConfigStep.test.tsx still passes. TypeScript sees no errors on the modified files. Task 2: Wire BackendSelectionStep to registry + remove dead export src/components/wizard/BackendSelectionStep.tsx, src/schemas/index.ts - BackendSelectionStep renders 'Azure Blob Storage', 'Amazon S3', 'S3-Compatible' cards (from registry, not hardcoded) - Azure Blob card appears before S3 in DOM order (Object.entries insertion order preserved) - Clicking a card with a valid remote name still dispatches SET_BACKEND_TYPE and SET_STEP (existing WIZD-01 test passes) - BackendFormValues type is absent from src/schemas/index.ts - npx tsc --noEmit exits with code 0 1. Edit src/components/wizard/BackendSelectionStep.tsx: - Add import: `import { BACKEND_REGISTRY } from '../../schemas/registry';` - Remove the `BACKENDS` constant entirely (lines 21-37) - In the JSX rendering section, replace `{BACKENDS.map((backend) => (` block with: ```tsx {Object.entries(BACKEND_REGISTRY).map(([type, entry]) => ( handleCardClick(type as BackendType)} /> ))} ``` - Remove the now-unused local type import for BackendType from '../../store/types' IF it is only used by the BACKENDS const (check — it may still be needed for pendingBackend.current type annotation). If BackendType is still needed, keep the import. 2. Edit src/schemas/index.ts: - Remove lines 27-28: the `export type BackendFormValues = z.infer;` export - Also remove the blank comment line above it (line 26: `// Utility type: infer TypeScript type from a backend's Zod schema`) to avoid orphan comment 3. Run TypeScript check to confirm no consumers of BackendFormValues exist: `npx tsc --noEmit` cd /c/Users/SebastienQUEROL/Documents/projets/Ready2Blob && npx vitest run src/components/wizard/BackendSelectionStep.test.tsx && npx tsc --noEmit 2>&1 | tail -10 BackendSelectionStep.test.tsx passes (WIZD-01 card text assertions still green — display strings match). npx tsc --noEmit exits with zero errors. BackendFormValues export is absent from src/schemas/index.ts. Full suite green except pre-existing RED stubs (TECH-01, TECH-02 ReviewStep stubs remain RED — implemented in Plan 02): ``` cd /c/Users/SebastienQUEROL/Documents/projets/Ready2Blob && npx vitest run && npx tsc --noEmit ``` Expected: All registry tests green, all BackendSelectionStep tests green, RemoteConfigStep tests green. Only TECH-01/TECH-02 ReviewStep stubs still RED. - BACKEND_REGISTRY shape is `Record` - BackendSelectionStep uses `Object.entries(BACKEND_REGISTRY)` — no hardcoded BACKENDS array - schemas/index.ts uses `.fields` access and has no BackendFormValues export - RemoteConfigStep uses `.fields` access - registry.test.ts fully green - BackendSelectionStep.test.tsx fully green - npx tsc --noEmit: zero errors After completion, create `.planning/phases/05-tech-debt/05-01-SUMMARY.md`