- C-1 verified end to end: the one-way door's bytes read against ADR-018 line by line and exact (registry 0x03/0x04, preimage-identity derivation, fleet threading per §Decision 7); interop green against the real git CLI - C-2 verified: ADR-019's mint-boundary cap + the typed MINT_REFUSED answer; the attack shape on paper; "not silence" exceeded - C-3/C-4 verified as chartered (busy_timeout=5000 pinned; KeyBytes) - review-002 stamped closed with disposition pointers; the prototype branch poc-o-git-objects deleted after parity confirmation - Minor inline fixes: the CHANGELOG [0.1.0] entry absorbs wave 13 (verified counts 218 default / 473 all-features, ADR-018/019 refs), the README names the git-object family honestly - Stamps: the plan's wave-13 row + frontmatter completed, AGENTS.md now publish-ready Verification: cargo test default 155+54+7+2; cargo test --all-features vs the live pglo-poc harness 338+125+7+3; both clippy variants -D warnings clean; cargo fmt --check clean; cargo doc --no-deps clean; fuzz corpus replay 7/7; cargo publish --dry-run --allow-dirty green (94 files).
9.3 KiB
Changelog
All notable changes to this crate are documented here. The format is based on Keep a Changelog, and this crate adheres to Semantic Versioning.
0.1.0 - 2026-10-18
Initial release of the alkblobs family: content-addressed blob storage with one canonical content hash, tiered pluggable engines, GC built in, and the network ops surface riding alkcall as a feature.
The crate is the store layer only — no transport, no wire protocol
in-core (ADR-001). Store never learns where bytes came from;
transport, framing, and serialization live above the facade (in the
feature-gated ops module) or nowhere. Keyed under the git-family
oid derivation ("blob <len>\0" + content) — SHA-256 canonically,
SHA-1 tolerated for existing repos (ADR-002) — with the git-object
derivation family for git's non-blob objects (ADR-018) — and
addressed through an algorithm-tagged Key encoding that is the
crate's one-way door: parsers validate and reject, never guess.
Added
- The
Storefacade —put/get/stat/read_range/has/list, with the write verifying the stored artifact as a whole before it publishes and verification-on-get on the kv tier's materialized reads (the windows themselves carry no check;read_rangereturns the ADR-006 slice digest for the caller to carry out-of-band) (ADR-006). Known-length and unknown-length puts share one signature (the unknown-length path buffers past the threshold in memory, then continues into the large tier's stage — a non-restartable source is a normal case, never an error). Nonew: the store is built through named constructors declaring one of three ADR-pinned modes —mem_only,kv_only, ordual_tier— with size-threshold dispatch the pure function routing between a store's kv tier and its large tier (default threshold 128 KiB, constructor-tunable; ADR-003). - Pins and batches — pin-before-publish: an entry cannot appear in
a sweep's view without already carrying its pin. The put's RAII
Pinguard releases on drop;Batchgroups a multi-put write (manifest writes are the shape) under one batch-scoped pin group, committed or dropped together (ADR-005). - The GC protocol —
sweep(mark phase / delete window / commit phase, aborts report as data with nothing deleted), directdelete, and liveness registration in two forms (ADR-005, ADR-008): the in-process callback and, for fleets, the named liveness table the constructor declares. - Five engines over two tiers (ADR-003, ADR-007, ADR-009) —
features gate engines, each pulling only its own driver cluster
(ADR-013); tiers are constructor composition, not features:
- kv
sqlite(featuresqlite, default-on): WAL +synchronous=NORMAL, prepared statements, read paths tolerate the no-tables-yet database; the durable single-host tier. - kv
postgres(featurepostgres): pooled connections, prepared statements,ON CONFLICT DO NOTHINGCAS — the fleet host. - kv
mem(featuremem, default-on): dependency-free ephemeral implementation; never a production story, never fleet-valid — the contract-reference engine every other engine's conformance tests mirror. - large
local(ungated, dependency-free): flat sharded files, stage-then-commit-rename, pread reads; the publish is fsync- durable and no-replace (ADR-015). - large
pg-lo(featurepg-lo): postgres Large Objects — descriptorless windowed reads, LO creation transactional (zero crash orphans), staged into a held transaction; one large-object consumer per database is the co-tenancy constraint theorphan_reap_permitteddeclaration carries (ADR-016).
- kv
- Fleet GC — DB-backed pins, sweep-window rows, and the sweep
lease host on the fleet's kv-tier engine (postgres): the lease is
an atomic test-and-set advisory lock (at most one sweep in flight
per pool; ADR-008, ADR-013); deletes are windowed and
re-arbitrated at execution so the sweep-vs-put race resolves
without data loss; constructors declare
fleet: trueexplicitly (never inferred) against the composite fleet-validity predicate (ADR-012). - The
opsmodule (featureops, default-off) — the network surface riding alkcall (ADR-001):blobs/fetch(the binary data-planeSubop, ranged-fetch addressing over the fanout registry) andblobs/put(the verified offer/stream/commitSinkop), plus the JSON control-op family (stat,have,delete) and the pin-token layer: the token is a CSPRNG capability over the pin, minted custodial (non-fleet) or renewable (fleet), renewed and confirmed through the store core's renewal access — the one crate-internal seam the module consumes. Authorization rides alkcall'sAccessControlseam — no in-band invented scheme (ADR-014, ADR-017). - Fuzzing —
fuzz/, a sidecar workspace excluded from the root workspace, pinning nightly inside itself: two libFuzzer targets over the parse surfaces (key_encodingover the key/algorithm parser cluster,ops_ingressover the ranged-fetch bounds ingress and token decode), and a stable-toolchain companion crate (fuzz/shared) replaying the committed corpora as a plaincargo testgate. - The git-object derivation family — the hash registry extends
with
0x03(git-object-sha-1) and0x04(git-object-sha-256) (ADR-018): the preimage-identity derivation over git's own loose-object form (<type> <len>\0+ content stored as the value), so the digest is byte-identical to git's oid of the object — trees, commits, and tags included — with verification-on-get, dedup, and external-oid addressing intact. Lands as the publicput_git_object(algorithm, len, stream)put seam (known-length only, family members only), threaded through the fleet put paths uniformly, and CLI-validated byte-exact against realgit hash-object. - The token registry's admission posture (ADR-019) — an
admission cap at the mint boundary
(
OpsConfig::token_registry_max_entries, default 65,536 entries,usize::MAXthe uncapped form), refusing — never evicting — with the newError::RegistryFullrefusal member and theblobs/putdeclared answerMINT_REFUSED(the committed digest in the details; no token, no custody taken). Bounds the non-confirming upload loop (unbounded registry growth plus never-expiring custody on a non-fleet store) at the store; the non-fleet custody posture is documented embedder-facing, the fleet TTL named as the safe posture for doors that cannot prove confirm. - Borrowed-key overloads —
Key::key_bytes()returning the fixed-capacityKeyBytes(a stackCopywrapper deref-coercing to&[u8], byte-identical toas_bytes) drops the per-call heap allocation from the serving paths' re-encode sites.
Changed
- sqlite contention posture explicit —
PRAGMA busy_timeout = 5000is set at open as a pinned constant (matching the family's explicit alkstore-sqlite value), joining the durability posture as stated contract: co-tenant assemblies on one sqlite file no longer ride rusqlite's implicit default by coincidence. alkcallbumped to 0.10 (the gateway ownership-seam release; additive for this crate's native-wire use — no code changes).
Verified
- The full verification block against the live harness
(
postgres:16-alpineon localhost:15432): 218 tests pass on the default feature set (mem+sqlite— unit 155, conformance 54, git-interop 7, README examples 2); 473 pass under--all-features— the pg columns run against the live harness (their server-less default is a clean skip); both clippy configurations (--all-targets --all-features,-D warnings),cargo fmt --check, andcargo doc --no-depsare clean; the fuzz corpus-replay gate passes (cargo test --manifest-path fuzz/shared/Cargo.toml, 7/7) — campaigns run viafuzz/run-detached.shperfuzz/README.md.