Files
silent-send/src/options/options.html
T
Claude 557b1ffd0c fix: Firefox broken — CSP blocks inline early hook script — v2.0.11
The inline <script> with textContent was blocked by claude.ai's
Content Security Policy on Firefox (Chrome is more permissive).
No fetch interception = no substitution = completely broken on FF.

Fixed by moving the early fetch hook to its own file (early-hook.js)
loaded via <script src="..."> which is CSP-compliant. Added to
web_accessible_resources in both Chrome and Firefox manifests.

Also fixed duplicate 'const api' declaration in injector.js that
would have crashed the content script.

https://claude.ai/code/session_01SWSwDfMVij53bCTNSCLMwn
2026-03-27 15:04:13 +00:00

601 lines
32 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Silent Send - Options</title>
<link rel="stylesheet" href="options.css">
</head>
<body>
<div class="container">
<header>
<h1>Silent Send Options</h1>
<p class="subtitle">Manage your privacy substitution mappings</p>
</header>
<section class="section">
<h2>Keyboard Shortcuts</h2>
<div class="setting-row">
<div>
<label>Toggle Reveal Mode</label>
<p class="setting-desc">Show your real data in AI responses</p>
</div>
<code style="font-size:12px;background:#f3f4f6;padding:4px 8px;border-radius:4px">Alt+Shift+R</code>
</div>
<div class="setting-row">
<div>
<label>Toggle Silent Send on/off</label>
<p class="setting-desc">Quickly enable or disable all substitution</p>
</div>
<code style="font-size:12px;background:#f3f4f6;padding:4px 8px;border-radius:4px">Alt+Shift+S</code>
</div>
<p class="section-desc" style="margin-top:8px;margin-bottom:0">
To change these shortcuts:<br>
<strong>Chrome:</strong> <code>chrome://extensions/shortcuts</code><br>
<strong>Firefox:</strong> <code>about:addons</code> → gear icon → Manage Extension Shortcuts
</p>
</section>
<section class="section">
<h2>Settings</h2>
<div class="setting-row">
<div>
<label>Show inline highlights</label>
<p class="setting-desc">Show a subtle underline on text that will be substituted</p>
</div>
<label class="toggle">
<input type="checkbox" id="showHighlights">
<span class="toggle-slider"></span>
</label>
</div>
<div class="setting-row">
<div>
<label>Secret scanning</label>
<p class="setting-desc">Auto-detect and redact API keys, tokens, passwords, SSNs, credit card numbers</p>
</div>
<label class="toggle">
<input type="checkbox" id="secretScanning" checked>
<span class="toggle-slider"></span>
</label>
</div>
<div class="setting-row">
<div>
<label>Auto-detect unconfigured PPI</label>
<p class="setting-desc">Warn when potential personal data (IPs, addresses, paths) is detected that you haven't configured</p>
</div>
<label class="toggle">
<input type="checkbox" id="autoDetect" checked>
<span class="toggle-slider"></span>
</label>
</div>
<div class="setting-row">
<div>
<label>Auto-redact detected PPI on send</label>
<p class="setting-desc">Automatically replace detected PPI with generic placeholders (192.0.2.1, 123 Example Street, etc.) when sending</p>
</div>
<label class="toggle">
<input type="checkbox" id="autoRedactDetected" checked>
<span class="toggle-slider"></span>
</label>
</div>
<div class="setting-row">
<div>
<label>Offer to auto-add detected PPI</label>
<p class="setting-desc">Show a + button on detected PPI to instantly create a mapping with a suggested fake value</p>
</div>
<label class="toggle">
<input type="checkbox" id="autoAddDetected" checked>
<span class="toggle-slider"></span>
</label>
</div>
<div class="setting-row">
<div>
<label>Max log entries</label>
<p class="setting-desc">Number of activity log entries to keep</p>
</div>
<input type="number" id="maxLogEntries" class="input-small" min="10" max="1000" value="200">
</div>
</section>
<section class="section">
<h2>Sync Between Browsers</h2>
<p class="section-desc">Keep your identities, mappings, and settings in sync across browsers.</p>
<!-- Sync Encryption -->
<div style="margin-bottom:20px;padding:12px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px">
<h3 style="font-size:13px;font-weight:600;margin:0 0 8px;display:flex;align-items:center;gap:6px">
<span>&#128274;</span> Sync Encryption
</h3>
<p class="section-desc" style="margin-bottom:10px">
Encrypt your sync data with a password, TOTP, or both. Authentication is only required when new data arrives and your cached key has expired.
</p>
<div id="syncEncryptionSetup">
<!-- Shown when encryption is NOT set up -->
<div id="encryptionNotConfigured">
<div style="display:flex;flex-direction:column;gap:8px">
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:end">
<div style="flex:1;min-width:160px">
<label style="font-size:11px;color:#6b7280;display:block;margin-bottom:2px">Password</label>
<input type="password" id="syncEncPassword" placeholder="Encryption password" autocomplete="new-password"
style="width:100%;box-sizing:border-box;font-size:12px;padding:5px 8px;border:1px solid #d1d5db;border-radius:6px">
</div>
<div style="flex:1;min-width:160px">
<label style="font-size:11px;color:#6b7280;display:block;margin-bottom:2px">Confirm Password</label>
<input type="password" id="syncEncPasswordConfirm" placeholder="Confirm password" autocomplete="new-password"
style="width:100%;box-sizing:border-box;font-size:12px;padding:5px 8px;border:1px solid #d1d5db;border-radius:6px">
</div>
</div>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center">
<label style="font-size:12px;display:flex;align-items:center;gap:4px;cursor:pointer">
<input type="checkbox" id="syncEncTOTP"> Enable TOTP (authenticator app)
</label>
<label style="font-size:12px;display:flex;align-items:center;gap:4px;cursor:pointer" id="syncEncWebAuthnLabel">
<input type="checkbox" id="syncEncWebAuthn"> Biometric/PIN re-auth
</label>
<div style="display:flex;align-items:center;gap:4px">
<label style="font-size:12px;white-space:nowrap">Re-auth every</label>
<select id="syncEncTTL" style="font-size:12px;padding:3px 6px;border:1px solid #d1d5db;border-radius:4px">
<option value="0">Each session</option>
<option value="30">30 days</option>
<option value="90" selected>90 days</option>
<option value="180">180 days</option>
<option value="365">1 year</option>
<option value="-1">Never</option>
</select>
</div>
</div>
<div>
<button class="btn btn-primary" id="btnSetupEncryption">Enable Encryption</button>
</div>
</div>
</div>
<!-- Shown when encryption IS set up -->
<div id="encryptionConfigured" style="display:none">
<div style="display:flex;align-items:center;gap:8px;flex-wrap:wrap">
<span style="font-size:12px;color:#10b981;font-weight:500">&#10003; Encryption active</span>
<span id="encryptionInfo" style="font-size:11px;color:#6b7280"></span>
<button class="btn btn-sm" id="btnChangeEncPassword">Change Password</button>
<button class="btn btn-sm btn-danger" id="btnDisableEncryption">Disable</button>
</div>
</div>
<!-- Auth prompt — first-device setup (password + optional TOTP) -->
<div id="syncAuthPrompt" style="display:none;margin-top:10px;padding:10px;background:#fffbeb;border:1px solid #fcd34d;border-radius:6px">
<p style="font-size:12px;font-weight:500;margin:0 0 8px;color:#92400e">Authentication required</p>
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:end">
<input type="password" id="syncAuthPassword" placeholder="Password" autocomplete="current-password"
style="flex:1;min-width:120px;font-size:12px;padding:5px 8px;border:1px solid #d1d5db;border-radius:6px">
<input type="text" id="syncAuthTOTPForPassword" placeholder="TOTP code" autocomplete="one-time-code" inputmode="numeric" maxlength="6"
style="width:80px;font-size:12px;padding:5px 8px;border:1px solid #d1d5db;border-radius:6px;display:none">
<button class="btn btn-primary btn-sm" id="btnSyncAuth">Unlock</button>
</div>
<!-- Re-verify alternatives (shown when key exists but TTL expired) -->
<div id="reverifyOptions" style="display:none;margin-top:8px;padding-top:8px;border-top:1px solid #fde68a">
<p style="font-size:11px;color:#92400e;margin:0 0 6px">Or re-verify with any one of these:</p>
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:end">
<button class="btn btn-sm" id="btnSyncAuthBiometric" style="display:none">Biometric / PIN</button>
<div id="totpReverifyGroup" style="display:none;display:flex;gap:4px;align-items:end">
<input type="text" id="syncAuthTOTP" placeholder="TOTP code" autocomplete="one-time-code" inputmode="numeric" maxlength="6"
style="width:80px;font-size:12px;padding:5px 8px;border:1px solid #d1d5db;border-radius:6px">
<button class="btn btn-sm" id="btnSyncAuthTOTP">Verify</button>
</div>
</div>
</div>
<div id="syncAuthStatus" style="font-size:11px;margin-top:4px;min-height:14px"></div>
</div>
<!-- TOTP setup result -->
<div id="totpSetupResult" style="display:none;margin-top:10px;padding:10px;background:#f0fdf4;border:1px solid #86efac;border-radius:6px">
<p style="font-size:12px;font-weight:500;margin:0 0 6px;color:#166534">TOTP Secret — save this in your authenticator app:</p>
<code id="totpSecretDisplay" style="font-size:13px;font-weight:600;letter-spacing:2px;display:block;margin-bottom:6px;word-break:break-all"></code>
<p style="font-size:11px;color:#6b7280;margin:0">Or use the otpauth URI: <code id="totpURIDisplay" style="font-size:10px;word-break:break-all"></code></p>
<button class="btn btn-sm" id="btnDismissTOTP" style="margin-top:8px">Done — I've saved it</button>
</div>
</div>
<div id="syncEncStatus" style="font-size:12px;margin-top:6px;min-height:14px"></div>
</div>
<div class="setting-row">
<div>
<label>Browser account sync</label>
<p class="setting-desc">Automatically sync via your browser account (Firefox Sync / Chrome account). Works across devices using the same browser.</p>
</div>
<label class="toggle">
<input type="checkbox" id="browserSync">
<span class="toggle-slider"></span>
</label>
</div>
<div style="margin-top:16px">
<h3 style="font-size:13px;font-weight:600;margin:0 0 4px">Sync Code — cross-browser copy-paste</h3>
<p class="section-desc" style="margin-bottom:8px">Generate a code in one browser, paste it in another. Newest data wins automatically.</p>
<div class="bulk-actions">
<button class="btn btn-primary" id="btnGenerateSyncCode">Generate Sync Code</button>
<button class="btn" id="btnImportSyncCode">Import from Code</button>
</div>
<div id="syncCodeDisplay" style="display:none;margin-top:10px">
<textarea id="syncCodeText" rows="3" style="width:100%;box-sizing:border-box;font-family:monospace;font-size:11px;resize:vertical;padding:6px;border:1px solid #d1d5db;border-radius:6px" readonly></textarea>
<div style="display:flex;align-items:center;gap:8px;margin-top:6px">
<button class="btn btn-primary" id="btnCopySyncCode">Copy to Clipboard</button>
<span id="syncCodeTime" style="font-size:11px;color:#6b7280"></span>
</div>
</div>
<div id="syncImportSection" style="display:none;margin-top:10px">
<textarea id="syncImportText" rows="3" placeholder="Paste sync code here…" style="width:100%;box-sizing:border-box;font-family:monospace;font-size:11px;resize:vertical;padding:6px;border:1px solid #d1d5db;border-radius:6px"></textarea>
<div style="display:flex;align-items:center;gap:8px;margin-top:6px;flex-wrap:wrap">
<button class="btn btn-primary" id="btnApplySyncCode">Apply</button>
<button class="btn" id="btnCancelSyncImport">Cancel</button>
<label style="font-size:12px;display:flex;align-items:center;gap:4px;cursor:pointer">
<input type="checkbox" id="syncForce"> Force (override if local is newer)
</label>
</div>
</div>
<div id="syncStatus" style="margin-top:8px;font-size:12px;min-height:16px"></div>
</div>
<div id="fileSyncSection" style="margin-top:20px;padding-top:16px;border-top:1px solid #e5e7eb">
<h3 style="font-size:13px;font-weight:600;margin:0 0 4px">Auto-Sync Folder — fully automatic, no copy-paste</h3>
<p class="section-desc" style="margin-bottom:8px">
Pick the same folder in each browser once. Changes are written to
<code>silent-send-sync.json</code> automatically whenever settings change,
and read back whenever this page is opened or regains focus.
Works with <strong>any cloud storage that has a desktop sync client</strong>
Dropbox, OneDrive, Google Drive, iCloud Drive, Box, pCloud, Nextcloud,
Synology Drive, or any network share. Just pick the cloud-synced folder.
</p>
<div class="bulk-actions" style="align-items:center">
<button class="btn btn-primary" id="btnPickSyncFolder">Choose Sync Folder</button>
<span id="syncFolderName" style="font-size:12px;color:#6b7280;font-family:monospace"></span>
<button class="btn btn-danger btn-sm" id="btnClearSyncFolder" style="display:none">Clear</button>
</div>
<div id="fileSyncStatus" style="margin-top:6px;font-size:12px;min-height:16px"></div>
</div>
<div style="margin-top:20px;padding-top:16px;border-top:1px solid #e5e7eb">
<h3 style="font-size:13px;font-weight:600;margin:0 0 4px">GitHub Gist Sync — no desktop client needed</h3>
<p class="section-desc" style="margin-bottom:8px">
Store settings in a private GitHub Gist. Works across any browser or device
with just a GitHub account. Create a
<a href="https://github.com/settings/tokens/new?scopes=gist&description=SilentSend" target="_blank" rel="noopener">
Personal Access Token
</a>
with the <code>gist</code> scope, paste it below, and click Push.
The Gist ID is remembered — future pushes update the same Gist.
</p>
<div style="display:flex;gap:8px;margin-bottom:6px;flex-wrap:wrap">
<input type="password" id="gistToken" placeholder="GitHub PAT (ghp_…)" autocomplete="off"
style="flex:1;min-width:180px;font-family:monospace;font-size:12px;padding:5px 8px;border:1px solid #d1d5db;border-radius:6px">
<button class="btn btn-primary" id="btnGistPush">Push</button>
<button class="btn" id="btnGistPull">Pull</button>
</div>
<div id="gistSyncStatus" style="font-size:12px;min-height:16px"></div>
</div>
<!-- Auto Sync -->
<div style="margin-top:20px;padding-top:16px;border-top:1px solid #e5e7eb">
<h3 style="font-size:13px;font-weight:600;margin:0 0 4px">Auto Sync — works in all browsers</h3>
<p class="section-desc" style="margin-bottom:8px">
Automatically push and pull settings in the background on a schedule.
Uses GitHub Gist or Custom URL — configure one of those above first, then enable auto sync here.
Changes you make locally are pushed immediately; remote changes are pulled on the interval.
</p>
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:center;margin-bottom:8px">
<label class="toggle" title="Enable auto sync">
<input type="checkbox" id="autoSyncEnabled">
<span class="toggle-slider"></span>
</label>
<select id="autoSyncMethod" style="font-size:12px;padding:3px 6px;border:1px solid #d1d5db;border-radius:4px">
<option value="gist">GitHub Gist</option>
<option value="url">Custom URL</option>
</select>
<div style="display:flex;align-items:center;gap:4px">
<label style="font-size:12px;white-space:nowrap">Every</label>
<select id="autoSyncInterval" style="font-size:12px;padding:3px 6px;border:1px solid #d1d5db;border-radius:4px">
<option value="5">5 min</option>
<option value="15" selected>15 min</option>
<option value="30">30 min</option>
<option value="60">1 hour</option>
</select>
</div>
</div>
<div id="autoSyncStatus" style="font-size:12px;min-height:16px"></div>
</div>
<div style="margin-top:20px;padding-top:16px;border-top:1px solid #e5e7eb">
<h3 style="font-size:13px;font-weight:600;margin:0 0 4px">Custom URL Sync</h3>
<p class="section-desc" style="margin-bottom:8px">
Any URL that supports HTTP GET (read) and PUT (write). Works with
Nextcloud/ownCloud WebDAV, a self-hosted server, or a cloud function.
Add custom headers (e.g. Authorization) as JSON if needed.
</p>
<div style="display:flex;gap:8px;margin-bottom:6px;flex-wrap:wrap">
<input type="url" id="customSyncUrl" placeholder="https://…/silent-send-sync.json"
style="flex:2;min-width:200px;font-size:12px;padding:5px 8px;border:1px solid #d1d5db;border-radius:6px">
<input type="text" id="customSyncHeaders" placeholder='{"Authorization":"Bearer …"}' autocomplete="off"
style="flex:1;min-width:160px;font-family:monospace;font-size:11px;padding:5px 8px;border:1px solid #d1d5db;border-radius:6px">
</div>
<div class="bulk-actions">
<button class="btn btn-primary" id="btnUrlPush">Push</button>
<button class="btn" id="btnUrlPull">Pull</button>
</div>
<div id="urlSyncStatus" style="margin-top:6px;font-size:12px;min-height:16px"></div>
</div>
</section>
<!-- Sync Conflicts -->
<section class="section" id="conflictSection" style="display:none">
<h2 style="color:#b45309">Sync Conflicts</h2>
<p class="section-desc">Both this device and another device changed the same data. Choose which version to keep for each conflict.</p>
<div id="conflictList"></div>
</section>
<!-- Connected Devices -->
<section class="section">
<h2>Connected Devices</h2>
<p class="section-desc">Devices that sync with this extension. The device list is shared via sync data.</p>
<div style="display:flex;gap:8px;align-items:center;margin-bottom:10px">
<label style="font-size:12px;white-space:nowrap">This device:</label>
<input type="text" id="deviceName" placeholder="Device name" style="flex:1;font-size:12px;padding:5px 8px;border:1px solid #d1d5db;border-radius:6px">
<button class="btn btn-sm" id="btnRenameDevice">Rename</button>
</div>
<div id="deviceList" style="font-size:13px"></div>
</section>
<!-- Version History -->
<section class="section">
<h2>Version History</h2>
<p class="section-desc">Snapshots of your data are saved automatically on each sync. Restore a previous version if a sync overwrote something important.</p>
<div style="display:flex;gap:8px;align-items:center;margin-bottom:10px">
<label style="font-size:12px;white-space:nowrap">Max snapshots</label>
<input type="number" id="maxVersionHistory" class="input-small" min="3" max="50" value="10">
<button class="btn btn-sm btn-danger" id="btnClearVersionHistory">Clear History</button>
</div>
<div id="versionHistoryList" style="font-size:13px"></div>
</section>
<!-- Organization -->
<section class="section">
<h2>Organization</h2>
<p class="section-desc">Join an organization to receive required substitution rules and secret scanner patterns from your admin. Org rules merge with your personal rules and cannot be disabled.</p>
<div id="orgNotJoined">
<div style="display:flex;gap:8px;flex-wrap:wrap;margin-bottom:8px">
<input type="text" id="orgInviteCode" placeholder="Invite code" style="flex:1;min-width:140px;font-size:12px;padding:5px 8px;border:1px solid #d1d5db;border-radius:6px;font-family:monospace">
<button class="btn btn-primary" id="btnJoinOrgCode">Join</button>
</div>
<div style="display:flex;gap:8px;flex-wrap:wrap;margin-bottom:8px">
<input type="url" id="orgPolicyUrl" placeholder="Policy URL (https://…/policy.json)" style="flex:1;min-width:200px;font-size:12px;padding:5px 8px;border:1px solid #d1d5db;border-radius:6px">
<button class="btn" id="btnJoinOrgUrl">Join by URL</button>
</div>
</div>
<div id="orgJoined" style="display:none">
<div style="padding:10px;background:#f0fdf4;border:1px solid #86efac;border-radius:6px;margin-bottom:8px">
<div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px">
<div>
<strong id="orgNameDisplay" style="font-size:13px"></strong>
<span id="orgPolicyVersion" style="font-size:11px;color:#6b7280;margin-left:6px"></span>
</div>
<button class="btn btn-sm btn-danger" id="btnLeaveOrg">Leave</button>
</div>
<div id="orgComplianceStatus" style="font-size:12px;margin-top:6px"></div>
<div id="orgRequiredMappings" style="font-size:11px;color:#6b7280;margin-top:4px"></div>
</div>
</div>
<div id="orgStatus" style="font-size:12px;min-height:16px"></div>
</section>
<section class="section">
<h2>Transfer Data</h2>
<p class="section-desc">Export all your identities, mappings, and settings to a file. Encrypted exports require a password to decrypt.</p>
<div class="bulk-actions">
<button class="btn" id="btnExportAll">Export All (plain)</button>
<button class="btn" id="btnExportEncrypted">Export Encrypted</button>
<button class="btn" id="btnImportAll">Import from File</button>
<input type="file" id="fileImportAll" accept=".json,.ssbackup" hidden>
</div>
<div style="margin-top:20px;padding-top:16px;border-top:1px solid #e5e7eb">
<h3 style="font-size:13px;font-weight:600;margin:0 0 4px">Bulk Import — populate from existing data</h3>
<p class="section-desc" style="margin-bottom:8px">
Import real values from a CSV, password manager export, or browser autofill export.
Passwords are <strong>never</strong> imported — only usernames, emails, names, and domains.
Imported values appear with blank substitutes so you can fill in fakes.
</p>
<div style="display:flex;gap:8px;margin-bottom:6px;flex-wrap:wrap;align-items:center">
<button class="btn btn-primary" id="btnBulkImport">Import CSV / Password Export</button>
<input type="file" id="fileBulkImport" accept=".csv,.tsv,.txt" hidden>
<span style="font-size:11px;color:#6b7280">Chrome passwords, Firefox logins, Bitwarden, 1Password, autofill, or plain CSV</span>
</div>
<div id="bulkImportPreview" style="display:none;margin-top:10px;padding:10px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:6px">
<h4 style="font-size:12px;font-weight:600;margin:0 0 8px">Import Preview</h4>
<div id="bulkImportSummary" style="font-size:12px;margin-bottom:8px"></div>
<div id="bulkImportItems" style="max-height:200px;overflow-y:auto;font-size:11px;margin-bottom:8px"></div>
<div style="display:flex;gap:8px">
<button class="btn btn-primary btn-sm" id="btnApplyBulkImport">Apply Import</button>
<button class="btn btn-sm" id="btnCancelBulkImport">Cancel</button>
</div>
</div>
<div id="bulkImportStatus" style="font-size:12px;margin-top:6px;min-height:16px"></div>
</div>
</section>
<section class="section">
<h2>Mappings</h2>
<p class="section-desc">Manage all your substitution rules. Longer matches take priority.</p>
<div class="bulk-actions">
<button class="btn" id="btnExport">Export Mappings</button>
<button class="btn" id="btnImport">Import Mappings</button>
<input type="file" id="fileImport" accept=".json" hidden>
<button class="btn btn-danger" id="btnClearAll">Clear All</button>
</div>
<table class="mapping-table">
<thead>
<tr>
<th>Real Value</th>
<th>Substitute</th>
<th>Category</th>
<th>Case</th>
<th>Enabled</th>
<th></th>
</tr>
</thead>
<tbody id="mappingTableBody">
</tbody>
</table>
<div class="add-row">
<input type="text" id="newReal" placeholder="Real value" class="input">
<input type="text" id="newSub" placeholder="Substitute" class="input">
<select id="newCategory" 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="newCaseSensitive">
Aa
</label>
<button class="btn btn-primary" id="btnAddMapping">Add</button>
</div>
</section>
<section class="section">
<h2>Passwords</h2>
<p class="section-desc">
Imported passwords are automatically redacted when sent to AI services.
Password values are hidden by default — enter your vault password to reveal them.
</p>
<div id="passwordsLocked" style="margin-bottom:12px">
<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap">
<span style="font-size:12px;color:#6b7280">&#128274; Password values are hidden</span>
<input type="password" id="passwordRevealKey" placeholder="Vault password to reveal" autocomplete="current-password"
style="font-size:12px;padding:5px 8px;border:1px solid #d1d5db;border-radius:6px;width:180px">
<button class="btn btn-sm" id="btnRevealPasswords">Reveal</button>
</div>
<div id="passwordRevealStatus" style="font-size:11px;margin-top:4px;min-height:14px"></div>
</div>
<div id="passwordsUnlocked" style="display:none;margin-bottom:12px">
<div style="display:flex;gap:8px;align-items:center">
<span style="font-size:12px;color:#b45309">&#128275; Passwords visible</span>
<button class="btn btn-sm" id="btnHidePasswords">Hide</button>
</div>
</div>
<table class="mapping-table">
<thead>
<tr>
<th>Password</th>
<th>Redacted As</th>
<th>Enabled</th>
<th></th>
</tr>
</thead>
<tbody id="passwordTableBody">
</tbody>
</table>
<div id="noPasswordsMsg" style="text-align:center;color:#9ca3af;padding:16px;font-size:13px;display:none">
No passwords imported. Use Transfer Data → Import to add passwords from your password manager.
</div>
</section>
<section class="section">
<h2>Custom Domains</h2>
<p class="section-desc">Add domains for self-hosted AI services (like OpenWebUI). The extension will activate on these domains in addition to the built-in ones.</p>
<div class="domain-list" id="domainList"></div>
<div class="add-row">
<input type="text" id="newDomain" placeholder="https://ai.myserver.com" class="input" style="flex:2">
<button class="btn btn-primary" id="btnAddDomain">Add Domain</button>
</div>
<p class="section-desc" style="margin-top:8px;margin-bottom:0">
When you click "Add Domain", your browser will ask you to confirm access. No extra steps needed.
</p>
</section>
<section class="section">
<h2>Activity Log</h2>
<div class="log-actions">
<span id="logCount">0 entries</span>
<button class="btn btn-danger" id="btnClearLog">Clear Log</button>
</div>
<div class="log-list" id="logList"></div>
</section>
<section class="section">
<h2>Danger Zone</h2>
<!-- Tamper Protection -->
<div style="margin-bottom:16px;padding:12px;background:#fef2f2;border:1px solid #fecaca;border-radius:8px">
<h3 style="font-size:13px;font-weight:600;margin:0 0 6px">Tamper Protection</h3>
<p class="section-desc" style="margin-bottom:8px">
Require a separate admin password to disable the extension, clear data, or change org settings.
This is a deterrent — it cannot prevent browser-level uninstall or dev tools access.
</p>
<div id="tamperNotEnabled">
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:end">
<input type="password" id="tamperAdminPassword" placeholder="Admin password" autocomplete="new-password"
style="flex:1;min-width:120px;font-size:12px;padding:5px 8px;border:1px solid #d1d5db;border-radius:6px">
<input type="password" id="tamperAdminPasswordConfirm" placeholder="Confirm" autocomplete="new-password"
style="flex:1;min-width:120px;font-size:12px;padding:5px 8px;border:1px solid #d1d5db;border-radius:6px">
<button class="btn btn-primary btn-sm" id="btnEnableTamper">Enable</button>
</div>
</div>
<div id="tamperEnabled" style="display:none">
<div style="display:flex;align-items:center;gap:8px;flex-wrap:wrap">
<span style="font-size:12px;color:#dc2626;font-weight:500">&#128274; Active</span>
<button class="btn btn-sm" id="btnChangeTamperPassword">Change Password</button>
<button class="btn btn-sm btn-danger" id="btnDisableTamper">Disable</button>
</div>
</div>
<div id="tamperStatus" style="font-size:12px;margin-top:4px;min-height:14px"></div>
</div>
<!-- Admin auth dialog (reusable prompt for protected actions) -->
<dialog id="adminAuthDialog" style="border:1px solid #d1d5db;border-radius:8px;padding:20px;max-width:300px">
<h3 style="margin:0 0 8px;font-size:14px">Admin Password Required</h3>
<p id="adminAuthReason" style="font-size:12px;color:#6b7280;margin:0 0 12px"></p>
<input type="password" id="adminAuthInput" placeholder="Admin password" autocomplete="current-password"
style="width:100%;box-sizing:border-box;font-size:13px;padding:8px;border:1px solid #d1d5db;border-radius:6px;margin-bottom:8px">
<div style="display:flex;gap:8px;justify-content:flex-end">
<button class="btn btn-sm" id="btnAdminAuthCancel">Cancel</button>
<button class="btn btn-primary btn-sm" id="btnAdminAuthSubmit">Confirm</button>
</div>
<div id="adminAuthStatus" style="font-size:11px;margin-top:4px;min-height:14px;color:#dc2626"></div>
</dialog>
<div class="setting-row">
<div>
<label>Reset all data</label>
<p class="setting-desc">Clears all identities, mappings, settings, and logs. Cannot be undone.</p>
</div>
<button class="btn btn-danger" id="btnResetAll">Reset Everything</button>
</div>
</section>
<footer>
<p>Silent Send v2.0.11</p>
</footer>
</div>
<script src="options.js" type="module"></script>
</body>
</html>