Files
bitchat/bitchatTests/Services
jackandClaude Fable 5 10ba71b1f8 Fix panic-wipe window, frame byte bound, and delivery-side test waits
Three confirmed defects from adversarial review of the per-relay inbound
pipeline (PR #1352):

- MEDIUM-2: a detached gift-wrap decrypt spawned just before a panic wipe
  strongly captures the pre-wipe Nostr private key and could deliver
  plaintext into ChatViewModel after the wipe. Add a per-pipeline
  monotonic wipe generation (NostrInboundPipeline.wipeGeneration), bumped
  from panicClearAllData via invalidateInFlightDecrypts(); spawn sites
  capture it and every main-actor hop drops the task's result on
  mismatch. The account-mailbox path (processNostrMessage) had the same
  pre-existing hazard and gets the identical guard, capturing the
  generation atomically with the identity fetch.

- MEDIUM-1: the per-relay stream cap bounds FRAMES (256) but not BYTES;
  with the URLSession default of 1 MiB per WebSocket frame a hostile
  relay could pile up ~256 MiB. Set URLSessionWebSocketTask
  .maximumMessageSize to TransportConfig.nostrInboundMaxFrameBytes
  (512 KiB — an order of magnitude above any legitimate Nostr event or
  gift wrap we produce or expect), halving the worst case to 128 MiB,
  and correct the "cannot exhaust memory" comments to state the actual
  cap × maxFrameBytes bound.

- LOW-5: three NostrRelayManagerTests gated on messagesReceived (first
  main hop) then immediately asserted delivery-side state that only
  lands after off-main verification plus a second main hop. Wait on the
  delivery-side state (receivedIDs / duplicate-drop counts) directly,
  keeping all assertions.

Also: brief comment documenting pendingGiftWrapIDs growth (LOW-6) and a
regression test that a panic wipe issued after spawn drops the decrypted
result while leaving the pipeline usable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 11:08:29 +02:00
..