mirror of
https://github.com/kccleoc/seedpgp-web.git
synced 2026-03-07 09:57:50 +08:00
feat(v1.3.0): add ephemeral session-key encryption for sensitive state
- Add src/lib/sessionCrypto.ts with AES-GCM-256 non-exportable session keys - Integrate into Backup flow: auto-clear plaintext mnemonic after QR generation - Add Lock/Clear button to destroy session key and clear all state - Add cleanup useEffect on component unmount - Add comprehensive GEMINI.md for AI agent onboarding - Fix TypeScript strict mode errors and unused imports Tested: - Session-key encryption working (mnemonic clears after QR gen) - Lock/Clear functionality verified - No plaintext secrets in localStorage/sessionStorage - Production build successful
This commit is contained in:
49
GEMINI.md
49
GEMINI.md
@@ -1,12 +1,14 @@
|
||||
# SeedPGP - Gemini Code Assist Project Brief
|
||||
|
||||
## Project Overview
|
||||
|
||||
**SeedPGP v1.3.0**: Client-side BIP39 mnemonic encryption webapp
|
||||
**Stack**: Bun + Vite + React + TypeScript + OpenPGP.js + Tailwind CSS
|
||||
**Deploy**: GitHub Pages (public repo: `seedpgp-web-app`, private source: `seedpgp-web`)
|
||||
**Live URL**: https://kccleoc.github.io/seedpgp-web-app/
|
||||
**Live URL**: <https://kccleoc.github.io/seedpgp-web-app/>
|
||||
|
||||
## 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)
|
||||
@@ -14,6 +16,7 @@
|
||||
5. **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
|
||||
@@ -25,10 +28,12 @@
|
||||
## Architecture Map
|
||||
|
||||
### Entry Points
|
||||
|
||||
- `src/main.tsx` → `src/App.tsx` (main application)
|
||||
- Build output: `dist/` (separate git repo for GitHub Pages deployment)
|
||||
|
||||
### Directory Structure
|
||||
|
||||
```
|
||||
src/
|
||||
├── components/ # React UI components
|
||||
@@ -51,14 +56,18 @@ src/
|
||||
### 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
|
||||
@@ -66,7 +75,9 @@ Ephemeral session-key encryption:
|
||||
- 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
|
||||
@@ -76,21 +87,25 @@ Core interfaces:
|
||||
## 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 - Session-Key Encryption (Current)
|
||||
|
||||
- **Ephemeral encryption**: AES-GCM-256 session key (non-exportable) encrypts sensitive state
|
||||
- **Auto-clear**: Plaintext mnemonic cleared from UI immediately after QR generation
|
||||
- **Encrypted cache**: Only ciphertext stored in React state; key lives in memory only
|
||||
@@ -102,6 +117,7 @@ Core interfaces:
|
||||
## Development Workflow
|
||||
|
||||
### Commands
|
||||
|
||||
```bash
|
||||
bun install # Install dependencies
|
||||
bun run dev # Dev server (localhost:5173)
|
||||
@@ -112,11 +128,13 @@ bun run preview # Preview production build
|
||||
```
|
||||
|
||||
### Deployment Process
|
||||
|
||||
1. **Private repo** (`seedpgp-web`): Source code, development
|
||||
2. **Public repo** (`seedpgp-web-app`): Built files for GitHub Pages
|
||||
3. **Deploy script** (`scripts/deploy.sh`): Builds + copies to dist/ + pushes to public repo
|
||||
|
||||
### Git Workflow
|
||||
|
||||
```bash
|
||||
# Commit feature
|
||||
git add src/
|
||||
@@ -135,24 +153,29 @@ git push origin main --tags
|
||||
## 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
|
||||
@@ -163,25 +186,30 @@ Before implementing any feature:
|
||||
## 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
|
||||
@@ -191,22 +219,27 @@ Before implementing any feature:
|
||||
## 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
|
||||
@@ -216,17 +249,20 @@ Before implementing any feature:
|
||||
## 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 claim "offline mode" without real CSP headers (GitHub Pages can't set custom headers)
|
||||
- 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
|
||||
@@ -236,6 +272,7 @@ Before implementing any feature:
|
||||
## 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
|
||||
@@ -244,6 +281,7 @@ Before implementing any feature:
|
||||
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()
|
||||
@@ -255,17 +293,20 @@ await window.runSessionCryptoTest()
|
||||
## Current Version: v1.3.0
|
||||
|
||||
### Recent Changes (2026-01-29)
|
||||
|
||||
- ✅ Added `src/lib/sessionCrypto.ts` with ephemeral AES-GCM session keys
|
||||
- ✅ Integrated into Backup flow: plaintext mnemonic auto-cleared after QR generation
|
||||
- ✅ Added Lock/Clear button to destroy session key and clear all state
|
||||
- ✅ Added cleanup on component unmount
|
||||
|
||||
### Known Limitations
|
||||
|
||||
- GitHub Pages cannot set custom CSP headers (need Cloudflare Pages for enforcement)
|
||||
- Read-only Mode is UI-level only (not browser-enforced)
|
||||
- Session-key encryption doesn't protect against active XSS/extensions
|
||||
|
||||
### Next Priorities (Suggested)
|
||||
|
||||
1. Extend session-key encryption to Restore flow
|
||||
2. Migrate to Cloudflare Pages for real CSP header enforcement
|
||||
3. Add "Encrypted in memory" badge when encryptedMnemonicCache exists
|
||||
@@ -276,12 +317,15 @@ await window.runSessionCryptoTest()
|
||||
## 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
|
||||
@@ -293,6 +337,7 @@ Always provide:
|
||||
## Example Prompts for Gemini
|
||||
|
||||
### Exploration
|
||||
|
||||
```
|
||||
Read GEMINI.md, then explain:
|
||||
1. Where is the mnemonic textarea and how is its value managed?
|
||||
@@ -301,6 +346,7 @@ Read GEMINI.md, then explain:
|
||||
```
|
||||
|
||||
### Feature Request
|
||||
|
||||
```
|
||||
Task: [Feature description]
|
||||
|
||||
@@ -315,6 +361,7 @@ Plan first: show proposed API/changes before generating code.
|
||||
```
|
||||
|
||||
### Verification
|
||||
|
||||
```
|
||||
Audit the codebase to verify [feature] is fully implemented.
|
||||
Check:
|
||||
|
||||
Reference in New Issue
Block a user