docs(06-new-backends): create phase plan
4 plans across 3 waves: Wave 0 TDD stubs, Wave 1 data layer (parallel: OneDrive/GCS/B2 + SFTP/SftpAuthToggle), Wave 2 RemoteConfigStep wiring. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,288 @@
|
||||
---
|
||||
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"
|
||||
---
|
||||
|
||||
<objective>
|
||||
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.
|
||||
</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/06-new-backends/06-RESEARCH.md
|
||||
@.planning/phases/06-new-backends/06-00-SUMMARY.md
|
||||
|
||||
<interfaces>
|
||||
<!-- Current state of files before modification -->
|
||||
|
||||
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<BackendType, {
|
||||
displayName: string;
|
||||
description: string;
|
||||
fields: FieldDef[];
|
||||
}> = { azureblob: {...}, s3: {...}, 's3-compatible': {...} };
|
||||
```
|
||||
|
||||
From src/schemas/index.ts (current):
|
||||
```typescript
|
||||
function buildZodSchema(backendType: BackendType): z.ZodObject<Record<string, z.ZodTypeAny>>
|
||||
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<string, string> = {
|
||||
azureblob: 'azureblob',
|
||||
s3: 's3',
|
||||
's3-compatible': 's3',
|
||||
};
|
||||
```
|
||||
</interfaces>
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto" tdd="true">
|
||||
<name>Task 1: Extend registry.ts — BackendType union + onedrive/gcs/b2 entries</name>
|
||||
<files>src/schemas/registry.ts</files>
|
||||
<behavior>
|
||||
- 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)
|
||||
</behavior>
|
||||
<action>
|
||||
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<BackendType, ...>` 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.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>npx vitest run src/schemas/registry.test.ts 2>&1 | tail -20</automated>
|
||||
</verify>
|
||||
<done>BackendType includes all 7 types; onedrive, gcs, b2 registry entries present with correct field keys; registry tests pass for those three backends</done>
|
||||
</task>
|
||||
|
||||
<task type="auto" tdd="true">
|
||||
<name>Task 2: Extend index.ts and rclone-conf.ts — schemas + type map for onedrive/gcs/b2</name>
|
||||
<files>src/schemas/index.ts, src/generators/rclone-conf.ts</files>
|
||||
<behavior>
|
||||
- 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
|
||||
</behavior>
|
||||
<action>
|
||||
**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<string, string> = {
|
||||
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.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>npx vitest run src/schemas/registry.test.ts src/generators/rclone-conf.test.ts 2>&1 | tail -20</automated>
|
||||
</verify>
|
||||
<done>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</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
`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.
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- 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
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/06-new-backends/06-01-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user