diff --git a/scripts/e2e/proxy-swap.sh b/scripts/e2e/proxy-swap.sh index a40e5009a..a8e19f382 100755 --- a/scripts/e2e/proxy-swap.sh +++ b/scripts/e2e/proxy-swap.sh @@ -300,6 +300,11 @@ matrix() { import pathlib, sys # Accepted differences (P7-DEPL-03 lead ruling 2026-10-12): transport framing and Vary are proxy-owned, and Traefik # adds no response headers to a 101 upgrade, so a websocket row keeps only its handshake headers. +# Browsers do not apply CSP or X-Frame-Options from a websocket handshake response (they govern the document). However, +# Chromium learns HSTS from secure WebSocket handshakes and enforces it on subsequent requests +# (https://github.com/chromium/chromium/blob/main/net/websockets/websocket_end_to_end_test.cc#L670); the missing HSTS +# header on 101 responses is therefore an unresolved difference. Vary (D-0769) stays open until the traefik renderer decides +# whether to add Accept-Encoding; the matrix is tightened in the same change as the renderer. skip={'date','server','connection','content-length','transfer-encoding','keep-alive','vary'} handshake={'upgrade','sec-websocket-accept'} headers=[] diff --git a/test/e2e/sdk_compat_parity_test.go b/test/e2e/sdk_compat_parity_test.go new file mode 100644 index 000000000..bbbee1672 --- /dev/null +++ b/test/e2e/sdk_compat_parity_test.go @@ -0,0 +1,39 @@ +package e2e + +import ( + "os" + "testing" + + internalcompat "github.com/nself-org/cli/internal/compat" + sdkcompat "github.com/nself-org/cli/sdk/go/v2/compat" +) + +// TestSDKCopyAgreesInCLIProcess pins D-0705. The CLI links sdk/go/compat (the +// pin store ancestor gate in sdk/go/remote reads it), and that copy reads only +// NSELF_V15. Today both copies apply the same rule, so they agree for every +// value. If P7-SHIP flips this package's default without the sdk copy following +// (or the CLI exporting its resolved mode), the CLI would print the v1.4 +// ancestor warning where it must refuse. This test fails the moment they +// diverge, so the flip has to handle the sdk copy in the same change. +// +// Lives in test/e2e (L3) rather than internal/compat (L0) because L0 may not +// import the SDK module; see internal/repoqa/testdata/layers.yaml D1. +func TestSDKCopyAgreesInCLIProcess(t *testing.T) { + for _, v := range []string{"", "", "0", "1", "true", "TRUE", "True", "yes", "on", " 1"} { + t.Run(v, func(t *testing.T) { + if v == "" { + t.Setenv(internalcompat.EnvVar, "x") + if err := os.Unsetenv(internalcompat.EnvVar); err != nil { + t.Fatalf("unset %s: %v", internalcompat.EnvVar, err) + } + } else { + t.Setenv(internalcompat.EnvVar, v) + } + if cli, sdk := internalcompat.V15(), sdkcompat.V15(); cli != sdk { + t.Fatalf("NSELF_V15=%q: internal/compat.V15() = %v but sdk/go/compat.V15() = %v; "+ + "the CLI process links both (sdk/go/remote/knownhosts_compat.go, D-0484): "+ + "export the resolved mode to the sdk copy or delete the v1.4 branch in the same change (D-0705)", v, cli, sdk) + } + }) + } +}