From 22853da0232769bfa9e3485c5059de45c0ba4a9d Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 2 Jun 2026 16:00:13 +0000 Subject: [PATCH] fix(capture): authenticate sidecar->mam-api calls with bearer token MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The live-thumbnail and manual /start,/stop sidecar->mam-api calls hit the CSRF guard (403 missing X-Requested-With). Match the working pattern in index.js: send Authorization: Bearer $MAM_API_TOKEN (= CAPTURE_TOKEN, injected by recorders.js), which is CSRF-exempt. Falls back to the UI header only when no token is set (dev). Fixes [livethumb] failed ... 403 — posters now persist. 🤖 Generated with Claude Code --- services/capture/src/capture-manager.js | 5 ++++- services/capture/src/routes/capture.js | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/services/capture/src/capture-manager.js b/services/capture/src/capture-manager.js index 8dbae25..17a02e4 100644 --- a/services/capture/src/capture-manager.js +++ b/services/capture/src/capture-manager.js @@ -1346,7 +1346,10 @@ exit "$BMXRC" // 4. Tell mam-api the key (only sticks while the asset is still 'live'). const resp = await fetch(`${mamUrl}/api/v1/assets/${assetId}/live-thumbnail`, { method: 'POST', - headers: { 'Content-Type': 'application/json' }, + headers: { + 'Content-Type': 'application/json', + ...(process.env.MAM_API_TOKEN ? { Authorization: `Bearer ${process.env.MAM_API_TOKEN}` } : {}), + }, body: JSON.stringify({ thumbnailKey: thumbKey }), }); if (!resp.ok) throw new Error(`mam-api ${resp.status}: ${(await resp.text()).slice(0, 200)}`); diff --git a/services/capture/src/routes/capture.js b/services/capture/src/routes/capture.js index 7fc3c06..a299116 100644 --- a/services/capture/src/routes/capture.js +++ b/services/capture/src/routes/capture.js @@ -77,6 +77,7 @@ function classifyProbeError(raw, sourceType) { const router = express.Router(); const MAM_API_URL = process.env.MAM_API_URL || 'http://mam-api:3000'; +const MAM_API_TOKEN = process.env.MAM_API_TOKEN || ''; /** * GET /devices @@ -340,7 +341,7 @@ router.post('/start', async (req, res) => { try { const mamResponse = await fetch(`${MAM_API_URL}/api/v1/assets`, { method: 'POST', - headers: { 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json', ...(MAM_API_TOKEN ? { Authorization: `Bearer ${MAM_API_TOKEN}` } : { 'X-Requested-With': 'dragonflight-ui' }) }, body: JSON.stringify({ projectId: project_id, binId: bin_id,