Storage System

How Xudanu stores and retrieves documents: content-addressed chunks, incremental checkpoints, and O(1) integrity verification.

1. Why We Needed a New Storage Engine 2. The Problem with Monolithic JSON 3. Architecture: Three-Layer Storage 4. ChunkStore: Content-Addressed Storage 5. BLAKE3 as the Universal Fingerprint 6. Edition Chunking: Breaking Documents into Pieces 7. Manifest: The Lightweight Index 8. Incremental Checkpoints 9. Data Integrity and Verification 10. Garbage Collection 11. Federation: Chunk Replication 12. Performance Characteristics 13. File Layout and Operations Guide

1. Why We Needed a New Storage Engine

Xudanu's storage engine was designed to solve four specific problems that emerge when a content-addressed hypertext system scales beyond a prototype.

Four Storage Requirements FAST WRITE/READ Documents are edited continuously. Checkpoint must not block requests. Target: <50ms checkpoint INCREMENTAL 10,000 docs with 1 edit should write 1 chunk, not re-serialize all 10K. Only write what changed FEDERATION Peers sync by exchanging chunks. Deduplication by content hash is automatic. Content-addressed = ready INTEGRITY Disk corruption, partial writes, bit rot. Must be detectable without full O(1) per-chunk verify ChunkStore: content-addressed BLAKE3-hashed chunk files One mechanism solves all four problems simultaneously

Figure 1: Four requirements that shaped the storage design, unified by content-addressed chunking.

The key insight: Xudanu already uses BLAKE3 content fingerprints throughout the engine — for transclusion identity, content deduplication, and the ContentAddressIndex. Reusing the same fingerprint as the storage key creates a system where identity, caching, and persistence all speak the same language.

Udanax-Gold comparison: Gold stored everything in a single monolithic file (ent database) with no incremental checkpointing or content-addressed chunks. Xudanu's three-layer storage (ChunkStore + Manifest + WAL) is a modern replacement that would not have been practical in the C++ era.

2. The Problem with Monolithic JSON

The original storage mechanism wrote the entire server state to a single server.json file on checkpoint. This worked for prototyping but had three critical flaws that would prevent production use:

Monolithic Write (Old)
{
  "works": [
    { "be_id": 1, "edition": {
      "entries": [
        /* 10,000 entries */
      ]
    }},
    /* 5,000 more works */
  ],
  "clubs": /* ... */,
  "links": /* ... */
}
Chunked Write (New)
manifest.json        /* 12 KB index */
chunks/
  0a/
    0a3f...b2c1      /* entry chunk */
    0a7e...d4a8      /* entry chunk */
  3b/
    3bc9...1f07      /* root chunk */
  /* 256 shard dirs max */
ProblemMonolithic JSONChunked Storage
Checkpoint cost O(n) — re-serialize everything O(changed) — write only modified chunks
Crash safety Partial write corrupts entire state Atomic rename per chunk; manifest is separate
Deduplication Same content stored N times BLAKE3 hash = filename; identical content stored once
Memory usage Must hold entire JSON in memory to parse Load only needed chunks; LRU cache for hot data
Federation sync Ship entire file to peers Exchange individual chunks by hash
Content-addressing aligns with Xudanu's core model. The same text in multiple documents already shares a BeId in the GrandMap. When that text is serialized to a chunk, it gets the same BLAKE3 hash regardless of which document triggered the write. Storage-level deduplication is free.

3. Architecture: Three-Layer Storage

The storage system is organized in three layers, each with a distinct responsibility. The top layer is a lightweight JSON index; the middle layer handles serialization of document structures into binary chunks; the bottom layer is the content-addressed file store.

Three-Layer Storage Architecture LAYER 1: MANIFEST manifest.json — lightweight JSON index Contains: work refs (be_id + chunk hashes), club refs, link graph, admin state, federation state SHA-256 checksum for tamper detection. Atomic write via rename. Typical: 5–50 KB hash refs LAYER 2: EDITION CHUNKS Serializes Editions and Works into chunk trees using postcard (binary) Root chunk = metadata + list of entry-chunk hashes. Entry chunks = up to 256 entries each. Work refs include revision history as a map of revision-number → EditionChunkRef. Source: src/persist/edition_chunks.rs write/read bytes LAYER 3: CHUNKSTORE Content-addressed file store. BLAKE3 hash of data = filename. Directory sharding: chunks/{first-2-hex-chars}/{full-64-char-hash} Atomic writes via tmp + rename. LRU cache (1024 entries). Integrity verified on every read. Deduplication is automatic: same bytes → same hash → same file. Write is idempotent. Source: src/persist/chunk_store.rs

Figure 2: Three layers separate concerns — indexing, serialization, and physical storage.

4. ChunkStore: Content-Addressed Storage

ChunkStore is the foundation. It maps arbitrary byte sequences to files named by their BLAKE3 hash. The API is intentionally minimal:

pub struct ChunkStore {
    base_dir: PathBuf,
    cache: Mutex<Cache>,         // LRU, 1024 entries
    cache_hits: AtomicU64,
    cache_misses: AtomicU64,
}

impl ChunkStore {
    pub fn write_chunk(&self, data: &[u8]) -> Result<[u8; 32], ChunkError>;
    pub fn read_chunk(&self, hash: &[u8; 32]) -> Result<Vec<u8>, ChunkError>;
    pub fn chunk_exists(&self, hash: &[u8; 32]) -> bool;
    pub fn verify_chunk(&self, hash: &[u8; 32]) -> Result<(), ChunkError>;
}

Write Path

write_chunk(data) Flow 1. BLAKE3 HASH hash = blake3(data) 32 bytes, 64 hex chars 2. EXISTS CHECK chunks/ab/ab3f...c2d1 Already on disk? Skip. 3. ATOMIC WRITE write ab3f.tmp rename ab3f.tmp → ab3f 4. CACHE INSERT LRU[hash] = data Return hash On-disk layout: data-dir/chunks/0a/0a3f7b2c1e8d9a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9 2-hex shard / ← 64-char BLAKE3 hex = filename → 256 possible shard directories (00–ff). Each contains chunk files named by their full hash.

Figure 3: Write path — hash, check existence, atomic write, cache.

Read Path

Every read_chunk checks the LRU cache first. On a cache hit, no disk I/O occurs. On a miss, the chunk is read from disk and its BLAKE3 hash is verified against the requested hash before returning. This means corruption is detected at read time, not just at verification time.

Cache hit avoids disk entirely. In the stress tests, deleting the on-disk file after a write still allows reads via the cache. The LRU holds 1,024 entries with O(1) eviction. Cache stats (hits, misses, rate) are tracked via atomic counters for monitoring.

5. BLAKE3 as the Universal Fingerprint

BLAKE3 serves double duty in Xudanu: it is both the content fingerprint used for transclusion identity and the storage key used for chunk addressing. This is not coincidental — it is a design decision that eliminates an entire class of mapping overhead.

BLAKE3: Shared Fingerprint Across Engine and Storage CONTENT ENGINE RangeElement.fingerprint() ContentAddressIndex Transclusion matching STORAGE ENGINE ChunkStore.write_chunk() File naming Integrity verification BLAKE3 32-byte hash Same input = same output Immutable, collision-resistant Consequences of shared fingerprinting: ✓ Same text in 10 documents → one chunk on disk (free deduplication) ✓ Federation peers can verify chunks without a separate checksum ✓ No mapping table between content IDs and storage keys ✓ Content-addressed index can reconstruct chunk location from content alone

Figure 4: BLAKE3 unifies content identity and storage addressing.

PropertyBLAKE3Why It Matters
Output size256 bits (32 bytes)Collision probability < 2-128 — negligible for any dataset size
Speed~1 GB/s single-threadedHashing never becomes the bottleneck
DeterministicSame input always produces same hashContent identity is stable across restarts, peers, and checkpoints
VerificationRe-hash and compareIntegrity check is just: does blake3(file_contents) == filename?

6. Edition Chunking: Breaking Documents into Pieces

An Edition (Xudanu's document data structure) is an O-tree with entries at integer positions. Rather than serializing an entire edition as one blob, edition_chunks.rs splits it into a root chunk and multiple entry chunks, each holding up to 256 entries.

Edition Chunk Tree EDITION pos 0: "Hello" pos 1: " " pos 2: "World" pos 255: "end" — chunk boundary — pos 256: "more" pos 257: "data" split ROOT CHUNK default: None domain_start: 0 entry_count: 300 entry_chunk_hashes: [ 0xa3f7..., 0xb2c1... ENTRY CHUNK 1 entries[0..255] 256 entries hash: a3f7...b2c1 ENTRY CHUNK 2 entries[256..299] 44 entries hash: b2c1...e8d9 Serialization: postcard (binary) Postcard is a compact binary format (no-tokio serde) Smaller than JSON, faster to parse Schema-evolution friendly (optional fields default) Same postcard library used in federation wire protocol Entries per chunk: ENTRIES_PER_CHUNK = 256

Figure 5: An Edition with 300 entries becomes 3 chunks: 1 root + 2 entry chunks. Entry chunks hold up to 256 entries each.

Work Chunk Refs

A Work (document) contains its current edition plus a revision history. Each revision is stored as its own edition chunk tree. The WorkChunkRef is the manifest's pointer to a work's data:

pub struct WorkChunkRef {
    be_id: BeId,
    owner: Option<BeId>,
    revision_count: u64,
    current_root: EditionChunkRef,          // current version
    history: BTreeMap<u64, EditionChunkRef>, // past versions
    read_club: Option<BeId>,
    edit_club: Option<BeId>,
    sponsors: Vec<BeId>,
}

Revisions are loaded lazily. work_from_chunks_current() reads only the current edition. work_load_revision() loads a specific revision by number. This means opening a document with 200 revisions reads 1 edition, not 201.

Provenance Chunks

The root chunk of an edition may also contain an optional provenance_hash pointing to a separate ProvenanceChunk. This chunk stores SpanProvenance data that tracks where each span of content originally came from — essential for transclusion tracking. When content is transcluded from one document into another, the provenance record preserves the source document's identity and span location, enabling correct attribution and back-references even after the source document is modified.

7. Manifest: The Lightweight Index

The manifest (manifest.json) is the only JSON file in the system. It contains references (not data) to all works, clubs, links, and administrative state. It is small by design:

pub struct Manifest {
    format_version: u32,                // currently version 3
    created_at: String,                 // ISO 8601 timestamp
    server_version: String,             // cargo package version
    checksum: String,                   // SHA-256 of content
    grand_map_id_counter: BeId,
    session_counter: u64,
    operation_counter: u64,
    system_clubs: SystemClubs,
    works: Vec<(BeId, WorkChunkRef)>,   // references to chunk trees
    clubs: Vec<ClubChunkRef>,
    standalone_editions: Vec<StandaloneEditionChunkRef>,
    links: Vec<LinkEntry>,
    link_counter: BeId,
    admin: AdminEntry,
    reconcile_store: ReconcileStore,       // federation reconciliation
    reconcile_counter: u64,
    federation: Option<FederationSnapshot>,
    content_address: Option<ContentAddressIndex>,
    blob_metas: Vec<BlobMetaEntry>,        // binary blob metadata
    key_history: Option<KeyHistoryEntry>,  // server key rotation history
}

Club Chunk Refs

Each club is stored as its own chunk tree. The ClubChunkRef in the manifest captures all club metadata:

pub struct ClubChunkRef {
    be_id: BeId,
    name: Option<String>,
    signature_club: Option<BeId>,
    work_root: WorkChunkRef,
    default_read_club: Option<BeId>,
    default_edit_club: Option<BeId>,
    is_personal: bool,                        // personal identity clubs
    display_name: Option<String>,             // human-readable name
    credential: Option<Credential>,           // password/boo auth
    encrypted_signing_key: Option<EncryptedSigningKey>,
    members: Vec<BeId>,
    sponsored_works: Vec<BeId>,
}
Clubs contain their own work tree. Each club has a work_root: WorkChunkRef pointing to a chunk tree for club-level documents (member lists, permissions). This means clubs are self-contained — loading a club reads its work root plus member data from a single chunk tree.
manifest.json work[0]: be_id=42, current_root work[1]: be_id=99, current_root club[0]: be_id=1, work_root links: [(42, 42, 99)] admin: accepting=true key_history, federation, blobs chunks/ directory a3/f7a3b2...root chunk for work 42 c1/b2c1d4...entry chunk for work 42 e8/d9e8f1...root chunk for work 99 0a/3f0a7e...club work root … shared chunks appear once

Figure 6: The manifest references chunks by BLAKE3 hash. Chunk data lives separately.

Checksum Protection

The manifest includes an SHA-256 checksum computed over its own content (with timestamp and version fields zeroed). On load, the checksum is recalculated and compared. If they don't match, the manifest is rejected with a ChecksumMismatch error. This catches accidental edits, partial writes, and bit-level corruption.

Manifest writes are atomic. The write path uses write manifest.tmp → rename manifest.tmp to manifest. On POSIX systems, rename is atomic on the same filesystem, so a crash during write leaves either the old or new manifest — never a partial file.

8. Incremental Checkpoints

The most significant performance benefit of chunked storage is incremental checkpoints. When a user edits a document:

Incremental vs. Full Checkpoint Server state: 5 documents, 1 edit made to doc #3 doc 1 (clean) doc 2 (clean) doc 3 (dirty) doc 4 (clean) doc 5 (clean) OLD: Full Serialization 1. Serialize all 5 documents to JSON 2. Write entire state to server.json I/O proportional to total data size NEW: Incremental Checkpoint 1. Chunk doc 3's new edition (N chunks) 2. Update manifest ref for doc 3 I/O proportional to changed data only On disk after checkpoint: New chunks written: only doc 3's changed entries. Old chunks for doc 3 (if shared with other docs) remain. Docs 1, 2, 4, 5: zero I/O.

Figure 7: With 10,000 documents and 1 edit, the old system writes all 10K. The new system writes the changed edition's chunks plus the manifest.

The checkpoint path in server.rs (checkpoint_to_store()) follows this sequence:

  1. Iterate works — skip if cached chunk_ref exists, serialize dirty ones
  2. Iterate clubs — skip if not in dirty_clubs set and cached ref exists
  3. Iterate standalone editions — skip if cached ref exists
  4. Collect all references into the manifest
  5. Write manifest atomically (tmp + rename)
  6. Run GC to remove orphaned chunks
  7. Log: "Checkpoint saved in Xms (dirty: W/C/E works/clubs/editions)"

Dirty Tracking

Incremental checkpoints rely on precise dirty tracking to avoid re-serializing unchanged data. Each entity type uses a different strategy:

Dirty Tracking: Works vs. Clubs WORKS (implicit dirty flag) State: chunk_ref: Option<WorkChunkRef> Dirty = no cached chunk_ref (first write or after mutation) Clean = chunk_ref cached from prior serialization After serialize: cache the ref → next checkpoint = zero I/O is_work_dirty() available for testing/monitoring CLUBS (explicit dirty set) State: dirty_clubs: HashSet<BeId> add_member() / remove_member() → insert ID into set On checkpoint: only re-serialize clubs in the set After checkpoint: clear the set entirely is_club_dirty() available for testing/monitoring

Figure 8: Works use cached refs as implicit dirty flags. Clubs use an explicit HashSet for precise tracking.

Because ChunkStore::write_chunk is idempotent (same data = same hash = no disk write if chunk exists), unchanged works produce no I/O even if the checkpoint code iterates over them. The dirty tracking is an optimization that avoids the serialization cost, not just the disk I/O.

9. Data Integrity and Verification

Xudanu provides a built-in verification tool: xudanu-server verify <data-dir>. This command performs a comprehensive integrity check across all stored data.

Verification Pipeline

xudanu-server verify Pipeline 1. MANIFEST CHECKSUM Verify SHA-256 of manifest content matches stored checksum Reject if version != current (format migration guard) 2. REFERENCE COLLECTION Walk manifest → work refs → edition refs → entry chunk hashes Build set of all hashes that should exist on disk 3. CHUNK INTEGRITY For every chunk on disk: read, BLAKE3 hash, compare to filename Detect: bit rot, truncation, wrong data, tampering 4. DESERIALIZATION Attempt to deserialize each work, club, standalone edition Catches schema corruption that passes hash check but has invalid structure 5. ORPHAN DETECTION Flag chunks on disk not referenced by manifest (leak detection)

Figure 9: Five-stage verification catches corruption, missing data, and storage leaks.

Report Output

$ xudanu-server verify /tmp/xudanu-data

Verification report:
  Chunks: 1,247 total, 1,247 verified
  Works: 50 ok, 0 failed
  Clubs: 3 ok, 0 failed
  Standalone editions: 12 ok, 0 failed
  Status: OK

The VerifyReport tracks: chunks verified, chunks corrupt (hash mismatch), chunks missing (referenced but not on disk), chunks orphaned (on disk but not referenced), deserialization errors, and per-type (work/club/edition) success/failure counts. A single failure in any category makes the overall status ISSUES FOUND.

10. Garbage Collection

After every checkpoint, the server automatically runs gc_orphaned_chunks() to reclaim disk space occupied by chunks no longer referenced by any work, club, or standalone edition. This prevents unbounded growth as documents are edited and old chunk trees are superseded.

Garbage Collection Pipeline 1. CHECKPOINT Write manifest + dirty chunks to disk. GC runs immediately after. 2. COLLECT REFS Walk works, clubs, standalone editions. HashSet of referenced hashes 3. COMPARE DISK List all chunk files in chunks/ directory. Set difference = orphans 4. DELETE ORPHANS Remove unreferenced chunk files from disk. Space reclaimed Log output: "Chunk GC: removed 3 orphaned chunks (247 referenced, 250 total on disk)" Source: src/server/server.rs — gc_orphaned_chunks() runs automatically after each checkpoint_to_store()

Figure 10: Garbage collection reclaims disk space by removing chunks no longer reachable from the manifest.

The GC process is safe because it runs after the manifest has been atomically written. Any chunk that was referenced by the previous manifest but is no longer referenced by the new one is guaranteed to be an orphan — the new manifest's references are the single source of truth.

GC is not a separate maintenance task. It runs as part of the normal checkpoint cycle. There is no cron job, no manual cleanup command, and no risk of accumulating orphaned chunks between maintenance windows. Each checkpoint is self-cleaning.

11. Federation: Chunk Replication

Content-addressed storage is a natural fit for federation. When two Xudanu servers synchronize, they exchange content at the chunk level. Because chunk identity is determined by content (BLAKE3 hash), peers can:

Federated Chunk Sync SERVER A Manifest: works [42, 99, 105] chunks/ a3f7... (doc 42) b2c1... (doc 42) chunks/ d4e8... (doc 99) f1a0... (shared) Want: hash e7b3... (new from B) SERVER B Manifest: works [55, 200, 42] chunks/ c5d9... (doc 55) a3f7... (doc 42) chunks/ e7b3... (doc 200) f1a0... (shared) Want: hash b2c1... (new from A) send b2c1... send e7b3... a3f7 and f1a0 already on both → skip (no transfer)

Figure 11: Federation sync exchanges only missing chunks. Shared content (same hash) is never sent twice.

The chunk-based federation protocol works in three steps:

StepActionData Transferred
1. Manifest exchangePeers share their manifestsSmall JSON (KB)
2. Want/have negotiationCompare chunk hash setsJust 32-byte hashes
3. Chunk transferSend only missing chunksBinary chunk data
Bandwidth scales with novelty, not size. If two servers share 90% of their content (common in a collaborative editing scenario), only the 10% that differs is transferred. The BLAKE3 hash comparison makes this negotiation cheap.

12. Performance Characteristics

The storage system was designed for the access patterns that Xudanu actually exhibits: frequent writes to a small number of active documents, infrequent reads of historical revisions, and periodic full checkpoints.

OperationComplexityNotes
Write chunk O(1) Hash data, check exists, atomic write. Same data = no-op.
Read chunk (cached) O(1) LRU lookup, no disk I/O. Cache holds 1,024 entries.
Read chunk (cold) O(chunk_size) Disk read + BLAKE3 verify. One file read per chunk.
Checkpoint (incremental) O(changed) Only modified chunks written. Unchanged works: zero I/O.
Checkpoint (full) O(total) All chunks serialized. But idempotent writes skip existing chunks.
Verify single chunk O(chunk_size) Read + re-hash + compare to filename.
Verify entire store O(total) Walk all chunks. Manifest + all chunk files.
Load work (current) O(1 edition) Only current_root chunk tree is read. History stays on disk.
Load revision N O(1 edition) BTreeMap lookup → one edition chunk tree. No scanning.
Deduplication O(1) Automatic: same bytes → same hash → same file. No dedup pass needed.

LRU Cache Behavior

The 1,024-entry LRU cache is particularly effective for Xudanu's workload. A user typically edits a handful of documents at a time. Each edit re-reads the same edition chunks and writes new ones for changed entries. The hot set (current editions of active documents) fits comfortably in 1,024 entries.

LRU Cache: 1024 Entries, O(1) Eviction oldest newest evict … 1018 more … Cache hit rate in stress tests: >95% for active working set Stats tracked: cache_hits, cache_misses (atomic u64). Exposed via cache_stats().

Figure 12: LRU cache with 1,024 entries covers the active working set of most sessions.

13. File Layout and Operations Guide

Directory Structure

data-dir/
  manifest.json                  # Lightweight index (SHA-256 checksummed)
  server.key                     # Server identity key (encrypted or plaintext)
  blobs/                         # Binary blobs (images, attachments)
    {blake3-hex}                 # Content-addressed binary data
  chunks/                        # Edition and work data
    00/                          # Shard 00
      {64-char-blake3-hex}       # One file per unique chunk
    01/                          # Shard 01
      ...
    ff/                          # Shard ff
      ...
  security.log                   # Chained security audit log
  security.log.seed              # Chain verification seed

Operational Commands

CommandPurpose
xudanu-server init <dir> Create data directory, generate server key, write empty manifest
xudanu-server run [addr] [dir] Start server. Restores from manifest + chunks. Checkpoints on Ctrl-C.
xudanu-server verify <dir> Full integrity check: manifest checksum, chunk hashes, deserialization, orphan detection
xudanu-server rebuild-manifest <dir> Reconstruct manifest from chunk files (disaster recovery)
xudanu-server verify-security-log <dir> Verify security log chain integrity (hash chain from seed)

Blob Storage

Binary blobs (images, attachments, and other non-text data) are stored in the blobs/ directory using the same content-addressed scheme as edition chunks. Each blob's filename is its BLAKE3 hash, ensuring automatic deduplication.

The manifest tracks blob metadata via BlobMetaEntry records:

pub struct BlobMetaEntry {
    content_hash: [u8; 32],       // BLAKE3 of blob data
    byte_size: u64,                // original file size
    mime_type: String,             // e.g. "image/png"
    preview_hash: Option<[u8; 32]>,// thumbnail/preview BLAKE3
    metadata: HashMap<String, String>, // extensible metadata
}
Blobs are separate from edition chunks. Edition chunks store document structure (entries, spans, transclusions). Blobs store raw binary data. This separation means blob storage can be backed by different infrastructure (CDN, object store) without affecting the edition chunk system.

Key History

The manifest stores a KeyHistoryEntry that enables key rotation verification across server restarts:

pub struct KeyHistoryEntry {
    server_id: BeId,
    entries: Vec<KeyHistoryRecord>,
    rotation_proofs: Vec<SignedProof>,
    current_key_id: String,
}

Each key rotation generates a signed proof that the old key authorized the new key. On startup, the server verifies the entire chain from the initial key to the current key. This prevents an attacker who compromises an old key from forging subsequent rotations.

Recovery Scenarios

Crash During Checkpoint

Chunk writes are atomic (tmp + rename). Manifest write is atomic. At worst, the previous checkpoint's data is intact. Individual chunks are either fully written or not present. The verify command identifies any gaps.

Disk Corruption

Each chunk is verified by filename = BLAKE3(contents). A corrupted chunk produces a HashMismatch error. The verify report lists all corrupt chunks by hash. Because chunks are small and independent, recovery can target individual files.

Lost Manifest

rebuild-manifest reconstructs the manifest from the chunk files on disk. Works and editions are rebuilt from their chunk trees. Not all metadata survives (admin grants, federation state), but document content is preserved.

Migration Between Servers

Copy the entire data-dir/ to the new server. Because chunks are content-addressed, the new server can verify them independently. The server key (server.key) controls identity — copy it to preserve server ID, or generate a new one for a fresh identity.

Storage Layer Guarantees ATOMICITY Each chunk: tmp + rename Manifest: tmp + rename Never see partial data POSIX rename guarantee INTEGRITY Every read verifies BLAKE3 Filename = hash(contents) Manifest SHA-256 checksummed Detect bit rot, truncation DEDUPLICATION Same content = same file Shared editions stored once Transcluded text = shared chunk Implicit, zero-cost

Figure 13: Three guarantees provided by the storage architecture.

Source files: src/persist/chunk_store.rs (950 lines) — ChunkStore with LRU cache. src/persist/edition_chunks.rs (508 lines) — Edition/Work serialization. src/persist/manifest.rs (418 lines) — Manifest with checksums. src/persist/verify.rs (422 lines) — Full-store verification. src/persist/stress.rs (1,259 lines) — Performance stress tests at Fast/Medium/Heavy scales. src/server/server.rs — checkpoint_to_store(), gc_orphaned_chunks(), dirty tracking.