diff --git a/services/mam-api/src/index.js b/services/mam-api/src/index.js index 934b5c8..fb914fa 100644 --- a/services/mam-api/src/index.js +++ b/services/mam-api/src/index.js @@ -88,13 +88,18 @@ app.use(session({ app.get('/health', (_req, res) => res.json({ status: 'ok' })); // ── Auth gate ───────────────────────────────────────────────────────────────── -// Mount once for everything under /api/v1, with an explicit allowlist for -// the three pre-login auth paths and a carve-out for /cluster/* (node-agent -// uses migration 019's token-binding, not user auth). See spec. +// req.path is relative to the /api/v1 mount, so /auth/login NOT /api/v1/auth/login. const UNAUTH_PATHS = new Set(['/auth/login', '/auth/setup', '/auth/setup-required']); +// Service-auth carve-outs: node-agent uses migration 019's bound-hostname +// api_token mechanism, not user auth. Today only /cluster/heartbeat is +// reached without a user session — operator/UI endpoints in cluster.js +// (containers restart, DELETE /:id, blackmagic device queries) ARE expected +// to require auth. If node-agent grows another endpoint, add it here. +// TODO: long-term, issue node-agent a real bound api_token and drop this carve-out. +const SERVICE_PATHS = new Set(['/cluster/heartbeat']); app.use('/api/v1', (req, res, next) => { if (UNAUTH_PATHS.has(req.path)) return next(); - if (req.path.startsWith('/cluster')) return next(); // node-agent service auth, not user auth + if (SERVICE_PATHS.has(req.path)) return next(); return requireAuth(req, res, next); });