Files
alkhttp/tasks/client/review-001-client-timeout-retry.md
T
glm-5.3-flash 12b35e2c5f docs(tasks): decompose review 001 remediation Units 1-5 into taskgraph tasks
21 review-001 tasks across server/adapters/client/gateway/websocket/infra,
chunked from the 7-unit remediation plan in
docs/reviews/001-initial-implementation-review.md.

- Scope split by mechanism, not one-per-finding: 15 tasks in generation 1
  (parallelizable), 6 sequenced after their file-sharing precursors
- Deliberately deferred until dependent fixes land: projection/doc
  fidelity partial (Unit 6 beyond dependency hygiene), coverage backfills
  (COV-01..07 via in-task acceptance for forward.rs), and per-finding
  minors (OAI-06/07, HY-02/04/06/10/11, CON-08)
- Cross-crate WS-12 (alkcall demux 4 GiB discard alloc) noted for filing
  in alkcall, not here

taskgraph: validate clean, no cycles, 6 generations
2026-08-29 07:10:15 +00:00

3.0 KiB

id, name, status, depends_on, scope, risk, impact, level, tags
id name status depends_on scope risk impact level tags
review-001-client-timeout-retry Client redirect/Retry-After policy — idempotency, timeouts, caps (FWD-03, FWD-04, FWD-05, FWD-11, FWD-09) pending
moderate medium component implementation
client
review-001

Description

Review 001 findings on the outbound client host (src/client/http_client.rs, retry_after.rs), grouped because they all shape the shared client's request policy:

  • FWD-03: no explicit redirect policy → reqwest's default cross-host redirect scrub removes only Authorization/Cookie/etc; HttpAuthScheme::ApiKey { header_name } credentials and default_headers follow a 302 to an attacker host intact (verified against reqwest 0.13 source). Fix: explicit policy — none, or limited same-host.
  • FWD-04: RetryTransientMiddleware retries POSTs (5xx/408/429/ timeout classified retryable regardless of method — verified in reqwest-retry 0.9.1) → duplicate upstream side effects; backoff has no total-duration cap. Fix: skip retries for non-idempotent methods (or make idempotency a per-adapter policy) and cap total retry wall time.
  • FWD-05: HttpClientConfig::default() sets request_timeout: None and no connect timeout anywhere; retry_after.rs:27-37 accepts any u64 Retry-After with no maximum — a hostile backend's 10-year deadline stalls calls to that URL indefinitely. Fix: default request + connect timeouts (the gateway's 30 s deadline is the natural anchor) and a Retry-After ceiling (e.g. 300 s, configurable).
  • FWD-11: Retry-After is keyed on the pre-redirect URL, eviction drops the earliest deadline (keeping year-long entries), and all waiters wake together with no jitter. Key on the effective URL, evict sensibly, add jitter.
  • FWD-09: blocking std::fs::read in build_client, reachable via the public documented hot-reload path SharedHttpClient::reloadtokio::fs/spawn_blocking the reads.

Acceptance Criteria

  • Cross-host redirect test with an API-key credential header — key must not reach the redirect target
  • Non-idempotent method is never retried (test); total retry duration bounded (test)
  • Default request + connect timeouts exist in HttpClientConfig::default(); Retry-After capped (tests)
  • Retry-After keyed post-redirect; eviction and wake behavior fixed or documented (tests)
  • No blocking fs reads on the async path (FWD-09)
  • HttpClientConfig defaults documented; review-001-forward-url-safety and this task together close the deployment-facing gate
  • cargo test and cargo clippy --all-targets -- -D warnings pass

References

  • docs/reviews/001-initial-implementation-review.md (Part D, FWD-03, FWD-04, FWD-05, FWD-09, FWD-11)
  • docs/architecture/decisions/039-http-server-and-client-host-colocated.md

Notes

Agent fills during implementation. Independent of review-001-forward-url-safety (different file); they form the deployment gate together.

Summary

Filled on completion.