Algostream_infrastructure_auth.TicketSingle-use tickets for the event stream.
Everything else authenticates with Authorization: Bearer, and that choice does more work than it looks like it does. A cross-origin fetch that sets Authorization is not a CORS simple request, so it triggers a preflight; the server sends no Access-Control-Allow-* headers, the preflight fails, and the request is never sent. A page the operator happens to have open in another tab therefore cannot forge a control action — a complete CSRF defence with no CSRF machinery, no tokens to double-submit and no SameSite reasoning.
This is precisely why there is no cookie session here. A cookie is attached by the browser automatically, including on a cross-site POST, which would reintroduce the attack the bearer header rules out — in order to solve a problem that exists at exactly one endpoint.
That one endpoint is /events. EventSource cannot set request headers, so the stream needs a credential it can carry in a URL. A ticket is that credential, made weak enough that carrying it in a URL does not matter:
kid and scopes of the key that minted it, so the stream can be attributed and swept when that key is revoked.Api_key.verify the keys use, rather than a second comparison path that could rot differently.The table is capped, and sweeping happens on mint, so a client that requests tickets and never connects cannot grow memory.
val mint : t -> now_ns:int64 -> kid:string -> scopes:Scope.Set.t -> stringmint t ~now_ns ~kid ~scopes returns the ticket string to hand to the client.
val redeem : t -> now_ns:int64 -> ticket:string -> Principal.t optionredeem t ~now_ns ~ticket consumes a ticket and returns the principal it was minted for.
None when the ticket is unknown, already used, or older than ttl_ns. The three are deliberately not distinguished: the caller answers 401 either way, and saying which would tell an attacker whether a guess was ever valid.
val outstanding : t -> intOutstanding, unredeemed count. For tests and telemetry.