--- phase: 06-new-backends plan: "01" type: execute wave: 1 depends_on: - "06-00" files_modified: - src/schemas/registry.ts - src/schemas/index.ts - src/generators/rclone-conf.ts autonomous: true requirements: - BACK-01 - BACK-03 - BACK-04 must_haves: truths: - "BackendType union includes 'onedrive', 'gcs', 'b2' (and 'sftp' added by Plan 02)" - "BACKEND_REGISTRY has onedrive, gcs, b2 entries with correct field keys matching rclone docs" - "BACKEND_SCHEMAS has onedrive, gcs, b2 entries built via buildZodSchema" - "RCLONE_TYPE_MAP maps gcs to 'google cloud storage' (with spaces)" - "buildRcloneConf(gcsState) outputs 'type = google cloud storage'" - "buildRcloneConf(b2State) outputs 'type = b2'" - "buildRcloneConf(onedriveState) outputs 'type = onedrive'" artifacts: - path: "src/schemas/registry.ts" provides: "BackendType union with 6 types (onedrive, gcs, b2 added); registry entries for all three" contains: "onedrive.*gcs.*b2" - path: "src/schemas/index.ts" provides: "BACKEND_SCHEMAS with onedrive, gcs, b2" contains: "buildZodSchema('onedrive')" - path: "src/generators/rclone-conf.ts" provides: "RCLONE_TYPE_MAP with gcs mapped to 'google cloud storage'" contains: "google cloud storage" key_links: - from: "src/schemas/index.ts" to: "src/schemas/registry.ts" via: "buildZodSchema calls — BackendType must include new types before BACKEND_SCHEMAS can reference them" pattern: "buildZodSchema\\('(onedrive|gcs|b2)'\\)" - from: "src/generators/rclone-conf.ts" to: "RCLONE_TYPE_MAP" via: "gcs key maps to string with spaces — critical for correct rclone.conf output" pattern: "gcs.*google cloud storage" --- Add OneDrive, GCS, and Backblaze B2 to the data layer — BackendType union, registry entries, Zod schemas, and RCLONE_TYPE_MAP. Purpose: Three simple backends (no custom toggle UI) that follow the pure registry + FieldRenderer pattern. Implementing them first keeps SFTP (Plan 02) isolated. Output: registry.ts, index.ts, rclone-conf.ts updated; registry and rclone-conf tests go green for these three backends. @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/06-new-backends/06-RESEARCH.md @.planning/phases/06-new-backends/06-00-SUMMARY.md From src/schemas/registry.ts (current): ```typescript export type BackendType = 'azureblob' | 's3' | 's3-compatible'; export interface FieldDef { key: string; label: string; inputType: 'text' | 'password' | 'select' | 'toggle'; required: boolean; placeholder?: string; helpText?: string; options?: { value: string; label: string }[]; } export const BACKEND_REGISTRY: Record = { azureblob: {...}, s3: {...}, 's3-compatible': {...} }; ``` From src/schemas/index.ts (current): ```typescript function buildZodSchema(backendType: BackendType): z.ZodObject> export const BACKEND_SCHEMAS = { azureblob: buildZodSchema('azureblob'), s3: buildZodSchema('s3'), 's3-compatible': buildZodSchema('s3-compatible'), } as const; ``` From src/generators/rclone-conf.ts (current): ```typescript const RCLONE_TYPE_MAP: Record = { azureblob: 'azureblob', s3: 's3', 's3-compatible': 's3', }; ``` Task 1: Extend registry.ts — BackendType union + onedrive/gcs/b2 entries src/schemas/registry.ts - BackendType union becomes: 'azureblob' | 's3' | 's3-compatible' | 'onedrive' | 'sftp' | 'gcs' | 'b2' (include 'sftp' in union now — Plan 02 adds its registry entry; including it in the union prevents TypeScript errors in Plan 02's parallel work) - BACKEND_REGISTRY gains onedrive entry: token (password, required), drive_id (text, required), drive_type (select, required, options: personal/business/documentLibrary) - BACKEND_REGISTRY gains gcs entry: project_number (text, required), service_account_credentials (password, required) - BACKEND_REGISTRY gains b2 entry: account (text, required), key (password, required) - sftp entry NOT added here — Plan 02 adds it. TypeScript will error on BACKEND_REGISTRY type until Plan 02 adds sftp. This is acceptable during parallel execution. - `npx vitest run src/schemas/registry.test.ts` passes for onedrive, gcs, b2 assertions; sftp assertions still fail (Plan 02 fixes those) Edit src/schemas/registry.ts: 1. Replace BackendType line with: `export type BackendType = 'azureblob' | 's3' | 's3-compatible' | 'onedrive' | 'sftp' | 'gcs' | 'b2';` 2. Add three new entries to BACKEND_REGISTRY after the 's3-compatible' entry: ```typescript onedrive: { displayName: 'OneDrive', description: 'Microsoft OneDrive (paste pre-obtained rclone token)', fields: [ { key: 'token', label: 'OAuth Token (JSON)', inputType: 'password', required: true, placeholder: '{"access_token":"...","token_type":"Bearer","refresh_token":"...","expiry":"..."}', helpText: 'Paste the JSON token from: rclone authorize "onedrive"', }, { key: 'drive_id', label: 'Drive ID', inputType: 'text', required: true, placeholder: 'b!...', helpText: 'The drive ID from your OneDrive. Found in the rclone authorize output.', }, { key: 'drive_type', label: 'Drive Type', inputType: 'select', required: true, options: [ { value: 'personal', label: 'Personal' }, { value: 'business', label: 'Business' }, { value: 'documentLibrary', label: 'SharePoint Document Library' }, ], helpText: 'Personal for consumer OneDrive, Business for Microsoft 365', }, ], }, gcs: { displayName: 'Google Cloud Storage', description: 'Google Cloud Storage', fields: [ { key: 'project_number', label: 'Project Number', inputType: 'text', required: true, placeholder: '123456789', helpText: 'Your GCP project number (not project ID)', }, { key: 'service_account_credentials', label: 'Service Account JSON', inputType: 'password', required: true, placeholder: '{"type":"service_account","project_id":"..."}', helpText: 'Paste the full content of your service account JSON key file', }, ], }, b2: { displayName: 'Backblaze B2', description: 'Backblaze B2 Cloud Storage', fields: [ { key: 'account', label: 'Application Key ID', inputType: 'text', required: true, placeholder: 'your-application-key-id', helpText: 'The applicationKeyId — not the master account ID', }, { key: 'key', label: 'Application Key', inputType: 'password', required: true, helpText: 'The application key (secret value from the B2 dashboard)', }, ], }, ``` Note: BACKEND_REGISTRY type is `Record` which requires ALL BackendType values. After this task, TypeScript will error because 'sftp' is in the union but not yet in the BACKEND_REGISTRY object. Plan 02 adds the sftp entry. If running `npx tsc --noEmit` between plans, expect this error temporarily. The Vitest tests will still run. npx vitest run src/schemas/registry.test.ts 2>&1 | tail -20 BackendType includes all 7 types; onedrive, gcs, b2 registry entries present with correct field keys; registry tests pass for those three backends Task 2: Extend index.ts and rclone-conf.ts — schemas + type map for onedrive/gcs/b2 src/schemas/index.ts, src/generators/rclone-conf.ts - BACKEND_SCHEMAS gains onedrive, gcs, b2 entries using buildZodSchema - RCLONE_TYPE_MAP gains: onedrive → 'onedrive', gcs → 'google cloud storage', b2 → 'b2' - buildRcloneConf(gcsState) produces a line 'type = google cloud storage' (with spaces — NOT 'type = gcs') - buildRcloneConf(b2State) produces 'type = b2' with account and key lines - buildRcloneConf(onedriveState) produces 'type = onedrive' with token, drive_id, drive_type lines - `npx vitest run src/generators/rclone-conf.test.ts` passes for onedrive, gcs, b2 describe blocks **src/schemas/index.ts:** Add three entries to BACKEND_SCHEMAS: ```typescript export const BACKEND_SCHEMAS = { azureblob: buildZodSchema('azureblob'), s3: buildZodSchema('s3'), 's3-compatible': buildZodSchema('s3-compatible'), onedrive: buildZodSchema('onedrive'), gcs: buildZodSchema('gcs'), b2: buildZodSchema('b2'), } as const; ``` Do NOT add sftp yet — Plan 02 adds it after adding the sftp registry entry. **src/generators/rclone-conf.ts:** Extend RCLONE_TYPE_MAP: ```typescript const RCLONE_TYPE_MAP: Record = { azureblob: 'azureblob', s3: 's3', 's3-compatible': 's3', onedrive: 'onedrive', gcs: 'google cloud storage', // NOTE: spaces in rclone type value — do NOT shorten b2: 'b2', }; ``` Do NOT add sftp yet — Plan 02 adds it. After editing, run full suite to confirm existing tests still pass and new backend tests pass. npx vitest run src/schemas/registry.test.ts src/generators/rclone-conf.test.ts 2>&1 | tail -20 BACKEND_SCHEMAS covers onedrive/gcs/b2; RCLONE_TYPE_MAP maps gcs to 'google cloud storage'; rclone-conf tests for onedrive/gcs/b2 pass; no regressions on existing backends `npx vitest run src/schemas/registry.test.ts src/generators/rclone-conf.test.ts` Expected: onedrive/gcs/b2 tests GREEN; sftp tests still RED (Plan 02 fixes those); no regressions on azureblob/s3/s3-compatible. `npx tsc --noEmit` — expect one error: BACKEND_REGISTRY missing 'sftp' key (fixed by Plan 02). All other TypeScript must be clean. - BackendType union has all 7 types - onedrive, gcs, b2 registry entries with correct rclone key names - BACKEND_SCHEMAS covers onedrive, gcs, b2 - gcs maps to 'google cloud storage' in RCLONE_TYPE_MAP - rclone-conf tests pass for onedrive, gcs, b2 - Zero TypeScript errors outside the known sftp-missing-key error After completion, create `.planning/phases/06-new-backends/06-01-SUMMARY.md`