Skip to content

feat(proxy): add /health endpoint for liveness checks#9

Merged
emretinaztepe merged 1 commit into
mainfrom
feature/wardgate-proxy-health-endpoint
May 27, 2026
Merged

feat(proxy): add /health endpoint for liveness checks#9
emretinaztepe merged 1 commit into
mainfrom
feature/wardgate-proxy-health-endpoint

Conversation

@emretinaztepe

Copy link
Copy Markdown

Summary

Adds a local GET /health endpoint to wardgate-proxy so sidecars (e.g. the Fleet sandbox boot sequence) can confirm the proxy is up and serving HTTP before it starts trusting the proxy with sealed credentials.

What it does

  • Mounts an http.ServeMux in wardgate-proxy that handles GET /health locally with a small JSON payload ({"status":"ok","service":"wardgate-proxy","version":"…"}).
  • All other paths continue to flow through the existing ReverseProxy handler — no behavior change for real traffic.
  • The endpoint performs no upstream call and requires no agent key, so it's safe to expose on the listen socket.
  • HEAD /health returns 200 with no body; non-GET/HEAD methods get 405 with Allow: GET, HEAD.

Why

Fleet's sandbox boot currently launches wardgate-proxy and immediately moves on to start OpenCode with sealed env vars. If the proxy never binds — or binds and then crashes on its first request — OpenCode's first sealed call goes to a dead socket and the failure surfaces in confusing ways. With this endpoint, the boot can do:

await proc.waitForPort(80, { mode: "http", path: "/health" });

so wardgate-proxy readiness is a hard precondition for downstream steps. Same pattern recommended in Fleet's pre-pentest audit F-06 fix-up (startup self-test that confirms the proxy is on path).

Tests

  • TestHealthHandler_ReturnsOK — 200 + application/json + payload shape.
  • TestHealthHandler_HEADReturnsNoBody — HEAD returns 200, empty body.
  • TestHealthHandler_RejectsNonGET — POST returns 405 with Allow: GET, HEAD.
  • TestBuildMux_HealthBypassesProxy/health is served locally and never hits the upstream.
  • TestBuildMux_NonHealthGoesToProxy — every other path still flows through the reverse-proxy with the agent's JWT injected.

Test plan

  • go test ./cmd/wardgate-proxy/... -count=1 passes locally
  • Existing proxy handler tests still pass (no behavior change for non-/health traffic)
  • Reviewer: confirm /health is acceptable as a reserved path (no real upstream that wardgate fronts uses /health as a meaningful route in our deployments)

🤖 Generated with Claude Code

Mount a local http.ServeMux on wardgate-proxy that serves GET /health
with a small JSON payload (status, service, version) and falls through
to the existing reverse-proxy handler for every other path. The endpoint
performs no upstream call and requires no agent key, so callers on the
local listen socket can confirm wardgate-proxy is on path before
forwarding real traffic.

Use case: sandbox sidecars that gate boot on wardgate-proxy readiness
can now waitForPort(80, { mode: "http", path: "/health" }) instead of
relying on a TCP probe that succeeds the instant the socket binds.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
-e
Signed-off-by: Emre Tinaztepe <emre@binalyze.com>
@emretinaztepe
emretinaztepe merged commit ccdc33e into main May 27, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant