Repository navigation
v0.4.5
FeatherReader 0.4.5 lets an operator teardown revoke the rust backend's sessions before anything is deleted (#257). Production runs that backend. Before this release, a teardown wiped those sessions' tokens without revoking them, so they stayed valid at each user's PDS until they expired. Fixing that exposed races in how a token refresh and a sign-out write the session row, and those are fixed here too.
Full engineering detail is in CHANGELOG.md.
Upgrade notes
- No schema change, no new settings. Upgrading from 0.4.4 is a deploy, and rolling back to 0.4.4 is a redeploy. Both were rehearsed on a fork of a production volume: 0.4.5 booted with
db: okand served its pages, then 0.4.4 booted on the result, also withdb: ok. - Session writes are now conditional. Login still writes unconditionally, and users see no difference.
- A token refresh updates the session row only if the row still holds the tokens the refresh started from. It never re-creates a row that a sign-out deleted.
- A sign-out deletes the row only if it hasn't changed since it was read.
- A refresh that loses such a race revokes the tokens it could not store. If that revocation fails, a
warnline says so.
--revoke-all-sessionssigns every user out. It is an operator tool for teardown, not routine maintenance. Seedeploy/teardown.md.
Security
- Teardown revokes the
rustbackend's sessions (#264, closes #257).- The new command.
featherreader --revoke-all-sessionssigns every stored session out at its own PDS, using RFC 7009 revocation through the same path as/logout. - Order matters.
deploy/teardown.shruns the sidecar revoke first, then a Rust revoke while the app is still serving, then stops the services, then runs a post-stop sweep, then wipes. The main pass has to run while the app is up: each PDS authenticates the revocation against the client metadata and JWKS the app serves, and caches them for only 10 minutes. - Pre-flight checks. Before anything is deleted, the command checks that it is the production client, that the encryption key decrypts the stored sessions, and that the signing key matches the JWKS the app serves. If any check fails it exits 2 and deletes nothing.
- Partial failure. It exits 3 and prints a summary line, which
teardown.shrequires before it will wipe. - Races closed. A refresh racing a sign-out can no longer resurrect a session or orphan a live token. A session whose issuer changes in the middle of a sign-out has its token revoked at its own issuer, never sent to another one.
- The new command.
- The work went through seven review rounds. It is covered by tests against a fake authorization server over TLS, a shell test of
teardown.sh(86 assertions), and 66 deliberate-break checks, all caught.