Repository navigation
Sessions expire after 30 days unused, and stop storing IP address and user agent (#228) - #240
Merged
Merged
Conversation
…address and user agent (#228) Draft for Gate A: decisions 1-5 ruled by the maintainer, 6-11 recommended. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ns no entry (#228) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…dress and user agent (#228) Task 1: Migrations, schema, and the callers of the two columns Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Task 2: `Session`'s expiry rule Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… once a day (#228) Task 3: An expired session is no session; use is recorded once a day Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Task 4: `Session.sweep!`, the job, and the schedule Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Task 5: The tenancy area doc, the index, the verification Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… session (#228) The once-a-day stamp write in Authentication#record_use_of is bookkeeping, and spec 049 decision 2 says a missed write is harmless: the stamp then lags by under 24 hours more. A busy database (SQLite3::BusyException or ActiveRecord::StatementTimeout) must therefore never fail the request. The write now rescues both, logs one warning line and returns without re-issuing the cookie; the next request tries again. Ruling by the supervisor, from the implementation review's major risk. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… shows no collection signals (#228) The AC-3.5 example now also expects ActiveRecord::StatementTimeout to be retried (checked by removing it from retry_on: the example failed, and the line was restored). The AC-1.4 example asserts the collector's account menu ("Sign out") is absent for the expired session and present for a fresh sign-in in the same example (checked by disabling the expiry test: it fails). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…usy database (#228) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…a doc Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…c (spec 027 D4) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… 027) Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
# Conflicts: # docs/architecture/tenancy-and-accounts.md
# Conflicts: # db/schema.rb # docs/architecture/tenancy-and-accounts.md
plainprogrammer
marked this pull request as ready for review
November 9, 2026 17:41
This was referenced Nov 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #228. Refs #218 (rulings 1 and 2).
What changes
sessions.last_used_at) is 30 days old or more is no session: a collector's GET is redirected to sign-in with the page kept, a non-GET is redirected and changes nothing, an open catalog page is shown as to a visitor. The request writes nothing and the response removes the cookie. No absolute lifetime.Session::SweepJob(sweep_sessions, 4:10 am, development and production), batches of 1,000, one at a time (limits_concurrency), retriesSQLite3::BusyExceptionandActiveRecord::StatementTimeout. The database cascades each session's bulk selection and Undo.sessions.ip_addressanduser_agentare dropped, with their values. Three migrations (add the stamp, backfill it with the upgrade's time so nobody is signed out, drop the columns and make the stampNOT NULL), all without a transaction, because SQLite rebuildssessionsand the rebuild would otherwise cascade-delete bulk selections and Undo records. A migration spec proves a session, its selection, mark and Undo survive down and up.Ruling made during review
The daily stamp write on a GET could turn a request into a 500 if SQLite stays busy past its timeout.
Authentication#record_use_ofnow rescuesActiveRecord::StatementTimeoutandSQLite3::BusyException, logs one line and skips the stamp and the new cookie. It only skips the stamp: expiry is decided before it, so the sign-in decision is untouched. Two examples inspec/requests/session_expiry_spec.rb(red first, with the exception propagating).Verification
bin/ci) passed onee9ba43; the suite has 2,873 examples at the earlier head (bin/rspec --dry-run).docs/specs/049-session-idle-expiry/verification.md; its major finding is the ruling above, its test gaps are closed.sessionsstays "Left out");spec/backup_guards_spec.rbgreen.CI and what is left
ee9ba43: RSpec shards 1-4,checks,ciand both image jobs (amd64 and arm64, which run the upgrade smoke test and its backup leg for AC-4.5 and AC-4.7) all pass: https://github.com/plainprogrammer/Collector/actions/runs/42666064698distill-featureretiresplan.md.🤖 Generated with Claude Code