Idunn/deploy/legacy
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Eureka b230703a5c Idunn: a stop halts before irreversible steps; fail-closed reader; break-glass clear
- Re-read the stop at the static flip intent and at entry into Fencing for a
  deploy (stop_note, the same path as Sealing). After the intent or fencing
  the transaction runs to its end; documented.
- Absent means NotFound in an existing directory; every other lookup error,
  a zero-length file and a missing parent fail closed. Unreadable names the
  idunn-provision deployment-brake-clear command.
- replace_stop is the operator's break-glass: it replaces v1, foreign,
  ambiguous, zero-length and caller-owned undecodable stores, never a symlink
  or another user's file.
- Mutation-proven tests: foreign-owner Clear, Unreadable admitting at
  Sealing, author from USER.
- docs: stop semantics, v6 downgrade hazard and backup; legacy script no
  longer requires the store and drops the signed-grant wording; two stale
  doc lines.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-13 17:36:57 +00:00
..
idunn-yggdrasil Idunn: a stop halts before irreversible steps; fail-closed reader; break-glass clear 2026-11-13 17:36:57 +00:00
idunn-yggdrasil.sudoers Retire the legacy bifrost-persona-feedback deploy route 2026-09-30 21:40:21 +02:00
README.md Retire the legacy bifrost-persona-feedback deploy route 2026-09-30 21:40:21 +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 ten targets, their repositories and their admitted refs, then delegates to executable manifests under /srv/odin/deploy-manifests/<target>. It calls idunn validate-minimum-source-revision, a subcommand the current binary does not have.

Checked on yggdrasil 2026-09-30: /usr/local/libexec/idunn-yggdrasil is installed and matches this file byte for byte (before the retirement below), but idunn-yggdrasil.sudoers is not installed. sudo -l -U idunn says the idunn user may not run sudo, so the daemon cannot reach this actuator; only an operator running it as root can.

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 ten 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 (retired with its only target) [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 retired 2026-09-30, see below
repixelizer GameCult/repixelizer main
streampixels GameCult/StreamPixels main two units, one target
gjallar GameCult/Gjallar codex/yggdrasil-aggregate-daemon

Seven of the ten live targets 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.

Retired targets

  • bifrost-persona-feedback, 2026-09-30. Its manifest ran the Bifrost compose lane (docker compose up persona-feedback), while the live provider is the native bifrost-persona-feedback.service, so firing it would have started a container beside the native unit. The operator ruled "delete the Bifrost lane". Its grant, dispatch case and the Bifrost release-authority check it alone used are gone; a deploy request that claims a Bifrost authority is refused. It was the only caller of idunn validate-release-authority. Rebinding persona-feedback to a current Idunn binding is a separate follow-up.

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.