05/18 Update CLAUDE.md and README.md

This commit is contained in:
2026-05-18 12:22:15 -04:00
parent 2eaf2adbf1
commit 09d3bbdc15
2 changed files with 164 additions and 54 deletions
+22 -11
View File
@@ -13,14 +13,14 @@ A self-hosted, zero-knowledge password manager — web app and Chrome/Firefox ex
- **Collapsible folder groups** — click any folder header in the vault list to collapse/expand; item count badge and chevron indicator; state persists across re-renders
- **TOTP / 2FA** — per-site TOTP codes stored in `plain.totp_uri`; live 6-digit display with countdown
- **Folder organisation** — create, rename, delete; filter vault by folder
- **Item sharing** — ECDH P-256 zero-knowledge re-encryption; share with any registered user
- **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)
- **Import / Export** — encrypted JSON backup; CSV export (plaintext, handle carefully); import from Chrome, Bitwarden, and 1Password CSV formats
- **Account MFA** — TOTP-based login (Google Authenticator / Authy)
- **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
- **Master password change** — atomic zero-knowledge re-encryption of entire vault including item names
- **Account recovery** — 128-bit recovery code; server never stores it
- **Audit log** — server-side trail of all create/edit/delete/import/export actions
- **Account recovery** — 128-bit recovery code; server never stores it; challenge-response proof prevents forgery
- **Audit log** — server-side trail of all create/edit/delete/import/export actions; no plaintext names ever logged
- **Encrypted item names** — `enc_name`/`iv_name`; server holds only the item type as a label
- **Browser history** — back/forward button works for all views (`history.pushState`)
- **Web-app auto-lock** — configurable inactivity timeout (5/10/15/30/60 min or Never); stored per browser in `localStorage`
@@ -55,6 +55,7 @@ Master Password
├─ PBKDF2(email, 100k iter) ──► authHash ──► POST /api/auth/login
│ Argon2id(authHash) stored in DB
│ (transparently rehashed if params upgraded)
└─ PBKDF2(enc_key_salt, 600k iter) ──► vaultKey (browser memory only)
@@ -64,9 +65,19 @@ Master Password
enc_name + iv_name (item name)
POST /api/vault ──► Server stores ciphertext only
Sharing: ECDH(Alice_priv, Bob_pub) ──► sharedKey ──► AES-256-GCM(enc_data + enc_name)
Server stores only ciphertext — cannot read item content or item name
```
A database breach exposes only encrypted ciphertext. The server cannot read vault names, passwords, or tags.
### Security hardening highlights
- **TOTP replay prevention** — each 6-digit code is single-use (120s window); recorded in `totp_used_codes` table
- **Recovery proof** — `enc_key_salt` not returned by server during recovery; client must decrypt the recovery blob to prove code possession
- **folder_id ownership** — all create/update/import operations validate folder belongs to current user
- **Audit log privacy** — item names and shared item names never appear in server-side audit logs
- **Extension fingerprinting** — `web_accessible_resources: []` blocks external pages from probing extension files
A database breach exposes only encrypted ciphertext. The server cannot read vault names, passwords, tags, or shared item names.
---
@@ -197,7 +208,7 @@ passkeeper/
├── app/ # Flask application
│ ├── models/ # SQLAlchemy models
│ ├── routes/ # API blueprints (auth, vault, folders, sharing, emergency)
│ ├── services/ # Auth (Argon2id, JWT, TOTP encryption)
│ ├── services/ # Auth (Argon2id, JWT, TOTP encryption, TOTP replay helpers)
│ ├── static/js/ # Client-side crypto + vault UI
│ └── templates/ # Jinja2 templates
├── extension/ # Browser extension
@@ -205,7 +216,7 @@ passkeeper/
│ ├── content/ # Content script (autofill, field detection)
│ ├── shared/ # Shared crypto + Firefox polyfill
│ ├── bridge/ # SSO bridge
│ ├── background.js # Chrome MV3 service worker
│ ├── background.js # Chrome MV3 service worker
│ ├── background.firefox.js # Firefox MV2 background page
│ ├── manifest.json # Chrome/Edge MV3
│ └── manifest.firefox.json # Firefox MV2
@@ -224,7 +235,7 @@ All vault/folder endpoints require `Authorization: Bearer <access_token>`.
|---|---|---|
| POST | `/api/auth/register` | Create account |
| POST | `/api/auth/login` | Authenticate |
| POST | `/api/auth/mfa/verify` | Complete MFA |
| POST | `/api/auth/mfa/verify` | Complete MFA (single-use code) |
| POST | `/api/auth/refresh` | Rotate tokens |
| POST | `/api/auth/logout` | Blacklist tokens |
| GET | `/api/vault` | List encrypted items |
@@ -234,7 +245,7 @@ All vault/folder endpoints require `Authorization: Bearer <access_token>`.
| GET | `/api/vault/export` | Download encrypted JSON backup |
| POST | `/api/vault/import` | Bulk import; returns `{ imported, skipped }` |
| GET/POST | `/api/folders` | List / create folders |
| POST | `/api/sharing` | Share item (ECDH re-encryption) |
| POST | `/api/sharing` | Share item — sends `enc_name`/`iv_name` for ZK name |
| POST | `/api/emergency` | Create emergency access grant |
| POST | `/api/auth/change-password` | Atomic vault re-encryption |
| POST | `/api/auth/recover` | Account recovery (one-time) |
@@ -245,7 +256,7 @@ All vault/folder endpoints require `Authorization: Bearer <access_token>`.
Tags are stored as `plain.tags: string[]` inside the encrypted vault blob — the server never sees them and no schema change is required.
**Web app:** Add tags in the item edit modal (comma-separated). Tags appear as purple badge pills on item rows. A Tags section in the sidebar lets you filter by any tag.
**Web app:** Add tags in the item edit modal (comma-separated). Tags appear as purple badge pills on item rows. A Tags section in the sidebar lets you filter by any tag. Search respects the active tag filter.
**Extension:** Tags appear as `.pk-tag` badges on item rows. Items tagged `favorite` appear in the **Favorites** tab and show a ★ in the site label.