Here's your `DEVELOPMENT.md`: ```markdown # Development Guide - SeedPGP v1.1.0 ## Architecture Quick Reference ### Core Types ```typescript // src/lib/types.ts interface SeedPgpPlaintext { v: number; // Version (always 1) t: string; // Type ("bip39") w: string; // Mnemonic words (normalized) l: string; // Language ("en") pp: number; // BIP39 passphrase used? (0 or 1) fpr?: string[]; // Optional recipient fingerprints } interface ParsedSeedPgpFrame { kind: "single"; // Frame type crc16: string; // 4-digit hex checksum b45: string; // Base45 payload } ``` ### Frame Format ``` SEEDPGP1:0:ABCD:BASE45DATA SEEDPGP1 - Protocol identifier + version 0 - Frame number (single frame) ABCD - CRC16-CCITT-FALSE checksum (4 hex digits) BASE45 - Base45-encoded PGP binary message ``` ### Key Functions #### Encryption Flow ```typescript buildPlaintext(mnemonic, bip39PassphraseUsed, recipientFingerprints?) → SeedPgpPlaintext encryptToSeedPgp({ plaintext, publicKeyArmored?, messagePassword? }) → { framed: string, pgpBytes: Uint8Array, recipientFingerprint?: string } ``` #### Decryption Flow ```typescript decryptSeedPgp({ frameText, privateKeyArmored?, privateKeyPassphrase?, messagePassword? }) → SeedPgpPlaintext frameDecodeToPgpBytes(frameText) → Uint8Array (with CRC16 validation) ``` #### Encoding/Decoding ```typescript frameEncode(pgpBinary: Uint8Array) → "SEEDPGP1:0:CRC16:BASE45" frameParse(text: string) → ParsedSeedPgpFrame frameDecodeToPgpBytes(frameText: string) → Uint8Array ``` ### Dependencies ```json { "openpgp": "^6.3.0", // PGP encryption (curve25519Legacy) "bun-types": "latest", // Bun runtime types "react": "^18.x", // UI framework "vite": "^5.x" // Build tool } ``` ### OpenPGP.js v6 Quirks ⚠️ **Important compatibility notes:** 1. **Empty password array bug**: Never pass `passwords: []` to `decrypt()`. Only include if non-empty: ```typescript if (msgPw) { decryptOptions.passwords = [msgPw]; } ``` 2. **Curve naming**: Use `curve25519Legacy` (not `curve25519`) in `generateKey()` 3. **Key validation**: Always call `getEncryptionKey()` to verify public key has usable subkeys ## Project Structure ``` seedpgp-web/ ├── src/ │ ├── lib/ │ │ ├── seedpgp.ts # Core encrypt/decrypt logic │ │ ├── seedpgp.test.ts # Test vectors (15 tests) │ │ ├── base45.ts # Base45 encoder/decoder │ │ ├── crc16.ts # CRC16-CCITT-FALSE │ │ └── types.ts # TypeScript interfaces │ ├── App.tsx # React UI entry │ └── main.tsx # Vite bootstrap ├── package.json ├── tsconfig.json ├── vite.config.ts ├── README.md └── DEVELOPMENT.md # This file ``` ## Development Workflow ### Running Tests ```bash # All tests bun test # Watch mode bun test --watch # Verbose output bun test --verbose ``` ### Development Server ```bash bun run dev # Start Vite dev server bun run build # Production build bun run preview # Preview production build ``` ### Adding Features 1. **Write tests first** in `seedpgp.test.ts` 2. **Implement in** `src/lib/seedpgp.ts` 3. **Update types** in `types.ts` if needed 4. **Run full test suite**: `bun test` 5. **Commit with conventional commits**: `feat: add QR generation` ## Feature Agenda ### 🚧 v1.2.0 - QR Code Round-Trip **Goal**: Read back QR code and decrypt with user-provided credentials **Tasks**: - [ ] Add QR code generation from `encrypted.framed` - Library: `qrcode` or `qr-code-styling` - Input: SEEDPGP1 frame string - Output: QR code image/canvas/SVG - [ ] Add QR code scanner UI - Library: `html5-qrcode` or `jsqr` - Camera/file upload input - Parse scanned text → `frameText` - [ ] Build decrypt UI form - Input fields: - Scanned QR text (auto-filled) - Private key (file upload or paste) - Key passphrase (password input) - OR message password (alternative) - Call `decryptSeedPgp()` - Display recovered mnemonic + metadata - [ ] Add visual feedback - CRC16 validation status - Key fingerprint match indicator - Decryption success/error states **API Usage**: ```typescript // Generate QR import QRCode from 'qrcode'; const { framed } = await encryptToSeedPgp({ ... }); const qrDataUrl = await QRCode.toDataURL(framed); // Scan and decrypt const scannedText = "SEEDPGP1:0:ABCD:..."; // from scanner const decrypted = await decryptSeedPgp({ frameText: scannedText, privateKeyArmored: userKey, privateKeyPassphrase: userPassword, }); console.log(decrypted.w); // Recovered mnemonic ``` **Security Notes**: - Never log decrypted mnemonics in production - Clear sensitive data from memory after use - Validate CRC16 before attempting decrypt - Show key fingerprint for user verification --- ### 🔮 Future Ideas (v1.3+) - [ ] Multi-frame support (for larger payloads) - [ ] Password-only (SKESK) encryption flow - [ ] Shamir Secret Sharing integration - [ ] Hardware wallet key generation - [ ] Mobile companion app (React Native) - [ ] Printable paper backup templates - [ ] Encrypted cloud backup with PBKDF2 - [ ] BIP85 child mnemonic derivation ## Debugging Tips ### Enable verbose PGP logging Uncomment in `seedpgp.ts`: ```typescript console.log("Raw PGP hex:", Array.from(pgpBytes).map(...)); console.log("SeedPGP: message packets:", ...); console.log("SeedPGP: encryption key IDs:", ...); ``` ### Test with known vectors Use Trezor vectors from test file: ```bash bun test "Trezor" # Run only Trezor tests ``` ### Validate frame manually ```typescript import { frameParse } from "./lib/seedpgp"; const parsed = frameParse("SEEDPGP1:0:ABCD:..."); console.log(parsed); // Check structure ``` ## Code Style - **Functions**: Async by default, explicit return types - **Errors**: Throw descriptive Error objects with context - **Naming**: `camelCase` for functions, `PascalCase` for types - **Comments**: Only for non-obvious crypto/encoding logic - **Testing**: One test per edge case, descriptive names ## Git Workflow ```bash # Feature branch git checkout -b feat/qr-generation # Conventional commits git commit -m "feat(qr): add QR code generation" git commit -m "test(qr): add QR round-trip test" # Tag releases git tag -a v1.2.0 -m "Release v1.2.0 - QR round-trip" git push origin main --tags ``` ## Questions for Next Session When continuing development, provide: 1. **Feature context**: "Adding QR code generation for v1.2.0" 2. **Current code**: Paste relevant files you're modifying 3. **Specific question**: "How should I structure the QR scanner component?" Example starter prompt: ``` I'm working on seedpgp-web v1.1.0 (BIP39 PGP encryption tool). [Paste this DEVELOPMENT.md section] [Paste relevant source files] I want to add QR code generation. Here's my current seedpgp.ts... ``` --- **Last Updated**: 2026-01-28 **Maintainer**: @kccleoc ``` Now commit it: ```bash git add DEVELOPMENT.md git commit -m "docs: add development guide with v1.2.0 QR agenda" git push origin main ``` Ready for your next feature sprint! 🚀📋