Files
alkgit/docs/architecture/decisions/009-bounded-resources-budget.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

64 lines
3.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-009: Bounded-resources budget model
## Status
Accepted
## Context
Git servers are internet-facing by definition; unbounded loops and buffers
are bugs. Each POC surfaced specific unbounded surfaces that need budgets:
- Negotiation rounds / haves count (fetch can loop forever without
`done`).
- receive-pack POST body size (push can be arbitrarily large; alkhttp
custom routes get hyper's unbounded stream — POC-3).
- Session wall-clock (long-lived ssh/git sessions).
- Blocking-pool usage: pack generation runs on `spawn_blocking`; a
thundering herd of fetches can starve the pool (POC-2 follow-up 2).
- Sideband chunk size is bounded (65000) but max pack size per fetch is
still unbounded above it.
- alkcall channels carry their own backpressure limits (alkcall ADR-040);
git sessions ride raw duplex streams, so those limits do not
automatically apply.
## Decision
Every session carries a `Limits` value, constructed by the adapter from
server config and handed to transport as part of the session tuple
(ADR-002). Defaults are per-crate constants; overrides are server config
in `alkgitd`.
| Budget | Applies to | Default direction |
|---|---|---|
| max negotiation rounds | fetch (V2, no `done`) | tens |
| max haves per round | fetch | thousands |
| max pack size | receive-pack | config-bound (tens of MB v1) |
| max request body | http POSTs (receive-pack especially) | same as max pack size |
| session wall clock | all sessions (enforced by transport's session loop on every door — it is the one component all doors hand the session to; alkcall channel caps add a second bound where channels exist) | tens of minutes |
| max concurrent pack generations | server-wide (blocking-pool budget) | small count |
| sideband chunk size | fetch streaming | 65000 (fixed, per protocol) |
| max advertisement refs | ls-refs response | config-bound |
On breach: the session ends with a substrate-appropriate error — pkt-line
error band + close on duplex; on http, *client-fault* budgets (request
body size) map to 413, *server/session* budgets (wall clock, rounds,
generation concurrency exhaustion) map to 503. Budgets are fail-closed.
Max pack size on fetch is *not* budgeted in v1 (the pack is a function of
the repo, not the request); receive-pack is the untrusted-input path and
gets the hard cap.
## Consequences
- No adapter can forget a budget: transport refuses to start a session
without `Limits` (part of the tuple, ADR-002).
- Streaming stays O(counts) regardless of budgets; budgets bound
*aggregate* work, not internal buffering.
- The blocking-pool budget is enforced at assembly/acceptance time
(reject/slow-path excess concurrent generations), not per-byte.
## References
- `docs/research/vision.md` §"Guiding principles" 7
- `docs/research/poc2-findings.md` follow-ups 2–3; `docs/research/poc3-findings.md` follow-up 3
- alkcall ADR-040 (channel backpressure — the thing git sessions bypass)
- ADR-002 (session tuple), transport.md §limits, http.md §budgets