Skip to content

docs: split THEORY out of ARCHITECTURE, refresh all three docs for encryption - #86

Merged
Xof merged 2 commits into
mainfrom
docs/theory-split-and-encryption
Jul 1, 2026
Merged

docs: split THEORY out of ARCHITECTURE, refresh all three docs for encryption#86
Xof merged 2 commits into
mainfrom
docs/theory-split-and-encryption

Conversation

@Xof

@Xof Xof commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

Refreshes the three top-level docs now that on-disk encryption has landed (#85), and draws the ARCHITECTURE / THEORY boundary that was never separated — the two were blended into a single ARCHITECTURE.md.

The split is by read pattern, not detail:

  • ARCHITECTURE.md — the cold-start map a context-free reader reads whole to act correctly: layer model, exact on-disk byte format, invariants, landmines.
  • THEORY.md (new) — the theory of operation a human reads once to understand why: the decisions, the rejected alternatives, the history.

ARCHITECTURE.md (compressed 759 → 710, 3 content bugs fixed)

Kept every byte-format table, the commit/recovery diagrams, the failure table, and the glossary. Extracted the narrative "why" and the entire implementation-history / benchmark-methodology narrative to THEORY.md. Fixed three bugs surfaced by re-checking against the code:

  1. Stale module map — the layer graph and table still listed flat transaction.rs / superblock.rs, but the code decomposed these into transaction/ (~14 submodules) and superblock/ (+crypto_header.rs); the whole crypto/ layer and handle.rs / lru.rs / spillway.rs were absent. Map and mermaid graph now match the code, including the encryption public surface.
  2. Superblock byte-offset contradiction — the format section called bytes 324..8184 "reserved" while the encryption section put the key-slot table at 324..1356. Now correctly conditional: plaintext DBs keep it reserved; encrypted DBs place the crypto-header + 8-slot key table there and seal the sensitive body under the DEK.
  3. Encryption presented as shipped, not speculative.

THEORY.md (new)

The 18 load-bearing decisions, each as chosen / rejected-alternative / why, harvested from the ADR graph, docs/specs/, and ISSUES.md — shadow-paging over WAL, single-writer, per-module COW, the poison model, the spillway, chunk tags, the encryption cipher/keys/format, the MSRV pins. Plus the implementation history and benchmark methodology. It cross-references ARCHITECTURE's invariant enumeration rather than restating it (verified: zero byte-tables in THEORY vs 31 in ARCHITECTURE; all cross-reference anchors resolve).

Seven rationale gaps are marked > Rationale not recovered from project sources rather than invented (why XXH3, why 8 KB pages, why 8 key-slots, why superblock default = 2, the Argon2 default costs, the spillway 1024× multiplier, the membership depth-6 bound). If any of these reasons are known, they're worth filling in.

README.md (updated)

Added the encryption surface (Options.encryption_key / argon2_params, Key / Argon2Params, add_key / rotate_key / remove_key, the five operational error variants + fatal DecryptionFailed, MAJOR=2, the Python encryption_key kwarg). Corrected the toolchain commands against Cargo.toml / pyproject.toml / ci.yml — the Python flow was missing hypothesis and used debug builds where CI uses --release; the clippy / msrv / test gates now match CI. Human-authored prose preserved.

Verification

Docs-only; no code touched. All internal cross-references resolve; ARCHITECTURE's own TOC has no dangling anchors after the section moves; the documented error variants and byte offsets were checked against src/.

Xof added 2 commits July 1, 2026 09:51
…cryption

Draw the ARCHITECTURE/THEORY boundary (previously blended into one file) and
bring the three top-level docs current with the merged on-disk encryption
feature.

- ARCHITECTURE.md: compressed to the cold-start, act-correctly map — kept every
  on-disk byte-format table, the commit/recovery diagrams, the failure table,
  and the glossary; extracted the narrative "why" and the implementation
  history to THEORY.md. Fixed three content bugs found against the code:
  the stale module map (transaction.rs / superblock.rs were decomposed into
  directory modules; the crypto/ layer and handle.rs / lru.rs / spillway.rs
  were missing), the superblock 324..8184 reserved-bytes contradiction (now
  conditional on plaintext vs encrypted), and encryption shown as shipped.

- THEORY.md (new): theory of operation for an engineer about to change the
  engine — the 18 load-bearing decisions with their rejected alternatives,
  the implementation history, and the benchmark methodology. Cross-references
  ARCHITECTURE's invariant enumeration instead of duplicating it. Seven
  rationale gaps are marked "not recovered from project sources" rather than
  invented.

- README.md: added the encryption surface (Options.encryption_key /
  argon2_params, Key / Argon2Params, add_key / rotate_key / remove_key, the
  five operational error variants + fatal DecryptionFailed, MAJOR=2, the
  Python encryption_key kwarg) and corrected the toolchain commands (the
  Python flow needs hypothesis and --release; the clippy / msrv / test gates
  now match CI).
Two of the seven "Rationale not recovered" gaps in THEORY.md are answered
directly by the engine author and move up into the decision sections:

- Page size 8 KB: chosen to align with the underlying storage block size so
  a page maps cleanly onto the device's block granularity (new subsection
  next to the durability decision).
- superblock_count default = 2: a deliberate integrity/performance balance —
  3 is defensible, but larger N costs considerable performance for little
  added safety (folded into the ADR-4 decision).

Both are attributed as recorded from the engine author rather than a written
ADR. Five genuine gaps remain, still marked "not recovered" rather than
invented.
@Xof
Xof merged commit 9efb735 into main Jul 1, 2026
6 checks passed
@Xof
Xof deleted the docs/theory-split-and-encryption branch July 1, 2026 16:58
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

🚦 Bench results: PR vs main

⚠️ 4 regression(s) detected across 3 scenario/mode pair(s)

Scenario Mode Δ throughput Worst Δ
document-store chisel-strict -1.6% p99 +15.5% ⚠️
ycsb-a chisel-mem -1.5% p95 +14.6% ⚠️
ycsb-a sqlite-strict -1.6% p99 +12.3% ⚠️
document-store chisel-mem +2.2%
document-store redb-strict +3.5%
document-store sqlite-strict +0.4%
mutation-log chisel-mem -0.6%
mutation-log chisel-strict -0.3%
mutation-log redb-strict +0.0%
mutation-log sqlite-strict -0.6%
ycsb-a chisel-strict -0.3%
ycsb-a redb-strict -0.0%
ycsb-b chisel-mem +1.2%
ycsb-b chisel-strict +0.4%
ycsb-b redb-strict +0.1%
ycsb-b sqlite-strict -1.5%
Per-scenario detail (4 metrics × cells)

document-store

Mode Throughput p50 p95 p99
chisel-mem 32485 ops/s → 33195 ops/s (+2.2%) 5.5 µs → 5.5 µs (-1.1%) 69.6 µs → 68.2 µs (-2.1%) 300.5 µs → 303.6 µs (+1.0%)
chisel-strict 2997 ops/s → 2950 ops/s (-1.6%) 13.9 µs → 14.6 µs (+5.4%) ⚠️ 831.1 µs → 836.5 µs (+0.6%) 2.22 ms → 2.56 ms (+15.5%) ⚠️
redb-strict 4009 ops/s → 4150 ops/s (+3.5%) 12.0 µs → 11.9 µs (-1.2%) 454.6 µs → 430.8 µs (-5.2%) 1.30 ms → 1.25 ms (-3.5%)
sqlite-strict 5130 ops/s → 5150 ops/s (+0.4%) 21.2 µs → 21.4 µs (+0.9%) 339.5 µs → 336.8 µs (-0.8%) 1.37 ms → 1.31 ms (-4.2%)

mutation-log

Mode Throughput p50 p95 p99
chisel-mem 53901 ops/s → 53569 ops/s (-0.6%) 23.3 µs → 23.4 µs (+0.3%) 26.5 µs → 26.8 µs (+1.1%) 35.9 µs → 36.1 µs (+0.4%)
chisel-strict 1776 ops/s → 1770 ops/s (-0.3%) 290.5 µs → 299.1 µs (+3.0%) 637.7 µs → 651.5 µs (+2.2%) 18.99 ms → 18.31 ms (-3.6%)
redb-strict 1805 ops/s → 1805 ops/s (+0.0%) 146.6 µs → 147.8 µs (+0.8%) 221.5 µs → 230.8 µs (+4.2%) 34.29 ms → 34.05 ms (-0.7%)
sqlite-strict 5029 ops/s → 4997 ops/s (-0.6%) 96.9 µs → 98.5 µs (+1.7%) 267.4 µs → 273.2 µs (+2.2%) 379.6 µs → 398.3 µs (+4.9%)

ycsb-a

Mode Throughput p50 p95 p99
chisel-mem 39605 ops/s → 39015 ops/s (-1.5%) 41.9 µs → 41.5 µs (-0.8%) 57.3 µs → 65.6 µs (+14.6%) ⚠️ 79.6 µs → 74.8 µs (-6.0%)
chisel-strict 2264 ops/s → 2256 ops/s (-0.3%) 256.2 µs → 253.9 µs (-0.9%) 720.5 µs → 760.9 µs (+5.6%) 2.23 ms → 2.11 ms (-5.1%)
redb-strict 2681 ops/s → 2681 ops/s (-0.0%) 118.6 µs → 118.0 µs (-0.5%) 205.1 µs → 203.2 µs (-0.9%) 412.0 µs → 449.1 µs (+9.0%)
sqlite-strict 132457 ops/s → 130276 ops/s (-1.6%) 7.7 µs → 7.7 µs (+0.4%) 10.1 µs → 10.2 µs (+1.1%) 11.9 µs → 13.3 µs (+12.3%) ⚠️

ycsb-b

Mode Throughput p50 p95 p99
chisel-mem 262270 ops/s → 265321 ops/s (+1.2%) 1.6 µs → 1.6 µs (-3.1%) 44.8 µs → 44.7 µs (-0.3%) 48.9 µs → 48.5 µs (-0.8%)
chisel-strict 22039 ops/s → 22120 ops/s (+0.4%) 3.7 µs → 3.3 µs (-10.7%) 260.9 µs → 259.8 µs (-0.4%) 653.0 µs → 632.1 µs (-3.2%)
redb-strict 27126 ops/s → 27158 ops/s (+0.1%) 3.0 µs → 3.1 µs (+1.7%) 118.2 µs → 119.4 µs (+1.0%) 181.1 µs → 188.0 µs (+3.8%)
sqlite-strict 161182 ops/s → 158819 ops/s (-1.5%) 6.3 µs → 6.4 µs (+1.7%) 8.4 µs → 8.5 µs (+1.2%) 10.6 µs → 10.8 µs (+1.8%)
Generated by chisel-bench-diff at 2026-07-01T17:12:35Z. Compares PR HEAD against main. Never blocks merge — signal, not gate. Thresholds: throughput 5%, p50 5%, p95 10%, p99 10%.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant