feat: add native Windows hierarchy test harness

This commit is contained in:
2026-09-09 16:48:54 +00:00
parent 8985457d37
commit 409b64a2fb
30 changed files with 1033 additions and 44 deletions
+8 -2
View File
@@ -590,8 +590,14 @@ tests = ["internal/client/spool/spool_test.go:TestSendWindowPinsUnacknowledgedBy
[[requirements]]
id = "HP-WINCTX-02"
layer = "integration"
status = "blocked_native_windows"
tests = []
status = "planned"
tests = ["test/windowsnative/native_fixture_test.go:TestNativeFixtureAssets_HP_HARNESS_20"]
[[requirements]]
id = "HP-HARNESS-20"
layer = "unit"
status = "implemented"
tests = ["test/windowsnative/native_fixture_test.go:TestNativeFixtureAssets_HP_HARNESS_20"]
[[requirements]]
id = "HP-STORE-01"
+11
View File
@@ -0,0 +1,11 @@
# Linux server native-test stack
This directory owns the Docker Compose stack for the Windows native E2E lane.
It runs on the current Linux controller and owns the Linux RVBox server, nginx
TLS proxy with a per-run matching-host self-signed leaf, SQLite/segment state,
control socket, and logs. The v1 client deliberately accepts this self-signed
leaf when no CA file is configured; it is encrypted transport, not server
authentication.
The Helium VM never hosts this stack. It receives only rvbox.exe and client
TOML through the Windows fixture controller.
+13
View File
@@ -0,0 +1,13 @@
#!/bin/sh
set -eu
test -f /pki/server.pem && test -f /pki/server-key.pem && exit 0
apk add --no-cache openssl
umask 077
openssl genrsa -out /pki/server-key.pem 2048
openssl req -x509 -new -key /pki/server-key.pem -sha256 -days 2 \
-subj "/CN=${RVBOX_NATIVE_ENDPOINT_HOST:?}" \
-addext "subjectAltName=DNS:${RVBOX_NATIVE_ENDPOINT_HOST}" \
-out /pki/server.pem
chmod 600 /pki/*key.pem
chmod 644 /pki/server.pem
+37
View File
@@ -0,0 +1,37 @@
# Per-run production-shaped Linux server/proxy fixture. It runs on the current
# controller; the Windows VM receives only its client bundle.
services:
server:
image: alpine:3.22
user: "${RVBOX_NATIVE_UID:-65532}:${RVBOX_NATIVE_GID:-65532}"
command: ["/opt/rvbox/rvbox-server", "--config", "/etc/rvbox/server.toml"]
volumes:
- ../../bin/rvbox-server:/opt/rvbox/rvbox-server:ro
- ../../bin/rvc:/opt/rvbox/rvc:ro
- "${RVBOX_NATIVE_RUNTIME_DIR}/server.toml:/etc/rvbox/server.toml:ro"
- "${RVBOX_NATIVE_RUNTIME_DIR}/state:/state"
- "${RVBOX_NATIVE_RUNTIME_DIR}/state/control:/run/rvbox"
networks: [native]
labels: { rvbox.native.run_id: "${RVBOX_NATIVE_RUN_ID}" }
nginx:
image: nginx:1.27-alpine
depends_on: [server]
ports: [ "${RVBOX_NATIVE_BIND:-0.0.0.0}:${RVBOX_NATIVE_PORT}:443" ]
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
- "${RVBOX_NATIVE_RUNTIME_DIR}/pki/server.pem:/etc/nginx/tls/server.pem:ro"
- "${RVBOX_NATIVE_RUNTIME_DIR}/pki/server-key.pem:/etc/nginx/tls/server-key.pem:ro"
networks: [native]
labels: { rvbox.native.run_id: "${RVBOX_NATIVE_RUN_ID}" }
certgen:
image: alpine:3.22
profiles: [tools]
environment:
RVBOX_NATIVE_ENDPOINT_HOST: "${RVBOX_NATIVE_ENDPOINT_HOST}"
volumes:
- "${RVBOX_NATIVE_RUNTIME_DIR}/pki:/pki"
- ./certgen.sh:/fixture/certgen.sh:ro
entrypoint: ["/bin/sh", "/fixture/certgen.sh"]
networks:
native:
labels: { rvbox.native.run_id: "${RVBOX_NATIVE_RUN_ID}" }
+21
View File
@@ -0,0 +1,21 @@
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl;
server_name _;
ssl_certificate /etc/nginx/tls/server.pem;
ssl_certificate_key /etc/nginx/tls/server-key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
location = /v1/agent {
proxy_pass http://server:6899;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_read_timeout 75s;
proxy_send_timeout 15s;
}
location / { return 404; }
}
+56
View File
@@ -0,0 +1,56 @@
package windowsnative
import (
"os"
"path/filepath"
"strings"
"testing"
)
// TestNativeFixtureAssets_HP_HARNESS_20 prevents the host-side controller from
// drifting back to a PowerShell-only or protocol-stub lane. It intentionally
// checks only static contracts; the real hierarchy proof remains the documented
// native VM run.
func TestNativeFixtureAssets_HP_HARNESS_20(t *testing.T) {
t.Parallel()
root := filepath.Clean(filepath.Join("..", ".."))
read := func(relative string) string {
t.Helper()
data, err := os.ReadFile(filepath.Join(root, relative))
if err != nil {
t.Fatalf("read %s: %v", relative, err)
}
return string(data)
}
runner := read("scripts/windows/native-test")
for _, required := range []string{
"scripts/windows/build-test-bundle\" --native-fixture",
"scripts/windows/test-host\" prepare",
"ACTIVE_USER_ELEVATED,ACTIVE_SYSTEM",
"assert_context local-service no local-service",
"clean --purge --yes",
"RVBOX_NATIVE_ENDPOINT_HOST",
"test/linux-server/compose.yaml",
} {
if !strings.Contains(runner, required) {
t.Fatalf("native runner is missing %q", required)
}
}
testHost := read("scripts/windows/test-host")
for _, required := range []string{"xz -T0 -3", "accelerated_stage", "copy_stage_file", "--proxy", "--anyauth", "--continue-at", "rvbox.exe.xz", "retry_limit=4", "ConnectTimeout=10", "bundle transfer did not reach the expected SHA-256 manifest", "verified transfer_sha256"} {
if !strings.Contains(testHost, required) {
t.Fatalf("native test-host is missing compressed transfer contract %q", required)
}
}
compose := read("test/linux-server/compose.yaml")
for _, required := range []string{"../../bin/rvbox-server", "nginx:1.27-alpine", "rvbox.native.run_id", "RVBOX_NATIVE_RUNTIME_DIR"} {
if !strings.Contains(compose, required) {
t.Fatalf("native Compose fixture is missing %q", required)
}
}
defaults := read("internal/client/supervisor/windows/testfaults_default.go")
fixture := read("internal/client/supervisor/windows/testfaults_fixture.go")
if !strings.Contains(defaults, "//go:build !rvbox_native_test") || !strings.Contains(fixture, "//go:build rvbox_native_test") {
t.Fatal("fixture-only context faults are not separated from release builds")
}
}