refactor: migrate governance routing from HTTPTransportPreHook to PreRequestHook - #3933
Conversation
|
|
|
Warning Review limit reached
More reviews will be available in 27 minutes and 36 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (7)
📝 WalkthroughWalkthroughMigrates governance routing/load-balancing from HTTPTransportPreHook to PreRequestHook, adds a Bifrost context key for lowercased query params, updates VK parsing/stamping and header validation, applies pre-request hooks to WebSocket upgrades, updates tests, and adjusts an indirect dependency. ChangesGovernance Routing Migration to PreRequestHook
Sequence Diagram(s)sequenceDiagram
participant Request
participant PreRequestHook
participant VirtualKeyStore
participant RoutingEngine
participant LoadBalancer
participant ModelCatalog
participant BifrostContext
Request->>PreRequestHook: incoming request
PreRequestHook->>VirtualKeyStore: load VK from context (if present)
VirtualKeyStore-->>PreRequestHook: return VK
PreRequestHook->>RoutingEngine: evaluate rules (headers + query from BifrostContext)
RoutingEngine-->>PreRequestHook: decision (provider/model/fallbacks, KeyID)
PreRequestHook->>LoadBalancer: perform weighted selection if needed
LoadBalancer->>ModelCatalog: optional model refinement
ModelCatalog-->>LoadBalancer: refined models
LoadBalancer-->>PreRequestHook: selected provider/model and fallbacks
PreRequestHook->>BifrostContext: stamp APIKeyID and MCP include-tools
PreRequestHook-->>Request: return routed request (possibly mutated model/provider)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 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 |
Confidence Score: 4/5Safe to merge with awareness that all governance routing tests are skipped and will remain so until Phase 3; any regression in weighted load balancing, routing-rule matching, or fallback generation will be invisible in CI until those tests are rewritten. The refactor is architecturally sound and the new
Important Files Changed
Reviews (13): Last reviewed commit: "feat: governance routing moved to prereq..." | Re-trigger Greptile |
aa95aa9 to
a4a44d5
Compare
8999736 to
7b50d58
Compare
7b50d58 to
0bc7c65
Compare
a4a44d5 to
3155412
Compare
0bc7c65 to
af32678
Compare
3155412 to
6e6d407
Compare
af32678 to
71ffdd3
Compare
6e6d407 to
41f9261
Compare
94645c5 to
dd5e71c
Compare
50f400c to
cd0c8b0
Compare
dd5e71c to
59a92e7
Compare
cd0c8b0 to
eedd80c
Compare
21ae88f to
4b9952a
Compare
eedd80c to
10203d1
Compare
There was a problem hiding this comment.
♻️ Duplicate comments (1)
plugins/governance/go.mod (1)
58-58:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winDuplicate
sonicrequires make the v1.15.0 change ineffective.Line 8 still has a direct require for
github.com/bytedance/sonic v1.15.1, and line 58 has an indirect require atv1.15.0. Go's module resolver will selectv1.15.1(the highest version), so this change tov1.15.0has no effect on the actual dependency resolution.If the intent is to demote
sonicto an indirect dependency (per the PR summary), remove the direct require at line 8. If the intent is to downgrade tov1.15.0, update line 8 to match or remove the conflicting indirect entry.Run the following script to confirm the effective selected version:
#!/bin/bash cd plugins/governance echo "=== All sonic require lines in go.mod ===" rg -n '^\s*github\.com/bytedance/sonic\s+v' go.mod echo "" echo "=== Effective version selected by Go module resolver ===" go list -m -f '{{.Version}}' github.com/bytedance/sonic🤖 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/go.mod` at line 58, go.mod currently has duplicate entries for the module github.com/bytedance/sonic (direct v1.15.1 and indirect v1.15.0) so the indirect change is ineffective; fix this by editing the go.mod require entries for github.com/bytedance/sonic to reflect the intended state — either remove the direct require (demote it to indirect) or change the direct require version to v1.15.0 to match the indirect entry — then run module cleanup (go mod tidy) to refresh go.sum and verify the effective selected version with the module resolver.
🤖 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.
Duplicate comments:
In `@plugins/governance/go.mod`:
- Line 58: go.mod currently has duplicate entries for the module
github.com/bytedance/sonic (direct v1.15.1 and indirect v1.15.0) so the indirect
change is ineffective; fix this by editing the go.mod require entries for
github.com/bytedance/sonic to reflect the intended state — either remove the
direct require (demote it to indirect) or change the direct require version to
v1.15.0 to match the indirect entry — then run module cleanup (go mod tidy) to
refresh go.sum and verify the effective selected version with the module
resolver.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: a914a6f4-8505-4213-aaff-d7a2306ce770
📒 Files selected for processing (7)
core/schemas/bifrost.goplugins/governance/go.modplugins/governance/httptransportprehook_test.goplugins/governance/main.goplugins/governance/utils.gotransports/bifrost-http/handlers/wsrealtime.gotransports/bifrost-http/lib/ctx.go
4b9952a to
29d2b9f
Compare
10203d1 to
26b5eaf
Compare
29d2b9f to
4b9952a
Compare
26b5eaf to
10203d1
Compare
10203d1 to
d1aa458
Compare
4b9952a to
1f4b826
Compare
Merge activity
|

Summary
Governance routing logic has been migrated from
HTTPTransportPreHookintoPreRequestHook, operating directly onBifrostRequeststructs rather than raw HTTP bodies. This eliminates the need to unmarshal/marshal JSON or multipart bodies in the transport hook, removes integration-specific path sniffing (Gemini/genai, Bedrock/bedrock), and makes routing decisions available earlier in the pipeline where provider/model fields are already normalized.Changes
HTTPTransportPreHookis now a no-op stub retained only to satisfy theHTTPTransportPlugininterface. All routing (virtual key load balancing, routing rules, MCP tool injection) flows throughPreRequestHook.loadBalanceProviderandapplyRoutingRulesnow accept*schemas.BifrostRequestinstead ofmap[string]any+*schemas.HTTPRequest, mutatingProvider,Model, andFallbacksdirectly on the request struct. Fallbacks are now typed[]schemas.Fallbackrather than[]string.governLargePayloadandgovernRealtimeQueryParamare removed. Large-payload routing is handled inPreRequestHookby readingLargePayloadMetadata.Modelfrom context and writing back the routed model. Realtime WebSocket upgrades now invokeRunPreRequestHooksexplicitly inwsrealtime.gobefore the upgrade completes, with provider/model mutations read back into local vars and mirrored to fasthttp user values.addMCPIncludeTools(which wrote an HTTP header) is replaced bycomputeMCPIncludeTools(which returns a[]string), stored viactx.SetValue(schemas.MCPContextKeyIncludeTools, ...)instead of mutating request headers.stampGovernanceCtxFromVKis extracted as a standalone helper inutils.goto copy team/customer identifiers from a virtual key onto the context, including the team's customer relationship which was previously missed.validateRequiredHeadersis moved frommain.gotoutils.go.parseVirtualKeyFromHTTPRequestis removed; virtual key resolution now readsBifrostContextKeyVirtualKeyset upstream by the transport middleware.BifrostContextKeyRequestQueryis added to the schema and populated inConvertToBifrostContextso governance CEL routing rules can evaluate query parameters. Keys are lowercased for case-insensitive lookup.github.com/bytedance/sonicis demoted from a direct dependency to an indirect dependency in the governance module since it is no longer used for body unmarshaling in this plugin.HTTPTransportPreHooktests are skipped with a note to rewrite them asPreRequestHooktests in Phase 3 of the refactor.Type of change
Affected areas
How to test
Note: several
HTTPTransportPreHooktests are currently skipped pending Phase 3 rewrites. Realtime routing can be validated end-to-end by connecting a WebSocket client to/v1/realtime?model=<model>with a virtual key that has weighted provider configs and confirming the selected provider is reflected in the upstream connection.Screenshots/Recordings
N/A
Breaking changes
loadBalanceProviderandapplyRoutingRulessignatures have changed. Any internal callers outside the governance plugin that referenced these methods directly will need to be updated to pass*schemas.BifrostRequestinstead ofmap[string]any. Fallbacks previously written as[]stringin the request body are now[]schemas.Fallbackstructs on the request object.Related issues
N/A
Security considerations
Virtual key resolution no longer parses raw
Authorization/x-api-keyheaders inside the governance plugin; it relies on the value already extracted and stored inBifrostContextKeyVirtualKeyby the transport layer. Ensure the transport middleware correctly populates this context key before governance runs.Checklist
docs/contributing/README.mdand followed the guidelinesSummary by CodeRabbit
New Features
Tests
Chores