4c15b8de49bb
test: T-A38 root-cause proof — >768 KiB snapshot succeeds because duress rides its own frame
- time
- 2026-07-30 22:28 UTC · 2 months ago
- machine
- koh2
- parent
- 1077ccaa33eb
↓ peach-browser-4c15b8de.tar.gzatlas at this save
files changed1 file
src/shared/vault-adopt.test.ts+61 −0src/shared/vault-adopt.test.ts+61 −0
@@ -792,4 +792,65 @@792792 expect(Object.keys(result.entries).length).toBeLessThan(200);793793 expect(result.tombstones).toEqual({ "dead-0": 1 });794794 });795+796+ // T-A38: the single test that proves the *root-cause fix* for the frame797+ // ceiling bug, not just the new wire path. Combines the high-level798+ // end-to-end success assertion (T-A33) with the structural proof (T-A34):799+ // a payload whose combined raw exceeds the 768 KiB wire ceiling succeeds800+ // because the duress slot rides its own frame instead of piggybacking on801+ // the entries final chunk. Pre-v4.6.4, duress counted against the entries802+ // frame, so a single frame would exceed SNAPSHOT_FRAME_WIRE_CEILING and the803+ // receiver would reject the whole snapshot with ADOPT_SNAPSHOT_CHUNK_TOO_LARGE.804+ it("T-A38: >768 KiB snapshot succeeds because duress no longer counts against the entries frame", async () => {805+ const [source, receiver] = memoryPair();806+ // Single entry that is ~450 KiB on its own; combined with a ~640 KiB807+ // duress JSON, the total payload exceeds the 768 KiB wire ceiling.808+ const entries: Record<string, string> = { "id-0": "x".repeat(450 * 1024) };809+ const tombstones: Record<string, number> = { "dead-0": 1 };810+ const duressJson = JSON.stringify({811+ version: 1,812+ salt: "aa".repeat(16),813+ nonce: "bb".repeat(12),814+ ciphertext: "cc".repeat(320 * 1024),815+ tag: "dd".repeat(16),816+ });817+ const CEILING = 768 * 1024;818+819+ // Probe the wire so we can assert the structural shape alongside the820+ // end-to-end success.821+ const observed: Array<{ size: number; hasDuress: boolean; entriesKeys: number }> = [];822+ const probe: PairingTransport = {823+ async send(msg) {824+ const f = JSON.parse(new TextDecoder().decode(msg)) as Record<string, unknown>;825+ observed.push({826+ size: msg.length,827+ hasDuress: typeof f.duress_slot === "string",828+ entriesKeys: Object.keys((f.entries as Record<string, unknown>) ?? {}).length,829+ });830+ return source.send(msg);831+ },832+ receive() { return source.receive(); },833+ };834+835+ const [result] = await Promise.all([836+ receiveVaultSnapshot(receiver),837+ sendVaultSnapshot(probe, entries, tombstones, duressJson),838+ ]);839+840+ // High-level success: the receiver accepts the >768 KiB combined payload.841+ expect(result.entries).toEqual(entries);842+ expect(result.tombstones).toEqual(tombstones);843+ expect(result.duressSlot).toBe(duressJson);844+845+ // Root-cause proof: duress is on its own frame, not on the entries frame.846+ // Every frame stays under the ceiling; only the combined raw exceeds it.847+ expect(observed.length).toBe(2);848+ expect(observed[0].hasDuress).toBe(false);849+ expect(observed[0].entriesKeys).toBe(1);850+ expect(observed[0].size).toBeLessThan(CEILING);851+ expect(observed[1].hasDuress).toBe(true);852+ expect(observed[1].entriesKeys).toBe(0);853+ expect(observed[1].size).toBeLessThan(CEILING);854+ expect(observed[0].size + observed[1].size).toBeGreaterThan(CEILING);855+ });795856 });