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
+5
View File
@@ -39,6 +39,11 @@ use the defaults documented by the all-knob client reference.
- The daemon prints its effective configuration after validation, with no
command data or TLS material. Since v1 stores command/environment payloads in
plaintext, configuration output is hygiene rather than a secrecy guarantee.
- With an empty `tls.ca_file`, the client accepts a matching-host self-signed
server leaf. This provides TLS encryption and hostname routing only; v1 makes
no server-authentication or endpoint-ownership guarantee. Supplying a PEM CA
bundle restores normal CA-chain verification and is the preferred future
deployment model.
## Limits and cross-field validation
+2 -1
View File
@@ -17,7 +17,8 @@ max_queued_commands = 100
shutdown_grace = "30s"
[tls]
# Optional PEM CA bundle; empty uses the operating-system trust store.
# Optional PEM CA bundle. Empty permits a matching-host self-signed leaf in v1;
# this encrypts transport but does not authenticate server ownership.
ca_file = ""
# Optional certificate name override; empty derives it from server_url.
server_name = ""
+2 -1
View File
@@ -17,7 +17,8 @@ max_queued_commands = 100
shutdown_grace = "30s"
[tls]
# Optional PEM CA bundle; empty uses the Windows trust store.
# Optional PEM CA bundle. Empty permits a matching-host self-signed leaf in v1;
# this encrypts transport but does not authenticate server ownership.
ca_file = ""
# Optional certificate-name override; empty derives it from server_url.
server_name = ""
+39
View File
@@ -740,6 +740,45 @@ side effect must add a hook and coverage row before merging.
### 2.6 Native Windows test-host requirements
#### 2.6.0 Implemented current-controller native hierarchy lane
Implement scripts/windows/native-test as the first-class production-shaped
native gate. One run must create an immutable run directory, compile a
separately tagged fixture-only rvbox.exe in the pinned Docker toolchain, and
run the Linux server and nginx fixture from test/linux-server in a labeled
Docker Compose project on the current controller. Helium hosts only the
Windows VM and the VirtualBox Guest Control bridge: no RVBox server, proxy,
or Compose resource may be staged or run there. The local stack must create a
two-day matching-host self-signed leaf for the explicit current-controller
endpoint (x1.xcel.me by default, overridable by
RVBOX_NATIVE_ENDPOINT_HOST). It binds the configured test port on the current
controller and copies only rvbox.exe and client configuration to the Windows
guest test root.
The Windows service must connect through that WSS endpoint; controller-side
success is not enough. With no tls.ca_file configured, the v1 client must
accept the matching-host self-signed leaf while retaining hostname validation;
that is encrypted routing only and makes no claim that the endpoint is
authenticated. Wait for the client to become connected through the local
server's actual Unix rvc socket, issue real CMD commands, wait for durable
terminal success, and retain the resulting command status records. Verify,
in order: normal ACTIVE_USER; elevated ACTIVE_USER_ELEVATED; forced
ACTIVE_USER_ELEVATED preparation failure falling back to ACTIVE_SYSTEM; forced
ACTIVE_USER_ELEVATED plus ACTIVE_SYSTEM failure falling back to LOCAL_SYSTEM;
then log off the sole fixture console session and verify normal LOCAL_SERVICE
and elevated LOCAL_SYSTEM. The forced faults must be available only in the
separately tagged fixture binary, only before child-process creation, and only
for these two active elevated contexts. They are not a protocol field, TOML
knob, release-build behavior, or product broker.
On ordinary success collect bounded guest and local server/proxy artifacts,
remove only that labeled Compose project and its volumes, and restore the exact
snapshot. On failure retain the exact local stack and VM lease for recover;
clean must reset the fixture and retain artifacts, while an explicit purge with
a confirmation removes only the matching local run root. Add static
tests for the runner's file layout and tagged-build boundary, and promote the
native coverage row only after this lane passes on the documented VM.
Native Windows is mandatory for the Phase 4/5 gates. Development can begin with
unit tests and cross-compilation before a host is connected, but the Windows
supervisor/service/tray implementation cannot be called complete without it.
+59
View File
@@ -174,6 +174,65 @@ connectivity and CA-trust probe. The resulting service and artifact paths are
recorded in the run report and reclaimed by the snapshot reset rather than broad
guest deletion.
The first-class end-to-end controller is scripts/windows/native-test run
--run-id ID. It runs the per-run Linux server and nginx stack in Docker Compose
under test/linux-server on the current controller. Helium hosts only the
Windows VM and VirtualBox Guest Control bridge. The client connects to the
explicit current-controller WSS endpoint (x1.xcel.me by default), never the
DHCP guest address, and intentionally accepts that endpoint's matching-host
self-signed certificate in v1. The controller drives requests with the local
stack's rvc, collects bounded artifacts, and deletes just its labeled Compose
project during cleanup.
The test bundle never sends a Windows executable over the controller-to-Helium
SSH hop. The tagged fixture build strips symbol and DWARF tables; `test-host
stage` creates a temporary `xz -3` payload, publishes it to the authenticated
controller HTTP endpoint, and directs Helium to download it through its SOCKS5
acceleration proxy. Helium resumes the HTTP payload, verifies its compressed
SHA-256, atomically decompresses it into the exact host stage, then validates
the ordinary uncompressed bundle manifest before Guest Control copies files
into Windows. The baseline Helium host must provide `curl` and `xz`. Small
non-secret `client.toml` and optional CA files still use bounded-retry SSH
copies; executable staging fails closed if the accelerated route is unavailable.
Each successful stage prints `verified transfer_sha256` and the verified
manifest. No manual remote checksum check is needed for a normal or resumed
test run. The controller uses bounded SSH retries (four attempts, short
backoff) for idempotent inspection, staging, installation, and service-run
operations. Reset, stop, and logoff intentionally remain single-attempt;
after an interrupted lifecycle transition, use `recover` and decide whether to
resume or reset instead of replaying an ambiguous action.
For this controller/Helium fixture, the required executable route publishes
only the stripped, compressed test executable under the current controller's
Downloads HTTP endpoint
(`http://x1.xcel.me:9124`, authentication `x1:x1`) and asks Helium to fetch it
through its metered `socks5h://127.0.0.1:1085` proxy. The endpoint currently
advertises Basic authentication, so the harness deliberately uses curl's
`--anyauth` negotiation rather than assuming Digest. It never publishes
`client.toml`, CA material, passwords, or other configuration. Helium resumes
the HTTP download, verifies the compressed SHA-256, atomically decompresses it
into its stage, and the ordinary manifest check still runs before Guest
Control copies files into Windows. The uniquely named published artifact is
removed after successful guest staging (and on a subsequently failed stage).
`RVBOX_TEST_ACCEL_HTTP_URL`, `RVBOX_TEST_ACCEL_HTTP_AUTH`,
`RVBOX_TEST_ACCEL_HTTP_PUBLISH_DIR`, and `RVBOX_TEST_ACCEL_SOCKS5` override the
documented fixture defaults.
Early Windows-service failures are appended to
`C:\ProgramData\RVBox\service-startup.log`, before client config, durable
state, or normal observability logging begins. This is intentionally outside a
per-run bundle directory so the LocalSystem service can report an ACL/path
failure affecting that directory.
To prove the complete elevated fallback chain in one single-user fixture, the
controller builds a separately tagged disposable rvbox.exe. Its only extra
behavior is the internal --test-fail-contexts switch, which can force
ACTIVE_USER_ELEVATED and then ACTIVE_SYSTEM token preparation to fail before
launch. Release binaries reject the switch. The normal active-user,
active-user-elevated, active-system, local-system, local-service, and
logged-out local-system rows are therefore observed through the real SCM
service without adding a product broker or protocol field.
### Clean baseline and non-interactive installation
`rvboxtest` deliberately remains a split-token administrator. Guest Control
+39
View File
@@ -56,6 +56,37 @@ The bundle manifest records the source commit and SHA-256 of every bundled
file. It is a test artifact, not a signed release package; release signing,
version resources, and publication are Phase 8 gates.
The preferred complete native lane is now one command:
~~~sh
scripts/windows/native-test run --run-id windows-hierarchy
~~~
It builds a disposable fixture-tagged Windows binary in the pinned toolchain,
starts the real Linux server and nginx TLS proxy in Docker Compose under
test/linux-server on the current controller, and connects the Helium-hosted
NAT guest to the current controller's explicit endpoint (x1.xcel.me by
default). Helium hosts the VM only; it does not host any RVBox server
containers. The self-signed server certificate is intentionally accepted by
the v1 client without a test CA. It then drives the installed SCM service
through the server's real Unix control socket and verifies every Windows
execution context. The tagged binary's controlled pre-launch failures are
limited to the test fixture; a release binary rejects that switch.
Successful runs collect bounded artifacts, remove only their labeled Compose
project, and restore the exact clean snapshot. A failed or --keep run stays
recoverable:
~~~sh
scripts/windows/native-test recover --run-id windows-hierarchy
scripts/windows/native-test clean --run-id windows-hierarchy
scripts/windows/native-test clean --run-id windows-hierarchy --purge --yes
~~~
clean retains local artifacts by default. The explicit purge form removes only
the exact local run root after the local stack is down and the VM snapshot has
been restored.
The integration harness provides the Phase 0 `sample` suite, the incremental
Phase 2 `store` suite, and the incremental Phase 3 `server-session` suite.
The resumable E2E harness adds `smoke`, `script`, `recovery`, and `all`
@@ -180,6 +211,14 @@ also performs a bounded guest-to-nginx HTTPS/TCP readiness probe before it
starts the service. Wine and protocol stubs are not equivalent Windows
coverage.
For the hierarchy fixture only, run --fail-contexts
ACTIVE_USER_ELEVATED[,ACTIVE_SYSTEM] restarts the separately tagged test
service and forces the named token preparation step to fail before process
creation. This proves the real daemon's fallback order without changing the
wire protocol, normal client TOML, or release binary. The logoff action ends
the sole active fixture session so the LocalService and no-user LocalSystem
rows can be tested with the same running service.
The clean baseline intentionally contains no RVBox service, tray registration,
or RVBox state. Guest Control supplies `rvboxtest` with a filtered medium UAC
token, so it cannot safely perform the first machine-wide install. The fixture