chore(deploy): build image off 1.89.1 backport (#30502) - #30547
chore(deploy): build image off 1.89.1 backport (#30502)#30547tin-berri wants to merge 37 commits into
Conversation
[Infra] Promote internal staging to main
[Infra] Promote internal staging to main
chore(ci): promote internal staging to main
chore(ci): promote internal staging to main
chore(ci): promote internal staging to main
chore(ci): promote internal staging to main
chore(ci): promote internal staging to main
chore(ci): promote internal staging to main
chore(ci): promote internal staging to main
…#30064) (#30143) * Add Claude Fable 5 across Anthropic, Bedrock, Vertex AI, and Azure AI Adds cost map entries for claude-fable-5 ($10/$50 per MTok, 1M context, 128K output, adaptive thinking only) on the Anthropic API, Bedrock converse (base, global, and us/eu geo inference profiles at the 10% regional premium), Vertex AI, and Azure AI (Microsoft Foundry, which serves Fable 5 with the full 1M context window unlike Opus 4.8). Registers anthropic.claude-fable-5 in BEDROCK_CONVERSE_MODELS, lists the model in the setup wizard, and extends the reasoning effort e2e grid. The Bedrock, Vertex, and Azure grid cells carry fail_reason markers until the CI accounts are provisioned: Bedrock needs the provider data sharing opt-in Fable 5 requires, and the Foundry resource needs a claude-fable-5 deployment. The first-party entry carries provider_specific_entry {us: 1.1} for the inference_geo premium and deliberately no fast multiplier since Fable 5 has no fast mode. https://claude.ai/code/session_01MZarYYT3aS7DxaNjoax6Gm * Drop removed sampling params for Claude 4.7+ when drop_params is set Fable 5, Opus 4.7, and Opus 4.8 removed sampling params: the API rejects top_p, top_k, and any temperature other than 1 with a 400. LiteLLM was forwarding them even with drop_params enabled because the Anthropic and Bedrock converse transformations passed temperature/top_p through unconditionally. Mirror the GPT-5/o-series handling: temperature=1 still passes through, other values and any top_p are dropped when drop_params is set, and without drop_params a clean client-side UnsupportedParamsError tells the caller how to opt in, instead of surfacing the raw provider error. https://claude.ai/code/session_01MZarYYT3aS7DxaNjoax6Gm * Drive sampling param gating from the cost map and cover top_k Greptile review follow-ups on the sampling param fix: the restriction for Fable 5 / Opus 4.7 / 4.8 is now declared as supports_sampling_params: false on every affected cost map entry (perplexity excluded; that route is OpenAI-compatible and maps sampling params upstream) and read back through a tri-state map lookup, keeping the name check only as a fallback for provider-routed ids whose hosted map entries predate the flag, the same layering supports_adaptive_thinking uses. top_k bypasses map_openai_params as a provider-specific kwarg, so it is gated at the shared AnthropicConfig.transform_request boundary (direct, Bedrock invoke, Vertex, Azure) and in the Bedrock converse _handle_top_k_value path, with drop_params threaded through the converse transform helpers. Also updates the reasoning effort grid cell count assertion for the four Fable 5 rows added on this branch (29 x 11 cells). https://claude.ai/code/session_01MZarYYT3aS7DxaNjoax6Gm * Declare supports_sampling_params in the cost map schema The model map validation schema uses additionalProperties: false, so the new flag must be declared for the 28 entries that carry it; this was the one failing job (misc / Run tests) on the previous commit. https://claude.ai/code/session_01MZarYYT3aS7DxaNjoax6Gm * fix(bedrock): gate top_k=0 on converse to match Anthropic boundary Truthiness check let top_k=0 silently disappear on models that removed sampling params, while AnthropicConfig.transform_request treats 0 as present and raises UnsupportedParamsError (or drops when drop_params is set). Switch to 'is not None' so converse, direct Anthropic, invoke, Vertex, and Azure all behave the same for top_k=0. --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
* feat(proxy): publish /v2/model/info in Swagger OpenAPI spec Expose the v2 model info endpoint in /docs by removing include_in_schema=False and documenting query parameters used by the admin UI and proxy CLI consumers. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(ui): regenerate schema.d.ts for /v2/model/info OpenAPI docs Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> (cherry picked from commit f5b11b7)
…#29665) (#29788) * feat(responses): add default no-op sign_request to BaseResponsesAPIConfig * feat(responses): call sign_request after body is final, send signed bytes when signed * feat(bedrock_mantle): add SigV4 sign_request via composed BaseAWSLLM (bearer path) * test(bedrock_mantle): cover SigV4 access-key, AssumeRole, body bytes, region/auth consistency * feat(bedrock_mantle): defer auth to sign_request; validate_environment no longer requires bearer * docs(bedrock_mantle): document SigV4 + Bearer auth on Responses route * test(responses): cover fake-stream signing order and mantle bearer arg/env precedence * fix(bedrock_mantle): wrap all botocore credential errors with both-paths guidance * fix(bedrock_mantle): catch specific credential errors, not all BotoCoreError, so STS transport failures are not masked * fix(bedrock_mantle): sign the compact Responses route too, not just create (cherry picked from commit 2c95d0b)
…gs (#29991) Capture user_id and extra_info from metadata or litellm_metadata. The single-bag read dropped identity whenever a request carried a present litellm_metadata field (null or a user-supplied dict), since /chat/completions routes the authenticated identity into metadata while the guardrail read litellm_metadata first (cherry picked from commit 1bbaf1c)
…29493) * feat(proxy): add disable_budget_reservation general setting (#27639) * feat(proxy): register disable_budget_reservation in ConfigGeneralSettings (#27639) * docs(proxy): document disable_budget_reservation concurrency tradeoff (#27639) * ci: re-trigger flaky docker build (prisma generate ECONNRESET) * fix(proxy): warn and document budget enforcement tradeoff when disable_budget_reservation is set (#27639) (cherry picked from commit 1032dd7)
(cherry picked from commit 92817cb)
…ware GET path (#29960) * fix(ui): load MCP tool configuration tools via the OBO/passthrough-aware GET path * fix(mcp): admin-only include_disabled_tools so the settings UI shows toggled-off tools * fix(ui): repopulate MCP server edit form when server data loads after mount (OAuth return) * fix(ui): persist MCP OAuth token on save and return to the Settings tab after authorize * fix(ui): scope MCP OAuth callback to the initiating form so create and edit flows don't cross-talk * fix(ui): derive OAuth-return Settings tab via lazy state init instead of setState-in-effect * Fix MCP OAuth edit token handling --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> (cherry picked from commit 51ba6e3)
…r server's token no longer leaks into the next add-server session (#30000) * fix(ui/mcp): reset OAuth hook state on modal close so a prior server's token no longer leaks into the next add-server session * fix(ui/mcp): clear in-flight OAuth guard on reset and reset form/tools on modal close so nothing leaks on a parent-driven dismiss (cherry picked from commit d8fe091)
…T-3593) (#30009) * fix(proxy): authorize batch files using upload target_model_names (LIT-3593) After replace_model_in_jsonl, body.model is a stripped provider id. Reverse-mapping it via resolve_model_name_from_model_id is first-match on model_list and caused false 403s when multiple deployments share the same stripped name. Use target_model_names from the unified file id instead. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(proxy): restore resolve_model_name_from_model_id for JSONL fallback path (LIT-3593) Restores the reverse-lookup for the JSONL body.model fallback path so that legacy/pre-target_model_names managed files still map stripped provider IDs back to proxy aliases before auth. Also cleans up redundant `or None`. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Revert "fix(proxy): restore resolve_model_name_from_model_id for JSONL fallback path (LIT-3593)" This reverts commit 30d2e96. --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> (cherry picked from commit 2cd7e87)
* fix(proxy): align /v1/model/info with router deployments Return router model_list entries (including team-scoped models) with team access metadata instead of wildcard-expanded names from get_complete_model_list. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(proxy): gate v1 team filter and honor key allowlists Only apply get_all_team_and_direct_access_models for admin or user-bound keys, then intersect with key/team model restrictions to avoid empty lists for service tokens and metadata leaks for restricted keys. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(proxy): skip v1 team filter when user row is missing Require a DB-backed user before applying team-access filtering on /v1/model/info, and skip the trailing filter in get_all_team_and_direct_access_models when user context cannot be resolved. Co-authored-by: Cursor <cursoragent@cursor.com> * Revert "fix(proxy): skip v1 team filter when user row is missing" This reverts commit 74e1fbd. * fix(proxy): restore legacy v1 model access filtering Keep /v1/model/info on key/team allowlists instead of DB team-membership filtering, while still listing router deployments for team-scoped models. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(proxy): drop A2A agent entries from public /v1/model/info list * fix(proxy): scope team BYOK rows on /v1/model/info to caller's teams Listing the full router model_list let any authenticated key without explicit model restrictions enumerate other teams' BYOK deployments (public name, team_id, api_base) via /v1/model/info. Reuse the existing _get_caller_byok_team_scope check so non-admin callers only see global deployments plus their own team's BYOK rows; admins keep the full view. --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com> (cherry picked from commit 6068bb7)
Enable teams to configure their own Datadog credentials via
POST /team/{team_id}/callback, following the same pattern as Langfuse.
(cherry picked from commit f5e6012)
… responses (#26153) (#27346) * fix: coerce server_tool_use dict to ServerToolUse in Usage.__init__ (#26153) * fix: coerce server_tool_use to ServerToolUse in stream_chunk_builder (#26153) * fix: dict/pydantic-tolerant access in tool_call_cost_tracking (#26153) * fix: dict/pydantic-tolerant access in anthropic cost_calculation (#26153) * test: assert ServerToolUse type in existing stream_chunk_builder anthropic web search test * test: regression test for #26153 (stream_chunk_builder server_tool_use type) * test: dict/pydantic safety for tool_call_cost_tracking helper * test: dict/pydantic safety for anthropic web_search cost * refactor: consolidate _get_web_search_requests into shared cost-calc utils * test(realtime): use gpt-realtime; openai retired gpt-4o-realtime-preview OpenAI shut down the gpt-4o-realtime-preview family (incl. the undated alias) on 2026-05-07, causing the live realtime test to fail with a 4000 invalid_request_error.invalid_model close. gpt-realtime is the GA successor; switch the live-call tests to it, matching the base branch. * refactor(types): drop redundant server_tool_use coercion in Usage.__init__ --------- Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com> (cherry picked from commit 4a3860d)
fix(proxy): atomic merge for team model aliases and team.models on BYOK create (cherry picked from commit ac7c2dc)
* fix(proxy): populate access_via_team_ids on /v1/model/info Team metadata enrichment previously only ran on /v2/model/info with include_team_models=true, leaving /v1/model/info without access_via_team_ids for project model-picker flows. Co-authored-by: Cursor <cursoragent@cursor.com> * docs(dashboard): sync OpenAPI schema for /v1/model/info query params Add include_team_models and teamId to the generated schema for /model/info and /v1/model/info after the proxy endpoint gained team-access filtering. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(proxy): always return direct_access on /v1/model/info Set direct_access to true or false on every enriched model so clients can filter without treating a missing field as ambiguous. Co-authored-by: Cursor <cursoragent@cursor.com> * perf(proxy): fail fast when teamId is set without a connected DB on /v1/model/info Raise the db_not_connected error before building, enriching, and translating the model list instead of after, so a teamId query against a proxy with no database no longer wastes the full enrichment pipeline. * fix(proxy): fail fast when include_team_models is set without a database include_team_models=True relies on _populate_team_access_on_models to set direct_access/access_via_team_ids, which only runs when a database is connected. Without one, _filter_models_to_user_accessible discarded every model and the endpoint returned an empty list with HTTP 200. Mirror the teamId guard so the request fails fast with a clear db_not_connected error before any model-list work. * fix(proxy): populate direct_access on single-model /model/info lookup The /v1/model/info list path populates model_info.direct_access (and access_via_team_ids) when a database is connected, but the litellm_model_id single-model lookup returned early without it. This made the two endpoints disagree, breaking the parity assertion in test_get_specific_model. Run the same population on the single-model path so both responses match. * fix(proxy): apply no-DB fast-fail before litellm_model_id branch The teamId/include_team_models no-DB guard sat after the litellm_model_id early return, so ?litellm_model_id=X&teamId=Y with no DB returned 200 with unpopulated access fields instead of the 500 raised on every other path. Move the guard ahead of the branch so the fast-fail is uniform. * fix(proxy): apply teamId/include_team_models filters on single-model lookup The litellm_model_id early-return branch in model_info_v1 populated the team access fields but returned before the teamId and include_team_models filters ran, so a single-model lookup surfaced the deployment regardless of team access when the DB was connected. Run both filters on the single-model list before returning so the documented query params behave the same with and without litellm_model_id. --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com> (cherry picked from commit 7d1f68e)
…thropic streaming logging Targeted subset of staging commit cfcdf87 (#30202): only the anthropic_passthrough_logging_handler.py hardening hunks and their four tests are taken; the rest of that staging batch is intentionally excluded. (cherry picked from commit cfcdf87) (cherry picked from commit 973c7eb)
…combined view (#30327) The grace-period branch assigned the recursive get_data result (a finished LiteLLM_VerificationTokenView) back into the variable that the combined-view dict normalization then subscripts, raising TypeError on every request made with a rotated key inside its grace window; auth surfaced that as a 401. Return the recursive result directly instead. Regression test drives the full get_data flow: old hash misses the view, deprecated table resolves to the active token, and the call must return the view object (cherry picked from commit 5047eaf)
The OAuth2 passthrough ran user_api_key_auth on the client's upstream bearer first and only recovered after the failed validation had already logged a 401 auth event to the tracer, so successful tool calls to a delegated server each carried a phantom 401 span. Check delegate_auth_to_upstream before validating: a delegated server skips the doomed call entirely so nothing is logged, and a non-delegated server validates normally and surfaces a real 401 rather than being exchanged for an anonymous upstream-passthrough session. (cherry picked from commit 039a2d8)
(cherry picked from commit d96ab46) Backport adaptation: applied only the pyproject.toml and ui/litellm-dashboard/package.json manifest hunks; uv.lock and package-lock.json are regenerated on this line in a separate commit rather than cherry-picked, and the package.json devDependencies are unioned with this line's @types/uuid and vite entries
Prerequisite for #27346 (completion_cost AttributeError on streaming Anthropic web_search). #27346's per-chunk coercion is undone by the existing Usage(**returned_usage.model_dump()) reconstruction in calculate_usage, which round-trips server_tool_use back to a plain dict; without this Usage.__init__ coercion the cost path still does attribute access on a dict and raises. The same prerequisite was bundled into the stable/1.88.x backport of #27346 (24b9655). Content-verified present on litellm_internal_staging via aggregator 32c88ca (Litellm oss staging 080626, #29932); this restores only the two-line coercion, not the rest of that aggregator. (cherry picked from commit 32c88ca)
…9x_multi chore(release): backport 1.84.8 patch set + MCP/model-info/DB fixes to stable/1.89.x and cut 1.89.1
|
|
Greptile SummaryThis is the 1.89.1 backport deployed against
Confidence Score: 4/5The backport is largely additive and defensive, but two changes warrant a closer look before promoting to production: the removal of the model-ID-to-proxy-name mapping in the batch rate limiter auth loop may reject legitimate non-managed batch job submissions, and the The deprecated-key grace-period fix, DB 503 promotion, and cached-plan reconnect are clear improvements. The MCP auth reorder correctly tightens the security boundary. The batch rate limiter change removes a mapping that the code comment explicitly noted was needed for post-replacement JSONL files; whether that path is still exercised for legacy (non-managed) files needs confirmation. litellm/proxy/hooks/batch_rate_limiter.py (resolve_model_name_from_model_id removal), litellm/llms/anthropic/common_utils.py (_supports_sampling_params fallback names)
|
| Filename | Overview |
|---|---|
| litellm/proxy/hooks/batch_rate_limiter.py | Introduces target_model_names from unified file ID for managed files, and removes the resolve_model_name_from_model_id mapping that previously normalized provider IDs to proxy names for all batch files in the auth loop. |
| litellm/llms/anthropic/common_utils.py | Adds _supports_sampling_params to gate top_p/top_k/temperature on Claude 4.7+ models. Primary lookup is model-map driven, but retains a hardcoded name-pattern fallback list that violates the no-hardcode-model-flags rule. |
| litellm/proxy/management_endpoints/team_endpoints.py | team_model_add replaces Python-side merge with an atomic SQL ARRAY append using DISTINCT unnest to fix race conditions in concurrent BYOK model creates; updates updated_at only for the follow-up find. |
| litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py | MCP auth refactor: reorders condition tree so explicit litellm key is checked before delegate_auth_to_upstream bypass, removes _target_servers_use_oauth2 fallback, narrows anonymous cold-start fallback to auth_type=none passthrough servers only. |
| litellm/proxy/proxy_server.py | model_info_v1 now reads directly from llm_router.model_list (like v2), adds include_team_models/teamId params, applies team BYOK scoping; v2/model/info promoted out of include_in_schema=False; helper functions extracted for testability. |
| litellm/proxy/utils.py | Cached-plan error recovery now calls attempt_db_reconnect (singleflight) instead of injecting a unique comment; also fixes a silent bug where deprecated_response was fetched but never returned during grace-period key lookups. |
| litellm/proxy/db/exception_handler.py | Adds is_prisma_engine_internal_error and is_database_service_unavailable_error to distinguish DB outage from auth failure, enabling 503 responses during connectivity issues instead of 401. |
| litellm/proxy/auth/auth_exception_handler.py | Adds a 503 fast-path when the authentication database is unreachable, preventing DB outages from masquerading as 401 auth failures. |
| litellm/proxy/auth/user_api_key_auth.py | Adds disable_budget_reservation flag to general_settings; passes general_settings into _reserve_budget_after_common_checks for the new skip path. |
| litellm/proxy/_experimental/mcp_server/rest_endpoints.py | Adds include_disabled_tools query param (admin-only) that bypasses allowed_tools filtering for MCP configuration UI; gated on PROXY_ADMIN role so non-admins always see filtered tools. |
| litellm/proxy/_experimental/mcp_server/db.py | MCP server delete now cleans up both litellm_mcpusercredentials and litellm_mcpuserenvvars independently so a failure on one table still attempts the other. |
| litellm/proxy/_experimental/mcp_server/discoverable_endpoints.py | exchange_token_with_server: expires_in is now omitted instead of defaulted to 3600 when absent, matching RFC 6749 §4.2.2 which makes expires_in optional. |
| litellm/llms/anthropic/chat/transformation.py | Routes temperature, top_p, and top_k through _apply_sampling_param to enforce model capability checks; no logic changes for supported models. |
Comments Outside Diff (1)
-
litellm/proxy/hooks/batch_rate_limiter.py, line 657-663 (link)resolve_model_name_from_model_idmapping removed from auth loopThe deleted code translated provider-level model IDs back to proxy model names before running access checks. The comment it carried ("body.model may be the provider id after
replace_model_in_jsonl") described a real case: when a non-managed JSONL file is pre-processed byreplace_model_in_jsonl, thebody.modelfields become provider IDs (e.g.openai/gpt-4.1), not the proxy aliases the caller has access to. After this change,model_to_checkequals the raw JSONL value for the non-managed path, so the access check compares a provider ID against a proxy-model allowlist and spuriously rejects legitimate callers.For managed files this is fine —
target_model_namesalready carries the proxy alias and bypasses the JSONL parse. The regression risk is on the legacy non-managed path ifreplace_model_in_jsonlhas already transformed the content before this hook runs.
Reviews (1): Last reviewed commit: "Merge pull request #30502 from BerriAI/l..." | Re-trigger Greptile
| model_lower = model.lower() | ||
| return not any( | ||
| v in model_lower | ||
| for v in ( | ||
| "fable", | ||
| "opus-4-7", | ||
| "opus_4_7", | ||
| "opus-4.7", | ||
| "opus_4.7", | ||
| "opus-4-8", | ||
| "opus_4_8", | ||
| "opus-4.8", | ||
| "opus_4.8", | ||
| ) | ||
| ) |
There was a problem hiding this comment.
Hardcoded model-name fallback violates no-hardcode-flags rule
The fallback name list ("fable", "opus-4-7", "opus-4-8" variants) is evaluated when _get_model_capability returns None — i.e. when the model map has no supports_sampling_params entry. The policy here is to express model capabilities solely through model_prices_and_context_window.json so users benefit from updates without code changes. The "fable" substring in particular is very broad and could silently match unintended provider-routed IDs.
Since the verified model IDs (claude-opus-4-7, claude-fable-5, etc.) already carry "supports_sampling_params": false in the JSON, the fallback names add risk rather than safety. The preferred pattern is to gate solely on _get_model_capability and, if that returns None, treat the model as supported (fail-open for unknown models) rather than maintaining a parallel name list in code.
Rule Used: What: Do not hardcode model-specific flags in the ... (source)
| " END || $1::text[]" | ||
| " ))" | ||
| ") " | ||
| "WHERE team_id = $2", | ||
| models_to_add, | ||
| data.team_id, | ||
| ) | ||
| # Re-fetch via update (write-routed) instead of find_unique (read-routed) | ||
| # to avoid returning stale data from a read replica. The models column was | ||
| # already set by execute_raw above; this bumps updated_at. `include` mirrors | ||
| # the relations the auth path consumes off the cached team object so that | ||
| # `_refresh_cached_team` doesn't null them out — see | ||
| # object_permission_utils.validate_key_search_tools_against_team and the | ||
| # MCP/agent authz paths, which treat a missing object_permission as | ||
| # "no team-level restriction". | ||
| updated_team = await prisma_client.db.litellm_teamtable.update( | ||
| where={"team_id": data.team_id}, |
There was a problem hiding this comment.
Silent success when
team_id does not match any row
execute_raw returns None regardless of whether the WHERE team_id = $2 clause matched any rows. If data.team_id refers to an already-deleted or nonexistent team, the SQL succeeds silently, the subsequent update also finds no row and returns None, and the caller receives no error. The old add_new_models_to_team + update(data={"models": ...}) path would raise a Prisma RecordNotFound from the update. Consider checking updated_team is None after the update and raising a 404 if the team row was not found.
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
| ) | ||
| region = self._resolve_region({**litellm_params, "api_base": api_base}) | ||
| base = ( | ||
| api_base |
There was a problem hiding this comment.
High: SigV4 signing to caller-controlled hosts
api_base can come from the request path through the proxy, and the new SigV4 fallback signs whatever URL is returned here when no bearer token is configured. An authenticated caller can set api_base to an attacker-controlled host for a Bedrock Mantle /v1/responses request and receive the proxy's AWS-signed headers and prompt body; restrict IAM signing to the standard Mantle host or an operator-configured allowlist, and reject request-supplied custom hosts before calling _sign_request.
PR overviewThis PR backports the deployment image build to the 1.89.1 line and includes changes affecting the Bedrock Mantle There is one open security issue: an authenticated caller can influence the Bedrock Mantle Open issues (1)
Fixed/addressed: 0 · PR risk: 7/10 |
Relevant issues
This PR exists to run the build/deploy workflow off the exact file state of the 1.89.1 backport merge (#30502, commit 3983231) so the resulting image can be deployed to a vcluster for testing. It is not intended as new feature work; the head branch points directly at that commit
Pre-Submission checklist
Type
🚄 Infrastructure
Changes
The head branch is the 1.89.1 backport (#30502); base is litellm_internal_staging, so the diff reflects the 1.89.x patch set (MCP, model-info, passthrough, DB fixes plus the 1.89.0 -> 1.89.1 version bump). No changes were authored here beyond pointing a branch at that commit