Skip to content

migration: prove release-qualified WebSocket transport before enabling Upgrade #112

Description

@seonghobae

Refs #28, #9, #58, #113.

Finding / authority boundary

The current gateway contract remains correctly fail-closed for uncharacterized HTTP/1 Upgrade. This issue owns the future reusable transport acceptance required before any versioned WebSocket enablement. It does not relax #28, enable Upgrade today, copy product authentication/business routing into the gateway, or move Keyverse/Wardnet/EgressWeave authority into transport delivery.

Consumer evidence remains product-owned. ContextualWisdomLab/naruon#1507 is the product-owner path, while pingora-gateway#9 records that one Naruon live-E2E Nginx path forwards WebSocket Upgrade/Connection and uses 600 s read/send timeouts. That does not establish the Kubernetes ingress or Traefik/Keycloak topology, and it does not make 600 s a reusable gateway timeout policy.

Current released-supplier RED is now source-bound and reproducible

The previous gap was not only that Pingora's HTTP/1 fast-101 path was suspected to fail, but that this repository lacked a source-bound real-wire oracle. #113 now closes that characterization gap only.

At exact #113@fbad4e031927b0a92adc7244224d2bfdaba7d513:

  • ordinary CI 35431884205: SUCCESS;
  • Supply Chain 35431884180: SUCCESS;
  • PgErd bounded-origin capacity 35431884182: SUCCESS;
  • dedicated WebSocket fast-101 Supplier Characterization 35431884211 / job 105867851370: SUCCESS in expected-RED receipt semantics.

The dedicated job verified exact checkout, proved that the default all-target graph excludes the feature-gated supplier RED, compiled the focused test, and ran only released_pingora_keeps_fast_101_upgrade_tunnel_bidirectional. Released Pingora 0.9.0 then reproduced the bounded post-101 failure client server-frame prefix closed before the frame completed; the focused Rust test result was FAILED exactly as the characterization predicate requires. Artifact 10585145835 (websocket-fast-101-supplier-red-fbad4e031927b0a92adc7244224d2bfdaba7d513) has SHA-256 643e78ee94d3289f69827e3c21aa3651422b62f2804aa6deea7b29c77b0cedb5.

This is not WebSocket capability GREEN. It proves that the unchanged current acceptance reliably fails on released Pingora 0.9.0 while ordinary repository CI remains GREEN.

Fresh supplier authority is still unresolved:

  • cloudflare/pingora#946 remains open and describes the same scheduling-sensitive HTTP/1 upgrade teardown when upstream 101 wins against empty request-body completion;
  • proposed repair cloudflare/pingora#947@1e8488b0627370831832744fc6e65614396c310d remains open/unmerged and is mutable contributor evidence only;
  • protected cloudflare/pingora/main remains 4487f7b2ab50f159e4a2cf4f6a6b813f61bb6e19;
  • latest public release remains Pingora 0.9.0, published 2026-09-09, so there is still no later release-qualified supplier identity containing a maintainer disposition for this defect.

Do not pin #947, vendor/copy its patch, weaken #28's Upgrade rejection, or convert the expected-RED receipt into capability/release credit.

Standards boundary

The transport forms remain distinct contracts:

  1. HTTP/1.1 WebSocket uses the RFC 6455 opening handshake over HTTP Upgrade. RFC 9931 reinforces that HTTP/1.1 protocol-transition data must not be sent optimistically before the transition is accepted; RFC 6455 already requires the client to wait for the server response before sending WebSocket data.
  2. HTTP/2 WebSocket uses RFC 8441 Extended CONNECT on one H2 stream, including SETTINGS_ENABLE_CONNECT_PROTOCOL=1 and :protocol = websocket. HTTP/1 Connection/Upgrade/101 semantics are not the H2 wire contract.
  3. HTTP/3 WebSocket uses RFC 9220's adaptation of Extended CONNECT and is a separate QUIC/H3 capability lane.

RFC 9110/9112 remain the HTTP semantics/HTTP/1.1 basis. H2 or H3 capability must never be inferred from HTTP/1 acceptance or generic downstream TLS/H2 support elsewhere in the stack.

Current RED acceptance

  1. v1 and current pg-erd versions intentionally reject HTTP/1 Upgrade before origin contact; no released versioned config admits WebSocket.
  2. test: reproduce Pingora fast-101 WebSocket tunnel teardown #113 now provides a source-bound, exact-SHA, real-wire fast-101 RED oracle against released Pingora 0.9.0, and that oracle currently fails as expected after the 101 transition.
  3. There is still no maintainer-integrated, release-qualified supplier repair that makes the unchanged test: reproduce Pingora fast-101 WebSocket tunnel teardown #113 acceptance GREEN.
  4. There is no reusable gateway acceptance yet for long-lived flow, bounded buffering/backpressure, client/origin disconnect propagation in both directions, half-close/abnormal reset, SIGTERM/drain, readiness with admitted tunnels, or payload-safe observability.
  5. Naruon E2E evidence does not establish Kubernetes ingress WebSocket behavior, production timeout values, TLS/SNI/certificate ownership, H2 Extended CONNECT, H3, or deployment rollback.
  6. HTTP/2 and HTTP/3 WebSocket capability remain independent RED→GREEN contracts.

GREEN acceptance

Only after a maintainer-owned supplier disposition exists in a release-qualified Pingora identity:

  1. reconcile the current supplier-characterization lane onto current release ancestry and rerun the unchanged test: reproduce Pingora fast-101 WebSocket tunnel teardown #113 real-wire acceptance against that exact supplier; fast-101 ordering must become GREEN under constrained CPU and realistic concurrency rather than by deleting the oracle, delaying 101 artificially, changing fingerprints, or widening timeouts;
  2. add an explicit versioned gateway capability that admits WebSocket only for consumer-derived routes/profiles; omission remains fail-closed and request data cannot select arbitrary tunnel destinations;
  3. prove valid 101 followed by bidirectional application frames, plus client-close, origin-close, abnormal reset and half-close behavior with no leaked task/connection, silent replay/failover, unrelated-route poisoning, or unbounded recovery;
  4. prove bounded backpressure/flow behavior for long-lived traffic without whole-message buffering, with timeout semantics derived from consumer contracts rather than copied from the Nginx 600 s fixture;
  5. prove SIGTERM/drain with admitted tunnels, /livez//readyz, rootless/read-only OCI execution, low-cardinality transport observability, and no payload/cookie/token/customer-data logging;
  6. prove HTTP/2 Extended CONNECT separately: SETTINGS_ENABLE_CONNECT_PROTOCOL=1, correct CONNECT + :protocol=websocket admission, stream-local cancellation/backpressure, sibling-stream survival, and no HTTP/1 Upgrade-field emulation;
  7. prove HTTP/3/RFC 9220 separately; no H3/QUIC support or cutover credit exists until the selected runtime exposes and verifies it;
  8. exact-head formatting, compile/test, strict Clippy, warning-denied rustdoc, 100% owned-production line+region coverage, realistic concurrency/load/failure traffic, OCI, Supply/Security and current-range review remain mandatory;
  9. after an immutable gateway release, each consumer owner must still prove its own parity → shadow/canary → observed rollback → cutover → legacy-proxy removal. This issue can only supply reusable transport capability.

DDD ownership remains in HTTP Policy / Runtime Isolation / Ingress delivery / Observability. WebSocket application authorization, subprotocol business meaning, tenant/session policy, product timeout choices and deployment rollback remain product-owned.

Keep this issue open and status: blocked until supplier release authority and the complete reusable transport acceptance are GREEN. The newly settled #113 receipt removes uncertainty about whether the 0.9.0 RED is reproducible; it does not remove the blocker.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions