hive-matrix-mcp: read the main account's token from the store too
The daemon reads each account's token from `swarm/agents/<agent>/matrix/` as the agent itself, inside its own container, and falls back to the file only when the store has none. This is #4519's read, without its `main` carve-out: the swarm now mints `main` there and no hive writes the file. The daemon unit gets the agent's store identity, spelled the way forge-token.nix spells it. A timer re-starts it while it is down: a token the swarm mints or replaces in the store changes no file, so the path watcher never fires for it, and a daemon that exited on a replaced token would otherwise stay down until the container restarts.
This commit is contained in:
parent
2776e121e5
commit
ab153bda2f
9 changed files with 670 additions and 85 deletions
|
|
@ -18,6 +18,7 @@ let
|
|||
;
|
||||
})
|
||||
agent
|
||||
agentWith
|
||||
runGroup
|
||||
;
|
||||
|
||||
|
|
@ -45,6 +46,15 @@ let
|
|||
homeserver = "https://matrix.example.invalid";
|
||||
};
|
||||
};
|
||||
# The daemon that reads its tokens from the store, `main` included. Paired
|
||||
# with `agentMatrix` above — same daemon, no store — so each case below can
|
||||
# tell "carries the store's coordinates" from "every matrix daemon does".
|
||||
agentMatrixBao = agentWith {
|
||||
services.hyperhive.agent.bao.addr = "https://bao.t.local:8200";
|
||||
services.hyperhive.agent.matrix.url = "https://chat.t.local";
|
||||
};
|
||||
|
||||
daemon = machine: machine.systemd.services.hive-matrix-daemon;
|
||||
cases = [
|
||||
{
|
||||
# A homeserver URL is the whole input: from it the module derives the
|
||||
|
|
@ -102,6 +112,69 @@ let
|
|||
# No hive homeserver, so nothing may claim one.
|
||||
&& !(env ? HIVE_MATRIX_URL);
|
||||
}
|
||||
{
|
||||
# The daemon reads this agent's tokens from the store ITSELF, as itself,
|
||||
# from inside this container — `main` too, since the swarm mints it and
|
||||
# no hive does. So it needs the same identity ./agent-forge-bao.nix's
|
||||
# fetch carries, in its own credentials directory.
|
||||
name = "the matrix daemon carries this agent's own store identity";
|
||||
ok =
|
||||
let
|
||||
u = daemon agentMatrixBao;
|
||||
in
|
||||
u.serviceConfig.LoadCredential == [
|
||||
"hive-agent-bao-cert"
|
||||
"hive-agent-bao-key"
|
||||
"hive-agent-bao-server-ca"
|
||||
]
|
||||
&& u.environment.BAO_ADDR == "https://bao.t.local:8200"
|
||||
&& u.environment.BAO_CLIENT_CERT == "%d/hive-agent-bao-cert"
|
||||
&& u.environment.BAO_CLIENT_KEY == "%d/hive-agent-bao-key";
|
||||
}
|
||||
{
|
||||
# The agent's name, and nothing derived from it: the daemon builds its
|
||||
# store path and its cert-auth role from this one string.
|
||||
name = "the matrix daemon is told which agent it is and not where its credentials live";
|
||||
ok =
|
||||
let
|
||||
e = (daemon agentMatrixBao).environment;
|
||||
in
|
||||
e.HIVE_AGENT_NAME == agentMatrixBao.services.hyperhive.agent.user.name
|
||||
&& !(lib.any (lib.hasInfix "swarm/agents") (lib.attrValues e));
|
||||
}
|
||||
{
|
||||
# 🩸 A secret is a path: every `BAO_*` entry is the store's address or a
|
||||
# file under this unit's own credentials directory, never bytes in an
|
||||
# environment `/proc/<pid>/environ` publishes.
|
||||
name = "the matrix daemon is handed store paths and never store values";
|
||||
ok =
|
||||
let
|
||||
store = lib.filterAttrs (n: _: lib.hasPrefix "BAO_" n) (daemon agentMatrixBao).environment;
|
||||
in
|
||||
store != { }
|
||||
&& lib.all (n: n == "BAO_ADDR" || lib.hasPrefix "%d/" store.${n}) (lib.attrNames store);
|
||||
}
|
||||
{
|
||||
# A token the swarm mints or replaces in the store changes no file, so
|
||||
# the path watcher never sees it. The timer is what re-starts a daemon
|
||||
# that exited on a missing or replaced token.
|
||||
name = "a store-backed matrix daemon is re-started while it is down";
|
||||
ok =
|
||||
agentMatrixBao.systemd.timers.hive-matrix-daemon.timerConfig.OnUnitInactiveSec or null == "5min";
|
||||
}
|
||||
{
|
||||
# The absence arm for the four above: with no store, no identity, no
|
||||
# timer, and the file is the whole mechanism.
|
||||
name = "a matrix daemon on an agent with no store declares no identity and no timer";
|
||||
ok =
|
||||
let
|
||||
u = daemon agentMatrix;
|
||||
in
|
||||
!(u.serviceConfig ? LoadCredential)
|
||||
&& !(u.environment ? BAO_ADDR)
|
||||
&& !(u.environment ? HIVE_AGENT_NAME)
|
||||
&& !(agentMatrix.systemd.timers ? hive-matrix-daemon);
|
||||
}
|
||||
];
|
||||
in
|
||||
runGroup "agent-matrix" cases
|
||||
|
|
|
|||
Loading…
Reference in a new issue