Files
glm-5.3-flash abf8c5ae9c docs(architecture): ADR-010/011 — I/O seams, GC-state home, vocabulary; pre-decomposition consistency round
ADR-010 (new): the Backend trait's I/O seams pinned before any code —
'get' returns a crate-internal read cursor (kv engines materialize;
'local' pread loop; pg-lo lo_get windows), 'put' has two named forms
(whole-value kv / staged-put large); GC state is store-core-owned via
a crate-internal contract-tested engine-state seam on the SQL-backed
engines (backends never learn liveness — ADR-005 verbatim); the store
core holds the joint entry+pin transaction (corrects ADR-009 §2's
ownership statement); kv-tier fleet-validity rule added (mirror of
ADR-008 §3); ops pin-token TTL race resolved (the token IS the pin;
renewal rides have/re-put; pause-past-TTL falls to delete-then-recover);
feature graph pinned (pg-lo does not imply postgres).

ADR-011 (new): vocabulary pinned — tier (contract, exactly two) vs
engine (concrete impl, exactly five); store instance / node / fleet
split (fleet = pool-sharing, not node count — fixes requirements.md's
self-contradiction with REQ-2); mem demoted from 'backend'/'testing
tier' to the kv tier's third engine (contract-reference engine);
fs tier renamed 'large' including the feature name (last free moment
before code exists); constructor modes pinned (dual-tier default,
kv-only, mem-only) plus the composite fleet-validity predicate.

Consistency round across all specs and ADR-003/004/007/008/009: stale
pg-lo passages resolved per ADR-009's supersession; ADR-008 owner
'node id' → store-instance id; threshold wording corrected (conservative
edge, not midpoint, of the 128-256 KiB crossover zone); SweepReport
shape specced; mem classification unified; 008/009 ADR files renamed to
match the tier rename; README deferral-policy recap aligned (third
category = decided-but-sequenced work, not a parking kind); POC crate
list completed.

Verification: two independent architecture review rounds (the first
found 4 criticals — unpinned trait I/O shapes, missing fleet-state
seam, node/fleet self-contradiction, pin-token/TTL conflict — all
resolved; final round: zero criticals); all markdown links resolve;
ADR tables complete (11 ADRs).
2026-10-03 05:55:20 +00:00

4.5 KiB

status, last_updated
status last_updated
draft 2026-10-01

Hashing and keys

What this is

The content-address layer: the canonical hash derivation every entry is keyed under, the tolerated legacy algorithm, the typed Key/Digest surface the store API speaks, and the physical byte encoding of keys inside backends. This is the crate's one-way door: key byte layouts are persisted in backend rows and filenames, survive digest-layer evolution, and must precede any wire consumer (AGENTS convention 5; phase-0 OQ-BL-03 residual).

The hash family

Three hash-policy classes (ADR-002 §Decision; resolved from OQ-BL-03 after the "multi-hash" premise dissolved — nothing forces BLAKE3 once iroh-blobs' inheritance is rejected):

  1. Canonical — git-blob-sha-256: the git oid derivation H("blob <len>\0" + content) with SHA-256, uncompressed content. Chosen because alkgit forces git's derivation by protocol definition, and every other consumer (workspaces, appfile) sees addresses, not algorithms — so one algorithm domain makes the pool one address space and cross-consumer dedup free by construction (ADR-005).
  2. Tolerated legacy — git-blob-sha-1: existing git repositories are overwhelmingly SHA-1; the store accepts them under the same preamble discipline. Git's own collision-hardened SHA-1 threat model is inherited verbatim; the store adds nothing and weakens nothing.
  3. Not present — BLAKE3: demoted out of the crate entirely. If a chunk-tree transfer encoding is ever adopted, it is a new decision at a new layer (ADR-006); its verified whole-contents would register as ordinary git-blob-sha-256 entries.

Security posture: one algorithm across consumers is safe here — SHA-256 has no practical cross-protocol ambiguity at these input shapes, and the preamble domain-separates the derivation (ADR-002 §Consequences).

Key encoding (the one-way door)

Physical key bytes inside backends (POC #1 finding 5, validated in the interop test where an oid produced by external git addresses the same pool entry the store puts):

  • Algorithm identity is part of the key itself — a per-store single-algorithm configuration cannot express git-sha-256 and git-sha-1 coexisting in one flat pool, which the external-oid test proves is required.
  • Fixed-length, enum-tagged: 1 algorithm byte + digest bytes (32 for sha-256, 20 for sha-1). The POC's extra "kind" tag byte is dropped — there is exactly one key kind. Algorithm bytes are assigned from a single registry constant in ADR-002 so external producers can compute them.
  • Sort stability: fixed-length enum-tagged keys sort cleanly in a total order — required for the sweep's live-set diffs (list() walks are plain range scans; ADR-005).
  • Opaque to backends: the Backend trait speaks opaque byte keys (ADR-003); only the store core constructs and interprets typed keys.

The Key/Digest surface (WHAT the API exposes)

  • Digest — an algorithm + digest pair; construction via the canonical derivation from content (known length) or from a pre-computed pair (interop: from_git_oid_hex shape validated in POC #1 finding 4).
  • Key — the typed wrapper; as_bytes() / from_bytes() are the only conversions across the backend boundary. Malformed key bytes (truncated, unknown algorithm) are rejects, never guesses — the POC's length-checking test is the standard.
  • Verification semantics ride the whole-blob posture (ADR-006): put and get paths hash-check against the canonical derivation; there is no per-range hash relationship under this derivation (preamble includes the length), which is the constraint ADR-006 documents rather than works around.

Design Decisions

ADR Decision Summary
002 Canonical hash + key encoding three-tier hash policy; algorithm-in-key byte layout; the declared wire-format ADR

Open Questions

None owned by this document. The interop surface alkgit ultimately needs (oid formats, hex/binary conventions at its boundary) is OQ-07 — alkgit's question, not a key-encoding question.

References

  • docs/research/phase-0.md OQ-BL-03 (resolution + key-encoding mechanics)
  • docs/research/poc-trait-dispatch-findings.md findings 4/5 (byte-exact git CLI validation; tagged-key coexistence)
  • gix-odb (/workspace/gitoxide/gix-odb) — the consumer-side baseline for object reads/writes
  • ADR-002; ADR-003 (opaque byte keys at the backend boundary); ADR-006 (what verification is possible under this derivation)