On this page
Host and request limits
The limits a host declares in its configuration beside the first-run profile: what a mobile client may ask, how loaded or swapped a host may be before a scan or job waits, where the Tailscale client is, and how large a source archive may be.
Mobile egress request boundary
The loopback proxy requires the deployment's listen address and header budget. The budget includes the request line, header fields and terminating blank line, not the request body or the bytes carried by a CONNECT tunnel.
stado egress mobile serve --interface "$INTERFACE" --bind "$BIND" --port "$PORT" \
--max-header-bytes "$HEADER_BYTES"
BIND must be a loopback address and HEADER_BYTES a positive whole number,
both chosen by the deployment. A missing --bind, a non-loopback address, or a
missing, zero or invalid budget is refused by the CLI before a listener starts.
Managed service declarations must include --bind, --port and
--max-header-bytes with their values in the service's argument list. There
is no built-in address or byte budget.
A request line that is not METHOD TARGET HTTP/… is answered 400 Bad Request. A CONNECT target must name its port (host:port); one without it is
refused and logged, never sent to an assumed port.
A header ending exactly at the declared boundary is accepted. A larger one
closes the client connection before opening an upstream connection; the service
log names --max-header-bytes, the declared limit and the observed byte count.
EOF before the terminating blank line is reported as an incomplete request.
Bodies and CONNECT payload bytes that arrive with the header are forwarded
without truncation. Readiness reports the actual bound socket address.
The real qualification journey is
node tests/egress/headers.mjs in the Stado checkout, with STADO_BIN naming
the candidate executable, STADO_TEST_SOURCE_REVISION its exact committed
source revision and STADO_EGRESS_TEST_INTERFACE a real interface with a
non-loopback IPv4 address on the qualification host. It launches an isolated
proxy and TCP receiver, checks a boundary-sized header with a body, oversized
and incomplete refusals, and CONNECT payload preservation. It keeps binary and
test hashes, commands, exit statuses, received bytes and the verdict under
.build/egress-headers-*. Missing prerequisites do not pass.
API request boundaries
How an API listener bounds every request head, body, operator console request and fleet join report before reading it, and where those bounds are declared: API request boundaries.
The scan load ceiling
host.scan_load_ceiling (WC_HOST_SCAN_LOAD_CEILING for one process) is the
one-minute load average above which the host process skips its scans of the
host's own disk — a preview of the janitor's build-cache walk, the beacon's
launchd event reads, the inventory walk of a space report on its own host —
and publishes the skip in the beacon's scans block
(Beacon). A janitor pass on a volume at the rule's
full threshold walks the build caches whatever the load, at background
priority, because that walk is what frees the disk; its reading is recorded
as an admission:
stado config set host.scan_load_ceiling "$LOAD_CEILING"
stado config get host.scan_load_ceiling
The value is a load average: a number, not negative, not infinite; anything
else refuses the scan with host.scan_load_ceiling = "<value>" is not a load average and the beacon carries the refusal. A host that declares nothing is
bounded by its logical core count, measured by the process that scans, and
the beacon names that source as measured_cores.
The swap ceiling
host.swap_ceiling_pct (WC_HOST_SWAP_CEILING_PCT for one process) is the
share of the host's swap, in percent, above which the host is out of memory
for new work: the host process skips the scans the load ceiling governs, and
stado product install, update, cargo and every swift operation wait
before they export or compile, as a czekam: wait that names the reading
(swap <used>% of <total> used, above host.swap_ceiling_pct <ceiling>) and
starts the work once swap falls under the ceiling. A compile started on a
host whose swap is full only pages: a Stado build that takes minutes took
over half an hour with its compiler at two percent of a core. The janitor's
relief walk on a full volume is admitted whatever the swap, as it is
whatever the load.
stado config set host.swap_ceiling_pct 90
stado config get host.swap_ceiling_pct
The value is a percentage from 1 to 100; anything else refuses with
host.swap_ceiling_pct = "<value>" is not a percentage from 1 to 100. A host
that declares nothing has no swap ceiling, and its swap is only reported. A
host whose swap cannot be read (vm.swapusage or /proc/meminfo did not
answer) is admitted, and the cause is kept beside the reading in the beacon's
scans block.
The Tailscale client paths
tailnet.clients (STADO_TAILSCALE_CLIENTS, comma-separated, for one
process) lists the paths this host's Tailscale client may be at; the first
that is a file is the client. A host that declares nothing uses
/usr/bin/tailscale, /usr/local/bin/tailscale,
/opt/homebrew/bin/tailscale and
/Applications/Tailscale.app/Contents/MacOS/Tailscale. A path that cannot be
examined is the beacon's failed cause; a list of which no path holds a file
is absent.
stado config set tailnet.clients '["/usr/local/bin/tailscale"]'
stado config get tailnet.clients
Machine source archive boundaries
machine.source_limits declares archive_bytes, extracted_bytes, members
and trailing_bytes for machine submissions that carry a source archive.
WC_MACHINE_SOURCE_LIMITS supplies the same document for one process. There is
no built-in size or member budget; stado config validate checks a stored
declaration, and source admission checks the effective declaration before
reserving a request. CLI and Desktop configuration use the same key. See
Source archive bounds for the
command, refusal semantics and real qualification journey.
Source: this website