Skip to content

restrict fallbacks and provider selection to vk boundry - #3924

Merged
akshaydeo merged 2 commits into
devfrom
05-31-restrict_fallbacks_and_provider_selection_to_vk_boundry
Jun 2, 2026
Merged

restrict fallbacks and provider selection to vk boundry#3924
akshaydeo merged 2 commits into
devfrom
05-31-restrict_fallbacks_and_provider_selection_to_vk_boundry

Conversation

@akshaydeo

@akshaydeo akshaydeo commented May 31, 2026

Copy link
Copy Markdown
Contributor

Summary

When a virtual key has provider constraints (but no weights), the governance plugin now propagates the list of allowed providers into the Bifrost context. The router then intersects that list with the model catalog's provider list, ensuring that only providers permitted by the virtual key are considered for routing and fallbacks.

Changes

  • The governance plugin sets BifrostContextKeyAvailableProviders on the context after filtering provider configs, including setting an empty slice when no provider configs exist or when no providers pass the model filter.
  • The router's createHandler intersects the catalog-derived provider list with any pre-existing BifrostContextKeyAvailableProviders value set by upstream plugins (e.g., governance). If the intersection is empty, an empty provider list is stored rather than falling back to the full catalog set.
  • extractAndParseFallbacks now accepts a BifrostContext and filters parsed fallbacks to only those whose provider appears in BifrostContextKeyAvailableProviders. If all fallbacks are filtered out, the fallback list on the request is explicitly cleared to nil.

Type of change

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

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins

How to test

go test ./plugins/governance/...
go test ./transports/bifrost-http/integrations/...
  • A virtual key with openai/gpt-4o and anthropic/claude-3-5-sonnet provider configs (no weights) and a request for gpt-4o should result in BifrostContextKeyAvailableProviders containing only openai.
  • A virtual key with only openai/gpt-4o and a request for claude-3-5-sonnet should result in an empty BifrostContextKeyAvailableProviders.
  • A request with fallbacks that include providers not in the allowed list should have those fallbacks stripped before the request is dispatched.

Breaking changes

  • Yes
  • No

Related issues

Closes #2516

Security considerations

Provider constraints enforced by virtual keys are now respected end-to-end through routing and fallback resolution, preventing requests from being routed to providers that the virtual key does not permit.

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

Summary by CodeRabbit

Release Notes

  • Tests

    • Added comprehensive test coverage for governance HTTP transport pre-hook with provider-constrained virtual keys.
    • Added router tests verifying proper provider constraint enforcement during request handling.
  • Bug Fixes

    • Router now correctly respects provider availability constraints when selecting providers for requests.
    • Fallback extraction now filters to only providers permitted by governance constraints.

@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

coderabbitai Bot commented May 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0033cb91-5777-4e82-91f5-e81d5eba2aef

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR threads provider availability constraints through the request handling pipeline. The governance plugin now sets allowed providers from virtual key constraints into the Bifrost context, the router respects this constraint when selecting catalog providers, and fallback extraction filters fallbacks accordingly.

Changes

Provider Availability Constraint Through Request Pipeline

Layer / File(s) Summary
Governance provider constraint initialization
plugins/governance/main.go, plugins/governance/httptransportprehook_test.go
loadBalanceProvider now sets BifrostContextKeyAvailableProviders from virtual key provider configs; tests verify the context is populated when model matches allowed providers and left empty when no provider allows the model.
Router provider selection respects governance constraints
transports/bifrost-http/integrations/router.go, transports/bifrost-http/integrations/router_test.go
Router model-catalog logic now reads pre-existing BifrostContextKeyAvailableProviders and intersects catalog results with that constraint; propagates the constrained list back to context; call to extractAndParseFallbacks now passes the bifrost context.
Fallback extraction filters by available providers
transports/bifrost-http/integrations/utils.go, transports/bifrost-http/integrations/utils_test.go
extractAndParseFallbacks now accepts BifrostContext parameter and filters parsed fallback providers to only those in AvailableProviders; tests verify filtering behavior and that invalid fallbacks are cleared.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • danpiths

Poem

🐰 A governance key sets providers free,
Router selects what's meant to be,
Fallbacks constrain with context tight,
Three layers thread the flow just right!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning Linked issue #123 requires Files API support for providers (OpenAI, Anthropic) for uploading files. The PR changes focus on restricting provider selection and fallbacks to virtual key boundaries, which is unrelated to File API implementation. The PR does not address Files API requirements from issue #123. Either the PR should implement file upload endpoints, or the issue link should be corrected to match the actual objective (restricting provider selection to virtual key boundaries).
Docstring Coverage ⚠️ Warning Docstring coverage is 10.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title references 'vk boundry' (virtual key boundary) and mentions restricting fallbacks and provider selection, which directly aligns with the core changes of enforcing virtual key provider constraints throughout the system.
Description check ✅ Passed The PR description covers Summary, Changes, Type of change, Affected areas, How to test, Breaking changes, and Related issues sections from the template. Most key details are present, though documentation updates are marked incomplete.
Out of Scope Changes check ✅ Passed All code changes (governance plugin updates, router provider filtering, fallback filtering, and tests) are cohesively scoped to enforcing virtual key provider constraints end-to-end, with no extraneous modifications detected.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 05-31-restrict_fallbacks_and_provider_selection_to_vk_boundry

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

@akshaydeo
akshaydeo marked this pull request as ready for review May 31, 2026 15:22
@greptile-apps

greptile-apps Bot commented May 31, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 3/5

The core constraint propagation mechanism works correctly in the happy path, but two previously-flagged structural gaps mean the VK provider boundary is not reliably enforced for fallbacks: the router narrows the allowed-provider list to the route's native provider before the fallback filter reads it, and governance's early-return for provider-prefixed models skips populating the context key entirely.

Both flagged gaps produce silent mis-enforcement: a VK explicitly permitting multiple providers will still drop valid cross-provider fallbacks after the router's single-provider narrowing step, and any request using a slash-prefixed primary model bypasses constraint propagation to the fallback stage completely. These are real, reproducible behavioral defects on the changed code paths rather than theoretical risks.

transports/bifrost-http/integrations/router.go (lines 815–828, where the context key is overwritten to a single-element list before fallback extraction) and plugins/governance/main.go (lines 740–751, the early return for provider-prefixed models that skips setting the context key).

Important Files Changed

Filename Overview
plugins/governance/main.go Sets BifrostContextKeyAvailableProviders in two new places; the early-return path for provider-prefixed models still exits without setting the key, leaving fallback filtering inactive for that code path (previously flagged).
transports/bifrost-http/integrations/router.go Intersection logic is correct, but the key is overwritten to a single-element list (the route's native provider) before extractAndParseFallbacks runs, making the fallback filter too narrow (previously flagged).
transports/bifrost-http/integrations/utils.go extractAndParseFallbacks correctly filters by available providers and now calls SetFallbacks(nil) to clear pre-existing fallbacks when all candidates are denied; GetProvidersForModel returns a fresh slice so slices.DeleteFunc is safe.
plugins/governance/httptransportprehook_test.go Two new test cases cover the model-filtered single-provider and no-match-provider scenarios; test setup is correct — weight=nil configs exercise the constraint-only path.
transports/bifrost-http/integrations/router_test.go New tests correctly simulate governance-set context values via fasthttp SetUserValue (copied to bifrostCtx by ConvertToBifrostContext) and verify the catalog–VK intersection; assertions are accurate.
transports/bifrost-http/integrations/utils_test.go New tests cover provider filtering and SetFallbacks(nil) clearing pre-parsed fallbacks; SetFallbacks correctly handles the nil case via the non-nil sub-request switch in core/schemas/bifrost.go.

Reviews (7): Last reviewed commit: "restrict fallbacks and provider selectio..." | Re-trigger Greptile

Comment thread transports/bifrost-http/integrations/router.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (1)
plugins/governance/main.go (1)

739-761: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Preserve VK provider constraints on prefixed-model requests before early return.

Line 740-Line 751 can return before Line 758/Line 827 are reached. That skips BifrostContextKeyAvailableProviders propagation for provider-prefixed models, so downstream routing/fallback filtering may miss VK boundaries on this path.

🔧 Suggested direction
-	// Check if model already has provider prefix (contains "/")
-	if strings.Contains(modelStr, "/") {
-		provider, _ := schemas.ParseModelString(modelStr, "")
-		// Checking valid provider when store is available; if store is nil,
-		// assume the prefixed model should be left unchanged.
-		if p.inMemoryStore != nil {
-			if _, ok := p.inMemoryStore.GetConfiguredProviders()[provider]; ok {
-				return body, nil
-			}
-		} else {
-			return body, nil
-		}
-	}
+	// Keep track of provider-pinned input, but still compute/set available providers first
+	alreadyPinnedProvider := false
+	if strings.Contains(modelStr, "/") {
+		provider, _ := schemas.ParseModelString(modelStr, "")
+		if p.inMemoryStore == nil {
+			alreadyPinnedProvider = true
+		} else if _, ok := p.inMemoryStore.GetConfiguredProviders()[provider]; ok {
+			alreadyPinnedProvider = true
+		}
+	}
@@
 	ctx.SetValue(schemas.BifrostContextKeyAvailableProviders, allowedModelProviders)
@@
+	// Model already pinned by caller: keep model unchanged, but constraints are now propagated.
+	if alreadyPinnedProvider {
+		return body, nil
+	}

As per coding guidelines, virtual_keys[].provider_configs: empty array = no providers allowed (deny-by-default) and the effective result should behave like no allowed providers.

🤖 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 `@plugins/governance/main.go` around lines 739 - 761, The early return for
prefixed models in the code that checks modelStr (the block using
strings.Contains(modelStr), schemas.ParseModelString, and p.inMemoryStore) skips
setting the per-virtual-key available providers context (ctx.SetValue with
schemas.BifrostContextKeyAvailableProviders) and its warning log, which breaks
VK provider constraints for prefixed requests; fix by, before any return in that
prefixed-model branch, computing and setting the available providers from
virtualKey.ProviderConfigs (if len(virtualKey.ProviderConfigs)==0 set an empty
[]schemas.ModelProvider and append the warn log via ctx.AppendRoutingEngineLog),
then return body,nil as before so downstream routing/fallback sees the VK
constraints.
🤖 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.

Outside diff comments:
In `@plugins/governance/main.go`:
- Around line 739-761: The early return for prefixed models in the code that
checks modelStr (the block using strings.Contains(modelStr),
schemas.ParseModelString, and p.inMemoryStore) skips setting the per-virtual-key
available providers context (ctx.SetValue with
schemas.BifrostContextKeyAvailableProviders) and its warning log, which breaks
VK provider constraints for prefixed requests; fix by, before any return in that
prefixed-model branch, computing and setting the available providers from
virtualKey.ProviderConfigs (if len(virtualKey.ProviderConfigs)==0 set an empty
[]schemas.ModelProvider and append the warn log via ctx.AppendRoutingEngineLog),
then return body,nil as before so downstream routing/fallback sees the VK
constraints.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: aa0fa3b8-75d8-478b-b9bd-c3748f0c8dce

📥 Commits

Reviewing files that changed from the base of the PR and between d4c96b8 and ee05752.

📒 Files selected for processing (6)
  • plugins/governance/httptransportprehook_test.go
  • plugins/governance/main.go
  • transports/bifrost-http/integrations/router.go
  • transports/bifrost-http/integrations/router_test.go
  • transports/bifrost-http/integrations/utils.go
  • transports/bifrost-http/integrations/utils_test.go

Comment thread plugins/governance/main.go
@akshaydeo akshaydeo reopened this May 31, 2026
@akshaydeo
akshaydeo changed the base branch from dev to graphite-base/3924 May 31, 2026 18:10
@akshaydeo
akshaydeo force-pushed the 05-31-restrict_fallbacks_and_provider_selection_to_vk_boundry branch from ee05752 to 98a3454 Compare May 31, 2026 18:10
@akshaydeo
akshaydeo changed the base branch from graphite-base/3924 to 05-31-azure_dignotstic_property_strip_for_claude_models May 31, 2026 18:10
@akshaydeo
akshaydeo force-pushed the 05-31-azure_dignotstic_property_strip_for_claude_models branch from 10db96d to 4d3097e Compare June 1, 2026 17:47
@akshaydeo
akshaydeo force-pushed the 05-31-restrict_fallbacks_and_provider_selection_to_vk_boundry branch from 98a3454 to 3f3b757 Compare June 1, 2026 17:47
@akshaydeo akshaydeo mentioned this pull request Jun 1, 2026
17 tasks
@akshaydeo
akshaydeo force-pushed the 05-31-restrict_fallbacks_and_provider_selection_to_vk_boundry branch from 3f3b757 to fe395bf Compare June 2, 2026 06:59
@akshaydeo
akshaydeo force-pushed the 05-31-azure_dignotstic_property_strip_for_claude_models branch from 4d3097e to 6f2eeb0 Compare June 2, 2026 06:59
@akshaydeo akshaydeo mentioned this pull request Jun 2, 2026
18 tasks
@akshaydeo
akshaydeo force-pushed the 05-31-azure_dignotstic_property_strip_for_claude_models branch from 6f2eeb0 to 3fec8de Compare June 2, 2026 08:36
@akshaydeo
akshaydeo force-pushed the 05-31-restrict_fallbacks_and_provider_selection_to_vk_boundry branch from fe395bf to 1e39cba Compare June 2, 2026 08:36

akshaydeo commented Jun 2, 2026

Copy link
Copy Markdown
Contributor Author

Merge activity

  • Jun 2, 8:41 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jun 2, 8:42 AM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo
akshaydeo changed the base branch from 05-31-azure_dignotstic_property_strip_for_claude_models to graphite-base/3924 June 2, 2026 08:41
@akshaydeo
akshaydeo changed the base branch from graphite-base/3924 to dev June 2, 2026 08:42
@akshaydeo
akshaydeo merged commit 23323b4 into dev Jun 2, 2026
9 of 10 checks passed
@akshaydeo
akshaydeo deleted the 05-31-restrict_fallbacks_and_provider_selection_to_vk_boundry branch June 2, 2026 08:42
akshaydeo added a commit that referenced this pull request Jun 2, 2026
## Summary

When a virtual key has provider constraints (but no weights), the governance plugin now propagates the list of allowed providers into the Bifrost context. The router then intersects that list with the model catalog's provider list, ensuring that only providers permitted by the virtual key are considered for routing and fallbacks.

## Changes

- The governance plugin sets `BifrostContextKeyAvailableProviders` on the context after filtering provider configs, including setting an empty slice when no provider configs exist or when no providers pass the model filter.
- The router's `createHandler` intersects the catalog-derived provider list with any pre-existing `BifrostContextKeyAvailableProviders` value set by upstream plugins (e.g., governance). If the intersection is empty, an empty provider list is stored rather than falling back to the full catalog set.
- `extractAndParseFallbacks` now accepts a `BifrostContext` and filters parsed fallbacks to only those whose provider appears in `BifrostContextKeyAvailableProviders`. If all fallbacks are filtered out, the fallback list on the request is explicitly cleared to `nil`.

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [x] Transports (HTTP)
- [ ] Providers/Integrations
- [x] Plugins

## How to test

```sh
go test ./plugins/governance/...
go test ./transports/bifrost-http/integrations/...
```

- A virtual key with `openai/gpt-4o` and `anthropic/claude-3-5-sonnet` provider configs (no weights) and a request for `gpt-4o` should result in `BifrostContextKeyAvailableProviders` containing only `openai`.
- A virtual key with only `openai/gpt-4o` and a request for `claude-3-5-sonnet` should result in an empty `BifrostContextKeyAvailableProviders`.
- A request with fallbacks that include providers not in the allowed list should have those fallbacks stripped before the request is dispatched.

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

Closes #2516

## Security considerations

Provider constraints enforced by virtual keys are now respected end-to-end through routing and fallback resolution, preventing requests from being routed to providers that the virtual key does not permit.

## 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

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

## Release Notes

* **Tests**
  * Added comprehensive test coverage for governance HTTP transport pre-hook with provider-constrained virtual keys.
  * Added router tests verifying proper provider constraint enforcement during request handling.

* **Bug Fixes**
  * Router now correctly respects provider availability constraints when selecting providers for requests.
  * Fallback extraction now filters to only providers permitted by governance constraints.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
akshaydeo added a commit that referenced this pull request Jun 4, 2026
## Summary

When a virtual key has provider constraints (but no weights), the governance plugin now propagates the list of allowed providers into the Bifrost context. The router then intersects that list with the model catalog's provider list, ensuring that only providers permitted by the virtual key are considered for routing and fallbacks.

## Changes

- The governance plugin sets `BifrostContextKeyAvailableProviders` on the context after filtering provider configs, including setting an empty slice when no provider configs exist or when no providers pass the model filter.
- The router's `createHandler` intersects the catalog-derived provider list with any pre-existing `BifrostContextKeyAvailableProviders` value set by upstream plugins (e.g., governance). If the intersection is empty, an empty provider list is stored rather than falling back to the full catalog set.
- `extractAndParseFallbacks` now accepts a `BifrostContext` and filters parsed fallbacks to only those whose provider appears in `BifrostContextKeyAvailableProviders`. If all fallbacks are filtered out, the fallback list on the request is explicitly cleared to `nil`.

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [x] Transports (HTTP)
- [ ] Providers/Integrations
- [x] Plugins

## How to test

```sh
go test ./plugins/governance/...
go test ./transports/bifrost-http/integrations/...
```

- A virtual key with `openai/gpt-4o` and `anthropic/claude-3-5-sonnet` provider configs (no weights) and a request for `gpt-4o` should result in `BifrostContextKeyAvailableProviders` containing only `openai`.
- A virtual key with only `openai/gpt-4o` and a request for `claude-3-5-sonnet` should result in an empty `BifrostContextKeyAvailableProviders`.
- A request with fallbacks that include providers not in the allowed list should have those fallbacks stripped before the request is dispatched.

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

Closes #2516

## Security considerations

Provider constraints enforced by virtual keys are now respected end-to-end through routing and fallback resolution, preventing requests from being routed to providers that the virtual key does not permit.

## 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

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

## Release Notes

* **Tests**
  * Added comprehensive test coverage for governance HTTP transport pre-hook with provider-constrained virtual keys.
  * Added router tests verifying proper provider constraint enforcement during request handling.

* **Bug Fixes**
  * Router now correctly respects provider availability constraints when selecting providers for requests.
  * Fallback extraction now filters to only providers permitted by governance constraints.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@akshaydeo akshaydeo mentioned this pull request Jun 7, 2026
akshaydeo added a commit that referenced this pull request Jun 7, 2026
## Summary

When a virtual key has provider constraints (but no weights), the governance plugin now propagates the list of allowed providers into the Bifrost context. The router then intersects that list with the model catalog's provider list, ensuring that only providers permitted by the virtual key are considered for routing and fallbacks.

## Changes

- The governance plugin sets `BifrostContextKeyAvailableProviders` on the context after filtering provider configs, including setting an empty slice when no provider configs exist or when no providers pass the model filter.
- The router's `createHandler` intersects the catalog-derived provider list with any pre-existing `BifrostContextKeyAvailableProviders` value set by upstream plugins (e.g., governance). If the intersection is empty, an empty provider list is stored rather than falling back to the full catalog set.
- `extractAndParseFallbacks` now accepts a `BifrostContext` and filters parsed fallbacks to only those whose provider appears in `BifrostContextKeyAvailableProviders`. If all fallbacks are filtered out, the fallback list on the request is explicitly cleared to `nil`.

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [x] Transports (HTTP)
- [ ] Providers/Integrations
- [x] Plugins

## How to test

```sh
go test ./plugins/governance/...
go test ./transports/bifrost-http/integrations/...
```

- A virtual key with `openai/gpt-4o` and `anthropic/claude-3-5-sonnet` provider configs (no weights) and a request for `gpt-4o` should result in `BifrostContextKeyAvailableProviders` containing only `openai`.
- A virtual key with only `openai/gpt-4o` and a request for `claude-3-5-sonnet` should result in an empty `BifrostContextKeyAvailableProviders`.
- A request with fallbacks that include providers not in the allowed list should have those fallbacks stripped before the request is dispatched.

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

Closes #2516

## Security considerations

Provider constraints enforced by virtual keys are now respected end-to-end through routing and fallback resolution, preventing requests from being routed to providers that the virtual key does not permit.

## 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

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

## Release Notes

* **Tests**
  * Added comprehensive test coverage for governance HTTP transport pre-hook with provider-constrained virtual keys.
  * Added router tests verifying proper provider constraint enforcement during request handling.

* **Bug Fixes**
  * Router now correctly respects provider availability constraints when selecting providers for requests.
  * Fallback extraction now filters to only providers permitted by governance constraints.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
akshaydeo added a commit that referenced this pull request Jun 7, 2026
## ✨ 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)
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.

/genai loses routing-rule target before governance load balancing in v1.5.0-prerelease1

2 participants