Two new bridge endpoints powering JSN's Volunteer Hub UI:
1. POST /api/volunteer/bridge/dashboard — bridge-secret-gated. Looks up User
by email, reuses volunteerDashboardService.getDashboard(userId) to compose
the same VolunteerDashboardPayload shape /volunteer/dashboard returns
internally. Identical shape so JSN frontend renders with no schema
translation. 404 when no cmlite user (JSN should provision identity first).
2. POST /api/auth/bridge/issue-sso-token (server-to-server, bridge-secret-
gated) + GET /api/auth/bridge/sso?token=…&redirectTo=… (browser-facing).
Mints a 60s one-time-use JWT signed with new SSO_BRIDGE_SECRET; consume
atomically deletes a Redis sentinel (sso:<jti>, TTL 60s) — returns 401 if
already consumed. On success, generates cmlite's normal cml_refresh
cookie via the existing authService.generateTokenPair, redirects to
${ADMIN_URL}${redirectTo}. The SPA hydrates session on mount from the
refresh cookie, so the user lands at the target path already logged in.
redirectTo sanitization mirrors JSN's sanitizeReturnTo — protocol-
relative, backslash-trick, traversal, and control-char protections.
Both endpoints rate-limited at rl:bridge-sso: prefix.
Minimal rebrand for the SSO-entry experience (VolunteerLayout.tsx):
- useSearchParams() reads ?layout=embedded → hides PublicNavBar so the new
tab feels like a continuation of whatever opener context the user came
from. Footer nav stays (it's the in-cmlite navigation surface).
- ConfigProvider colorPrimary already reads from siteSettings.publicColor
Primary. Set via SQL once: UPDATE site_settings SET "publicColorPrimary"
= '#b8362b' — JSN's campaign red. Persistent.
NEW env var SSO_BRIDGE_SECRET (z.string().min(32).optional()) lives only on
cmlite — JSN never sees it. Generate with openssl rand -hex 32. Distinct
from JSN_BRIDGE_SECRET and all JWT_* secrets.
End-to-end verified: JSN /account → click "Open Volunteer Hub" → new tab
opens at http://localhost:3095/volunteer?layout=embedded with user
authenticated via SSO bridge redirect, chrome hidden by layout flag,
primary color matched.
Bunker Admin