An object holding exactly the age header plus its 16-byte nonce decrypts
without error: age.Decrypt succeeds, and on the first read the age stream's
io.ErrUnexpectedEOF is mapped by the zstd decoder to a clean io.EOF at frame
start. blobgen.Reader.Read then reported zero bytes and no error, so a
truncated stream was indistinguishable from a valid empty one. Blobs are
caught by the Close-time hash check, but the metadata database export was not:
restore built a fresh schema on the empty file and exited reporting success.
blobgen.Reader.Read now, on EOF, reads once more from the age reader and
surfaces io.ErrUnexpectedEOF unless that read is (0, io.EOF) — the state a
genuine end leaves behind, so an empty payload still round-trips to empty with
no error. downloadSnapshotDB additionally rejects a zero-length decrypted
database before OpenReadOnly applies a schema.
On next the decrypted-DB identity check already rejects an empty database, so
the restore-level test guards the required end-to-end property; the blobgen
tests are the ones that fail without the reader change.
Model: opus-4-8