# Storage format version 1 All integers are unsigned, little endian. No native Rust layouts are serialized. File length is exactly twice bank_size; each bank starts at `bank_number * bank_size`. Default bank_size is 16,777,216 bytes. Unused bytes are ignored and can retain older data; deletion is not secure erasure. Each bank begins with a 64-byte header: | Offset | Length | Meaning | |---|---:|---| | 0 | 8 | ASCII RATDB001 | | 8 | 4 | Format version, 1 | | 12 | 4 | Reserved, written zero | | 16 | 8 | Generation, starts at 1 | | 24 | 8 | Used record bytes following header | | 32 | 8 | Record count | | 40 | 8 | Bank size | | 48 | 12 | Reserved, written zero | | 60 | 4 | CRC-32 of bytes 0..60 (exclusive end) | CRC is CRC-32/ISO-HDLC (reflected polynomial 0xedb88320, initial state 0xffffffff, final XOR 0xffffffff). Standard check value for ASCII `123456789` is 0xcbf43926. It detects accidental corruption, not malicious modification. Record sequence starts at bank offset 64. Each record has: | Relative offset | Length | Meaning | |---|---:|---| | 0 | 4 | Key length K | | 4 | 4 | Value length V | | 8 | 4 | CRC-32 of concatenated length fields, key, value | | 12 | K | Key bytes | | 12+K | V | Value bytes | Records have no padding. Keys are nonempty and strictly increasing in byte order; values may be empty. All live records are present in the committed bank, with no tombstones. A reader selects the highest-generation valid header and validates lengths, checksums, ordering and count in that bank. A valid selected header with corrupt payload is a hard error, not fallback to an older snapshot. Unknown versions in a valid header are rejected. A zero header is invalidated/unused. A nonzero header with invalid magic/checksum is treated as an interrupted commit candidate and sets `Database::suspect_headers()`. Normal open refuses this image; explicit read-only inspection exposes the diagnostic because damage to a previously acknowledged header can look identical. See DURABILITY.md. Document keys are UTF-8 collection bytes, one NUL byte, then UTF-8 ID bytes. Neither component may be empty or contain NUL. Document values are UTF-8 JSON objects with a string `id` matching the key. See the optional C1 catalog encoding below. Core binary APIs and document APIs should not be mixed in one file unless all keys/values follow this encoding. Configuration limits are supplied by the caller and not persisted except bank size. Reopening with smaller limits can reject existing records. There is no migration or auto-detection of nondefault bank size. ## Document namespace extension W1 The physical header, checksum, records, and format version remain unchanged. Legacy keys remain exactly `den UTF-8 || NUL || ID UTF-8` and belong to the reserved `default` warren. New nondefault warren keys are `NUL || ASCII W1 || NUL || warren UTF-8 || NUL || den UTF-8 || NUL || ID UTF-8`. All components are nonempty and reject embedded NUL, so boundaries are unambiguous. The initial NUL cannot collide with any valid legacy key (legacy den names were nonempty and excluded NUL). No key rewriting or migration is performed; operations on the default warren continue writing legacy keys. The document decoder rejects malformed/unknown prefixed keys rather than guessing. Namespace lists skip other namespaces, and updated legacy collection listing excludes prefixed keys. A file with only W1 and legacy keys contains no explicit empty namespaces. Compatibility is forward reading of old files, not downgrade compatibility: old document binaries do not understand W1 keys and must not be used once nondefault warrens have been written. Raw core binary keys remain independent of document encoding; mixing arbitrary core keys into a document instance is unsupported. ## Explicit namespace catalog C1 A warren marker key is `NUL || ASCII C1 || NUL || warren UTF-8`. A den marker appends `NUL || den UTF-8` to its warren key. Marker values have length zero. Each component is 1–256 UTF-8 bytes and excludes NUL. The disjoint C1 prefix separates markers from documents. Every marker is an ordinary checksummed physical record and counts toward instance storage statistics. It never appears as a shiny. Readers derive names from both catalog markers and the W1/legacy document keys. Existing records need no migration. Explicit den creation writes any missing parent and den marker in a single commit. Removing an empty den deletes only its marker. Removing a warren first checks both the den-marker range and the document range (including all legacy dens for the default warren). There is no cascade. Use a C1-aware document reader after the first explicit create, including for files containing only the default warren. Store a verified backup before switching reader versions.