Expand description
Per-agent local identity token, keyed by the agent’s UID (db_agents.id).
Identity M1 of docs/specs/SPEC_AGENT_IDENTITY_CARRIED_NOT_DERIVED_2026_09_23.md
(§6, §9.1). See db_agent_tokens in migrations.rs (OBJECT_SCHEMA_VERSION
v37).
What it is. A secret the server generates for one agent and hands to
that agent’s process environment at spawn (AGENTMUX_AGENT_TOKEN, set by
build_persistent_spawn_env). Only the server and the agent it spawned
ever hold the value, which is what will let a later phase (M4) map
token → UID on a request and treat that as the caller’s identity,
instead of trusting an agent_id the request body asserts. Spec §2
rule 2: identity is proven, not asserted.
What it is not. Not the cloud Cognito M2M credential in
muxbus/agent_credentials.rs — that one needs a prior human login and
falls back to a shared token by design, both of which disqualify it
(spec §0.3). This is minted locally, with no network and no fallback.
Lifetime. Long-lived for the agent’s lifetime and revoked when the
agent is deleted (purge_agent_dependents), never renewed on a timer:
spec §6.3 — expiry mid-task turns a healthy agent silent, and renewal is a
liveness dependency on the very path being secured. Persisted here, in
the server’s own store, so an srv restart does not strand every running
agent with a token nothing can verify (same section). This is the
server persisting its own secret where only the server reads it — not a
name-keyed, agent-readable file in shared space, which §6.3 rules out.
Keyed by UID, not name. db_agent_jekt_keys and the registry entry
files are keyed by display name, so two agents sharing a name share one
credential (spec §6.3). This table cannot have that defect: db_agents.id
is a PRIMARY KEY, and every non-template row is a UUID.
Read since M4a through TokenIndex: a request carrying
X-Agent-Token is attributed to the UID the token was minted for
(spec §6.5.3). Attribution only — an unknown token is treated as absent,
never refused.
Structs§
- Token
Index - token → UID, in memory, so attributing a request never reads the store
(spec §10.1). Attached to the channel’s object store only
(
Store::attach_token_index) and kept in step withdb_agent_tokensby the two statements that change it — mint (agent_token_ensure) and revoke (purge_agent_dependents) — each under the store’s connection lock, so the index never disagrees with a committed row (spec §6.5.3: purge is a sequence of autocommit statements, not a transaction, so the index follows the token statement itself, not the purge’s result). - Token
Maps 🔒
Functions§
- random_
token 🔒 - 32 bytes of CSPRNG randomness from
random_seed_bytes, hex-encoded (64 chars); hex rather than base64 so the value is safe in any environment-variable or shell context without quoting.