# Recovery audit - storage v1 The reference model is one exclusive writer, exact reads/writes, zero-filled growth, and successful sync persisting prior bytes and length. A failed call may have taken effect. A write must not damage bytes outside its range, including adjacent bytes in the same device sector. RAM storage models persistence only while its byte vector exists. |Boundary|Durable candidates after loss| |---|---| |Empty storage: resize to two banks; sync|Empty (creation may retry), wrong length (reject), or all-zero banks (reject). Never auto-repair a nonempty invalid image.| |Write initial bank 0 generation 1; sync|No valid header (reject), or valid empty database. Open succeeds only after sync and reread.| |Invalidate inactive header; sync|Prior committed snapshot remains. Zero is normal. Partial nonzero invalidation is ambiguous: refuse normal access.| |Read each old record, write replacement lengths, CRC and body; sync payload|New bank remains unpublished. Any short write/read or failed barrier poisons the handle; no subsequent commit on that handle.| |Write next 64-byte header; final sync|Zero: old snapshot. Torn nonzero invalid CRC/magic: refuse. Complete header: new snapshot even if caller saw error.| |Final sync succeeds; acknowledge|New snapshot must survive under the stated adapter contract. No additional disk operation needed for ACK. Lost network response is indeterminate to client.| Open checks both headers. Valid v1 generation starts at one and alternates by bank; two published generations must be adjacent. A bad payload in the selected generation is a hard error. The checksum covers each record's lengths, key and value, and each header's first 60 bytes. The full open scan verifies count and strict key order. No WAL, checkpoint or migration exists in v1. Reading a v1 file needs its original bank size. No format change in this run. Preserve suspect media. Database::inspect returns a handle that cannot commit or initialize an empty adapter. Its surviving snapshot may be stale. Database::open rejects a nonzero invalid header even if another bank is valid. Completely erased latest header is still indistinguishable from intentional invalidation; even CRC-valid data is not authenticated. Zero-length truncation is indistinguishable from fresh embedded storage; host commands must open_existing or explicitly create_new. No automated repair. Use a verified independent backup. Tests: fault adapter with separate volatile/durable images; simulated short writes, failed sync with zero/all preceding writes durable, successive failures, init boundaries, all 65 header publication prefixes, acknowledged updates, truncation, corruption, model stress and real process termination harness. Failures during resize that leave a nonstandard nonzero length are covered by length rejection; device-level arbitrary sector reorder, loss outside target, cache misreporting, parent-directory loss, and hardware power cuts are not validated. Additional gates: 65 torn-invalidation prefixes; impossible CRC-valid generation pairs; and 32 deterministic seeds that spill scattered pending bytes before every write/barrier fault in a two-document batch. Inspection saw only a complete old or new pair. This samples arbitrary persistence subsets; it is not exhaustive over all bit patterns.