alkgit-substrate 0.1.0

The shipped alkgit backend composition: the reactive alkstore + alkblobs backend implementing alkgit's backend seam — reactive halves, cached read provider, engine twins, migrations, GC wiring, and the LFS surface (ADR-019/025)
Documentation
# Changelog

All notable changes to this crate are documented here. The format is
based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
this crate adheres to [Semantic Versioning](https://semver.org/).

## [0.1.0] - 2026-10-24

The founding entry — the shipped composition's first release.
`alkgit-substrate` is the shipped backend composition for the
[`alkgit`](https://crates.io/crates/alkgit) protocol core: the complete
ADR-019 composition implementing alkgit's five-trait backend seam over
the alkstore + alkblobs substrate — reactive by default, engine-twinned
(sqlite / postgres / in-memory), schema-migrated, GC-wired, and carrying
the LFS surface (the `lfs` feature, default-on). The wire layer, the
backend traits, and the seam types are the core crate's; this crate
implements the storage beneath them. It carries no binary and no front
doors — the alkhttp `git`/`lfs` features and alkssh are family
infrastructure; a downstream app embeds the core (which serves the
wire), composes this crate's backends underneath, and brings its own
door.

The posture is **honest advertisement** (ADR-003 in the core's doc set
carries the family rule): public API surface is the crate-root
re-export list pinned in substrate.md §public API (the OQ-03
inventory), unimplemented surface declines loudly rather than serving
half-shapes, and the composition's postures are stated where a reader
needs them — the reactive halves are wired with no opt-out
(ADR-019 §5), receive-pack's pin bridge and mutation-marker machinery
are composition-internal (never re-exported), and the LFS lock server
(`lfs.locks`) is not served (the deferred OQ-21; its composition
validation is evidenced, the build deferred on client need).

### Added

**Wave 6 — the substrate foundation:**

- The crate scaffold and the feature placement (ADR-025's two-member
  workspace): `sqlite` (default-on, the co-tenant registry/ref twin +
  connection driver), `postgres` (optional, the fleet twin), `lfs`
  (default-on, the ADR-022 surface's placement home).
- The registry adapter family: the trait pair
  (`RegistryBackend`/`RegistryRead`/`RegistryWrite`), the in-memory
  default adapter (`InMemoryRegistry`, stamp-free per ADR-024 §6), the
  coherence contract's cached read provider (`CachedRegistryProvider` —
  whole-table snapshot, wake/reconcile invalidation), and the core's
  `GitRegistry`/`GitRegistryStore` implemented by all three engines
  (the `HEAD_SEED_TARGET` both twins seed with).
- Schema migrations (ADR-024): one alkgit-owned stamp table versioning
  the co-tenant schema as a unit; ordered hand-written monomorphic step
  sets per engine; construction-run with loud failure (a half-migrated
  store refuses service); concurrent-open-safe; additive-first. The
  initial co-tenant schema ships in step 1 (the record/ref/marker rows,
  the `registry_seq` singleton, the LFS rows — ADR-024 §5).
- The refs row table: the CAS-semantics reference impl
  (`InMemoryRefTable`), the sqlite row-CAS twin (`SqliteRefTable` —
  every `apply_updates` call one `BEGIN IMMEDIATE` transaction), the
  postgres row-CAS twin (wave 7), the shared CAS kernel, table-layer
  name validation (the core's deny-list reused; invalid name →
  `funny refname` per-ref denial), and the unborn-HEAD symref row
  shape. The twins carry the write-counter wrap (`VersionedRefTable`)
  themselves — the liveness discipline's epoch half.
- The reactive halves (ADR-019 §5, wired — no opt-out): `Reactor` +
  `AnnouncingRegistry` (announce publish/notify/enqueue, fail-soft
  each), the wake runner, the stream consumer (cursor model +
  per-seq idempotency), and the reconcile sweep closing the
  crash-window. The channel names (`WAKE_CHANNEL`, `EVENTS_STREAM`,
  `MAINTENANCE_QUEUE`, `MAINTENANCE_LOCK`) carry the alkstore streams
  contract.

**Wave 7 — objects, packs, GC:**

- The object front (`ObjectFront`): the alkblobs git-object-family
  wiring (`loose_form`/`oid_key`/`key_to_oid`) and the sync
  `gix_object::Find`/`Exists` + `gix_pack::Find` front with per-session
  `SessionFind` views and the one sync/async bridge
  (`block_on` from blocking pipeline tasks, `block_in_place` in async
  contexts).
- The real `GitPackGen` (`PackGen`): ADR-004's pipeline over the real
  Find — the two-stage closure, the missing-objects abort, ADR-014 §5's
  ack predicate as the real `common_haves` — in both serving shapes
  (direct streaming; through-store ranged windows with mid-flight
  digest verification over the shared `PackCache`).
- The GC liveness source (`RefClosure` — the full-graph walk over the
  object front) with the refs-rows fingerprint seam (`RefRows`) and the
  memoization discipline (durable fingerprint + write-counter
  `VersionedRefTable`, bump-after-commit).
- The maintenance chain's consumer side (`MaintenanceChain`): the
  `@every` sweep schedule registration, the supervised scheduler and
  worker (claim loop, leader-TTL lock, `PackHousekeeping` release
  path), the wake runner's restart, and the reconcile tick's driving
  (`MaintenanceOpts`).
- The postgres refs row-CAS twin (the wave-7 N-c rider — the same
  one-transaction CAS, the engine-swapped shape, advisory-lock
  serialization).

**Wave 8 — receive-pack ingestion and the composition entry:**

- `GitPackIngest` (`PackIngest`): ADR-020 §2's ingestion composition —
  the budgeted host working area's index (thin bases through the
  substrate Find), unpack-to-loose under the decompressed-size cap with
  guards riding the pin-bridge custody seam, the full-graph
  connectivity walk from the pushed tips, and the working-area discard
  (every failure the `unpack ng` leg).
- The composition entry (`SubstrateAssembly`): one fallible constructor
  per assembly shape — `mem` (the completeness shape taking the
  substrate engine handles), `sqlite` (the default single-host shape),
  `postgres` (the fleet/durable-shared shape) — wiring the complete
  backend per shape (registry pair + cached provider + reactor, the
  wrapped refs table, the object front, both pack serving shapes, the
  ingest, both liveness registrations, the maintenance chain).
  `AssemblyOptions` and `PackServing` carry the knobs.
- End-to-end evidence against real `git` (push / clone / fetch over
  every assembly shape) and the replication loop end-to-end (the
  POC-X gates re-landed through the published serving machines).

**Wave 9 — LFS:**

- The pointer-lifecycle row store (`LfsRows`/`LfsRow`,
  `InMemoryLfsRows`, `SqliteLfsRows`, `PgLfsRows` under the `lfs`
  feature; ADR-022 §4): one row per `(repo_id, oid)` reference, the
  refcount column's cross-reference re-protection contract, and the
  repo-deletion removal legs riding the record-removal transactions
  unconditionally. The epoch wrapper (`VersionedLfsRows`,
  bump-after-commit) is carried by the twin assemblies themselves and
  wired through the entry (no double wrap).
- The LFS media liveness source (`LfsMedia`/`lfs_media_key`) wired as
  the composition's second registration (default — the fail-safe
  posture, ADR-022 §6): sweep re-protects media while any row
  references it, orphans reclaim, repo-deletion media follows the
  machinery for free.
- The batch/transfer adapter (`LfsAdapter`, `LfsAdapterConfig`, the
  `LfsGrantProvider`, the DTO family): the formable-key existence over
  the ops control plane (`blobs/stat` through the DirectOps binding),
  the pre-keyed put (mislabel refused, zero residue), and the download
  byte path — per-window slice-digest verification with the
  **whole-span oid check** (the resolved span budgeted by
  `max_object_bytes`; F-S3's end-to-end oid conclusion as amended into
  ADR-022 §2). The wired ownership provider is a required constructor
  argument (the alkcall ADR-048 posture; the static fallback is
  unreachable and battery-pinned so).
- End-to-end evidence against real `git-lfs` (round trips across the
  engine matrix, token hand-off, auth refusals, range semantics, GC
  sweep rows).

**Wave 10 — validation and release readiness:**

- The test-harness consolidation (one testutil home; zero public-API
  change) and the per-piece parity class closed: the LFS twins carry
  the `VersionedLfsRows` wrap (the refs twins' posture), the
  through-store default-cache constructor documented as deliberate
  per-piece probe surface, and the test-only `mem_registry` name
  removed from the inventory (the entry's mem shape is the surface).
- The test-evidence rows: the big-media/ceiling door paths
  (`TooLarge`→413 with the ceiling-edge partial span, the transfer-body
  budget refusing before the adapter, the unrouted and doubled route
  forms), the anonymous-refusal row (synthesized `anon` PUT refused at
  the adapter — push always authenticated), the live-pg fleet battery
  (the confirm-immediately custody posture proven slot-neutral), and
  the `FleetTable` materialization exercised at the assembly rows.
- The feature-matrix hygiene one-pass: the off-matrix combos
  (engine-less, lfs-alone, postgres-alone) now compile
  warning-free alongside the documented matrix.

### Notes

- `lfs` is default-on but the composition is fully usable without
  databases: the mem assembly (in-memory engines) runs the complete
  reactive/GC machinery ephemeral.
- Object/refs rows are keyed sha1 (the pinned default, OQ-05); the
  composition keys LFS media under the identity family's sha256
  derivation (the LFS oid — ADR-022 §1) as the protocol requires.

[0.1.0]: https://git.alk.dev/alkdev/alkgit/releases/tag/alkgit-substrate-v0.1.0