Files
tutabridge/crates
Anthony 3d4ef0efad Full-text body search via an encrypted FTS5 index
BODY/TEXT searches previously matched only bodies that happened to be
decoded in memory, so results were inconsistent. Add a persistent FTS5
index (a virtual table inside the SQLCipher store, encrypted at rest) over
the plain-text body of every message we download.

- store.rs: mail_fts(element_id UNINDEXED, body) with unicode61 +
  remove_diacritics; index_body / unindex_body / search_body / fts_count.
  Terms become prefix tokens ANDed together (factur -> factur*), built by
  fts_match_expr which strips everything but alphanumerics so it is
  injection-safe.
- rfc2822.rs: strip_html (drops tags + script/style + entities) and
  extract_body_text (decodes the text part of our own .eml) feed the index.
- sync.rs: index inline at prefetch; one-time backfill at boot
  (body_fts_indexed_v1) for bodies cached before the index existed;
  unindex on delete.
- search.rs: BODY/TEXT resolve through the index — the session collects the
  distinct body terms, queries the index once each, and passes the hit sets
  to matches() via a SearchContext. A body term only matches messages whose
  body has actually been downloaded (full coverage needs sync_limit = 0).
- LocalStore threaded into ImapSession (Option; None in unit tests).

Validated live: backfilled 7,687 cached bodies, then BODY/TEXT/AND/OR/NOT
queries returned coherent subsets — NOT BODY x == total - (BODY x), an
exact complement. 233 unit tests, incl. real FTS5 MATCH against the bundled
SQLCipher (confirms FTS5 is compiled in for the cross-OS release).
2026-06-01 10:38:47 +02:00
..