05/18 Enhanced codes and functionalities 8
This commit is contained in:
@@ -272,6 +272,26 @@ Requires Chrome 111+. `content.js` `onChanged` listener watches `area === 'sessi
|
||||
|
||||
## Key Implementation Details
|
||||
|
||||
### Vault health notifications (background checks)
|
||||
|
||||
`runBackgroundHealthCheck()` fires after every `loadVault()` call — async, non-blocking.
|
||||
|
||||
**Flow:**
|
||||
1. Computes weak + reused counts synchronously from `_items` → updates sidebar badge instantly
|
||||
2. Runs HIBP k-anonymity checks in parallel (`checkHibp`) → updates badge + banner when done
|
||||
|
||||
**Module state:**
|
||||
- `_healthCache` — `{ weak, reused, breached, breachedItems, hibpResults }` — set after first run
|
||||
- `_hibpRunning` — boolean guard prevents concurrent runs
|
||||
|
||||
**`_updateHealthUI({ weak, reused, breached })`** — renders:
|
||||
- **Sidebar badge** (`#security-badge`) on the 🛡️ Security link: red for breaches, amber for weak/reused only, hidden when clean
|
||||
- **Dismissible banner** (`#health-banner`) above the vault list: summarises issues with "View report" link → Security tab; dismiss hides for the session (`banner.dataset.dismissed = "1"`); resets on next vault load
|
||||
|
||||
**Security tab caching:** `renderSecurityDashboard` checks `_healthCache?.hibpResults` before querying HIBP — avoids double-calling the API within the same session.
|
||||
|
||||
**Banner reset:** `banner.dataset.dismissed` is set to `"0"` on each vault reload so fresh results (e.g. after a password change) are visible again.
|
||||
|
||||
### WebAuthn / Passkey
|
||||
|
||||
**Library:** `py-webauthn` (`webauthn>=2.0`). Installed via `pip install webauthn`.
|
||||
@@ -594,6 +614,8 @@ webauthn>=2.0 # Passkey / WebAuthn (py-webauthn)
|
||||
## Notes
|
||||
|
||||
- Never log decrypted vault data server-side — audit details use `item_type` + `id` only
|
||||
- Background health check runs after every vault load — badge + banner update without user action
|
||||
- HIBP results cached in `_healthCache` per session — Security tab reuses them, no double-query
|
||||
- Tags live in `enc_data` as `plain.tags: string[]` — no schema change ever needed
|
||||
- `vault_items_cs` is in `chrome.storage.session` — decrypted data never written to disk
|
||||
- HIBP checks run progressively — synchronous sections render first, then parallel async checks
|
||||
|
||||
@@ -16,6 +16,7 @@ A self-hosted, zero-knowledge password manager — web app and Chrome/Firefox ex
|
||||
- **Item sharing** — ECDH P-256 zero-knowledge re-encryption; item name encrypted with shared key — server never sees it
|
||||
- **Emergency access** — configurable wait-timer access grant for a trusted contact
|
||||
- **Security dashboard** — weak / reused / old / **no 2FA saved** / **HaveIBeenPwned breach check** (k-anonymity — passwords never transmitted)
|
||||
- **Proactive health notifications** — sidebar badge and dismissible banner on vault load when breached, weak, or reused passwords are detected; HIBP runs in the background without blocking the UI; results cached so opening the Security tab is instant
|
||||
- **Import / Export** — encrypted JSON backup; CSV export (plaintext, handle carefully); import from Chrome, Bitwarden, and 1Password CSV formats (RFC 4180 compliant parser)
|
||||
- **Account MFA** — TOTP-based login (Google Authenticator / Authy); single-use code enforcement prevents replay attacks
|
||||
- **Passkeys / WebAuthn** — register device biometrics or hardware keys as a sign-in method; master password still required to unlock vault (zero-knowledge preserved); manage passkeys in Account Settings
|
||||
|
||||
+11
-3
@@ -1513,15 +1513,23 @@ const Vault = (() => {
|
||||
}
|
||||
ul.innerHTML = shares
|
||||
.map(
|
||||
(s) => `
|
||||
(s) => {
|
||||
// Resolve the display name: prefer the decrypted name from _items
|
||||
// (owner's vault is already in memory), fall back to item_name which
|
||||
// is now the item_type label for new shares, or a legacy plaintext
|
||||
// name for shares created before the enc_name migration.
|
||||
const vaultItem = _items.find((i) => i.id === s.item_id);
|
||||
const displayName = vaultItem?.name || s.item_name;
|
||||
return `
|
||||
<li class="share-item">
|
||||
<div class="share-icon">${itemIcon(s.item_type)}</div>
|
||||
<div class="share-info">
|
||||
<span class="share-name">${escHtml(s.item_name)}</span>
|
||||
<span class="share-name">${escHtml(displayName)}</span>
|
||||
<span class="share-meta">Shared with ${escHtml(s.recipient_email)} · ${s.accepted ? "✅ Accepted" : "⏳ Pending"}</span>
|
||||
</div>
|
||||
<button class="btn-icon" title="Revoke share" data-revoke="${s.id}">🗑️</button>
|
||||
</li>`,
|
||||
</li>`;
|
||||
},
|
||||
)
|
||||
.join("");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user