search: a file is found by what it says

The text of every file in the tree that is text, by its type or by its
first 8 KiB reading as UTF-8 without a NUL, now goes into `file_text` and a
second FTS5 index beside the documents', up to its first 256 KiB, the same
part the viewer shows. A search asks both, lists a node found in both once,
and marks a file found by its text with `in_text`; the list shows the words
around the match under its name.

There is one way in, `file_text::catch_up`, which reads every unsealed file
that has no row yet. An upload, an import, an SFTP save and a decrypt call
it once their own transaction is done, and the server runs it at start for
anything that slipped past. A file that is not text gets an empty row, so it
is read once and not again.

The triggers keep it honest the other way. New bytes drop the old text, so
an SFTP save is read again, and `:encrypt` writes a file under a new media
id, so its plaintext is gone in the same statement that seals it. The text
of a sealed file is refused outright, whatever path tries to store it;
otherwise it would sit in `diary.db` and its mirror beside the sealed bytes.

PDFs and office documents are not read: their text needs a parser this
binary does not carry.
This commit is contained in:
nvrl committed 2026-10-21 01:12:42 +02:00
1 parent 6673298cb2
commit 909abf5fcb
13 files changed
+476 -14

No files matched your search

+2
View File
@@ -36,6 +36,8 @@ export interface NodeSummary {
file: FileInfo | null
/** Search results only: where the match sits, `work/notes`. */
location?: string
/** Search results only: a file found by what it says; `excerpt` is the words around the match. */
in_text?: boolean
}
/** One step of a node's path, the space first and the node itself last. */