Skip to content

v0.4.5

Choose a tag to compare

@justin-stanley justin-stanley released this 06 Oct 15:24
· 16 commits to main since this release
215b557

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: ok and served its pages, then 0.4.4 booted on the result, also with db: 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 warn line says so.
  • --revoke-all-sessions signs every user out. It is an operator tool for teardown, not routine maintenance. See deploy/teardown.md.

Security

  • Teardown revokes the rust backend's sessions (#264, closes #257).
    • The new command. featherreader --revoke-all-sessions signs every stored session out at its own PDS, using RFC 7009 revocation through the same path as /logout.
    • Order matters. deploy/teardown.sh runs 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.sh requires 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 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.

Docs

  • Every doc and number is up to date with the code (#256). Four audits checked every Markdown doc against the code, and a final sweep covered numbers and line references. The open risks the audits found are tracked as issues #258–#263.