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).
3.2 KiB
ADR-002: Front-door-blind core — the session boundary
Status
Accepted
Context
The load-bearing composability rule ("ALPN as a service",
docs/research/vision.md): alkgit (the single crate) must never
know which front door is talking. POC-1 proved the exact shape survives the
wire: Connection::accept_bi() → BiStream → tokio::io::split → tokio-util compat → gix-packetline ran a full V2 fetch against real git.
POC-3 proved the stateless-http variant: the same protocol state machines
ran per-POST over (request-reader, response-writer) instead of a duplex
stream.
The question this ADR settles: what is the interface the core/transport exposes to adapters?
Alternatives considered:
- Adapters implement an alkcall-style
ProtocolHandlerthemselves and call into transport with rawBiStream— pushes too much protocol responsibility (advertisement timing, framing errors) into every adapter. - Transport speaks alkcall
Connectiondirectly — forces stateless http (one request per connection) through a session-shaped API; wrong shape for http, and couples transport to alkcall connection lifecycle. - HTTP-specific abstractions in transport — violates the blind-core rule.
Decision
The transport exposes two session entry points, both consuming the same tuple (peer identity, resolved repo, limits):
- Duplex session (ssh, git://, any stream door): transport consumes a
BiStream-shaped duplex byte stream (AsyncRead + AsyncWrite + Unpin, the alkcallBiStreamcontract, alkcall ADR-005/009) and runs the advertise-once → command-loop state machine. Adapters hand it over after ACL and repo resolution (ADR-007, ADR-008). - Stateless session (smart-http): transport consumes a (request-reader, response-writer) pair per http request and runs one command per invocation, matching smart-http's stateless framing. The same core state machines run under both entry points.
Storage-facing side: the wire layer calls the backend traits for advertisement data, pack generation (want/have set in → streaming pack out), and pack ingestion + ref CAS (receive-pack). Storage never sees pkt-lines.
The futures-io bridging detail (tokio_util::compat), the split/compat
glue, and the packetline stop-delimiter handling live inside transport —
adapters never see futures_io types (POC-1 follow-ups 1–2, POC-3
follow-up 2).
Consequences
- The core+transport pair is embeddable with any front door; POC-1/3 are existence proofs of both shapes.
- State machines are written once; http statelessness is a substrate property, not a protocol fork.
- Transport depends on alkcall types only (
BiStreamshape, identity, limits) — no alkhttp, no channel types below the stream. - One cost: the stateless entry point needs explicit per-request limits (body budget, wall clock) since there is no session to amortize them (ADR-009).
References
docs/research/vision.md§"ALPN as a service"docs/research/poc-1-findings.md(duplex shape validated),docs/research/poc3-findings.md(stateless shape validated)- alkcall ADR-005 (
BiStreamtype), ADR-009 (BiStream as handler leaf) - ADR-005 (substrate types detail), ADR-007/008 (what adapters do before calling transport)
- overview.md §"Crate map"