Odin (96a55ec) now computes Ready with an external-operator-binding
dependency not ready, but CultLib's shared contract
(runtime_authority_contracts.rs:797-805) refuses any correlation claiming
Ready while a non-optional dependency is not ready, so Odin rejected every
Ghostlight Active presence (30/30 in the last deploy). The external kind
existed only because Heimdall isn't v2-managed; that reason doesn't survive
contact with Odin's own Ready computation.
Ghostlight's deploy stops declaring Heimdall as an Idunn dependency. The
daemon discovers it through Odin at use instead: HeimdallClient already took
Option<HeimdallDependencyBinding> with None as the non-managed path, so
runtime.rs now passes None directly rather than computing it from a
dependency_bindings field that no longer exists, and the loopback-only,
non-secret-bearing, app-bound HMAC+AES envelope enforcement is unchanged.
When Heimdall becomes a v2 target the dependency returns as `required`
managed.
- deployment/idunn/recipe.toml: deleted the heimdall.command-boundary
[[dependencies]] block. Ghostlight's own required_environment for
GHOSTLIGHT_HEIMDALL_APP_SECRET_FILE/GHOSTLIGHT_HEIMDALL_BASE_URL is
unrelated (Heimdall's HTTP app integration, not the Idunn dependency) and
stays.
- idunn_health.rs: runtime_dependency_bindings now requires exactly the Odin
dependency (one, not two). Deleted HEIMDALL_CAPABILITY,
required_external_dependency and its doc comment, the `heimdall` field on
RuntimeDependencyBindings, the fixture's external_dependency helper and
its Heimdall entry, and the recipe-drift test's Heimdall block/assertion
(now asserts exactly one [[dependencies]] block and fails if a Heimdall
dependency reappears without the daemon changing to expect it again).
HeimdallDependencyBinding itself moved to heimdall.rs (see below) rather
than being deleted outright: it's still the shape
require_expected_heimdall_boundary checks a discovered boundary against
when Idunn does supply one, which stays true the moment Heimdall returns
as a managed dependency.
- heimdall.rs: now owns HeimdallDependencyBinding (moved from
idunn_health.rs, which no longer has any use for it). No behavior change:
HeimdallBoundaryLocator::Odin's `expected: Option<HeimdallDependencyBinding>`
and its None-tolerant checking logic were already exactly the
"discover through Odin, verify against a managed binding when one exists"
shape this ruling asks for.
- runtime.rs: expected_heimdall is gone; `HeimdallClient::from_env` now
takes `None` directly instead of a value computed from a
dependency_bindings field that no longer exists, with a comment on why.
Mutation: re-added the heimdall.command-boundary [[dependencies]] block to
the recipe -> recipe_matches_the_daemon_it_deploys fails (asserts exactly
one dependency block). Restored; deployment/idunn/recipe.toml is
git-diff-clean after, one clean 7-line deletion.
Verification: cargo test -p ghostlight-dungeon --bin ghostlight-dungeon ->
192 passed, 0 failed, 4 ignored (unchanged count: removed a test helper, not
a test).
Structural delta: 4 files changed, 42 insertions(+), 138 deletions(-) in
Ghostlight (net -96 lines) — a genuine subtraction, not a relocation with
padding; the only addition of substance is the doc comment on the relocated
HeimdallDependencyBinding explaining why it still exists.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>