Skip to content

Document claim_seconds and the logout machinery - #13

Open
stsepelin wants to merge 8 commits into
docs/session-readinessfrom
docs/claim-and-logout
Open

stsepelin wants to merge 8 commits into
docs/session-readinessfrom
docs/claim-and-logout

Conversation

@stsepelin

Copy link
Copy Markdown
Owner

Second of three. Based on docs/session-readiness.

claim_seconds, SessionUnclaimed, the logout note and streaming behaviour; how a logout the page left behind is finished, per transport, and what a reader must do about it; the per-call baseURL rule; the stale-marker limitation and the stand-down anchor.

…must do about it

A docs-versus-behaviour audit found claims a security-conscious reader would have relied on: that lukk-js
had shipped no breaking changes, that every throttle has a key in the rate-limits table, that the browser
holds nothing but the opaque session cookie, that logout is an authenticated route.

So: the signed-out cookie is named and explained alongside the note; the 5s wait and 10s cooldown are
stated, along with their per-process scope; the logout lookup bucket appears everywhere clientIpHeader is
advised; the claim route's throttle is in the endpoint table; what lukk-js writes to web storage in direct
mode is listed, because clearing localStorage on logout can end a newer session; a replacement refresh
repository is told it must populate createdAt; co-hosted apps are told to differ on app.baseURL as well as
session.name; and Known limitations gains the logout lookup budget as a side channel and the note that
expires while lukk is unreachable.

Also recorded: a page under a Nitro cache route rule renders signed out, because a cached handler only
receives the headers its rule varies on — measured, not assumed.
…moved under it

The re-audit checked the previous documentation round rather than trusting it, and found claims that had
gone stale within a day: the browser-storage keys and the co-hosting rule both predate scoping on
`session.name`; the signed-out cookie was described as withheld from cacheable responses, which describes
a guard that was measured to be unnecessary and removed; note renewal is BFF-only, since direct mode
deliberately never re-stamps; and the cached-route note claimed more than was measured — a cached HANDLER
is what never sees the cookie, while lukk's own logout middleware still runs on that request.

Also records the cost of turning `cookieSecure` off in production (both logout cookies lose `__Host-` with
the session cookie), the logout lookup bucket in the one deployment bullet that omitted it, and the claim
window's fixed tolerance for a replacement repository.
`useLukkFetch` judges a per-call `baseURL` as well as the path, since ofetch applies the base after
the hook that decides whether to attach credentials — spelled out next to the existing cross-origin
note, with what is accepted in each mode.

New known limitation: a `logout()` whose work outlives the page can stand down on the next page load,
when there is evidence of a sign-in since it was asked for. Standing down is correct — the session it
was for is gone and sending would end the newer one — but the original call had already resolved
without throwing, so a `.then()` that renders "signed out" is describing the old session. Read the
reactive state instead.
…tion

A review comparing the pages against the code found these had been rewritten against code that moved
under them — one docs commit landed eleven seconds after the commit that invalidated part of it.

- **security.md** described the note-renewal rule for the third time with a third answer, and the
  last one was wrong: direct mode does not renew its note. Its minute runs from the moment `logout()`
  was called, whether or not it names a session.
- **security.md** also said neither logout cookie carries a value. The note now carries one — the
  moment the logout was asked for, which the page finishing it cannot otherwise know.
- **transport-modes.md** said `lukk:signed-in-at` is "only read to decide whether a logout note that
  names no session is still current", contradicting authentication.md, which is the accurate one:
  every logout in both transports consults it. The rule generalised and this table was never carried
  along.
- **configuration.md** warned readers to weigh disabling rotation, reuse detection and the denylist
  thirteen lines after correctly saying 0.7.0 removed those keys as never-read.

New known limitation: a BFF sign-in that arrives with no session cookie has no old session key to
record as replaced, so a page load still in flight for the previous session can set the ten-second
signed-out marker on a browser that has since signed in. One page renders signed out; the cookie is
untouched and other tabs correct it. Fixing it would need a per-browser identifier outliving the
cookie, which the design deliberately does not keep.
… share one session

Two things the code does that the pages did not say.

The stand-down rule reads "after that logout was asked for" from the NOTE, not from the page load that
finishes it — so a sign-in already on the wire when that page loaded still counts as having happened
since. Only a note written by a release predating the value falls back to the finishing page's clock.

And a limitation worth stating plainly: both client-side keys are scoped per app (`app.baseURL`, plus
`session.name`), which in BFF mode is the whole story because each app holds its own sealed cookie. In
DIRECT mode it is not — lukk issues a single `__Host-refresh` cookie for the origin, so `/shop/` and
`/admin/` are one session on the server however their keys are named. Signing out of one signs out of
both, and a refresh in one rotates the token the other holds. Separate origins, or BFF.
Queued on the shared `pages` group, GitHub keeps only the newest pending
run and cancels the others — opening three docs PRs together left one with
no checks at all. Deploys still serialize.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant