v1.5.11
Changelog
This release rebases Bifrost Enterprise on OSS transportsv1.6.11. The main work is a rewrite of cluster usage sync that sends only changed governance entries instead of full snapshots, quarterly budget support carried end to end through the enterprise UI and business unit APIs, and SCIM provenance protection so an OIDC login or token refresh can no longer overwrite roles that SCIM owns.✨ Features
- Incremental Cluster Usage Sync - Governance usage now gossips changed entries every 5 seconds, a lightweight heartbeat every 10 seconds, and a full repair snapshot every 30 seconds, instead of a complete snapshot on every tick. Internal cluster gzip compression is removed, remote budget and rate-limit totals are precomputed into an immutable snapshot so the request path does a direct id lookup, and a new
governance_usage_v2message keeps rolling upgrades safe because older nodes ignore it and still receive the legacy full snapshot. Docs - Quarterly Budgets Across the Enterprise UI -
reset_config(the fiscal quarter start month) is now propagated through every budget create, edit, duplicate, and save flow for access profiles, teams, customers, and users. The1Qduration renders as “Quarterly” with a fiscal quarter note next to it, and the dirty-state check includesquarter_start_monthso changing the start month is detected as an unsaved edit. - Role Filter and Real Sorting on the Users List - The users table gains a Role filter populated from the RBAC roles endpoint, plus a “No role” option. Name and email sorting now actually works:
sort_byandsort_orderare URL-backed, allowlisted at the handler, and applied in SQL, and roleless users are grouped last in both directions so SQLite and Postgres agree. Docs - Keycloak Department and Title Mapping -
convertKeycloakUsernow promotes thedepartmentandtitlecustom attributes (including thejob_titleandjobTitlevariants) into the dedicated provisioned-user fields, so attribute-to-team, attribute-to-role, and attribute-to-business-unit mappings apply during SCIM import instead of being silently dropped. Docs - Gray Swan Sees the Original Request - Guardrail evaluations forward the original Chat or Responses request JSON to the monitor API instead of rebuilding it from extracted text. Multi-part content arrays, images and files, native Responses tool shapes, and fields such as
nameand the developer role survive intact, per-turn batches are sliced from a cached snapshot without re-parsing or re-fetching media, and the raw body size cap is removed. Docs
🌎 Open Source Features
- URL Sources Inlined for AWS-Hosted Claude - URL-sourced images and documents are fetched and inlined on the native Anthropic path, because Bedrock Mantle rejects
{"source":{"type":"url"}}. Fetches use the SSRF-safe dialer with a size cap, and a failed fetch aborts the request instead of silently dropping the attachment. Docs - Quarterly Budgets for Customers - The customer entity and virtual key provider configs now accept quarterly budgets, so a customer budget can reset on a quarter boundary rather than only monthly or weekly.
- Fiscal Year Start in Budget Labels - Budget labels surface the configured fiscal year start through a new
fiscalQuarterNotehelper, and the quarter start selector is relaid out as a horizontal label and preview row. - Configurable Entity Selector Width - The entity selector accepts a
contentClassName, so a caller can widen or constrain its dropdown instead of being pinned to the default width.
🐞 Fixed
- SCIM Roles Overwritten by OIDC Login or Refresh - Role and team sync from token claims is now skipped for SCIM-managed users on both the login and token refresh paths, and the
source=scimprofile marker is re-stamped before the OAuth upsert overwrites the parsed profile. Truncated or stale claims can no longer downgrade a role that SCIM owns. Provenance checks fail closed, so an error in the check skips the sync. - Claims Not Enriched on Token Refresh - The refresh path now enriches claims from the provider, so claims that arrive through the provider API rather than directly in the token are no longer missing after a refresh.
- Keycloak Auth Cookie Used the Wrong Token - Keycloak is added to the id-token providers in
ChooseAuthCookieToken, matching how Keycloak populates both the access token and the id token. - Fiscal Quarter Start Lost on Business Unit Budgets -
ResetConfigis now assigned on the budget create path, the budget update path, and the create-during-update path. It was omitted from all three, so a fiscal quarter start was silently dropped on every save. The update path assigns it unconditionally, so clearing the quarter start is respected too. - User-Scoped Model Configs Survived User Deletion -
CascadeDeleteUsernow removes everyscope=usermodel config and its owned budgets, rate limits, and alert rules, and clears the access-profile materialization tracking rows. These rows are keyed by user id rather than being foreign-key children, so nothing else in the cascade reached them and a restored user with the same id inherited stale rows. - gRPC Peer Connection Falsely Stuck - The dial loop read the channel state twice per iteration, so a peer that became ready in between made
WaitForStateChangewait for a change away from ready and triggered needless reconnects. State is now read once per iteration, idle channels are explicitly connected, and a bounded probe RPC reports the real transport failure (connection refused, TLS handshake failure, mesh rejection) instead of only the channel state. - WebSocket Writes After Disconnect - A broadcast racing a client disconnect could panic on a nil connection or deliver to an unrelated client’s socket, because fasthttp recycles the hijacked connection as soon as the upgrade handler returns. Clients now carry an explicit closed flag, and close blocks until in-flight writes finish.
- Realtime Heartbeat Panic on Disconnect -
stopHeartbeatwaits for the heartbeat goroutine to exit before the upgrade handler returns. A ping already insideWriteMessagedereferenced a recycled connection, and with no recover on that path the panic took down the process. - Stop Sequences Dropped for Nova and Titan - Bedrock’s Converse camelCase
stopSequencesnow maps to the neutralstopparameter alongside Anthropic’sstop_sequences. 81 catalog rows were losingstop, so those models ran toend_turninstead of stopping. - Reasoning Replay Rejected on Chat-Shaped Requests -
/v1/chat/completionsand/v1/messagescarry replayed reasoning onreasoning_details, but the fail-soft strip only handled Responses-shaped items. A router that switched models mid-conversation returned an invalidsignatureerror instead of retrying without the signature. - Thinking Signatures on Responses Content Blocks - Signatures are stripped from content blocks, not only from
encrypted_contenton the reasoning item, and only reasoning items are dropped when nothing survives, so an ordinary message keeps its own content. - Reasoning Content Rejected by OpenAI and Azure Models -
reasoning.contentis no longer sent to non-gpt-oss reasoning models, which cap that array at zero entries and reject a populated one. Replayed Anthropic thinking blocks were hitting this;summaryandencrypted_contentalready carry everything those models accept. - Reasoning Effort Cleared for Current Grok Models - The rule substring-matched “grok-3-mini”, so
grok-4.5,grok-4.6, andgrok-4.20-multi-agentsilently lostreasoning_effortand answered at the wrong depth, cost, and latency. It is now an exact-match deny-list that normalizes routing prefixes,-latest, and xAI’s 4-digit date suffixes. - xhigh Reasoning Effort Downgraded for Grok - The shared OpenAI-dialect normalizer downgraded
xhightohighbefore the xAI compat pass ran.grok-4.5still downgrades on purpose, matching xAI’s documented upstream coercion. - Empty Structured-Output Streams -
content_part.added,output_text.delta,output_text.done, andcontent_part.doneare emitted when a tool-based structured-output call is reassembled on the Responses streaming path. Onlyoutput_item.addedanddonewere emitted, so consumers reading incremental events saw no text while tokens were billed. Affects Vertex, Bedrock Mantle, and Azure Claude. - HTTP 529 Rotating Credentials - Anthropic’s
overloaded_erroris treated as a transient server error and retried with backoff on the same key, since it reflects capacity across all callers rather than anything about the credential.
🗄️ Database Migrations
No new database migrations in this release, in either the OSS transports layer or the enterprise repo.📀 Base OSS version
transports/v1.6.11
