fix(security): persistent search index forgets redacted and left-room text
Nothing ever removed an indexed row: redacted messages stayed searchable with full plaintext and rendered as normal results. Now: a client-level RoomEvent.Redaction listener deletes the row, leave/ban clears the room (clearRoom finally has a caller), m.replace edits upsert the original row instead of indexing the "* fallback" separately, and cached rows whose local event is redacted render through the existing redacted_because placeholder. Unit-tested. Fixes #14 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
@@ -288,6 +288,23 @@ export const mergeSearchResults = <
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete a single cached row, e.g. because its event was redacted. Gitea #14:
|
||||
* without this, a redaction only ever removed the in-memory hit — the
|
||||
* decrypted plaintext stayed in IndexedDB forever.
|
||||
*/
|
||||
export const deleteRow = async (roomId: string, eventId: string): Promise<void> => {
|
||||
const db = await openDb();
|
||||
if (!db) return;
|
||||
try {
|
||||
const tx = db.transaction(MESSAGES_STORE, 'readwrite');
|
||||
tx.objectStore(MESSAGES_STORE).delete([roomId, eventId]);
|
||||
await awaitTx(tx);
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
};
|
||||
|
||||
export const clearRoom = async (roomId: string): Promise<void> => {
|
||||
const db = await openDb();
|
||||
if (!db) return;
|
||||
|
||||
Reference in New Issue
Block a user