Skip to content

fix(agent): trim unauthenticated /health payload to bare status#275

Open
jaredglaser wants to merge 3 commits into
mainfrom
fix/f3-agent-health-payload
Open

fix(agent): trim unauthenticated /health payload to bare status#275
jaredglaser wants to merge 3 commits into
mainfrom
fix/f3-agent-health-payload

Conversation

@jaredglaser

Copy link
Copy Markdown
Owner

Summary

  • Agent /health (intentionally unauthenticated) previously returned the agent version, Docker engine/API versions, and ZFS capability detail. It now returns only { status: "healthy" | "unhealthy" } with the same 200/503 semantics, so liveness consumers (agent-updater health-reporter, the agent Dockerfile HEALTHCHECK, worker dev-seed) keep working unchanged.
  • Added an authenticated GET /info endpoint on the agent that carries the previous detail payload (agentVersion, Docker and ZFS capabilities). The auth middleware only bypasses /health, so /info requires a valid JWT; a middleware test asserts this.
  • Updated the shared contract types in agent/src/types.ts: AgentHealthCheckResponse is now status-only and a new AgentInfoResponse describes /info. The old AgentHealthyResponse/AgentUnhealthyResponse types did not match what the agent actually returned.
  • AgentClient.health() now queries /info (it always has a signer) and reads agentVersion.
  • checkAgentHealth() in the web app still probes /health for liveness, and accepts an optional token minter to fetch version/Docker version from /info afterward. Failures on /info (no keypair enrolled yet, older agent, network error) never affect the healthy verdict.
  • Host server functions (addHost, updateAgent, checkHostHealth) wire a per-host JWT signer into the health check, so agent version reporting in Settings -> Managed Hosts is preserved (and now actually populated; the old code read a version field the agent never sent).
  • Updated the agent endpoint table in docs/architecture.md.

Testing

  • bun run typecheck and bun run typecheck:agent: pass.
  • Agent: full suite bun test --isolate (269 pass), including new handleInfo tests, status-only /health assertions, and a middleware test that /info requires auth.
  • Web: agent-health-service.test.ts (liveness plus new authenticated /info paths: bearer token, 401, non-JSON, token minting failure, no /info call when /health fails), agent-client.test.ts (health() hits /info), handlers.test.ts, host-utils.test.ts: all pass.

Closes #230

🤖 Generated with Claude Code

The /health endpoint bypasses auth so the agent-updater and Docker
healthchecks can probe liveness, but it also returned the agent version,
Docker engine/API versions, and ZFS capability detail to anyone who
could reach the port. That detail now lives on a new authenticated
GET /info endpoint; /health returns only { status } with the same
200/503 semantics, so liveness consumers (agent-updater, Dockerfile
HEALTHCHECK, dev-seed) keep working unchanged.

Web callers that read version info were updated to preserve behavior:
AgentClient.health() now queries /info with its existing signer, and
checkAgentHealth() accepts an optional token minter so host health
checks fetch version/capability detail from /info after the liveness
probe. Hosts without an enrolled keypair still get a liveness verdict,
just without version info.

Closes #230

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@jaredglaser, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 56 minutes and 15 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0db629aa-2195-45df-8277-d0d94d506b84

📥 Commits

Reviewing files that changed from the base of the PR and between 5d66d9f and 37fbe05.

📒 Files selected for processing (13)
  • agent/src/__tests__/health.test.ts
  • agent/src/__tests__/middleware.test.ts
  • agent/src/index.ts
  • agent/src/routes/health.ts
  • agent/src/types.ts
  • docs/architecture.md
  • src/data/hosts/__tests__/handlers.test.ts
  • src/data/hosts/functions.tsx
  • src/data/hosts/handlers.ts
  • src/lib/clients/__tests__/agent-client.test.ts
  • src/lib/clients/agent-client.ts
  • src/lib/services/__tests__/agent-health-service.test.ts
  • src/lib/services/agent-health-service.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/f3-agent-health-payload

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

claude added 2 commits June 20, 2026 19:22
- Validate /health body shape at runtime: check body.status === 'healthy'
  rather than just parsing JSON, so an unrelated server returning 200
  with arbitrary JSON is rejected
- Guard handleUpdateAgent retry loop against undefined version: a
  transient /info failure returns version: undefined, which must not be
  treated as a version change or the loop exits prematurely
- Log /info HTTP errors and network failures via console.error so
  operators can diagnose missing version info in Managed Hosts; getToken
  failures remain silent (expected for pending/unenrolled hosts)
- Fix missing expectedAudience arg in new middleware test for /info
- Add tests: /health body shape validation, console.error logging for
  /info failures, no logging on getToken throws, hostName forwarding in
  handleRefreshHostStatus, undefined-version guard in update loop

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016xMT3rEMsfcBMLhLTHqTtk
The PR branch authenticateRequest takes 3 args (no expectedAudience);
the cherry-pick left HOST references from the main-branch version.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016xMT3rEMsfcBMLhLTHqTtk
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.

Trim unauthenticated agent /health payload

2 participants