Files
alkgit/docs/research/vision.md
T
glm-5.3-flash c4b9c53674 docs(architecture): ADR-015 — manage grant tier + repo-op gate, OQ-16 identity namespace
Resolves review 001 finding A-1 (critical): ADR-012 §3's "scope
git:admin OR ownership" gate is not expressible in alkcall's
AccessControl (AND-composition). Resolution is the review's option (a)
shape with the OR-term generalized: the per-repo grant action set gains
manage, authorize(record, identity, read|write|manage) becomes the
single policy function for git access and repo administration, and the
delete/update/get gate is admin scope OR manage grant (handler-side,
generic FORBIDDEN, unknown-repo = unauthorized per ADR-008). Repo
create seeds the creator's {read, write, manage} grants —
administration is grantable, so collaborators/bots/app-compiled roles
work without global scopes. Ownership stays as alkcall spawn-tracking
(mint at create unchanged); "ownership never implies git access" is
superseded.

- ADR-015 (new): manage grant tier, op gate, flat-grants-as-replication-
  substrate, opaque grant-key rule
- ADR-011: action set + policy domain amended, references updated
- ADR-012 §3: gate table replaced, two-tier paragraph superseded
- backend.md/doors.md/overview.md: gate + grant restatements, ADR tables
- OQ-16 (new, deferred(scope)): grant-key identity namespace —
  globally-comparable ids for cross-assembly/replicator grant state;
  tracker task tasks/architecture/oq-16-grant-identity-namespace.md
- review 001: A-1 marked resolved (ADR-015)
- vision.md: supersession notes (Internal-ops framing, v1 grant set)

Verification: cargo test, clippy -D warnings, fmt --check, doc --no-deps
all clean.
2026-09-26 11:50:25 +00:00

155 lines
7.9 KiB
Markdown

# 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).