Idunn/deploy/legacy
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Meta Vens f6b97fdc62 Retire gjallar; record why retirement is what forces the migration
Gjallar had a brief useful life on Nightwing's framebuffer, broke, and was
never fixed. Its Yggdrasil incarnation ran --headless --refresh-hz 2 for
eleven days: a compositor with no display recomposing twice a second, 55
minutes of CPU and 125M resident producing frames nothing rendered. The
only reference to gjallar.overview in the estate is one Odin test file.
Stopped and disabled; 420M under /srv/gjallar is reclaimable.

Removed the codex-connector and gjallar sudo grants from the host and
synced deploy/legacy/idunn-yggdrasil.sudoers to match. Four grants gone,
verified by diffing the grant set against a backup, nothing else changed.

That diff caught a defect I introduced: removing the last entry of a
Cmnd_Alias leaves a dangling continuation, and my repair silently dropped
the wildcard from `deploy streampixels`, which would have failed every
streampixels deployment. The procedure now says validate with visudo -c -f
before installing and diff the grant set afterwards.

The larger finding: the installed generation CANNOT express that a target
is retired. Its target list is compiled in, it offers restart and redeploy
and no way to drop a daemon from supervision, and its only brake is the
deployment brake -- which doctrine forbids using for this, since a
deployment brake must not suspend continuity. Stopping codex-connector
therefore produced eighty "decision: restart" lines in ten minutes against
a service we had just retired. Suspending continuity for one target is
precisely the current generation's lifecycle brake. The estate found the
argument for its own migration by trying to throw something away.

Gjallar was handled correctly by contrast: its failure classified as
dependency-unavailable, so Idunn raised an alarm instead of resurrecting
it. The old generation can tell failures it owns from failures it does
not; it cannot tell a broken target from a finished one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 00:07:22 +02:00
..
idunn-yggdrasil Make the public entry point describe the binary that actually ships 2026-09-05 23:15:46 +02:00
idunn-yggdrasil.sudoers Retire gjallar; record why retirement is what forces the migration 2026-09-06 00:07:22 +02:00
README.md Make the public entry point describe the binary that actually ships 2026-09-05 23:15:46 +02:00

Legacy actuator — the generation currently installed on yggdrasil

These files are superseded. Do not use them for a new installation. They are kept because they are what is running, and a migration needs both sides.

idunn-yggdrasil is a root shell actuator reached through the narrow sudo grant in idunn-yggdrasil.sudoers. It hardcodes eleven targets, their repositories and their admitted refs, then delegates to executable manifests under /srv/odin/deploy-manifests/<target>. It calls idunn validate-release-authority and idunn validate-minimum-source-revision — subcommands the current binary does not have.

What replaced it

Everything this script does by convention, the current Idunn does by contract:

Legacy mechanism Current owner
deployment_target_policy() — a case over eleven target names one operator binding per target, in --bindings-dir
upstream_ref=refs/heads/... in shell [repository] admitted_ref
minimum_source_revision_required [repository] minimum_revision
requires_bifrost_authority + --release-authority-store [repository] selection = "signed-release", per target
/srv/odin/deploy-manifests/<target> shell scripts recipe [[steps]] in the target's own repository
run_manifest_while_holding_authority_locks the deployment transaction and process write-lease
flock on a brake store [brakes] deployment_store and lifecycle_store
root shell with IDUNN_ACTUATOR=1 systemd-transient workload driver under DynamicUser

The structural difference is not tidiness. The legacy path admits a deployment by validating arguments to a root shell script, and everything after that validation is unverified shell running as root. The current path seals exact source and artifacts, admits one incarnation against typed operator authority, and hands execution to systemd — with no place to pass a command string, enforced by cli_exposes_only_declarative_commands.

The target inventory, which is still useful

This is the real migration scope, read out of deployment_target_policy():

Target Repository Admitted ref Notes
odin GameCult/Odin codex/ygg-idunn-independent-bootstrap ref is a branch, not main
codex-connector GameCult/CodexConnector codex/ghostlight-release-binding minimum revision enforced
ghostlight GameCult/Ghostlight codex/ghostlight-dungeon-mvp minimum revision enforced
voidbot GameCult/VoidBot main
heimdall GameCult/Heimdall main restart is docker compose restart
epiphany GameCult/Epiphany codex/epiphany-shakedown-live
epiphany-capstone-17 GameCult/Epiphany codex/epiphany-shakedown-live second target, same repo
bifrost-persona-feedback GameCult/Bifrost main only target requiring Bifrost release authority
repixelizer GameCult/repixelizer main
streampixels GameCult/StreamPixels main two units, one target
gjallar GameCult/Gjallar codex/yggdrasil-aggregate-daemon

Seven of eleven are pinned to a non-main branch. That is its own problem — the swarm goal is everyone on main and current with each other — and migrating a target is the moment to fix its ref, not to copy it forward.

When these files die

When every target above has a binding and a recipe, and idunn serve owns actuation on yggdrasil. At that point delete the sudoers grant first, then the script, then /srv/odin/deploy-manifests/. The grant is the privileged half; it should not outlive its consumer.