docs(#3255): correct the rest of the relay-shaped wording

mara asked for the docs and comments to be fixed in one PR before the
implementation, since a half-corrected description is what confuses a
reader coming back after a context compact.

Three more places said or implied "forward the payload":

- post_webhook_forge's doc ("relays the delivery to every hive ... the
  payload is never parsed here")
- its OpenAPI request_body description ("the delivery can be relayed
  unmodified") -- this one is published in the spec, so it was the most
  externally visible of them
- DeliveryKind::as_str, which called the hook kind the event's routing
  key; the message is semantic, and which hook it arrived on is an input
  to deriving it rather than the thing sent

docs/swarm/README.md gains the direction next to the interim state, so
"two hooks, one of which only logs" reads as a step rather than a design.
This commit is contained in:
atlas 2026-08-18 12:33:15 +02:00
commit b172e67fbd
2 changed files with 21 additions and 8 deletions

View file

@ -363,6 +363,13 @@ nothing more. **Do not delete either.** Removing a hive's hook stops that
hive acting on knowledge pushes and config PRs; removing the hive acting on knowledge pushes and config PRs; removing the
controller's just gets recreated on its next start. controller's just gets recreated on its next start.
Where this is going, so the interim state reads as interim: the
controller will **interpret** a delivery and send hives a specific
message — *the knowledge repo changed*, *deploy agent `foo` at rev
`abc123`* — rather than forwarding forge payloads for each hive to
re-derive. Approval happens once, at the swarm level, before the message
is sent; a hive receives a decision, not an event to adjudicate.
Nothing to configure. The hooks are registered only when this host also Nothing to configure. The hooks are registered only when this host also
serves the swarm UI vhost — that is what publishes the endpoint, and a serves the swarm UI vhost — that is what publishes the endpoint, and a
hook the forge cannot reach would collect failed deliveries while hook the forge cannot reach would collect failed deliveries while

View file

@ -218,9 +218,14 @@ impl DeliveryKind {
} }
} }
/// Stable string form, used for logging and (once fan-out lands) as the /// Stable string form, used for logging. Deliberately the same spelling
/// event's routing key. Deliberately the same spelling as the path /// as the path segment so a journal line can be matched against a
/// segment so a journal line can be matched against a registered URL. /// registered URL.
///
/// ⚠️ **Not the routing key for the swarm→hive message.** That message is
/// semantic (*knowledge repo changed*, *deploy agent X at rev Y*) and is
/// addressed to the hives that need it; which hook a delivery arrived on
/// is an input to deriving it, not the thing sent.
fn as_str(self) -> &'static str { fn as_str(self) -> &'static str {
match self { match self {
Self::Knowledge => "knowledge", Self::Knowledge => "knowledge",
@ -311,9 +316,10 @@ pub(super) fn verify(
/// POST `/webhook/forge/{kind}` — a swarm-wide Forgejo delivery. /// POST `/webhook/forge/{kind}` — a swarm-wide Forgejo delivery.
/// ///
/// Verifies the HMAC over the raw body, then (once fan-out lands) relays the /// Verifies the HMAC over the raw body. Nothing consumes the delivery yet;
/// delivery to every hive over the swarm queue. The payload is never parsed /// once the swarm→hive channel lands, this daemon **parses** it and emits a
/// here — see the module docs. /// semantic message (*knowledge repo changed*, *deploy agent X at rev Y*) to
/// the hives that need it — see the module docs.
/// ///
/// Returns 200 on an accepted delivery so Forgejo does not retry. A refused /// Returns 200 on an accepted delivery so Forgejo does not retry. A refused
/// one answers 401 (bad signature) or 503 (this daemon has no secret), and /// one answers 401 (bad signature) or 503 (this daemon has no secret), and
@ -329,8 +335,8 @@ pub(super) fn verify(
content = String, content = String,
content_type = "application/json", content_type = "application/json",
description = "Forgejo webhook payload, taken as raw bytes so HMAC \ description = "Forgejo webhook payload, taken as raw bytes so HMAC \
verification runs over the exact wire bytes and the \ verification runs over the exact wire bytes rather \
delivery can be relayed unmodified" than over a reserialised copy"
), ),
responses( responses(
(status = 200, description = "delivery accepted", body = String), (status = 200, description = "delivery accepted", body = String),