- Rust 99.1%
- Shell 0.9%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Brings across everything an operator needs to run Idunn without reference to Odin. deploy/ carries the worked systemd installation -- unit, operator wrapper, and the narrow sudoers grant. docs/ carries the four documents that were scattered across Odin's tree. The README is new and is the public entry point the repo lacked: what Idunn decides, how to build and run it, the authority model in the form doctrine asks for, how to install it as a service, and where the deeper documents are. Two corrections made while moving: Requires=docker.service becomes Wants=. Deployment runners use Docker; continuity actuation does not. A hard requirement lets a Docker outage stop Idunn itself and take daemon survival down with it, which is precisely the invariant Idunn exists to hold. This is live on yggdrasil today and should be changed there too. The guide still told operators to run from E:\Projects\Odin -- a drive that no longer exists -- via npm wrappers that belonged to Odin. Paths generalised, commands moved to direct cargo invocations, and a note added that the document predates the extraction. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
| deploy | ||
| docs | ||
| src | ||
| tests/fixtures | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| README.md | ||
Idunn
Deployment admission and daemon-survival authority for the GameCult swarm.
Idunn decides two things and nothing else: whether an artifact may be installed, and whether an already-installed body may be restarted. It keeps daemons alive across a fleet, admits releases against operator-signed authority, and reports typed health — while depending on none of the services it manages.
Extracted from Odin on 2026-09-05 with its full 136-commit history. Idunn had lived as a crate inside the repository of a service it manages, which inverted the authority it exists to hold.
Quick start
Requires Rust 1.95+. Idunn is a Linux daemon; see Platform.
git clone https://github.com/GameCult/Idunn.git
cd Idunn
cargo build --release
Two binaries land in target/release/:
| Binary | Purpose |
|---|---|
idunn |
the daemon — keepalive supervision, deployment actuation, health |
idunn-provision |
operator tooling — brake status, identity enrolment, provisioning |
Run one daemon locally, with no swarm and no persistence:
./target/release/idunn --daemon demo --restart-command "echo restart demo"
Inspect a deployment brake without touching anything:
./target/release/idunn-provision deployment-brake-status \
--store /var/lib/gamecult/idunn-authority/deployment-brake.cc \
--operator-anchor /etc/gamecult/idunn/deployment-brake-operator-anchor.cc \
--runtime-id <runtime> --release-id <sha> --deployment-id <id>
--rudp-health-bind is explicit and off by default. A bare single-daemon Idunn
opens no health ingress.
Authority
Owner. Deployment admission, and the continuity of installed bodies.
Inputs. Its own typed state stores, its own credentials, and an operator-provided trust anchor. Nothing else. In particular, not the state, health, binaries or availability of anything it manages.
The invariant.
Idunn must be able to start, recover, observe and report while any managed target is absent, broken, or deliberately braked.
A target's brake gates mutation of that target only. It can neither authorize nor block Idunn's own startup, nor any other target's lifecycle.
Two brakes, not one. Deployment and continuity are separate authorities with separate stores, and the daemon refuses to start if the two resolve to the same store.
- Continuity is restarting an already-admitted installed release. Physiology.
- Deployment is changing an artifact, revision, configuration, schema, unit, or authority binding.
A deployment brake does not own the former. Suspending restart actuation requires the separately named lifecycle brake.
Forbidden. Idunn does not depend on a managed target, and does not repair one merely to satisfy a deploy. If recovery would require that, the target dependency is the thing to cut.
Contracts
Idunn's typed contracts are published by
CultLib in cultnet-rs — deployment and
lifecycle brakes, service identity, runtime activation, expected incarnation,
and the provider-health family. Idunn consumes them and defines no private
copies.
State is CultCache (.cc typed documents) throughout. Health is published over
CultNet RUDP.
Odin keeps its own separate projection of Idunn state for aggregation. That is the all-seer's view, not Idunn's contract, and the two sets do not overlap.
Running as a service
deploy/ carries a worked systemd installation:
| File | |
|---|---|
idunn-yggdrasil.service |
the unit |
idunn-yggdrasil |
operator wrapper |
idunn-yggdrasil.sudoers |
the narrow sudo grant the wrapper needs |
The unit runs as a dedicated idunn user under ProtectSystem=full,
ProtectHome=yes, PrivateTmp=yes, with ReadWritePaths enumerated per
managed target and its own authority store mounted read-only —
ReadOnlyPaths=/var/lib/gamecult/idunn-authority.
Note Wants=docker.service, not Requires=. Deployment runners use Docker;
continuity actuation does not. A hard requirement would let a Docker outage
stop Idunn itself and take daemon survival down with it. This was changed from
Requires= during extraction — if you are copying an older installed unit,
change it.
Adapt the store paths, --swarm-profile, and --rudp-health-bind for your
host. Every path in ExecStart is explicit on purpose; Idunn discovers no
authority implicitly.
Documentation
docs/guide.md |
what Idunn is for, who it helps, running it, what daemons should publish, typed records |
docs/authority-map.md |
authority map, repository declaration, operator binding, release foundation, promotion and continuity |
docs/deployment-authority.md |
the deployment transaction in depth |
docs/signed-daemon-health-authority.md |
signed health admission and trust bindings |
Platform
Idunn targets Linux. cargo test on Windows reports 63 passed, 18 failed;
those 18 assert against absolute deployment paths (/srv/...,
/var/lib/gamecult/...) and Rust's Path::is_absolute() requires a drive
prefix there. It is platform semantics, not breakage — the same 18 fail
identically in the Odin tree this was extracted from. Build and test on Linux
for a true result.
Licence
MIT.