1# PCH-02-FIXES — Integration Contract23Source of truth for integrating these drafts. Where a patch file and this4contract disagree, this contract wins.56## Integration Contract78### Files in `src/drafts/PCH-02-FIXES/`910| Draft file | Destination / role |11|---|---|12| `README.md` | index — stays in drafts (or trash after integration) |13| `INTEGRATION-CONTRACT.md` | this file — keep as reference (cited by tests) |14| `PCH-02-001-vault-patch-sanitizers.patch.md` | edits → `src/background/vault.ts:2375-2388` |15| `vault.update-entry-sanitize.test.ts` | → `src/background/vault.update-entry-sanitize.test.ts` |16| `PCH-02-002-noise-xx-msg1-hash.patch.md` | doc part → `src/shared/noise-js.ts:11-14` + `src/shared/noise-xx.ts:17`; wire part **deferred** |17| `PCH-02-003-sas-trust-model-comment.patch.md` | edits → `src/shared/chirp-handshake.ts:125-154` |18| `PCH-02-004-exact-pin-deps.patch.md` | edits → `package.json:40-46`; then `bun install` |19| `WASM-PROVENANCE.md` | → repo root `WASM-PROVENANCE.md` (new file) |20| `PCH-02-005-legacy-pbkdf2-doc.patch.md` | edits → `src/shared/backup.ts:146` + `src/popup/views/Import.tsx` (3 hunks) |21| `PCH-02-006-vault-id-privacy-note.patch.md` | edits → `src/shared/sync-identity.ts:62-67` |22| `PCH-02-007-hibp-add-padding.patch.md` | edits → `src/background/vault.ts:230` |23| `vault.hibp-padding.test.ts` | → `src/background/vault.hibp-padding.test.ts` |24| `PCH-02-008-binaryreader-bounds.patch.md` | edits → `src/crypto/peachPayload.ts:940-969` (+ `export` seam) |25| `peachPayload.binaryreader-bounds.test.ts` | → `src/crypto/peachPayload.binaryreader-bounds.test.ts` |26| `PCH-02-009-reject-zero-dh.patch.md` | edits → `src/shared/noise-xx.ts` (6 sites) + `src/shared/noise-js.ts` (6 sites) |27| `noise.reject-zero-dh.test.ts` | → `src/shared/noise.reject-zero-dh.test.ts` |28| `PCH-02-010-clipboard-hash-match.patch.md` | **Option A (recommended):** comment → `src/background/clipboard.ts:18-19`. **Option B:** `clipboard.ts` + `offscreen.ts` + `manifest.json` |29| `clipboard.hash-match.test.ts` | → `src/background/clipboard.hash-match.test.ts` — **Option B ONLY; do not integrate under Option A** |3031### Decisions required from the integrator (2)32331. **PCH-02-010 Option A vs B.** Option B requires adding `clipboardRead` to34 `manifest.json` — a store-visible permission expansion ("Read data you35 copy and paste"). Recommendation: Option A now, Option B parked.362. **PCH-02-004 papaparse hunk.** The brief pins 5 packages; the report also37 cites `papaparse`. The patch includes it as an optional sixth line.3839### ⚠ PCH-02-002 wire-change coordination (MUST land with Android)4041The Noise XX msg-1 empty-payload `mixHash` changes every XX handshake42ciphertext from msg 2 onward. **Do not apply the wire part** until the43matching peach-android change ships in the same release (PCH-01-002 /44v3.9.1-android-v2.2.9 model). What lands now: the deferral comment in45`noise-xx.ts`, the corrected `snow`-interop claim in `noise-js.ts`, and the46ready-to-apply patch staying in this folder. When the window opens: apply the47two `mixHash(new Uint8Array(0))` insertions, regenerate the XX vectors in48`noise-xx.test.ts`/`noise-blake2s-kat.test.ts`, and regenerate the matching49Android `CrossPlatformKATTest` vectors.5051### PCH-02-004 exact versions (read from bun.lock 2026-06-12 — pin, don't upgrade)5253| Package | Pin |54|---|---|55| otpauth | 9.5.0 |56| pako | 2.1.0 |57| @zxing/library | 0.23.0 |58| bwip-js | 4.11.1 *(lockfile had drifted above the declared ^4.10.1)* |59| pdf-lib | 1.17.1 |60| papaparse | 5.5.3 *(optional hunk)* |6162After the edit run `bun install` (regenerates `bun.lock`; resolved tree is63unchanged because every pin equals the installed version).6465### Estimated test count per finding6667| Finding | New tests |68|---|---|69| PCH-02-001 | 8 |70| PCH-02-002 | 0 now (KAT regeneration when the wire change lands) |71| PCH-02-003 | 0 — doc only (gateOnSAS already pinned by PCH-01-024 test) |72| PCH-02-004 | 0 — dependency metadata only |73| PCH-02-005 | 0 required (1 optional UI contract case sketched in the patch) |74| PCH-02-006 | 0 — doc only |75| PCH-02-007 | 3 |76| PCH-02-008 | 8 |77| PCH-02-009 | 5 |78| PCH-02-010 | Option A: 0 — doc only / Option B: 4 |79| **Total** | **24 (Option A) / 28 (Option B)** |8081### Documentation-only findings (no tests needed)8283PCH-02-003, PCH-02-005 (comment + notice), PCH-02-006, PCH-02-002 (the part84landable now), PCH-02-010 under Option A.8586### Suggested integration order (one koh save each, tests green at every step)87881. PCH-02-001 (the Low) + its tests892. PCH-02-007, PCH-02-008, PCH-02-009 + tests (independent hardening)903. PCH-02-003, PCH-02-005, PCH-02-006 + PCH-02-002 doc part (comments/UI)914. PCH-02-004 (package.json + `bun install` + WASM-PROVENANCE.md)925. PCH-02-010 (whichever option is chosen)936. Version bump + build all three targets (`npm run build`)9495### Gates after every save9697- `npx tsc --noEmit` clean (baseline: clean)98- `npx vitest run` — baseline 117 files / 3474 passed; after full99 integration expect **+4 test files / +24 tests** (Option A) or **+5 / +28**100 (Option B)101- No `@ts-ignore` / type suppressions introduced (none in any draft)102103### Version bump recommendation104105v4.0.0 → **v4.0.1** (patch: hardening + docs, no feature surface) across106`package.json`, `manifest.json`, `manifest.firefox.json`, then107`npm run build` (all three targets, per project rule). If PCH-02-010108Option B is chosen, bump v4.0.0 → **v4.1.0** instead — a new permission is109not a patch-level change.110111### Out-of-scope observations recorded during drafting112113- `vault.updateEntryDirect` (vault.ts:1978) spreads patches verbatim but has114 zero production callers — dead-code candidate, noted in the 001 patch.115- The fix brief's PCH-02-005 text says "100,000 iterations"; the code and116 report say 250,000 — drafts use 250,000.117- The brief's PCH-02-004 step references an existing `WASM-PROVENANCE.md`;118 no such file exists in the repo, so the draft ships one.