Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

### Changed
- **`ww run` now requires a persistent identity by default.** Identity resolution no longer silently falls back to ephemeral keys when `--identity` is missing or points to a nonexistent file. Default lookup is `~/.ww/identity`; if absent, startup fails with a clear message and remediation. Operators can explicitly bypass with `--insecure-ephemeral` (named insecure on purpose), which restores prior ephemeral behavior for quick trial runs.
- **Admin UDS interface removed; `ww shell` is temporarily unavailable.** Removed the daemon-side Unix-domain admin service and its local socket discovery path. `ww shell` now remains as a forward-stable CLI surface but exits with `NOT IMPLEMENTED` until the replacement remote transport/auth path lands.
- **Filesystem data-plane contract tightened: backend is now root-layer-only and `perform fs` reads are deprecated.** The shell/MCP evaluation wrapper no longer routes data-plane reads through `(perform fs ...)`; filesystem reads now go through WASI path I/O (`load`, `import`, `/ipfs/...`, `/ipns/...`). The legacy `fs` handler remains only to return a migration-grade deprecation error. Backend virtual mount resolution now rejects targeted mounts (`source:/guest/path`) and accepts root layers only; `ww run` enforces this early with a CLI preflight error that lists offending mounts. Docs updated across `doc/shell.md`, `doc/capabilities.md`, and `doc/architecture.md` to reflect the single-path model.
- **CompilationService now uses a dedicated worker pool with in-flight dedupe.** The compiler subsystem moved from single-thread compile handling to a fixed worker pool (`WW_COMPILE_WORKERS`, default derived from CPU count), keys cache entries by `(wasm_blake3, engine identity)`, and coalesces concurrent duplicate compile requests so one cold compile serves all waiters.
- **Shell local-discovery policy aligned to per-user run dir.** `ww shell` local discovery now scans only `~/.ww/run/` for `<peer-id>.sock` entries (no `/var/run/ww` fallback), and the client fails deterministically with a disambiguation error when multiple local daemons are present instead of prompting interactively. Updated `src/discovery.rs`, `src/cli/shell.rs`, and shell/CLI docs to match this behavior and keep the local admin auth boundary consistently user-scoped.
Expand Down
21 changes: 7 additions & 14 deletions doc/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,11 @@ Connect to a running daemon and open a Glia REPL.
ww shell [ADDR] [--discover]
```

Today only the local-UDS path is implemented. The CLI surface for
remote shell access is forward-stable but currently exits with
`Error: NOT IMPLEMENTED`.
The admin UDS path has been removed. The command surface is preserved
for forward compatibility while remote transport/auth work lands, and
currently exits with `NOT IMPLEMENTED`.

- *(no args)* — connect to a local daemon over Unix Domain Socket at
`~/.ww/run/<peer-id>.sock`. Scans `~/.ww/run/`; if multiple daemons
are running locally it fails with a disambiguation error.
- *(no args)* — **NOT IMPLEMENTED.**
- `<multiaddr>` — **NOT IMPLEMENTED.** Future libp2p remote dial.
- `--discover` — **NOT IMPLEMENTED.** Future mDNS LAN browse.

Expand All @@ -115,21 +113,16 @@ compatibility; today both exit `NOT IMPLEMENTED`).
### Examples

```sh
ww shell # local UDS, auto-discover
ww shell # NOT IMPLEMENTED
ww shell /dnsaddr/master.wetware.run # NOT IMPLEMENTED (clap parse OK)
ww shell /ip4/127.0.0.1/tcp/2025 # NOT IMPLEMENTED (clap parse OK)
ww shell garbage # clap parse error: invalid multiaddr
```

### Auth model

The local UDS path is an admin endpoint. Filesystem permissions on
`~/.ww/run/` ARE the auth boundary — matching the
convention of `/var/run/docker.sock`, `~/.ipfs/api`, and
`~/.podman/podman.sock`. The spawned shell cell receives the daemon's
full membrane, unattenuated. There is no Noise handshake, no Terminal
challenge, no auth token. If you can write to the run dir, you can
admin the daemon.
No shell auth model is active right now because there is no live shell
transport path. The replacement design will use explicit remote auth.

See [shell.md](shell.md) for Glia syntax and the capabilities the
shell cell exposes.
Expand Down
3 changes: 1 addition & 2 deletions doc/runtimes.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ shared runtimes.
|---|---|---|---|
| Libp2p swarm | `swarm` (+ `ww-swarm-worker-*`) | `multi_thread` | TLS handshake parallelism — see below |
| Epoch pipeline | `epoch` | `current_thread` | Single linear consumer of L1 events |
| Admin UDS shell | `admin-uds` | `current_thread` + `LocalSet` | Cap'n Proto RPC drivers are `!Send` |
| Executor pool worker (×N) | `executor-N` | `current_thread` + `LocalSet` | `wasmtime::Store` is `!Send` |

The default is `current_thread`. We pick it because:
Expand Down Expand Up @@ -111,7 +110,7 @@ total thread budget is:

- 1 `swarm` OS thread (the supervisor's child)
- N `ww-swarm-worker-*` workers (tokio default)
- 1 `epoch`, 1 `admin-uds`
- 1 `epoch`
- M `executor-*` (also `available_parallelism()`)

On an 8-core Mac this lands around 18 threads under load, which is
Expand Down
121 changes: 11 additions & 110 deletions doc/shell.md
Original file line number Diff line number Diff line change
@@ -1,117 +1,18 @@
# Shell

The `ww shell` command opens an interactive Glia REPL against a running
wetware daemon. Today only the local-UDS path is implemented; the
forward-stable CLI surface for remote shell access (libp2p multiaddr,
mDNS LAN browse) is documented below but exits with
`Error: NOT IMPLEMENTED`.
The `ww shell` transport is currently unavailable.

## Connecting
The previous local admin UDS path has been removed, and the replacement
remote shell transport/auth path has not landed yet. For now, all
invocations of `ww shell` return `NOT IMPLEMENTED`.

```sh
ww shell # connect to local daemon via UDS
ww shell <multiaddr> # NOT IMPLEMENTED — future remote dial
ww shell --discover # NOT IMPLEMENTED — future LAN browse
```

With no arguments, `ww shell` scans `~/.ww/run/` for `<peer-id>.sock`
files. If exactly one daemon is running locally, it connects. If
multiple are running, it fails with a deterministic error listing the
discovered sockets. If none are running, it errors with a hint to run
`ww run .` first.

## Local admin gate (UDS)

The local path is an admin endpoint by design. Whoever can write to
`~/.ww/run/` has full administrative control of the daemon — by
convention with `/var/run/docker.sock`,
`~/.ipfs/api`, `~/.podman/podman.sock`, and similar local-CLI sockets.
Filesystem permissions on the run directory ARE the auth boundary;
there is no Noise handshake, no Terminal challenge, no auth token.

The spawned shell cell receives the daemon's **full membrane** — every
capability the daemon exposes, without attenuation. Admin scope is
exempt from epoch-based capability expiry: the shell remains usable for
the daemon's lifetime regardless of stem activity.

If you need auth-gated remote shell access in the future, that's a
separate `:listen` registration via init.d, with a `Terminal(Shell)`
gate per the April-2 design — see the
[design doc](https://github.com/wetware/ww/issues/452) for context.
## CLI Surface (Forward-Compatible)

## Syntax

Every expression is an S-expression. Effects use the `perform` form:
the first argument is the capability, the second is a keyword naming
the method, and the rest are method arguments.

```
(perform capability :method [args...])
```sh
ww shell
ww shell <multiaddr>
ww shell --discover
```

Strings are double-quoted. Symbols are bare words. Comments start with
`;` and run to end of line.

## Capabilities exposed to the shell

The shell cell currently grafts these caps from its membrane (see
`std/shell/src/lib.rs::run_impl`):

### host

| Method | Example | Description |
| ---------- | ------------------------------------------------------------- | -------------------------------------- |
| `id` | `(perform host :id)` | Peer ID (bs58-encoded string) |
| `addrs` | `(perform host :addrs)` | Listen multiaddrs |
| `peers` | `(perform host :peers)` | Connected peers with addresses |
| `connect` | `(perform host :connect "/ip4/1.2.3.4/tcp/2025/p2p/12D3...")` | Dial a peer |
| `listen` | `(perform host :listen "/ip4/0.0.0.0/tcp/0")` | Listen on an additional address |

### routing

| Method | Example | Description |
| --------------- | --------------------------------------------- | ------------------------------------ |
| `provide` | `(perform routing :provide cid)` | Announce as provider for a CID |
| `findProviders` | `(perform routing :findProviders cid)` | Find providers for a CID over DHT |

### Local effect handlers

The shell cell wires Glia-only local helpers that do not go through a
remote capability:

- **`import`** — load other Glia source files
- **`load`** dispatch form — read bytes from the WASI filesystem
- The kernel's built-in expressions: arithmetic, `let`, `if`, `defn`,
etc.

`(perform fs ...)` is deprecated and returns a migration error. Filesystem
reads should go through normal WASI file I/O (`load`, `import`, and guest
file operations on `/ipfs/...` / `/ipns/...` paths).

### Built-ins

| Form | Description |
| ------------------ | -------------------------------------------------------- |
| `(def name value)` | Bind a value in the session environment (persists) |
| `(help)` | Print available capabilities and methods |
| `(exit)` | Disconnect cleanly |

`def` state and any other env bindings persist for the lifetime of
the connection. A new `ww shell` session starts with a fresh cell
and an empty environment.

## Connection model

Each `ww shell` invocation spawns a fresh shell cell on the daemon
side via `executor.spawn_request()` — sessions are isolated by
construction. The cell exits cleanly when you `(exit)` or close stdin
(Ctrl-D).

The daemon side bridges your `tokio::net::UnixStream` to the cell's
WASI stdio via the existing `handle_vat_connection_spawn` helper
(`crates/rpc/src/vat_listener.rs`) — the same one used by the libp2p
path. The cell itself doesn't know which transport you connected over;
it sees a generic Cap'n Proto duplex.

For implementation details of the daemon-side service, see
[`src/admin_uds.rs`](../src/admin_uds.rs).
The command shape is intentionally preserved so the remote-shell rollout
can land without another CLI-breaking change.
Loading