Stamp the secret scanner so old sessions get checked (#335) - #339
Merged
mando merged 2 commits intoAug 18, 2026
Merged
Conversation
mando
marked this pull request as ready for review
August 17, 2026 19:48
Contributor
Author
|
Pushed follow-up commit
Verification: |
Inline scanning only covers sessions the incremental pipeline touched, so upgrading to a build with the scanner left a user's back catalogue silently unscanned, and a rules refresh changed nothing for sessions already indexed. Record which scanner version last looked at each session (resolved_sessions.secret_scan_version, schema v25; existing rows migrate to NULL) and drain the backlog after each index pass: sessions the current version hasn't stamped get their retained text read back, rescanned, and stamped. No model call, so no rate limiter, but the pass is bounded and yields so `argus run` stays responsive. Bumping SECRET_SCAN_VERSION is now step 5 of the gitleaks rules-refresh procedure. Sessions indexed with text retention off can't be reached from the store at all. `argus status` says how many, and that re-reading their transcripts is what fixes it, rather than leaving the gap silent.
mando
force-pushed
the
mando-issue-335-secret-scan-version
branch
from
August 18, 2026 20:50
2e29527 to
e4b7f14
Compare
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 #335. Stacked on #337 (which is stacked on #332) — rebase the base to
mainonce those land.The gap
Secret scanning (#327) runs inline at materialize, and the incremental pipeline only materializes touched sessions. Nothing about upgrading to a build that has the scanner marked old sessions as needing a look, so a user who upgraded got findings only for sessions that happened to change afterwards — their back catalogue silently never scanned. Same for a rule-set refresh: improving
secret-scan-rules.tschanged nothing for sessions already indexed. The only remedies were a fullargus index refresh(minutes on a large store, and you had to know to do it) or waiting for each session to change on its own.What this does
SECRET_SCAN_VERSION(src/indexing/secret-scan.ts) — the scanner's implementation version. Unlike the interpreter's version, this one is part of eligibility: a bump is precisely how a rules refresh reaches sessions already in the store.resolved_sessions.secret_scan_version, NULL for never scanned. Existing rows migrate to NULL, which is exactly the "upgraded, never scanned" state this issue is about. Materialize stamps it from the scan it just ran, and deliberately does not carry it forward when a materialize didn't scan: the wholesale replace cascades the findings away, so keeping the stamp would claim a scan with nothing to show. NULL hands the session back to the drain, which self-heals.SECRET_SCAN_ELIGIBLE_SQLinstore.ts, alongsideINTERPRETATION_ELIGIBLE_SQLand shared by the drain query and theargus statuscounts so "waiting" can't desync from the work. PlusreadPendingSecretScanSessions,writeSessionSecretFindings(always stamps, even for an empty finding set, so a clean session de-queues; leavessecret_scan_dismissedalone so the digest comparison still governs), andsecretScanProgress.src/indexing/secret-scan-drain.ts), run fromrunIndexright after the structural index and before the interpretation drain. Shaped like the interpretation drain minus what made that one expensive: no model call, so no rate limiter. 500 sessions per pass, yielding every 25 so a large backlog can't makeargus runstop responding, with the same self-recovering failure cooldown.secret-scan-rules.ts, with the note that a bump re-warns in bulk (dismissal is anchored to the finding-set digest), so it's only for changes that can actually change findings.The retainText constraint
Option 1 from the issue: sessions indexed with text retention off (#120) have no
resolved_interaction_textto read, so a stamp-driven rescan is structurally impossible for them (interpretation has the same limitation). Eligibility excludes them, andargus statusreports the state rather than leaving it silent:argus index refreshremains the explicit "rescan everything now" path, and the only one that covers those sessions. It is no longer the only way a rules improvement lands.Test plan
bun run typecheckcleanbun test— 800 pass / 0 failtest/secret-scan-drain.test.ts(10 tests): stamping at materialize, eligibility, newest-first ordering, a version bump re-queuing scanned sessions, the drain scanning from retained text and de-queuing, clean sessions still stamped, dismissal surviving an identical rescan and lapsing on a changed one, wholesale replace, and a re-materialize without a scan handing the session backtest/store.test.ts— v24 → v25 migration test: existing sessions migrate to "never scanned" and show up as pendingtest/cli.test.ts— pins the two newargus statuslinesstatusreported the checkNote for reviewers
The v25 migration means a store touched by this branch can't be read by an older build.
🤖 Generated with Claude Code
https://claude.ai/code/session_01TTu8aFTkXgk2SVjkAw8rWn