Replace the count of logouts with a random value (part of #256)

The session manager now keeps a random value from crypto/rand in the
logout table, made when the table has none and replaced by each logout.
A session carries the value current at its login and is refused when it
differs. A lost state directory now ends every login session, and no
logout can make an ended one work again, as a count starting from 0
could. README.md and the Manager doc comment say the check for a logout
compares no time, while a session's expiry still compares the clock.

Model: opus-5-5
This commit is contained in:
2026-10-15 18:15:46 +00:00
committed by clawbot
parent 066811580d
commit df3bff6c6b
5 changed files with 82 additions and 66 deletions
+17 -16
View File
@@ -42,6 +42,23 @@ P2: security: per-origin rate limiting
sizes. Storing a source over a file of another size replaces that file. A
source that fails to decode is not removed for that alone: a damaged upstream
image would then be fetched on every request.
- 2026-10-15 logging out ends every login session (closes #256): a login session
was a cookie with nothing kept on the server, so `/logout` removed it from one
browser and a copy of it kept working for its 30 days. Every login is made
with the one signing key, so logging out now ends them all: the session
manager keeps a random value, made with `crypto/rand` when the new `logout`
table has none and replaced by each logout, saves it there so that it outlasts
a restart, puts the value at login in each session, and refuses a session
carrying another value. The check for a logout compares no time, so a login
after a logout works whatever the host's clock does; a session's 30 days are
still checked against the clock. Losing the state directory ends every login
session, and no logout can make an ended one work again. Logging out is now
`POST /logout` from a form on the generator page, behind the CSRF check the
other forms have, so a link or image elsewhere on the same site cannot end the
sessions. A logout without a valid login session ends none and only removes
the cookie, as anyone can take a CSRF token from the login page. A logout that
cannot be saved answers 500. `session.NewManager`, which the tests use, keeps
the value in memory only; pixad uses `session.NewManagerWithDatabase`.
- 2026-10-15 a transcode stops once its request's `downstream_timeout` has
ended, unless it has begun encoding (closes #243): the image processor looked
at its context only while it waited for a processing slot, so an image was
@@ -76,22 +93,6 @@ P2: security: per-origin rate limiting
405, or a CORS preflight. The metrics library takes the label before the
request is routed, so the metrics middleware asks the router which route
matches.
- 2026-10-15 logging out ends every login session (closes #256): a login session
was a cookie with nothing kept on the server, so `/logout` removed it from one
browser and a copy of it kept working for its 30 days. Every login is made
with the one signing key, so logging out now ends them all: the session
manager counts logouts, saves the count in the new `logout` table so that it
outlasts a restart, puts the count at login in each session, and refuses a
session whose count is not the current one. No time is compared, so a login
after a logout works whatever the host's clock does. A restart without a
persistent volume for the state directory forgets the count. Logging out is
now `POST /logout` from a form on the generator page, behind the CSRF check
the other forms have, so a link or image elsewhere on the same site cannot end
the sessions. A logout without a valid login session ends none and only
removes the cookie, as anyone can take a CSRF token from the login page. A
logout that cannot be saved answers 500. `session.NewManager`, which the tests
use, keeps the count in memory only; pixad uses
`session.NewManagerWithDatabase`.
- 2026-10-15 expired negative cache rows are removed on a schedule (closes
#244): the row of a failed fetch, which makes pixa answer 502 for that source
URL for 5 minutes, was deleted only when the same URL was requested again