Diluvium 5.5.1_build8
[5.5.1_build8] - 2026-08-15
v5.5.1_build8 · Lua 5.5.1 · bytecode format 0x46
Nothing blocks the shared thread, and a capability can live in
another program. Until now a connector answered inline: the host
called it and wrote the reply on the next line, so a connector that
needed time simply did not return, and exec sitting in a poll()
loop stalled every guest and the listener until its child exited. A
connector can now say later -- take the call, return, and answer
when the answer exists. Eight 200ms calls from one instance finish in
about 208ms rather than 1600.
The plugin channel is what that makes possible. A capability
answered by a separate program the host execs from an absolute path,
talking length-prefixed msgpack over a socketpair it inherits as fd 3,
described by a self-contained <name>.plugin.json manifest and wired
by a plugins table beside connectors. New capability without a new
Diluvium release.
plugins/rest is the first one, and closes the net gap build 7
deferred -- in C against OpenSSL and in JavaScript against fetch,
one manifest describing both, and a guest that cannot tell them apart.
The point is what diluvium-host did not have to learn: it links no
TLS, resolves no names, and opens no outbound socket.
host.capabilities() answers what this host can do and what of it
the caller may do, and keeps them apart. Every entry carries
granted, so a capability a deployment wires and a program may not
call is still listed rather than absent -- the difference between
"this host cannot" and "I may not", which had produced identical
silence. A visibility field (public, private, hidden, inherit;
public by default) decides what a caller is told exists, which is a
separate axis from what it may do.
The guest side needed no new surface for any of it: host.call already
reached any connector by name, and now forwards an optional timeout.
Added
- Deferred hostcall replies.
DH_CALL_PENDINGis a fourth
connector status meaning taken; exactly one reply is owed. The
host keeps a ledger keyed by (instance, token), sweeps it when an
instance dies so a dead program's work is abandoned rather than
computed, and reclaims an entry whose deadline elapses so a wedged
connector cannot hang a guest. - The plugin channel.
plugins = { name = { manifest = ... } }in
a deployment;<name>.plugin.jsonbeside it. Manifests are parsed
with the runtime's own strict JSON decoder in alua_Statethe host
owns, so nothing is vendored and no schema validator is embedded --
the runtime reads the flat metadata and reads pastargs/result.
Per-pluginmax_inflightbounds what a serial plugin is handed;
call_timeout_msis the host-side backstop. Errors carry one of
three classes --transport,plugin,capability-- because the
caller's retry decision differs for each. plugins/rest, outbound HTTP and HTTPS, in C (OpenSSL,
verifying the chain and the name) and in JavaScript (fetch, on
fd 3 under Node and overpostMessagein a Worker). Plus
plugins/dvplug.h, a dependency-free single-header kit for writing
a plugin in C, andplugins/README.md.host.capabilities()and thevisibilityfield, on the
deployment and per plugin. Discovery is gated on
host:capabilities/list, which is what makes an auditing agent
expressible: one that can report everything a swarm can reach while
being able to reach none of it.doc/Extending.md: adding a capability as a C connector, as a plugin, or as a Lab connector, side by side.doc/BUILD8.md: the plan, and the honest list of what it did not build.
Changed
- The host sleeps in exactly one place.
dh_host_sleepfolds the
listener's sockets, the plugin channels and a plain timeout into a
singlepoll(). Two sleeping polls in sequence would not deadlock,
but the first to sleep would delay the second by its whole timeout,
and "nothing blocks the shared thread" is only checkable if there is
one place the thread stops. host.callandhost.trytake an optionalwaitms, whichroundtriphad always accepted.dh_call_fncarries the request's correlation token, so a connector that defers can name the call it is answering.DH_MAX_CONNECTORSis 16, since every plugin claims a slot beside the built-ins.
Fixed
- The generic host builds on macOS.
dhost_crypto.ccalled
getrandom(2)unguarded; that is Linux's, and<sys/random.h>is
spelled the same on macOS but declaresgetentropyinstead, so the
/dev/urandomfallback underneath it was unreachable -- the file
never compiled. Split at compile time. Pre-existing and invisible
becausehost_checkdid not run in CI until this build put it
there. - A reply-queue accounting bug the deferral seam exposed. The pump
refused to drain a request when the reply queue was full, but a
deferred call is drained and not yet answered, so the queue looked
emptier than it was. Pending calls now count against the headroom. realpathwas handed a 512-byte buffer inhost_check; it writes up toPATH_MAX. Found by addinghost_checktosanitize_checks, which_FORTIFY_SOURCEcatches and ASan does not.
Security
- A plugin is exec'd with
execvfrom an absolute path, never
execvp: a plugin path comes from a manifest an operator wrote, and
resolving it throughPATHis an injection surface with nothing on
the other side of the trade. A relative path is refused by name at
config load. - There is no plugin authentication, deliberately. Containment
comes from a plugin being a narrow program rather than from
certifying it, and an attacker who can swap the plugin binary can
equally swapdiluvium-host. The channel has no filesystem path and
no port, so parentage is structural rather than negotiated. A
manifest checksum is recorded and logged at startup without being
enforced, which is forensics now and a one-line change later. - The rest plugin refuses credentials in a URL rather than laundering them into the host's log and the guest's message log, and refuses a header value carrying CR or LF rather than stripping it -- silently changing what was sent is worse than declining to send it.
Upgrading
Snapshots taken by 5.5.1_build7 restore on this build. Unlike
build7, which added a module table to the permanents set and moved the
fingerprint, everything build8 adds on the guest side is a Lua closure
inside the existing host table. ds_perm_walk names only C
functions and the fingerprint hashes the sorted name list, so it is
byte-identical. DILUVIUM_SNAP_FORMAT, DS_THREAD_VERSION and
LUAC_FORMAT are unchanged.
A deployment that wants host.capabilities() must grant it.
Discovery is a capability like any other and is gated on
host:capabilities/list; a program without it is denied by name. No
existing deployment grants it, because none could until now.
exec still answers synchronously. Build 8 made deferral possible
and did not convert exec, which is a behaviour change to a shipped
connector and belongs in its own build. A running child still stalls
every guest and the listener, and host/types/host.lua still says so.
Plugin binaries are not release assets. The plugin channel ships,
and nothing to run through it does: diluvium-host itself is still
not published either (build 7 §5's open item). Building both from
source is the path today.
Built from commit 0d6180f6283b.
Download guide
| Platform | File | Notes |
|---|---|---|
| Linux (standard) | diluvium_linux_static_x86_64 |
Static; works on Ubuntu, Fedora, CentOS, Arch |
| Raspberry Pi 3/4/5 | diluvium_linux_static_aarch64 |
64-bit OS only |
| Raspberry Pi Zero | diluvium_linux_static_armv7l |
32-bit ARM |
| macOS (Apple silicon) | diluvium_darwin_arm64 |
M1/M2/M3/M4 |
| macOS (Intel) | diluvium_darwin_x86_64 |
|
| Windows | diluvium_windows_x86_64.exe |
64-bit |
| WASI | diluvium_wasi.wasm |
Needs a runtime with wasm exception-handling (wasmtime 28+ with -W exceptions=y) |
| Browser | libdiluvium_wasm_unknown.a |
wasm32-unknown-unknown static library |
Each platform also ships a diluvium_compiler_* binary (luac
with the -r analysis report flag) and a libdiluvium_*.a static
library for embedding.
Verifying a download
sha256sum -c SHA256SUMS.txt --ignore-missing
BUILDINFO.txt records the exact commit, build time and workflow run.