Skip to content

Commit eee2509

Browse files
protoclaude
andcommitted
Promote S28: WebSocket-over-HTTP/3 (RFC 9220) COMPLETE — opt-in newness gate
WS-over-H3 Stage C (the carried relay wiring) built + verified end-to-end and promoted. The WebSocket transport matrix is now H1 (RFC 6455, shipped) + H2 (RFC 8441, gated) + H3 (RFC 9220, gated newness). Off-by-default (websocket.h3_extended_connect); when off the H3 front is byte-identical (R3). WHAT LANDED (dependency-inversion via closure injection — the approved design): - ws_tunnel.rs seam types + a WsRelayLauncher closure threaded QuicListenerParams -> RouterParams -> ActorParams (mirrors config_factory). - conn_actor pump_ws_tunnels: intercept a validated :protocol=websocket extended CONNECT, build the bounded H3WsTunnel, call the injected launcher (dials the H1 backend + completes the upstream RFC 6455 handshake BEFORE the 200 — the H3 analog of the WS-H1 GHSA / WS-H2 F-S27-1 ordering, R12), then relay both directions over the single-sourced lb_l7::ws_proxy::proxy_frames. Unknown :protocol -> 501; no launcher -> 502 (fail closed). - lb-l7 dial_backend_ws (keeps tokio-tungstenite out of the binary); lb build_ws_h3_launcher injected in wire_h3_terminate_backends' H1 arm. VERIFICATION (all from completed runs, R15): - Binding ×3 gate GREEN: 1496 passed / 0 failed / 18 ignored per run (+8 WS-H3 e2e tests, no regression R3); clippy --all-targets --all-features -D warnings; fmt clean. - Real-binary e2e through spawn_quic: echo-roundtrip, reset-vs-EOF (CleanClose vs Abrupt), 50× burst, R8 wired-tunnel backpressure (backend plateaus at ~63/512 under a stalled client + drains on resume — both directions bounded), 501, 502 (upstream-before-200), client-FIN-abnormal, no-launcher-fail-closed. - RFC 9220 conformance: audit/websockets/s28-rfc9220-conformance.md. - WS-H3 soak (sc8c_ws_h3) BOUNDED: 720s, ~600K echoes, 0 err, fds/RSS bounded, no leak, panic=0. - Scoped coverage 82.0% (>= 80% bar). FINDINGS (R4, none asterisked): 2 confirmed-correct gateway behaviors (WS Text UTF-8 enforcement; bare stream-FIN = abnormal close) + 1 LOW carried (CF-S28-WSH3-WAKEUP: the 2ms busy-poll while a tunnel is live; bounded, not a leak). REMAINS (S29): gRPC-over-H3 conformance (the program's LAST spec item). Own workstreams: CF-S27-2 (WS-H2 window-aware backpressure; until it lands WS-H2 stays gated), CF-QUICHE-UPGRADE, CF-DEP-1. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2 parents 5267147 + 06ba6f6 commit eee2509

99 files changed

Lines changed: 28777 additions & 23 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIBtTCCAVugAwIBAgIUcjiThVP3BF7bwuQQ1wYZjyalNCEwCgYIKoZIzj0EAwIw
3+
ITEfMB0GA1UEAwwWcmNnZW4gc2VsZiBzaWduZWQgY2VydDAgFw03NTAxMDEwMDAw
4+
MDBaGA80MDk2MDEwMTAwMDAwMFowITEfMB0GA1UEAwwWcmNnZW4gc2VsZiBzaWdu
5+
ZWQgY2VydDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABMPFNhTRk9hJhTfRB3XJ
6+
pqQtqThkMhd7E731UP9ExzARSM9WZwJzbCJkZT9mrCMm2a7fVbgu0nsUoqZh2c3V
7+
dJCjbzBtMCYGA1UdEQQfMB2HBH8AAAGCCWxvY2FsaG9zdIIKc29hay1mcm9udDAT
8+
BgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQU/4Rt5OOwDAurav6bzvOj+WFU
9+
laswDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiBT+jgINqZ6u6Xd
10+
3BpXCnAaunZ94p5GDEAYyjS3oQH2NAIhAN17ZutnzSxvZi9j5Hadhc4EFuS3Jnzz
11+
ddMPxH9BDO7+
12+
-----END CERTIFICATE-----
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIBtTCCAVugAwIBAgIUcjiThVP3BF7bwuQQ1wYZjyalNCEwCgYIKoZIzj0EAwIw
3+
ITEfMB0GA1UEAwwWcmNnZW4gc2VsZiBzaWduZWQgY2VydDAgFw03NTAxMDEwMDAw
4+
MDBaGA80MDk2MDEwMTAwMDAwMFowITEfMB0GA1UEAwwWcmNnZW4gc2VsZiBzaWdu
5+
ZWQgY2VydDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABMPFNhTRk9hJhTfRB3XJ
6+
pqQtqThkMhd7E731UP9ExzARSM9WZwJzbCJkZT9mrCMm2a7fVbgu0nsUoqZh2c3V
7+
dJCjbzBtMCYGA1UdEQQfMB2HBH8AAAGCCWxvY2FsaG9zdIIKc29hay1mcm9udDAT
8+
BgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQU/4Rt5OOwDAurav6bzvOj+WFU
9+
laswDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiBT+jgINqZ6u6Xd
10+
3BpXCnAaunZ94p5GDEAYyjS3oQH2NAIhAN17ZutnzSxvZi9j5Hadhc4EFuS3Jnzz
11+
ddMPxH9BDO7+
12+
-----END CERTIFICATE-----
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[runtime]
2+
drain_timeout_ms = 5000
3+
readiness_settle_ms = 100
4+
5+
[[listeners]]
6+
address = "127.0.0.1:46915"
7+
protocol = "quic"
8+
9+
[listeners.quic]
10+
cert_path = "audit/soak/s28-soak-data/sc7_cmp-work/cert.pem"
11+
key_path = "audit/soak/s28-soak-data/sc7_cmp-work/key.pem"
12+
retry_secret_path = "audit/soak/s28-soak-data/sc7_cmp-work/retry.bin"
13+
14+
[observability]
15+
metrics_bind = "127.0.0.1:43357"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgHO0erqxxWDOo5Sig
3+
gtEVr1q1l1cWjA/xWRhU4BvaxKyhRANCAATDxTYU0ZPYSYU30Qd1yaakLak4ZDIX
4+
exO99VD/RMcwEUjPVmcCc2wiZGU/ZqwjJtmu31W4LtJ7FKKmYdnN1XSQ
5+
-----END PRIVATE KEY-----
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
�۫�}���x��Βy�&�:xX�*��Ӄ�
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
t_secs,rss_kb,vmhwm_kb,fds,threads,panic_total
2+
0.000,8140,8140,11,9,0
3+
10.001,17720,18472,11,9,0
4+
20.002,18648,19544,12,9,0
5+
25.001,19252,19544,11,9,0
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
scenario=sc7_h3terminate duration_secs=25 samples=4 overall=BOUNDED
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
=== SOAK sc7_h3terminate — BOUNDED (25s, 4 samples) ===
2+
rss_kb [INCONCLUSIVE] rss_kb: only 4 steady-state samples (< 8 required) — first=8140 last=19252 min=8140 max=19252
3+
vmhwm_kb [INCONCLUSIVE] vmhwm_kb: only 4 steady-state samples (< 8 required) — first=8140 last=19544 min=8140 max=19544
4+
fds [INCONCLUSIVE] fds: only 4 steady-state samples (< 8 required) — first=11 last=11 min=11 max=12
5+
threads [INCONCLUSIVE] threads: only 4 steady-state samples (< 8 required) — first=9 last=9 min=9 max=9
6+
panic_total [BOUNDED] panic_total: stayed zero across the run — first=0 last=0 min=0 max=0
7+
load:
8+
h3_load: ok=176 err=0
9+
h3_reset_flood: ok=400336 err=0
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
{
2+
"scenario": "sc7_h3terminate",
3+
"label": "sc7_cmp",
4+
"duration_secs": 25,
5+
"sample_secs": 10,
6+
"scale": 1,
7+
"samples": 4,
8+
"overall": "BOUNDED",
9+
"columns": [
10+
{
11+
"column": "rss_kb",
12+
"kind": "trend",
13+
"verdict": "INCONCLUSIVE",
14+
"n": 4,
15+
"first": 8140.0,
16+
"last": 19252.0,
17+
"min": 8140.0,
18+
"max": 19252.0,
19+
"first_third_median": 0.0,
20+
"last_third_median": 0.0,
21+
"rel_growth": 0.0,
22+
"slope_per_sample": 3426.4,
23+
"monotone_frac": 1.0,
24+
"note": "rss_kb: only 4 steady-state samples (< 8 required)"
25+
},
26+
{
27+
"column": "vmhwm_kb",
28+
"kind": "trend",
29+
"verdict": "INCONCLUSIVE",
30+
"n": 4,
31+
"first": 8140.0,
32+
"last": 19544.0,
33+
"min": 8140.0,
34+
"max": 19544.0,
35+
"first_third_median": 0.0,
36+
"last_third_median": 0.0,
37+
"rel_growth": 0.0,
38+
"slope_per_sample": 3528.4,
39+
"monotone_frac": 1.0,
40+
"note": "vmhwm_kb: only 4 steady-state samples (< 8 required)"
41+
},
42+
{
43+
"column": "fds",
44+
"kind": "trend",
45+
"verdict": "INCONCLUSIVE",
46+
"n": 4,
47+
"first": 11.0,
48+
"last": 11.0,
49+
"min": 11.0,
50+
"max": 12.0,
51+
"first_third_median": 0.0,
52+
"last_third_median": 0.0,
53+
"rel_growth": 0.0,
54+
"slope_per_sample": 0.1,
55+
"monotone_frac": 0.6666666666666666,
56+
"note": "fds: only 4 steady-state samples (< 8 required)"
57+
},
58+
{
59+
"column": "threads",
60+
"kind": "trend",
61+
"verdict": "INCONCLUSIVE",
62+
"n": 4,
63+
"first": 9.0,
64+
"last": 9.0,
65+
"min": 9.0,
66+
"max": 9.0,
67+
"first_third_median": 0.0,
68+
"last_third_median": 0.0,
69+
"rel_growth": 0.0,
70+
"slope_per_sample": 0.0,
71+
"monotone_frac": 1.0,
72+
"note": "threads: only 4 steady-state samples (< 8 required)"
73+
},
74+
{
75+
"column": "panic_total",
76+
"kind": "counter_must_be_zero",
77+
"verdict": "BOUNDED",
78+
"n": 4,
79+
"first": 0.0,
80+
"last": 0.0,
81+
"min": 0.0,
82+
"max": 0.0,
83+
"first_third_median": 0.0,
84+
"last_third_median": 0.0,
85+
"rel_growth": 0.0,
86+
"slope_per_sample": 0.0,
87+
"monotone_frac": 1.0,
88+
"note": "panic_total: stayed zero across the run"
89+
}
90+
],
91+
"load": [
92+
{
93+
"name": "h3_load",
94+
"ok": 176,
95+
"err": 0
96+
},
97+
{
98+
"name": "h3_reset_flood",
99+
"ok": 400336,
100+
"err": 0
101+
}
102+
]
103+
}

0 commit comments

Comments
 (0)