Conversation
Add examples/cloudflare-sync-worker as a clean-room MIT Worker template for BYO R2 vault sync (VoltiusApp#267). Phase 1: GET /health, wrangler/vitest harness, and docs. Auth and R2 routes come next.
Require SYNC_TOKEN on /v1/* with timing-safe compare. Leave /health public. Return misconfigured when the secret is unset. Refs VoltiusApp#267.
Implement /v1/manifest with schema validation (salt, devices). Disable flaky vitest isolated R2 storage; tests clear the bucket. Refs VoltiusApp#267.
GET/PUT/DELETE /v1/devices/:id with JSON {content,label,pushedAt},
manifest upsert, and path-safe device ids. Serialize vitest files to
avoid shared R2 races. Refs VoltiusApp#267.
OPTIONS preflight and Access-Control-* on all responses. Document the MVP HTTP API in the worker README. Refs VoltiusApp#267.
Add plugin-cloudflare-sync mirrored on gist-sync: manifest, stub sync-engine, settings placeholder, i18n, and register cleanup tests. Refs VoltiusApp#267.
Typed helpers for health, manifest, and device blob routes with WorkerApiError mapping. Refs VoltiusApp#267.
Require passphrase for KDF (never the transport token). Setup/link, disconnect, device remove, pull-then-push syncNow, poll helpers, and unit tests with mocked worker-api. Refs VoltiusApp#267.
Connection fields (Worker URL, token, passphrase), create/link/health, sync now, poll interval, and disconnect. Refs VoltiusApp#267.
Register cloudflare-sync in build-plugins, Tauri SEEDED_IDS, and CI's Windows plugin bundle assert (six → seven). Update catalogue publish expectations. Refs VoltiusApp#267.
Show manifest devices with labels/timestamps and allow removing other devices from the Worker vault. Refs VoltiusApp#267.
Document one-click deploy for examples/cloudflare-sync-worker, plus setup:buckets / secret:token / deploy:easy scripts for CLI users. Refs VoltiusApp#267.
Deploy UX follow-upAdded a Deploy to Cloudflare button and a 3-command Wrangler path in
Happy to adjust the button URL to `VoltiusApp/voltius`/`dev` once this lands. |
Refuse Create vault when a remote vault already exists unless the user confirms overwrite, require https Worker URLs, start poll after configure, document the Worker threat model, and compare SYNC_TOKEN via SHA-256 digests to avoid length leaks.
Follow-up review (post live-test)Answers
Security review notes
Fixes in latest commit (
|
Wire plugin-cloudflare-sync into the titlebar, dropdown, settings, and effective-status selector (Voltius > Cloudflare > Gist). Tag plugin exportState blobs with the plugin id instead of hardcoded gist-sync.
Reject a wrong passphrase before leaving cloudflare-sync configured, and CAS manifest RMW with ETag/If-Match (412 on mismatch) plus bounded client pull+push retries.
Follow-up: remaining gaps addressedPushed to
Also: Local verification: client targeted suites 67 passed; Worker vitest 20 passed. Note: GitHub Actions |
|
Closing per maintainer guidance on #267: prefer marketplace-only, not seeded in-app, and keep the Worker template in our repo rather than upstream We’ll resubmit via VoltiusApp/marketplace once the standalone plugin + Worker are ready. Thanks for the review bandwidth — sorry for the misaligned delivery shape. |
|
Closing: pivoting to marketplace-only per #267 (kipavy). |
Summary
Adds a bring-your-own Cloudflare Worker + R2 encrypted sync path, complementary to GitHub Gist Sync and official Voltius cloud sync.
plugin-cloudflare-sync(seeded, optional,defaultEnabled: false)examples/cloudflare-sync-worker/(MIT, clean-room — opaque ciphertext only)Architecture
api.crypto.deriveKey(passphrase, salt)+exportState/importStates(same as Gist)SYNC_TOKENis never used as the KDF secretimportStates→ push local (poll default 60s)src/services/sync.tsWorker API
/health/v1/manifest/v1/devices/:idR2 keys:
manifest.json,devices/{id}.b64Test plan
pnpm exec vitest run src/plugins/cloudflare-syncpnpm exec vitest run tests/pluginCatalogPublish.test.ts(7 seeded plugins)pnpm exec node scripts/build-plugins.mjs cloudflare-syncpnpm --ignore-workspace testinexamples/cloudflare-sync-workerpnpm test/ cargo)Notes for maintainers
syncNowis exposed viaplugins.expose).runtime.exportStatecurrently stampsaccountId: "gist-sync"into the blob header for all plugin exports — pre-existing; CF reuses the same API without changing that host path in this PR.