Relationships
#2481 serve HA: a server token minted on one replica is rejected by the other replicas until they restart (auto-definitions/ is only pulled at boot)
Opened by skunk-ape · 9/24/2026· Shipped 10/6/2026
Summary
On a multi-replica swamp serve with a remote datastore, a server token minted on one replica cannot authenticate on the others until they restart. The token definition is written to auto-definitions/, and running replicas never pull that directory after boot.
This came out of #2466 (fixed in swamp-club/swamp#2606): access token mint --server now works and is live at once on the replica that handled it. Other replicas still reject the token.
Why
- Auth reads the token definition from the local repo on every connection:
createServerTokenAuthDepsthendefinitionRepo.findByName(SERVER_TOKEN_MODEL_TYPE, name)insrc/serve/token_auth.ts. A missing definition fails with "Server token ... does not exist — mint it first". - A mint writes the definition to
auto-definitions/and pushes it (per-path markDirty, since #2127/#2275). The token data goes todata/, and the secret goes to the control-plane store. - Other replicas pull
auto-definitions/only at boot: the full boot pull, plus the managedConfig pull insrc/cli/commands/serve.tsaround line 1910. After boot, the pollers pull onlydata/(RuntimeDataPoller, every 30s),config/and extension dirs (ConfigPoller), and the grant/group data dirs (AccessDataPoller). None of them pullauto-definitions/.
So a peer replica gets the token data within about 30s and can read the secret from the shared control-plane store, but it never sees the definition, and auth fails until that replica restarts.
Likely also affected (from reading the code, not reproduced)
Anything else authenticated through an auto-definition created at runtime on another replica:
- server tokens minted by the OAuth device login (
device_auth_handler.ts), when the next connection lands on a different replica; - worker enrollment tokens.
Steps to reproduce
- Run two
swamp servereplicas against the same S3/GCS datastore, with--auth-mode token. - As an admin, run
swamp access token mint probe --principal user:probe --server <replica A>. - Reveal the credential and connect to replica B with it (for example
swamp access can-i --server <replica B> --token <credential>).
Expected
Replica B accepts the token within its normal poll interval, with no restart.
Actual (expected from the code path above)
Replica B fails authentication with "does not exist — mint it first" until it restarts. Replica A accepts the token.
Possible directions
- Have a poller also pull
auto-definitions/, or at least the server-token and enrollment-token type directories. - Or, on a definition miss during auth, do a targeted pull of that token definition before failing.
Shipped
Click a lifecycle step above to view its details.
Sign in to post a ripple.