Files
kawaandClaude Opus 4.6 4bf3f1e45f docs(13): create phase plan for backend expansion
4 plans across 3 waves to expand from 7 to 17 rclone backends:
- Plan 01 (W1): Registry refactoring, BackendType derivation, 10 new entries
- Plan 02 (W2): OAuthInstructions, GdriveAuthToggle, BackendIcons components
- Plan 03 (W2): BackendSelectionStep UX overhaul with categories, search, icons
- Plan 04 (W3): RemoteConfigStep wiring for all new backends + visual verify

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 15:58:51 +02:00

236 lines
11 KiB
Markdown

---
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\\)"
---
<objective>
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.
</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/STATE.md
@.planning/phases/13-add-remaining-rclone-remotes/13-CONTEXT.md
@.planning/phases/13-add-remaining-rclone-remotes/13-RESEARCH.md
<interfaces>
<!-- Current contracts that will be refactored -->
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<BackendType, { displayName: string; description: string; fields: FieldDef[] }>;
```
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<string, string> = {
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 };
```
</interfaces>
</context>
<tasks>
<task type="auto">
<name>Task 1: Refactor registry types and add all 10 new backend entries</name>
<files>src/schemas/registry.ts, src/store/types.ts</files>
<action>
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<BackendType, ...>` 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').
</action>
<verify>
<automated>npx vitest run src/schemas/registry.test.ts src/store/ --reporter=verbose 2>&1 | tail -30</automated>
</verify>
<done>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.</done>
</task>
<task type="auto">
<name>Task 2: Auto-generate BACKEND_SCHEMAS, update RCLONE_TYPE_MAP, update tests</name>
<files>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</files>
<action>
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<BackendType, ReturnType<typeof buildZodSchema>>;
```
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
</action>
<verify>
<automated>npx vitest run src/schemas/ src/generators/rclone-conf.test.ts --reporter=verbose 2>&1 | tail -40</automated>
</verify>
<done>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.</done>
</task>
</tasks>
<verification>
- `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)
</verification>
<success_criteria>
- 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
</success_criteria>
<output>
After completion, create `.planning/phases/13-add-remaining-rclone-remotes/13-01-SUMMARY.md`
</output>