Expand description
zackees/soldr#2360/#2363 — composite broker/daemon session token
authority. Wired into hello_handler via
HelloHandler::with_session_token_authority — see the module docs.
Composite broker/daemon session token authority (zackees/soldr#2360, #2361
Phase 1, #2363).
STATUS: wired into crate::broker::server::hello_handler::HelloHandler via
with_session_token_authority — opt-in, dormant unless a caller
configures it. See “Not done yet” below for what’s still open.
§What this is — a cooperative invalidation signal, NOT authentication
This is a liveness/generation notification scheme for a cooperative client inside one trust domain (all roles run as the same user on the same machine). It is not a security boundary and does not authenticate anyone.
Every client session carries a composite token broker_token ‖ daemon_token: the first half minted once by the broker at its own
startup, the second minted by the specific daemon the client is talking
to. The halves are generation markers — “the broker/daemon incarnation
you established this session against”. When a presented token stops
validating, that tells the client its session has terminated or the
broker/daemon got forcefully cycled since its last message: the session
is invalid, and the client should report the error (the
cancelled-because-stopped message class, soldr#2363), unwind, and exit 1
— never retry against the new incarnation as if nothing happened.
Two-level invalidation falls out of the split for free:
- Rotating the broker half signals every session across every daemon at once (broker restart, or a live rotation e.g. after the spawn-storm guard trips).
- Invalidating one daemon’s half signals only that daemon’s sessions; sessions against other daemons are unaffected.
The halves come from OS randomness only so that incarnations are
globally unique — a restarted broker or daemon can never accidentally
validate a stale token minted by its predecessor, the way a counter or
timestamp could collide. The bytes are not secrets guarding anything,
which is also why the plain != comparison (mirroring
crate::broker::server::handoff::HandoffToken) is fine here: constant-time comparison
defends secrets against guessing oracles, and there is no secret and
nothing to guess for.
There is deliberately no TTL on these tokens. A session may go silent for arbitrarily long (e.g. a link phase with no daemon traffic) and remain valid; invalidation is communicated lazily, just in time, on the next communication intent — the client learns its session died at the exact moment it next tries to use it, which is the only moment it matters.
This module is the authority that mints, rotates, and validates both
halves. It deliberately knows nothing about the wire (Hello.auth_token,
already reserved on the v2-reuses-v1-framing Hello message — see
broker_v1_envelope.proto) or about HelloHandler /
RegisteredBackend — see “Not done yet”.
§Not done yet (left for a follow-up slice)
daemon_idis resolved ashello.service_name— the same keyRegisteredBackendalready uses — rather than a new field.RefusedusesERROR_PEER_REJECTEDfor everycrate::broker::server::session_token::SessionTokenRejectionkind. Both settled in theHelloHandlerwiring.- Where the authority instance itself lives (per-broker-process
singleton state) and how
register_daemon/invalidate_daemonare threaded into the daemon spawn/exit lifecycle — that’s soldr#2361 Phase 2 (spawn-chain inversion), which is what will actually callwith_session_token_authorityand stop this from being dormant. - Persistence-boundary invariant from soldr#2363’s testing invariants (“no token material is ever written under a daemon cache root”) — this module is pure in-memory today, so that invariant holds trivially for it, but the caller that eventually persists broker-side session state must uphold it too.
Structs§
- Session
Token Authority - Mints, rotates, and validates the composite
broker_token ‖ daemon_tokenpair described in the module docs. - Token
Half - One 128-bit half of a composite session token. Used for both the broker-minted half and each daemon-minted half — the two are typed identically; which is which is a matter of which map an instance is looked up in, not a type-level distinction.
Enums§
- Session
Token Error - Errors raised while minting session-token halves.
- Session
Token Rejection - Why a presented composite token failed validation.
Constants§
- SESSION_
TOKEN_ HALF_ BYTES - Number of bytes in one half of the composite token (128 bits), matching
super::handoff::HandoffToken’s existing size for consistency. - SESSION_
TOKEN_ TOTAL_ BYTES - Total presented-token length: broker half + daemon half.
Functions§
- compose_
presented_ token - Concatenate a broker half and a daemon half into one presented-token
byte vector, matching what
SessionTokenAuthority::validateexpects. A convenience for a client-side caller assemblingHello.auth_token.
Type Aliases§
- Daemon
Id - Opaque identifier for one daemon’s token slot. Deliberately a plain
Stringrather than reusingServiceDefinition’s type, since how a daemon identity maps to a registered backend is one of the open wiring questions above — this keeps the authority decoupled from that decision until it’s made.