budget overrides ui - #5443
budget overrides ui#5443
Conversation
|
|
📝 WalkthroughWalkthroughBudget overrides were added to governance contracts, utilities, API mutations, and virtual-key UI flows. Effective limits now drive usage, exhaustion, displays, and CSV exports. Test command modules update Bifrost core to v1.7.3. ChangesVirtual-key budget overrides
Go module updates
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Operator
participant BudgetOverrideDialog
participant virtualKeySheet
participant governanceApi
participant VirtualKeyBudgetEndpoint
Operator->>BudgetOverrideDialog: enter override amount and duration
BudgetOverrideDialog->>virtualKeySheet: submit validated request
virtualKeySheet->>governanceApi: set budget override
governanceApi->>VirtualKeyBudgetEndpoint: PUT override request
VirtualKeyBudgetEndpoint-->>governanceApi: updated budget and effective limit
governanceApi-->>virtualKeySheet: mutation result and cache invalidation
virtualKeySheet-->>Operator: render updated override and budget
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
@coderabbitai full review |
✅ Action performedFull review finished. You're currently rate limited under our Fair Usage Limits Policy. Your recent PR review activity is in the 95th percentile or higher among CodeRabbit users, so adaptive limits apply. Your next review will be available in 29 minutes. |
05389e1 to
1e1c2e5
Compare
|
@coderabbitai full review |
✅ Action performedFull review finished. |
1e1c2e5 to
d2c4c2a
Compare
46b5981 to
4657156
Compare
There was a problem hiding this comment.
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 (2)
ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx (1)
73-113: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winRate-limit exhaustion logic is duplicated with a truthy-vs-null-check divergence across three implementations.
useVirtualKeyUsage.ts(lines 77-84) correctly uses!= nullguards when comparing rate-limit current usage against max limits. Two other call sites reimplement the same comparison with truthy guards (value && ...), which silently skip the edge case wherecurrent_usageis0andmax_limitis also0(fully exhausted zero-limit) because0 && ...never reaches the comparison. This PR already had to apply the same one-linegetEffectiveBudgetLimitfix to all three places for the budget half of the check — the rate-limit half shows the duplication is real and prone to drift.
ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx#L73-L113: destructure and useisExhausteddirectly fromuseVirtualKeyUsage(virtualKey)(already called here) instead of recomputing it locally.ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx#L75-L82: this file doesn't use the hook (it maps over a rawVirtualKey[]for CSV export), so extract the shared exhaustion logic (budgets viagetEffectiveBudgetLimit+ rate limits via!= nullchecks) into a reusable utility inui/lib/utils/governance.tsand have bothuseVirtualKeyUsage.tsandvirtualKeysToCSVcall it.🤖 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/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx` around lines 73 - 113, The duplicated exhaustion logic must be centralized and reused. In ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx lines 73-113, destructure isExhausted from the existing useVirtualKeyUsage(virtualKey) call and remove the local calculation. In ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx lines 75-82, use a shared utility from ui/lib/utils/governance.ts that checks budgets via getEffectiveBudgetLimit and rate limits with != null guards; update useVirtualKeyUsage.ts to call the same utility.ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx (1)
75-82: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winRate-limit exhaustion check uses truthy comparisons instead of null-safe checks.
Same divergence as
virtualKeyDetailsSheet.tsx:vk.rate_limit?.token_current_usage && vk.rate_limit?.token_max_limit && ...misses the zero-usage/zero-limit exhausted case thatuseVirtualKeyUsage.ts's!= nullversion correctly catches. See consolidated comment below.🤖 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/app/workspace/virtual-keys/views/virtualKeysTable.tsx` around lines 75 - 82, Update the isExhausted calculation in the virtual keys table to use null-safe presence checks for token_current_usage, token_max_limit, request_current_usage, and request_max_limit instead of truthiness checks. Preserve the existing budget comparison and ensure zero-valued usage or limits are still compared and can mark the key exhausted, matching useVirtualKeyUsage.ts.
🧹 Nitpick comments (4)
ui/app/_fallbacks/enterprise/lib/types/accessProfile.ts (1)
8-10: 📐 Maintainability & Code Quality | 🔵 TrivialDuplicated override-mode literal instead of reusing
BudgetOverrideMode.
override_mode?: "cycles" | "forever"re-declares the union thatBudgetOverrideMode(inui/lib/types/governance.ts) already exports. See consolidated comment below for the shared fix across files.🤖 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/app/_fallbacks/enterprise/lib/types/accessProfile.ts` around lines 8 - 10, Update the access profile type’s override_mode field to reuse the exported BudgetOverrideMode type from governance.ts instead of redeclaring the "cycles" | "forever" union. Preserve the field’s optionality and leave override_amount and override_cycles_remaining unchanged.ui/components/budgetOverrideDialog.tsx (2)
181-199: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win"Remove override" gives no loading feedback.
Unlike the codebase's established pattern (e.g., the Rotate Key button's "Rotating..." label), the destructive Remove button only becomes
disabledwhileisSaving— no spinner or text change signals the in-flight request.⏳ Suggested fix
<Button type="button" variant="destructive" className="rounded-sm" onClick={handleRemove} disabled={isSaving} data-testid="budget-override-remove" > - Remove override + {isSaving ? "Removing..." : "Remove override"} </Button>As per path instructions, "For ui/**, check interactive workflows for loading, empty, error, and success states."
🤖 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/components/budgetOverrideDialog.tsx` around lines 181 - 199, The Remove override button in the budget override dialog lacks in-flight loading feedback. Update the Button controlled by handleRemove and isSaving to use the established loading presentation, including a spinner or loading label while isSaving, while preserving its destructive styling and disabled behavior.Source: Path instructions
132-143: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win"Duration" label isn't programmatically associated with the Select.
Unlike the amount/cycles fields (which pair
Label htmlForwith matchingInput id), the DurationLabelhas nohtmlForandSelectTriggerhas noid, so screen readers can't associate them.Note: adding
id/htmlForis the standard fix, but Radix's own tracker documents cases whereSelect.Triggerdoesn't forward theidto the underlying element for full label association — worth confirming this project'sSelectwrapper actually resolves it before relying solely on that fix.♿ Suggested fix (verify wrapper forwards id correctly)
- <Label>Duration</Label> - <Select value={mode} onValueChange={(value) => setMode(value as "cycles" | "forever")} disabled={isSaving}> - <SelectTrigger className="w-full rounded-sm" data-testid="budget-override-mode"> + <Label htmlFor={`budget-override-mode-${budget.id}`}>Duration</Label> + <Select value={mode} onValueChange={(value) => setMode(value as "cycles" | "forever")} disabled={isSaving}> + <SelectTrigger id={`budget-override-mode-${budget.id}`} className="w-full rounded-sm" data-testid="budget-override-mode">🤖 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/components/budgetOverrideDialog.tsx` around lines 132 - 143, Associate the Duration label with the mode Select by adding a matching identifier to the Label’s htmlFor and the SelectTrigger’s id. Update the project’s Select wrapper usage around SelectTrigger to confirm the id reaches the underlying control; if it does not, apply the wrapper-supported association mechanism while preserving the existing mode and disabled behavior.ui/lib/utils/governance.ts (1)
33-56: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winOverride-mode literal
"cycles" | "forever"is duplicated in three places instead of reusingBudgetOverrideMode.
ui/lib/types/governance.tsalready exportsBudgetOverrideMode = "cycles" | "forever", but three other sites re-declare the same literal union inline. This is harmless today since the literals match, but any future change to the mode set (e.g., adding a new mode) requires updating all four locations in lockstep, and a mismatch would only surface as a runtime/type error rather than a compile-time one at the point of divergence.
ui/lib/utils/governance.ts#L33-L56: importBudgetOverrideModeand use it forBudgetOverrideFields.override_modeandvalidateBudgetOverride'smodeparameter instead of"cycles" | "forever".ui/components/budgetOverrideDialog.tsx#L32-L32: importBudgetOverrideModefrom@/lib/types/governance(already importsBudget/BudgetOverrideRequestfrom there) and use it for themodestate type instead of"cycles" | "forever".ui/app/_fallbacks/enterprise/lib/types/accessProfile.ts#L8-L10: useBudgetOverrideModeforoverride_modeif this fallback module is allowed to depend on@/lib/types/governance; otherwise leave as-is (verify whether this_fallbacksmodule is intentionally decoupled from the mainlibtree).🤖 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/utils/governance.ts` around lines 33 - 56, Centralize all override-mode typing on the existing BudgetOverrideMode symbol. In ui/lib/utils/governance.ts:33-56, import and use BudgetOverrideMode for BudgetOverrideFields.override_mode and validateBudgetOverride’s mode parameter; in ui/components/budgetOverrideDialog.tsx:32, use the same imported type for mode state. In ui/app/_fallbacks/enterprise/lib/types/accessProfile.ts:8-10, use BudgetOverrideMode only if the fallback module may depend on the main governance types; otherwise leave that declaration unchanged.
🤖 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/virtual-keys/views/virtualKeyDetailsSheet.tsx`:
- Around line 311-327: Update the Provider Budgets override detail rendered by
the hasActiveBudgetOverride branch near UsageLine to append the same
cycles-remaining or “until removed” text used by the Budget Information section,
based on the budget’s override_mode. Reuse the existing duration calculation and
wording so both sections present identical override information.
---
Outside diff comments:
In `@ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx`:
- Around line 73-113: The duplicated exhaustion logic must be centralized and
reused. In ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx lines
73-113, destructure isExhausted from the existing useVirtualKeyUsage(virtualKey)
call and remove the local calculation. In
ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx lines 75-82, use a
shared utility from ui/lib/utils/governance.ts that checks budgets via
getEffectiveBudgetLimit and rate limits with != null guards; update
useVirtualKeyUsage.ts to call the same utility.
In `@ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx`:
- Around line 75-82: Update the isExhausted calculation in the virtual keys
table to use null-safe presence checks for token_current_usage, token_max_limit,
request_current_usage, and request_max_limit instead of truthiness checks.
Preserve the existing budget comparison and ensure zero-valued usage or limits
are still compared and can mark the key exhausted, matching
useVirtualKeyUsage.ts.
---
Nitpick comments:
In `@ui/app/_fallbacks/enterprise/lib/types/accessProfile.ts`:
- Around line 8-10: Update the access profile type’s override_mode field to
reuse the exported BudgetOverrideMode type from governance.ts instead of
redeclaring the "cycles" | "forever" union. Preserve the field’s optionality and
leave override_amount and override_cycles_remaining unchanged.
In `@ui/components/budgetOverrideDialog.tsx`:
- Around line 181-199: The Remove override button in the budget override dialog
lacks in-flight loading feedback. Update the Button controlled by handleRemove
and isSaving to use the established loading presentation, including a spinner or
loading label while isSaving, while preserving its destructive styling and
disabled behavior.
- Around line 132-143: Associate the Duration label with the mode Select by
adding a matching identifier to the Label’s htmlFor and the SelectTrigger’s id.
Update the project’s Select wrapper usage around SelectTrigger to confirm the id
reaches the underlying control; if it does not, apply the wrapper-supported
association mechanism while preserving the existing mode and disabled behavior.
In `@ui/lib/utils/governance.ts`:
- Around line 33-56: Centralize all override-mode typing on the existing
BudgetOverrideMode symbol. In ui/lib/utils/governance.ts:33-56, import and use
BudgetOverrideMode for BudgetOverrideFields.override_mode and
validateBudgetOverride’s mode parameter; in
ui/components/budgetOverrideDialog.tsx:32, use the same imported type for mode
state. In ui/app/_fallbacks/enterprise/lib/types/accessProfile.ts:8-10, use
BudgetOverrideMode only if the fallback module may depend on the main governance
types; otherwise leave that declaration unchanged.
🪄 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: 2320f252-3d28-462f-bf1d-27866852b1be
📒 Files selected for processing (14)
tests/cmd/e2eseed/go.modtests/cmd/seed/go.modtests/cmd/seedvks/go.modui/app/_fallbacks/enterprise/lib/types/accessProfile.tsui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.tsui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsxui/app/workspace/virtual-keys/views/virtualKeySheet.tsxui/app/workspace/virtual-keys/views/virtualKeysTable.tsxui/components/budgetDisplay.tsxui/components/budgetOverrideDialog.tsxui/lib/store/apis/governanceApi.tsui/lib/types/governance.tsui/lib/utils/governance.test.tsui/lib/utils/governance.ts
4657156 to
6b8024f
Compare
d2c4c2a to
d59302d
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/lib/utils/governance.ts`:
- Around line 52-54: Update validateBudgetOverride to require
Number.isSafeInteger for positive cycle counts instead of only Number.isInteger.
In the date-calculation logic covering the affected range, reject unsafe or
arithmetic-invalid cycle values and return null when the resulting expiry date
is invalid, while preserving valid-date behavior.
🪄 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: 477edb63-ed5c-43c1-a19a-e78c6edf2f2f
📒 Files selected for processing (14)
tests/cmd/e2eseed/go.modtests/cmd/seed/go.modtests/cmd/seedvks/go.modui/app/_fallbacks/enterprise/lib/types/accessProfile.tsui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.tsui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsxui/app/workspace/virtual-keys/views/virtualKeySheet.tsxui/app/workspace/virtual-keys/views/virtualKeysTable.tsxui/components/budgetDisplay.tsxui/components/budgetOverrideDialog.tsxui/lib/store/apis/governanceApi.tsui/lib/types/governance.tsui/lib/utils/governance.test.tsui/lib/utils/governance.ts
🚧 Files skipped from review as they are similar to previous changes (11)
- tests/cmd/seedvks/go.mod
- ui/lib/utils/governance.test.ts
- tests/cmd/seed/go.mod
- tests/cmd/e2eseed/go.mod
- ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts
- ui/app/_fallbacks/enterprise/lib/types/accessProfile.ts
- ui/lib/store/apis/governanceApi.ts
- ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx
- ui/components/budgetOverrideDialog.tsx
- ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx
- ui/lib/types/governance.ts
d59302d to
1504eb2
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/components/budgetOverrideDialog.tsx`:
- Around line 46-54: Update handleSubmit in BudgetOverrideDialog to validate the
form through a Zod schema defined in ui/lib/types/schemas.ts, including
meaningful field validation messages. Replace the validation-only
validateBudgetOverride flow with the schema result, map its errors into the
dialog’s setError handling, and preserve submission only when parsing succeeds.
In `@ui/lib/utils/governance.ts`:
- Around line 86-99: Update the calendar-aligned branches in the duration expiry
logic for “M” and “y”/“Y” so month-end and leap-day start dates are clamped to
the target month’s final day rather than overflowing into the following month.
Preserve the existing non-calendar calculations and use the computed target
year/month when applying the clamp.
🪄 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: d0a8cece-1154-46d3-8c2c-a55bd858486d
📒 Files selected for processing (14)
tests/cmd/e2eseed/go.modtests/cmd/seed/go.modtests/cmd/seedvks/go.modui/app/_fallbacks/enterprise/lib/types/accessProfile.tsui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.tsui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsxui/app/workspace/virtual-keys/views/virtualKeySheet.tsxui/app/workspace/virtual-keys/views/virtualKeysTable.tsxui/components/budgetDisplay.tsxui/components/budgetOverrideDialog.tsxui/lib/store/apis/governanceApi.tsui/lib/types/governance.tsui/lib/utils/governance.test.tsui/lib/utils/governance.ts
🚧 Files skipped from review as they are similar to previous changes (11)
- ui/lib/utils/governance.test.ts
- tests/cmd/seedvks/go.mod
- ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts
- tests/cmd/seed/go.mod
- tests/cmd/e2eseed/go.mod
- ui/app/_fallbacks/enterprise/lib/types/accessProfile.ts
- ui/lib/types/governance.ts
- ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx
- ui/components/budgetDisplay.tsx
- ui/app/workspace/virtual-keys/views/virtualKeySheet.tsx
- ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx
6b8024f to
bda0931
Compare
a34e661 to
65b87f1
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (2)
ui/lib/utils/governance.test.ts (2)
21-26: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAdd boundary cases for cycle validation.
Only fractional cycles are tested. Add cases for
0, negative values, and missingcycleswhenmodeis"cycles"to cover every rejection path in the schema refinement.🤖 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/utils/governance.test.ts` around lines 21 - 26, Add boundary assertions to the “validates positive amounts and whole finite cycle counts” test for validateBudgetOverride: verify that cycles mode rejects 0, negative values, and a missing cycle count. Keep the existing fractional rejection and valid cycle/forever cases unchanged.
12-19: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winCover the incomplete override branch.
This test claims to cover “incomplete or expired” state, but only exercises a complete finite override with zero remaining cycles. Add a fixture with missing override fields and verify the effective limit remains
max_limit.🤖 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/utils/governance.test.ts` around lines 12 - 19, Add an incomplete override fixture to the test case for hasActiveBudgetOverride and getEffectiveBudgetLimit, omitting required override fields while retaining max_limit. Assert that the incomplete state is inactive and getEffectiveBudgetLimit returns the original max_limit, while preserving the existing expired finite-override assertions.
🤖 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.
Nitpick comments:
In `@ui/lib/utils/governance.test.ts`:
- Around line 21-26: Add boundary assertions to the “validates positive amounts
and whole finite cycle counts” test for validateBudgetOverride: verify that
cycles mode rejects 0, negative values, and a missing cycle count. Keep the
existing fractional rejection and valid cycle/forever cases unchanged.
- Around line 12-19: Add an incomplete override fixture to the test case for
hasActiveBudgetOverride and getEffectiveBudgetLimit, omitting required override
fields while retaining max_limit. Assert that the incomplete state is inactive
and getEffectiveBudgetLimit returns the original max_limit, while preserving the
existing expired finite-override assertions.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 14d150d4-b912-4d1a-a4f0-b15de4fe6733
📒 Files selected for processing (15)
tests/cmd/e2eseed/go.modtests/cmd/seed/go.modtests/cmd/seedvks/go.modui/app/_fallbacks/enterprise/lib/types/accessProfile.tsui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.tsui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsxui/app/workspace/virtual-keys/views/virtualKeySheet.tsxui/app/workspace/virtual-keys/views/virtualKeysTable.tsxui/components/budgetDisplay.tsxui/components/budgetOverrideDialog.tsxui/lib/store/apis/governanceApi.tsui/lib/types/governance.tsui/lib/types/schemas.tsui/lib/utils/governance.test.tsui/lib/utils/governance.ts
🚧 Files skipped from review as they are similar to previous changes (12)
- tests/cmd/e2eseed/go.mod
- tests/cmd/seedvks/go.mod
- tests/cmd/seed/go.mod
- ui/app/workspace/virtual-keys/views/virtualKeySheet.tsx
- ui/app/_fallbacks/enterprise/lib/types/accessProfile.ts
- ui/components/budgetDisplay.tsx
- ui/lib/store/apis/governanceApi.ts
- ui/lib/types/governance.ts
- ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx
- ui/components/budgetOverrideDialog.tsx
- ui/app/workspace/virtual-keys/hooks/useVirtualKeyUsage.ts
- ui/app/workspace/virtual-keys/views/virtualKeyDetailsSheet.tsx
65b87f1 to
55a0b95
Compare
bda0931 to
97cb796
Compare
Merge activity
|
55a0b95 to
95f798b
Compare
97cb796 to
26e0572
Compare
The base branch was changed.
## Summary
Adds support for additive budget overrides on virtual key budgets, allowing operators to temporarily increase a virtual key's spending capacity beyond its base limit without modifying the base budget itself.
## Changes
- Added `override_amount`, `override_mode`, and `override_cycles_remaining` fields to the `Budget` type, along with `BudgetOverrideRequest` and `BudgetOverrideResponse` types.
- Introduced three utility functions in `governance.ts`: `hasActiveBudgetOverride`, `getEffectiveBudgetLimit`, and `validateBudgetOverride`. These handle override state detection, effective limit calculation, and input validation respectively.
- Replaced all direct references to `b.max_limit` in exhaustion checks, progress bars, and CSV exports with `getEffectiveBudgetLimit(b)` so overrides are reflected everywhere budgets are displayed or evaluated.
- Added `setVirtualKeyBudgetOverride` (PUT) and `removeVirtualKeyBudgetOverride` (DELETE) RTK Query mutations to `governanceApi`, targeting `/governance/virtual-keys/:vkId/budgets/:budgetId/override`.
- Created `BudgetOverrideDialog` component that lets operators add, edit, or remove an override on a single budget. The dialog supports two modes: a fixed number of reset cycles or indefinite ("until removed"). It is surfaced in the virtual key detail sheet for non-managed keys.
- The `BudgetDisplay` tooltip and inline label now show an "override" badge and a breakdown of base + override amounts when an active override is present.
- Added unit tests covering effective limit calculation, expired/incomplete override detection, and input validation.
## Type of change
- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI
## Affected areas
- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (React)
- [ ] Docs
## How to test
```sh
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```
1. Open a virtual key detail sheet for a key that is not managed by an access profile and has at least one budget with a persisted ID.
2. Click **Add override** next to a budget line.
3. Enter an additional amount, select a mode (cycles or forever), and save. Verify the usage bar and effective limit update immediately.
4. Re-open the dialog and click **Edit override** to confirm existing values are pre-populated.
5. Click **Remove override** and confirm the budget reverts to its base limit.
6. Verify that a key whose usage meets or exceeds the effective limit (base + override) is shown as exhausted.
7. Export virtual keys to CSV and confirm the Budget Limit column reflects the effective limit.
## Screenshots/Recordings
_Add before/after screenshots of the virtual key detail sheet showing the override badge, breakdown text, and dialog._
## Breaking changes
- [ ] Yes
- [x] No
## Related issues
## Security considerations
The override mutations respect the existing `RbacResource.VirtualKeys` / `RbacOperation.Update` permission check; the **Add/Edit override** button is disabled for users without that permission.
## Checklist
- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
Adds support for additive budget overrides on virtual key budgets, allowing operators to temporarily increase a virtual key's spending capacity beyond its base limit without modifying the base budget itself.
- Added `override_amount`, `override_mode`, and `override_cycles_remaining` fields to the `Budget` type, along with `BudgetOverrideRequest` and `BudgetOverrideResponse` types.
- Introduced three utility functions in `governance.ts`: `hasActiveBudgetOverride`, `getEffectiveBudgetLimit`, and `validateBudgetOverride`. These handle override state detection, effective limit calculation, and input validation respectively.
- Replaced all direct references to `b.max_limit` in exhaustion checks, progress bars, and CSV exports with `getEffectiveBudgetLimit(b)` so overrides are reflected everywhere budgets are displayed or evaluated.
- Added `setVirtualKeyBudgetOverride` (PUT) and `removeVirtualKeyBudgetOverride` (DELETE) RTK Query mutations to `governanceApi`, targeting `/governance/virtual-keys/:vkId/budgets/:budgetId/override`.
- Created `BudgetOverrideDialog` component that lets operators add, edit, or remove an override on a single budget. The dialog supports two modes: a fixed number of reset cycles or indefinite ("until removed"). It is surfaced in the virtual key detail sheet for non-managed keys.
- The `BudgetDisplay` tooltip and inline label now show an "override" badge and a breakdown of base + override amounts when an active override is present.
- Added unit tests covering effective limit calculation, expired/incomplete override detection, and input validation.
- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI
- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (React)
- [ ] Docs
```sh
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```
1. Open a virtual key detail sheet for a key that is not managed by an access profile and has at least one budget with a persisted ID.
2. Click **Add override** next to a budget line.
3. Enter an additional amount, select a mode (cycles or forever), and save. Verify the usage bar and effective limit update immediately.
4. Re-open the dialog and click **Edit override** to confirm existing values are pre-populated.
5. Click **Remove override** and confirm the budget reverts to its base limit.
6. Verify that a key whose usage meets or exceeds the effective limit (base + override) is shown as exhausted.
7. Export virtual keys to CSV and confirm the Budget Limit column reflects the effective limit.
_Add before/after screenshots of the virtual key detail sheet showing the override badge, breakdown text, and dialog._
- [ ] Yes
- [x] No
The override mutations respect the existing `RbacResource.VirtualKeys` / `RbacOperation.Update` permission check; the **Add/Edit override** button is disabled for users without that permission.
- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
Adds support for additive budget overrides on virtual key budgets, allowing operators to temporarily increase a virtual key's spending capacity beyond its base limit without modifying the base budget itself.
- Added `override_amount`, `override_mode`, and `override_cycles_remaining` fields to the `Budget` type, along with `BudgetOverrideRequest` and `BudgetOverrideResponse` types.
- Introduced three utility functions in `governance.ts`: `hasActiveBudgetOverride`, `getEffectiveBudgetLimit`, and `validateBudgetOverride`. These handle override state detection, effective limit calculation, and input validation respectively.
- Replaced all direct references to `b.max_limit` in exhaustion checks, progress bars, and CSV exports with `getEffectiveBudgetLimit(b)` so overrides are reflected everywhere budgets are displayed or evaluated.
- Added `setVirtualKeyBudgetOverride` (PUT) and `removeVirtualKeyBudgetOverride` (DELETE) RTK Query mutations to `governanceApi`, targeting `/governance/virtual-keys/:vkId/budgets/:budgetId/override`.
- Created `BudgetOverrideDialog` component that lets operators add, edit, or remove an override on a single budget. The dialog supports two modes: a fixed number of reset cycles or indefinite ("until removed"). It is surfaced in the virtual key detail sheet for non-managed keys.
- The `BudgetDisplay` tooltip and inline label now show an "override" badge and a breakdown of base + override amounts when an active override is present.
- Added unit tests covering effective limit calculation, expired/incomplete override detection, and input validation.
- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI
- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (React)
- [ ] Docs
```sh
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```
1. Open a virtual key detail sheet for a key that is not managed by an access profile and has at least one budget with a persisted ID.
2. Click **Add override** next to a budget line.
3. Enter an additional amount, select a mode (cycles or forever), and save. Verify the usage bar and effective limit update immediately.
4. Re-open the dialog and click **Edit override** to confirm existing values are pre-populated.
5. Click **Remove override** and confirm the budget reverts to its base limit.
6. Verify that a key whose usage meets or exceeds the effective limit (base + override) is shown as exhausted.
7. Export virtual keys to CSV and confirm the Budget Limit column reflects the effective limit.
_Add before/after screenshots of the virtual key detail sheet showing the override badge, breakdown text, and dialog._
- [ ] Yes
- [x] No
The override mutations respect the existing `RbacResource.VirtualKeys` / `RbacOperation.Update` permission check; the **Add/Edit override** button is disabled for users without that permission.
- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
Adds support for additive budget overrides on virtual key budgets, allowing operators to temporarily increase a virtual key's spending capacity beyond its base limit without modifying the base budget itself.
- Added `override_amount`, `override_mode`, and `override_cycles_remaining` fields to the `Budget` type, along with `BudgetOverrideRequest` and `BudgetOverrideResponse` types.
- Introduced three utility functions in `governance.ts`: `hasActiveBudgetOverride`, `getEffectiveBudgetLimit`, and `validateBudgetOverride`. These handle override state detection, effective limit calculation, and input validation respectively.
- Replaced all direct references to `b.max_limit` in exhaustion checks, progress bars, and CSV exports with `getEffectiveBudgetLimit(b)` so overrides are reflected everywhere budgets are displayed or evaluated.
- Added `setVirtualKeyBudgetOverride` (PUT) and `removeVirtualKeyBudgetOverride` (DELETE) RTK Query mutations to `governanceApi`, targeting `/governance/virtual-keys/:vkId/budgets/:budgetId/override`.
- Created `BudgetOverrideDialog` component that lets operators add, edit, or remove an override on a single budget. The dialog supports two modes: a fixed number of reset cycles or indefinite ("until removed"). It is surfaced in the virtual key detail sheet for non-managed keys.
- The `BudgetDisplay` tooltip and inline label now show an "override" badge and a breakdown of base + override amounts when an active override is present.
- Added unit tests covering effective limit calculation, expired/incomplete override detection, and input validation.
- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI
- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (React)
- [ ] Docs
```sh
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```
1. Open a virtual key detail sheet for a key that is not managed by an access profile and has at least one budget with a persisted ID.
2. Click **Add override** next to a budget line.
3. Enter an additional amount, select a mode (cycles or forever), and save. Verify the usage bar and effective limit update immediately.
4. Re-open the dialog and click **Edit override** to confirm existing values are pre-populated.
5. Click **Remove override** and confirm the budget reverts to its base limit.
6. Verify that a key whose usage meets or exceeds the effective limit (base + override) is shown as exhausted.
7. Export virtual keys to CSV and confirm the Budget Limit column reflects the effective limit.
_Add before/after screenshots of the virtual key detail sheet showing the override badge, breakdown text, and dialog._
- [ ] Yes
- [x] No
The override mutations respect the existing `RbacResource.VirtualKeys` / `RbacOperation.Update` permission check; the **Add/Edit override** button is disabled for users without that permission.
- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
Adds support for additive budget overrides on virtual key budgets, allowing operators to temporarily increase a virtual key's spending capacity beyond its base limit without modifying the base budget itself.
- Added `override_amount`, `override_mode`, and `override_cycles_remaining` fields to the `Budget` type, along with `BudgetOverrideRequest` and `BudgetOverrideResponse` types.
- Introduced three utility functions in `governance.ts`: `hasActiveBudgetOverride`, `getEffectiveBudgetLimit`, and `validateBudgetOverride`. These handle override state detection, effective limit calculation, and input validation respectively.
- Replaced all direct references to `b.max_limit` in exhaustion checks, progress bars, and CSV exports with `getEffectiveBudgetLimit(b)` so overrides are reflected everywhere budgets are displayed or evaluated.
- Added `setVirtualKeyBudgetOverride` (PUT) and `removeVirtualKeyBudgetOverride` (DELETE) RTK Query mutations to `governanceApi`, targeting `/governance/virtual-keys/:vkId/budgets/:budgetId/override`.
- Created `BudgetOverrideDialog` component that lets operators add, edit, or remove an override on a single budget. The dialog supports two modes: a fixed number of reset cycles or indefinite ("until removed"). It is surfaced in the virtual key detail sheet for non-managed keys.
- The `BudgetDisplay` tooltip and inline label now show an "override" badge and a breakdown of base + override amounts when an active override is present.
- Added unit tests covering effective limit calculation, expired/incomplete override detection, and input validation.
- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI
- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (React)
- [ ] Docs
```sh
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```
1. Open a virtual key detail sheet for a key that is not managed by an access profile and has at least one budget with a persisted ID.
2. Click **Add override** next to a budget line.
3. Enter an additional amount, select a mode (cycles or forever), and save. Verify the usage bar and effective limit update immediately.
4. Re-open the dialog and click **Edit override** to confirm existing values are pre-populated.
5. Click **Remove override** and confirm the budget reverts to its base limit.
6. Verify that a key whose usage meets or exceeds the effective limit (base + override) is shown as exhausted.
7. Export virtual keys to CSV and confirm the Budget Limit column reflects the effective limit.
_Add before/after screenshots of the virtual key detail sheet showing the override badge, breakdown text, and dialog._
- [ ] Yes
- [x] No
The override mutations respect the existing `RbacResource.VirtualKeys` / `RbacOperation.Update` permission check; the **Add/Edit override** button is disabled for users without that permission.
- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
## Summary
Adds support for additive budget overrides on virtual key budgets, allowing operators to temporarily increase a virtual key's spending capacity beyond its base limit without modifying the base budget itself.
## Changes
- Added `override_amount`, `override_mode`, and `override_cycles_remaining` fields to the `Budget` type, along with `BudgetOverrideRequest` and `BudgetOverrideResponse` types.
- Introduced three utility functions in `governance.ts`: `hasActiveBudgetOverride`, `getEffectiveBudgetLimit`, and `validateBudgetOverride`. These handle override state detection, effective limit calculation, and input validation respectively.
- Replaced all direct references to `b.max_limit` in exhaustion checks, progress bars, and CSV exports with `getEffectiveBudgetLimit(b)` so overrides are reflected everywhere budgets are displayed or evaluated.
- Added `setVirtualKeyBudgetOverride` (PUT) and `removeVirtualKeyBudgetOverride` (DELETE) RTK Query mutations to `governanceApi`, targeting `/governance/virtual-keys/:vkId/budgets/:budgetId/override`.
- Created `BudgetOverrideDialog` component that lets operators add, edit, or remove an override on a single budget. The dialog supports two modes: a fixed number of reset cycles or indefinite ("until removed"). It is surfaced in the virtual key detail sheet for non-managed keys.
- The `BudgetDisplay` tooltip and inline label now show an "override" badge and a breakdown of base + override amounts when an active override is present.
- Added unit tests covering effective limit calculation, expired/incomplete override detection, and input validation.
## Type of change
- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI
## Affected areas
- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (React)
- [ ] Docs
## How to test
```sh
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```
1. Open a virtual key detail sheet for a key that is not managed by an access profile and has at least one budget with a persisted ID.
2. Click **Add override** next to a budget line.
3. Enter an additional amount, select a mode (cycles or forever), and save. Verify the usage bar and effective limit update immediately.
4. Re-open the dialog and click **Edit override** to confirm existing values are pre-populated.
5. Click **Remove override** and confirm the budget reverts to its base limit.
6. Verify that a key whose usage meets or exceeds the effective limit (base + override) is shown as exhausted.
7. Export virtual keys to CSV and confirm the Budget Limit column reflects the effective limit.
## Screenshots/Recordings
_Add before/after screenshots of the virtual key detail sheet showing the override badge, breakdown text, and dialog._
## Breaking changes
- [ ] Yes
- [x] No
## Related issues
## Security considerations
The override mutations respect the existing `RbacResource.VirtualKeys` / `RbacOperation.Update` permission check; the **Add/Edit override** button is disabled for users without that permission.
## Checklist
- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
## Summary
Adds support for additive budget overrides on virtual key budgets, allowing operators to temporarily increase a virtual key's spending capacity beyond its base limit without modifying the base budget itself.
## Changes
- Added `override_amount`, `override_mode`, and `override_cycles_remaining` fields to the `Budget` type, along with `BudgetOverrideRequest` and `BudgetOverrideResponse` types.
- Introduced three utility functions in `governance.ts`: `hasActiveBudgetOverride`, `getEffectiveBudgetLimit`, and `validateBudgetOverride`. These handle override state detection, effective limit calculation, and input validation respectively.
- Replaced all direct references to `b.max_limit` in exhaustion checks, progress bars, and CSV exports with `getEffectiveBudgetLimit(b)` so overrides are reflected everywhere budgets are displayed or evaluated.
- Added `setVirtualKeyBudgetOverride` (PUT) and `removeVirtualKeyBudgetOverride` (DELETE) RTK Query mutations to `governanceApi`, targeting `/governance/virtual-keys/:vkId/budgets/:budgetId/override`.
- Created `BudgetOverrideDialog` component that lets operators add, edit, or remove an override on a single budget. The dialog supports two modes: a fixed number of reset cycles or indefinite ("until removed"). It is surfaced in the virtual key detail sheet for non-managed keys.
- The `BudgetDisplay` tooltip and inline label now show an "override" badge and a breakdown of base + override amounts when an active override is present.
- Added unit tests covering effective limit calculation, expired/incomplete override detection, and input validation.
## Type of change
- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI
## Affected areas
- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (React)
- [ ] Docs
## How to test
```sh
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```
1. Open a virtual key detail sheet for a key that is not managed by an access profile and has at least one budget with a persisted ID.
2. Click **Add override** next to a budget line.
3. Enter an additional amount, select a mode (cycles or forever), and save. Verify the usage bar and effective limit update immediately.
4. Re-open the dialog and click **Edit override** to confirm existing values are pre-populated.
5. Click **Remove override** and confirm the budget reverts to its base limit.
6. Verify that a key whose usage meets or exceeds the effective limit (base + override) is shown as exhausted.
7. Export virtual keys to CSV and confirm the Budget Limit column reflects the effective limit.
## Screenshots/Recordings
_Add before/after screenshots of the virtual key detail sheet showing the override badge, breakdown text, and dialog._
## Breaking changes
- [ ] Yes
- [x] No
## Related issues
## Security considerations
The override mutations respect the existing `RbacResource.VirtualKeys` / `RbacOperation.Update` permission check; the **Add/Edit override** button is disabled for users without that permission.
## Checklist
- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable

Summary
Adds support for additive budget overrides on virtual key budgets, allowing operators to temporarily increase a virtual key's spending capacity beyond its base limit without modifying the base budget itself.
Changes
override_amount,override_mode, andoverride_cycles_remainingfields to theBudgettype, along withBudgetOverrideRequestandBudgetOverrideResponsetypes.governance.ts:hasActiveBudgetOverride,getEffectiveBudgetLimit, andvalidateBudgetOverride. These handle override state detection, effective limit calculation, and input validation respectively.b.max_limitin exhaustion checks, progress bars, and CSV exports withgetEffectiveBudgetLimit(b)so overrides are reflected everywhere budgets are displayed or evaluated.setVirtualKeyBudgetOverride(PUT) andremoveVirtualKeyBudgetOverride(DELETE) RTK Query mutations togovernanceApi, targeting/governance/virtual-keys/:vkId/budgets/:budgetId/override.BudgetOverrideDialogcomponent that lets operators add, edit, or remove an override on a single budget. The dialog supports two modes: a fixed number of reset cycles or indefinite ("until removed"). It is surfaced in the virtual key detail sheet for non-managed keys.BudgetDisplaytooltip and inline label now show an "override" badge and a breakdown of base + override amounts when an active override is present.Type of change
Affected areas
How to test
Screenshots/Recordings
Add before/after screenshots of the virtual key detail sheet showing the override badge, breakdown text, and dialog.
Breaking changes
Related issues
Security considerations
The override mutations respect the existing
RbacResource.VirtualKeys/RbacOperation.Updatepermission check; the Add/Edit override button is disabled for users without that permission.Checklist
docs/contributing/README.mdand followed the guidelines