9.4 KiB
Fileverse + rStack Integration Plan
Key Architectural Decision: Y.js vs Automerge
rSpace already uses both Automerge and Y.js:
- Automerge 2.2.8 — Document state, sync protocol, binary wire format
- Y.js 13.6 — TipTap editor binding (
y-prosemirror), IndexedDB persistence (y-indexeddb)
Fileverse uses Y.js exclusively for CRDTs.
Assessment
rSpace's dual approach is actually well-positioned. The Y.js layer handles editor collaboration (which is what Fileverse's components need), while Automerge handles the broader document state management. We don't need to choose one — the integration points are at the Y.js/TipTap layer.
Decision: Keep both. Integrate Fileverse at the Y.js/TipTap layer.
The Automerge sync protocol handles state replication, while Y.js handles real-time editor cursors and awareness. Fileverse's ddoc component and collaboration-server plug into the Y.js side.
Phase 1: Crypto Primitives Evaluation
Status: Not started
Effort: 1–2 days
Target: Determine whether to use @fileverse/crypto or build equivalent from MIT libs
rSpace DocCrypto (existing)
- AES-256-GCM for document encryption
- HKDF key derivation: Master key → Space key → Doc key
- Key material from EncryptID passkey PRF
- Location:
rspace-online/shared/local-first/crypto.ts
@fileverse/crypto (Fileverse)
- ECIES (asymmetric encryption via elliptic curves)
- NaCl SecretBox (symmetric authenticated encryption via TweetNaCl)
- RSA envelope encryption for large messages
- HKDF key derivation
- Argon2id password hashing
Comparison
| Feature | DocCrypto | @fileverse/crypto |
|---|---|---|
| Symmetric encryption | AES-256-GCM (Web Crypto) | NaCl SecretBox (TweetNaCl) |
| Asymmetric encryption | Not implemented | ECIES + RSA |
| Key derivation | HKDF (Web Crypto) | HKDF + Argon2id |
| Key hierarchy | Master → Space → Doc | Flat (per-operation) |
| Sharing keys between users | Not implemented | ECIES key exchange |
| Security audit | No | No |
| License | Proprietary (rStack) | AGPL-3.0 |
Gap Analysis
rSpace's DocCrypto lacks:
- Asymmetric encryption — needed to share document keys between collaborators without a central server
- Key exchange — ECIES allows encrypting a doc key for a specific collaborator's public key
- Password-derived keys — Argon2id enables password-protected notes (useful for shared links)
MIT Alternatives
The underlying primitives in @fileverse/crypto are all MIT-licensed:
- Noble curves (
@noble/curves) — ECIES elliptic curve operations - StableLib (
@stablelib/x25519,@stablelib/hkdf) — Key exchange and derivation - TweetNaCl (
tweetnacl) — SecretBox symmetric encryption - argon2-browser — Argon2id in WASM
Recommendation: Build a thin wrapper around MIT libs, matching @fileverse/crypto's API where useful. This avoids AGPL while gaining all the cryptographic capabilities.
Tasks
- Benchmark NaCl SecretBox vs AES-256-GCM (performance + bundle size)
- Implement ECIES key exchange using Noble curves
- Add Argon2id for password-protected notes
- Test interop: can we decrypt Fileverse-encrypted content?
Phase 2: IPFS File Storage
Status: Not started Effort: 3–5 days Target: Replace centralized file uploads with IPFS-backed storage Resolves: rNotes TASK-4 (file/image upload)
Architecture
Client Server/IPFS
│ │
├─ Pick file │
├─ Encrypt (SecretBox) │
├─ Upload encrypted blob ───────►│ Store on IPFS
│◄──────── Return CID ──────────┤
├─ Store CID + key in │
│ document metadata │
│ │
├─ To view: fetch CID ─────────►│ Return encrypted blob
│◄──────────────────────────────┤
├─ Decrypt locally │
└─ Display │
Options
A. Use Fileverse's storage service
- Requires UCAN tokens for authorization
- Depends on Fileverse infrastructure
- No self-hosting option documented
B. Self-host IPFS node on Netcup
- Full control over storage
kubo(go-ipfs) orhelia(JS)- Pin encrypted blobs, serve via gateway
- CIDs stored in Automerge documents
C. Use Pinata/web3.storage
- Managed IPFS pinning
- Free tiers available
- Less operational overhead
Recommendation: Start with option C (managed pinning) for POC, migrate to B (self-hosted) for production.
Tasks
- Set up Pinata account and API keys (store in Infisical)
- Build upload service: encrypt → pin → return CID
- Build retrieval service: fetch CID → decrypt → serve
- Add TipTap image extension that uses IPFS CIDs
- Test with rNotes note editor
Phase 3: Collaboration Server
Status: Not started Effort: 3–5 days Target: Self-host Fileverse's collaboration-server on Netcup
Requirements
- Node.js runtime
- MongoDB (temporary update storage)
- Redis (session management)
- WebSocket support via Traefik
Deployment Plan
# docker-compose.yml on Netcup
services:
collab-server:
image: node:20-slim
# Build from github.com/fileverse/collaboration-server
environment:
PORT: 5000
MONGODB_URI: mongodb://collab-mongo:27017/collab
CORS_ORIGINS: "https://rnotes.jeffemmett.com,https://rspace.jeffemmett.com"
labels:
- "traefik.enable=true"
- "traefik.http.routers.collab.rule=Host(`collab.jeffemmett.com`)"
- "traefik.http.routers.collab.tls.certresolver=letsencrypt"
depends_on:
- collab-mongo
- collab-redis
collab-mongo:
image: mongo:7
volumes:
- collab-mongo-data:/data/db
collab-redis:
image: redis:7-alpine
volumes:
- collab-redis-data:/data
Integration with rSpace
The collaboration-server uses Y.js sync protocol. rSpace already has Y.js for TipTap. Integration points:
- Connect TipTap's
y-prosemirrorbinding to collab-server WebSocket - Use collab-server's awareness protocol for cursor presence
- Automerge sync continues separately for document state
UCAN Auth Integration
Fileverse's collab-server uses UCAN tokens. Options:
- Adapt: Generate UCANs from EncryptID DIDs (preferred)
- Bypass: Fork server, replace UCAN auth with EncryptID JWT
- Bridge: Proxy auth through an adapter service
Tasks
- Fork collaboration-server, evaluate auth integration
- Create Docker Compose config for Netcup
- Deploy with Traefik routing
- Connect rSpace TipTap editor to collab-server
- Test real-time collaboration between two clients
Phase 4: dSheet as rSheet Module
Status: Not started
Effort: 5–7 days
Target: Integrate @fileverse-dev/dsheet as a new rStack module
Architecture
rstack-online/
└── modules/
└── rsheet/ # New module
├── schemas.ts # Automerge schemas for spreadsheet metadata
├── components/
│ └── folk-sheet-app.ts # LitElement wrapper around dSheet
├── local-first-client.ts # Sync integration
└── converters/
├── csv.ts # CSV import/export
└── xlsx.ts # Excel import/export
dSheet Component Props
<DSheet
isAuthorized={true}
dsheetId="room-id" // Collaboration room
enableWebrtc={true} // P2P sync
enableIndexeddbSync={true} // Offline persistence
isCollaborative={true} // Multi-user
onChange={handleChange} // Data callback
/>
Integration Points
- Use rSpace's EncryptID auth for
isAuthorized - Generate
dsheetIdfrom Automerge document ID - Route WebRTC signaling through self-hosted collab-server
- Store spreadsheet metadata in Automerge (title, permissions, CID)
- Store spreadsheet data in IndexedDB (via dSheet's built-in support)
Use Cases for rStack
- DAO treasury tracking (live blockchain data queries)
- Token allocation spreadsheets
- Budget planning with E2E encryption
- Research data tables alongside rNotes
Tasks
- Create rSheet module scaffold in rspace-online
- Wrap dSheet React component in LitElement
- Wire auth and collaboration
- Add CSV/XLSX import/export converters
- Deploy and test
Phase 5: Advanced — UCAN + Decentralized Identity
Status: Future Effort: 5+ days
Goals
- Complement EncryptID with UCAN capability tokens
- Decentralized authorization without central server
- Fine-grained permissions: read, write, share, admin per document
UCAN Flow
User (EncryptID DID) → Mint UCAN → Delegate to collaborator
↓
Collaborator presents UCAN to:
- Collaboration server (real-time sync)
- Storage server (file uploads)
- IPFS gateway (content retrieval)
Timeline
| Phase | Duration | Dependencies |
|---|---|---|
| 1. Crypto evaluation | 1–2 days | None |
| 2. IPFS storage | 3–5 days | Phase 1 |
| 3. Collab server | 3–5 days | None (parallel with Phase 2) |
| 4. dSheet module | 5–7 days | Phase 3 |
| 5. UCAN auth | 5+ days | Phases 2, 3 |