diff --git a/src/servers/hono.ts b/src/servers/hono.ts index eefc7fed..acdb4c03 100644 --- a/src/servers/hono.ts +++ b/src/servers/hono.ts @@ -139,8 +139,6 @@ const PROTECTED_MOUNTS: [prefix: string, router: ReturnType // ['/gitea', giteaRouter], // plugin — switched off 2026-08-13 ['/app-store', appStoreRouter], ['/plugins', pluginsRouter], - // Loopback dev servers, framed by the Preview panel. See its router for why it is not a proxy host. - ['/dev-proxy', devProxyRouter], // ['/caldav', caldavRouter], // the JSON door for Officer's own calendar/contacts UI — plugin, switched off 2026-08-13 // ['/dav', davRouter], // app-password management (the sync door is /dav, top-level) — plugin, switched off // ['/notify', notifyRouter], // plugin — switched off 2026-08-13 @@ -178,6 +176,7 @@ export const UNPROTECTED_API_PREFIXES: string[] = [ // '/vault', // switched off with the Vaultwarden mounts — see above '/sidecar', '/agent-handoff', + '/dev-proxy', ]; /** @@ -234,6 +233,14 @@ export function buildHonoApp(plugins: MountedPlugin[] = []): Hono<{ Variables: H // peer on that panel's own dashboard. See servers/api/agent-handoff/router.ts. app.route('/api/agent-handoff', agentHandoffRouter); + // Loopback dev servers, framed by the Preview panel. + // + // UNPROTECTED because an iframe navigation carries no Authorization header — `userMiddleware` would 401 + // the document before the router saw it, which is exactly what happened: the pane showed the + // middleware's "Unauthorized", not this router's own message. It is not open: the router verifies the + // OWNER's token on `/session` and requires the cookie that issues on everything else. + app.route('/api/dev-proxy', devProxyRouter); + // CalDAV/CardDAV for phones and desktop clients — mounted TOP-LEVEL for the same reason the vault is: // DAVx5, iOS and Thunderbird authenticate with HTTP Basic on every request and have nowhere to put a // platform JWT, so userMiddleware would 401 them. The credential is a scoped DAV app password; see