fix: Bug - Sending files between users doesn't really work (chunk-time size re-gate)

Remove the leftover MAX_AUTO_SAVE_SIZE_BYTES guard from handleFileChunk's
in-memory path. The request gate (canReceiveAttachment) already admits 10-50 MB
generic files for in-memory receive on stores without disk streaming (browser),
but the chunk handler silently dropped every chunk of such files: no ack was
sent, the sender's waitForAck timed out, and the receiver's GUI never changed.
Receive admission is now decided once, at request time.

Adds a two-browser regression e2e that sends an 11 MB generic file and asserts
Request -> progress -> Download.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-13 18:48:30 +02:00
co-authored by Cursor
parent 497033aff0
commit 590e487250
5 changed files with 161 additions and 7 deletions
+7
View File
@@ -25,6 +25,13 @@ Durable rules for AI agents working on this project. Read this file at session s
## Lessons
### Decide attachment receive admission once at request time; never re-gate size in the chunk handler [attachments]
- **Trigger:** "Sending files between users doesn't really work" — a browser user clicked Request on a 1050 MB generic file, the request gate (`canReceiveAttachment`) admitted it for in-memory receive, the sender streamed chunks, but `handleFileChunk` still had a leftover hard `size > MAX_AUTO_SAVE_SIZE_BYTES` rejection on the in-memory path, so every chunk was dropped, no ack was ever sent, the sender's `waitForAck` timed out, and the GUI never changed.
- **Rule:** `canReceiveAttachment` (request time) is the single admission decision; the chunk handler may only route between disk-streaming and in-memory assembly — any stricter size check there silently drops chunks the request gate already admitted.
- **Why:** the failure is invisible in logs-from-the-outside: the sender's per-chunk sends look like a working transfer ("packages with size 32kb") until the ack timeout, and the receiver sets `requestError` only into memory that a re-request immediately clears — the user just sees a dead Request button.
- **Example:** removed the `MAX_AUTO_SAVE_SIZE_BYTES` guard in `attachment-transfer.service.ts#handleFileChunk`; regression e2e `e2e/tests/chat/large-generic-file-transfer.spec.ts` sends an 11 MB `.bin` between two browser clients and asserts Request → progress → Download (fails on the old code, passes after).
### Re-queue attachment auto-downloads on every message/room binding event; never trust one transport's ordering [attachments] [realtime]
- **Trigger:** cross-user attachment sync e2e (`chat-message-features.spec.ts`) flaked ~50%: `file-announce` (WebRTC data channel) beat `chat-message` (signaling websocket) to the receiver, so the announce-time auto-download resolved `roomId=null`, silently gave up, and nothing ever retried — the receiver showed "Waiting for image source..." forever. A related bug: the stalled-download reset keyed only on "receivedBytes>0 && no pending request", but the pending-request marker is deleted on the *first* chunk, so any auto-download pass during an active transfer cancelled it mid-stream and the retry deadlocked against the sender's active-transfer dedupe.