tasks: decompose the review-002 fix round — eight dependency-ordered tasks
The general review (docs/reviews/002-protocol-core-implementation-review.md) decomposed into the fix-round group, grouped so no session carries both a code-fix vertical and the test sweep: - fix-bind-reply2-reentry: C-1 (the BIND reply#2 re-entry guard) + D-1 (the reader decision) + N-6 (the constructor prologue helper) + S-2 (the reap doc line) — one consumer session - fix-producer-gate-policy: C-3 (the explicit BIND gate input) + D-2 (the register/builder coverage) + S-1/N-2 (the stage doc lines) — one producer session - fix-rfc1928-posture: N-1 (the keep-or-cut pass) + N-4 (the honest refusal vocabulary) — one fork posture session - fix-hygiene-residue: D-3 (the ErrorDefinition declaration) + N-3 (the unreachable let-else) + N-9 (the is_mid_frame note) - fix-coverage-residue: N-8's attributed line list — tests only, after the code fixes (final shapes) - fix-test-helper-consolidation: N-5 — after the coverage round - architecture/adr-014-idle-timeout-posture: C-2 — the ADR-sized decision, independent, before the doors exist - review-fix-round-002: the closing checkpoint; the batch-2 gate The review doc's disposition table now names the landed tasks. N-7 is recorded-only (the review's own recommendation).
This commit is contained in:
1 parent
d612d7f7f2
commit
6d14d35a54
9 files changed
+828
-10
No files matched your search
@@ -0,0 +1,106 @@
|
||||
---
|
||||
id: architecture/adr-014-idle-timeout-posture
|
||||
name: "ADR-014 — the idle-timeout posture for the pre-command handshake and the association (review-002 C-2)"
|
||||
status: pending
|
||||
depends_on: []
|
||||
scope: narrow
|
||||
risk: medium
|
||||
impact: project
|
||||
level: implementation
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
Review 002's C-2 (major): the pre-command RFC handshake and the
|
||||
association have **no timeout surface** — a silent channel holds a
|
||||
spawned task and reader state indefinitely (bounded memory,
|
||||
unbounded time). The alkcall 10s establishment bound governs the
|
||||
*open-op call*, not the in-stream conversation
|
||||
(`src/producer.rs:183-191` parks on `accept_bi` → `accept_no_auth`
|
||||
→ `read_command` with no timeout; the datagram stage's loop exits
|
||||
only on EOF/error/data). BIND's quiet wait got an explicit decision
|
||||
(ADR-007 — teardown-governed, "FTP-length waits stay legal"); the
|
||||
handshake and the association lifetime got "inherited from the
|
||||
channel" — implicit, never decided.
|
||||
|
||||
The mitigations are real (the 256-channel cap bounds the count,
|
||||
memory per idle channel is bounded, teardown fires on channel
|
||||
close — nothing leaks, nothing grows), but the aggregate is: any
|
||||
identity with `socks5:open` can hold 256 parked tasks + 256 channel
|
||||
entries indefinitely *without sending a byte*. And batch 2's
|
||||
providers (`local`, `composed`) are about to route *vanilla
|
||||
clients* through these same phases via the front doors, where the
|
||||
peer is a kernel socket often outside alkcall's channel-cap regime
|
||||
entirely — slowloris-shaped holds become the assembly layer's
|
||||
problem, and the protocol layer is where a timeout seam would live.
|
||||
|
||||
**The deliverable is a decision, not code** — ADR-014
|
||||
(`docs/architecture/decisions/014-*.md`), landing *before* the
|
||||
`local` doors exist. Decide between the review's two options:
|
||||
|
||||
1. **Idle timeout is the substrate's/assembly's job** — the
|
||||
protocol layer never times out (consistent with "no in-band
|
||||
control vocabulary" and association-lifetime-equals-channel);
|
||||
record the DoS posture explicitly (the cap bounds it; doors
|
||||
apply their own accept timeouts). Cheapest, defensible.
|
||||
2. **A producer-side idle bound** — an optional per-session
|
||||
inactivity timeout at the pump level (config on
|
||||
`Socks5ProducerBuilder`), enforced by racing the handshake/stage
|
||||
reads with a sleep timer; a timeout = clean EOF-shaped teardown,
|
||||
no reply (the RFC has no timeout reply code; 0x01
|
||||
`GeneralFailure` on a pre-reply timeout is the closest and is
|
||||
what upstream's connect-timeout path surfaces). More work;
|
||||
touches no wire format.
|
||||
|
||||
The ADR must state, whichever option wins: the BIND quiet wait's
|
||||
existing decision (ADR-007) and how the new decision relates to it
|
||||
(same regime or different — and why the difference is principled);
|
||||
the DoS posture in the doors' terms (what a `local` door's accept
|
||||
path must do if the protocol layer does not); and whether the
|
||||
decision is revisitable post-batch-2 or is itself a one-way door
|
||||
(it should not be — a timeout seam is additive — but say so).
|
||||
|
||||
Also update `docs/architecture/open-questions.md` if C-2 was
|
||||
tracked there, and the affected spec lines (wire.md §UDP
|
||||
ASSOCIATE's association-lifetime bullet; producer.md's pump
|
||||
description) to carry the decided posture rather than the implicit
|
||||
one.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] ADR-014 exists at
|
||||
`docs/architecture/decisions/014-<slug>.md`, status accepted,
|
||||
deciding explicitly between the two options (or a reasoned
|
||||
third)
|
||||
- [ ] The BIND quiet wait's ADR-007 relationship is stated (same
|
||||
regime or a principled difference)
|
||||
- [ ] The doors' DoS posture is recorded (what the assembly layer
|
||||
must do if the protocol layer does not)
|
||||
- [ ] The affected spec lines (wire.md, producer.md) carry the
|
||||
decided posture — no implicit residue
|
||||
- [ ] The decision lands before any `local`/`composed` door work
|
||||
(the batch-2 tasks may depend on this one)
|
||||
- [ ] `cargo doc --no-deps` clean if any doc-comment carries the
|
||||
posture; the full verification sweep green
|
||||
|
||||
## References
|
||||
|
||||
- docs/reviews/002-protocol-core-implementation-review.md §C-2 (the
|
||||
finding — the task's source of truth)
|
||||
- docs/architecture/decisions/007-bind-in-base.md (the quiet wait's
|
||||
existing decision — the contrast case)
|
||||
- docs/architecture/decisions/008-provider-defaults.md,
|
||||
009-feature-gates.md (the batch-2 provider posture the decision
|
||||
precedes)
|
||||
- docs/architecture/wire.md §UDP ASSOCIATE (association lifetime =
|
||||
channel lifetime — the contract the decision qualifies)
|
||||
- The POC findings (the stage's measured shapes — the
|
||||
"sufficient for relay postures" lineage)
|
||||
|
||||
## Notes
|
||||
|
||||
> Agent fills this during implementation.
|
||||
|
||||
## Summary
|
||||
|
||||
> Agent fills this on completion.
|
||||
Reference in new issue
Block a user