Keepalive via refresh-session; GET pings measured insufficient
The endurance test refuted the sliding-window model I committed earlier. A keepalive doing only GET /api/v3/me succeeded at t+0/30/60/90 and was still rejected by t+120 — consistent with the session ending ~2h after LOGIN (t+107), and inconsistent with 2h after the last request, which would have been t+210. This is a live-vs-source divergence, not a misreading: both the current JwtWhitelistAdapter and the legacy Feathers ensureTokenIsWhitelisted re-set the Valkey TTL on every authenticated request, so the source reads as a sliding window. The instance does not behave that way. So the keepalive now calls POST /authentication/refresh-session, the endpoint behind the UI's "Sitzung verlängern" button, which a separate 100s test showed does hold the reported budget at 7200s. It is the only non-GET request in the server: no body, touches only our own session, cannot read or modify user data, and is not exposed as a tool, so no model-driven call can ever be a POST. It logs the returned budget, which makes a failing extension visible before the session is lost. Whether this is sufficient is NOT established. Two mechanisms still fit: an idle TTL that reads fail to refresh (keepalive works), or an absolute cap/revocation anchored at login — e.g. the IDP's back-channel logout, which clears every token for the account rather than one. Added scripts/session-diagnose.mjs to settle it: it logs the budget every 10 min, so a decaying series indicates the former and an abrupt 401 at 7200s the latter. Docs state the open question rather than asserting a mechanism. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
22
README.md
22
README.md
@@ -50,20 +50,21 @@ npm run probe # verifies the token and API against the live instan
|
||||
Then either deploy it as a remote connector, or point Claude Code at
|
||||
`dist/bin/stdio.js`. Both paths are in [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md).
|
||||
|
||||
Getting `TSC_JWT_COOKIE` takes four clicks in DevTools. With the server running
|
||||
it lasts up to 30 days; left idle for two hours it dies regardless — see
|
||||
[docs/AUTH.md](docs/AUTH.md).
|
||||
Getting `TSC_JWT_COOKIE` takes four clicks in DevTools. Expect to redo it
|
||||
often until the session question in [docs/AUTH.md](docs/AUTH.md) is settled —
|
||||
sessions have been observed ending ~2 h after login.
|
||||
|
||||
## Design decisions
|
||||
|
||||
**Bearer token plus a keepalive.** The instance's `jwt` cookie works verbatim
|
||||
as `Authorization: Bearer` — no cookie jar, no `connect.sid`. But the token has
|
||||
two clocks: a 30-day `exp` claim, and a **2-hour idle timeout** held in a
|
||||
server-side whitelist that *every* authenticated request resets. Only the first
|
||||
is visible in the token, which makes "valid for 30 days" an easy and wrong
|
||||
conclusion. So the server pings `GET /api/v3/me` every 30 minutes to hold the
|
||||
window open. See [docs/AUTH.md](docs/AUTH.md) — this one cost a day-old token to
|
||||
pin down.
|
||||
as `Authorization: Bearer` — no cookie jar, no `connect.sid`. But the token's
|
||||
`exp` claim (30 days) is not its lifetime: the session ends about **two hours
|
||||
after login**, and measurement showed that ordinary API reads do *not* extend
|
||||
it, despite the upstream source saying they should. So the server calls
|
||||
`refresh-session` every 30 minutes — the one non-GET request here, and not
|
||||
exposed as a tool. Whether that is enough is still being measured; see
|
||||
[docs/AUTH.md](docs/AUTH.md), which has the endurance test and the open
|
||||
question.
|
||||
|
||||
**Read-only by construction.** Every method on the API client is a `GET`,
|
||||
including `api_get`. The endpoint is internet-facing by necessity (Claude's
|
||||
@@ -104,6 +105,7 @@ npm run dev # watch mode, runs src/ directly
|
||||
npm test # unit tests, no network
|
||||
npm run probe # check assumptions against the live instance
|
||||
npm run smoke # full end-to-end: real server, real client, real data
|
||||
npm run session-diagnose # instrument what actually ends the session (~2.5h)
|
||||
npm run typecheck
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user