feat(#3255): register the swarm-wide forge hooks against the controller
The endpoint landed inert: nothing pointed at it, so the only way to see it work was to mint an HMAC by hand. Register the two swarm-wide hooks at startup so a real forge event produces a journal line. Registered ALONGSIDE the per-hive hooks, not instead of them. Every hive keeps receiving and acting on its own deliveries; the controller gets a copy and logs it. Moving the registration is a later step and has to be: fan-out swarm->hive does not exist yet, so a hook moved now would point at a receiver that forwards nowhere, silently on both sides. Deliberately no stale-hook deletion arm, unlike the two per-hive registrars this otherwise mirrors: theirs delete hooks matching their own path with a foreign base, and the hives' hooks are not stale. The route prefix is what keeps this safe. Both hive-side registrars delete any hook ending in /webhook/knowledge or /webhook/config-pr with a different base, so a swarm hook under those paths would be deleted by every hive on every boot. Serving them under /webhook/forge/ avoids it, and a test pins it -- there is nothing else that can. SWARM_CONTROLLER_PUBLIC_URL is set only where the swarm vhost is served, because a hook whose target_url nothing answers is worse than no hook.
This commit is contained in:
parent
a8bc084262
commit
4573865745
6 changed files with 325 additions and 13 deletions
|
|
@ -33,6 +33,7 @@ let
|
|||
|
||||
natsCfg = config.services.hyperhive.swarm.nats;
|
||||
forgeCfg = config.services.hyperhive.swarm.forge;
|
||||
uiCfg = config.services.hyperhive.swarm.ui;
|
||||
|
||||
# The controller's own OAuth2 client. It is NOT a hive: the per-hive
|
||||
# clients the roster issues belong to hives, and the responder's client
|
||||
|
|
@ -85,6 +86,19 @@ let
|
|||
SWARM_CONTROLLER_FORGE_TOKEN_FILE = "%d/forge-token";
|
||||
};
|
||||
|
||||
# How the forge must address this controller to deliver a swarm-wide
|
||||
# webhook. Gated on the swarm UI being served *here*, because that module
|
||||
# is what declares the vhost and the `/webhook/forge/` location inside it:
|
||||
# absent, nothing outside this host can reach the endpoint.
|
||||
#
|
||||
# 🔑 The gate is the point, not a detail. The daemon registers hooks only
|
||||
# when this is set, and a hook whose `target_url` nothing answers is worse
|
||||
# than no hook at all — forgejo keeps the registration, marks every
|
||||
# delivery failed, and the hook still reads as configured.
|
||||
webhookEnv = lib.optionalAttrs uiCfg.enable {
|
||||
SWARM_CONTROLLER_PUBLIC_URL = "https://${uiCfg.domain}";
|
||||
};
|
||||
|
||||
# Not a secret to deliver — `swarm-authelia-bridge`'s own bearer check
|
||||
# is satisfied by THIS daemon's existing queue OIDC identity
|
||||
# (`queueEnv` above): "one identity per principal" already covers this,
|
||||
|
|
@ -594,6 +608,7 @@ in
|
|||
}
|
||||
// queueEnv
|
||||
// forgeEnv
|
||||
// webhookEnv
|
||||
// authBridgeEnv;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue