Skip to content

Commit a6480d6

Browse files
authored
Merge pull request #58 from lamborghini21/add-health-ready-endpoints
Add /healthz and /readyz endpoints with readiness component reporting
2 parents 12eadff + 420d7fd commit a6480d6

2 files changed

Lines changed: 79 additions & 0 deletions

File tree

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,32 @@ PORT=3001
121121
INTERNAL_BASE_URL=https://stellarmind.example.com
122122
```
123123

124+
## Operational Health Checks
125+
126+
StellarMind exposes lightweight endpoints for deployment tooling and load balancer probes:
127+
128+
- `GET /healthz`
129+
- returns `200` and `status: ok` when the process is alive
130+
- no external dependency checks are performed
131+
- `GET /readyz`
132+
- returns `200` when the configured critical components are ready
133+
- returns `503` when required configuration is missing
134+
135+
Example `/readyz` response:
136+
137+
```json
138+
{
139+
"status": "ready",
140+
"ready": true,
141+
"timestamp": "2026-05-28T12:00:00.000Z",
142+
"components": {
143+
"app": { "ready": true, "description": "Core HTTP server initialized" },
144+
"anthropic": { "configured": true, "ready": true, "description": "Anthropic API key is configured for Claude-powered agents" },
145+
"x402": { "enabled": true, "ready": true, "description": "x402 payment wallet is configured" }
146+
}
147+
}
148+
```
149+
124150
## Available Commands
125151

126152
| Command | Purpose |

src/server.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ app.use(requestId);
2525

2626
// ─── SSE Event Stream ────────────────────────────────────────
2727
const sseClients = [];
28+
let x402MiddlewareReady = false;
2829

2930
function broadcast(event) {
3031
const data = JSON.stringify(event);
@@ -33,6 +34,55 @@ function broadcast(event) {
3334
});
3435
}
3536

37+
function buildReadinessPayload() {
38+
const anthropicConfigured = !!config.anthropicApiKey;
39+
const x402Enabled = !!config.serverAddress;
40+
41+
const components = {
42+
app: {
43+
ready: true,
44+
description: 'Core HTTP server initialized',
45+
},
46+
anthropic: {
47+
configured: anthropicConfigured,
48+
ready: anthropicConfigured,
49+
description: anthropicConfigured
50+
? 'Anthropic API key is configured for Claude-powered agents'
51+
: 'Missing Anthropic API key; demo fallback responses are available',
52+
},
53+
x402: {
54+
enabled: x402Enabled,
55+
ready: !x402Enabled || (x402MiddlewareReady && !!config.facilitatorUrl),
56+
description: x402Enabled
57+
? (x402MiddlewareReady
58+
? 'x402 payment middleware initialized'
59+
: 'x402 is enabled but middleware initialization failed')
60+
: 'x402 paywall is disabled; premium endpoints are not protected by payments',
61+
},
62+
};
63+
64+
const ready = Object.values(components).every(component => component.ready);
65+
return {
66+
status: ready ? 'ready' : 'not_ready',
67+
ready,
68+
timestamp: new Date().toISOString(),
69+
components,
70+
};
71+
}
72+
73+
app.get('/healthz', (req, res) => {
74+
res.json({
75+
status: 'ok',
76+
uptime: process.uptime(),
77+
timestamp: new Date().toISOString(),
78+
});
79+
});
80+
81+
app.get('/readyz', (req, res) => {
82+
const payload = buildReadinessPayload();
83+
res.status(payload.ready ? 200 : 503).json(payload);
84+
});
85+
3686
app.get('/api/events', (req, res) => {
3787
res.setHeader('Content-Type', 'text/event-stream');
3888
res.setHeader('Cache-Control', 'no-cache');
@@ -96,11 +146,14 @@ if (config.serverAddress) {
96146
[{ network: config.network, server: stellarScheme }],
97147
)
98148
);
149+
x402MiddlewareReady = true;
99150
console.log('✅ x402 payment middleware active');
100151
} catch (err) {
152+
x402MiddlewareReady = false;
101153
console.warn('⚠️ x402 middleware init failed (non-fatal):', err.message);
102154
}
103155
} else {
156+
x402MiddlewareReady = false;
104157
console.warn('⚠️ No SERVER_STELLAR_ADDRESS set — x402 paywall disabled');
105158
}
106159

0 commit comments

Comments
 (0)