Valid gateway/security gap
Fresh review of the current pg-erd leaf 0145c455f5010bcff2af96e2293530c4fdf35aa4 and pinned/current Pingora 09696b51bc59315353d96686355861604d0bb48c confirms that request-body and process in-flight budgets are explicit, but downstream request-header resource admission is not yet an edge-owned configurable contract.
This matters before commercial cutover because a callback-only header-size check would occur after Pingora has already buffered and parsed the request header. It can reject an application request, but it cannot honestly be described as a pre-allocation parser/resource bound.
Exact supplier evidence
At pinned/current Pingora 09696b51bc59315353d96686355861604d0bb48c:
- HTTP/1
pingora-core/src/protocols/http/v1/common.rs hard-codes MAX_HEADERS = 256, INIT_HEADER_BUF_SIZE = 4096, and MAX_HEADER_SIZE = 1_048_575 bytes.
- HTTP/1
HttpSession::read_request() grows the parser buffer until that fixed maximum. The source explicitly notes that the maximum-size check happens before a subsequent read, so one already-completed large socket read may have allocated/read beyond the nominal threshold before rejection.
- these HTTP/1 values are supplier constants, not a gateway Admin Config option exposed by the current
ProxyHttp callback surface.
- HTTP/2 is a different contract:
default_h2_options() applies a decoded header-list limit of 64 KiB and 100 concurrent streams, and H2Options::max_header_list_size can customize the H2 value. Do not claim that the H1 fixed wire/parser cap and H2 decoded-header-list accounting are equivalent byte semantics.
The current CWL Runtime Isolation boundary owns max_request_body_bytes, max_in_flight_requests, and the pg-erd v2 response-body progress lifetime only. MigrationGatewayProxy::request_filter() runs after session.req_header() exists, so adding a semantic header sum there would not close the parser-allocation boundary above.
RED acceptance
- Keep the current exact supplier constants/API as explicit evidence rather than calling request headers "unbounded"; the gap is operator-controlled and migration-versioned admission below the supplier ceiling, not absence of any supplier ceiling.
- Prove with real downstream traffic that an HTTP/1 request exceeding a desired commercial header budget can be buffered/parsed before
ProxyHttp::request_filter, so a callback-only 431 check is not pre-allocation enforcement.
- Keep HTTP/2 evidence separate: prove the configured/default decoded header-list limit through the actual server composition before claiming H2 header-budget parity.
- Do not reduce body/in-flight limits, hide the case behind a front proxy, or rely on Nginx/Traefik remaining in front after cutover.
Required repair boundary
- Determine whether current Pingora provides a supported server/composition hook that can lower HTTP/1 request-header bytes/count before or during parser buffering, while preserving the existing bounded defaults for HTTP/2. If not, open/advance the supplier path instead of copying mutable Pingora parser source into this repository.
- Introduce any CWL operator-facing field only as an explicit positive versioned Admin Config contract. Preserve generic v1 and pg-erd v1/v2 behavior unless a deliberate version increment is adopted; no hidden default or semantic reinterpretation.
- Keep separate invariants for at least HTTP/1 header bytes, HTTP/1 header count, and HTTP/2 decoded header-list size because their supplier accounting differs. Reject impossible/zero/overflow values before listener authority.
- Add real-listener RED→GREEN acceptance with near-limit success and over-limit failure. For HTTP/1, include many-small-fields and one-large-field cases; for H2, include decoded-list-size behavior once H2 is actually admitted by a later protocol version. Preserve
/livez//readyz, low-cardinality telemetry, and independent-route recovery without logging attacker header contents.
- Use HTTP 431 only where the runtime can reliably produce it without weakening parser/resource safety; a transport/parser rejection before application callback is acceptable if that is the supplier's supported behavior. Do not fabricate a prettier status at the cost of reading more attacker-controlled data.
- Keep
SECURITY.md, THREAT_MODEL.md, API_CONFIG_CONTRACT.md, TEST_STRATEGY.md, OPERABILITY.md, TRD.md, CHANGELOG.md, TRACEABILITY, and docs/product-technical-gap-baseline.md code-current with the exact supplier semantics and protocol scope.
- Require exact-head fmt/compile/test/clippy/rustdoc/100% owned-production coverage plus realistic failure/concurrency traffic, k6/OCI/security/supply-chain and independent review before merge/release credit.
Responsibility boundary
This is reusable Ingress / Runtime Isolation / HTTP transport resource safety. It does not authorize product auth/business policy, Keyverse identity, Wardnet/EgressWeave decisions, cookie semantics, downstream TLS issuance, H2/H3/QUIC admission, or consumer source changes. Any supplier change must be immutable/provenance-bound and reconciled with .github#1605 before release.
Valid gateway/security gap
Fresh review of the current pg-erd leaf
0145c455f5010bcff2af96e2293530c4fdf35aa4and pinned/current Pingora09696b51bc59315353d96686355861604d0bb48cconfirms that request-body and process in-flight budgets are explicit, but downstream request-header resource admission is not yet an edge-owned configurable contract.This matters before commercial cutover because a callback-only header-size check would occur after Pingora has already buffered and parsed the request header. It can reject an application request, but it cannot honestly be described as a pre-allocation parser/resource bound.
Exact supplier evidence
At pinned/current Pingora
09696b51bc59315353d96686355861604d0bb48c:pingora-core/src/protocols/http/v1/common.rshard-codesMAX_HEADERS = 256,INIT_HEADER_BUF_SIZE = 4096, andMAX_HEADER_SIZE = 1_048_575bytes.HttpSession::read_request()grows the parser buffer until that fixed maximum. The source explicitly notes that the maximum-size check happens before a subsequent read, so one already-completed large socket read may have allocated/read beyond the nominal threshold before rejection.ProxyHttpcallback surface.default_h2_options()applies a decoded header-list limit of 64 KiB and 100 concurrent streams, andH2Options::max_header_list_sizecan customize the H2 value. Do not claim that the H1 fixed wire/parser cap and H2 decoded-header-list accounting are equivalent byte semantics.The current CWL Runtime Isolation boundary owns
max_request_body_bytes,max_in_flight_requests, and the pg-erd v2 response-body progress lifetime only.MigrationGatewayProxy::request_filter()runs aftersession.req_header()exists, so adding a semantic header sum there would not close the parser-allocation boundary above.RED acceptance
ProxyHttp::request_filter, so a callback-only 431 check is not pre-allocation enforcement.Required repair boundary
/livez//readyz, low-cardinality telemetry, and independent-route recovery without logging attacker header contents.SECURITY.md,THREAT_MODEL.md,API_CONFIG_CONTRACT.md,TEST_STRATEGY.md,OPERABILITY.md,TRD.md,CHANGELOG.md, TRACEABILITY, anddocs/product-technical-gap-baseline.mdcode-current with the exact supplier semantics and protocol scope.Responsibility boundary
This is reusable Ingress / Runtime Isolation / HTTP transport resource safety. It does not authorize product auth/business policy, Keyverse identity, Wardnet/EgressWeave decisions, cookie semantics, downstream TLS issuance, H2/H3/QUIC admission, or consumer source changes. Any supplier change must be immutable/provenance-bound and reconciled with
.github#1605before release.