v2.2.0
Changelog
v2.2.0 moves the enterprise gateway onto OSS transports v2.2.0. Guardrails now inspect and redact tool call names and arguments across every provider, so a model can no longer smuggle secrets or destructive commands past a policy inside a tool invocation. MCP gets an endpoint inspection path: Edge submits tool arguments to the gateway before execution and the result after it, and MCP tool logs record governance names at ingestion instead of resolving them on read. Access profiles and projects acceptregex: model entries and reference Virtual MCPs by name, and prompt repository writes now replicate across cluster nodes.✨ Features
- Singulr AI Guardrail Provider - New
singulr-aiguardrail provider that sends normalized conversations to Singulr’s AI gateway endpoint and mapsallow,blockandredactdecisions back to Bifrost. Redaction spans arrive as Unicode code-point offsets and are converted to UTF-8 byte offsets before findings are produced, and a redact action aimed at a tool-call-only message fails closed. The enterprise UI adds a full configuration view with verify-before-enable, so the provider cannot be switched on until its API key, application ID and guardrail ID are validated. Docs - Tool Call Scanning Across All Guardrail Providers - Guardrail providers now scan LLM tool call names and arguments, not just conversational text. Structured providers receive the tool call directly; text-only providers (Azure, Bedrock, Model Armor, Patronus, Presidio, Prompt Guardrail, Repello) receive a stable canonical JSON envelope. Regex and secrets providers apply block and detect rules straight against raw tool names and arguments, and MCP arguments already serialized into the text lane are not double-counted. Docs
- Tool Call Argument Redaction - PII, secrets and regex redaction now covers tool call arguments in both request history and streaming output. Azure PII, Presidio, Secrets and Regex providers report argument findings on a separate lane so offsets stay anchored to the original argument document, and a request that declares or carries tools is promoted to full-hold streaming so partial argument JSON never escapes before evaluation. Chat and Responses streams are replayed atomically with redacted values, and an incomplete or mismatched fragment stream fails closed. Docs
- Provider-Managed Argument Rewrites for Bedrock and Model Armor - Bedrock and Model Armor can now rewrite tool call arguments during deidentification transforms, landing the sanitized value in the correct native JSON field. Transforms are validated before they are applied: a provider output that changes a tool’s ID, name or type is rejected, and a raw payload that uses native object arguments (such as an Anthropic
tool_useinput object) is passed through unchanged with a warning rather than failing the request. The Bedrock guardrail output scope moves toFULLso every submitted row has a positionally aligned output row. Docs - Attachment Screening Capabilities and Unscreened Accounting - Images and files are unified into a single
GuardrailAttachmentcarrying bytes, a normalized MIME type and a kind, and providers declare exactly which MIME types they screen and under which policy classes. The engine counts attachments that no executing provider will evaluate, records the count on the guardrail span asgen_ai.guardrail.attachments_skippedand logs a warning, so an unscreened attachment no longer reads as a clean pass. Model Armor enforces a 4 MB client-side ceiling and gates image screening on theusandeulocations, and a newjudge_supports_attachmentsflag lets operators assert that a prompt guardrail judge model can actually read images and PDFs. Docs teamsCEL Variable for Multi-Team Rules - Guardrail CEL evaluation gains ateamslist variable holding every team the authenticated user belongs to, not just the credential’s primary team. Team rules in the query builder compile toteams-based expressions ("value" in teams,teams.exists(...),teams.size() == 0), the operator list is restricted to membership operators, and the legacy scalarteamvariable is preserved for hand-written expressions. Docs- Regex Model Entries on Access Profiles and Projects - Access profile and project model lists accept
regex:<pattern>entries alongside exact names, matching the OSS virtual key and provider key behaviour. Prefixed entries are validated at create and update time so a pattern that does not compile is refused with a 400 naming the field, while rows that mix*with explicit names keep working. The grant details view and the project provider access tab render patterns through the shared model access badges and grant details gains a Blocked Models row. Docs - Virtual MCP References by Name - Access profiles and projects can reference a Virtual MCP with
virtual_mcp_nameinstead of an opaque ID, soconfig.jsonand API payloads stay portable across environments. The name is resolved to an ID before the record is hashed or written, so switching a declaration from ID to name produces the same hash and does not trigger a re-sync; an ID present alongside a name wins, and an unknown name is refused with a 400. Retiredmcp_tool_groups,mcp_serversandmcp_tool_overrideskeys are folded intovirtual_mcpsandmcp_configsat load time with a deprecation warning. Docs - Governance Names Stamped on MCP Tool Logs at Ingestion - MCP tool logs now record user, team, customer and business unit names when the call is made, so nothing is resolved per read and a later rename cannot change what an old log says. The MCP hooks settle the same identity the LLM hooks do, including virtual key name and the customer a team-attached key reaches, and all three write paths (gateway calls, Edge inspection, passive agent ingest) go through one function. Data access control is preserved: a row carrying a customer from an org the caller cannot see has both the ID and the name removed. Rows written before the columns existed fall back to the governance cache on single-row reads.
- Endpoint MCP Inspection - MCP tool calls made by Edge-managed clients are inspected by the gateway through a two-phase HTTP exchange that mirrors LLM inspection: the agent submits tool arguments before execution, receives approved parameters and an opaque session ID, then submits the result or error for post-hook processing before releasing it to the client. The canonical MCP plugin context is preserved in bounded, expiring server-side sessions; both phases verify identity and installation ownership, response submissions are consumed once, and policy or transport failures fail closed. Because sessions are node-local, clustered deployments require session affinity.
- MCP Registration Metadata and Inspection Logs - Device inventory carries MCP registration occurrences with source, enablement, package, server and protocol versions, and removal state, and the enterprise gateway builds the completed MCP inspection log itself with device, app, server, decision, final output, governance identity and plugin logs attached. Inspection uses the same plugin exclusions as LLM inspection so the entry is queued exactly once, and the server fails closed before execution when the logging plugin does not expose the enqueue helper.
- Edge Approval Gates on MCP Connections - Starting an upstream MCP process or initializing a remote connection now requires explicit Edge approval, so opening a client can no longer initialize a pending remote server and launch its OAuth browser before inspection runs. Pending servers stay inventory-only, and pending, denied or unknown targets stop startup before OAuth or tool discovery. When the fleet setting “Allow pending apps and MCP servers” is on, pending servers are admitted to the connection allowlist while explicit global, user and team denials stay blocked.
- Native Tool Call Reporting - A fleet-controlled setting records shell commands, file reads and other native tool executions from coding apps as they pass through the gateway, with no hooks installed and no client behaviour changed. The gateway validates ingested events against an app allowlist, payload size, status enum and latency bounds, re-checks the fleet flag server-side, and maps observations onto MCP tool log entries with MCP enforcement fields cleared. MCP log reads resolve user, team, customer and business unit display names from the live governance cache within the caller’s data access scope.
- Fleet Provider Login Controls - Edge Settings gains three independent toggles: Require Anthropic login, Require ChatGPT login and Enable login-free Claude Desktop. The first two switch Claude Code and Codex to native-login rendering so users authenticate with their own accounts while gateway routing and the governed model picker stay in place; the third provisions Claude Desktop through OS-level managed policy so it runs through Edge without an Anthropic account. All three fields are carried through the config store, the edge config API and agent sync. Docs
- Gemini CLI as a Governed Edge Application -
gemini-cliis added to the Edge application list and agent settings, so Gemini CLI can be enabled, disabled and governed from Edge Settings the same way Claude Code, Codex and OpenCode are. Docs - Prompt Repository Writes Replicated Across Cluster Nodes - Publishing a prompt version on one node now reloads the prompts plugin index on every node. Previously only the node that served the write rebuilt its in-memory index, so an inference request carrying
x-bf-prompt-id/x-bf-prompt-versionthat load-balanced to another node errored on an unknown version, or served stale content forlatest, until that node restarted. A local reload that fails does not broadcast, so peers are never told to reload a change this node could not apply. Docs - Environment References in Cluster Configuration - Cluster configuration string fields move to
SecretVar, so discovery endpoints, credentials and related settings can be declared asenv.VARreferences inconfig.jsoninstead of literals. This resolves environment variables and plain strings; vault references are not wired through this path because vault resolution today runs on GORM hooks. Docs - Trusted Networks Synced from config.json - The
trusted_networkslist declared inconfig.jsonis reconciled into the stored allowlist and included in the provider hash, so a declared change is detected and applied. An explicitly empty list clears dashboard-added entries and is treated as distinct from the key being absent, which leaves the stored allowlist untouched. - Retry Queue for Cluster Broadcast Messages - Each peer connection owns a push queue and a background worker, so a delivery that fails because the peer has no active stream, a busy send mutex or a transport error is retried instead of silently dropped. Broadcast ordering is preserved across concurrent callers, a chunked message that fails mid-sequence restarts from the first chunk, and the queue caps both pending message count and retained bytes. This reduces how often a brief network interruption forces an expensive full governance sync. Docs
- Normalized Error Type in Connector Metrics - The BigQuery, Datadog and Splunk connectors resolve an error’s type from the normalized
bifrost.error.typeattribute first, then the rawgen_ai.error.type, thengen_ai.error.code, thenunknown. Equivalent failures now group consistently across providers in dashboards and alerts without per-provider logic. Docs - System Role Access Profile Assignment - Access profile assignment is no longer skipped for the system role, so system-role users receive their configured profile like every other role.
🌎 Open Source Features
- Claude Desktop and Cowork Marketplace - Skills stored in Bifrost can be registered as a marketplace in Claude Desktop and Cowork, which reject a direct JSON URL and require a cloneable Git repository URL. A new
/api/skills/serve/claude-code.gitendpoint implements the two Git smart-HTTP requests used during a clone and serves a repository containing.claude-plugin/marketplace.json; the existing Claude Code flow is unchanged. - Time-of-Day Peak and Off-Peak Pricing - Model pricing accepts
off_peak_cost_multiplierand apeak_hoursweekly schedule, so a provider that bills the same model at two rates is costed correctly. Base rates are treated as peak and the multiplier scales usage-based charges outside the declared windows, while flat per-request fees, per-search-query fees and guardrail or MCP additional cost are never discounted. Windows use IANA timezones, weekday numbers and half-openHH:MMintervals that may wrap past midnight, and both fields are editable from the custom pricing override sheet. - GA Realtime Transcription - OpenAI and Azure GA transcription sessions are served over both WebSocket and WebRTC with normal Bifrost authentication, routing, governance, guardrails, logging and transcription-aware pricing. These sessions carry only
intent=transcriptionon the connection and deliver the routing model later insession.update, or in the initial multipart/v1/realtime/callsrequest for WebRTC, so Bifrost routes on the nested transcription model while preserving realtime connection and turn semantics. - Regex Model Allow and Block Lists -
allowed_modelsandblacklisted_modelson virtual keys, andmodelsandblacklisted_modelson provider keys, acceptregex:<pattern>entries next to exact names. Patterns are compiled once as case-insensitive full matches, a pattern that is empty,*or does not compile is refused with a 400, and list-models never surfaces a pattern as a model. Provider key create and update validatemodelsthe same way asblacklisted_models. - Governance Entity Names on MCP Tool Logs -
mcp_tool_logsgains the attribution shape thelogstable already has:user_name,team_name,customer_nameandbusiness_unit_namebecome real columns, the multi-valued ID and name sets are stored as index-aligned JSON arrays, andbudget_idsandrate_limit_idsare recorded. Names are written from the request context at ingestion, so the dashboard stops rendering raw UUIDs. - Endpoint-Attributed MCP Inspections - Inspected MCP tool calls are logged with bounded identity sourced from the gateway rather than payload-supplied headers, carrying device, app key, server label, tool name and decision onto both the pending and final log entry. The MCP logs view falls back to
app_keywhenappis absent so endpoint-attributed rows show the right app icon and name. - Virtual MCP References by Name - Access profiles and governance projects reference Virtual MCPs through
virtual_mcp_name, and names resolve on startup with a name matching nothing refused.mcp_configs({ mcp_client_id, tools_to_execute }) replaces themcp_servers/mcp_tool_overridesinclude-exclude model with a single allowlist, where["*"]grants all tools including future ones and[]grants none.virtual_mcp_idand the old keys are deprecated, still accepted, and folded into the new shape at load time. - Normalized
error_typeMetric Label -bifrost_error_requests_totalgains anerror_typelabel with a closed, prefix-structured vocabulary (caller_*,policy_*,provider_*,bifrost_*,_OTHER), so a 429 from a governance rate limit is distinguishable from a 429 from an upstream. Classification resolves a declared error type first, then Bifrost’s own markers, then the status code, and deliberately ignores providererror.typestrings because they disagree across providers for the same condition. Docs - Bedrock OpenAI-Compatible Endpoint Routing - A
use_openai_endpointsflag on Bedrock keys and aliases routes chat completions and responses through Bedrock’s/openai/v1surface instead of Converse, for models that support it. It is opt-in by design, because Converse carries Bedrock Guardrails,performanceConfigandrequestMetadatathat the OpenAI-compatible surface silently ignores. The alias value wins over the key, matchinguse_anthropic_endpointsprecedence. Docs - Anthropic Tool Search on Bedrock Claude - Anthropic tool search (
tool_search_tool_*,defer_loading) is served onbedrock/Claude models by routing those requests to InvokeModel and InvokeModelWithResponseStream, the only Bedrock API AWS allows it on, and CountTokens counts such requests with the same InvokeModel body. Server-side tool search also survives the Bedrock-native invoke ingress end to end, with results returned as aserver_tool_useplustool_search_tool_resultpair on both the unary and streaming paths. Docs - Namespace Tool Support Across Providers - Responses
namespacetools are flattened in core for every provider whose wire lacks the type, with nested functions renamed to<namespace>__<function>so two namespaces sharing a function name no longer collide into an upstream duplicate-tool-name 400. Returnedfunction_callitems map back to the bare name plus namespace, prior-turn calls andtool_choicenames are re-aliased, and a still-duplicate name is rejected with a clear 400 before reaching the provider. Flattened names honour each wire’s documented tool-name limit, overridable per model throughtool_name_max_length. - Trusted Networks for the SSRF Guard - A
trusted_networkslist of IP and CIDR entries that the SSRF guard consults before outbound discovery calls, so a self-hosted identity provider on an internal network can be reached by the generic provider’s discover-endpoints and discover-claims flows. Declaring the key inconfig.jsonmakes it own the whole list, an explicit empty array clears dashboard-added entries, and hostnames are refused because DNS would then decide which requests bypass SSRF protection. - Prompt Cache Reload Through the Server -
ReloadPromptCachemoves ontoServerCallbacksso enterprise can gossip it across nodes. OSS behaviour is unchanged. - Guardrail Tool-Call Argument Redaction - Guardrail redaction covers LLM tool-call arguments (Chat function arguments, Responses function arguments and custom-tool input) across the Anthropic streaming and non-streaming paths, without touching tool names, IDs or definitions. A separate identity-based transformer path lets provider-managed rewrites land in the correct native JSON field even when the same text appears in several fields, verifying the original before patching and the written value after.
- Regions and Service URLs in Plaintext - Regions and service URLs (Azure endpoint, Vertex, Bedrock and Bedrock Mantle region, vLLM, Ollama, SGL and Databricks URL, MCP connection string) are public identifiers, not credentials, and were being unconditionally redacted into unreadable values in the UI.
SecretVar.RedactedIfSecret()returns a plain clone for a literal value and still masks anything sourced from an environment variable or vault reference. wait_for_usagefor Custom Providers - Await_for_usageflag oncustom_provider_configtells Bifrost the upstream sends a trailing usage-only frame, so the read loop holds open pastfinish_reasonuntil it arrives instead of synthesizing a zero-usage terminal chunk. Termination stays bounded by the usage chunk, two consecutive post-finish heartbeat comments, EOF, orstream_idle_timeout_in_seconds.- Pinnable Log Search Mode - The logs search box gains a mode dropdown (Auto, Content, Request ID). Auto-detection treated UUID-shaped input as an ID lookup and everything else as a content scan, which breaks for request IDs that are not UUID-shaped; a pinned mode bypasses all sniffing and re-runs the current input immediately.
- MCP Usage Guide Auth Methods - The MCP usage guide generates client configs for virtual key, OAuth and identity provider authentication instead of requiring a virtual key for every config. OAuth emits no headers, identity provider emits a
Bearerplaceholder, and virtual key keepsx-bf-vk. - Chart Color System - Dashboard charts, status badges and components read a structured set of CSS custom properties instead of hard-coded hex values, so colors adapt correctly between light and dark themes. Tokens are grouped as semantic (hues 0 to 70 reserved so no category can look like an error), sequential, ordinal for percentile series, and categorical at matched chroma assigned by rank.
🐞 Fixed
- SCIM-Only Login Gate Too Aggressive - The SCIM-only login gate now handles role mismatch, missing role and no-signal cases without deprovisioning the user.
- Reasoning and Compaction Blocks Sent to Guardrail Providers - Reasoning blocks, reasoning summaries and compaction blocks are excluded from every guardrail extraction path instead of being sent as read-only rows.
- GraySwan Monitor Output Dialect - Generated output blocks are rendered as native Responses items (
message,function_call,function_call_output) instead of a Chat-dialecttool_callsfield that is invalid in a Responses transcript. - Plugin
ctx.CalculateCostReturned Nothing - The model catalog is passed from the enterprise config into the bootstrap server config, so plugins initialized during bootstrap can calculate cost. - Edge Allow-Pending Ignored for MCP Connections - The MCP connection gate required explicit approval even when the effective Edge policy allowed pending servers; the effective allowlist now includes pending servers when the setting is on, while explicit denials stay blocked and unknown registrations fail closed.
- User Rankings Chart Colors - Trend badges and ranking bars in the user rankings tab use shared chart tokens, so they render correctly in both light and dark mode.
- Client Disconnect Not Cancelling Requests - A client that closes its socket while Bifrost is still waiting on core now cancels the request, so upstream retries stop as soon as nobody is listening.
- Silent Upstream Never Timed Out -
default_request_timeout_in_secondsbounds the wait for response headers on streaming requests, so an upstream that accepts the connection and never answers fails with a 504 and its fallbacks are used instead of pinning the provider worker. - Retry Storm After Client Disconnect - fasthttp-level stale-connection retries no longer multiply
max_retries, and retry backoff ends as soon as the request context is cancelled. - Abandoned Request Billing Coin Flip - Non-streaming requests whose caller had already disconnected were billed and logged only about half the time; terminal post-hooks now run deterministically.
- Stream Never Terminated Without
[DONE]- An OpenAI-compatible upstream that omits[DONE]and then goes silent afterfinish_reasonno longer fails the stream on idle timeout; the final chunk is synthesized from the bufferedfinish_reason. - Dropped SSE Frames in
raw_response- Role-only, finish-only and usage-only frames are no longer discarded from the reconstructedraw_response, anddelta.refusalanddelta.annotationsare forwarded instead of dropped. - Bedrock Mantle Trailing Usage - Bedrock Mantle chat streaming no longer drops the usage-only chunk that arrives after
finish_reason, so streamed usage and cost are recorded. - Fallbacks Re-Ran the Primary for Image and Video Edits - Fallbacks for image edit, image variation and video edit requests now reach the configured fallback provider and model instead of being routed back to the primary.
- Provider Response Headers Leaked Across Fallbacks - A fallback that failed pre-flight no longer serves provider A’s
Retry-Afterand rate-limit headers on a response attributed to provider B. - Credential-Bearing Response Headers Forwarded - Provider response headers are filtered through
IsSensitiveHeader, which recognizes credential names by substring and suffix, instead of a fixed list of 28 exact names. - Nil Dereference on Incomplete Fallback Errors - A plugin returning an error whose nested error field is nil no longer crashes the request worker.
- Bedrock Duplicate Document Names - Untitled document blocks are disambiguated with numeric suffixes, so a request with two or more untitled documents no longer fails with a Converse
ValidationException. - Bedrock Text Document Source - Plain text document formats (
text/plain,text/markdown,text/csv,text/html) ship base64-encoded throughsource.bytesinstead of a text-only document source Converse rejects. - Bedrock Tool Result Images - Images inside a
toolResultare hoisted out and re-inserted after the last tool result, for Bedrock-hosted model families that reject them in place. - gpt-oss Message Mistagging on Mantle - The Bedrock-grouped ingress converter no longer tags user and system input text as
output_textor omitsstatuson replayed assistant messages, and Bedrock requests with no explicitmax_tokenspopulate it from the model’s known capacity. - Azure Foundry Output Token Cap - Azure Foundry deployments of Fireworks-hosted models are served through
/openai/v1/chat/completionswhen/v1/responsesis absent, lifting the silent 4096 output token cap, and a turn truncated by the output-token cap reportsstop_reason: max_tokenson the Anthropic egress. - Gemini Inline Image and Audio Dropped - Gemini image-generation output (
inlineData) is no longer silently dropped on/v1/chat/completions, unary or streaming. - Gemini Image Edit Misclassified - Image-edit detection scans all parts across all contents instead of only the first part, so a request with prompt text before the image reaches Vertex as an edit, and
imageConfig.aspectRatiois preserved as a typed parameter. - Gemini Per-Part Media Resolution Dropped -
Part.mediaResolutionround-trips both spellings end to end, so per-part image and PDF tokenization no longer falls back to the model default. - Gemini
generationConfigLost Across Retries -top_k,frequency_penalty,presence_penalty,stop_sequencesandmedia_resolutionare no longer deleted while mapping intogenerationConfig, so every retry and fallback after the first keeps them. - MCP Tool Schema Property Order - MCP tool schemas keep one property and
$defsorder across tool syncs, so prompt caching is not invalidated by reordering alone. - vLLM Alias Resolution During Key Selection - The alias is resolved per key before comparing against each key’s physical
model_name, so the same public alias can map to different physical model IDs across vLLM instances. Allowed Models, Blocked Models and Deployments/Aliases are exposed on the vLLM key form. - opencode-zen Responses Routing - opencode-zen Responses calls are routed through
/v1/chat/completions, which its upstream serves, instead of/v1/responses, which it does not. - DeepSeek
max_completion_tokensIgnored - The field is remapped to the legacymax_tokenson the wire, which is the only form DeepSeek’s chat completions endpoint recognizes. - Anthropic Server Tools on Third-Party Endpoints - Unsupported Anthropic server tools are dropped before the request leaves Bifrost for Fireworks, vLLM and SGLang, the caller’s function tools are kept, and the drops are reported on
DroppedUnsupportedTools. - Bedrock Guardrail Headers -
guardrailIdentifier,guardrailVersionandtraceare mapped to theX-Amzn-Bedrock-Guardrail*headers on Bedrock’s OpenAI-compatible endpoints, so a configured guardrail is no longer silently ignored there. - Responses SSE
item: null- Responses stream events that carry no item payload no longer serialize"item": null, which strict clients reject as an invalid frame. - Responses
actionString Decode -image_generation_callitems where the provider emitsactionas a bare JSON string now decode, so the terminal events carrying the image are no longer dropped. - Mid-Conversation System Messages Broke Prompt Caching - Mid-conversation
role: "system"messages are inlined in place as<system-reminder>user turns on every converter with a top-level system field, instead of being hoisted into the system block where they grew the prompt prefix each turn and defeated prefix-based caches. - Unsupported
reasoning.contextRejected the Request - Areasoning.contextvalue the target model does not accept is dropped on the OpenAI and Azure Responses path instead of failing the request, with accepted values coming from the model datasheet. - ClickHouse Retention Filled Replica Disks - Log store deletes run as a single lightweight
DELETE FROM ... WHEREper run instead of oneALTER TABLE ... DELETEmutation per 100 rows, and the table TTL derived fromlogs_store.retention_daysis reconciled on every startup. - Governance Cleanup Dump Race - The periodic reset worker is cancelled and awaited before the final budget and rate-limit dumps, so shutdown no longer fails with
context canceled. - OAuth Refresh Failed for Public Clients -
client_secretis omitted from the refresh request when the secret is empty, so public clients no longer flip toneeds_reauthon a valid refresh token. - Complexity Router Skipped Continuation Turns - A continuation turn with no active session keeps its extracted input and falls back to classifying the recovered last user text instead of being left without a tier.
- Runtime Responses-Compat Routing - Bedrock runtime models that serve the Responses API are routed to it through a dedicated surface resolver rather than falling back to Converse.
- Bedrock Mantle Base Path - Base path resolution is centralized and backed by a
bedrock_mantle_base_pathdatasheet field, so a new model generation no longer silently falls through to the wrong path. - Virtual Key
allowed_models: ["*"]Handling Reverted - The wildcard handling added in OSS #6767 is reverted; configurations relying onallowed_models: ["*"]with an empty synced catalog return to the previous behaviour. - Helm
perUserHeaderKeysNot Rendered -mcp.clientConfigs[].perUserHeaderKeysis mapped into the renderedconfig.json. - Helm Plural Access Profiles - Governance roles accept
access_profilesas an array in the Helm and config schemas; the singular form keeps rendering unchanged, the plural wins when both are present, and an explicitly empty plural list clears existing grants. - Sidebar Title Overflow - Long sidebar item titles are truncated instead of overflowing.
- MCP Logs App Icon - App icons in the MCP logs table render at 20x20 and no longer shrink when the column is narrow.
🗄️ Database Migrations
- add_use_openai_endpoints_column - Adds the
use_openai_endpointscolumn to the provider keys table for Bedrock OpenAI-compatible endpoint routing. Reversible: the rollback drops the added column. Additive and nullable, so it is safe to run during a rolling upgrade. - add_time_of_day_pricing_columns - Adds
off_peak_cost_multiplierandpeak_hourstogovernance_model_pricingfor time-of-day pricing. Reversible: the rollback drops both added columns. Additive and nullable, so it is safe to run during a rolling upgrade. - mcp_tool_logs_add_governance_snapshots - Adds twelve governance attribution columns to
mcp_tool_logs:user_name,team_name,customer_name,business_unit_name, theteam_ids/team_names,customer_ids/customer_namesandbusiness_unit_ids/business_unit_namespairs, plusbudget_idsandrate_limit_ids. Reversible: the rollback drops all twelve in reverse order. Additive and nullable, so it is safe to run during a rolling upgrade. The twelveALTER TABLEs run under a bounded DDL lock wait, so startup does not stall behind a long-running log transaction.
🐙 Closed OSS Issues
- #6033 - Helm chart:
mcp.clientConfigs[].perUserHeaderKeysnot rendered into config.json - #6778 - opencode-zen Anthropic endpoint fails, zen upstream does not support /v1/responses
- #6782 - Azure Fireworks/Foundry models capped at 4096 output tokens on Responses and Anthropic ingress; truncation reported as end_turn
- #6825 - Bedrock provider silently drops Anthropic compaction, capability matrix says supported but Claude egress is Converse-only
- #6966 - Fallbacks silently re-target the primary provider for image edit and variation requests
- #6967 -
shouldContinueWithFallbacksnil-dereferencesBifrostError.Error, crashing the process on a plugin-returned error - #6972 - Abandoned-request billing is a ~50% coin flip when a client disconnects mid-request
- #6973 - Provider response headers leak across fallback boundaries
- #7003 - Bedrock Converse assigns duplicate default name “document” to untitled document blocks, ValidationException
- #7032 - Gemini image-generation output (inlineData) silently dropped on /v1/chat/completions, unary and streaming
- #7034 - Request and stream idle timeouts do not fire while waiting for response headers; a silent upstream blocks the request and the fallback is never used
- #7035 - Upstream retries continue after the client has disconnected and go past
max_retries - #7048 - Compat namespace flattening creates duplicate tool names
- #7065 - Bedrock Mantle chat streaming drops trailing usage after finish_reason
- #7072 - Bedrock Converse drops text-format document bytes (v1 to v2 regression)
- #7074 - gpt-oss via Bedrock Responses API mistags replayed history as output_text, breaking multi-turn sessions
- #7098 - ClickHouse logs store retention cleaner runs one mutation per 100 rows and fills replica disks
- #7099 - UsageTracker cleanup races the periodic rate-limit dump during shutdown
- #7108 - Custom-provider streaming never terminates when the upstream omits [DONE]
- #7120 - Provider response-header filter ignores
IsSensitiveHeader, forwarding credential-named headers to inference callers - #7143 -
does_not_send_done_markerdrops trailing Chat Completions usage and records zero cost - #7144 - Chat Completions streaming raw_response omits usage-only and finish-only SSE frames
- #7155 - Bedrock-native invoke ingress silently drops Anthropic tool search, served eagerly over Converse
- #7169 - MCP tool schema property order changes between tool syncs, breaking prompt caching
📀 Base OSS version
transports/v2.2.0 (pinned as github.com/maximhq/bifrost/transports v1.6.12-0.20260915184229-fa091d6feb03), with core v1.9.0, framework v1.7.0, governance v1.8.0, and logging v1.8.0.
