Skip to content

test(gateway): reproduce whole-response buffering - #443

Draft
seonghobae wants to merge 17 commits into
codex/coraza-header-enforcement-red-20260917from
test/442-gateway-streaming-red
Draft

seonghobae wants to merge 17 commits into
codex/coraza-header-enforcement-red-20260917from
test/442-gateway-streaming-red

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 20, 2026 •

Copy link
Copy Markdown
Contributor

Refs #442.

Scope and current serialization state

This Draft is the Wardnet-owned generic gateway response-streaming/backpressure lane. The branch has now non-force adopted the complete current Coraza + HTTP mediation parent instead of racing the same gateway seam.

Current topology:

The seven hostile buyer contracts remain:

  1. an immediate upstream first chunk must be observable before a delayed tail;
  2. a hostile 8 MiB Content-Length must not cause the admitted prefix to wait for whole-body materialization;
  3. an admitted prefix must remain observable before a later upstream body failure, and the later failure must remain a downstream body error rather than successful completion;
  4. a real 1 MiB + 64 KiB prefix without declared length must cross before the held tail, with the producer itself emitting bounded 16 KiB chunks;
  5. dropping the admitted downstream body must promptly drop the held upstream body without releasing its tail;
  6. an unpolled buyer body must not drain a finite 64 MiB upstream beyond the explicit 8 MiB read-ahead witness during the 250 ms idle interval;
  7. four independent held streams must expose admitted heads/prefixes concurrently while an unrelated fast buyer request remains responsive.

All timing fixtures wait until the real loopback upstream has accepted the request before starting the semantic timing witness. Cleanup releases are used only on current-behavior failure paths so a RED cannot strand its fixture.

Executed RED lineage

Predecessor eedc56c1e0fefc4654f2e1bdc8b7ceae99a28825 acquired hosted Ubuntu 24.04 in CI 35610237483, rust job 106367237430. Checkout, toolchain, formatting and all existing 142 library unit tests passed before the real gateway integration binary failed the three intended cases: delayed-tail response observability, dishonest-large-Content-Length prefix observability, and partial-upstream-failure prefix observability. SAST 35610237552 and Security 35610237788 were terminal SUCCESS. The required CodeQL failure was handed to the canonical central settlement owner; it is not promoted as Wardnet GREEN.

Predecessor 239c747848a8241cbbccd66e6f91d20725860c51 added only the slow-consumer/concurrency fixture and first exposed rustfmt-only noise. Exact successor 2cccfb37b85c3fc30d4b91d3027266feaf338774 applied only that formatter output. CI 35921459298, rust job 107386159436, then passed checkout/toolchain/formatting, all 142 existing library unit tests and the pre-existing integration suites before failing only the two newly added buyer cases:

  • unpolled_buyer_body_does_not_drain_the_entire_large_upstream: Wardnet/upstream read-ahead drained all 1024 x 64 KiB chunks (64 MiB) while the buyer body was intentionally unpolled for 250 ms, far beyond the explicit 8 MiB witness;
  • concurrent_held_streams_expose_prefixes_and_do_not_block_fast_buyer_traffic: four admitted held upstreams kept buyer response heads/prefixes behind unreleased tails.

Those receipts establish the causal whole-response-buffering finding. They are historical after the ancestry movement and do not transfer as exact-current GREEN.

Valid finding and minimum causal repair boundary

Fresh source review on the adopted parent confirms the generic proxy still calls response.bytes().await before constructing the downstream response. That materializes the complete upstream body, causally explaining every executed RED above.

The minimum Wardnet-owned repair is therefore one bounded asynchronous body relay at the existing generic proxy boundary: preserve the already-admitted status/header map, expose the upstream body as a streaming Axum body, retain natural downstream backpressure/cancellation, and leave a late upstream body error observable through the downstream body. It must not add an unbounded channel, eagerly drain the stream, automatically replay a request, infer success after a partial failure, or absorb EgressWeave transport policy. The existing truncated-body unit fixture must likewise assert successful response-head admission followed by a body-read error instead of requiring pre-response BAD_GATEWAY whole-body materialization.

Serialization is now clear because the complete #441 mediation delta is already in current parent #435. A production repair may proceed only on this restacked child (or a verified bounded successor) and must compose once with the inherited header/representation mediation authority.

Exact-current evidence

Current exact c47b35c36eed9aad1c0968c82aa14b1c40cf352b is mechanically mergeable against exact parent #435 and still changes only the four hostile test files. Current CI 35985182231 is now terminal semantic RED on the expected streaming defect: formatting and all inherited/pre-existing test coverage run before the hostile streaming/backpressure assertions fail because current production still whole-body materializes upstream responses. Current SAST 35985182196 and Fuzz 35985182228 are terminal SUCCESS; Security 35985182193 and CodeQL PR 35985182368 remain queued. No predecessor result is promoted over those current receipts.

The minimum causal production repair has been dispatched on this existing branch at the unchanged exact head with instructions to replace only whole-body collection with a direct bounded asynchronous Axum relay, preserve admitted status/headers and downstream body errors, update the legacy truncated-body acceptance, and run fmt/locked workspace tests/strict Clippy. No competing PR, force update, transport-policy duplication or gate weakening is authorized.

Keep Draft until the causal streaming repair is present and one unchanged exact candidate passes format, locked workspace tests, strict Clippy, Fuzz, security/SAST/CodeQL, 100% owned production statement/branch/edge/public-rustdoc evidence, realistic async buyer-path/k6 acceptance including p95 <= 20 ms for Wardnet-owned processing, reviews/threads, fresh parent compatibility, and all live package/SBOM/provenance/governance gates.

No force push, destructive rebase, self/model approval, synthetic status, no-op redispatch churn, gate weakening, routine bypass, mutable foreign dependency, source copy, cross-service SQL, or predecessor-evidence transfer.

@coderabbitai

coderabbitai Bot commented Sep 20, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copy link
Copy Markdown
Contributor Author

Fresh exact-head execution update (2026-09-24 KST): #443@2cccfb37b85c3fc30d4b91d3027266feaf338774 has now reached the real hostile fixtures. CI run 35921459298, rust job 107386159436, acquired hosted Ubuntu 24.04, completed checkout/toolchain and cargo fmt --check, then passed all 142 existing library unit tests and the pre-existing integration suites before failing only the two newly added streaming/backpressure cases.

Semantic REDs:

  • unpolled_buyer_body_does_not_drain_the_entire_large_upstream: Wardnet/upstream read-ahead drained all 1024 x 64 KiB chunks (64 MiB) while the buyer body was intentionally left unpolled for 250 ms. This proves current whole-response materialization defeats downstream backpressure and violates the explicit bounded-relay witness.
  • concurrent_held_streams_expose_prefixes_and_do_not_block_fast_buyer_traffic: four admitted held upstreams kept buyer response heads/prefixes behind unreleased tails, proving whole-body buffering prevents concurrent streams from becoming observable before completion.

This is source-causal semantic RED, not bootstrap/format/runner noise. Current SAST 35921459251 is terminal SUCCESS. Security 35921459231 and CodeQL 35921459105 remain queued; those do not invalidate the executed RED, but they are still required before any promotable GREEN lineage. Production repair remains serialized behind #441/#440; this Draft stays test-only and must not acquire src/lib.rs or duplicate EgressWeave/contextual-orchestrator/quarantine/appguardrail authority.

@seonghobae
seonghobae changed the base branch from main to codex/coraza-header-enforcement-red-20260917 September 24, 2026 10:05

Copy link
Copy Markdown
Contributor Author

@devin Current serialization is clear: #441 has been normally merged into canonical parent #435, and #443c47b35c is now the sole child writer for issue #442. Please implement the minimum causal GREEN directly on the existing test/442-gateway-streaming-red branch, non-force and without opening a competing PR.

Verified RED/source cause: current proxy_request() in src/lib.rs admits status/headers, then awaits response.bytes() before constructing the Axum response. Exact current CI 35985182231 fails the hostile streaming/backpressure fixtures as intended; the same test step proves 64 MiB upstream drain while buyer body is unpolled and held concurrent streams cannot expose heads/prefixes before their tails.

Minimum repair only:

  • replace complete-body collection with a direct bounded asynchronous Axum body relay over the existing reqwest upstream byte stream (e.g. Body::from_stream(response.bytes_stream()) or the smallest equivalent already supported by current dependencies);
  • preserve the already-admitted status and gateway_mediation::admit_response_headers() result exactly once;
  • preserve natural downstream backpressure and cancellation; add no unbounded queue/channel, eager drain, replay, elapsed-time success inference, or EgressWeave transport logic;
  • preserve late upstream body failure as a downstream body error after the admitted response head/prefix;
  • update only the existing truncated-body unit acceptance that still expects pre-response BAD_GATEWAY: it must instead accept the response head and assert that consuming the body returns an error;
  • do not change Coraza, destination/DNS/peer/redirect/proxy/TLS authorization, contextual-orchestrator, quarantine, appguardrail, CGC/EA, or central workflows.

Run cargo fmt --check, cargo test --locked --workspace, and strict workspace Clippy. Keep the PR Draft. Commit the smallest causal source/test delta to this same branch and report the new exact head plus the specific RED→GREEN test results. Do not force push, rebase destructively, weaken gates, synthesize status, or promote predecessor evidence.

@devin-ai-integration

Copy link
Copy Markdown

Failed to start a Devin session. Please try again.

Copy link
Copy Markdown
Contributor Author

@devin Retry the failed session start from issuecomment-5814995333 on the unchanged exact head c47b35c36eed9aad1c0968c82aa14b1c40cf352b. Scope is unchanged and deliberately narrow: replace generic response.bytes().await whole-body collection with the direct backpressure-preserving Axum body stream at proxy_request_with_headers, preserve the existing admitted status/header map exactly once, keep late upstream body errors observable downstream, and update only the legacy truncated-body acceptance that assumes pre-response 502. Do not copy transport/policy logic, open a competing PR, force-push, rebase, weaken gates, or touch foreign-owner contracts. Run fmt, locked workspace tests, and strict Clippy before pushing normally to test/442-gateway-streaming-red.

@devin-ai-integration

Copy link
Copy Markdown

Failed to start a Devin session. Please try again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant