feat(dashboard): Add authenticated Junior dashboard#448
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Add a packaged Junior dashboard with Better Auth, reporting APIs, conversation views, transcript redaction, and Sentry links. Replace the old diagnostics dashboard routes with the dashboard package and wire the example app to run it locally. Capture safer conversation metadata for dashboard and trace reporting while redacting private conversation inputs and outputs. Add dashboard docs, policy coverage, and tests for the route and reporting behavior. Co-Authored-By: GPT-5 Codex <codex@openai.com>
Replace dashboard path and auth URL slash-trimming regexes with linear helpers so CodeQL does not flag route inputs as polynomial regular expression risks. Co-Authored-By: GPT-5 Codex <codex@openai.com>
Cache standalone dashboard handler initialization through a single promise so concurrent first requests do not create duplicate dashboard app instances. Co-Authored-By: GPT-5 Codex <codex@openai.com>
- Extend auth middleware to cover page sub-routes when basePath is "/";
app.use("/", ...) only matches the exact root in Hono, leaving
/conversations, /sessions, and their children unprotected
- Make the initial recordAgentTurnSessionSummary(state='running') call
fire-and-forget so it does not delay reply generation; the 'running'
state record is best-effort tracking and must not block the turn
- Add GEN_AI_SERVER_ADDRESS to @/chat/pi/client mocks in four unit test
files that mock the module without this export; respond.ts uses the
constant and vitest strict mocks reject missing exports
Action taken on behalf of David Cramer.
---
[View Session in Sentry](https://sentry.sentry.io/traces/?project=4510944073809921&query=gen_ai.conversation.id%3A%22slack%3AC0B595QDZLL%3A1780119001.371349%22)
Co-authored-by: David Cramer <david@sentry.io>
Missed GEN_AI_SERVER_PORT=443 in the previous mock patch. The export was added alongside GEN_AI_SERVER_ADDRESS in this PR; respond.ts uses both at line 1165 and vitest strict mocks reject any missing export. Action taken on behalf of David Cramer. --- [View Session in Sentry](https://sentry.sentry.io/traces/?project=4510944073809921&query=gen_ai.conversation.id%3A%22slack%3AC0B595QDZLL%3A1780119001.371349%22) Co-authored-by: David Cramer <david@sentry.io>
When resolveConversationPrivacy returns undefined (no recognizable Slack channel identifier), privacy checks using === "private" incorrectly take the expose-content path. traced-stream.ts already uses the correct pattern (=== "public" to expose, else redact). Align respond.ts input and output message serialization and reporting.ts session title/channel redaction to use !== "public", so undefined falls to the safe metadata-only path. Fixes Warden finding EZN-84H. Action taken on behalf of David Cramer. --- [View Session in Sentry](https://sentry.sentry.io/traces/?project=4510944073809921&query=gen_ai.conversation.id%3A%22slack%3AC0B595QDZLL%3A1780119001.371349%22) Co-authored-by: David Cramer <david@sentry.io>
- Change advisor/tool.ts privacy guards from === "private" to !== "public"
to match the fail-closed pattern mandated by specs/data-redaction-policy.md
and used in respond.ts, reporting.ts, and traced-stream.ts; the existing
?? "private" default made it functionally safe but the pattern was
inconsistent and fragile
- Add dashboard-routes test covering unauthenticated access to /conversations,
/conversations/:id, /sessions, and /sessions/:id at root basePath; the
previous test only verified / and would not have caught the Hono routing
gap where app.use("/", ...) skips sub-routes
Action taken on behalf of David Cramer.
---
[View Session in Sentry](https://sentry.sentry.io/traces/?project=4510944073809921&query=gen_ai.conversation.id%3A%22slack%3AC0B595QDZLL%3A1780119001.371349%22)
Co-authored-by: David Cramer <david@sentry.io>
Keep loaded skill metadata available when timeout and auth-pause persistence runs outside the active skill scope. Add dashboard reporting coverage for the session-record-backed transcript path. Co-Authored-By: GPT-5 Codex <codex@openai.com>
1d31eac to
0123461
Compare
Move dashboard-specific presentation out of the HTML stylesheet and into Tailwind-styled React components. Use a simpler black Junior mark and keep only the logo/title link target in the header. Add the frontend component policy and update dashboard reporting language for turn-session records. Tighten turn-session parsing to the current session-log storage contract and keep summary updates projection-only. Co-Authored-By: GPT-5 Codex <codex@openai.com>
Require dashboard sessions to have a verified email before matching explicit allowedEmails entries. This keeps email exceptions aligned with the hosted-domain authorization path and the dashboard spec. Co-Authored-By: GPT-5 Codex <codex@openai.com>
Keep auth-resume records materialized with projection-tail host observations while terminal turn transcripts stay pinned to their committed prefix. Avoid adding a conversation-specific turn-session API for dashboard detail reads by reusing the existing summary feed with a dashboard-scoped limit. Co-Authored-By: GPT-5 Codex <codex@openai.com>
Mark non-public conversation turns as privacy redacted even after the transcript checkpoint expires. This keeps expired private turns from looking like generic missing transcripts. Co-Authored-By: GPT-5 Codex <codex@openai.com>
Keep the best-effort running turn summary write off the critical path while still capturing failures. This avoids unhandled promise rejections from dashboard checkpoint recording. Co-Authored-By: GPT-5 Codex <codex@openai.com>
Read conversation detail from a conversation-scoped turn-session index so permalink pages do not depend on the capped global recent feed. Keep a global-index fallback for records written before the conversation index existed. Co-Authored-By: GPT-5 Codex <codex@openai.com>
Redirect dashboard API callers back through the dashboard login route when an authenticated request returns 401. This prevents expired sessions from leaving the SPA in a polling error state. Co-Authored-By: GPT-5 Codex <codex@openai.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 9 total unresolved issues (including 8 from previous reviews).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit d16817f. Configure here.
Clear the cached standalone dashboard app promise when config or app creation rejects so a transient startup failure does not pin the handler until process restart. Co-Authored-By: GPT-5 Codex <codex@openai.com>
Keep the dashboard fallback HTML aligned with the frontend component policy by using Tailwind classes instead of inline styles. Co-Authored-By: GPT-5 Codex <codex@openai.com>
Disable Better Auth account-data cookies for dashboard OAuth sessions. Bound private payload key metadata and add coverage for the denied-page shell. Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Separate dashboard-owned routes from the public runtime health route. Document that private conversation APIs expose redacted metadata instead of raw transcript payloads. Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Strip Better Auth session internals before dashboard routes store identity in request context. This keeps the /api/dashboard/me response limited to display-safe user fields even when the auth provider returns a broader session object. Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Require dashboard auth by default in the example app and only disable it for local development outside Vercel. This keeps Vercel preview and production deployments authenticated while preserving a low-friction pnpm dev path. Co-Authored-By: GPT-5 Codex <noreply@openai.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Add a packaged Junior dashboard that runs as a Nitro plugin with Better Auth-protected routes, a React command center, conversation lists, and permalinked transcript views. This replaces the old diagnostics dashboard surface with a deployable dashboard package and wires the example app for local development.
Dashboard Package
The new @sentry/junior-dashboard package exposes Nitro and handler entry points, dashboard APIs, route tests, docs, and a dark-mode UI for command center stats, turn duration history, and conversation details. Dashboard points and conversation rows link to stable conversation permalinks, and Sentry links appear when the runtime has enough Sentry configuration.
Conversation Privacy
Junior now classifies conversation privacy and redacts private message, thinking, tool argument, and tool result content before exposing dashboard APIs or trace metadata. Private views keep safe metadata such as actor, status, message counts, tool names, timing, and byte sizes without leaking raw transcript content.
Instrumentation And Packaging
Turn tracing captures more OpenTelemetry-aligned conversation metadata while respecting redaction policy. @sentry/node and @sentry/starlight-theme concrete versions are pinned through pnpm catalogs, and Junior owns its Sentry SDK dependency directly instead of requiring apps to install it separately.