v1.13.4: Standardize all route responses to use response helpers
CI / Test & Lint (push) Has been cancelled
CI / Security audit (push) Has been cancelled

Convert ~160 raw res.json()/res.status().json() calls across 32+ files
to use centralized helpers from src/utils/responses.js (ok, errorResponse,
successMessage, notFound, validationError, forbidden, unauthorized, conflict).

No behavior changes — response shapes are identical. Future schema changes
(e.g., requestId envelope) only need to update one module.

Fix error vs errorResponse signature mismatch in routes/health.js CA cert
endpoint where error(res, message, statusCode) was being called with
errorResponse(res, statusCode, message, extras) argument order.

Files changed: middleware.js, csrf-protection.js, error-handler.js,
license-manager.js, src/app.js, and 27 route files.

Test suite: 755 pass / 4 pre-existing failures (services credential tests).
This commit is contained in:
Hermes
2026-06-11 00:48:13 -07:00
parent 2d394d882d
commit 53680c4c74
40 changed files with 251 additions and 275 deletions
+6 -11
View File
@@ -15,6 +15,7 @@ const crypto = require('crypto');
const rateLimit = require('express-rate-limit');
const { createCSRFMiddleware, csrfValidationMiddleware, CSRF_HEADER_NAME } = require('./csrf-protection');
const { RATE_LIMITS, LIMITS, APP } = require('./constants');
const { errorResponse, unauthorized, forbidden, validationError } = require('./src/utils/responses');
const { CACHE_CONFIGS, createCache } = require('./cache-config');
/**
@@ -33,7 +34,7 @@ module.exports = function configureMiddleware(app, {
// ── Container ID param validation ──
app.param('id', (req, res, next, id) => {
if (req.path.includes('/containers/') && !isValidContainerId(id)) {
return res.status(400).json({ success: false, error: 'Invalid container ID' });
return validationError(res, 'Invalid container ID');
}
next();
});
@@ -127,9 +128,7 @@ module.exports = function configureMiddleware(app, {
const fromTailscale = ipsToCheck.some(ip => isTailscaleIP(ip.toString().split(',')[0].trim()));
if (!fromTailscale) {
return res.status(403).json({
success: false,
error: '[DC-120] Access denied. This dashboard requires Tailscale connection.',
return errorResponse(res, 403, '[DC-120] Access denied. This dashboard requires Tailscale connection.', {
requiresTailscale: true,
clientIP: clientIP
});
@@ -150,9 +149,7 @@ module.exports = function configureMiddleware(app, {
for (const ip of (peer.TailscaleIPs || [])) knownIPs.add(ip);
}
if (!knownIPs.has(clientTailscaleIP)) {
return res.status(403).json({
success: false,
error: '[DC-121] Access denied. Device not in allowed tailnet.',
return errorResponse(res, 403, '[DC-121] Access denied. Device not in allowed tailnet.', {
requiresTailscale: true,
clientIP
});
@@ -358,7 +355,7 @@ module.exports = function configureMiddleware(app, {
if (isPublicRoute(req)) return next();
if (isSessionValid(req)) return next();
return res.status(401).json({ success: false, error: '[DC-110] Authentication required', requiresTotp: true });
return errorResponse(res, 401, '[DC-110] Authentication required', { requiresTotp: true });
};
app.use(totpAuthMiddleware);
@@ -406,9 +403,7 @@ module.exports = function configureMiddleware(app, {
}
// No valid auth — reject
return res.status(401).json({
success: false,
error: '[DC-110] Authentication required - provide TOTP session, JWT token, or API key',
return errorResponse(res, 401, '[DC-110] Authentication required - provide TOTP session, JWT token, or API key', {
requiresTotp: totpConfig.enabled
});
};