Repository navigation
[P0] Stream generic gateway upstream responses with bounded backpressure #442
Description
Activity
seonghobae commented
on Sep 21, 2026 ContributorAuthorMore actions2026-09-21 KST hostile RED expansion for #443.
Fresh review kept production source byte-identical and added one real over-budget loopback fixture on
test/442-gateway-streaming-red. Exact head is now7f0e1ed021f109e45c274014e55d9c94017ac6ca: the upstream exposes an admitted1 MiB + 64 KiBprefix with no declared length and holds its tail, and the buyer contract requires more than the explicit 1 MiB relay-memory budget to arrive before that tail is released. This prevents a dishonest-Content-Lengthspecimen alone from standing in for actual large-body evidence.The predecessor
20f3fcd3a56c2d1069784cf43bd739eabfa6ea45queued workflow set is invalidated and does not transfer. Exact7f0e1ed021f109e45c274014e55d9c94017ac6cacurrently has no materialized hosted workflow evidence, so no semantic RED/GREEN is claimed. Keep the lane Draft and test-only while #435/#441/#140 own the overlapping production seam.Still required before production repair: slow-consumer backpressure, post-admission disconnect/cancellation, concurrent slow/chunked isolation, and composition with #440 header mediation plus unchanged route/local-deny/Coraza/audit behavior. No EgressWeave/contextual-orchestrator/quarantine/appguardrail owner logic is duplicated.
seonghobae commented
on Sep 21, 2026 ContributorAuthorMore actions2026-09-22 KST exact-head hostile RED is now established for #443.
Production source remains byte-identical to protected
main@f8260f1e03836039ff9463dd99fa982e4e270c4b, and #443 exact head remainseedc56c1e0fefc4654f2e1bdc8b7ceae99a28825.Hosted CI
35610237483/ rust job106367237430reached the real loopback tests aftercargo fmt --checkpassed and all earlier workspace test suites succeeded.tests/gateway_streaming.rsexecuted three hostile buyer assertions and all three failed for the intended causal behavior:- delayed tail: Wardnet withheld the downstream response until the upstream tail was released;
- dishonest
Content-Length: Wardnet withheld the admitted prefix instead of streaming it; - partial upstream reset: Wardnet withheld the admitted prefix until the later upstream body failure.
This is semantic RED, not bootstrap/runner/format noise. Security
35610237788and SAST35610237552are GREEN; CodeQL35610237414remains queued under the central workflow settlement. The separate no-Content-Length>1 MiB bounded-memory fixture and downstream-cancellation fixture are present on this exact head, butcargo teststopped after the earlier failing integration binary, so those two fixtures are not promoted as hosted execution evidence.Still required before production repair: a defensible slow-consumer/backpressure witness, concurrent slow/chunked isolation, then non-force composition/restack with #440/#441 header mediation and preservation of route/local-deny/Coraza/audit semantics. Keep production repair serialized behind #435/#441/#140. Do not copy EgressWeave/contextual-orchestrator/quarantine/appguardrail owner authority, and do not use bypass/no-op dispatch to manufacture evidence.
seonghobae commented
on Sep 23, 2026 ContributorAuthorMore actions2026-09-24 KST RED-lane expansion on #443.
Current exact test-only head is
239c747848a8241cbbccd66e6f91d20725860c51; production source remains byte-identical to protectedmain@f8260f1e03836039ff9463dd99fa982e4e270c4band the lane remains Draft behind the serialized #435/#441/#140 source writers.New
tests/gateway_a_streaming_backpressure.rsadds the two previously missing protocol-generic witnesses without copying foreign-owner logic:- slow consumer/backpressure: a real loopback upstream offers a finite 64 MiB body in 64 KiB chunks. Wardnet must expose the response before body completion and, while the buyer body stays unpolled for 250 ms, bounded read-ahead must remain within the explicit 8 MiB witness rather than draining the whole body in the background;
- concurrent held streams: four independent slow upstream responses hold their tails. All four buyer response heads/prefixes must be exposed before tail release, and unrelated fast buyer traffic must remain responsive while those streams stay open.
Fresh exact-head CI
35880184584, Security35880184517, SAST35880184578, and CodeQL PR35880184686are queued. Therefore predecessor semantic RED validates the causal finding but is not promoted as evidence for this successor head, and the two new cases are not yet claimed RED/GREEN. No blind rerun or wake commit.Remaining #442 acceptance before production repair is non-force composition with the single #440/#441 header-mediation boundary plus unchanged route/local-deny/Coraza/audit semantics. Production repair remains unauthorized until that writer lane clears.
seonghobae commented
on Sep 24, 2026 ContributorAuthorMore actionsCurrent hostile RED is now executed on unchanged test-only
#443@2cccfb37b85c3fc30d4b91d3027266feaf338774. CI35921459298, rust job107386159436, acquired hosted Ubuntu 24.04; checkout/toolchain/cargo fmt --checkpassed, all 142 existing library unit tests and pre-existing integration suites passed first, then only the new streaming/backpressure witnesses failed:- idle buyer body drained the entire upstream
1024 x 64 KiB(64 MiB) within the 250 ms observation window instead of applying bounded downstream backpressure; - four concurrent held upstreams kept all admitted buyer response heads/prefixes behind unreleased tails instead of exposing independent streams before completion.
This is valid source-causal RED for the whole-response-buffering finding, not runner/bootstrap/format noise. SAST
35921459251is terminal SUCCESS; Security35921459231and CodeQL35921459105remain queued. Keep production GREEN serialized behind active generic gateway mediation #441/#440, then implement one bounded async relay that composes with the single header-mediation boundary; do not copy EgressWeave transport authorization or other owner logic.- idle buyer body drained the entire upstream
seonghobae commented
on Sep 24, 2026 ContributorAuthorMore actionsFresh composition review now clears the former #440/#441 serialization prerequisite for #442: #441 is normally integrated into current Coraza/gateway parent #435 (
534a48b54dcd9e668ceeec8d3d00f824531b0ad1), and #443 has non-force adopted that parent as exactc47b35c36eed9aad1c0968c82aa14b1c40cf352b. The parent-relative #443 delta is still only the four hostile streaming test files; no foreign-owner transport policy is present.The valid production finding is still exact and causal in current
src/lib.rsblobe9b751c59474cae83c99d3df56a418c28e7fa083:proxy_request_with_headers()admits status/headers, then callsresponse.bytes().awaitbefore constructing the Axum response. That whole-body materialization directly explains the executed delayed-tail, dishonest-Content-Length, late-reset, 64 MiB idle-buyer drain, and concurrent-held-stream REDs.Minimum Wardnet-owned repair on #443 is deliberately narrow:
-use axum::{ - Json, Router, - body::Bytes, +use axum::{ + Json, Router, + body::{Body, Bytes}, ... - let bytes = response - .bytes() - .await - .map_err(|error| format!("upstream body read failed: {error}"))?; - let mut response = (status, bytes).into_response(); + let body = Body::from_stream(response.bytes_stream()); + let mut response = Response::new(body); + *response.status_mut() = status; *response.headers_mut() = admitted_response_headers; Ok(response) }
Also update the existing truncated-upstream unit fixture from pre-response
BAD_GATEWAYto admitted200 OKfollowed by a downstream body-read error (using the test module's existingto_byteshelper); do not assert unstable error text. Do not add channels, eager drains, replay, timeout-success inference, EgressWeave authorization, or another header-mediation pass.Current #435 and #443 exact-head workflow sets are still queued/pending, so this handoff is not GREEN and does not authorize merge/no-op redispatch/bypass. Apply the causal source repair only by normal non-force branch history, then require the unchanged repaired exact head to turn the seven hostile contracts GREEN plus all then-live deterministic/security/coverage/review/thread/package/SBOM/provenance/governance gates.
Verified buyer/security gap
Fresh protected-source review on
main@f8260f1e03836039ff9463dd99fa982e4e270c4bconfirms that Wardnet's genericproxy_request()sends the upstream request with reqwest and then materializes the upstream response before returning it through Axum. Issue #440 independently records the same current behavior as "reads only the upstream status and complete body bytes" and explicitly requires unresolved response streaming to be tracked as a dependent gateway gap.This is independent of #440's header-mediation defect: even after end-to-end fields are mediated correctly, whole-response buffering allows an admitted upstream to turn one buyer request into unbounded/large resident memory, delays first byte until the response completes, defeats natural downstream backpressure, and makes long-lived/chunked/SSE-style responses non-viable. It is also distinct from #89's contextual-orchestrator-specific LLM seam and #86's Coraza/IDS streaming requirements.
Ownership boundary
This is Wardnet-owned generic gateway/SOC control-plane relay behavior. Wardnet owns safe request admission, generic response relay, cancellation/backpressure evidence and buyer-path latency. It must not copy or reimplement EgressWeave's canonical outbound URL/address/DNS/peer/redirect/proxy/TLS/resource-authorization logic, contextual-orchestrator provider/model routing, Coraza engine internals, quarantine runtime behavior, or appguardrail policy logic.
Consume released owner contracts only. Until an immutable EgressWeave contract/release exists for transport-policy authority, keep that dependency fail-closed/documented rather than inventing a local substitute.
Hostile realistic RED
Serialize implementation behind the active gateway writers (#435 and #441/#440); do not create a competing
src/lib.rswriter while either owns the same seam. The first implementation PR must keep production behavior unchanged until tests prove the defect against a loopback upstream.RED must include at least:
Content-Length) proving current whole-body materialization can exceed the intended memory envelope;Runner/bootstrap/format noise is not semantic RED. The loopback client must observe the real stream/timing/cancellation assertions.
Minimum causal GREEN contract
Bytes/Vecfirst.Exact-head acceptance
On one unchanged candidate head require:
cargo fmt --check,cargo test --locked --workspace, strict Clippy, Fuzz and live security/SAST/CodeQL/governance checks;<=20 mstarget for ordinary admitted responses, plus separately reported first-byte latency/stream duration for intentionally long-lived fixtures;Keep this issue open until the effective code/test/doc delta reaches protected
main. No self/model approval, force push, destructive rebase, routine bypass, gate weakening, no-op redispatch churn, mutable dependency, or predecessor-head evidence promotion.Traceability