Saved searches: new-since-last-viewed badges

Each saved search carries a count of new documents matching its query since you last opened it — clearer than email digests, no inbox noise.

Updated 2026-05-26

When you save a search ("Save this search" on /search), Kodori starts watching that query for new matches. The next time you open /search, each saved-search chip carries a small numeric badge showing how many documents matching the saved query were uploaded since the last time you viewed it.

Clicking a chip does two things in one action: it navigates to the search results AND pushes the watermark forward to "now", so the badge clears. The next batch of matching uploads will repopulate it automatically.

The count comes from a permission-trimmed FTS query against your tenant — a viewer who can't see a document doesn't see it counted. There's no separate digest pipeline, no email opt-in, and no cron — the count is computed when you load /search, so a stale watermark never silently hides a real match.

**CSV export.** Each saved search on /search/alerts has an "Export matching docs to CSV ↓" link. Streams up to 1000 hits as RFC 4180 CSV with columns: documentId, displayName, mimeType, sensitivityLabel, sizeBytes, currentVersionHash, createdAt, lastModifiedAt. Permission-trimmed (you only see rows you can read). Postgres FTS only — semantic-only matches that don't hit the FTS query don't appear in the export. The saved search's sensitivity + mime-family filters carry through. `X-Kodori-Cap-Hit` response header reports whether the 1000-row cap was reached. Each export emits `saved-search-alert.fired` with `kind: 'csv-export'` on the audit chain so admins reviewing the log see who exported what when.

Sharing saved searches across the team is on the roadmap; today they're per-user.

**Email digest.** If you're already opted into the activity digest (set on /settings/profile to daily / weekly), saved-search hits surface as a "Saved searches with new hits" section in the same email — top 5 saved searches by hit count over the digest window, each with a deep link back to /search?savedSearch=<id> for one-click load. Reuses the existing Resend send + reply-to + unsubscribe plumbing — no separate email opt-in. The in-app /search badge remains the read-time complete view; the digest is a push-time summary signal for users who'd rather get nudged in their inbox.