refactor(architecture): ADR-010 — pure protocol crate (alktty template)
Structural decision (OQ-09 resolved): alkgit follows the alktty/ alktunnels template — a single published protocol crate on alkcall channels, no binary, no front doors. - ADR-010 supersedes ADR-001 (crate decomposition) and ADR-006 (http router factory); both marked Superseded - Single crate at repo root: Cargo.toml with gix feature (default-on backend implementations; wire layer compiles without it — gix-hash always-on with sha1 per the compile-time-rejected invariant), crates/ workspace deleted, src/lib.rs stub in place - doors.md replaces http.md/ssh.md/alkgitd.md: alkhttp git-feature sequencing (after first publish), alkssh requirement (fixed-grammar exec dispatch), native alk/git path, downstream assembly - backend.md replaces storage.md: GitRegistry/GitRefs/GitPackGen/ GitPackIngest traits (ingest validates, refs commits — single CAS home), gix feature encodes POC-2 prerequisites - transport.md reframed for the single crate; backend traits replace hook traits in the public API - OQ-09 resolved (all five sub-decisions in ADR-010), OQ-01 resolved (subsumed), OQ-03 narrowed to publish-freeze, OQ-08 narrowed to registry identity + vault placement, OQ-07 rescoped to the gix feature's registry impl - vision.md v2: single-binary/monorepo framing corrected as init-agent artifact; POC checklist marked complete - AGENTS.md + .opencode agent specs updated to the new shape Verification: cargo build (default + no-default-features), cargo test --all-features, clippy --all-features -D warnings, fmt --check all pass. Third review round: zero critical, all warnings/suggestions addressed (GitPackGen signature amended in ADR-004, stale anchors fixed, ADR-006 body tense normalized, CAS split stated, vision residuals cleaned).
This commit is contained in:
1 parent
de922253a4
commit
86bf5a0cf0
37 files changed
+730
-947
No files matched your search
@@ -0,0 +1,103 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-09-21
|
||||
---
|
||||
|
||||
# Backend traits: the storage seam
|
||||
|
||||
## What this is
|
||||
|
||||
The payload side of the protocol crate: the traits a service deployer
|
||||
implements (or consumes via the feature-gated gix implementation) so the
|
||||
git protocol can talk to storage. Per ADR-010 this mirrors alktty's
|
||||
`TtyBackend` pattern — traits in-crate, real implementation behind a
|
||||
feature. Unlike alktunnels (no backend trait), git needs the seam: pack
|
||||
generation/ingestion is too heavy to hard-wire.
|
||||
|
||||
## The trait family (ADR-010 sub-decision 4)
|
||||
|
||||
Four traits, kept small and orthogonal — the protocol crate never sees
|
||||
gix types:
|
||||
|
||||
1. **`GitRegistry`** — repo id → (storage root, visibility, ACL scope).
|
||||
The authoritative mapping (ADR-008); resolution failure is
|
||||
indistinguishable from authorization failure (ADR-007). Metadata holds
|
||||
vault references, never secrets.
|
||||
2. **`GitRefs`** — listing for advertisement (refs + peeled tags + symref
|
||||
targets, the ls-refs response data) and ref transactions (CAS apply
|
||||
for receive-pack, name validation per git ref rules + reserved-
|
||||
namespace deny-list).
|
||||
3. **`GitPackGen`** — (repo, wants, haves, limits) → streaming pack
|
||||
(`io::Write` consumer). Negotiation-agnostic. Missing objects abort
|
||||
with an error, never a broken pack (ADR-004).
|
||||
4. **`GitPackIngest`** — client pack stream → indexed pack + fsck/
|
||||
connectivity report. It *prepares* the validated ref updates; the
|
||||
transaction itself is applied by `GitRefs` (single CAS home — ingest
|
||||
validates, refs commits). Budgeted (ADR-009 max pack size);
|
||||
blocking-thread friendly.
|
||||
|
||||
Minimal-vs-full was the open sub-question; resolved as **full family** —
|
||||
the four traits are each one or two methods plus types, and collapsing
|
||||
them (e.g. refs into the registry) would force one impl block per
|
||||
downstream where independent seams are cheaper to satisfy. The `gix`
|
||||
feature implements all four; a downstream with its own object store
|
||||
implements 3–4 and reuses 1–2, or none of it.
|
||||
|
||||
## The gix feature (default on)
|
||||
|
||||
- `alkgit = { default-features = true }` — wire layer + gix backend;
|
||||
`default-features = false` — wire/protocol layer only (an embedder
|
||||
brings its own backend). Hash: `sha1` pinned (the compile-time-rejected
|
||||
invariant from `docs/research/gitoxide.md`); `sha256` passthrough
|
||||
feature (OQ-05 policy unchanged).
|
||||
- Encodes the POC-2 prerequisites by construction: odb handle sharing
|
||||
(`Arc<Store>` shared, per-session handles, `prevent_pack_unload()` +
|
||||
`ignore_replacements = true`), generation on blocking threads,
|
||||
O(counts) memory, missing-objects abort.
|
||||
- Received-pack ingestion via `gix-pack::data::input` (`streaming-input`)
|
||||
+ `gix-fsck` + `gix-ref` transactions (ADR-004). Validation against
|
||||
real `git push` is OQ-04.
|
||||
|
||||
## Concurrency model
|
||||
|
||||
- `gix` structures: `parking_lot` short-held locks; per-session handles
|
||||
moved into `spawn_blocking` tasks (POC-2's shape: store shared, handle
|
||||
per session, generation on blocking threads).
|
||||
- Poisoned locks: `unwrap_or_else(|e| e.into_inner())` (convention 2).
|
||||
- The traits are `Send + Sync` object-safe; impls run under the
|
||||
adapter's tokio context.
|
||||
|
||||
## Public API surface
|
||||
|
||||
Crate-root re-exports (the alktty pattern): backend traits + types,
|
||||
`GitAdapter`/`register_openable` (producer), `GitSession` (consumer),
|
||||
substrate types, `Limits`, protocol error enums; `gix`-feature types
|
||||
(`GixBackend`-family) exported under the feature. The embedder-facing
|
||||
freeze point remains OQ-03 (narrowed: it is now this crate's own publish,
|
||||
not a multi-crate freeze).
|
||||
|
||||
## Design Decisions
|
||||
|
||||
| ADR | Decision | Summary |
|
||||
|---|---|---|
|
||||
| [004](decisions/004-pack-pipeline.md) | Pack pipeline | `data::output` gen / `data::input` ingestion |
|
||||
| [007](decisions/007-acl-before-advertisement.md) | ACL first | registry returns rule inputs |
|
||||
| [008](decisions/008-registry-resolved-repo-identity.md) | Repo identity | wire names are registry ids |
|
||||
| [009](decisions/009-bounded-resources-budget.md) | Budgets | limits flow into gen/ingest |
|
||||
| [010](decisions/010-pure-protocol-crate.md) | Pure protocol crate | traits in-crate, gix behind a feature |
|
||||
|
||||
## Open Questions
|
||||
|
||||
- **OQ-06**: registry backing store (deferred(scope) — the trait is what
|
||||
matters; the gix feature can ship a config-file/classic-on-disk impl,
|
||||
and richer backing is downstream's choice).
|
||||
- **OQ-04**: pack ingestion validation (deferred(unclear)).
|
||||
- **OQ-05**: sha256 policy (deferred(scope)).
|
||||
|
||||
## References
|
||||
|
||||
- `docs/research/gitoxide.md` (API contract notes — normative for the
|
||||
gix impl)
|
||||
- `docs/research/poc2-findings.md` (generation pipeline + prerequisites)
|
||||
- alktty `backend.rs`/`local` module (the trait + feature template)
|
||||
- ADR-010 (the structural decision)
|
||||
Reference in new issue
Block a user