# SeedPGP - Gemini Code Assist Project Brief ## Project Overview **SeedPGP v1.4.4**: Client-side BIP39 mnemonic encryption webapp **Stack**: Bun + Vite + React + TypeScript + OpenPGP.js + Tailwind CSS **Deploy**: Cloudflare Pages (private repo: `seedpgp-web`) **Live URL**: ## Core Constraints 1. **Security-first**: Never persist secrets (mnemonic/passphrase/private keys) to localStorage/sessionStorage/IndexedDB 2. **Small PRs**: Max 1-5 files per feature; propose plan before coding 3. **Client-side only**: No backend; all crypto runs in browser (Web Crypto API + OpenPGP.js) 4. **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 `any` types without justification --- ## Architecture Map ### Entry Points - `src/main.tsx` → `src/App.tsx` (main application) - Build output: `dist/` ### Directory Structure ```BASH 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 password - `decryptFromSeedPgp()` - 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 object - `destroySessionKey()` - Drops key reference for garbage collection - Test: `await window.runSessionCryptoTest()` (DEV only) #### `src/lib/types.ts` Core interfaces: - `SeedPgpPlaintext` - Decrypted mnemonic data structure - `SeedPgpCiphertext` - Encrypted payload structure - `EncryptedBlob` - 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 ```bash 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:** ### Cloudflare Pages Setup 1. **Repository:** `seedpgp-web` (private repo) 2. **Build command:** `bun run build` 3. **Output directory:** `dist/` 4. **Security headers:** Automatically enforced via `public/_headers` ### Git Workflow ```bash # 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-react` library - Common: Shield, QrCode, Lock, Eye, AlertCircle ### Crypto Operations - **PGP**: OpenPGP.js (`openpgp` package) - **Session keys**: Web Crypto API (`crypto.subtle`) - **Key generation**: `crypto.subtle.generateKey()` with `extractable: false` - **Encryption**: AES-GCM with random 12-byte IV per operation ### Type Safety - Strict TypeScript (`tsconfig.json`: `strict: true`) - Check `src/lib/types.ts` for core interfaces - Avoid `any`; use `unknown` + 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 `any` types 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) 1. ✅ `bun run typecheck` passes (no TypeScript errors) 2. ✅ `bun run build` succeeds (dist/ generated) 3. ✅ Browser test: Feature works as described 4. ✅ DevTools Console: No runtime errors 5. ✅ DevTools Application tab: No plaintext secrets in storage 6. ✅ DevTools Network tab: No unexpected network calls (if Read-only Mode) ### Session-Key Encryption Test (v1.3+) ```javascript // In browser DevTools console: await window.runSessionCryptoTest() // Expected: ✅ Success: Data integrity verified. ``` --- ## Current Version: v1.4.4 **Recent Changes (v1.4.4):** - Enhanced security documentation with explicit threat model - Improved README with simple examples and best practices - Better air-gapped usage guidance for maximum security - Version bump with security audit improvements **Known Limitations (Critical):** 1. **Browser extensions** can read DOM, memory, keystrokes - use dedicated browser 2. **Memory persistence** - JavaScript cannot force immediate memory wiping 3. **XSS attacks** if hosting server is compromised - host locally 4. **Hardware keyloggers** - physical device compromise not protected against 5. **Supply chain attacks** - compromised dependencies possible 6. **Quantum computers** - future threat to current cryptography **Next Priorities:** 1. Enhanced BIP39 validation (full wordlist + checksum) 2. Multi-frame support for larger payloads 3. Hardware wallet integration (Trezor/Keystone) --- ## Quick Reference ### File a Bug/Feature 1. Describe expected vs actual behavior 2. Include browser console errors (if any) 3. 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