Expand description
Cross-process control inbox (design.md “Cross-process control”).
The single-writer rule (§4.3) means only the engine appends events.jsonl.
Other processes (CLI kranz msg/pause/resume, the server) talk to a
running engine by dropping ControlCommand JSON files into
paths.control_dir(). File names are <zero-padded-nanos>-<8-hex>.json
so lexicographic order == chronological order; writes go through a tmp
file + rename so a draining engine never observes a partial file. The
nanosecond prefix keeps back-to-back enqueues (e.g. pause immediately
followed by resume) in issue order — a millisecond prefix left same-ms
enqueues to be ordered by the random suffix.
The engine drains the inbox between worker runs, and a
ControlWatcher polls peek_interrupt so an interrupt message can
abort the active run.
§Authenticity (audit 2026-09-01 C1)
The inbox carries operator consent: approve-grant, approve-revision,
answer-question, and config-change all land as events that are
indistinguishable from a human decision. It used to be a plain directory
any process with write access to the repo could drop a file into, which
made forging consent a one-file operation for a worker, a validator, or
any gate command.
Every file therefore carries a sig: a hex HMAC-SHA256 over the mission
id, the file name, and the canonical JSON of the command, keyed by the
repository authority key (crate::paths::authority_key_path). drain
and peek_interrupt verify it with a constant-time compare and
quarantine anything unsigned or wrongly signed to .bad, never applying
it. acknowledge records the acknowledged file’s name as the mission’s
control mark outside the repository, and any later file whose name is at
or below the mark is quarantined as a replay even when its signature
verifies.
Structs§
- Control
Watcher - Spawn-able helper that polls
peek_interruptand fires atokio::sync::Notifyonce an interrupt message is queued. The orchestrator selects on the notify alongside the active worker run.
Functions§
- acknowledge
- Remove a command returned by
drainafter its event has been durably applied. The delete stays relative to the same no-follow mission/control chain as enqueue and drain, so a swapped parent symlink cannot redirect acknowledgement outside the mission. - drain
- Drain the inbox: parse every queued
.jsonfile, oldest first, NON-destructively. - enqueue
- Enqueue one command into the mission’s control inbox.
- peek_
interrupt - True if any queued file AUTHENTICATES to
Msg { interrupt: true }. - resolve_
active_ mission - Resolve the target mission for a mid-mission control command (config
change, pause, resume): an ACTIVE (non-terminal) mission, chosen
unambiguously. Shared by the Slack bridge (
/kranz config|pause|resume) and the CLI (kranz config role), so both surfaces refuse the same hazardous targets: