/ architecture / choices.md
choices.md
1 Great — now we’re at the point where we can stop being abstract and be **opinionated**. 2 3 Below is a **cohesive, end-to-end architecture** where **each layer uses the option that makes the most sense together**, not just individually. This is essentially a **reference P2P system design** optimized for: 4 5 * browser + native 6 * offline-first 7 * capability security 8 * minimal ceremony 9 * maximal leverage of Cap’n Web 10 11 I’ll flag when a choice is a *layer* vs a *cross-cutting concern*. 12 13 --- 14 15 # The “sane default” P2P stack (opinionated) 16 17 --- 18 19 ## 0. Threat model & trust assumptions *(foundation)* 20 21 **Choice** 22 23 * Zero central authority 24 * Mutual distrust by default 25 * Explicit capability delegation 26 * Eventual consistency 27 * Offline-first 28 29 **Why** 30 This aligns with: 31 32 * CRDTs 33 * content addressing 34 * UCAN 35 * Cap’n Web’s authority-by-reference 36 37 --- 38 39 ## 1. Identity *(layer)* 40 41 ### ✅ Choice 42 43 **ed25519 keypair → `did:key`** 44 45 **Why this is the sweet spot** 46 47 * Small keys 48 * Fast signatures 49 * Browser-compatible 50 * DID gives structure without infrastructure 51 52 **Result** 53 54 ```text 55 did:key:z6Mk… 56 ``` 57 58 --- 59 60 ## 2. Secure transport *(layer)* 61 62 ### ✅ Choice 63 64 **Noise protocol (XX or IK)** 65 66 **Why** 67 68 * Mutual auth 69 * No PKI 70 * Works in P2P 71 * Used by libp2p, WireGuard 72 73 **Browser note** 74 75 * WebRTC DTLS (fallback) 76 * Identity bound via fingerprint 77 78 --- 79 80 ## 3. Peer discovery *(layer)* 81 82 ### ✅ Choice 83 84 **Hybrid discovery** 85 86 * DHT (Kademlia) 87 * QR / invite links 88 * Optional rendezvous server 89 90 **Why** 91 92 * Pure P2P alone has bad UX 93 * Hybrid keeps decentralization while being usable 94 95 --- 96 97 ## 4. Session establishment *(layer)* 98 99 ### ✅ Choice 100 101 **Noise handshake + UCAN presentation** 102 103 Flow: 104 105 1. Secure channel established 106 2. UCAN sent once 107 3. Verified locally 108 4. Cap’n Web session starts 109 110 **Why** 111 112 * Cryptographic trust 113 * No ambient authority 114 * No OAuth servers 115 116 --- 117 118 ## 5. Portable authorization *(layer)* 119 120 ### ✅ Choice 121 122 **UCAN** 123 124 **Why UCAN over Biscuit here** 125 126 * Delegation chains map to P2P 127 * JWT-compatible 128 * DID-native 129 * Designed specifically as “OAuth for decentralized systems” 130 131 **Usage** 132 133 * One UCAN per intent 134 * Short expiry 135 * Scoped to resources 136 137 --- 138 139 ## 6. Connection-local authorization *(layer)* 140 141 ### ✅ Choice 142 143 **Cap’n Web object-capabilities** 144 145 **Why** 146 147 * Eliminates permission checks 148 * Impossible to misuse 149 * Perfect fit with UCAN minting 150 151 **Pattern** 152 153 ```ts 154 if (ucan.allows("doc:write")) { 155 return new DocumentEditor(docId); 156 } 157 ``` 158 159 --- 160 161 ## 7. Storage *(layer)* 162 163 ### ✅ Choice 164 165 **Content-addressed storage (CAS)** 166 167 Examples: 168 169 * IPLD blocks 170 * IPFS-compatible DAGs 171 * Hash-addressed blobs 172 173 **Why** 174 175 * Integrity by default 176 * Deduplication 177 * Natural fit with Merkle replication 178 179 **Local backing** 180 181 * IndexedDB (browser) 182 * RocksDB / SQLite (native) 183 184 --- 185 186 ## 8. Replication *(layer)* 187 188 ### ✅ Choice 189 190 **Merkle-DAG replication** 191 192 **Why** 193 194 * Partial sync 195 * Lazy fetch 196 * Integrity-preserving 197 * Proven at scale 198 199 **Mechanism** 200 201 * Exchange root CIDs 202 * Fetch missing blocks 203 * Verify hashes 204 205 --- 206 207 ## 9. Sync *(layer)* 208 209 ### ✅ Choice 210 211 **CRDTs (Automerge / Yjs)** 212 213 **Why** 214 215 * Offline edits 216 * No conflicts 217 * No locks 218 * Real-time collaboration 219 220 **Storage model** 221 222 * CRDT ops stored as blocks 223 * Addressed by hash 224 * Replicated via DAG 225 226 --- 227 228 ## 10. Consistency model *(cross-cutting)* 229 230 ### ✅ Choice 231 232 **Explicit eventual consistency** 233 234 **Why** 235 236 * Anything stronger breaks P2P 237 * UX can be designed around it 238 * Cap’n Web is async-first 239 240 --- 241 242 ## 11. State ownership & mutation authority *(layer)* 243 244 ### ✅ Choice 245 246 **Capability-scoped mutation** 247 248 Rules: 249 250 * Read = hash 251 * Write = capability 252 * Delete = lease + capability 253 254 **Why** 255 256 * No ACLs 257 * No roles 258 * No global policy engine 259 260 --- 261 262 ## 12. Delegation *(layer)* 263 264 ### ✅ Choice 265 266 **Dual delegation** 267 268 * UCAN for cross-peer 269 * Cap’n Web objects for in-session 270 271 **Why** 272 273 * UCAN is portable 274 * Cap’n Web is ergonomic 275 276 --- 277 278 ## 13. Revocation *(cross-cutting)* 279 280 ### ✅ Choice 281 282 **Expiration + connection lifetime** 283 284 * UCANs expire quickly 285 * Cap’n Web dies on disconnect 286 * Keys rotate rarely 287 288 **Why** 289 290 * Global revocation is poison in P2P 291 292 --- 293 294 ## 14. Versioning & history *(layer)* 295 296 ### ✅ Choice 297 298 **Immutable append-only history** 299 300 * CRDT log 301 * Merkle-linked snapshots 302 303 **Why** 304 305 * Debuggable 306 * Auditable 307 * Undo/redo for free 308 309 --- 310 311 ## 15. Garbage collection *(layer)* 312 313 ### ✅ Choice 314 315 **Reachability-based GC** 316 317 Rules: 318 319 * Retain pinned roots 320 * Drop unreachable blocks 321 * Respect leases 322 323 --- 324 325 ## 16. Performance & flow control *(cross-cutting)* 326 327 ### ✅ Choice 328 329 **Async backpressure** 330 331 * Streaming iterators 332 * Windowed replication 333 * Cap’n Web pipelining 334 335 --- 336 337 ## 17. Application protocol *(layer)* 338 339 ### ✅ Choice 340 341 **Cap’n Web RPC** 342 343 **Why** 344 345 * Bidirectional 346 * Object-capability native 347 * No schemas 348 * Browser-first 349 * Promise pipelining 350 351 --- 352 353 ## 18. UX & developer ergonomics *(layer)* 354 355 ### ✅ Choice 356 357 **Capability-driven APIs** 358 359 Principle: 360 361 > *If you can call it, you’re allowed to.* 362 363 No: 364 365 * auth middleware 366 * role checks 367 * headers 368 * global state 369 370 --- 371 372 # Final “best sense” stack (one glance) 373 374 ``` 375 UX / APIs → Cap’n Web 376 Application Capabilities → Cap’n Web objects 377 Portable Authorization → UCAN 378 Identity → ed25519 / did:key 379 Secure Transport → Noise / WebRTC 380 Peer Discovery → DHT + invites 381 Sync → CRDTs 382 Replication → Merkle DAG 383 Storage → Content-addressed 384 ``` 385 386 --- 387 388 # Why this stack is unusually coherent 389 390 Because **every layer shares the same mental model**: 391 392 * Identity = keys 393 * Authority = capabilities 394 * State = immutable history 395 * Change = mergeable ops 396 * Interaction = async objects 397 398 There are **no impedance mismatches**. 399 400 That’s rare. 401 402 --- 403 404 # If you want to go even deeper next 405 406 We could: 407 408 * Walk a **single write** from keystroke → CRDT op → DAG block → replication → Cap’n Web call 409 * Compare this stack to **Solid / ActivityPub / Matrix** 410 * Design a **minimal prototype** 411 * Talk about **global invariants** (the hardest part) 412 * Explore **how far Cap’n Web can go in pure P2P** 413 414 Just tell me where you want to drill down.