Watch
0
0
Fork
You've already forked hyperhive
0

swarm UI: send a message to an agent, without its hive

The agent view in the swarm UI gets a message box. The text reaches the
agent's harness straight from swarm-controller over the swarm queue and
becomes an inbox turn from the operator's authelia username. hive-c0re is
not in the path.

- gateway: `/api/` forwards authelia's `Remote-User`, replacing any the
  client sent.
- swarm-controller: `POST /api/agents/{name}/input` takes that header as
  the sender (401 without it) and sends `{from, body}` as a NATS request
  on `$SWARM.input.<agent>`. No subscriber is a 503.
- swarm-nats-auth: the controller is granted publish on `$SWARM.input.*`;
  no hive or agent grant names the family, so the harness can trust
  `from`.
- hive-agent: a task subscribes to the agent's own input subject and
  pushes each message into the serve loop's existing reminder channel,
  renamed `local_msg_*` since it now carries both.

The harness does not reply to the request: no agent grant covers a reply
subject. The controller therefore answers 202 once the request times out
(2s) and 503 on the server's no-responders status.

Closes #4828
This commit is contained in:
atlas 2026-10-04 03:00:05 +02:00
commit 48ac4ac423
13 changed files with 664 additions and 24 deletions

View file

@ -215,7 +215,14 @@ in
# nginx forwards, no prefix-stripping to keep in sync by hand.
"/api/" = {
proxyPass = "http://unix:${deployCfg.swarm-controller.socketPath}:";
extraConfig = swarmAuthRequest;
# `Remote-User` from authelia's answer, set here so it replaces
# any the client sent: swarm-controller takes it as the sender of
# the text the operator types to an agent (`agent_input.rs`).
extraConfig = ''
${swarmAuthRequest}
auth_request_set $authelia_user $upstream_http_remote_user;
proxy_set_header Remote-User $authelia_user;
'';
};
# ⚠️ THE ONE LOCATION ON THIS VHOST WITH NO `swarmAuthRequest`,
# and that is deliberate rather than an omission.
@ -247,10 +254,10 @@ in
'';
};
# Session identity for the header's profile menu: initials
# avatar + "who is this" line. `auth_request` above
# only ever answers yes/no — it never forwards *who* — so the
# frontend has no other way to learn this. Same-origin proxy
# straight to authelia's own `GET /api/user/info`
# avatar + "who is this" line. `auth_request` tells the
# browser nothing about *who* (only `/api/` passes it on, to the
# controller), so the frontend has no other way to learn this.
# Same-origin proxy straight to authelia's own `GET /api/user/info`
# (session-cookie authenticated) rather than new
# swarm-controller code: the cookie is already valid here (the
# session cookie's domain is the swarm's, shared across every