nix: gate the avatar-sync path unit on the same condition as its service
`systemd.paths.forge-avatar-sync` was gated on `agent.icon != null` alone, while the `systemd.services.forge-avatar-sync` it triggers is gated on `agent.icon != null && agent.forge.url != null`. An agent with an icon and no forge URL therefore rendered a `.path` unit, pulled into multi-user.target, watching for a forge-token whose arrival would activate a unit that does not exist. The module already documents the fixed behaviour: `forge.url`'s own option description says the tea-login and avatar-sync units are "not generated at all" when it is null --- an absent integration, never a misdirected one. That sentence was true of the oneshot and false of its watcher. Latent, not live: hive-c0re renders `forge.url` into every agent's config from the host's `HIVE_FORGE_URL`, so on a real hive it is always set and the asymmetric arm is unreachable. It is reachable wherever the agent modules are evaluated outside a hive. A module-eval case pins both halves absent for an agent with an icon and no forge; it fails on the parent commit, where the path unit renders.
This commit is contained in:
parent
fb9a2c0830
commit
ed1fce3329
2 changed files with 39 additions and 7 deletions
|
|
@ -12,8 +12,8 @@ let
|
|||
homeDir = "/home/${userName}";
|
||||
# Same 512×512 rasterization of the agent icon the matrix avatar
|
||||
# sync uses (./matrix.nix — identical derivation, same store path).
|
||||
# Only forced when an icon is configured (the avatar-sync unit below
|
||||
# is gated on `services.hyperhive.agent.icon != null`).
|
||||
# Only forced when an icon is configured AND a forge is (the avatar-sync
|
||||
# unit below, the one thing that references this, is gated on both).
|
||||
iconPng = pkgs.runCommand "hive-agent-icon.png" { nativeBuildInputs = [ pkgs.librsvg ]; } ''
|
||||
rsvg-convert -f png -w 512 -h 512 ${config.services.hyperhive.agent.icon} -o $out
|
||||
'';
|
||||
|
|
@ -266,11 +266,20 @@ in
|
|||
# watches paths this unit has no business reacting to.
|
||||
# The service reads `$HYPERHIVE_STATE_DIR/forge-token`; this is the same
|
||||
# file, spelled the way `tea-login` above already spells it.
|
||||
systemd.paths.forge-avatar-sync = lib.mkIf (config.services.hyperhive.agent.icon != null) {
|
||||
description = "trigger forge-avatar-sync when forge-token appears";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
pathConfig.PathChanged = "/agents/${userName}/state/forge-token";
|
||||
};
|
||||
#
|
||||
# ⚠️ Gated on the SAME condition as the service it triggers, not just on
|
||||
# the icon: a `.path` unit whose `Unit=` does not exist is a unit pulled
|
||||
# into multi-user.target that can only ever fail to activate. The two
|
||||
# halves are one feature and appear together or not at all --- which is
|
||||
# what `forge.url`'s own option doc promises.
|
||||
systemd.paths.forge-avatar-sync =
|
||||
lib.mkIf
|
||||
(config.services.hyperhive.agent.icon != null && config.services.hyperhive.agent.forge.url != null)
|
||||
{
|
||||
description = "trigger forge-avatar-sync when forge-token appears";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
pathConfig.PathChanged = "/agents/${userName}/state/forge-token";
|
||||
};
|
||||
|
||||
# One-shot: services.hyperhive.agent.icon → Forgejo profile avatar. Shape contract:
|
||||
# docs/process/conventions.md::Best-effort oneshot services.
|
||||
|
|
|
|||
Loading…
Reference in a new issue