Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

### Changed
- **Examples now default to shell-forward demos with explicit Glia snippets.** Example READMEs now guide users through daemon + `ww shell` flows (`load glia/register.glia`, plus `serve`/`consume` snippets where relevant), per-example demo wiring moved from `examples/*/etc/init.d/*.glia` into new `examples/*/glia/*.glia` snippet files, and `doc/images.md` now documents init.d boot as deployment guidance rather than the demo default.
- **Init export policy switched to a bare capability map with recursive `attenuate` support (shell + init).** `init.glia` must now return a bare export map (legacy `:export/:caps/:methods` is rejected), kernel boot remains fail-closed with strict unknown-cap errors, and recursive attenuation authored via existing Glia `attenuate` syntax is enforced at the membrane/RPC proxy layer for cap-returning paths (including `host.network`, `runtime.load`, `identity.signer`, and `ipfs.read`). Added init-system docs under `doc/init.md` and migrated bundled/example init scripts to the new policy shape.
- **Dynamic-cap return paths now use typed envelopes (`TypedCap`) with schema nodes, and WW_ROOT path handling is hardened against symlink escapes.** `Process.bootstrap`, `VatClient.dial`, and `VatHandler.serve` now flow through `TypedCap { cap, schema }` (`SchemaBundle` uses `schema.Node` root + deps), recursive attenuation wrappers consume typed schema metadata, and policy/docs/tests were updated to match the hard cutover. `load-file`, kernel `list-dir`, and kernel `path-is-dir` now enforce WW_ROOT containment against both lexical traversal and symlink escape paths.
- **Vat protocol now performs inline schema attestation before Cap'n Proto starts.** On `/ww/0.1.0/vat/{cid}`, listener writes a versioned schema-attestation preface (canonical `schema.Node` bytes) before RPC bootstrap; dialer verifies magic/version, canonicalizes payload, recomputes CID, and hard-fails on mismatch. `VatClient.dial` now returns typed schema from attested producer bytes (not caller-echoed schema input).
- **AutoNAT v2 probe observability exposed with bounded history (#512).** Added a ring-buffered `nat_probe_events` surface in runtime `NetworkState` (tested address, probing server peer ID, result, timestamp), wired capture from `AutonatV2` events, and exposed operator JSON at admin `GET /host/nat` alongside existing node-level `nat_status`.
- **`system.Ipfs` read API is now stream-only (`read -> ByteStream`).** Removed `Ipfs.readStream` and changed `Ipfs.read` to return `ByteStream`, consolidating capability attenuation to a single read method while retaining chunked daemon-backed transfer semantics for `/ipfs`, `/ipns`, and `/ipld` paths.
- **`ww shell --mcp` now runs MCP process-local in the shell path (#508).** Replaced daemon-spawned `std/mcp` WASM execution with a process-local MCP JSON-RPC loop in the CLI that reuses shell dial/login/graft auth flow and local Glia evaluation, while keeping daemon-backed transport/auth/capability dispatch unchanged.
Expand Down Expand Up @@ -599,6 +602,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
- 14 unit tests covering host lifecycle, executor pool scheduling, round-robin distribution, panic handling, exit code piping, and bounded channel backpressure

### Changed
- `Process.bootstrap` now requires `schema: Data` and enforces non-empty schema payloads.
- Recursive export attenuation now enforces `AnyPointer` return edges at RPC proxy boundaries for `vat-client.dial.cap` and `process.bootstrap.cap`.
- `spawn_rpc_inner` and child cell spawn paths use ambient `LocalSet` instead of nested `LocalSet`, enabling proper M:N cooperative scheduling across cells on the same worker thread
- `SwarmService` and `EpochService` now respect shutdown signal via `tokio::select!`
- `ExecutorPool` stores worker `JoinHandle`s and joins them on drop for clean shutdown
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ curl http://localhost:2080/status
}
```

The second command hit a WebAssembly cell running inside the daemon. The cell can't read your filesystem, reach the network, or see your environment variables. The only thing it can do is what the membrane handed it; in this case, the `host` capability, so it can report your peer ID and connected peers. The wiring that hands the `host` capability (and nothing else) to the HTTP handler cell lives at `~/.ww/etc/init.d/05-status.glia`:
The second command hit a WebAssembly cell running inside the daemon. The cell can't read your filesystem, reach the network, or see your environment variables. The only thing it can do is what the membrane handed it; in this case, the `host` capability, so it can report your peer ID and connected peers. The wiring that hands the `host` capability (and nothing else) to the HTTP handler cell lives in `~/.ww/etc/init.d/05-status.glia` (orchestrated by `~/.ww/etc/init.glia`):

```clojure
(perform host :listen (cell (load "bin/status.wasm")) "/status")
Expand Down
24 changes: 17 additions & 7 deletions capnp/system.capnp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@
@0xbf5147b78c0e6a2f;

using MembraneSchema = import "membrane.capnp";
using Schema = import "/capnp/schema.capnp";

struct SchemaBundle {
root @0 :Schema.Node;
deps @1 :List(Schema.Node);
}

struct TypedCap {
cap @0 :Capability;
schema @1 :SchemaBundle;
}

struct PeerInfo {
peerId @0 :Data; # libp2p peer ID, serialized.
Expand Down Expand Up @@ -128,9 +139,9 @@ interface Process {
wait @3 () -> (exitCode :Int32);
# Block until the process exits and return its exit code.

bootstrap @4 () -> (cap :AnyPointer);
# Return the capability exported by the guest via system::serve().
# The cap is type-erased — cast to the expected interface on the guest side.
bootstrap @4 (schema :Data) -> (typed :TypedCap);
# Return the capability exported by the guest via system::serve() with
# producer-attached schema metadata required for recursive attenuation.
# Errors if the guest didn't export a capability.

kill @5 () -> ();
Expand All @@ -141,7 +152,7 @@ struct VatHandler {
union {
spawn @0 :Executor;
# Stateless: spawn a fresh cell per connection.
serve @1 :AnyPointer;
serve @1 :TypedCap;
# Stateful: bootstrap all connections with this persistent capability.
}
}
Expand All @@ -166,15 +177,14 @@ interface VatListener {
}

interface VatClient {
dial @0 (peer :Data, schema :Data) -> (cap :AnyPointer);
dial @0 (peer :Data, schema :Data) -> (typed :TypedCap);
# Open a Cap'n Proto RPC connection to peer on /ww/0.1.0/vat/{cid}
# where cid = CIDv1(raw, BLAKE3(schema)).
# The schema is the canonical Cap'n Proto encoding of a schema.Node.
# Bootstraps a Cap'n Proto vat over the stream and returns the remote
# cell's bootstrap capability.
#
# The returned cap is type-erased (AnyPointer) — cast it to the expected
# interface type on the guest side.
# Returns a capability plus schema metadata for recursive attenuation.
}

interface ByteStream {
Expand Down
Loading
Loading