From 5e47ed5aaed7b1745c7ab3a5b57f473e487fce2e Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 29 Mar 2026 17:20:48 +0000 Subject: [PATCH] fix: reveal pairs oscillating between populated and empty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two bugs found: 1. Individual name parts ("Ademo"→"John", "Demo"→"Smith") were added as reveal pairs, causing partial replacements that corrupted the DOM. The smart engine sends combined forms ("Ademo Demo"→"John Smith") which the catch-all already handles. Removed individual name entries from buildRevealPairs — only emails, usernames, hostnames, phones are matched individually. 2. Cache invalidated on every ss:config-updated (including settings-only changes like reveal toggle). Now only invalidates when mappings or identity actually change. https://claude.ai/code/session_01KF4i7Ra7zCEDskxDBaNtcT --- manifest.firefox.json | 2 +- manifest.json | 2 +- package.json | 2 +- src/content/content.js | 27 ++++++++++++++++++--------- src/options/options.html | 2 +- 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/manifest.firefox.json b/manifest.firefox.json index d0a72a5..a27eaab 100644 --- a/manifest.firefox.json +++ b/manifest.firefox.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Silent Send", - "version": "0.9.13", + "version": "0.9.14", "description": "Intercepts personal info and substitutes it with user-defined replacements before sending to AI services.", "browser_specific_settings": { "gecko": { diff --git a/manifest.json b/manifest.json index d14c1c8..95acc09 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Silent Send", - "version": "0.9.13", + "version": "0.9.14", "description": "Intercepts personal info and substitutes it with user-defined replacements before sending to AI services.", "permissions": [ "storage", diff --git a/package.json b/package.json index c0bf710..8a74f3c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "silent-send", - "version": "0.9.13", + "version": "0.9.14", "private": true, "license": "MIT", "description": "Browser extension that substitutes personal data before sending to AI services", diff --git a/src/content/content.js b/src/content/content.js index ba3fab2..df55dbb 100644 --- a/src/content/content.js +++ b/src/content/content.js @@ -1404,13 +1404,17 @@ // session, preventing false positives (e.g. "user" in AI prose). function buildRevealPairs() { const pairs = []; + const added = new Set(); // Helper: only add if this substitute was actually sent function addIfUsed(from, to, caseSensitive) { if (!from || !to) return; - const entry = sessionSubstitutions.get(from.toLowerCase()); + const key = from.toLowerCase(); + if (added.has(key)) return; + const entry = sessionSubstitutions.get(key); if (entry) { pairs.push({ from, to, caseSensitive }); + added.add(key); } } @@ -1423,9 +1427,9 @@ for (const e of (identity.emails || [])) { addIfUsed(e.substitute, e.real); } - for (const n of (identity.names || [])) { - addIfUsed(n.substitute, n.real); - } + // For names: DON'T add individual first/last — the smart pattern engine + // combines them (e.g. "Ademo Demo" for "John Smith"). The catch-all + // below picks up the combined form from sessionSubstitutions. for (const u of (identity.usernames || [])) { addIfUsed(u.substitute, u.real); } @@ -1437,10 +1441,13 @@ } } - // Also add auto-detect and auto-redact substitutions from this session + // Catch-all: add any session substitution not already covered above. + // This picks up combined names ("Ademo Demo" → "John Smith"), + // auto-detected PII, and auto-redacted secrets. for (const [key, entry] of sessionSubstitutions) { - if (!pairs.some(p => p.from.toLowerCase() === key)) { + if (!added.has(key)) { pairs.push({ from: entry.replaced, to: entry.original }); + added.add(key); } } @@ -1448,11 +1455,13 @@ return pairs; } - // Cache — invalidate when config changes or new substitutions happen + // Cache — invalidate when identity/mappings change or new substitutions happen + // Settings-only updates (e.g. reveal toggle) do NOT invalidate let _revealPairsCache = null; - let _revealPairsCacheSize = 0; window.addEventListener('message', (event) => { - if (event.data?.type === 'ss:config-updated') _revealPairsCache = null; + if (event.data?.type === 'ss:config-updated') { + if (event.data.mappings || event.data.identity) _revealPairsCache = null; + } if (event.data?.type === 'ss:substitution-performed') _revealPairsCache = null; }); diff --git a/src/options/options.html b/src/options/options.html index cd0ed47..9bedb4e 100644 --- a/src/options/options.html +++ b/src/options/options.html @@ -629,7 +629,7 @@