fix: Reserve frame for duress at chunk cap (v2.9.9 HIGH re-review fix) Mirrors the cross-repo GPT-5.6-Sol HIGH finding on peach-browser v4.6.4 (silent duress drop at MAX_SNAPSHOT_CHUNKS): when duress is configured, the entry cap is MAX_SNAPSHOT_CHUNKS - 1 = 199 so the duress frame can fit alongside. Previously a vault with exactly 200 entries + duress had its duress frame silently dropped at the cap, and ordinary sync cannot restore duress (`VaultRepository.exportDuressSlotForAdoption` is the only transfer path on Android). Now duress always fits (one entry is deferred to sync when needed, which is safe because sync carries entries and tombstones). Also mirrors the overflow guard for oversized standalone duress: duress that itself exceeds the 768 KiB SNAPSHOT_FRAME_WIRE_CEILING now throws ADOPT_SNAPSHOT_DURESS_FRAME_TOO_LARGE BEFORE any frame is sent, so the caller can split duress out of band instead of silently losing it. app/src/main/java/com/peachpasswords/sync/VaultAdopt.kt:sendVaultSnapshot - entryCap = includeDuress ? MAX_SNAPSHOT_CHUNKS - 1 : MAX_SNAPSHOT_CHUNKS - sendDuress = includeDuress (always try when configured; rely on entryCap to leave room) - pre-encode check on the duress envelope; throw ADOPT_SNAPSHOT_DURESS_FRAME_TOO_LARGE if it would exceed the ceiling - doc comment updated to call out the duress-frame reservation rationale AND the oversized-duress hard-stop semantics app/src/test/java/com/peachpasswords/sync/VaultAdoptSnapshotTest.kt: - updated T-A33 comment to historical tense (matches browser) - new `duress is reserved a frame so 199 entries plus duress fits in MAX_SNAPSHOT_CHUNKS` (T-A36) - new `200 entries plus duress does not silently drop duress at the chunk cap` (T-A37) - new `duress larger than wire ceiling throws loudly before sending` (cap-pre-check guardrail) versions: peach-android VERSION unchanged at 2.9.9 (cap fix is a follow-up to the prior v2.9.9 save c0c413a8804 -- there was no behavior change that requires a version bump. A follow-up review by GPT-5.6-Sol cleared the HIGH finding; the underlying protocol doc was also corrected.). Gate: focused `testDebugUnitTest --tests "*.VaultAdoptSnapshotTest"` green on first pass after the coroutine-style fix (the first attempt used runBlocking-inside-runBlocking which Kotlin rejected at compile); full gate `./gradlew testDebugUnitTest lintDebug assembleRelease --rerun-tasks` BUILD SUCCESSFUL 2m28s. 846 tests / 117 suites / 0 failures / 0 errors / 0 skips (was 840 at v2.9.8 baseline + 3 v4.6.4 frame-fix mirrors + 3 cap-math mirrors = 846). VaultAdoptSnapshotTest: 19 tests / 0 / 0.

dev · 4 weeks ago · 2026-07-30 · 5.7 MB

$ koh steal kepr.uk/peach-android@943c244c435c
·
← c0c413a880b4 9cb3dd127225 →
⇓ download .face