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).
123 lines
6.2 KiB
Markdown
123 lines
6.2 KiB
Markdown
---
|
|
status: draft
|
|
last_updated: 2026-10-03 (vocabulary pinned by ADR-011 — tiers/engines/instances/fleet; large tier renamed `large`)
|
|
---
|
|
|
|
# Requirements
|
|
|
|
The deployment-relevant facts each use case forces on this crate.
|
|
Specs and ADRs reference these by ID (REQ-n); a future session must be
|
|
able to read this document and never re-derive a requirement from
|
|
conversation or vision prose. **This document is the anchor: when a
|
|
consumer fact changes, it changes here first, with a dated note, and
|
|
the ADRs re-derive from it.**
|
|
|
|
## Vocabulary (defined once; used everywhere — ADR-011 is the decision behind this section)
|
|
|
|
- **Tier** — one contract (a `Backend` trait implementation boundary)
|
|
serving one routing class of the pool. Exactly two tiers: **kv**
|
|
(small content) and **large** (over the size-threshold content;
|
|
the tier formerly named `fs` — renamed in ADR-011 because the tier's
|
|
routing criterion is length, and half its engines are not
|
|
filesystems). "Backend" names the same thing at a different
|
|
altitude (the tier as shipped including its engine set); "two
|
|
backends" (ADR-004) reads forever as "two tiers".
|
|
- **Engine** — a concrete storage implementation of one tier's
|
|
contract. Five ship: the kv tier's `sqlite` (default),
|
|
`postgres` (feature `postgres`), and `mem` (ephemeral; feature
|
|
`mem`; the contract-reference engine; ADR-003); the large tier's
|
|
`local` (default; ADR-003) and `pg-lo` (ADR-009).
|
|
- **Pool** — the flat content-addressed namespace of one deployment
|
|
(`hash → bytes` everywhere; ADR-005).
|
|
- **Store instance** — one running instantiation of the store facade
|
|
(one engine set — one or two engines per the constructor mode,
|
|
ADR-011 §4 — plus dispatch and GC state). The **GC arbitration
|
|
domain** for single-instance topologies (ADR-005's pins, liveness
|
|
locks, and delete windows live inside one); the pin-row owner id
|
|
under fleet engines (ADR-008/010 — ADR-008 wrote "node id" before
|
|
this split existed; a store instance is what owns pins).
|
|
- **Node** — one running *process* (an embedder's binary). **A node
|
|
hosts one or more store instances** — this fixes the prior
|
|
definition's collapse (which REQ-2's phrasing contradicted). Node
|
|
is the process/ops unit: alkcall connections, ACL grants, sweep
|
|
cadence, and deployment identity attach to nodes.
|
|
- **Fleet** — **two or more store instances over one shared pool**
|
|
(via a shared SQL engine). Defined by pool-sharing, not node count:
|
|
two instances in one process over one postgres pool are a fleet;
|
|
two processes on two sqlite files are two pools, never a fleet. A
|
|
fleet is the only topology in which cross-instance GC and
|
|
large-tier locality questions exist (ADR-008).
|
|
- **Deployment** — one operator's whole system: typically one fleet
|
|
or one node; consumer tables, op registrations, and sweep cadence
|
|
are deployment choices.
|
|
|
|
## The use cases and their requirements
|
|
|
|
### UC-1: Self-hosted git serving (gitea-replacement scale)
|
|
|
|
Git repos for a user/team on one machine. Small-object regime dominated
|
|
by loose objects in the kv tier; packs and large artifacts (git-lfs
|
|
shape) on the large tier.
|
|
|
|
- **REQ-1 (traces: ADR-007, POC #3 A4)** — single-machine economics:
|
|
sqlite is the default kv engine; single-writer WAL ceiling (~1.2k
|
|
objects/s under contention) is comfortably above single-node push
|
|
rates. **Zero-ops is a requirement**: no daemon beyond the node
|
|
process itself.
|
|
|
|
### UC-2: Distributed git with replicator nodes hosting repos for many users
|
|
|
|
The p2p/OSS sketch (phase-0 §p2p shape): replicators are push/clone
|
|
endpoints serving many concurrent users; gossip-style sync between
|
|
replicators; ACL/ownership above (alkcall layer).
|
|
|
|
- **REQ-2 (traces: ADR-007, ADR-008)** — **a replicator node may run
|
|
multiple store instances (a fleet) sharing one pool** via a shared
|
|
postgres kv engine, including serving large (>threshold) pool
|
|
content from that fleet. This is stated as a requirement, dated
|
|
2026-10-03 (recording a planning fact from the use case's origin
|
|
discussion; it predates all POCs and architecture docs, recorded
|
|
here on the operator's authority as the use case's stated shape).
|
|
Consequences are derived in ADR-008: fleet GC (DB-backed pins,
|
|
advisory-locked sweeper, SQL delete arbitration), the large-tier
|
|
engine concept with its locality contract, and the pg-lo engine
|
|
(POC #7 — **passed** 2026-10-03, admitted as a shipped
|
|
engine by ADR-009: a fleet node can consolidate on postgres-only).
|
|
- **REQ-3 (traces: ADR-007, POC #5 B3/B4)** — concurrency scale-out:
|
|
the fleet's hub-class nodes need put throughput that *increases*
|
|
under concurrency (pg: near-linear to ~37k puts/s at 24 conns);
|
|
sqlite's WAL ceiling (~1.2k/s, latency-climbs-unbounded) bounds
|
|
single-node sustained write pressure regardless of client count.
|
|
This is the measured basis for the per-node engine split.
|
|
|
|
### UC-3: Agent workspaces (many agents, near-identical content)
|
|
|
|
Agents working simultaneously in mostly-identical workspaces, each
|
|
making small edits; a shared pool dedups by construction; per-workspace
|
|
path→hash manifests above.
|
|
|
|
- **REQ-4 (traces: ADR-005, ADR-002)** — pooling and one address space
|
|
across workspaces; dedup must be structural (not configured). Small
|
|
edits mean the small-blob regime dominates: sqlite-class kv
|
|
performance is what matters; the large tier is hit rarely (large
|
|
workspace artifacts).
|
|
|
|
## What this document is not
|
|
|
|
- **Not consumer architecture**: how alkgit maps refs/manifests onto
|
|
the store remains OQ-07 (externally-owned); how alkfs shapes
|
|
workspaces remains OQ-08. This document records what each use case
|
|
*forces on this crate*, not what each consumer *is*.
|
|
- **Not a requirements-change process substitute**: a new or changed
|
|
REQ arrives here with a dated note and owner; ADRs that depended on
|
|
the old fact state their reopen conditions and reopen when this
|
|
file changes.
|
|
|
|
## Decision trace
|
|
|
|
| REQ | Introduced | Source | ADRs |
|
|
|---|---|---|---|
|
|
| REQ-1 | 2026-10-03 (fact: phase-0 §deployment posture) | POC #3 A4 | ADR-007 |
|
|
| REQ-2 | 2026-10-03 (fact: use case origin discussion, pre-POC) | user/planning record | ADR-007, ADR-008 |
|
|
| REQ-3 | 2026-10-03 (fact: phase-0 §deployment posture) | POC #5 B3/B4 | ADR-007 |
|
|
| REQ-4 | 2026-10-03 (fact: phase-0 §vision) | POC #1, ADR-002 | ADR-002, ADR-005 | |