--- phase: 13-add-remaining-rclone-remotes plan: 01 type: execute wave: 1 depends_on: [] files_modified: - src/schemas/registry.ts - src/schemas/index.ts - src/store/types.ts - src/generators/rclone-conf.ts - src/schemas/registry.test.ts - src/schemas/index.test.ts - src/generators/rclone-conf.test.ts autonomous: true requirements: [REMOTE-01, REMOTE-02, REMOTE-06] must_haves: truths: - "BACKEND_REGISTRY contains all 17 backends with correct fields and category" - "BackendType is derived from registry keys, not an explicit union" - "BACKEND_SCHEMAS auto-generates from registry (no manual per-backend calls)" - "RCLONE_TYPE_MAP has correct type strings for all 17 backends" - "buildRcloneConf produces valid rclone.conf for every new backend" artifacts: - path: "src/schemas/registry.ts" provides: "17 backend entries with category field, BackendType derived via keyof" contains: "as const" - path: "src/schemas/index.ts" provides: "Auto-generated BACKEND_SCHEMAS from registry keys" contains: "Object.fromEntries" - path: "src/generators/rclone-conf.ts" provides: "RCLONE_TYPE_MAP entries for all 17 backends" key_links: - from: "src/schemas/registry.ts" to: "src/store/types.ts" via: "BackendType re-export" pattern: "export type.*BackendType" - from: "src/schemas/registry.ts" to: "src/schemas/index.ts" via: "BACKEND_SCHEMAS auto-generation" pattern: "Object\\.keys\\(BACKEND_REGISTRY\\)" --- Refactor the backend registry to support 17 backends with categories, derive BackendType from registry keys, auto-generate BACKEND_SCHEMAS, and add all 10 new backend entries with correct rclone type mappings. Purpose: This is the data foundation every other plan in Phase 13 depends on. No UI work can proceed until the registry has all backends, the types are derived, and schemas auto-generate. Output: Updated registry.ts, index.ts, types.ts, rclone-conf.ts with all 17 backends, full test coverage. @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/STATE.md @.planning/phases/13-add-remaining-rclone-remotes/13-CONTEXT.md @.planning/phases/13-add-remaining-rclone-remotes/13-RESEARCH.md From src/schemas/registry.ts: ```typescript export type BackendType = 'azureblob' | 's3' | 's3-compatible' | 'onedrive' | 'sftp' | 'gcs' | 'b2'; export interface FieldDef { key: string; label: string; inputType: 'text' | 'password' | 'select' | 'toggle'; required: boolean; placeholder?: string; helpText?: string; options?: { value: string; label: string }[]; validate?: { regex: RegExp; message: string }; tooltipText?: string; } // Current cast at bottom (must be removed): // } as Record; ``` From src/schemas/index.ts: ```typescript export const BACKEND_SCHEMAS = { azureblob: buildZodSchema('azureblob'), // ... explicit per-backend calls } as const; ``` From src/generators/rclone-conf.ts: ```typescript const RCLONE_TYPE_MAP: Record = { azureblob: 'azureblob', s3: 's3', 's3-compatible': 's3', onedrive: 'onedrive', sftp: 'sftp', gcs: 'google cloud storage', b2: 'b2', }; ``` From src/store/types.ts: ```typescript import type { BackendType } from '../schemas/registry'; export type { BackendType }; ``` Task 1: Refactor registry types and add all 10 new backend entries src/schemas/registry.ts, src/store/types.ts 1. Add `BackendCategory` type: `'cloud-object-storage' | 'cloud-drives' | 'protocol-based'` 2. Add `category` field to the backend entry shape. Update the interface used by entries to include `category: BackendCategory`. 3. Remove the explicit `BackendType` union literal. Instead, add `as const` to the BACKEND_REGISTRY object and derive: `export type BackendType = keyof typeof BACKEND_REGISTRY;` 4. CRITICAL: Remove the `as Record` cast at the bottom of the registry object. With `as const`, TypeScript infers the precise type. The cast creates a circular reference when BackendType is derived from keyof. 5. Add `category` to all 7 existing entries: - azureblob: 'cloud-object-storage' - s3: 'cloud-object-storage' - s3-compatible: 'cloud-object-storage' - gcs: 'cloud-object-storage' - b2: 'cloud-object-storage' - onedrive: 'cloud-drives' - sftp: 'protocol-based' 6. Add 10 new backend entries (see 13-RESEARCH.md for field details): Cloud Object Storage: - `azure-files`: displayName 'Azure Files', fields: account (text, required), key (password, required). Verify field names against rclone.org/azurefiles/ — account + key is the standard pattern. - `swift`: displayName 'OpenStack Swift', fields: user (text, required), key (password, required), auth (text, required, placeholder 'https://auth.example.com/v3'), tenant (text, required), region (text, optional) Cloud Drives (OAuth token-paste): - `gdrive`: displayName 'Google Drive', fields: token (password, required, helpText about rclone authorize "drive"), service_account_credentials (password, optional, helpText for service account JSON), root_folder_id (text, optional) - `dropbox`: displayName 'Dropbox', fields: token (password, required, helpText about rclone authorize "dropbox") - `box`: displayName 'Box', fields: token (password, required), box_sub_type (select: user/enterprise, default 'user') - `pcloud`: displayName 'pCloud', fields: token (password, required), hostname (select: api.pcloud.com/eapi.pcloud.com with labels 'US (default)'/'EU') Protocol-based: - `ftp`: displayName 'FTP', fields: host (text, required), user (text, optional, placeholder 'anonymous'), pass (password, optional), port (text, optional, placeholder '21'), explicit_tls (select: ''/true with labels 'Plain FTP'/'Explicit FTPS') - `webdav`: displayName 'WebDAV', fields: url (text, required, placeholder 'https://example.com/dav'), user (text, required), pass (password, required), vendor (select: nextcloud/owncloud/sharepoint/sharepoint-ntlm/other) - `smb`: displayName 'SMB / Windows Share', fields: host (text, required), user (text, required), pass (password, optional), domain (text, optional, placeholder 'WORKGROUP'), port (text, optional, placeholder '445') - `http`: displayName 'HTTP (read-only)', fields: url (text, required, placeholder 'https://example.com/path/') - `seafile`: displayName 'Seafile', fields: url (text, required, placeholder 'https://cloud.seafile.com'), user (text, required), pass (password, required) 7. Add appropriate helpText and tooltipText to new backend fields following existing patterns (see 13-RESEARCH.md pitfalls section for OAuth token fields). 8. Verify src/store/types.ts still works — it does `import type { BackendType } from '../schemas/registry'` and `export type { BackendType }`. No changes needed since the derived type exports identically. IMPORTANT: Do NOT pass real placeholder text to fields that will be rendered by TextFieldMD3 — TextFieldMD3 uses `placeholder=" "` internally for floating labels. Use `helpText` instead for descriptive hints. Placeholders are only safe on fields NOT rendered via TextFieldMD3 (select fields, or fields where the placeholder is a format example like 'AKIAIOSFODNN7EXAMPLE'). npx vitest run src/schemas/registry.test.ts src/store/ --reporter=verbose 2>&1 | tail -30 BACKEND_REGISTRY has 17 entries each with displayName, description, category, and fields. BackendType is derived from keyof typeof BACKEND_REGISTRY. No circular type reference. TypeScript compiles cleanly. Task 2: Auto-generate BACKEND_SCHEMAS, update RCLONE_TYPE_MAP, update tests src/schemas/index.ts, src/generators/rclone-conf.ts, src/schemas/index.test.ts, src/generators/rclone-conf.test.ts, src/schemas/registry.test.ts 1. In src/schemas/index.ts: Replace the explicit BACKEND_SCHEMAS object with auto-generation: ```typescript export const BACKEND_SCHEMAS = Object.fromEntries( (Object.keys(BACKEND_REGISTRY) as BackendType[]).map(t => [t, buildZodSchema(t)]) ) as Record>; ``` This eliminates the need to add a manual `buildZodSchema()` call per new backend. 2. In src/generators/rclone-conf.ts: Add entries to RCLONE_TYPE_MAP for all 10 new backends. Verified type strings from rclone docs: - 'azure-files': 'azurefiles' - 'swift': 'swift' - 'gdrive': 'drive' - 'dropbox': 'dropbox' - 'box': 'box' - 'pcloud': 'pcloud' - 'ftp': 'ftp' - 'webdav': 'webdav' - 'smb': 'smb' - 'http': 'http' - 'seafile': 'seafile' 3. Update src/schemas/registry.test.ts: - Add test: every backend has displayName, description, category, and at least one field - Add test: BackendCategory values are one of the three valid categories - Verify all 17 backend keys are present 4. Update/create src/schemas/index.test.ts: - Test that BACKEND_SCHEMAS has an entry for every key in BACKEND_REGISTRY (no undefined) - Test that each schema is a ZodObject (not undefined) 5. Update src/generators/rclone-conf.test.ts: - Add test: RCLONE_TYPE_MAP has entry for every BackendType - Add a buildRcloneConf snapshot test for at least 3 new backends (gdrive, ftp, smb) to confirm correct output format npx vitest run src/schemas/ src/generators/rclone-conf.test.ts --reporter=verbose 2>&1 | tail -40 BACKEND_SCHEMAS auto-generates for all 17 backends. RCLONE_TYPE_MAP covers all 17 backends. All tests pass including new coverage for auto-generation, type mapping, and rclone.conf output for new backends. - `npx vitest run` — full suite green (no regressions) - TypeScript compiles: `npx tsc --noEmit` — no errors - All 17 backend keys present in BACKEND_REGISTRY - BackendType derived (no explicit union) - BACKEND_SCHEMAS auto-generated (no manual calls) - 17 backends in BACKEND_REGISTRY with category field - BackendType = keyof typeof BACKEND_REGISTRY (derived, not explicit) - BACKEND_SCHEMAS auto-generated from registry keys - RCLONE_TYPE_MAP has all 17 entries with verified rclone type strings - All existing + new tests pass - TypeScript compiles without errors After completion, create `.planning/phases/13-add-remaining-rclone-remotes/13-01-SUMMARY.md`