Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion app/config/openapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,28 @@ const spec = {
},
},
},
503: { description: 'Degraded — DB unreachable' },
503: {
description: 'Degraded — DB unreachable',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
status: { type: 'string', enum: ['degraded'] },
db: { type: 'string', enum: ['down'] },
uptime_s: { type: 'integer' },
version: { type: 'string' },
elapsed_ms: { type: 'number' },
migration: { type: 'string', nullable: true },
db_error: {
type: 'string',
description: 'The underlying DB connection error message (e.g. "ECONNREFUSED 127.0.0.1:5432"). Useful for operator debugging; never includes credentials. Present only on the 503 path.',
},
},
},
},
},
},
},
},
},
Expand Down
19 changes: 19 additions & 0 deletions tests/api/openapi.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,25 @@ describe('OpenAPI spec', () => {
expect(m.get.responses['200']).toBeDefined();
});

test('/healthz 503 response documents the db_error field', async () => {
// The healthz controller (app/controllers/healthcontroller.js)
// appends a `db_error` string field to the 503 body when the
// SELECT 1 probe throws. Operators rely on this for debugging;
// SDK generators read it from the spec. Pin the schema so a
// future controller refactor that drops the field also fails
// here and the docs stay in sync with reality.
const res = await request(app).get('/openapi.json');
const h = res.body.paths['/healthz'];
const r503 = h.get.responses['503'];
expect(r503).toBeDefined();
const schema = r503.content
&& r503.content['application/json']
&& r503.content['application/json'].schema;
expect(schema, '/healthz 503 should declare a body schema').toBeDefined();
expect(schema.properties.db_error, 'db_error should appear in the 503 body').toBeDefined();
expect(schema.properties.db_error.type).toBe('string');
});

test('GET /docs serves Swagger UI HTML', async () => {
const res = await request(app).get('/docs/');
// swagger-ui-express serves HTML; we don't pin the exact body
Expand Down