# toybox Vats whose code is installed at runtime: each vat is a Durable Object whose app runs as a [facet](https://developers.cloudflare.com/dynamic-workers/usage/durable-object-facets/) on code loaded through workerd's Worker Loader. Think `vatAdmin.createVat(bundle)`, with a supervisor per vat. - [supervisor.js](supervisor.js): `Vat` stores code by SHA-256 and runs the app on it; `Public` and `Admin` are the two entrypoints; `Egress` is a vat's `fetch`. - [switchboard.js](switchboard.js): a separate workerd process, the vats' only way out: a forward proxy for HTTP and WebSockets. - [config.capnp](config.capnp): the sockets have no addresses; whoever starts workerd hands them in, so holding a socket is the authority it grants. | socket | reaches | what its holder can do | |---|---|---| | `http` | `Public` | `GET //…`: talk to a vat's app | | `admin` | `Admin` | `PUT /` with an ES module body: install it and (re)start the app; its storage carries over. `?egress=` grants the app that one host. | An app must export `class App extends DurableObject` (see [apps/](apps/)). It gets an empty `env`. With no grant, `fetch` throws; with one, its `globalOutbound` is `Egress` with the granted host in `ctx.props`, which forwards matching requests, WebSocket upgrades included, to the switchboard and refuses the rest with a 403. toybox reaches the switchboard over a unix socket (`-e switchboard=unix:…`), in HTTP proxy style so the full URL, scheme included, survives the hop. ## Run it ```sh pnpm install pnpm test # real workerds: install, upgrade, isolation, egress grants, fetch and WebSocket out, crash and restart pnpm switchboard # systemd-socket-activate on ./switchboard.sock pnpm start # likewise on 127.0.0.1:8787 and ./admin.sock; state in ./state ``` Then, in a third terminal: ```sh curl -X PUT --unix-socket admin.sock --data-binary @apps/counter-v1.js http://toybox/alice curl localhost:8787/alice # v1 count 1 curl -X PUT --unix-socket admin.sock --data-binary @apps/counter-v2.js http://toybox/alice curl localhost:8787/alice # v2 count 2 curl -X PUT --unix-socket admin.sock --data-binary @apps/egress-probe.js 'http://toybox/erin?egress=example.com' curl 'localhost:8787/erin?url=https://example.com/' # got: … curl 'localhost:8787/erin?url=https://example.org/' # got: egress to example.org not granted ``` ## Under systemd [systemd/](systemd/) has socket and service pairs for toybox and its switchboard, assuming this directory is installed at `/opt/toybox`. toybox gets no network of its own (`PrivateNetwork=yes`): only the two sockets it is handed and the switchboard's socket, which only members of the `toybox` group can open. The switchboard has the network, fenced by `IPAddressDeny=`; `switchboard.capnp` allows `local` addresses only so the tests can reach a local echo server. Neither unit has been run under the system manager yet. `PrivateNetwork=` needs the system manager; as a `systemd-run --user` unit, systemd logs "lack privileges for network namespace, proceeding without".