diff --git a/manifest.firefox.json b/manifest.firefox.json index 12ae541..525c703 100644 --- a/manifest.firefox.json +++ b/manifest.firefox.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Silent Send", - "version": "0.9.45", + "version": "0.9.46", "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 ace3c3e..0877f8e 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Silent Send", - "version": "0.9.45", + "version": "0.9.46", "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 38814b0..afb84ea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "silent-send", - "version": "0.9.45", + "version": "0.9.46", "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 0fae146..2626424 100644 --- a/src/content/content.js +++ b/src/content/content.js @@ -280,7 +280,7 @@ // 4. Auto-detect: scan the FINAL text for unconfigured PII // Auto-redact if enabled, otherwise just warn if (settings.autoDetect !== false) { - const warnings = autoDetectPII(finalText, identity, { detectProperNouns: settings.detectProperNouns === true }) + const warnings = autoDetectPII(finalText, identity, { detectProperNouns: settings.detectProperNouns === true, mappings }) .filter(w => !ignoredDetections.has(w.value)); if (warnings.length > 0) { // Auto-redact detected PII in the outbound text @@ -471,6 +471,14 @@ addAll(ident.names); addAll(ident.emails); addAll(ident.usernames); addAll(ident.hostnames); addAll(ident.phones); } + // Also skip values covered by mappings (both real and substitute) + if (opts?.mappings) { + for (const m of opts.mappings) { + if (!m.enabled) continue; + if (m.real) configured.add(m.real.toLowerCase()); + if (m.substitute) configured.add(m.substitute.toLowerCase()); + } + } const findings = []; for (const pat of PII_PATTERNS) { @@ -1412,7 +1420,19 @@ preSendWarningEl.classList.remove('visible'); } - // Add to mappings via background script (handles encryption) + // Optimistically add to local mappings so re-scan skips this value + const tempMapping = { + id: crypto.randomUUID(), + real, substitute: fake, + category: cat, + caseSensitive: false, + enabled: true, + createdAt: Date.now(), + }; + mappings = [...mappings, tempMapping]; + + // Persist via background script (handles encryption); + // update local mappings with the authoritative list on success addMappingViaBackground({ real, substitute: fake, category: cat }) .then(updatedMappings => { if (updatedMappings.length) mappings = updatedMappings; @@ -1509,7 +1529,7 @@ return; } - const warnings = autoDetectPII(text, identity, { detectProperNouns: settings.detectProperNouns === true }) + const warnings = autoDetectPII(text, identity, { detectProperNouns: settings.detectProperNouns === true, mappings }) .filter(w => !ignoredDetections.has(w.value)); if (warnings.length > 0) { showPreSendWarning(warnings, target);