Files
alkgit/docs/architecture/storage.md
T
glm-5.3-flash 8f73da5d12 docs(architecture): phase 1 bootstrap — specs, 9 ADRs, OQ tracker
Architecture documentation structure per sdd_process phase 1:

- README index (doc table, ADR table, lifecycle), overview with crate
  map, dependency rules, and security invariants
- Component specs: storage, transport, http, ssh, alkgitd (all draft)
- ADRs 001-009: crate decomposition, front-door-blind core, V2-first
  protocol, pack pipeline (data::output generation / data::input
  ingestion), session substrate types, http adapter composition
  (proposed, OQ-01), ACL-before-advertisement, registry-resolved repo
  identity, bounded-resources budgets
- open-questions.md: OQ-01..08 with two deferred(scope), one
  deferred(unclear), door-type definitions, blocker tracker tasks in
  tasks/architecture/
- v1 ssh-door decision recorded: russh terminates wire SSH in alkgitd;
  alkcall channels stay the internal substrate (OQ-03 partially
  resolved)

Two review rounds (fresh-context subagent): 4 critical + 17 warnings
fixed in round one; zero critical + 4 warnings + 5 suggestions fixed in
round two. All ADR/OQ cross-references verified resolving.
2026-09-21 03:55:33 +00:00

117 lines
5.1 KiB
Markdown

---
status: draft
last_updated: 2026-09-21
---
# alkgit-core: Storage
## What it is
The repository storage layer: repo registry, object database wrappers, ref
store, pack generation/ingestion, and access-rule input types. It is
transport-agnostic and front-door-blind (ADR-001): it knows nothing about
pkt-lines, http, or ssh.
## Why this shape
gitoxide provides the primitives (odb, packs, refs, fsck, objects); the
generation-pipeline decision is ADR-004 (POC-2-validated). The crate
exists to (a) wrap gix with a coherent session-safe API (`gix_odb::Cache`
is not `Sync` — the sharing rules are enforced by the API in this crate),
(b) own the registry (ADR-008), and (c) hold the ACL input types the
adapters and alkcall share.
## Components
### Repository registry
- Authoritative (repo id → storage root, visibility, ACL scope) mapping.
- Wire repo names are registry IDs, never paths (ADR-008); resolution
failure is indistinguishable from authorization failure (ADR-007).
- Backing store: **open** — OQ-06. Core defines the trait; alkgitd picks
the backing. Metadata holds no secrets (vault references at most).
- Storage roots are server-configured; the registry maps IDs onto them.
### Repository access (`Repo`)
- Opens a (storage root, hash algo) into an object database + ref store.
- Wraps `gix_odb::Store` sharing: `Arc<Store>` shared across sessions,
per-session handles (`to_handle_arc()` + `prevent_pack_unload()` +
`ignore_replacements = true` — the POC-2 prerequisites). The public API
hands out handles, never the raw `Cache`.
- Ref listing for advertisement: refs + peeled tags + symref targets, the
ls-refs response data.
- Ref transactions: CAS apply for receive-pack (`gix-ref` transaction
module), with name validation (git ref rules + reserved-namespace
deny-list; `docs/research/git-protocol.md` §security notes).
### Pack generation (fetch side)
- Type: (odb handle, wants, haves, limits) → streaming pack (`io::Write`
consumer). Negotiation-agnostic: negotiation produces the boundary sets,
the writer streams them (ADR-004).
- Encodes the POC-2 composition: tip peeling → commit-ancestry walk →
`TreeContents` count → entries → bytes; missing objects abort (never
emit a broken pack); entry statistics surface as metrics.
- Memory profile is O(counts) — the budget model (ADR-009) bounds
aggregate work, not internal buffering.
### Pack ingestion (receive side)
- Client pack stream → indexed pack + fsck/connectivity report + per-ref
CAS application. Uses `gix-pack` streaming-input + `gix-fsck` +
`gix-ref` transactions. Shape is designed (ADR-004); validation against
real `git push` is pending — OQ-04.
- Received pack size is budgeted (ADR-009 max pack size); ingestion runs
on blocking threads like generation.
### Access-rule input types
- The types alkcall `AccessControl::check` consumes for repos: visibility
(public/private), identity-based read/write. Deliberately *input types*:
the evaluation function lives in alkcall (single source of authorization
logic); invocation/wiring happens in the adapters (ADR-007). Core
defines what a repo's rule set looks like.
- v1 scope: repo visibility + identity read/write, nothing richer
(vision §"Primary deployment target").
## Concurrency model
- `Store`/registry structures: `parking_lot` short-held locks (project
convention 3).
- odb handles: per-session, owned, moved into `spawn_blocking` tasks.
- Ref transactions: serialized per-ref by gix-ref's lock files; the
registry mapping's read-mostly synchronization (ArcSwap-class or
equivalent) is part of OQ-06's backing decision.
- Poisoned locks: `unwrap_or_else(|e| e.into_inner())` per convention 2.
## Public API surface (v1)
`lib.rs` re-exports (module structure per convention 14): registry trait +
types, `Repo`/handle types, pack generate/ingest types, ref-transaction
API, ACL input types, error enums (`thiserror`, no panics, no unwrap
outside tests). The embedder-facing freeze point is tracked in OQ-03.
## Design Decisions
| ADR | Decision | Summary |
|---|---|---|
| [001](decisions/001-crate-decomposition.md) | Crate decomposition | core = storage, transport-blind |
| [004](decisions/004-pack-pipeline.md) | Pack pipeline | `data::output` generation, `data::input` streaming ingestion |
| [007](decisions/007-acl-before-advertisement.md) | ACL before advertisement | core supplies rule inputs, adapters enforce |
| [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 generation/ingestion |
## Open Questions
- **OQ-06**: registry backing store (deferred(scope) — blocked on
metadata-scale requirements).
- **OQ-04**: receive-pack ingestion validation (deferred(unclear) — pieces
decided, push state machine needs a walkthrough/POC).
- **OQ-03**: embedder-facing API freeze (deferred(scope)).
## References
- `docs/research/gitoxide.md` (the API contract notes are normative here)
- `docs/research/poc2-findings.md` (generation pipeline + prerequisites)
- `docs/research/git-protocol.md` §"Server-side pack generation"