Skip to content

feat: show live access-profile-backed usage in virtual key views#2761

Merged
akshaydeo merged 2 commits intov1.5.0from
feature/04-16-feat_show_live_access-profile-backed_usage_in_virtual_key_views
Apr 17, 2026
Merged

feat: show live access-profile-backed usage in virtual key views#2761
akshaydeo merged 2 commits intov1.5.0from
feature/04-16-feat_show_live_access-profile-backed_usage_in_virtual_key_views

Conversation

@danpiths
Copy link
Copy Markdown
Collaborator

@danpiths danpiths commented Apr 16, 2026

Summary

Reworks the virtual-keys table and details sheet to reflect live usage when a
VK is managed by an access profile, and extracts the supporting rate-limit
display + number formatting into shared pieces that the dashboard model
rankings tab also adopts. When a VK is attached to users via an access
profile, the governance plugin tracks usage on the AP rather than the VK (to
avoid double-counting); the UI now mirrors that — polling the managing AP
every 5s so bars update without a full page refresh — and soft-locks the VK
edit form to name/description only for managed VKs.

The "is this VK AP-managed?" signal is resolved strictly: a VK is treated as
managed only when an access profile explicitly lists it in virtual_key_ids
(no fallback to first-active / first AP), so multi-AP setups can't
misattribute one profile's budgets to another's VKs. Row status, budget
cells, and rate-limit cells all derive exhaustion from that same source, so
the Active / Exhausted badge stays in lockstep with the bars next to it.

Changes

Shared:

  • ui/lib/utils/governance.ts: new formatCompactNumber(n) (e.g.
    10_000 → "10K", 1_500_000 → "1.5M") and formatRateLimitLines(rl)
    helpers. formatCompactNumber is backed by Intl.NumberFormat compact
    notation so trailing zeros are dropped (10_000 → "10K", not "10.0K")
    and boundary values promote correctly (999_950 → "1M", not "1000.0K").
  • ui/components/rateLimitDisplay.tsx (new): shared <RateLimitDisplay>
    component with compact bars + tooltips, a limitOnly mode for template
    entities (access profiles), and a compact prop for tight cells.
  • ui/app/workspace/dashboard/components/modelRankingsTab.tsx: drop the
    local formatNumber copy in favor of the shared formatCompactNumber.

OSS build support:

  • ui/app/_fallbacks/enterprise/lib/types/accessProfile.ts,
    .../types/user.ts,
    .../store/apis/accessProfileApi.ts,
    .../store/apis/virtualKeyUsersApi.ts (new): stub types + no-op hooks
    that resolve the @enterprise/* imports used by useVirtualKeyUsage
    when building OSS. The hooks return { data: undefined, isLoading: false } so in OSS the hook never finds a managing AP and transparently
    falls through to the VK's own budgets / rate limits (identical behavior
    to pre-PR OSS). Mirrors the existing largePayload.ts fallback pattern.

Virtual keys:

  • ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts (new): resolves
    the managing access profile for a VK via useGetVirtualKeyUsersQuery +
    useGetUserAccessProfilesQuery (polled every 5s). The managing profile
    is matched strictly by virtual_key_ids.includes(vk.id), and
    isManagedByProfile = managingProfile !== undefined — a VK with
    direct-attached users but no AP relation is not treated as AP-managed.
    When profile-managed, displayBudgets / displayRateLimit mirror the AP's
    values (including empty ones — an AP with no rate limits shows nothing,
    instead of leaking the VK's own stale rate limits). When not
    profile-managed, the hook returns the VK's own budgets / rate limits as
    before. Also exposes assignedUsers and isExhausted (derived from the
    same source) so consumers don't reimplement the logic.
  • ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx:
    • Budget, rate-limit, and status cells all call useVirtualKeyUsage (RTK
      Query dedupes the underlying request across the per-row hook call
      sites) so row status and the bars beside it never disagree.
    • New "Rate Limits" column.
    • New VKStatusBadge component derives Active / Exhausted / Inactive
      from the hook's isExhausted, so a managed key never shows "Active"
      next to exhausted-looking bars.
    • For managed VKs, the row's delete button is a disabled button wrapped in
      a <span> with cursor-not-allowed and a tooltip (300ms delay) that
      explains the profile must be detached first — instead of luring the user
      into confirm-then-403.
    • Delete-confirm AlertDialog Cancel / Confirm buttons carry
      data-testid="vk-delete-cancel-${vk.name}" /
      data-testid="vk-delete-confirm-${vk.name}" per the project's
      entity-element-qualifier convention.
  • ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx: new
    UsageLine component with threshold-colored progress bars, managed-by
    info alert that explicitly calls out name/description as still editable,
    "Assigned To" section, and section headers that attribute budgets /
    rate limits to managingProfile.name when managed. Last reset {...}
    timestamps render only when the underlying token_last_reset /
    request_last_reset field is populated — no placeholder "just now" when
    the AP has never reset its counters.
  • ui/app/workspace/virtual-keys/views/virtualKeySheet.tsx: detect
    AP-managed VK on edit via the same useVirtualKeyUsage hook; if managed,
    submit only name/description updates and wrap the rest of the form in a
    disabled <fieldset> with a lock alert and assigned-users display. The
    detection uses the hook's strict isManagedByProfile so a VK with
    direct-attached (non-AP) users still gets the full edit form and its edits
    aren't silently dropped by the restricted submit path.

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

cd ui
pnpm i || npm i
pnpm build || npm run build

Functional:

  1. Create an access profile with budgets + rate limits and attach it to a
    user. The user gets a VK minted through the profile.
  2. Issue traffic against that VK and watch the virtual-keys table — the
    budget and rate-limit cells should update roughly every 5s without
    refreshing the page.
  3. Open the VK details sheet: the info banner should mention
    name/description remain editable, and the Budget/Rate Limits sections
    should be annotated "(from {access profile name})".
  4. Click the row's delete button — it should be disabled with a
    not-allowed cursor and show a tooltip (after ~300ms hover).
  5. Click "Edit" on the same VK — all fields except name/description should
    be locked by a visible <fieldset disabled> with an accompanying alert.
  6. For a non-managed VK, confirm table cells and the details sheet still
    render the VK's own counters and the full edit form is unlocked.
  7. Dashboard → Model Rankings: numbers like 10K, 1.5M still render
    correctly (now from the shared formatCompactNumber).

Screenshots/Recordings

UI change — screenshots/recordings to be attached in the PR description.

Breaking changes

  • Yes
  • No

Related issues

N/A

Security considerations

No auth, secret, or PII surface changes. The new hook only reads from
already-authorized RTK Query endpoints.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

@danpiths danpiths requested a review from akshaydeo April 16, 2026 11:10
Copy link
Copy Markdown
Collaborator Author

danpiths commented Apr 16, 2026

@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 16, 2026

📝 Walkthrough

Walkthrough

Virtual key usage now derives from assigned users' access profiles when present. A new hook fetches assigned users and profiles and exposes display budgets, rate-limits, and management flags; UI components use the hook, number formatting was centralized, and edit/delete flows are restricted for profile-managed virtual keys.

Changes

Cohort / File(s) Summary
Virtual Key Usage Hook
ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts
Added exported hook that queries assigned users and user access profiles, selects a managing profile (if any), and computes assignedUsers, managingProfile, isManagedByProfile, displayBudgets, displayRateLimit, hasApRateLimit, and isExhausted.
Virtual Key Views (details & edit)
ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx, ui/app/workspace/virtual-keys/views/virtualKeySheet.tsx
Switched rendering to use hook outputs; added managed-info Alert, Assigned Users section, usage progress UI (UsageLine), and disabled form/edit behavior when a VK is managed by a profile. Submit path short-circuits for managed VKs (only name/description).
Virtual Keys Table & Row Components
ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx
Added "Rate Limits" column and increased empty-state colspan; replaced inline budget/rate-limit/exhaustion logic with componentized cells and status/delete controls (VKBudgetCell, VKRateLimitCell/RateLimitDisplay, VKStatusBadge, VKDeleteButton) driven by useVirtualKeyUsage.
Rate Limit UI Component
ui/components/rateLimitDisplay.tsx
New exported RateLimitDisplay component that renders token/request rows, compact/limit-only modes, progress bars with threshold coloring, tooltips, and formatted max/reset labels.
Governance Utilities
ui/lib/utils/governance.ts
Added formatCompactNumber(n) using Intl compact notation and formatRateLimitLines(...) plus short-duration label mapping for rate-limit line construction.
Dashboard Number Formatting
ui/app/workspace/dashboard/components/modelRankingsTab.tsx
Replaced local formatNumber helper with imported formatCompactNumber from governance utilities.
Enterprise Fallback APIs & Types
ui/app/_fallbacks/enterprise/lib/store/apis/accessProfileApi.ts, ui/app/_fallbacks/enterprise/lib/store/apis/virtualKeyUsersApi.ts, ui/app/_fallbacks/enterprise/lib/types/accessProfile.ts, ui/app/_fallbacks/enterprise/lib/types/user.ts
Added stubbed RTK-query-style hooks (useGetUserAccessProfilesQuery, useGetVirtualKeyUsersQuery) returning constant shapes, and new types for access profiles, budget/rate-limit lines, User, and response shapes used by the hook/UI.
sequenceDiagram
    actor User
    participant VKUI as VirtualKey Sheet / Table
    participant Hook as useVirtualKeyUsage
    participant API as RTK Query (virtualKeyUsers / accessProfiles)
    participant UI as RateLimitDisplay / UsageLine

    User->>VKUI: open view or table row
    VKUI->>Hook: call useVirtualKeyUsage(vk)
    Hook->>API: useGetVirtualKeyUsersQuery(vk.id)
    API-->>Hook: assignedUsers[]
    alt assignedUsers non-empty
        Hook->>API: useGetUserAccessProfilesQuery(userId)
        API-->>Hook: accessProfiles[]
        Hook->>Hook: select managingProfile by virtual_key_ids
        Hook-->>VKUI: displayBudgets, displayRateLimit, isManagedByProfile, assignedUsers
    else no assignedUsers
        Hook-->>VKUI: fallback to vk.budgets, vk.rate_limit
    end
    VKUI->>UI: render UsageLine / RateLimitDisplay using display data
    UI-->>User: show progress bars, limits, and managed indicators
Loading

🎯 4 (Complex) | ⏱️ ~45 minutes

🐰 I dug through profiles, fetched users with care,
Budgets and limits now follow the one who’s there.
Managed keys locked gently — edits trimmed to a name,
Progress bars hop forward, numbers speak the same. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: showing live access-profile-backed usage in virtual key views, which is the primary objective of this feature-focused PR.
Description check ✅ Passed The PR description comprehensively covers the purpose, detailed changes, testing instructions, security considerations, and follows the template structure.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/04-16-feat_show_live_access-profile-backed_usage_in_virtual_key_views

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 16, 2026

Confidence Score: 5/5

Safe to merge; remaining findings are P2 style/consistency items that do not block correct behavior.

All previously flagged P1 concerns are addressed. The two remaining findings (CSV export inconsistency, isExhausted duplication) are P2 clean-up items with no runtime impact on the primary AP-backed usage display feature.

virtualKeysTable.tsx (CSV export for managed VKs), virtualKeyDetailsSheet.tsx (isExhausted duplication)

Important Files Changed

Filename Overview
ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts New hook resolving the managing AP for a VK; multi-AP and new Date() fallback issues from prior review are addressed; polling logic is correct.
ui/lib/utils/governance.ts New formatCompactNumber uses Intl.NumberFormat (fixes trailing-zero issue from prior review), formatRateLimitLines helper added correctly.
ui/components/rateLimitDisplay.tsx New shared component; limitOnly/compact modes well-handled; null-safety and color thresholds look correct.
ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx Four per-row hook instances for useVirtualKeyUsage; CSV export uses raw VK fields and will show stale status/budget for AP-managed keys.
ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx Recomputes isExhausted with truthy-checks instead of using the hook's returned value, creating subtle duplication; rendering logic otherwise correct.
ui/app/workspace/virtual-keys/views/virtualKeySheet.tsx AP-managed detection and submit-only-name/description guard are correctly implemented; fieldset disabled pattern is sound.
ui/app/_fallbacks/enterprise/lib/store/apis/accessProfileApi.ts OSS fallback correctly returns undefined so consumers fall back to VK-owned values.
ui/app/_fallbacks/enterprise/lib/store/apis/virtualKeyUsersApi.ts OSS fallback returns undefined data; no AP-managed detection will fire, correct.
ui/app/workspace/dashboard/components/modelRankingsTab.tsx Local formatNumber replaced by shared formatCompactNumber alias; clean refactor with no functional change.

Reviews (6): Last reviewed commit: "feat: show live access-profile-backed us..." | Re-trigger Greptile

Comment thread ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts Outdated
Comment thread ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts Outdated
Comment thread ui/lib/utils/governance.ts
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts`:
- Around line 23-39: The current logic infers AP-management from
assignedUsers[0] which can misattribute profiles; instead, stop assuming the
first assigned user is the manager: fetch access profiles for all assigned users
(e.g., call useGetUserAccessProfilesQuery per assignedUsers[*] or a batched
endpoint), then compute managingProfile by searching those users' profiles for
one where profile.virtual_key_ids includes vk.id; set isManagedByProfile true
only if such a matching profile exists and otherwise leave managingProfile
undefined (so keys assigned directly or with multiple users are not incorrectly
marked AP-managed). Use the existing symbols useGetVirtualKeyUsersQuery,
vkUsersData / assignedUsers, useGetUserAccessProfilesQuery and managingProfile
to locate and replace the current managingUserId-based logic.
- Around line 41-67: The code currently falls back to vk.budgets and
vk.rate_limit when managingProfile exists but has empty budget_lines or no
rate_limits; update the logic so that presence of managingProfile (not presence
of items) determines the source: for displayBudgets, if managingProfile is
defined return managingProfile.budget_lines (map to Budget objects if present,
else return an empty array or undefined consistent with downstream expectations)
instead of falling back to vk.budgets; for displayRateLimit, if managingProfile
is defined then use apRL if present (construct RateLimit when hasApRateLimit) or
set displayRateLimit to undefined (do not fall back to vk.rate_limit); change
the ternary conditions around displayBudgets and displayRateLimit to check
managingProfile !== undefined rather than relying on .length or truthiness so
profile-managed keys never show raw vk limits.

In `@ui/app/workspace/virtual-keys/views/virtualKeySheet.tsx`:
- Around line 162-165: The code incorrectly sets isManagedByProfile using
assignedUsers length; change it to detect an actual access-profile association
on the virtual key instead of checking for assignees. Replace the
isManagedByProfile assignment (currently using useGetVirtualKeyUsersQuery,
assignedUsers and assignedUsers.length) with a check for the virtualKey's
access-profile identifier/property (e.g. virtualKey?.accessProfileId or
virtualKey?.managedByAccessProfile) or, if there is a dedicated hook (e.g.
useGetVirtualKeyAccessProfileQuery), use that to determine profile ownership so
the restricted submit path only activates when the key is truly owned by an
access profile.

In `@ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx`:
- Around line 173-188: Add stable data-testid attributes to the dialog's confirm
and cancel controls so tests can target them: update the AlertDialogCancel
component to include data-testid="virtual-key-delete-cancel" and the
AlertDialogAction (the delete button that calls onDelete and uses isDeleting) to
include data-testid="virtual-key-delete-confirm"; ensure you add these to the
existing AlertDialogCancel and AlertDialogAction elements surrounding the
onDelete(vk.id) usage so selectors follow the pattern entity-element-qualifier.
- Around line 637-640: The row badge is still computing isExhausted from
vk.budgets / vk.rate_limit while VKBudgetCell and VKRateLimitCell now use the
AP-backed useVirtualKeyUsage hook; change the badge to derive exhaustion from
the same source by calling useVirtualKeyUsage (or consuming its returned
isExhausted/isExhaustedByBudget/isExhaustedByRateLimit) for the given vk (e.g.,
via vk.id) and use that value for the row-level isExhausted determination
instead of reading vk.budgets or vk.rate_limit directly so managed keys display
consistent Active/Exhausted state.

In `@ui/lib/utils/governance.ts`:
- Around line 34-39: The formatCompactNumber function currently produces
rollover artifacts (e.g., 999_950 -> "1000.0K" instead of "1.0M"); replace the
simple if-chain with a unit-scaling loop that divides the numeric value by 1000
until it's below 1000 or you hit the largest unit, then format with the desired
decimal places, but after formatting check if the rounded value equals 1000
(e.g., Number(formattedValue) === 1000); if so, divide once more and advance the
unit (promote K->M, M->B, etc.) before returning the final string—apply this
logic inside formatCompactNumber so boundary values are promoted to the next
unit correctly.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 60ad4dce-8b8b-49fd-a40a-7ce921713ca9

📥 Commits

Reviewing files that changed from the base of the PR and between 50ff0e0 and 0c02b29.

📒 Files selected for processing (7)
  • ui/app/workspace/dashboard/components/modelRankingsTab.tsx
  • ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts
  • ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx
  • ui/app/workspace/virtual-keys/views/virtualKeySheet.tsx
  • ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx
  • ui/components/rateLimitDisplay.tsx
  • ui/lib/utils/governance.ts

Comment thread ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts Outdated
Comment thread ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts Outdated
Comment thread ui/app/workspace/virtual-keys/views/virtualKeySheet.tsx Outdated
Comment thread ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx
Comment thread ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx
Comment thread ui/lib/utils/governance.ts
@danpiths danpiths force-pushed the feature/04-16-feat_consolidate_user_identity_context_key_and_propagate_user_name branch from 50ff0e0 to af73b47 Compare April 16, 2026 12:56
@danpiths danpiths force-pushed the feature/04-16-feat_show_live_access-profile-backed_usage_in_virtual_key_views branch from 0c02b29 to 3913095 Compare April 16, 2026 12:56
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx`:
- Around line 92-99: The label "Assigned To" used for the assignedUsers list is
ambiguous with the other "Assigned To" row; change the Label text in the block
that renders assignedUsers (the JSX using assignedUsers.map(...) and the Label
component) to "Assigned Users" (or another distinct string like "Users
Assigned") so the two sections are clearly differentiated; update only the Label
content in the virtualKeyDetailsSheet component where assignedUsers is rendered.

In `@ui/app/workspace/virtual-keys/views/virtualKeySheet.tsx`:
- Around line 162-165: The hook useVirtualKeyUsage currently checks only
assignedUsers[0] to determine AP ownership, so update its implementation to
search across all assignedUsers for an access-profile that contains the virtual
key (e.g., iterate assignedUsers and for each fetch/check their
accessProfiles.virtual_key_ids includes virtualKey.id), return the first
matching managing profile and set isManagedByProfileHook true when any assigned
user’s profile manages the key; ensure the virtualKeySheet code continues to use
isManagedByProfileHook (and the virtualKey id) so editing is disabled when any
assignee’s profile claims ownership.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d789b33a-9d68-42b6-a5c3-7946e18abc16

📥 Commits

Reviewing files that changed from the base of the PR and between 0c02b29 and 3913095.

📒 Files selected for processing (11)
  • ui/app/_fallbacks/enterprise/lib/store/apis/accessProfileApi.ts
  • ui/app/_fallbacks/enterprise/lib/store/apis/virtualKeyUsersApi.ts
  • ui/app/_fallbacks/enterprise/lib/types/accessProfile.ts
  • ui/app/_fallbacks/enterprise/lib/types/user.ts
  • ui/app/workspace/dashboard/components/modelRankingsTab.tsx
  • ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts
  • ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx
  • ui/app/workspace/virtual-keys/views/virtualKeySheet.tsx
  • ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx
  • ui/components/rateLimitDisplay.tsx
  • ui/lib/utils/governance.ts
✅ Files skipped from review due to trivial changes (4)
  • ui/app/_fallbacks/enterprise/lib/store/apis/accessProfileApi.ts
  • ui/app/_fallbacks/enterprise/lib/store/apis/virtualKeyUsersApi.ts
  • ui/app/_fallbacks/enterprise/lib/types/accessProfile.ts
  • ui/app/_fallbacks/enterprise/lib/types/user.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx
  • ui/lib/utils/governance.ts
  • ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts

Comment thread ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx
Comment thread ui/app/workspace/virtual-keys/views/virtualKeySheet.tsx
@danpiths danpiths force-pushed the feature/04-16-feat_show_live_access-profile-backed_usage_in_virtual_key_views branch from 3913095 to 1a2e6e1 Compare April 16, 2026 19:43
@danpiths danpiths force-pushed the feature/04-16-feat_consolidate_user_identity_context_key_and_propagate_user_name branch from af73b47 to 529faf5 Compare April 16, 2026 19:43
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx (1)

15-15: Prefer the @/ alias for this hook import.

This file already uses project aliases elsewhere; switching this one off the relative path keeps the UI import style consistent and avoids fragile ../ traversal.

Proposed fix
-import { useVirtualKeyUsage } from "../hooks/useVirtualKeyUsage";
+import { useVirtualKeyUsage } from "@/app/workspace/virtual-keys/hooks/useVirtualKeyUsage";

Based on learnings: In the UI codebase, prefer alias imports using @/... over relative imports.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx` at line 15,
Replace the relative import of the hook in virtualKeyDetailsSheet.tsx: update
the import of useVirtualKeyUsage to use the project alias (starting with "@/")
instead of "../hooks/useVirtualKeyUsage" so the file follows the same
alias-based import style used elsewhere (i.e., import useVirtualKeyUsage from
"@/.../useVirtualKeyUsage").
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts`:
- Around line 19-41: Add an explicit ownership-loading flag so callers can treat
ownership as unknown until queries resolve: update useVirtualKeyUsage to return
a new boolean (e.g., isOwnershipLoading) and compute it from the query
loading/fetching flags and undefined data from useGetVirtualKeyUsersQuery and
useGetUserAccessProfilesQuery (and account for the skip logic via
managingUserId). While isOwnershipLoading is true, keep
managingProfile/isManagedByProfile as-is or undefined so callers can avoid
treating the VK as unowned; update the hook's return signature to include
isOwnershipLoading and adjust callers to hold off on destructive actions until
that flag is false.

In `@ui/app/workspace/virtual-keys/views/virtualKeySheet.tsx`:
- Around line 409-416: The managed-key update currently uses "description:
data.description || undefined" which omits falsy values and prevents clearing
the description; change the payload logic in the isManagedByProfile branch
(where updateVirtualKey is called with vkId and data) to send an explicit null
when the user cleared the field (e.g. description: data.description === '' ?
null : data.description ?? undefined) so the backend receives an explicit clear
intent, while preserving the current handling for name (data.name || undefined)
or using the null-aware pattern if desired.

In `@ui/lib/utils/governance.ts`:
- Around line 71-76: The UI currently hides unmapped rate-limit durations by
using shortDurationLabels[...] ?? "" which yields strings like "10K tokens"
without the window; update the suffix logic used for both token and request
blocks (where shortDurationLabels is referenced and lines.push uses
formatCompactNumber for token_max_limit and request_max_limit) to fall back to
the raw duration string when no mapping exists (e.g., use
rateLimits.token_reset_duration or rateLimits.request_reset_duration as the
fallback) so the displayed text becomes "10K tokens/30s" or "10K req/1Y" instead
of omitting the window entirely.

---

Nitpick comments:
In `@ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx`:
- Line 15: Replace the relative import of the hook in
virtualKeyDetailsSheet.tsx: update the import of useVirtualKeyUsage to use the
project alias (starting with "@/") instead of "../hooks/useVirtualKeyUsage" so
the file follows the same alias-based import style used elsewhere (i.e., import
useVirtualKeyUsage from "@/.../useVirtualKeyUsage").
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 19e612a7-79cd-4a79-8558-72ad2b625f15

📥 Commits

Reviewing files that changed from the base of the PR and between 3913095 and 1a2e6e1.

📒 Files selected for processing (11)
  • ui/app/_fallbacks/enterprise/lib/store/apis/accessProfileApi.ts
  • ui/app/_fallbacks/enterprise/lib/store/apis/virtualKeyUsersApi.ts
  • ui/app/_fallbacks/enterprise/lib/types/accessProfile.ts
  • ui/app/_fallbacks/enterprise/lib/types/user.ts
  • ui/app/workspace/dashboard/components/modelRankingsTab.tsx
  • ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts
  • ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx
  • ui/app/workspace/virtual-keys/views/virtualKeySheet.tsx
  • ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx
  • ui/components/rateLimitDisplay.tsx
  • ui/lib/utils/governance.ts
✅ Files skipped from review due to trivial changes (4)
  • ui/app/_fallbacks/enterprise/lib/store/apis/accessProfileApi.ts
  • ui/app/_fallbacks/enterprise/lib/store/apis/virtualKeyUsersApi.ts
  • ui/app/_fallbacks/enterprise/lib/types/accessProfile.ts
  • ui/app/_fallbacks/enterprise/lib/types/user.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • ui/app/workspace/dashboard/components/modelRankingsTab.tsx
  • ui/components/rateLimitDisplay.tsx
  • ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx

Comment thread ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts
Comment thread ui/app/workspace/virtual-keys/views/virtualKeySheet.tsx
Comment thread ui/lib/utils/governance.ts Outdated
@danpiths danpiths force-pushed the feature/04-16-feat_show_live_access-profile-backed_usage_in_virtual_key_views branch from 1a2e6e1 to ab41166 Compare April 17, 2026 07:42
@danpiths danpiths force-pushed the feature/04-16-feat_consolidate_user_identity_context_key_and_propagate_user_name branch from 529faf5 to 313d58b Compare April 17, 2026 07:42
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx (1)

54-73: CSV export shows raw VK values, not AP-managed live usage.

The virtualKeysToCSV function reads directly from vk.budgets / vk.rate_limit, while the table cells now display AP-managed values via useVirtualKeyUsage. Users exporting CSV may see different numbers than displayed in the UI for AP-managed keys.

If intentional (export captures VK-owned governance, not live AP counters), consider adding a note in the export dialog. Otherwise, this may need alignment.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx` around lines 54 -
73, virtualKeysToCSV currently reads static governance fields (vk.budgets,
vk.rate_limit) which causes exported CSV to diverge from the AP-managed live
values shown by useVirtualKeyUsage; update virtualKeysToCSV to accept (or be
passed) the AP-managed live usage data (e.g., a usage map produced by
useVirtualKeyUsage) and use those live counters for Budget Spent / Status /
Budget Limit columns instead of vk.budgets/vk.rate_limit, falling back to vk
fields if live data is unavailable; alternatively, if the intent is to export
governance-only values, add a clear descriptive flag/parameter and surface that
in the export UI so callers choose which dataset to export.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx`:
- Around line 217-226: The provider-budget and rate-limit blocks in
virtualKeyDetailsSheet.tsx currently call formatDistanceToNow(new
Date(b.last_reset)) without guarding for null/empty last_reset, causing "Invalid
Date" errors; update the provider budget and rate-limit renderers (the blocks
that render b.last_reset and similar provider.rate_limit.last_reset) to use the
same conditional pattern as the VK-level rate-limit section: check that
last_reset is present/truthy before calling new Date(...) and
formatDistanceToNow, and otherwise render a placeholder like "never" or "-" so
the UI never passes an invalid date into formatDistanceToNow (ensure you update
every occurrence where b.last_reset or provider.rate_limit.last_reset is used).
- Around line 344-357: The budget render block passes b.last_reset directly into
new Date() which can be empty/undefined and yields "Invalid Date"; update the
displayBudgets map in VirtualKeyDetailsSheet so the "Last reset" span only calls
formatDistanceToNow(new Date(...)) when b.last_reset is present and parses to a
valid date (e.g., Date.parse(b.last_reset) not NaN), otherwise render a safe
fallback like "never" or an empty string; locate the displayBudgets mapping and
change the b.last_reset usage inside the span to perform this guard before
calling formatDistanceToNow.

---

Nitpick comments:
In `@ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx`:
- Around line 54-73: virtualKeysToCSV currently reads static governance fields
(vk.budgets, vk.rate_limit) which causes exported CSV to diverge from the
AP-managed live values shown by useVirtualKeyUsage; update virtualKeysToCSV to
accept (or be passed) the AP-managed live usage data (e.g., a usage map produced
by useVirtualKeyUsage) and use those live counters for Budget Spent / Status /
Budget Limit columns instead of vk.budgets/vk.rate_limit, falling back to vk
fields if live data is unavailable; alternatively, if the intent is to export
governance-only values, add a clear descriptive flag/parameter and surface that
in the export UI so callers choose which dataset to export.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1b8523dc-e3e5-45a5-b75d-c45ad1f1a436

📥 Commits

Reviewing files that changed from the base of the PR and between 1a2e6e1 and ab41166.

📒 Files selected for processing (11)
  • ui/app/_fallbacks/enterprise/lib/store/apis/accessProfileApi.ts
  • ui/app/_fallbacks/enterprise/lib/store/apis/virtualKeyUsersApi.ts
  • ui/app/_fallbacks/enterprise/lib/types/accessProfile.ts
  • ui/app/_fallbacks/enterprise/lib/types/user.ts
  • ui/app/workspace/dashboard/components/modelRankingsTab.tsx
  • ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts
  • ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx
  • ui/app/workspace/virtual-keys/views/virtualKeySheet.tsx
  • ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx
  • ui/components/rateLimitDisplay.tsx
  • ui/lib/utils/governance.ts
✅ Files skipped from review due to trivial changes (5)
  • ui/app/workspace/dashboard/components/modelRankingsTab.tsx
  • ui/app/_fallbacks/enterprise/lib/store/apis/accessProfileApi.ts
  • ui/app/_fallbacks/enterprise/lib/store/apis/virtualKeyUsersApi.ts
  • ui/app/_fallbacks/enterprise/lib/types/accessProfile.ts
  • ui/app/_fallbacks/enterprise/lib/types/user.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • ui/components/rateLimitDisplay.tsx
  • ui/app/workspace/virtual-keys/views/virtualKeySheet.tsx

Comment thread ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx
Comment thread ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx
@danpiths danpiths force-pushed the feature/04-16-feat_show_live_access-profile-backed_usage_in_virtual_key_views branch from ab41166 to c8e88fc Compare April 17, 2026 10:44
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx (1)

47-71: ⚠️ Potential issue | 🟡 Minor

Use hook-provided exhaustion state to avoid drift and zero-limit edge bugs.

isExhausted is recomputed locally with truthy checks (token_current_usage && token_max_limit), which diverges from the hook's canonical != null logic and can misclassify zero-valued usage as non-exhausted.

Suggested fix
-	const { assignedUsers, isManagedByProfile, managingProfile, hasApRateLimit, displayBudgets, displayRateLimit } =
+	const { assignedUsers, isManagedByProfile, managingProfile, hasApRateLimit, displayBudgets, displayRateLimit, isExhausted } =
 		useVirtualKeyUsage(virtualKey);
 
-	const isExhausted =
-		// Budget exhausted (AP-mirrored when managed, VK-own otherwise)
-		displayBudgets?.some((b) => b.current_usage >= b.max_limit) ||
-		// Rate limits exhausted
-		(displayRateLimit?.token_current_usage &&
-			displayRateLimit?.token_max_limit &&
-			displayRateLimit.token_current_usage >= displayRateLimit.token_max_limit) ||
-		(displayRateLimit?.request_current_usage &&
-			displayRateLimit?.request_max_limit &&
-			displayRateLimit.request_current_usage >= displayRateLimit.request_max_limit);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx` around lines
47 - 71, The local isExhausted recomputes exhaustion with truthy checks (which
misclassifies zero values) instead of using the canonical exhaustion value from
the hook; replace the manual computation by consuming the exhaustion state
returned by useVirtualKeyUsage (e.g., use the hook's isExhausted or equivalent
property) and remove the local displayBudgets/displayRateLimit truthy checks;
ensure you fall back to false if the hook value is undefined so the component
uses the hook's canonical null/!= null semantics rather than the current
token_current_usage && token_max_limit style.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx`:
- Around line 242-275: The UI hides rate-limit sections when max limit values
are 0 because it uses truthy checks; change all conditionals that test
config.rate_limit.token_max_limit and config.rate_limit.request_max_limit to
nullish presence checks (e.g., compare against null/undefined using != null) so
zero is treated as a valid limit, and update the "No rate limits configured"
rendering logic to only show when both token_max_limit and request_max_limit are
null/undefined (not when they are 0). Locate and update conditionals around
config.rate_limit.token_max_limit, config.rate_limit.request_max_limit and the
related "No rate limits configured" branches (UsageLine, parseResetPeriod,
token_last_reset/request_last_reset) to use != null checks.

---

Outside diff comments:
In `@ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx`:
- Around line 47-71: The local isExhausted recomputes exhaustion with truthy
checks (which misclassifies zero values) instead of using the canonical
exhaustion value from the hook; replace the manual computation by consuming the
exhaustion state returned by useVirtualKeyUsage (e.g., use the hook's
isExhausted or equivalent property) and remove the local
displayBudgets/displayRateLimit truthy checks; ensure you fall back to false if
the hook value is undefined so the component uses the hook's canonical null/!=
null semantics rather than the current token_current_usage && token_max_limit
style.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3e810be1-8d83-40ff-8cdb-5bdef6182fbf

📥 Commits

Reviewing files that changed from the base of the PR and between ab41166 and c8e88fc.

📒 Files selected for processing (11)
  • ui/app/_fallbacks/enterprise/lib/store/apis/accessProfileApi.ts
  • ui/app/_fallbacks/enterprise/lib/store/apis/virtualKeyUsersApi.ts
  • ui/app/_fallbacks/enterprise/lib/types/accessProfile.ts
  • ui/app/_fallbacks/enterprise/lib/types/user.ts
  • ui/app/workspace/dashboard/components/modelRankingsTab.tsx
  • ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts
  • ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx
  • ui/app/workspace/virtual-keys/views/virtualKeySheet.tsx
  • ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx
  • ui/components/rateLimitDisplay.tsx
  • ui/lib/utils/governance.ts
✅ Files skipped from review due to trivial changes (4)
  • ui/app/_fallbacks/enterprise/lib/store/apis/virtualKeyUsersApi.ts
  • ui/app/_fallbacks/enterprise/lib/types/accessProfile.ts
  • ui/components/rateLimitDisplay.tsx
  • ui/app/_fallbacks/enterprise/lib/types/user.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • ui/app/workspace/dashboard/components/modelRankingsTab.tsx
  • ui/app/_fallbacks/enterprise/lib/store/apis/accessProfileApi.ts
  • ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts
  • ui/app/workspace/virtual-keys/views/virtualKeySheet.tsx
  • ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx

Comment thread ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx Outdated
@danpiths danpiths force-pushed the feature/04-16-feat_show_live_access-profile-backed_usage_in_virtual_key_views branch from c8e88fc to 1e7027c Compare April 17, 2026 11:05
@danpiths danpiths force-pushed the feature/04-16-feat_show_live_access-profile-backed_usage_in_virtual_key_views branch from 1e7027c to aefb353 Compare April 17, 2026 11:05
@danpiths danpiths force-pushed the feature/04-16-feat_consolidate_user_identity_context_key_and_propagate_user_name branch from 313d58b to 3bd057e Compare April 17, 2026 11:05
Copy link
Copy Markdown
Collaborator Author

@coderabbitai resolve

coderabbitai[bot]
coderabbitai Bot previously approved these changes Apr 17, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 17, 2026

✅ Actions performed

Comments resolved and changes approved.

akshaydeo
akshaydeo previously approved these changes Apr 17, 2026
Copy link
Copy Markdown
Contributor

akshaydeo commented Apr 17, 2026

Merge activity

  • Apr 17, 5:17 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Apr 17, 5:19 PM UTC: Graphite couldn't merge this PR because it was not satisfying all requirements (PR does not have required approvals).
  • Apr 17, 5:23 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Apr 17, 5:24 PM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo akshaydeo changed the base branch from feature/04-16-feat_consolidate_user_identity_context_key_and_propagate_user_name to graphite-base/2761 April 17, 2026 17:18
@akshaydeo akshaydeo changed the base branch from graphite-base/2761 to v1.5.0 April 17, 2026 17:18
@akshaydeo akshaydeo dismissed stale reviews from coderabbitai[bot] and themself April 17, 2026 17:18

The base branch was changed.

@akshaydeo akshaydeo merged commit a77f037 into v1.5.0 Apr 17, 2026
13 of 15 checks passed
@akshaydeo akshaydeo deleted the feature/04-16-feat_show_live_access-profile-backed_usage_in_virtual_key_views branch April 17, 2026 17:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants