fix(server): stop relaying upstream and JS error text to the client

Ported onto the split provider layout: the routes now live in
server/providers/openai/{hud-summary,realtime}.js and the camera health
entry in server/providers/cctv.js.

The routes #263 names — celestrak, terrain, adsbdb — were sanitized by
#289. The same defect had moved:

- /api/openai/hud-summary relayed `data.error.message` verbatim on a
  non-ok upstream. That is OpenAI's own error text, carrying request ids,
  organization hints and quota wording. Its catch echoed the JS error too.
- /api/realtime/token echoed the JS error when minting failed, which for a
  network fault is a resolver message naming the upstream host.
- cctvProxy stored the raw error as a camera's health `message`. This is
  the least obvious of the three and the reason the PR is worth its size:
  GET /api/cctv/health serializes `message`, and src/layers/cctv/frames.js
  renders it as the camera's status label, so the detail reached the
  screen through a different door than the sanitized 502 beside it.

Logs name the failure and the upstream status without the text, matching
the Launch Library and terrain paths; these lines get pasted into issues.

Coverage extends the existing harnesses rather than adding files —
localServices.test.mjs drives both OpenAI routes over a mocked upstream,
mediaProviders.test.mjs drives a failing media fetch and then reads
/health. All three assertions fail on the previous implementation.

Refs #263. Does not touch /api/realtime/debug-log's identical echo; that
route is the subject of the #23 PR, so the two do not overlap a line.
This commit is contained in:
Pedro Lobato committed 2026-09-14 21:24:05 -05:00
1 parent 96a6b49477
commit 9e71081a5a
7 files changed
+97 -8

No files matched your search

+6 -1
View File
@@ -308,11 +308,16 @@ export function cctvProxy({ sourceRoot = process.cwd() } = {}) {
}
const timedOut =
error?.name === 'AbortError' || error?.name === 'TimeoutError';
// GET /api/cctv/health serializes `message`, and the CCTV panel
// renders it as a status label, so the raw error would leave the
// server by a different door than the sanitized body below and
// land on screen. Keep the detail in the log.
console.warn('[CCTV Proxy] media fetch failed');
setHealth(cameraId, {
status: 'degraded',
sourceKind: 'upstream',
label: source?.provider || 'Configured source',
message: error?.message || 'Media fetch failed',
message: 'Media fetch failed',
});
res.writeHead(timedOut ? 504 : 502, {
'Content-Type': 'application/json',