Passwords imported from password managers are now: - Displayed as dots (••••••••) by default in both options and popup - Separated into their own "Passwords" section in options page - Only revealable by entering the vault encryption password - Always masked in the popup mappings list (no reveal there) Options page: - New Passwords section with locked/unlocked states - Reveal button validates against vault encryption password - Hide button re-masks all password values - Password mappings excluded from the general Mappings table - Delete and enable/disable controls work while masked Popup: - Password-category mappings show dots for real value - Password category added to mapping add form dropdown Storage: - Added 'password' to default categories list https://claude.ai/code/session_01SWSwDfMVij53bCTNSCLMwn
215 lines
10 KiB
HTML
215 lines
10 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=400">
|
|
<link rel="stylesheet" href="popup.css">
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<!-- Header -->
|
|
<header class="header">
|
|
<div class="header-left">
|
|
<h1 class="title">Silent Send</h1>
|
|
<span class="status-dot" id="statusDot"></span>
|
|
</div>
|
|
<div class="header-right">
|
|
<button class="btn-icon" id="btnReveal" title="Reveal Mode - show real data">
|
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
|
|
<path d="M8 3C4.5 3 1.7 5.1 0.5 8c1.2 2.9 4 5 7.5 5s6.3-2.1 7.5-5c-1.2-2.9-4-5-7.5-5z" stroke="currentColor" stroke-width="1.5" fill="none"/>
|
|
<circle cx="8" cy="8" r="2.5" stroke="currentColor" stroke-width="1.5" fill="none"/>
|
|
</svg>
|
|
</button>
|
|
<label class="toggle" title="Enable/disable Silent Send">
|
|
<input type="checkbox" id="enableToggle" checked>
|
|
<span class="toggle-slider"></span>
|
|
</label>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Tab Bar -->
|
|
<nav class="tabs">
|
|
<button class="tab active" data-tab="identity">Identity</button>
|
|
<button class="tab" data-tab="mappings">Mappings</button>
|
|
<button class="tab" data-tab="activity">Activity</button>
|
|
<button class="tab" data-tab="test">Test</button>
|
|
</nav>
|
|
|
|
<!-- Locked State Overlay -->
|
|
<div id="lockedOverlay" style="display:none">
|
|
<div style="padding:24px 16px;text-align:center">
|
|
<div style="font-size:32px;margin-bottom:8px">🔒</div>
|
|
<h2 style="font-size:15px;margin:0 0 6px;color:#1f2937">Silent Send is Locked</h2>
|
|
<p style="font-size:12px;color:#6b7280;margin:0 0 16px">
|
|
Your data is encrypted. Enter your password to unlock.
|
|
<br>Substitutions are <strong>paused</strong> until unlocked.
|
|
</p>
|
|
<div style="display:flex;flex-direction:column;gap:8px;max-width:260px;margin:0 auto">
|
|
<input type="password" id="unlockPassword" placeholder="Encryption password" autocomplete="current-password"
|
|
style="width:100%;box-sizing:border-box;font-size:13px;padding:8px 10px;border:1px solid #d1d5db;border-radius:6px;text-align:center">
|
|
<input type="text" id="unlockTOTP" placeholder="TOTP code (if enabled)" autocomplete="one-time-code" inputmode="numeric" maxlength="6"
|
|
style="width:100%;box-sizing:border-box;font-size:13px;padding:8px 10px;border:1px solid #d1d5db;border-radius:6px;text-align:center;display:none">
|
|
<button class="btn btn-primary" id="btnUnlock" style="width:100%;padding:8px;font-size:13px">Unlock</button>
|
|
<button class="btn" id="btnUnlockBiometric" style="width:100%;padding:8px;font-size:13px;display:none">Unlock with Biometric</button>
|
|
<div id="unlockStatus" style="font-size:11px;min-height:16px;color:#dc2626"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- First-Run Setup Banner -->
|
|
<div class="first-run-banner" id="firstRunBanner" style="display:none">
|
|
<div class="first-run-icon">!</div>
|
|
<div class="first-run-text">
|
|
<strong>Setup required</strong> — Silent Send needs to know who you are before it can protect you.
|
|
Fill in at least your name below, then click Save Identity.
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Identity Tab (Smart Patterns) -->
|
|
<section class="tab-content active" id="tab-identity">
|
|
<!-- Profile selector -->
|
|
<div class="profile-bar">
|
|
<select id="profileSelect" class="select" style="flex:1"></select>
|
|
<button class="btn-icon" id="btnAddProfile" title="Add profile">+</button>
|
|
<button class="btn-icon" id="btnRenameProfile" title="Rename profile">✎</button>
|
|
<button class="btn-icon" id="btnDeleteProfile" title="Delete profile">×</button>
|
|
<label class="toggle" title="Enable/disable this profile" style="margin-left:4px">
|
|
<input type="checkbox" id="profileActive" checked>
|
|
<span class="toggle-slider"></span>
|
|
</label>
|
|
</div>
|
|
<p class="help-text">Each profile is a person/identity. All active profiles are protected simultaneously.</p>
|
|
|
|
<div class="id-section">
|
|
<div class="id-label-row"><span class="id-label">Names</span><button class="btn-add" data-field="names">+ Add</button></div>
|
|
<div id="idNames"></div>
|
|
<div class="id-hint">Catches: first last, last first, possessives, case variants</div>
|
|
</div>
|
|
|
|
<div class="id-section">
|
|
<div class="id-label-row"><span class="id-label">Emails</span><button class="btn-add" data-field="emails">+ Add</button></div>
|
|
<div id="idEmails"></div>
|
|
<div class="id-row">
|
|
<input type="email" id="idCatchAllEmail" placeholder="Catch-all email (for any unrecognized address)" class="input" style="flex:1">
|
|
</div>
|
|
<div class="id-hint">Catches: any *@gmail.com, *@yahoo.com, *@outlook.com, etc.</div>
|
|
</div>
|
|
|
|
<div class="id-section">
|
|
<div class="id-label-row"><span class="id-label">Usernames</span><button class="btn-add" data-field="usernames">+ Add</button></div>
|
|
<div id="idUsernames"></div>
|
|
<div class="id-hint">Catches: user@host, /home/user, ~user, C:\Users\user</div>
|
|
</div>
|
|
|
|
<div class="id-section">
|
|
<div class="id-label-row"><span class="id-label">Hostnames</span><button class="btn-add" data-field="hostnames">+ Add</button></div>
|
|
<div id="idHostnames"></div>
|
|
<div class="id-hint">Catches: hostname in user@hostname and standalone</div>
|
|
</div>
|
|
|
|
<div class="id-section">
|
|
<div class="id-label-row"><span class="id-label">Phones</span><button class="btn-add" data-field="phones">+ Add</button></div>
|
|
<div id="idPhones"></div>
|
|
<div class="id-hint">Catches: all formats — (555) 123-4567, 555-123-4567, 555.123.4567</div>
|
|
</div>
|
|
|
|
<button class="btn btn-primary" id="btnSaveIdentity" style="width:100%;margin-top:8px">Save Identity</button>
|
|
</section>
|
|
|
|
<!-- Mappings Tab -->
|
|
<section class="tab-content" id="tab-mappings">
|
|
<div class="add-mapping">
|
|
<div class="input-row">
|
|
<input type="text" id="inputReal" placeholder="Real value (e.g. John Smith)" class="input">
|
|
<span class="arrow">→</span>
|
|
<input type="text" id="inputSub" placeholder="Substitute (e.g. Alex Demo)" class="input">
|
|
</div>
|
|
<div class="input-row secondary">
|
|
<select id="inputCategory" class="select">
|
|
<option value="name">Name</option>
|
|
<option value="email">Email</option>
|
|
<option value="phone">Phone</option>
|
|
<option value="address">Address</option>
|
|
<option value="ssn">SSN</option>
|
|
<option value="dob">DOB</option>
|
|
<option value="domain">Domain</option>
|
|
<option value="password">Password</option>
|
|
<option value="general">General</option>
|
|
</select>
|
|
<label class="checkbox-label">
|
|
<input type="checkbox" id="inputCaseSensitive">
|
|
Case sensitive
|
|
</label>
|
|
<button class="btn btn-primary" id="btnAdd">Add</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mapping-list" id="mappingList">
|
|
<div class="empty-state">
|
|
No mappings yet. Add your first one above.
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Activity Tab -->
|
|
<section class="tab-content" id="tab-activity">
|
|
<div class="activity-header">
|
|
<span class="badge" id="sessionCount">0 substitutions this session</span>
|
|
<button class="btn-text" id="btnClearLog">Clear</button>
|
|
</div>
|
|
<div class="activity-list" id="activityList">
|
|
<div class="empty-state">No activity yet.</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Test Tab -->
|
|
<section class="tab-content" id="tab-test">
|
|
<div class="test-mode-toggle">
|
|
<button class="test-mode-btn active" data-mode="strip">Strip (real → fake)</button>
|
|
<button class="test-mode-btn" data-mode="reveal">Reveal (fake → real)</button>
|
|
</div>
|
|
|
|
<div id="stripMode">
|
|
<p class="help-text">Paste text with your real info. See what gets sent.</p>
|
|
<textarea id="testInput" class="textarea" placeholder="Try: My name is John Smith, email john@gmail.com, logged in as jsmith@macbook-pro" rows="4"></textarea>
|
|
<div class="diff-view" id="diffView">
|
|
<div class="diff-label">What gets sent:</div>
|
|
<div class="diff-output" id="diffOutput"></div>
|
|
</div>
|
|
<div class="diff-stats" id="diffStats"></div>
|
|
</div>
|
|
|
|
<div id="revealMode" style="display:none">
|
|
<p class="help-text">Paste text from AI responses (with fake data). Get back real data to copy.</p>
|
|
<textarea id="revealInput" class="textarea" placeholder="Paste AI output here, e.g.: Hello Alex Demo, I see your project at /home/ademo/..." rows="4"></textarea>
|
|
<div class="diff-view" id="revealView">
|
|
<div class="diff-label">Your real data:</div>
|
|
<div class="diff-output" id="revealOutput"></div>
|
|
</div>
|
|
<button class="btn btn-primary" id="btnCopyRevealed" style="width:100%;margin-top:8px">Copy to Clipboard</button>
|
|
<div class="diff-stats" id="revealStats"></div>
|
|
</div>
|
|
|
|
<div class="test-identity-status" id="identityStatus"></div>
|
|
</section>
|
|
|
|
<!-- Footer -->
|
|
<footer class="footer">
|
|
<div class="privacy-note">
|
|
Your data never leaves your browser. No servers, no tracking, no analytics.
|
|
<span id="privacyEncNote">When sync encryption is enabled, identity data is
|
|
AES-256 encrypted at rest — unreadable without your password.</span>
|
|
</div>
|
|
<div class="privacy-note" style="color:#b45309;background:#fef3c7;padding:6px 8px;border-radius:4px;margin-bottom:6px">
|
|
Silent Send is a convenience tool, not a security guarantee. It can miss
|
|
PPI in images, file uploads, unusual name forms, or data you forgot to
|
|
configure. Always verify sensitive messages before sending.
|
|
</div>
|
|
<a href="#" id="btnOptions">Options</a>
|
|
</footer>
|
|
</div>
|
|
|
|
<script src="popup.js" type="module"></script>
|
|
</body>
|
|
</html>
|