// lib/api/soft_auth.js — shared middleware // Soft auth: identifies the actor if auth is present but never blocks the request. // Owner-only sub-routes enforce 401/403 via requireOwner. import * as agents from '../db/repos/agents.js'; import { timingSafeStrEqual } from '../auth/safe_compare.js'; import { accessOwnerEmail } from '../auth/cf_access.js'; export async function softAuth(req, _res, next) { try { const cfEmail = await accessOwnerEmail(req); if (cfEmail) { req.actor = { kind: 'user', id: null }; return next(); } const auth = req.headers.authorization || ''; const [scheme, token] = auth.split(' '); if (scheme === 'Bearer' && token) { if (process.env.OWNER_TOKEN && timingSafeStrEqual(token, process.env.OWNER_TOKEN)) { req.actor = { kind: 'user', id: null }; return next(); } try { const agent = await agents.verifyToken(token); if (agent) req.actor = { kind: 'agent', id: agent.id, capabilities: agent.capabilities || {}, scopes: agent.scopes || {} }; } catch { /* ignore */ } } } catch { /* ignore */ } next(); }