# alkgit Phase 0: Vision and Guiding Principles **Status**: draft v2 — 2026-09-21 (v1 2026-09-19; v2 amends the delivery shape — see "Sub-crate shape") **Phase**: 0 (exploration) — this document captures WHAT we are building and WHY before architecture (phase 1) commits to HOW. ## Vision A git payload service for the alk family, in Rust: alkgit implements the git smart protocol as a **pure protocol crate** on alkcall channels (the `alk/git` ALPN) — storage behind backend traits (gitoxide implementation behind a feature), producer/consumer halves, no binary, no front doors. Doors are family infrastructure: alkhttp exposes smart-http, alkssh (planned) will expose git-over-ssh, the alknet rewrite carries the native path; downstream consumers assemble what they want. It exists because self-hosted git platforms (gitea/gitlab) are large multi-component applications with a long-tail of exposed APIs, plaintext secret storage, and web-UI attack surface — and because CVE-2026-59774 (gitea) demonstrated that a single logic bug in an internally-exposed API is enough for full compromise of the host. Our blast-radius and exposure model is designed from day one, not retrofitted. ## The problem, precisely 1. **Exposure model**: mainstream self-hosted git servers expose a large HTTP API surface regardless of auth (openapi describes everything; enforcement is somewhere else). alkcall inverts this: only operations the caller has privileges for are visible on the wire, and `Visibility::Internal` ops are structurally unreachable. alkgit inherits that property by using alkcall as the transport/protocol substrate. 2. **Secret hygiene**: gitea stores secrets plaintext in its DB. alkgit uses alkvault for anything credential-shaped; the metadata store holds vault references, never plaintext secrets. 3. **Footprint**: a git server is a small program (storage + smart protocol + thin doors); the platform features (issues, PRs, CI) are where the CVEs live. alkgit v1 is deliberately just the git service as a protocol crate; everything else stays out (doors live in the door crates — alkhttp, alkssh — per ADR-010). 4. **Language**: the whole serving path is Rust (memory-safe, no C deps in the packet path). ## Guiding principles (architecture must honor) 1. **Authenticated by default** — no unauthenticated endpoint exists unless a repo is explicitly marked public; even then, advertisement is the only anonymous surface, and push is always authenticated. 2. **Visible-surface = authorized-surface** — the alkcall model end to end; no endpoint exists on the wire that a caller cannot see themselves authorized for; internal/admin ops are never wire-reachable. 3. **No plaintext secrets at rest** — alkvault or nothing. 4. **Thin interfaces, one core** — http and ssh are adapters that authenticate, resolve a repo, and hand a duplex stream to the transport layer. Policy lives in exactly one place. The core never knows which front door is talking (see "ALPN as a service" below). 5. **Honest capability advertisement** — the git protocol advertises only what we actually serve (this is both protocol correctness and the security pattern: promise/enforce in the same place). 6. **gitoxide for storage/wire primitives** — never shell out to the `git` binary (no GPL dependency, no process injection surface); own the smart protocol server layer ourselves on gitoxide primitives. 7. **Bounded resources** — every protocol session carries wall-clock, size, and round limits; git servers are internet-facing by definition. ## Non-goals for v1 - Web UI of any kind. - Issues/PR/review features. - Git LFS (later phase, separate decision). - federation/replication between alkgit instances (later phase). - Serving as a general sshd (alkgit carries no ssh surface at all; alkssh is the door). - Windows as a serving platform (linux first; keep code portable-ish but don't test it). ## Sub-crate shape (amended 2026-09-21 by ADR-010) The v1 draft's table below was an init-agent artifact (monorepo + binary + own doors); the corrected shape is the alktty/alktunnels pattern — see `docs/architecture/decisions/010-pure-protocol-crate.md`: | Piece | Role | |---|---| | `alkgit` (single crate) | wire layer (substrates, V2 state machines) + producer/consumer halves + backend traits | | `gix` feature (default on) | gitoxide-backed implementation of the backend traits | | alkhttp `git` feature (future) | smart-http mounting of the stateless substrate | | alkssh (future family crate) | git-over-ssh door | | downstream assembly | the actual deployment (config, listeners, TLS/ACME, vault) | ## Composability: "ALPN as a service" alkgit is the git member of the alk "ALPN as a service" family — alktty, alktunnels, and alksocks (socks5) follow the same pattern, and the alknet mono-repo is being decomposed into exactly these pieces for rewrite. The pattern's load-bearing rule: **alkgit never knows which front door is talking.** The protocol crate consumes (identity, repo id, duplex stream, limits) and speaks git; everything above the stream is the door's problem. That is what keeps alkgit composable for downstream use: - A future gitea/gitlab-like application embeds `alkgit` (wire layer, with its own backend implementation via the traits or the gix feature) and adds its own UI/issues/PR layer without forking anything here. - Registry management ops, if the gix feature ships any, are a set of alkcall ops, not an embedded web framework — a downstream app can either use them or replace them (OQ-07). - Nothing in the crate may reach upward into alkhttp/alkssh concerns (no http types, no channel types below the transport boundary). The v1 reduction follows from this: **wire layer + backend traits + one gix implementation**. A simple static/template web UI for the public repo listing is explicitly out of scope here (would be a separate downstream thing on top). ## Primary deployment target Our own use case is the design anchor: **public self-hosted repos with anonymous clone over http, authenticated push, no gitea-style app features in use**. So: - Anonymous *fetch* (clone/fetch advertisement + pack) on explicitly-public repos is a first-class path, not an afterthought. - Push is always authenticated, on every repo, no exceptions. - ACL must be simple enough to reason about completely: repo visibility (public/private) + identity-based read/write, nothing richer in v1. *(Amended by ADR-015: the grant set gains `manage` — repo administration — still flat, still per-repo, still one policy function.)* ## What phase 0 must still produce before phase 1 - [x] gitoxide capability + version research (`gitoxide.md`) - [x] alk stack fit + integration surface (`alk-stack.md`) - [x] server-side protocol inventory (`git-protocol.md`) - [x] license/reference policy (`reference-policy.md`) - [x] POC-1: real `git clone` over alkcall BiStream using gix-packetline (validates BiStream fit + packetline async codec end-to-end) - [x] POC-2: server-side pack generation composition (bundle-write vs entries-to-bytes) for a small want/have set - [x] POC-3: http smart-endpoint streaming shape through alkhttp (chunked pack response, unbuffered receive-pack POST ingestion) - [x] Convergence: recommended approach summary feeding phase 1 architecture ## Immediate threat-model notes carried into architecture - Registry management ops, if the gix feature ships any, are alkcall `Visibility::Internal` ops over an admin-only listener; they are never part of the git traffic surface (OQ-07). *(Superseded by ADR-012 §3 and ADR-015: the ops are External, gated by scope + the `manage` grant — right mechanism, wrong axis.)* - Repo names arriving on the wire are registry IDs, never paths; storage roots are configured server-side only. - The advertisement phase runs ACL before the first ref line is emitted. - receive-pack applies ref updates via CAS transactions; hooks/plugins do not exist in v1 (no arbitrary code execution surface at all).