# Test Expansion Integration Contract Generated by session: `test coverage expansion` Agent: `claude-sonnet-4-6` Priority 1: T-001–T-010 (10 files), Priority 2: T-011–T-024 (11 files, T-011–T-014 in one file), Priority 3: T-025, T-030, T-037 (3 files) --- ## Test File Index | File | T-numbers | Asserts | Notes | |------|-----------|---------|-------| | `recovery-words.integrity.test.ts` | T-001 | 5 | Word list structural checks | | `recovery-words.checksum.test.ts` | T-002 | 6 | Round-trip, swap, order, length | | `recovery-words.kek.test.ts` | T-003 | 5 | HKDF round-trip, zero-pad bytes[16-31] | | `totp.rfc6238.test.ts` | T-004 | 6 | RFC 6238 SHA1/256/512, boundary, URI parse | | `peachPayload.bomb.test.ts` | T-005 | 4 | MV-4 length-bomb, decompressZstd NOT called | | `backup.nfc-fallback.test.ts` | T-006 | 5 | LV-1 NFD-sealed unlocked with NFC | | `pdf-import.sandbox.test.ts` | T-007 | 4 | MV-9 pdf.js hardened flags | | `messages.batch-sanitize.test.ts` | T-008 | 6 | PCH-01-016 canary/tag sanitization | | `license.verification.test.ts` | T-009 | 6 live + 2 todo | Ed25519 verify, structural checks | | `chirp-transport.probe.test.ts` | T-010 | 3 | PCH-01-018 no-msg3 identity leak | | `content.orchestration.test.ts` | T-011–T-014 | 0 live + 11 todo | All stubs (index.ts exports nothing) | | `passkey.ed25519.test.ts` | T-015 | 7 | Ed25519 COSE, sign, verify, replay | | `vault.rotate-sync-identity.test.ts` | T-016 | 7 | MV-8 rotation: new key, clear peers, recovery pending | | `codex.multistripe.test.ts` | T-017 | 5 | Multi-stripe RS round-trip + erasure | | `vault.corruption.test.ts` | T-018 | 5 live + 1 todo | corrupted vs wrong_key discrimination | | `argon2id.kat.test.ts` | T-019 | 6 (1 skipped until KAT generated) | KDF params, determinism, NFC | | `sync.disconnect.test.ts` | T-020 | 4 | PCH-01-026 #9 onerror/onclose | | `import.csv.formulainjection.test.ts` | T-021 | 6 | Formula-injection round-trip | | `messages.edit-origin.test.ts` | T-022 | 5 | GET_ENTRY_FOR_EDIT origin check, includeAll guard | | `vault.consolidate-passkeys.test.ts` | T-023 | 4 | mergePasskeyOnlyIntoLogins lastUsed sort | | `vault.purge-trash.test.ts` | T-024 | 5 | Retention cutoff, 0-day guard, count | | `generate.empty-pool.test.ts` | T-025 | 8 | Empty pool fallback, 128-char, min/max | | `ml.predictbatch.test.ts` | T-030 | 8 | Batch sizes, softmax stability | | `clipboard.double-failure.test.ts` | T-037 | 4 | alreadyWritten skip, double-fail no throw | **Total: 24 test files, ~150 live assertions, ~13 todos** --- ## Real Crypto vs. Mocked Crypto (Priority 1) All Priority 1 tests use **real cryptographic primitives**: | Test | Crypto used | Notes | |------|-------------|-------| | T-001 | None | Word list structural | | T-002 | SubtleCrypto AES-GCM, HKDF, BLAKE2s | Via `recovery-words.ts` | | T-003 | SubtleCrypto HKDF, AES-GCM | Via `recovery-words.ts` | | T-004 | HMAC-SHA1/256/512 | Via `otpauth` library | | T-005 | Argon2id (m=65536, t=3, p=4), AES-GCM | `vi.mock("../../crypto/zstd")` for decompressZstd spy only | | T-006 | Argon2id, AES-GCM | Via `backup.ts` / `derivePeachExportKey` | | T-007 | None | `vi.mock("pdfjs-dist")` — testing flag plumbing only | | T-008 | Argon2id, AES-GCM | Via full vault setup | | T-009 | Ed25519 sign/verify | Local `validateLicenseWithKey` re-impl; prod `validateLicense` for structural checks | | T-010 | Curve25519 DH (Noise XX) | Via `noiseXXInitiator` + `noiseXXResponder` | --- ## New Dependencies Added These dependencies are used in the draft tests but are already present in `package.json`: - `@stablelib/x25519` — Noise XX keypair generation (T-010, T-020) - `pako` — deflate/inflate for Codex tests (T-017) - `hash-wasm` — Argon2id in T-005, T-006 (already used by production code) - `otpauth` — TOTP generation (T-004, already used by production code) No new npm dependencies are required. --- ## Source Refactoring Recommendations ### Required for T-011–T-014 (content orchestration) — HIGH PRIORITY `src/content/index.ts` exports nothing. All orchestration state and functions are module-private. To make the autofill orchestration tests runnable: ```typescript // src/content/index.ts — add these exports export { handleFieldInteraction } // T-012 export { initialScan } // T-013 export { wasAlreadyFilled } // T-011 export const _testSeam = { getLastDismissedField(): HTMLInputElement | null { return lastDismissedField; }, setLastDismissedField(f: HTMLInputElement | null): void { lastDismissedField = f; }, isDismissLocked(): boolean { return dismissLock !== null; }, DISMISS_LOCK_MS, } as const; ``` Additionally, the vitest environment for this file must be switched to `jsdom`: ```typescript // vitest.config.ts environmentMatchGlobs: [ ['src/drafts/TEST-EXPANSION/content.orchestration.test.ts', 'jsdom'], ] ``` ### Required for T-009f/g (license + chrome storage) Add `validateLicenseWithKey(keyString: string, pubKeyHex: string)` as an exported helper in `src/background/license.ts` with injectable public key. Currently the public key is hardcoded in a private `importPublicKey()` closure. ### Required for T-018f (consumeLastUnlockFailureReason integration) The test needs chrome.storage mock setup identical to T-008/T-016. The `it.todo` can be promoted to a live test using the same mock pattern. ### Recommended for T-019a (Argon2id KAT) Add a script at `scripts/gen-argon2id-kat.ts` to generate the expected hash vector and update `KAT_EXPECTED_HEX` in `argon2id.kat.test.ts`. Run once and commit. See the inline documentation in the test for the script body. --- ## Environment Requirements | Test file | Environment | Notes | |-----------|-------------|-------| | All current tests | `node` (default vitest env) | — | | `content.orchestration.test.ts` | `jsdom` required | Needs `environmentMatchGlobs` | | `sync.disconnect.test.ts` | `node` | Uses `vi.stubGlobal("WebSocket", ...)` | --- ## CI/Exclusion Configuration The `vitest.config.ts` already excludes `src/drafts/**` from CI runs: ```typescript exclude: ["src/drafts/**"] ``` Draft tests do not run automatically. To promote a test file to CI, move it from `src/drafts/TEST-EXPANSION/` to the canonical location beside its source (e.g., `src/background/vault.rotate-sync-identity.test.ts`) and remove it from the drafts directory. --- ## T-numbers Not Implemented The following Priority 3 test numbers from the brief were not implemented in this session (available for follow-up): - **T-026**: timestamp-clamp + manifest-freshness boundaries - **T-027**: full Codex UI round-trip e2e - **T-028**: autofill real-page e2e - **T-029**: inject.ts selector keyboard nav - **T-031**: SW eviction mid-operation - **T-032**: backup.ts empty-password contradiction - **T-033**: Firefox passkey e2e - **T-034**: LV-2 homograph UI surfacing - **T-035**: HIBP breach-check integration - **T-036**: reed-solomon try/finally free - **T-038**: favicon canvas fallbacks - **T-039**: chirp pairing failure paths - **T-040**: sync alert queue bounds --- ## Summary Statistics | Category | Count | |----------|-------| | Priority 1 files | 10 | | Priority 2 files | 11 | | Priority 3 files | 3 | | **Total draft files** | **24** | | Live assertions (approx.) | ~150 | | `it.todo` stubs | ~13 | | Tests using real crypto | All P1 (except T-007 which tests flag plumbing) | | Tests requiring source refactoring | T-011–T-014 (index.ts exports) |