Document idunn order and add the idunn-orders unit

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-11-01 02:33:02 +01:00
commit 1a3634e046
2 changed files with 77 additions and 0 deletions

View file

@ -58,6 +58,35 @@ idunn status --command <id>
the bindings, so `idunn up profile:full-gamecult` brings up everything bound
into that profile.
### Steward orders
A second root unit from the same binary, `idunn-orders` (`idunn orders serve`),
takes typed orders from one steward Mind over `/run/idunn-orders/steward.sock`.
It has its own store, `orders.cc`, and its own binding, `steward.toml`; the
survival daemon takes no order. There is still no command string:
```bash
idunn order package-install <pkg>[=version]... --reason TEXT # apt-get update, then install
idunn order unit <start|stop|restart|reload> <unit> --reason TEXT
idunn order deploy <service|profile:name> --reason TEXT # the same commit as `idunn up`
idunn order show <id> # status and output tails
idunn order list
```
A unit order may act on any unit except Idunn's own (`idunn-*`) and the minds'
own (`mind-self@*`, `mind-persona@*`). That set is compiled into the binary and
read from no configuration. A name, an alias that resolves to one of them, or a
`stop` or `restart` whose dependents systemd would stop with it is refused,
recorded and posted. Slices, scopes and globs are not units an order can name.
An order runs once, after the steward's uid is checked and the instance's
brake check (`mind-control --instance <principal> check`) exits 0; an order
that had started when the service died is recorded as lost and never run
again. No order releases a brake. Acceptance and result are posted to
`#operator` as a retried projection of `orders.cc`: a chat outage delays the
posts and not the orders. A refusal names the field and a code, never the value
it refused.
## Authority
**Owner.** Deployment admission, and the continuity of installed bodies.

View file

@ -0,0 +1,48 @@
[Unit]
Description=Idunn steward orders: typed package, unit and deploy orders from the steward
# Deliberately no After= or Requires= on any managed target, Synapse or
# idunn-yggdrasil: orders are how an operator repairs those, so none of them
# may be a condition of this unit starting. Posts are a retried projection and
# wait for Synapse on their own.
[Service]
Type=simple
# Root, from the same binary as idunn-yggdrasil, with its own store and socket.
# idunn-yggdrasil keeps its no-imperative-input invariant and its write set:
# no order code runs in `idunn serve`.
#
# The unit name matches idunn-*, which is in the always-refused set, so no
# order can stop or restart this service.
User=root
# The socket is created root:idunn-steward 0660 (UMask below). The steward user
# is the only peer the service answers: it checks SO_PEERCRED on every
# connection, so the group is a second door held shut, not the lock.
Group=idunn-steward
ExecStart=/usr/local/bin/idunn orders serve \
--store /var/lib/gamecult/idunn-orders \
--state-store /var/lib/gamecult/idunn/control.cc \
--steward-binding /etc/gamecult/idunn/steward.toml \
--socket /run/idunn-orders/steward.sock
Restart=always
RestartSec=5
TimeoutStopSec=20
UMask=0117
RuntimeDirectory=idunn-orders
RuntimeDirectoryMode=0750
# The Synapse access token of @idunn, copied from a root-only file, and read
# through $CREDENTIALS_DIRECTORY; the service names it in steward.toml.
LoadCredential=idunn-matrix-token:/etc/gamecult/idunn/matrix-token
PrivateTmp=yes
ProtectHome=yes
ProtectSystem=strict
# Its own order store, and the control store a deploy order commits a command
# to. Transient units started with systemd-run run in the manager's namespace,
# so packages and units are not limited by this list.
ReadWritePaths=/var/lib/gamecult/idunn-orders /var/lib/gamecult/idunn
[Install]
WantedBy=multi-user.target