Standardize response shapes and fix dead fetchT timeout keys
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled

Three small cleanups for v1.14.0:

1. /caddy/cas now uses standard success envelope
   Was: { status: 'success', data: { cas: caList } }
   Now: { success: true, cas: caList }
   Updated frontend service-infrastructure.js to match.

2. /api/health/ca now uses standard envelope + meaningful HTTP codes
   Was: { status, message, daysUntilExpiration } with 200 on every error
   Now: { success, caStatus, message|error, daysUntilExpiration }
        with 200 / 404 / 500 as appropriate
   caStatus field preserves the original 'healthy'/'warning'/'critical'/'error'
   semantic so any future consumer of the CA-health state still has it.
   Tests updated to match.

3. Dead timeout: keys in fetchT opts are now a warning, not a silent strip
   src/utils/http.js:41 used to do  without telling
   anyone. Callers that wrote fetchT(url, { timeout: 5000 }) got the default
   5s timeout with no indication that their explicit value was ignored.
   Now it logs a warning naming the call site, then strips the key.
   Fixed 4 call sites that had stale timeout: keys:
   - src/context/caddy.js
   - src/context/dns.js
   - src/context/provider-dns.js
   - routes/dns.js (2 places)
This commit is contained in:
Hermes
2026-06-10 21:52:33 -07:00
parent 11cfb8c26a
commit 2d394d882d
10 changed files with 53 additions and 42 deletions
@@ -538,7 +538,7 @@ describe('Health Routes', () => {
const { app } = createApp();
const res = await request(app).get('/api/health/ca');
expect(res.status).toBe(200);
expect(res.body.status).toBe('healthy');
expect(res.body.caStatus).toBe('healthy');
expect(res.body.daysUntilExpiration).toBeGreaterThan(90);
});
@@ -551,7 +551,7 @@ describe('Health Routes', () => {
const { app } = createApp();
const res = await request(app).get('/api/health/ca');
expect(res.status).toBe(200);
expect(res.body.status).toBe('warning');
expect(res.body.caStatus).toBe('warning');
expect(res.body.daysUntilExpiration).toBeLessThan(90);
expect(res.body.daysUntilExpiration).toBeGreaterThanOrEqual(30);
});
@@ -565,7 +565,7 @@ describe('Health Routes', () => {
const { app } = createApp();
const res = await request(app).get('/api/health/ca');
expect(res.status).toBe(200);
expect(res.body.status).toBe('critical');
expect(res.body.caStatus).toBe('critical');
expect(res.body.daysUntilExpiration).toBeLessThan(30);
expect(res.body.daysUntilExpiration).toBeGreaterThanOrEqual(0);
});
@@ -579,7 +579,7 @@ describe('Health Routes', () => {
const { app } = createApp();
const res = await request(app).get('/api/health/ca');
expect(res.status).toBe(200);
expect(res.body.status).toBe('critical');
expect(res.body.caStatus).toBe('critical');
expect(res.body.daysUntilExpiration).toBeLessThan(7);
});
@@ -592,7 +592,7 @@ describe('Health Routes', () => {
const { app } = createApp();
const res = await request(app).get('/api/health/ca');
expect(res.status).toBe(200);
expect(res.body.status).toBe('critical');
expect(res.body.caStatus).toBe('critical');
expect(res.body.daysUntilExpiration).toBeLessThan(0);
expect(res.body.message).toMatch(/EXPIRED/);
});
@@ -601,9 +601,9 @@ describe('Health Routes', () => {
exists.mockResolvedValue(false);
const { app } = createApp();
const res = await request(app).get('/api/health/ca');
expect(res.status).toBe(200);
expect(res.body.status).toBe('error');
expect(res.body.message).toMatch(/not found/);
expect(res.status).toBe(404);
expect(res.body.caStatus).toBe('error');
expect(res.body.error).toMatch(/not found/);
expect(res.body.daysUntilExpiration).toBeNull();
});
@@ -612,9 +612,9 @@ describe('Health Routes', () => {
execSync.mockImplementation(() => { throw new Error('openssl not found'); });
const { app } = createApp();
const res = await request(app).get('/api/health/ca');
expect(res.status).toBe(200);
expect(res.body.status).toBe('error');
expect(res.body.message).toBe('openssl not found');
expect(res.status).toBe(500);
expect(res.body.caStatus).toBe('error');
expect(res.body.error).toBe('openssl not found');
expect(res.body.daysUntilExpiration).toBeNull();
});
});