Compare commits

...
2 Commits
Author SHA1 Message Date
Hermes 92bcafb4f1 DC-011: mark done — 750/750 tests pass, fixed route regression + ctx bug
CI / Security audit (push) Has been cancelled
CI / Test & Lint (push) Has been cancelled
2026-06-21 05:54:17 -07:00
Hermes 16276c62fc DC-011: fix credential route paths + undefined ctx reference error
The src/ module-flattening refactor regressed the DC-001 fix: the 3
service-credential routes in routes/services.js used '/:serviceId/credentials'
instead of '/services/:serviceId/credentials', causing 4 test failures
(services.routes.test.js → 404 instead of 200) — every other route in the
file uses the '/services' prefix.

Also fixed a latent ReferenceError in the same validation branches: they
called ctx.errorResponse() but ctx is never defined in this module's scope
(the factory destructures its deps). Replaced with the imported errorResponse
helper so invalid serviceIds now return a clean 400 instead of crashing 500.

Tests: 4 failed → 0 failed (750 pass). ESLint: no new warnings.
2026-06-21 05:54:00 -07:00
2 changed files with 9 additions and 9 deletions
+3 -3
View File
@@ -16,10 +16,10 @@
- **result:** Root cause: routes used `/:serviceId/credentials` (missing `/services/` segment). All 3 credential routes (POST/DELETE/GET) in `routes/services.js` had the wrong path. Fixed to `/services/:serviceId/credentials` — matches the URL pattern used by the live frontend and all 759 tests pass.
### DC-011: Fix DC-001 regression reintroduced by src/ refactor (4 failing tests)
- **status:** in-progress
- **status:** done
- **owner:** hermes
- **details:** The module-flattening refactor (DC-005) force-pushed to `main` dropped the DC-001 route-prefix fix. `routes/services.js` again defines `/:serviceId/credentials` (POST/DELETE/GET) instead of `/services/:serviceId/credentials`, so `/api/services/:id/credentials` returns 404 and 4 tests in `services.routes.test.js` fail. Baseline: `npx jest` → 4 failed, 746 passed.
- **result:** (in progress)
- **details:** The module-flattening refactor (DC-005) force-pushed to `main` dropped the DC-001 route-prefix fix. `routes/services.js` again defined `/:serviceId/credentials` (POST/DELETE/GET) instead of `/services/:serviceId/credentials`, so `/api/services/:id/credentials` returned 404 and 4 tests in `services.routes.test.js` failed. Baseline: `npx jest` → 4 failed, 746 passed.
- **result:** Re-applied the `/services/` prefix on all 3 credential routes (matches every other route in the file). Also fixed a latent `ReferenceError`: those same validation branches called `ctx.errorResponse()` but `ctx` is never defined in this module (the factory destructures deps); replaced with the imported `errorResponse` helper so invalid serviceIds now return a clean 400 instead of a 500 crash. Result: 750/750 tests pass (4 failed → 0), zero new ESLint warnings. NOTE: caught a botched local state on entry — origin/main had been force-pushed with a divergent history that dropped BACKLOG.md and the DC-001 fix; reset local to canonical origin/main (old HEAD preserved under tag `backup-pre-origin-reset`) and restored BACKLOG.md.
### DC-002: Sync VERSION file
- **status:** done
+6 -6
View File
@@ -196,12 +196,12 @@ module.exports = function({
// ===== SERVICE CREDENTIAL ENDPOINTS =====
// Store credentials for a service
router.post('/:serviceId/credentials', asyncHandler(async (req, res) => {
router.post('/services/:serviceId/credentials', asyncHandler(async (req, res) => {
const { serviceId } = req.params;
// Validate serviceId to prevent path traversal in credential keys
if (!serviceId || !/^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,100}$/.test(serviceId)) {
return ctx.errorResponse(res, 400, 'Invalid service ID');
return errorResponse(res, 400, 'Invalid service ID');
}
const { apiKey, username, password } = req.body;
@@ -220,12 +220,12 @@ module.exports = function({
}, 'store-service-creds'));
// Delete credentials for a service
router.delete('/:serviceId/credentials', asyncHandler(async (req, res) => {
router.delete('/services/:serviceId/credentials', asyncHandler(async (req, res) => {
const { serviceId } = req.params;
// Validate serviceId to prevent path traversal in credential keys
if (!serviceId || !/^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,100}$/.test(serviceId)) {
return ctx.errorResponse(res, 400, 'Invalid service ID');
return errorResponse(res, 400, 'Invalid service ID');
}
await credentialManager.delete(`service.${serviceId}.apikey`);
@@ -235,12 +235,12 @@ module.exports = function({
}, 'delete-service-creds'));
// Check credential status for a service (what's stored)
router.get('/:serviceId/credentials', asyncHandler(async (req, res) => {
router.get('/services/:serviceId/credentials', asyncHandler(async (req, res) => {
const { serviceId } = req.params;
// Validate serviceId to prevent path traversal in credential keys
if (!serviceId || !/^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,100}$/.test(serviceId)) {
return ctx.errorResponse(res, 400, 'Invalid service ID');
return errorResponse(res, 400, 'Invalid service ID');
}
const arrKey = await credentialManager.retrieve(`arr.${serviceId}.apikey`).catch(() => null);
const svcKey = await credentialManager.retrieve(`service.${serviceId}.apikey`).catch(() => null);