The credential deadline — the moment a resolved credential stops
authenticating, which a long-lived connection opened on it must not outlive.
A WebSocket or an SSE stream is authorized once, at open, and closed on
revocation by identity. Expiry has no revocation event: nothing is written
when a session or token passes its expires_at. So the auth middleware
computes the deadline once (CREDENTIAL_DEADLINE_KEY, gathered onto
ResolvedAuth.credential_deadline) and the transport closes the connection
when it arrives (schedule_credential_deadline).
The deadline is the earliest of what the credential carries:
- Session — the signed cookie's embedded expiry and the
auth_session
row's expires_at. - API token — the
api_token row's expires_at; an eternal token
(expires_at IS NULL) has none. - Daemon token — none: it has no row and no expiry, and a rotation
closes no connection.
A row's expiry is read as remaining time measured on the database clock
(EXPIRES_IN_MS_SQL, expires_at - NOW() in the same statement that checks
expires_at > NOW()), then anchored to this process's monotonic clock
(performance.now()) — so a skew between the database's clock and the
server's moves no deadline. The cookie's expiry is a wall-clock second this
server signed, read against the same wall clock the cookie check reads.
The monotonic clock stops while the host is suspended, so a deadline on it
alone would hold a connection past its credential by the time asleep. The
wait (schedule_credential_deadline) therefore also carries the deadline on
the wall clock (Date.now()), which keeps running through a suspend, and
fires at whichever is reached first: after a resume, within one timer step
(CREDENTIAL_DEADLINE_TIMER_CAP_MS, an hour). The wall deadline is taken
from the time left when the wait starts, so a skew between the database's
clock and the server's still moves nothing. A wall clock stepped forward
can fire it early; the client reconnects through the gates, the fail-closed
side of the trade.
The twin of the Rust spine's fuz_auth::ResolvedAuth::credential_deadline
and fuz_realtime's deadline wait.