OS bundle download was buffering 1.2GB in RAM then writing → network
timeout or memory pressure killed it. Now:
Kiosk side:
- Streams directly to /var/tmp/betterframe/ in 256KB chunks
- On network error: resumes from last byte written (Range header)
- Up to 5 retries with 10s backoff between attempts
- Progress logged every ~50MB
- sha256 verified on the complete file on disk (not in memory)
Server side:
- /api/kiosk/os/download/:id supports Range: bytes=N- header
- Returns 206 Partial Content with Content-Range for resume
- streamBundle accepts start/end for partial reads via createReadStream
- Advertises Accept-Ranges: bytes on all responses