{"record":{"id":"3dfe4ce1d5e2d9f2","repo":"thedotmack/claude-mem","slug":"not-found-middleware","errorCode":null,"errorMessage":"Not found","messagePattern":"Not found","errorType":"http","errorClass":null,"httpStatus":404,"severity":"info","filePath":"src/services/worker/http/middleware.ts","lineNumber":303,"sourceCode":"      path: req.path,\n      presentedToken,\n      expectedToken: options.getToken(),\n    });\n\n    if (!decision.allow) {\n      // Never log the secret or the raw query string. `req.path` excludes the\n      // query string in Express, which is what makes that safe.\n      logRemoteDenial({\n        path: req.path,\n        method: req.method,\n        clientIp,\n        reason: decision.reason,\n      });\n      // Always write the response. The worker never calls finalizeRoutes(), so\n      // it has no terminal error handler — forwarding an error to Express\n      // would land in its default handler and return an HTML stack page.\n      if (decision.status === 404) {\n        res.status(404).json({ error: 'Not found' });\n      } else if (decision.status === 403) {\n        res.status(403).json({\n          error: 'Forbidden',\n          message: 'Observation TV remote access is read-only'\n        });\n      } else {\n        res.status(401).json({\n          error: 'Unauthorized',\n          message: 'Missing or invalid Observation TV token'\n        });\n      }\n      return;\n    }\n\n    // 6. Pass.\n    res.setHeader('Cache-Control', 'no-store');\n    next();\n  };","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/services/worker/http/middleware.ts#L285-L321","documentation":"createRemoteReadOnlyGuard filters remote (non-localhost) access to observation TV endpoints. When the guard's decision is 404, the middleware writes `{ error: 'Not found' }` directly, hiding the endpoint's existence from remote callers. Responses are always written inline because the worker has no terminal error handler.","triggerScenarios":"A remote request hits an observation-TV path the guard classifies as nonexistent (wrong route, hidden endpoint, or deliberately masked path).","commonSituations":"Probing remote endpoints that only exist locally; clients constructed from outdated route lists after the route was removed/renamed; enumeration attempts being masked as 404.","solutions":["Use the correct, current route path for the observation TV API","Run the request from localhost if the endpoint is local-only","Check the guard configuration to see which paths are exposed remotely"],"exampleFix":"// before\nfetch('http://remote-host:37777/api/obs-tv/old-route')\n// after\nfetch('http://127.0.0.1:37777/api/obs-tv/current-route')","handlingStrategy":"fallback","validationCode":"// only call obs-tv routes that are in the documented remote-exposed set\nconst isExposedRemotely = REMOTE_EXPOSED_ROUTES.includes(path);","typeGuard":null,"tryCatchPattern":"if (res.status === 404) {\n  // remote: path not exposed; retry locally or correct the route\n}","preventionTips":["Keep client route lists in sync with the worker's exposed API","Treat remote 404s as possible access masking; verify locally","Document which obs-tv routes are remote-accessible"],"tags":["http","security","not-found"],"backgroundTag":"resource-not-found","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}