fix(#2860): give the eval-only container configs a forge.url placeholder

Making `hyperhive.forge.url` required broke `nix flake check`:
`nixosConfigurations.agent-base` and `.ruth` exist to typecheck the
agent modules and to pre-build the container closure, and nothing in
that path supplies a value — `forge.nix` reads the option
unconditionally for tea-login's `FORGE_URL`.

Real containers are unaffected: they are built from the generated meta
flake, where hive-c0re renders the option per agent from the host's
`HIVE_FORGE_URL` (meta.rs's `SERVICE_URL_OPTIONS`). They never evaluate
through `self.nixosConfigurations`, so this value cannot reach a
running agent.

Uses a `.invalid` host (RFC 2606, guaranteed not to resolve) rather
than a plausible loopback: if it ever did escape into a runtime path it
must fail at DNS instead of quietly connecting to whatever is listening
locally, which is the failure mode this issue exists to remove.

Verified without the build farm:
  nix eval .#nixosConfigurations.<cfg>.config.assertions \
    --apply 'l: builtins.filter (a: !a.assertion) l'   # => []
  nix eval --raw .#nixosConfigurations.<cfg>.config.systemd.services.tea-login.script

Refs #2860
This commit is contained in:
atlas 2026-07-31 23:03:22 +02:00
commit bf78808f9b

View file

@ -149,11 +149,34 @@
nixosConfigurations =
let
# Values the agent modules require but that only a real
# deployment can know. Real containers are built from the
# generated meta flake, where hive-c0re renders these per
# agent from the host's `HIVE_FORGE_URL` (see meta.rs's
# `SERVICE_URL_OPTIONS`) — they never evaluate through
# `self.nixosConfigurations`, so nothing here can reach a
# running agent. These two configs exist only to typecheck
# the modules and to pre-build the container closure
# (`system.extraDependencies`, see hive-c0re/default.nix).
#
# Deliberately a `.invalid` host (RFC 2606: guaranteed not to
# resolve) rather than something plausible like a loopback
# port. If this value ever *did* escape into a runtime path,
# it must fail loudly at DNS instead of quietly connecting to
# whatever happens to be listening — which is the entire
# point of removing the `http://localhost:3000` default this
# replaces.
evalOnlyPlaceholders = {
hyperhive.forge.url = "http://forge.invalid";
};
mkContainer =
module:
nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [ module ];
modules = [
module
evalOnlyPlaceholders
];
};
in
{