A microVM has no init unless something is it, and three of the jobs belong to
nothing else in the guest: reaping whatever the workload orphans, turning a
signal into an ordered shutdown, and being the guest end of the one channel
out.
None of it knows what it is running. The guest dials out on a fixed vsock port,
says its protocol version first, is handed one boot descriptor — a command
line, shares, output geometry, and what an exit means — and carries that out.
There is no code path that branches on which workload started, which is the
property the component exists to keep.
It reports and does not supervise. When the workload ends, the exit goes up the
channel and the session is over; `on_exit` says what the exit means, and
starting something again is a decision for the end that can see whether
restarting is repair or a loop. A signalled workload is reported as signalled
with no exit code, because reporting 0 for a killed process makes a kill look
like a clean run.
Two seams keep this testable without a VM, which is the reason for both of
them. Reaping runs against real forked children, with the subreaper bit making
a test process inherit orphans the way PID 1 does. The channel is generic over
the byte stream, so the exchange is driven over an in-memory pipe — the
transport contributes nothing to the protocol beyond ordering and framing.
The lifecycle types live in nesprotocol behind a feature, off by default: both
ends of the channel read one definition and cannot drift from it silently,
while the media components keep building without serde.
Mounting shares is not implemented in this build. The descriptor's mounts are
refused rather than ignored — a workload started without the shares it was
promised fails later, somewhere else, for a reason nobody can see from here.
First component into this repo. Renamed from `nestri-protocol` — everything
else in the family carries the `nes` prefix and this was the odd one out.
**Imported as a tree, not as history.** The upstream repo is private, so its
commits and commit messages have never been reviewed for what may be published,
and squashing avoids the failure this project has already documented once: a
repo published wholesale carries private history with it, permanently. Origin is
`nestrilabs/nestri-protocol`, and this is its state today rather than its past.
The `control` module is deliberately left behind. It carries the host↔guest
control channel, and its types are shaped by a payload that has no business
being described in a public repo — a box is supposed to be able to run anything.
It was already an optional feature that nothing here enables, so leaving it out
costs nothing today and stops a boundary from being crossed by accident.
What lands is the media protocol: frames, audio, cursor, input and stats. One
definition shared by both ends, so no two can drift silently. 9 tests pass.
One pre-existing clippy warning (`input.rs`, too many arguments) is left alone
on purpose — an import commit should be a faithful copy, and mixing a cleanup
into one makes both harder to read.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>