Skip to main content

Module ext

Module ext 

Source
Expand description

Unified, effect-separated protocol abstraction shared by native and browser.

Design: functional core, imperative shell. A protocol author writes only a pure state transition over its own typed events and effects; all IO is performed by the extension’s own Interpret shell, which is handed a namespace-scoped capability (Scope) — send/inject confined to the interpreter’s own namespace.

Notation (used throughout the doc-comments here):

  decode : Wire ⇀ Event
  step   : (Ctx S, Event) → Transition (S, Effect)     where Transition (S,E) ≅ (S, [E])

The effect algebra is not global: each extension defines Protocol::Effect and the interpreter that runs it. The core owns no Effect enum — adding an extension never touches the core, and a protocol can only emit its own effects (no global command bus).

step is pure (no IO, clocks, globals) and total over well-typed events; the decode boundary makes “undecodable/foreign input” an explicit Reject instead of a silent no-op. The abstraction is identical on both targets; the sole divergence is the Send / ?Send bound, isolated in MaybeSend.

§Module layout

  • envelope — the wire Envelope.
  • protocol — the pure core: Wire/Reject (decode boundary), Ctx, Inbound (router-internal), Transition, and the Protocol trait.
  • interpret — the per-extension imperative shell (Interpret).
  • registry — the scoped capability Scope handed to shells, plus the router-internal Core / Handler and the namespace registry (Extensions).

Structs§

Ctx
Read-only state carrier passed into a step: the protocol’s current state S plus read-only node facts. The state is borrowed; a step returns the next state in its Transition rather than mutating in place.
Envelope
Namespaced message envelope carried over the P2P transport (bincode), in place of the old closed BackendMessage enum. payload is opaque to the core.
Extensions
Registry of (Protocol, Interpret) pairs by namespace, plus the router-internal Core. Cheaply cloneable and shared (interior mutability) so the Provider and the inbound callback see the same table.
Reject
The explicit result of a failed Protocol::decode: the input is malformed or not for this protocol. The router drops it (a defined no-op) instead of the pure step silently returning an unchanged state — so “valid no-op” and “undecodable input” are distinguishable.
Scope
A namespace-scoped capability handed to an Interpret shell — the effectful counterpart of the pure side’s read-only Ctx. Every action is confined to the interpreter’s own namespace: it may send to peers and self-inject only there, and it can neither reach another namespace nor forge a remote from. This is what keeps the capability honest: an extension shell cannot use the router as a generic inject-any-namespace bus (e.g. manufacture another extension’s lifecycle events). Cloneable and 'static, so a long-running engine task can keep a copy.
Transition
The output of a step: the next state and the protocol’s own effects to run. Transition (S, E) ≅ (S, [E]) — the Writer-over-State pair, now parameterized by the protocol’s private effect type E. PartialEq/Eq are derived (when S/E are) so tests can compare whole transitions.
Wire
The raw boundary input handed to Protocol::decode: an inbound message’s authenticated sender, this node’s own did, and the opaque payload bytes. decode turns this into the protocol’s typed Event (or rejects it).

Traits§

Interpret
Runs the effects produced by a protocol’s pure step. run returns the payloads to re-inject into the router; each is re-delivered to this protocol’s own namespace with from = this node — the router sets the provenance, so a shell can forge neither a namespace nor a remote from. A hard failure is an Err. Defined per-effect outcomes (e.g. “addressed no live session”) are the extension’s own concern and surfaced however it likes (its own return shapes / tests), not a core enum.
MaybeSend
Auto-trait bound that is Send + Sync on native and empty on browser.
Protocol
A protocol: a namespace, an initial state, a decode boundary, and a state transition that is pure by contract.