diff --git a/docs/research/iroh-blobs-eval.md b/docs/research/iroh-blobs-eval.md index 1aa7857..b043904 100644 --- a/docs/research/iroh-blobs-eval.md +++ b/docs/research/iroh-blobs-eval.md @@ -31,7 +31,9 @@ Lessons for alkblobs: - **The command-enum-as-contract is a working pattern** (it is what makes iroh-blobs' remote/local symmetry possible), but it carries the whole irpc machinery into the store layer and *is* the reason their - store is welded to their transport. POC #1's lean `Backend` trait is + store is welded to their protocol stack (theirs also welds transport + endpoints above that; the store-actor weld alone is what kills + backend swappability). POC #1's lean `Backend` trait is the smaller hammer for our split: the trait stays dumb (opaque bytes), and any ops surface above it (alkcall) speaks its own protocol. - **Re-borrowed conclusion, not mechanism: per-hash serialized actors.** @@ -175,7 +177,7 @@ findings (first-party, measured). ## Do-not-inherit list (re-confirmed against 0.103) - The `Command`-actor + irpc store abstraction (welds store to their - transport stack). + protocol stack; endpoints/transport weld on above it). - redb-specific entry-state modeling if we go sqlite (their tables and `EntryState` postcard encoding are theirs; our sqlite schema is `key → (value, size)` and our dispatch is store-layer policy). diff --git a/docs/research/phase-0.md b/docs/research/phase-0.md index b04ed9a..a527f9d 100644 --- a/docs/research/phase-0.md +++ b/docs/research/phase-0.md @@ -29,8 +29,9 @@ documents (`poc-trait-dispatch-findings.md`, `poc-largeblob-findings.md`, a put/get/verify store keyed under one canonical content hash (the git-family derivation; legacy SHA-1-tolerant), with pluggable backends (small blobs in a kv/sqlite-ish store, large blobs on a filesystem -fallback), split from any transport/protocol layer, with auth-gated -network operations riding the alkcall seam (OQ-BL-01). +fallback), split from any wire/ops-protocol layer (framing, op family, +ACL ride the alkcall substrate when they exist — OQ-BL-01), which is +itself transport-free (alkcall is a pure protocol crate). **Why this crate exists (the converging consumers):** @@ -82,15 +83,16 @@ The implications for this crate: alkcall substrate (OQ-BL-01), whether it lives in this crate or a sibling. -**The scope line:** this crate is the *store*, not the *transport*. -iroh-blobs welds store + provider protocol + tickets + postcard into -one crate; the defining posture here is the opposite split — -put/get/verify against a hash is its own layer, and any -provider/protocol/ops surface lives above it or in feature-gated -modules (the alk* inversion-point pattern). "Above it" does not mean -"without alkcall": the ops surface *is* alkcall-shaped (OQ-BL-01) — -what the store layer itself must never grow is transport, framing, or -auth internals. What stays *above* the crate regardless: repos/ +**The scope line:** this crate is the *store*, not the *wire/ops +protocol*. iroh-blobs welds store + provider protocol + tickets + +postcard into one crate; the defining posture here is the opposite +split — put/get/verify against a hash is its own layer, and any +ops/protocol surface lives above it or in feature-gated modules (the +alk* inversion-point pattern). "Above it" does not mean "without +alkcall": the ops surface *is* alkcall-shaped (OQ-BL-01) — what the +store layer itself must never grow is wire framing, op dispatch, ACL, +or transport (alkcall carries none of the last either; the connection +is handed to it). What stays *above* the crate regardless: repos/ workspaces as reference sets (trees/manifests), path→hash mapping, git semantics, the contract/gossip/replicator policy layer. @@ -304,16 +306,22 @@ appfile pattern this crate now owns by its own validated design. ### alkcall — the substrate (and the ops surface's foundation) -`/workspace/@alkdev/alkcall` (the call + channels RPC crate). The ops -surface rides it (OQ-BL-01, settled): JSON-shaped control ops with -JSON Schema validation and typed error schemas (ADR-016), binary -streaming via the `channel_open` marker (ADR-047) in both directions -(`Sub` ADR-021 for verified fetch, `Pub`/`HandlerKind::Sink` ADR-046 -for put), ACL via `AccessControl` + ownership checks (ADR-011) under -the ADR-017 privilege model, and the established data-path patterns +`/workspace/@alkdev/alkcall` (the call + channels RPC crate). **It +contains no transport code** — no networking dependencies (README: +"a pure protocol crate — no networking, no transport dependencies"); +a `Connection` wraps an already-established byte stream that the +*caller* provides (dialing/listening happens above it, per ADR-012's +dial/call decoupling). What it owns is the wire/ops protocol: JSON +op family with JSON Schema validation and typed error schemas +(ADR-016), binary streaming via the `channel_open` marker (ADR-047) +in both directions (`Sub` ADR-021 for verified fetch, `Pub`/ +`HandlerKind::Sink` ADR-046 for put), ACL via `AccessControl` + +ownership checks (ADR-011) under the ADR-017 privilege model, service +discovery, and N-channel multiplexing; established data-path patterns (`BiStream`, two-pump `pump_bidi` ADR-050). The store layer itself stays alkcall-free (principle 1: substrate-agnostic); alkcall enters -only at the ops module/sibling boundary. +only at the ops module/sibling boundary — which is where transport, +if p2p git ever needs a specific one, enters above *that*. ## Open Questions @@ -330,11 +338,12 @@ are now settled separately. decision rather than an inherited assumption.) The original draft's "undecided pending the first consumer's shape" conflated two things: iroh-blobs' *actual* weld (no Store trait — its message-actor store is -inseparable from the irpc transport machinery, the thing convention 7 +inseparable from the irpc protocol machinery, the thing convention 7 rejects) and the presence of a protocol substrate under the ops layer, which is a different layer entirely and is family-standard. The inverted-point posture constrains the *store layer only*: the store -grows no transport, framing, or auth internals. It does not argue for +grows no wire framing, op dispatch, ACL, or transport internals. It +does not argue for an ops layer that reinvents them. Why alkcall specifically, rather than an in-band op scheme: @@ -362,10 +371,12 @@ Why alkcall specifically, rather than an in-band op scheme: - **The store stays substrate-agnostic regardless.** alkcall enters only at the ops module/sibling layer, behind the store's public surface — the same relationship alkhttp's handlers have to their - storage. If alkcall were ever unavailable, the store layer loses - nothing (that independence is principle 1); the point is that the - ops surface, when it exists, does *not* re-implement what the - substrate provides. + storage. If the ops surface were ever re-homed, the store layer + loses nothing (that independence is principle 1); the point is that + the ops surface, when it exists, does *not* re-implement what the + substrate provides — and neither layer grows transport, which has + no home in either crate (alkcall's `Connection` is handed in, not + dialed). **The crate-boundary question — reduced to placement only:** given an alkcall-shaped op family, the remaining choice is where the