Retire the legacy bifrost-persona-feedback deploy route
The operator ruled "delete the Bifrost lane". This route was that lane's live trigger: /srv/odin/deploy-manifests/bifrost-persona-feedback runs `docker compose up persona-feedback`, and the provider actually running on Yggdrasil is the native bifrost-persona-feedback.service. Firing the route would start a container next to it. Following deploy/legacy's own order, the grant goes first, then the dispatch: - sudoers: drop `deploy bifrost-persona-feedback *`. - idunn-yggdrasil: drop the target's policy case and its dispatch token, plus the Bifrost release-authority check that only it used (requires_bifrost_authority and the `idunn validate-release-authority` call). A deploy request that claims a Bifrost authority is still refused. The manifest environment keeps IDUNN_REQUIRES_BIFROST_AUTHORITY=false, because the installed Epiphany manifest checks for it. - README: record the retirement and the counts. Also record that on 2026-09-30 the installed actuator matched this file, but the sudoers grant was not installed: the idunn user cannot sudo. Rebinding persona-feedback to a current Idunn binding is a separate follow-up. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
85964d0f00
commit
889e23629c
3 changed files with 34 additions and 55 deletions
|
|
@ -4,11 +4,16 @@
|
|||
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
|
||||
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-release-authority`
|
||||
and `idunn validate-minimum-source-revision` — subcommands the current binary
|
||||
does not have.
|
||||
`/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
|
||||
|
||||
|
|
@ -16,10 +21,10 @@ 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` |
|
||||
| `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` | `[repository] selection = "signed-release"`, per target |
|
||||
| `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` |
|
||||
|
|
@ -45,15 +50,26 @@ This is the real migration scope, read out of `deployment_target_policy()`:
|
|||
| `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 |
|
||||
| ~~`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 eleven are pinned to a non-`main` branch. That is its own problem — the
|
||||
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
|
||||
|
|
|
|||
|
|
@ -96,14 +96,12 @@ deployment_target_policy() {
|
|||
daemon_id=yggdrasil-odin
|
||||
repository_full_name=GameCult/Odin
|
||||
upstream_ref=refs/heads/codex/ygg-idunn-independent-bootstrap
|
||||
requires_bifrost_authority=false
|
||||
manifest_takes_action=true
|
||||
;;
|
||||
codex-connector)
|
||||
daemon_id=yggdrasil-codex-connector
|
||||
repository_full_name=GameCult/CodexConnector
|
||||
upstream_ref=refs/heads/codex/ghostlight-release-binding
|
||||
requires_bifrost_authority=false
|
||||
minimum_source_revision_required=true
|
||||
manifest_takes_action=true
|
||||
;;
|
||||
|
|
@ -111,7 +109,6 @@ deployment_target_policy() {
|
|||
daemon_id=yggdrasil-ghostlight
|
||||
repository_full_name=GameCult/Ghostlight
|
||||
upstream_ref=refs/heads/codex/ghostlight-dungeon-mvp
|
||||
requires_bifrost_authority=false
|
||||
minimum_source_revision_required=true
|
||||
manifest_takes_action=true
|
||||
;;
|
||||
|
|
@ -119,52 +116,39 @@ deployment_target_policy() {
|
|||
daemon_id=yggdrasil-voidbot
|
||||
repository_full_name=GameCult/VoidBot
|
||||
upstream_ref=refs/heads/main
|
||||
requires_bifrost_authority=false
|
||||
manifest_takes_action=true
|
||||
;;
|
||||
heimdall)
|
||||
daemon_id=yggdrasil-heimdall
|
||||
repository_full_name=GameCult/Heimdall
|
||||
upstream_ref=refs/heads/main
|
||||
requires_bifrost_authority=false
|
||||
;;
|
||||
epiphany-capstone-17)
|
||||
daemon_id=yggdrasil-epiphany-capstone-17
|
||||
repository_full_name=GameCult/Epiphany
|
||||
upstream_ref=refs/heads/codex/epiphany-shakedown-live
|
||||
requires_bifrost_authority=false
|
||||
manifest_takes_action=true
|
||||
;;
|
||||
epiphany)
|
||||
daemon_id=yggdrasil-epiphany
|
||||
repository_full_name=GameCult/Epiphany
|
||||
upstream_ref=refs/heads/codex/epiphany-shakedown-live
|
||||
requires_bifrost_authority=false
|
||||
manifest_takes_action=true
|
||||
;;
|
||||
bifrost-persona-feedback)
|
||||
daemon_id=yggdrasil-bifrost-persona-feedback
|
||||
repository_full_name=GameCult/Bifrost
|
||||
upstream_ref=refs/heads/main
|
||||
requires_bifrost_authority=true
|
||||
;;
|
||||
repixelizer)
|
||||
daemon_id=yggdrasil-repixelizer
|
||||
repository_full_name=GameCult/repixelizer
|
||||
upstream_ref=refs/heads/main
|
||||
requires_bifrost_authority=false
|
||||
;;
|
||||
streampixels)
|
||||
daemon_id=yggdrasil-streampixels
|
||||
repository_full_name=GameCult/StreamPixels
|
||||
upstream_ref=refs/heads/main
|
||||
requires_bifrost_authority=false
|
||||
;;
|
||||
gjallar)
|
||||
daemon_id=yggdrasil-gjallar
|
||||
repository_full_name=GameCult/Gjallar
|
||||
upstream_ref=refs/heads/codex/yggdrasil-aggregate-daemon
|
||||
requires_bifrost_authority=false
|
||||
;;
|
||||
*) echo "deployment target has no root actuator policy: $target" >&2; exit 1 ;;
|
||||
esac
|
||||
|
|
@ -190,19 +174,10 @@ require_signed_deployment_grant() {
|
|||
*) echo "signed deployment request is not for root target $target" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
case "$requires_bifrost_authority" in
|
||||
true)
|
||||
[ -n "$release_authority_id" ] || { echo "missing Bifrost release authority id" >&2; exit 1; }
|
||||
case "$release_authority_sha256" in
|
||||
*[!0-9a-f]*|'') echo "invalid or missing Bifrost release authority digest" >&2; exit 1 ;;
|
||||
esac
|
||||
[ "${#release_authority_sha256}" -eq 64 ] || { echo "Bifrost release authority digest must be 64 lowercase hex characters" >&2; exit 1; }
|
||||
;;
|
||||
false)
|
||||
[ -z "$release_authority_id" ] || { echo "source-observed release cannot claim Bifrost authority id" >&2; exit 1; }
|
||||
[ -z "$release_authority_sha256" ] || { echo "source-observed release cannot claim Bifrost authority digest" >&2; exit 1; }
|
||||
;;
|
||||
esac
|
||||
# No target carries Bifrost release authority: its only one, bifrost-persona-feedback,
|
||||
# was retired on 2026-09-30. A request that claims one is refused.
|
||||
[ -z "$release_authority_id" ] || { echo "source-observed release cannot claim Bifrost authority id" >&2; exit 1; }
|
||||
[ -z "$release_authority_sha256" ] || { echo "source-observed release cannot claim Bifrost authority digest" >&2; exit 1; }
|
||||
|
||||
require_root_owned_resolved_executable "$idunn_provision"
|
||||
require_root_owned_regular_path "$brake_store"
|
||||
|
|
@ -234,18 +209,6 @@ require_signed_deployment_grant() {
|
|||
--daemon "$daemon_id" \
|
||||
--source-revision "$source_commit"
|
||||
fi
|
||||
|
||||
if [ "$requires_bifrost_authority" = true ]; then
|
||||
require_root_owned_resolved_executable /usr/local/bin/idunn
|
||||
/usr/local/bin/idunn validate-release-authority \
|
||||
--store /var/lib/gamecult/idunn/yggdrasil.keepalive.cc \
|
||||
--release-authority-store /srv/bifrost/state/repository-release-authority.cc \
|
||||
--repository-full-name "$repository_full_name" \
|
||||
--upstream-ref "$upstream_ref" \
|
||||
--source-revision "$source_commit" \
|
||||
--release-authority-id "$release_authority_id" \
|
||||
--release-authority-sha256 "$release_authority_sha256"
|
||||
fi
|
||||
}
|
||||
|
||||
manifest_group_exists() {
|
||||
|
|
@ -355,7 +318,7 @@ case "$action:$target" in
|
|||
run_manifest_while_holding_authority_locks "$manifest" restart
|
||||
exit $?
|
||||
;;
|
||||
deploy:voidbot|deploy:epiphany|deploy:epiphany-capstone-17|deploy:odin|deploy:codex-connector|deploy:ghostlight|deploy:heimdall|deploy:repixelizer|deploy:streampixels|deploy:bifrost-persona-feedback|deploy:gjallar)
|
||||
deploy:voidbot|deploy:epiphany|deploy:epiphany-capstone-17|deploy:odin|deploy:codex-connector|deploy:ghostlight|deploy:heimdall|deploy:repixelizer|deploy:streampixels|deploy:gjallar)
|
||||
manifest="/srv/odin/deploy-manifests/$target"
|
||||
require_root_owned_regular_path "$manifest"
|
||||
[ -x "$manifest" ] || { echo "root actuator manifest is not executable: $manifest" >&2; exit 1; }
|
||||
|
|
@ -368,7 +331,8 @@ case "$action:$target" in
|
|||
export BIFROST_RELEASE_AUTHORITY_ID="$release_authority_id"
|
||||
export BIFROST_RELEASE_AUTHORITY_SHA256="$release_authority_sha256"
|
||||
export IDUNN_DEPLOYMENT_REQUEST_ID="$deployment_request_id"
|
||||
export IDUNN_REQUIRES_BIFROST_AUTHORITY="$requires_bifrost_authority"
|
||||
# Installed manifests (Epiphany's) still require this to read false.
|
||||
export IDUNN_REQUIRES_BIFROST_AUTHORITY=false
|
||||
if [ "$manifest_takes_action" = true ]; then
|
||||
run_manifest_while_holding_authority_locks "$manifest" "$action"
|
||||
exit $?
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Narrow root actuator grant for the Idunn Yggdrasil deployment/continuity path.
|
||||
# One line per live target. codex-connector and gjallar were retired 2026-09-06;
|
||||
# their grants are removed here first, because the privileged half of a retired
|
||||
# target must not outlive its consumer.
|
||||
# One line per live target. codex-connector and gjallar were retired 2026-09-06,
|
||||
# and bifrost-persona-feedback on 2026-09-30; their grants are removed here first,
|
||||
# because the privileged half of a retired target must not outlive its consumer.
|
||||
Cmnd_Alias IDUNN_YGGDRASIL_DEPLOY = \
|
||||
/usr/local/libexec/idunn-yggdrasil deploy odin *, \
|
||||
/usr/local/libexec/idunn-yggdrasil deploy ghostlight *, \
|
||||
|
|
@ -9,7 +9,6 @@ Cmnd_Alias IDUNN_YGGDRASIL_DEPLOY = \
|
|||
/usr/local/libexec/idunn-yggdrasil deploy heimdall *, \
|
||||
/usr/local/libexec/idunn-yggdrasil deploy epiphany-capstone-17 *, \
|
||||
/usr/local/libexec/idunn-yggdrasil deploy epiphany *, \
|
||||
/usr/local/libexec/idunn-yggdrasil deploy bifrost-persona-feedback *, \
|
||||
/usr/local/libexec/idunn-yggdrasil deploy repixelizer *, \
|
||||
/usr/local/libexec/idunn-yggdrasil deploy streampixels *
|
||||
Cmnd_Alias IDUNN_YGGDRASIL_RESTART = \
|
||||
|
|
|
|||
Loading…
Reference in a new issue