feat: add business unit CRUD, team assignment, and governance endpoints to OpenAPI spec - #4082
Conversation
|
Caution Review failedAn error occurred during the review process. Please try again later. 📝 WalkthroughWalkthroughAdds OpenAPI management paths and schemas for Business Units (CRUD, team assignment, governance configuration) and expands the ChangesBusiness Units and Model Configs Governance API
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
587e3c5 to
e9cf297
Compare
f8a1972 to
5816c9f
Compare
e9cf297 to
b4fe5d7
Compare
5816c9f to
8c43dd1
Compare
Confidence Score: 5/5Additive OpenAPI spec changes only — no Go implementation, no runtime paths, no migrations in this diff. Safe to merge. All changes are documentation additions to the OpenAPI spec. The three findings are schema-completeness gaps that do not affect the server runtime behavior and can be iterated on independently. docs/openapi/schemas/management/governance.yaml — BusinessUnitDetailResponse and BusinessUnitGovernanceResponse schema shapes. Important Files Changed
Reviews (7): Last reviewed commit: "docs: governance/business-units apis" | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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 `@docs/openapi/openapi.json`:
- Around line 39491-39529: The paginated "Paginated list of business units"
response object is missing a required array; update the schema for the object
(the one with description "Paginated list of business units") to include a
"required": ["business_units","total","page","limit"] entry so clients can rely
on those fields, and apply the same change to other paginated responses (e.g.,
the "teams list" paginated schema) to mark their top-level pagination fields
required; optionally also add required arrays inside the business unit item
object for essential fields like "id" and "name" if those must always be
present.
- Around line 40069-40095: The path parameter name uses camelCase `{teamId}` but
must be snake_case to match the API spec and the request body; update the
OpenAPI path and parameter for the removeTeamFromBusinessUnit operation so the
path key becomes "/api/governance/business-units/{id}/teams/{team_id}" and the
corresponding parameter object (name and any references) uses "team_id" (type
string, in: path, required: true); also search within the
removeTeamFromBusinessUnit operation for any examples, $ref or schema entries
referencing "teamId" and change them to "team_id" to keep the operation
consistent.
- Around line 40952-40961: The OpenAPI spec for GET
/api/governance/model-configs currently restricts the query parameter named
"scope" to enum ["global","virtual_key"], but ModelConfig.scope
(components/schemas/ModelConfig.scope) and the handler/configstore accept "user"
as a valid value; update the "scope" query parameter definition in openapi.json
for the GET /api/governance/model-configs endpoint to include "user" in its enum
and add a description annotation indicating that "user" is Enterprise-only (or
alternatively document why it is intentionally excluded) so OpenAPI tooling
reflects actual behavior.
In `@docs/openapi/schemas/management/governance.yaml`:
- Around line 839-849: The schema for CreateBusinessUnitGovernanceRequest
currently allows an empty object even though the description requires at least
one of budget or rate_limit; update the CreateBusinessUnitGovernanceRequest
schema to enforce this by adding an anyOf (or oneOf) clause that requires either
the property "budget" or the property "rate_limit" (referencing the existing
budget and rate_limit properties), so the schema validation matches the prose.
🪄 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: ASSERTIVE
Plan: Pro
Run ID: 023206fd-22c7-450a-a964-eb3661062fa1
📒 Files selected for processing (4)
docs/openapi/openapi.jsondocs/openapi/openapi.yamldocs/openapi/paths/management/businessunits.yamldocs/openapi/schemas/management/governance.yaml
b4fe5d7 to
37fdaa7
Compare
8c43dd1 to
52ec606
Compare
ec9856a to
a054346
Compare
52ec606 to
2a46736
Compare
a054346 to
d4fe403
Compare
2a46736 to
75341fc
Compare
75341fc to
63532b5
Compare
04b4b8a to
37472e0
Compare
Merge activity
|
37472e0 to
713dd42
Compare
…ts to OpenAPI spec (#4082) ## Summary Introduces Business Units as a new Enterprise governance entity — an organizational grouping that sits above teams (one business unit to many teams) and supports its own budget and rate limit governance. Also expands model config limits with multi-budget support, scoping (global/virtual_key/user), and calendar-aligned resets, and adds a `SessionCookieAuth` security scheme for dashboard session endpoints. ## Changes - Added a full CRUD API for business units under `/api/governance/business-units`, including list (paginated, searchable), create, get, update, and delete operations. - Added team assignment endpoints (`POST /api/governance/business-units/{id}/teams` and `DELETE /api/governance/business-units/{id}/teams/{teamId}`) to associate and unassociate teams from a business unit. A team can only belong to one business unit at a time (409 on conflict). - Added governance sub-resource endpoints (`POST/PUT/DELETE /api/governance/business-units/{id}/governance`) to configure, update, and remove budget and rate limit governance on a business unit. - Replaced the single `budget` field on `ModelConfig`, `CreateModelConfigRequest`, `UpdateModelConfigRequest`, and provider governance schemas with a `budgets` array supporting multiple budget lines per model limit, each with a unique `reset_duration`. The legacy `budget` field is retained for backward compatibility. - Added `scope` (`global`, `virtual_key`, `user`) and `scope_id` fields to model config schemas to allow per-virtual-key and per-user model limits. - Added `calendar_aligned` flag to model config and provider governance schemas to enable budget resets at clean calendar boundaries. - Renamed `count` to `total_count` in `ListModelConfigsResponse` to better reflect its role in pagination. - Updated `listModelConfigs` to be paginated with `limit`, `offset`, `search`, `scope`, `provider`, and `from_memory` query parameters. - Removed `ManagementBearerAuth` requirement from the session login, session info, and OAuth callback endpoints (they are now unauthenticated or use other mechanisms). - Added `SessionCookieAuth` as an accepted security scheme on session logout and WebSocket ticket endpoints, alongside `ManagementBearerAuth`. - Updated the `/api/keys/virtual` endpoint to accept `VirtualKeyAuth`, `BearerAuth`, and `ApiKeyAuth` instead of `ManagementBearerAuth`. - Added the `SessionCookieAuth` security scheme definition (HTTPOnly `token` cookie set by the login endpoint). - Added new OpenAPI source files: `docs/openapi/paths/management/businessunits.yaml` and corresponding schemas in `docs/openapi/schemas/management/governance.yaml`. ## Type of change - [ ] Bug fix - [x] Feature - [ ] Refactor - [x] Documentation - [ ] Chore/CI ## Affected areas - [x] Core (Go) - [x] Transports (HTTP) - [ ] Providers/Integrations - [ ] Plugins - [ ] UI (React) - [x] Docs ## How to test ```sh go test ./... ``` - Create a business unit via `POST /api/governance/business-units` and verify it is returned by `GET /api/governance/business-units`. - Assign a team to the business unit and confirm a 409 is returned when attempting to assign the same team to a different business unit. - Configure governance on the business unit via `POST /api/governance/business-units/{id}/governance` and verify budget/rate limit are reflected in `GET /api/governance/business-units/{id}`. - Delete the business unit and confirm assigned teams are unassigned atomically. - Create a model config with multiple `budgets` entries and verify the legacy `budget` field still returns the first entry. - Verify that session login and OAuth callback endpoints no longer require a management bearer token. - Verify that session logout accepts both `ManagementBearerAuth` and the `token` session cookie. ## Breaking changes - [x] Yes - [ ] No `count` in `ListModelConfigsResponse` has been renamed to `total_count`. Clients reading this field will need to update accordingly. The legacy `budget` field on model config and provider governance responses is deprecated in favour of `budgets` but remains present for backward compatibility. ## Related issues ## Security considerations The session login and OAuth callback endpoints have had `ManagementBearerAuth` removed, making them publicly accessible as intended for unauthenticated flows. The new `SessionCookieAuth` scheme uses an HTTPOnly cookie, limiting XSS exposure for dashboard session authentication. ## 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 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Business Units management (CRUD), team assignment/removal, and governance (budget/rate-limit) endpoints. * Business Unit governance supports create/update/delete of budget and rate-limit associations. * **Documentation** * API docs updated for new endpoints, paginated responses, and request/response shapes. * Expanded scope options for model-configs listing to include "user" (Enterprise-only). <!-- end of auto-generated comment: release notes by coderabbit.ai -->
## ✨ Features - **OpenAI Compaction** — Added OpenAI conversation compaction support across core, framework, logging, and the API surface (#4053) - **Multi-Customer & Org Hierarchy** — Logs and usage tracking now support multiple customers, teams, and business units, including business unit CRUD, team assignment, and governance endpoints in the OpenAPI spec (#4066, #4041, #4082) - **Provider-Level Governance** — Budgets & limits are now scope-aware and can be applied at the virtual-key top level and per provider, wired from the model configs table, with UI filters for scope and providers (#3938, #3937, #3939, #3981, #3962) - **Customer Budgets** — Customers support multiple budgets and `calendar_aligned` budget windows (#3998, #3997) - **Virtual Key Attribution & Controls** — Added a `created_by` user attribution column and a `blacklisted_models` column for virtual key provider configs (#3672, #3653) - **Request Header Capture** — OTel and Maxim observability plugins capture `request_headers` by pattern, with wildcard support (e.g. `x-custom-*`); logging gained the same wildcard header capture (#4012, #3958) - **OTel Content Controls & Collectors** — New `disable_content_logging` option drops message/tool content from exported spans, plus support for multiple OTel collectors (#4064, #3894) - **xAI x_search** — Added xAI `x_search` tool support (#3976) - **URL Validation** — Added fetch URL validation with private-network configuration and link-local blocking (#3947, #3991) - **File Scheme Pricing URLs** — Pricing source URLs now accept the `file://` scheme for air-gapped and self-hosted deployments (#4045) - **Paginated Virtual Keys** — Virtual key fetching is paginated to handle deployments with very large numbers of keys (#3957) - **Client IP Resolution** — Resolve client IP from `X-Forwarded-For`/`X-Real-IP` headers - **SCIM Provisioning** — Added `attributeType`/`attributeValue` SCIM provisioning fields - **Helm/Config Schema** — Added `roles` RBAC governance config and `per_user_oauth` MCP auth to the Helm chart and config schema (#4004, #4009) - **Log Navigation UI** — Added a "View logs" menu item to customer, team, and virtual key tables, clickable links in log detail views, a customer detail sheet, and a reusable `BudgetDisplay` component (#4073, #4054, #4026, #4055) - **Faster First Paint** — Added an inline loading shell to `#root` before React mounts (#4063) - **Materialized View Alias** — Added an `alias` column to the materialized view with filter support (#4078) ## 🐞 Fixed - **Fetch URL IP Checks** — Hardened fetch URL IP checks against SSRF (#4092) - **Mantle Model Matching** — Broadened Mantle model matching to all `gpt` variants (#4091) - **Empty Thinking Blocks** — Strip thinking blocks when the signature is empty (#4079) - **OpenAI Stream Usage** — Removed usage from the `responses.created` event in the OpenAI stream (#4080) - **Prompt Cache Key** — Set the prompt cache key from the Anthropic integration (#4086) - **Upstream Failure Status** — Map upstream connection failures to 502 instead of 400 (#3929) (thanks [@chris-colinsky](https://github.com/chris-colinsky)!) - **Gemini Schema Constraints** — Accept numeric schema integer constraints for Gemini (#3994) (thanks [@yanhao98](https://github.com/yanhao98)!) - **Files Provider Param** — Accept the `?provider=` query param on `GET /v1/files` (#3971) (thanks [@alexef](https://github.com/alexef)!) - **Optional Batch Model** — Made the `model` field optional on `POST /v1/batches` (#3973) (thanks [@alexef](https://github.com/alexef)!) - **Helm Azure Config** — Added missing `azure_key_config` fields to the Helm schema (#3996) (thanks [@axelray-dev](https://github.com/axelray-dev)!) - **Text Completion Chunk Model** — Added the missing `Model` field to `TextCompletionChunkResponse` (#3970) (thanks [@kuishou68](https://github.com/kuishou68)!) - **MCP Inline stdio Env** — MCP stdio server configs accept inline environment variable assignments (#3861) (thanks [@Shushmitaaaa](https://github.com/Shushmitaaaa)!) - **Orphaned Tool Results** — Orphaned tool results in the OpenAI to Anthropic conversion flow are no longer rejected by the Anthropic API (#3919) - **Node Usage Reconciliation** — Added a monotonic `inc_number` log cursor so node usage reconciliation does not skip late async log writes (#3664) - **Bedrock Output Assessments** — Corrected the type of `outputAssessments` in Bedrock responses (#4028) - **Model Pool Pricing Reloads** — Preserve non-pricing model pool entries across pricing reloads (#3999) - **Ghost Node Reconciliation** — Replicate the VK hierarchy flow for ghost node reconciliation (#4088) - **VK Double Usage Counting** — Fixed double usage counting when creating a virtual key (#4070) - **Model Config Lifecycle** — Cascade deletes for model configs and removal of stale in-memory model configs (#4051, #4043) - **FTS Index Cap** — Reduced the FTS index `left()` cap from 800k to 250k chars to stay within the tsvector limit (#4057) - **Sync Worker Drift** — Reduced the sync worker ticker period to 5m to prevent threshold drift (#4023) - **Passthrough** — Fixed passthrough budgets, gated passthrough models per VK, model extraction for Azure passthrough, and restricted fallbacks/provider selection to the VK boundary (#3941, #3988, #3983, #3924) - **Provider Response Headers** — Strip provider response headers and add a content-type filter (#3955, #4024) - **Stream Handling** — Drain non-SSE stream readers and retry stale connections (#3956, #3967) - **Azure Claude** — Strip Azure diagnostic property for Claude models (#3925) - **Compat max_tokens** — Preserve chat `max_tokens` during param filtering (#3992) - **Raw Request Flag** — Removed the raw request flag from providers that don't support it (#4058) - **UI Fixes** — Standardized page container layout, virtual key model configs UI, and dashboard chart tooltips (#4046, #4052, #4044) ## 🔧 Maintenance - **Dependency Upgrades** — Bumped transitive `golang.org/x` dependencies (crypto, net, sys, text) for Docker Scout CVE remediation and `recharts` to 3.8.1; cascaded version bumps across all modules (#3900, #4003)

Summary
Introduces Business Units as a new Enterprise governance entity — an organizational grouping that sits above teams (one business unit to many teams) and supports its own budget and rate limit governance. Also expands model config limits with multi-budget support, scoping (global/virtual_key/user), and calendar-aligned resets, and adds a
SessionCookieAuthsecurity scheme for dashboard session endpoints.Changes
/api/governance/business-units, including list (paginated, searchable), create, get, update, and delete operations.POST /api/governance/business-units/{id}/teamsandDELETE /api/governance/business-units/{id}/teams/{teamId}) to associate and unassociate teams from a business unit. A team can only belong to one business unit at a time (409 on conflict).POST/PUT/DELETE /api/governance/business-units/{id}/governance) to configure, update, and remove budget and rate limit governance on a business unit.budgetfield onModelConfig,CreateModelConfigRequest,UpdateModelConfigRequest, and provider governance schemas with abudgetsarray supporting multiple budget lines per model limit, each with a uniquereset_duration. The legacybudgetfield is retained for backward compatibility.scope(global,virtual_key,user) andscope_idfields to model config schemas to allow per-virtual-key and per-user model limits.calendar_alignedflag to model config and provider governance schemas to enable budget resets at clean calendar boundaries.counttototal_countinListModelConfigsResponseto better reflect its role in pagination.listModelConfigsto be paginated withlimit,offset,search,scope,provider, andfrom_memoryquery parameters.ManagementBearerAuthrequirement from the session login, session info, and OAuth callback endpoints (they are now unauthenticated or use other mechanisms).SessionCookieAuthas an accepted security scheme on session logout and WebSocket ticket endpoints, alongsideManagementBearerAuth./api/keys/virtualendpoint to acceptVirtualKeyAuth,BearerAuth, andApiKeyAuthinstead ofManagementBearerAuth.SessionCookieAuthsecurity scheme definition (HTTPOnlytokencookie set by the login endpoint).docs/openapi/paths/management/businessunits.yamland corresponding schemas indocs/openapi/schemas/management/governance.yaml.Type of change
Affected areas
How to test
go test ./...POST /api/governance/business-unitsand verify it is returned byGET /api/governance/business-units.POST /api/governance/business-units/{id}/governanceand verify budget/rate limit are reflected inGET /api/governance/business-units/{id}.budgetsentries and verify the legacybudgetfield still returns the first entry.ManagementBearerAuthand thetokensession cookie.Breaking changes
countinListModelConfigsResponsehas been renamed tototal_count. Clients reading this field will need to update accordingly. The legacybudgetfield on model config and provider governance responses is deprecated in favour ofbudgetsbut remains present for backward compatibility.Related issues
Security considerations
The session login and OAuth callback endpoints have had
ManagementBearerAuthremoved, making them publicly accessible as intended for unauthenticated flows. The newSessionCookieAuthscheme uses an HTTPOnly cookie, limiting XSS exposure for dashboard session authentication.Checklist
docs/contributing/README.mdand followed the guidelinesSummary by CodeRabbit
New Features
Documentation