Skip to content

feat(toolkit): add REST healthcheck infrastructure#4167

Open
refur-nfn wants to merge 1 commit into
constructorfabric:mainfrom
refur-nfn:add-rest-healthcheck
Open

feat(toolkit): add REST healthcheck infrastructure#4167
refur-nfn wants to merge 1 commit into
constructorfabric:mainfrom
refur-nfn:add-rest-healthcheck

Conversation

@refur-nfn

@refur-nfn refur-nfn commented Jun 30, 2026

Copy link
Copy Markdown
  • Concurrent healthcheck execution with timeout protection
  • HealthcheckRegistry for registering and running per-gear probes
  • Message sanitization to prevent secret leaks in responses
  • API Gateway integration for /health and /readyz endpoints
  • Comprehensive test coverage with panic/timeout/degradation scenarios

Summary by CodeRabbit

  • New Features
    • Added readiness-focused /health, /healthz, and /readyz endpoints with JSON status, RFC3339 timestamp, and per-component details.
    • Introduced a shared readiness healthcheck registry and a new REST readiness hook for services to publish checks.
    • Ensured health endpoints remain reachable at root paths even when the gateway is configured with a non-root prefix.
  • Bug Fixes
    • Health responses now consistently reflect aggregated healthy/degraded/unhealthy readiness with correct 200 vs 503.
  • Tests
    • Added integration tests covering endpoint behavior, aggregation semantics, prefix handling, and readiness hook default/override behavior.

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 426a7340-f0d7-43cd-adfc-a60c94fe3e6d

📥 Commits

Reviewing files that changed from the base of the PR and between 36b1e50 and 5254ada.

📒 Files selected for processing (7)
  • gears/system/api-gateway/src/gear.rs
  • gears/system/api-gateway/src/web.rs
  • gears/system/api-gateway/tests/health_endpoints.rs
  • libs/toolkit/src/contracts.rs
  • libs/toolkit/src/healthcheck.rs
  • libs/toolkit/src/lib.rs
  • libs/toolkit/src/runtime/host_runtime.rs
💤 Files with no reviewable changes (7)
  • libs/toolkit/src/lib.rs
  • libs/toolkit/src/contracts.rs
  • gears/system/api-gateway/tests/health_endpoints.rs
  • libs/toolkit/src/runtime/host_runtime.rs
  • libs/toolkit/src/healthcheck.rs
  • gears/system/api-gateway/src/web.rs
  • gears/system/api-gateway/src/gear.rs

📝 Walkthrough

Walkthrough

Adds a shared readiness healthcheck registry in toolkit, wires it through REST runtime setup and the API gateway, and replaces the gateway’s static health response with registry-backed /health, /healthz, and /readyz endpoints.

Changes

REST Readiness Healthcheck

Layer / File(s) Summary
Healthcheck types, trait, and RestApiCapability hook
libs/toolkit/src/healthcheck.rs, libs/toolkit/src/lib.rs, libs/toolkit/src/contracts.rs
Defines healthcheck status types, result and report structs, the registry module exports, and adds the optional healthcheck() hook to RestApiCapability.
Registry execution, caching, and sanitization
libs/toolkit/src/healthcheck.rs
Implements registry storage, cached reporting, concurrent execution, timeout handling, aggregate status computation, message sanitization, and unit tests for registry behavior.
Runtime registry creation and gear registration
libs/toolkit/src/runtime/host_runtime.rs
run_rest_phase creates a shared RestHealthcheckRegistry, publishes it to ClientHub, and registers each gear’s healthcheck after route setup.
Gateway health handlers and router lifecycle
gears/system/api-gateway/src/web.rs, gears/system/api-gateway/src/gear.rs
Replaces the static health handler with registry-backed /health and /readyz responses, stores the shared registry on ApiGateway, and threads it through router construction, public route policy, and REST prepare/finalize wiring.
Gateway health endpoint coverage
gears/system/api-gateway/tests/health_endpoints.rs
Tests the API gateway health endpoints across readiness states and prefix paths, and verifies RestApiCapability healthcheck defaults and overrides.

Estimated code review effort: 4 (Complex) | ~60 minutes

Suggested reviewers: mattgarmon, aviator5

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding REST healthcheck infrastructure in toolkit.
Docstring Coverage ✅ Passed Docstring coverage is 94.87% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
libs/toolkit/src/contracts.rs (1)

72-75: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Nit: TODO is doubly-commented inside a doc comment.

Lines 74-75 use /// + //, so the rendered rustdoc shows literal // TODO: .... Drop the inner // for clean rendering. The gRPC hook is also tracked here as a follow-up — I can open an issue to track it if helpful.

Proposed doc tweak
     /// # gRPC healthcheck
     ///
-    /// // TODO: Add gRPC healthcheck hook in a follow-up PR.
-    /// // This PR intentionally implements REST readiness healthchecks only.
+    /// TODO: Add gRPC healthcheck hook in a follow-up PR.
+    /// This PR intentionally implements REST readiness healthchecks only.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@libs/toolkit/src/contracts.rs` around lines 72 - 75, The rustdoc on the gRPC
healthcheck section is doubly commented, so the rendered docs show literal
comment markers instead of clean text. Update the doc comments in the
contracts.rs healthcheck block to remove the inner “//” while keeping the note
about the gRPC healthcheck hook and the REST-only scope; use the existing
healthcheck-related doc section and surrounding contract comments to locate it.
libs/toolkit/src/healthcheck.rs (2)

77-93: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Optional: HealthcheckStatus and HealthcheckAggregateStatus are structurally identical.

Two enums with the same three variants and serde config add maintenance overhead (any new variant must be mirrored, plus the manual mapping in compute_aggregate). If the aggregate truly can never diverge from the per-check status set, consider a single type with an alias; if divergence is anticipated (e.g., a future aggregate-only Initializing), keeping them separate is justified — a short comment noting the rationale would help.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@libs/toolkit/src/healthcheck.rs` around lines 77 - 93, The two status enums,
HealthcheckStatus and HealthcheckAggregateStatus, are identical and currently
require duplicated serde settings plus manual mirroring in compute_aggregate.
Either consolidate them behind a single shared type/alias if the aggregate will
always use the same variants, or keep both enums only if future divergence is
intended; in that case, add a short rationale comment near the enum definitions
and ensure compute_aggregate clearly uses the intended type mapping.

320-353: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Optional: broad substring blocklist can mask useful diagnostics.

Entries like "tenant", "select ", "update ", and "delete " will redact otherwise-safe operator messages (e.g., "tenant pool exhausted" or "update queue backlog") to a generic "health check failed", reducing debuggability on /health. This is reasonable defense-in-depth for a public endpoint, but worth a brief comment documenting the intentional trade-off so future maintainers don't treat redacted messages as a bug.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@libs/toolkit/src/healthcheck.rs` around lines 320 - 353, The broad blocklist
in sanitize_message is intentionally redacting some otherwise-safe operator
diagnostics, so add a brief comment near SUSPICIOUS_SUBSTRINGS or
sanitize_message explaining that this is a deliberate defense-in-depth tradeoff
for the public health endpoint. Keep the note focused on the intent behind
entries like tenant, select , update , and delete , so future maintainers
understand why messages may collapse to "health check failed" and do not treat
it as an accidental bug.
gears/system/api-gateway/src/web.rs (1)

40-57: 🚀 Performance & Scalability | 🔵 Trivial | 🏗️ Heavy lift

Consider caching/throttling readiness results.

/health and /readyz are public routes that run every registered check (each spawning tasks, potentially pinging DB/upstreams) on every request with no caching. Under frequent probing or hostile traffic this can amplify load on downstream dependencies. Consider a short-lived cached report (e.g., a few hundred ms TTL) so bursts of probes reuse one result. Worth verifying whether these root-mounted health routes sit behind any rate limiting.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gears/system/api-gateway/src/web.rs` around lines 40 - 57, The health
endpoints in health_detail and readyz_check currently call
registry.report(HEALTHCHECK_TIMEOUT) on every request, which can repeatedly fan
out expensive checks. Add a short-lived cached/throttled report layer inside the
RestHealthcheckRegistry or a helper used by both handlers so bursty /health and
/readyz probes reuse a recent result instead of spawning new checks each time.
Keep the existing status_for_report and response shaping logic, but have both
health_detail and readyz_check read from the shared cached report path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@gears/system/api-gateway/src/gear.rs`:
- Around line 105-138: The root-mounted health routes created in
apply_prefix_nesting/health_routes are being merged in a way that bypasses the
middleware stack applied to the prefixed router. Update apply_prefix_nesting so
the merged Router that serves /health, /healthz, and /readyz also goes through
the same apply_middleware_stack path as the rest of the API, using the existing
health_routes and apply_middleware_stack symbols to keep request IDs, tracing,
metrics, and CatchPanicLayer consistent.

In `@gears/system/api-gateway/src/web.rs`:
- Around line 51-54: Update the documentation comment for the `readyz` endpoint
in `web.rs` so it no longer calls `/readyz` “Shallow” or “all registered REST
healthchecks”; the implementation uses `registry.report(...)`, which is the deep
readiness probe. Align the wording with the module-level terminology in
`healthcheck.rs` by describing `/readyz` as readiness/deep and reserving
“shallow” or liveness language for `/healthz`, so operators are not misled when
wiring probes.

---

Nitpick comments:
In `@gears/system/api-gateway/src/web.rs`:
- Around line 40-57: The health endpoints in health_detail and readyz_check
currently call registry.report(HEALTHCHECK_TIMEOUT) on every request, which can
repeatedly fan out expensive checks. Add a short-lived cached/throttled report
layer inside the RestHealthcheckRegistry or a helper used by both handlers so
bursty /health and /readyz probes reuse a recent result instead of spawning new
checks each time. Keep the existing status_for_report and response shaping
logic, but have both health_detail and readyz_check read from the shared cached
report path.

In `@libs/toolkit/src/contracts.rs`:
- Around line 72-75: The rustdoc on the gRPC healthcheck section is doubly
commented, so the rendered docs show literal comment markers instead of clean
text. Update the doc comments in the contracts.rs healthcheck block to remove
the inner “//” while keeping the note about the gRPC healthcheck hook and the
REST-only scope; use the existing healthcheck-related doc section and
surrounding contract comments to locate it.

In `@libs/toolkit/src/healthcheck.rs`:
- Around line 77-93: The two status enums, HealthcheckStatus and
HealthcheckAggregateStatus, are identical and currently require duplicated serde
settings plus manual mirroring in compute_aggregate. Either consolidate them
behind a single shared type/alias if the aggregate will always use the same
variants, or keep both enums only if future divergence is intended; in that
case, add a short rationale comment near the enum definitions and ensure
compute_aggregate clearly uses the intended type mapping.
- Around line 320-353: The broad blocklist in sanitize_message is intentionally
redacting some otherwise-safe operator diagnostics, so add a brief comment near
SUSPICIOUS_SUBSTRINGS or sanitize_message explaining that this is a deliberate
defense-in-depth tradeoff for the public health endpoint. Keep the note focused
on the intent behind entries like tenant, select , update , and delete , so
future maintainers understand why messages may collapse to "health check failed"
and do not treat it as an accidental bug.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6107aa71-8c94-4412-a51c-37e23dd44ec2

📥 Commits

Reviewing files that changed from the base of the PR and between 0424c01 and 1c7cc69.

📒 Files selected for processing (7)
  • gears/system/api-gateway/src/gear.rs
  • gears/system/api-gateway/src/web.rs
  • gears/system/api-gateway/tests/health_endpoints.rs
  • libs/toolkit/src/contracts.rs
  • libs/toolkit/src/healthcheck.rs
  • libs/toolkit/src/lib.rs
  • libs/toolkit/src/runtime/host_runtime.rs

Comment thread gears/system/api-gateway/src/gear.rs
Comment thread gears/system/api-gateway/src/web.rs Outdated
@refur-nfn refur-nfn changed the title feat(toolkit): add REST healthcheck infrastructure, NO-REF-ISSUE feat(toolkit): add REST healthcheck infrastructure Jul 1, 2026
@refur-nfn refur-nfn force-pushed the add-rest-healthcheck branch 3 times, most recently from 838d355 to 36b1e50 Compare July 3, 2026 16:21
- Concurrent healthcheck execution with timeout protection
- HealthcheckRegistry for registering and running per-gear probes
- Message sanitization to prevent secret leaks in responses
- API Gateway integration for /health and /readyz endpoints
- Comprehensive test coverage with panic/timeout/degradation scenarios

Signed-off-by: Raudur Refur <261796072+refur-nfn@users.noreply.github.com>
@refur-nfn refur-nfn force-pushed the add-rest-healthcheck branch from 36b1e50 to 5254ada Compare July 6, 2026 11:37
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