ui: add OAuth Grants page and identity exact-match filter for MCP sessions#4511
Conversation
|
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (16)
✅ Files skipped from review due to trivial changes (2)
🚧 Files skipped from review as they are similar to previous changes (14)
📝 WalkthroughSummary by CodeRabbit
WalkthroughAdds an exact-match ChangesMCP Sessions identity filter
OAuth Grants management
Sequence Diagram(s)sequenceDiagram
participant User
participant OAuthGrantsPage
participant oauth2SessionsApi
participant Server
User->>OAuthGrantsPage: Navigate to /workspace/oauth-grants
OAuthGrantsPage->>oauth2SessionsApi: useGetOAuth2GrantsQuery()
oauth2SessionsApi->>Server: GET /oauth2/sessions
Server-->>oauth2SessionsApi: OAuth2GrantsListResponse
oauth2SessionsApi-->>OAuthGrantsPage: grant rows
User->>OAuthGrantsPage: Filter by search/mode or modify offset
OAuthGrantsPage->>OAuthGrantsPage: Client-side filter + slice paginated results
User->>OAuthGrantsPage: Click "Revoke" on a row
OAuthGrantsPage->>OAuthGrantsPage: Open RevokeGrantDialog
User->>OAuthGrantsPage: Confirm revoke
OAuthGrantsPage->>oauth2SessionsApi: useRevokeOAuth2GrantMutation(id)
oauth2SessionsApi->>Server: DELETE /oauth2/sessions/:id
Server-->>oauth2SessionsApi: 200 OK
oauth2SessionsApi->>baseApi: Invalidate "OAuth2Grants" tag
baseApi-->>OAuthGrantsPage: Cache invalidated, trigger refetch
OAuthGrantsPage-->>User: Toast success or error message
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 golangci-lint (2.12.2)level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies" Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
ui/lib/store/apis/oauth2SessionsApi.ts (1)
25-28: ⚡ Quick winPrefer deterministic cache patch for revoke to avoid stale grants rows.
For this delete-by-id mutation, patching
getOAuth2GrantsinonQueryStartedis safer than full invalidation in this codebase’s clustered setup.♻️ Suggested change
revokeOAuth2Grant: builder.mutation<void, string>({ query: (id) => ({ url: `/oauth2/sessions/${id}`, method: "DELETE" }), - invalidatesTags: ["OAuth2Grants"], + async onQueryStarted(id, { dispatch, queryFulfilled }) { + const patch = dispatch( + oauth2SessionsApi.util.updateQueryData("getOAuth2Grants", undefined, (draft) => { + draft.sessions = draft.sessions.filter((s) => s.id !== id); + }), + ); + try { + await queryFulfilled; + } catch { + patch.undo(); + } + }, }),Based on learnings: “In
ui/lib/store/apis/, optimistically patch the cache withonQueryStarted + updateQueryDatafor deterministic mutations like deleting a known row.”🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@ui/lib/store/apis/oauth2SessionsApi.ts` around lines 25 - 28, The revokeOAuth2Grant mutation currently uses invalidatesTags to fully invalidate the OAuth2Grants cache, which can cause stale rows in a clustered setup. Replace the invalidatesTags approach with an onQueryStarted handler that uses updateQueryData to patch the getOAuth2Grants query cache. The handler should optimistically remove the revoked grant with the matching ID from the cached grants list, ensuring only the specific deleted grant is removed rather than invalidating the entire cache, making the mutation deterministic and cache-safe.Source: Learnings
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@ui/app/workspace/mcp-sessions/page.tsx`:
- Line 35: Normalize the identity value before using it in the query and
active-filter checks to handle whitespace-only values consistently with the
backend. At line 35 where identity is assigned from urlState.identity and at
line 69 where it's used in the active-filter check, apply trimming to the
identity string and convert empty or whitespace-only values to undefined. This
ensures that values like identity=%20 don't create inconsistent UI state and
unnecessary cache fragmentation between the UI and backend behavior.
In `@ui/app/workspace/oauth-grants/page.tsx`:
- Around line 108-126: The AlertDialog component in the revoke confirmation
dialog is missing data-testid attributes on its interactive controls for E2E
testing. Add data-testid attributes to the AlertDialogCancel (Cancel button) and
AlertDialogAction (Revoke button) elements within the AlertDialogFooter to
ensure they are properly selectable in E2E tests, following the repository's
testing convention.
- Around line 305-317: The AccessTokenExpiry function does not validate that the
timestamp from row.created_at is valid before using it in calculations. When new
Date(row.created_at).getTime() receives an invalid date string, it returns NaN
instead of throwing an error, which causes the function to render "in NaN min".
Add a Number.isFinite() guard check immediately after calculating createdMs to
validate it is a valid number, and return a fallback span with an appropriate
message (such as "Unknown expiry") if the timestamp is invalid. This same
validation pattern should also be applied to other similar timestamp
calculations referenced in the "Also applies to" comment at lines 401-414.
- Around line 60-276: The OAuthGrantsPage component contains excessive UI logic
and rendering that should be extracted into view components according to project
conventions. Move the filter bar section (search input, ComboboxSelect, clear
filters button) into a separate view component, extract the table rendering
logic with its header and body rows into another view component, and separate
the AlertDialog confirmation logic into its own component. Keep the
OAuthGrantsPage function focused on state management and composition, delegating
rendering to these view components. Create these new components in a views/
subdirectory alongside page.tsx.
---
Nitpick comments:
In `@ui/lib/store/apis/oauth2SessionsApi.ts`:
- Around line 25-28: The revokeOAuth2Grant mutation currently uses
invalidatesTags to fully invalidate the OAuth2Grants cache, which can cause
stale rows in a clustered setup. Replace the invalidatesTags approach with an
onQueryStarted handler that uses updateQueryData to patch the getOAuth2Grants
query cache. The handler should optimistically remove the revoked grant with the
matching ID from the cached grants list, ensuring only the specific deleted
grant is removed rather than invalidating the entire cache, making the mutation
deterministic and cache-safe.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 41aea2ef-4014-4abc-bd40-7165db2edfda
📒 Files selected for processing (12)
framework/configstore/rdb.goframework/configstore/store.gotransports/bifrost-http/handlers/mcp_sessions.goui/app/workspace/mcp-sessions/page.tsxui/app/workspace/oauth-grants/layout.tsxui/app/workspace/oauth-grants/page.tsxui/components/sidebar.tsxui/lib/store/apis/baseApi.tsui/lib/store/apis/index.tsui/lib/store/apis/mcpSessionsApi.tsui/lib/store/apis/oauth2SessionsApi.tsui/lib/types/mcpSessions.ts
identity exact-match filter for MCP sessionsidentity exact-match filter for MCP sessions
ffd24d4 to
9424fab
Compare
e5a9a8f to
47cce08
Compare
9424fab to
41e5b36
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@ui/app/workspace/oauth-grants/page.tsx`:
- Around line 33-35: The pagination offset can become invalid when the filtered
results shrink after actions like revoking items. On line 34 where
filtered.slice is called with offset, the offset variable needs to be clamped to
ensure it doesn't exceed the bounds of the new filtered array. Before calling
slice with offset and offset + PAGE_SIZE, calculate the maximum valid offset
using Math.max(0, Math.floor((totalCount - 1) / PAGE_SIZE)) or similar logic,
then use the smaller of the current offset and this maximum value to ensure
pagination stays within valid bounds when the filtered count decreases.
In `@ui/app/workspace/oauth-grants/views/grantActions.tsx`:
- Around line 40-47: The conditional check on the DropdownMenuItem gating the
View auth sessions link currently only includes user and vk modes, excluding
session-based grants. Extend the bf_mode condition to also include the "session"
mode so that session-bound grants can navigate to auth sessions, aligning with
the identity filter contract that supports exact matching on session_id just as
it does for user_id and virtual_key_id.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 92a7db2e-849e-43c1-8365-68106e57eb5f
📒 Files selected for processing (16)
framework/configstore/rdb.goframework/configstore/store.gotransports/bifrost-http/handlers/mcp_sessions.goui/app/workspace/mcp-sessions/page.tsxui/app/workspace/oauth-grants/layout.tsxui/app/workspace/oauth-grants/page.tsxui/app/workspace/oauth-grants/views/grantActions.tsxui/app/workspace/oauth-grants/views/grantsFilterBar.tsxui/app/workspace/oauth-grants/views/grantsTable.tsxui/app/workspace/oauth-grants/views/revokeGrantDialog.tsxui/components/sidebar.tsxui/lib/store/apis/baseApi.tsui/lib/store/apis/index.tsui/lib/store/apis/mcpSessionsApi.tsui/lib/store/apis/oauth2SessionsApi.tsui/lib/types/mcpSessions.ts
✅ Files skipped from review due to trivial changes (3)
- ui/app/workspace/oauth-grants/layout.tsx
- ui/lib/store/apis/index.ts
- ui/lib/store/apis/baseApi.ts
🚧 Files skipped from review as they are similar to previous changes (6)
- ui/components/sidebar.tsx
- ui/lib/store/apis/mcpSessionsApi.ts
- framework/configstore/rdb.go
- transports/bifrost-http/handlers/mcp_sessions.go
- ui/lib/store/apis/oauth2SessionsApi.ts
- ui/app/workspace/mcp-sessions/page.tsx
41e5b36 to
d30ef75
Compare
47cce08 to
577e9c3
Compare
577e9c3 to
87046c1
Compare
d30ef75 to
15499ee
Compare
87046c1 to
c6c30c4
Compare
15499ee to
8bff02e
Compare
8bff02e to
93724be
Compare
c6c30c4 to
1525b40
Compare
93724be to
5da157b
Compare
1525b40 to
3ab71d6
Compare

Summary
Adds an OAuth Grants management page to the UI and introduces an
identityexact-match filter for MCP sessions. Together these allow operators to view all active downstream OAuth grants issued to MCP clients and drill through from a grant directly to the auth sessions belonging to that specific identity.Changes
Identityfield toMCPSessionsFilterParamsin the config store, which exact-matches againstuser_id,virtual_key_id, orsession_idcolumns (ANDed with any other active filters).identityquery parameter in the HTTP handler so callers can pass it via the API.identityto the MCP sessions URL state and query params in the UI, included it in the "has active filters" check, and wired it intohandleClearFilters.oauth2SessionsApi.tswithgetOAuth2GrantsandrevokeOAuth2Grantendpoints, registered theOAuth2Grantscache tag inbaseApi, and exported the new API from the store index.OAuthGrantsPagecomponent with client-side search and mode filtering, a paginated table showing client name, bound identity (user/virtual key/anonymous session), access token expiry, created time, and last used time, and per-row actions to revoke a grant or navigate to MCP sessions pre-filtered to that identity viaauth_mode+identityquery params.The
identityfilter is intentionally an exact match (not a substring) so that linking from a grant to its sessions produces a precise, unambiguous result rather than a fuzzy hit list.Type of change
Affected areas
How to test
&identity=<some-id>to the URL and confirm only sessions matching that exact identity are returned.Screenshots/Recordings
Add before/after screenshots of the OAuth Grants page and the MCP Sessions identity filter.
Breaking changes
Related issues
Link related issues here.
Security considerations
Revocation stops refresh token rotation immediately; the current short-lived JWT access token (≤10 min TTL) remains valid until it expires naturally. This is documented in the revocation confirmation dialog so operators understand the brief window before full cutoff.
Checklist
docs/contributing/README.mdand followed the guidelines