mirror of
https://github.com/kccleoc/seedpgp-web.git
synced 2026-03-06 17:37:51 +08:00
- Update package.json version to v1.4.7 - Update README.md header to v1.4.7 - Update GEMINI.md version references to v1.4.7 - Update RECOVERY_PLAYBOOK.md version to v1.4.7 - Update SECURITY_AUDIT_REPORT.md version to v1.4.7 - Move documentation files to doc/ directory for better organization - Add new documentation files: LOCAL_TESTING_GUIDE.md, SERVE.md, TAILS_OFFLINE_PLAYBOOK.md - Add Makefile and serve.ts for improved development workflow
11 KiB
11 KiB
SeedPGP - Gemini Code Assist Project Brief
Project Overview
SeedPGP v1.4.7: Client-side BIP39 mnemonic encryption webapp
Stack: Bun + Vite + React + TypeScript + OpenPGP.js + Tailwind CSS
Deploy: Cloudflare Pages (private repo: seedpgp-web)
Live URL: https://seedpgp-web.pages.dev/
Core Constraints
- Security-first: Never persist secrets (mnemonic/passphrase/private keys) to localStorage/sessionStorage/IndexedDB
- Small PRs: Max 1-5 files per feature; propose plan before coding
- Client-side only: No backend; all crypto runs in browser (Web Crypto API + OpenPGP.js)
- Honest security claims: Don't overclaim what client-side JS can guarantee
Non-Negotiables
- Small diffs only: one feature slice per PR (1-5 files if possible)
- No big code dumps; propose plan first, then implement
- Never persist secrets to browser storage
- Prefer "explain what you found in the repo" over guessing
- TypeScript strict mode; no
anytypes without justification
Architecture Map
Entry Points
src/main.tsx→src/App.tsx(main application)- Build output:
dist/
Directory Structure
src/
├── components/ # React UI components
│ ├── PgpKeyInput.tsx
│ ├── QrDisplay.tsx
│ ├── QrScanner.tsx
│ ├── ReadOnly.tsx
│ ├── StorageIndicator.tsx
│ ├── SecurityWarnings.tsx
│ └── ClipboardTracker.tsx
├── lib/ # Core logic & crypto utilities
│ ├── seedpgp.ts # Main encrypt/decrypt functions
│ ├── sessionCrypto.ts # Ephemeral AES-GCM session keys
│ ├── types.ts # TypeScript interfaces
│ └── qr.ts # QR code utilities
├── App.tsx # Main app component
└── main.tsx # React entry point
Key Modules
src/lib/seedpgp.ts
Core encryption/decryption:
encryptToSeedPgp()- Encrypts mnemonic with PGP public key + optional passworddecryptFromSeedPgp()- Decrypts with PGP private key + optional password- Uses OpenPGP.js for PGP operations
- Output format:
SEEDPGP1:version:base64data:fingerprint
src/lib/sessionCrypto.ts (v1.3.0+)
Ephemeral session-key encryption:
getSessionKey()- Generates/returns non-exportable AES-GCM-256 key (idempotent)encryptJsonToBlob(obj)- Encrypts to{v, alg, iv_b64, ct_b64}decryptBlobToJson(blob)- Decrypts back to original objectdestroySessionKey()- Drops key reference for garbage collection- Test:
await window.runSessionCryptoTest()(DEV only)
src/lib/types.ts
Core interfaces:
SeedPgpPlaintext- Decrypted mnemonic data structureSeedPgpCiphertext- Encrypted payload structureEncryptedBlob- Session-key encrypted cache format
Key Features
v1.0 - Core Functionality
- Backup: Encrypt mnemonic with PGP public key + optional password → QR display
- Restore: Scan/paste QR → decrypt with private key → show mnemonic
- PGP support: Import public/private keys (.asc files or paste)
v1.1 - QR Features
- QR Display: Generate QR codes from encrypted data
- QR Scanner: Camera + file upload (uses html5-qrcode library)
v1.2 - Security Monitoring
- Storage Indicator: Real-time display of localStorage/sessionStorage contents
- Security Warnings: Context-aware alerts about browser memory limitations
- Clipboard Tracker: Monitor clipboard operations on sensitive fields
- Read-only Mode: Toggle to clear state + show CSP/build info
v1.3-v1.4 - Session-Key Encryption
- Ephemeral encryption: AES-GCM-256 session key (non-exportable) encrypts sensitive state
- Backup flow (v1.3): Mnemonic auto-clears immediately after QR generation
- Restore flow (v1.4): Decrypted mnemonic auto-clears after 10 seconds + manual Hide button
- Encrypted cache: Only ciphertext stored in React state; key lives in memory only
- Lock/Clear: Manual cleanup destroys session key + clears all state
- Lifecycle: Session key auto-destroyed on page close/refresh
Development Workflow
Commands
bun install # Install dependencies
bun run dev # Dev server (localhost:5173)
bun run build # Build to dist/
bun run typecheck # TypeScript validation (tsc --noEmit)
bun run preview # Preview production build
Deployment Process
Production: Cloudflare Pages (auto-deploys from main branch)
Live URL: https://seedpgp-web.pages.dev
Cloudflare Pages Setup
- Repository:
seedpgp-web(private repo) - Build command:
bun run build - Output directory:
dist/ - Security headers: Automatically enforced via
public/_headers
Git Workflow
# Commit feature
git add src/
git commit -m "feat(v1.x): description"
# Push to main branch (including tags) triggers auto-deploy to Cloudflare
git tag v1.x.x
git push origin main --tags
# **IMPORTANT: Update README.md before tagging**
# Update the following sections in README.md:
# - Current version number in header
# - Recent Changes section with new features
# - Any new usage instructions or screenshots
# Then commit the README update:
git add README.md
git commit -m "docs: update README for v1.x.x"
Required Workflow for AI Agents
1. Study First
Before implementing any feature:
- Read relevant files
- Explain current architecture + entry points
- List files that will be touched
- Identify potential conflicts or dependencies
2. Plan
- Propose smallest vertical slice (1-5 files)
- Show API signatures or interface changes first
- Get approval before generating full implementation
3. Implement
- Generate code with TypeScript strict mode
- Include JSDoc comments for public APIs
- Show unified diffs, not full file rewrites (when possible)
- Keep changes under 50-100 lines per file when feasible
4. Verify
- Run
bun run typecheck- no errors - Run
bun run build- successful dist/ output - Provide manual test steps for browser verification
- Show build output / console logs / DevTools screenshots
Common Patterns
State Management
- React
useState+useEffect(no Redux/Zustand/external store) - Ephemeral state only; avoid persistent storage for secrets
Styling
- Tailwind utility classes (configured in
tailwind.config.js) - Responsive design: mobile-first with
md:breakpoints - Dark theme primary: slate-900 background, blue-400 accents
Icons
lucide-reactlibrary- Common: Shield, QrCode, Lock, Eye, AlertCircle
Crypto Operations
- PGP: OpenPGP.js (
openpgppackage) - Session keys: Web Crypto API (
crypto.subtle) - Key generation:
crypto.subtle.generateKey()withextractable: false - Encryption: AES-GCM with random 12-byte IV per operation
Type Safety
- Strict TypeScript (
tsconfig.json:strict: true) - Check
src/lib/types.tsfor core interfaces - Avoid
any; useunknown+ type guards when necessary
Security Architecture
Threat Model (Honest)
What we protect against:
- Accidental persistence to localStorage/sessionStorage
- Plaintext secrets lingering in React state after use
- Clipboard history exposure (with warnings)
What we DON'T protect against (and must not claim to):
- Active XSS or malicious browser extensions
- Memory dumps or browser crash reports
- JavaScript garbage collection timing (non-deterministic)
Memory Handling
- Session keys: Non-exportable CryptoKey objects (Web Crypto API)
- Plaintext clearing: Set to empty string + drop references (but GC timing is non-deterministic)
- No guarantees: Cannot force immediate memory wiping in JavaScript
Storage Policy
- NEVER write to: localStorage, sessionStorage, IndexedDB, cookies
- Exception: Non-sensitive UI state only (theme preferences, etc.) - NOT IMPLEMENTED YET
- Verification: StorageIndicator component monitors all storage APIs
What NOT to Do
Code Generation
- Don't generate full file rewrites unless necessary
- Don't add dependencies without discussing bundle size impact
- Don't use
anytypes without explicit justification - Don't skip TypeScript strict mode checks
Security Claims
- Don't claim "RAM is wiped" (JavaScript can't force GC)
- Don't promise protection against active browser compromise (XSS/extensions)
Storage
- Don't write secrets to storage without explicit approval
- Don't cache decrypted data beyond immediate use
- Don't assume browser storage is secure
Testing & Verification
Manual Test Checklist (Before Marking Feature Complete)
- ✅
bun run typecheckpasses (no TypeScript errors) - ✅
bun run buildsucceeds (dist/ generated) - ✅ Browser test: Feature works as described
- ✅ DevTools Console: No runtime errors
- ✅ DevTools Application tab: No plaintext secrets in storage
- ✅ DevTools Network tab: No unexpected network calls (if Read-only Mode)
Session-Key Encryption Test (v1.3+)
// In browser DevTools console:
await window.runSessionCryptoTest()
// Expected: ✅ Success: Data integrity verified.
Current Version: v1.4.7
Recent Changes (v1.4.5):
- Fixed QR Scanner bugs related to camera initialization and race conditions.
- Improved error handling in the scanner to prevent crashes and provide better feedback.
- Stabilized component props to prevent unnecessary re-renders and fix
AbortError.
Known Limitations (Critical):
- Browser extensions can read DOM, memory, keystrokes - use dedicated browser
- Memory persistence - JavaScript cannot force immediate memory wiping
- XSS attacks if hosting server is compromised - host locally
- Hardware keyloggers - physical device compromise not protected against
- Supply chain attacks - compromised dependencies possible
- Quantum computers - future threat to current cryptography
Next Priorities:
- Enhanced BIP39 validation (full wordlist + checksum)
- Multi-frame support for larger payloads
- Hardware wallet integration (Trezor/Keystone)
Quick Reference
File a Bug/Feature
- Describe expected vs actual behavior
- Include browser console errors (if any)
- Specify which flow (Backup/Restore/QR Scanner)
Roll Over to Next Session
Always provide:
- Current version number
- What was implemented this session
- Files modified
- What still needs work
- Any gotchas or edge cases discovered
Example Prompts for Gemini
Exploration
Read GEMINI.md, then explain:
1. Where is the mnemonic textarea and how is its value managed?
2. List all places localStorage/sessionStorage are used
3. Show data flow from "Backup" button to QR display
Feature Request
Task: [Feature description]
Requirements:
1. [Specific requirement]
2. [Another requirement]
Files to touch:
- [List files]
Plan first: show proposed API/changes before generating code.
Verification
Audit the codebase to verify [feature] is fully implemented.
Check:
1. [Requirement 1]
2. [Requirement 2]
Output: ✅ or ❌ for each item + suggest fixes for failures.
Last Updated: 2026-01-29
Maintained by: @kccleoc
AI Agent: Optimized for Gemini Code Assist