The relay client's HTTP proxy dialed http://127.0.0.1:<FrontendPort> for
every proxied mobile request. With HTTPS_ENABLED the main listener serves
TLS on that port, so Go answered each plaintext dial with a bare
"Client sent an HTTP request to an HTTPS server" 400 - breaking Remote
Access backlog sync (alerts/approvals) on every HTTPS-enabled instance.
A non-loopback BIND_ADDRESS broke the same dial outright.
Route proxied requests through the router's own handler chain in-process
instead, via a streaming-capable RoundTripper (pipe-backed, SSE flush,
panic recovery, loopback RemoteAddr for address-keyed middleware). The
listener's scheme and bind address no longer matter, and the request
traverses exactly the middleware the real listener serves.
Reported by Johannes Strasser (Remote Access thread, 2026-07-14).
Six small refactors aggregated from a simplify-review pass over this
session's commits:
1. internal/config/persistence_relay.go — LoadRelayConfig had two
ApplyEnvOverrides call sites (one inside the not-exist branch, one
on the happy path) and a redundant cfg = DefaultConfig() reassignment.
Collapse to a single ApplyEnvOverrides call after the load attempt;
the file-absent branch already has the default cfg from line 1.
2. internal/relay/config_env.go — swap two strings.TrimSpace(os.Getenv(...))
calls for utils.GetenvTrim, matching the 30+ existing call sites in
internal/config/config.go. Trim narrating comments back to the
product-behavior sentences that aren't obvious from the code.
3. internal/relay/config_env_test.go — collapse seven near-identical
ApplyEnvOverrides scenarios into a single table-driven test
(TestApplyEnvOverridesTable). Reduces ~85 lines to ~60 and gives each
subcase a named t.Run for clearer failure output. Keeps the
nil-config-safe and parseEnvBool tests separate since they exercise
different surfaces.
4. .github/workflows/install-sh-smoke.yml — replace the /api/health
bash for-loop (sleep 2; curl; loop 30x) with a single
curl --retry 30 --retry-delay 2 --retry-connrefused --retry-all-errors
invocation. Curl already implements the same polling behaviour
natively; the bash loop was 13 lines of redundant scaffolding.
5. scripts/installtests/build_release_assets_test.go — extract the
repeated "read file, iterate required substrings, fail on first
miss" boilerplate into assertFileContainsAll(t, path, required...).
Migrate the four tests I added in this session; existing tests in
the file follow the same shape and can adopt the helper
incrementally without churning unrelated code in this commit. Also
updated the pinned curl string for the /api/health retry change.
Contract-neutral: every change preserves identical user-visible
behavior. PULSE_ALLOW_CONTRACT_NEUTRAL_COMMIT applied for the
canonical-shape-guard bypass; sensitivity, gitleaks, governance-stage,
control-plane, status, registry, contract, and pre-commit hooks still
run.
Verified locally:
- go test ./internal/relay/ ./internal/config/ → all pass
- go test ./scripts/installtests/ → all pass
- ruby -ryaml install-sh-smoke.yml → parses clean
These two env vars were documented as relay overrides in v6 docs since
March 18 (CONFIGURATION.md, RELAY.md, and the frontend-served doc copy)
but no code ever read them. Operators trying to bootstrap relay headlessly
saw no effect.
Implement them rather than remove the documentation. Headless and
container deployments now have a real path to enable relay and point it
at a private endpoint without going through Settings → Relay.
internal/relay/config_env.go:
- ApplyEnvOverrides(*Config) mutates relay.Config in place.
- PULSE_RELAY_ENABLED accepts true/false/yes/no/1/0/on/off (case-
insensitive). Unrecognized values log a warning and leave the file
value untouched — important so "unset" reads differently from
"explicit false."
- PULSE_RELAY_SERVER goes through the existing validateRelayServerURL
check; invalid URLs log a warning and fall through.
internal/config/persistence_relay.go:
LoadRelayConfig calls ApplyEnvOverrides after the file load and after
the default-fallback when relay.enc is absent, so the env override
applies on every load.
Tests cover unset / true / false / garbage-bool / valid-URL / invalid-URL
/ both-together / nil-config paths in the relay package, plus two
end-to-end tests in internal/config that prove the override flows through
LoadRelayConfig against a real persisted file and against the
missing-file default branch.
Restore the env-var docs with the correct default URL (the full
wss://relay.pulserelay.pro/ws/instance, not the bare hostname the
original aspirational table claimed) and add an explicit precedence note:
saving from the UI after an env override persists the env-effective state
to disk, so clearing the env alone does not revert.
Add internal/relay/config_env_test.go to the relay-runtime registry's
desktop-relay-runtime exact_files so the new code surface is proof-tracked.
Update the matching pin in subsystem_lookup_test.py. Extend the
relay-runtime contract Extension Point 3 to document the override
semantics LoadRelayConfig must satisfy.