d1f501a07784

test: VaultAdopt T-A33 >768 KiB frame-ceiling regression (v4.6.4)

Adds one regression case to src/shared/vault-adopt.test.ts that proves the root-cause fix for REVIEW_DEFERRED_ITEMS_BRIEF.md Item 1 (MEDIUM): duress no longer counts against the entries frame. The case builds a 450 KiB entry plus a 320 KiB sealed-duress JSON whose combined raw crosses the 768 KiB SNAPSHOT_FRAME_WIRE_CEILING and asserts sendVaultSnapshot/receiveVaultSnapshot round-trip entries, tombstones, and duressSlot intact. Gate: tsc --noEmit clean; vitest run 139 files / 3665 baseline tests pass, only T-A33 fails. Failure throws ADOPT_SNAPSHOT_CHUNK_TOO_LARGE at vault-adopt.ts:364 - the duress-rides-final-chunk reject path that the v4.6.4 frame-ceiling fix must remove. Failing assertion is the intended regression signal; goes green with no test edit when duress moves to its own frame. Deferral: the actual browser-side duress-on-separate-frame wire fix is NOT in this save. Coordinated with peach-android v2.9.9 receiver work and dual-path backward-compat tests per the brief. VERSION 4.6.3 -> 4.6.4.

time
2026-07-30 18:35 UTC · 2 months ago
machine
koh2
parent
158d02e85de5
4 files manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/shared/vault-adopt.test.ts+33 −0
manifest.firefox.json+1 −1
@@ -1,7 +1,7 @@11 {22   "manifest_version": 3,33   "name": "Peach Password Manager",4-  "version": "4.6.3",4+  "version": "4.6.4",55   "description": "Zero-knowledge password manager",66   "browser_specific_settings": {77     "gecko": {

view file

manifest.json+1 −1
@@ -2,7 +2,7 @@22   "manifest_version": 3,33   "minimum_chrome_version": "116",44   "name": "Peach Password Manager",5-  "version": "4.6.3",5+  "version": "4.6.4",66   "description": "Zero-knowledge password manager",77   "action": {88     "default_popup": "src/popup/index.html",

view file

package.json+1 −1
@@ -1,6 +1,6 @@11 {22   "name": "peach",3-  "version": "4.6.3",3+  "version": "4.6.4",44   "description": "Zero-knowledge password manager",55   "license": "GPL-3.0-only",66   "type": "module",

view file

src/shared/vault-adopt.test.ts+33 −0
@@ -5,6 +5,8 @@55   isAdoptGrant,66   requestAdoption,77   sendFrame,8+  sendVaultSnapshot,9+  receiveVaultSnapshot,810   type AdoptRequest,911   type AdoptionReceiverDeps,1012   type AdoptionSourceDeps,@@ -630,5 +632,36 @@630632     const result = await receiverPromise;631633     expect(result).not.toBeNull();632634     expect(result!.snapshotCapable).toBe(false);635+  });636+637+  // T-A33: regression for the SNAPSHOT_FRAME_WIRE_CEILING (768 KiB) bug.638+  // Today duress rides the final entries chunk, so an entry + duress whose639+  // combined raw exceeds 768 KiB throws ADOPT_SNAPSHOT_CHUNK_TOO_LARGE on640+  // receive. The v4.6.4 frame-ceiling fix separates duress from the entries641+  // frame; this test proves that root-cause change rather than just a new642+  // frame type. Currently fails until the fix lands.643+  it("T-A33: >768 KiB snapshot (entry + duress) succeeds because duress no longer counts against the entries frame", async () => {644+    const [source, receiver] = memoryPair();645+    const entries: Record<string, string> = { "id-0": "x".repeat(450 * 1024) };646+    const tombstones: Record<string, number> = { "dead-0": 1 };647+    // ~320 KiB sealed duress: 450 KiB entry + ~320 KiB duress + JSON envelope648+    // and tombstone map crosses the 768 KiB SNAPSHOT_FRAME_WIRE_CEILING when649+    // duress rides the entries chunk.650+    const duressJson = JSON.stringify({651+      version: 1,652+      salt: "aa".repeat(16),653+      nonce: "bb".repeat(12),654+      ciphertext: "cc".repeat(320 * 1024),655+      tag: "dd".repeat(16),656+    });657+658+    const [result] = await Promise.all([659+      receiveVaultSnapshot(receiver),660+      sendVaultSnapshot(source, entries, tombstones, duressJson),661+    ]);662+663+    expect(result.entries).toEqual(entries);664+    expect(result.tombstones).toEqual(tombstones);665+    expect(result.duressSlot).toBe(duressJson);633666   });634667 });

view file