Commit graph

17 commits

Author SHA1 Message Date
yujonglee
c919f3d9f3
refactor(proxy): inject database repositories through per-repository dependencies (#48507)
* refactor(proxy): inject database repositories through per-repository dependencies

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(proxy): model Prisma client cleanup

* test(rust): include NativeDatabase in bridge API surface

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-30 22:57:54 +00:00
tin-berri
53a4cee0d8
fix(ui): honor dark and local logos across Connect and Chat (#48532) 2026-10-27 03:00:03 +00:00
ishaan-j-berri
205cfd8044
fix(proxy): restore Claude gateway model discovery (#48204) (#48221)
* fix(proxy): restore Claude gateway model discovery (#48204)

* test(proxy): cover gateway discovery after OAuth sign-in (#48204)

* refactor(proxy): share model listing route policy (#48204)

* test(proxy): isolate SSO settings environment (#48204)
2026-10-24 16:47:15 -07:00
moe-berri
08ef4f40b1
feat(ui): configure the default Usage time range (#48207)
* feat(ui): configure the default Usage time range

* fix(ui): retain the selected calendar preset during input sync

* fix(ui): preserve fallback dates when applying across DST
2026-10-24 12:20:13 -07:00
yucheng-berri
f7e6ddec66
feat(proxy): add LITELLM_OFFLINE_MODE, one switch for the fetches LiteLLM makes on its own (#48096)
* feat(proxy): add LITELLM_OFFLINE_MODE to stop every request the proxy makes on its own

* fix(ui): name LITELLM_OFFLINE_MODE where the cost map panel says local mode is forced

* test: isolate the offline-mode tokenizer tests from the local Hugging Face cache

* test: cover the offline policy templates and the cached Kimi K3 tokenizer

* test(integration): count Kimi K3 tokens in the offline-mode egress test

* refactor(token_counter): skip non-bundled tokenizers in offline mode instead of listing downloaded ones

---------

Co-authored-by: yucheng-berri <293926326+yucheng-berri@users.noreply.github.com>
2026-10-23 16:54:19 -07:00
yucheng-berri
013be3eb04
feat(proxy): add LITELLM_DISABLE_LATEST_RELEASE_CHECK to stop the release check (#48065)
* feat(proxy): add LITELLM_DISABLE_LATEST_RELEASE_CHECK to stop the release check

The dashboard asks the proxy for the latest LiteLLM release, and the proxy fetches it from api.github.com on every cache miss. Deployments that block or audit outbound traffic had no way to turn that off. With LITELLM_DISABLE_LATEST_RELEASE_CHECK=true the endpoint returns null without making a request, which the dashboard already treats as no upgrade banner.

* fix(proxy): regenerate dashboard types for the release check flag

The endpoint docstring feeds the OpenAPI description, so the ui-api-types
check needs schema.d.ts regenerated. The docstring now says the flag skips
every outbound request, which stays true once the changelog feed is read
too

---------

Co-authored-by: Sujit Nirmal <nirmalsujit891@gmail.com>
Co-authored-by: yucheng-berri <293926326+yucheng-berri@users.noreply.github.com>
2026-10-23 12:52:27 -07:00
yucheng-berri
46922bf120
fix(proxy): take the upgrade notice from the changelog instead of GitHub releases (#47998)
The Admin UI upgrade notice read GitHub's latest release, which the release
pipeline sets on its own, so admins were offered releases the changelog had
not announced yet and sent to the auto-generated GitHub release page. The
notice now reads the newest stable release from the docs changelog feed and
links to its changelog page. GitHub release notes are still used for the
feature and fix counts of that version's minor line.

Co-authored-by: yucheng-berri <293926326+yucheng-berri@users.noreply.github.com>
2026-10-23 11:18:38 -07:00
Misbah Syed
8b442f00fc
fix(proxy): count the whole minor line in the upgrade notice for patch releases (#46942)
* fix(proxy): count the whole minor line in the upgrade notice for patch releases

A patch release's notes only list its backports, so v1.105.1 showed
"0 new features, 1 fix, and 0 other updates" even though upgrading from
v1.104.x brings everything in v1.105.0 too. When the latest release is a
patch, also fetch the recent release list and sum the stable releases on
the same major.minor line (skipping rc/dev prereleases and drafts).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(proxy): use tuples for release lists and sync the dashboard API types

Satisfies the LIT001 type-discipline gate and regenerates the
latest_release_info description in schema.d.ts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(proxy): cover the bad release-list payload and non-semver latest tag

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(proxy): type the release-line Counters so basedpyright sees no unknowns

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(proxy): fetch earlier patches of the minor line by tag

Reading the first page of /releases could miss the line's .0 release when
prereleases push it off the page, and one unrelated release with a null
body failed validation for the whole list. Fetch each earlier patch tag
directly instead (v1.105.0 .. v1.105.N-1), skip tags with no stable
release, and treat a null release body as empty notes.

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 15:49:57 -07:00
Mateo Wang
610443519a
fix(proxy): unset DB environment variables removed from the row on every worker by row revision (#46709)
* fix(proxy): unset DB environment variables removed from the row on every worker by row revision

* fix(proxy): order the environment variables revision migration after main's and set its lock timeout

* fix(proxy): snapshot the environment at the first DB sync even when no environment_variables row exists yet

* fix(proxy): close gaps in DB environment variable reconciliation

Grant the revision sequence to every role so a writer role with only
table grants can still save environment_variables. Unset SSO keys that
only the environment_variables row stored on the next SSO sync, while
keeping keys the SSO settings table holds. Skip a revision-less row once
a revision has been applied, so a stale cached row cannot bring a
removed key back. Keep plaintext and undecryptable values when rotating
the master key instead of dropping them from the row.

* fix(proxy): keep env var revisions monotonic across DB copies and restores

Stamp at least the old revision plus one on update so a copied row keeps
rising, re-read a stale cached row from the writer and apply it when the
database itself went back, unset dropped SSO keys when sso_settings are not
loaded from the DB, and keep env values master key rotation cannot decrypt
exactly as stored

* fix(proxy): skip an env var row read before an overlapping sync that already applied a newer one

* test(proxy): cover a read replica back on an older row and an SSO client removed from DB environment_variables

* fix(proxy): keep config reads up when the writer is down, find the revision sequence by table schema, read the writer before rewriting env vars, and add the trigger under db push

* test(proxy): model the writer database in the retry policy config update fake

* fix(proxy): recheck the environment_variables row revision right before applying it

A sync that started later could read a stale environment_variables row
before an earlier sync applied a newer one, then pass the read-order check
and apply the stale row, bringing back keys the newer row removed. The
behind-the-applied-revision check now runs at apply time, re-reading the
writer when the row is behind, and a writer row read while another sync
applied a newer revision is dropped.

The config sync tests now inject a fake database client and use the real
get_config_param and its cache instead of replacing get_config_param.

* test(proxy): keep encryption real in the SSO replica-lag test

* test(proxy): inject a fake Prisma client in the env var replica-lag test

* fix(proxy): keep the applied environment variables when the writer database is out of connections

* test(proxy): cover a writer database out of connections in the env var integration tests
2026-10-17 03:51:05 +00:00
Krrish Dholakia
e4dc696af8
feat(ui): turn the Chat UI on by default (#46918)
Co-authored-by: Krrish Dholakia <krrishdholakia@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-16 09:33:49 -07:00
ryan-crabbe-berri
aa879f77a9
feat(proxy): let team admins create keys for team members behind an opt-in setting (#45870)
* feat(proxy): let team admins create keys for team members behind an opt-in setting

A team admin calling POST /key/generate with a team they administer and the
user_id of another member of that team got a 403, and the dashboard only
offered the "Another User" owner option to proxy admins

Add a create_member_keys entry to team_admin_editable_team_fields. When a
proxy admin turns it on, a team admin can create a team key owned by another
member of a team they administer, through the API and through the Create Key
form. It stays off by default, so nothing changes until a proxy admin opts in

With the setting off, the 403 a team admin gets for this call now names the
setting to enable instead of saying they can only create keys for themselves

* fix(ui): order the member owner picker after the team and drop the viewer from it

For a team admin the owner picker depends on the team, so it now sits under the Team field, lists only the other members of that team, and the Team field says why it is required

* fix(proxy): keep keys a team admin creates for a member from carrying more than LLM access

A key authenticates as its owner, so with create_member_keys on a team admin could create a key owned by a proxy admin who sits in their team and act as a proxy admin with it

The member now has to hold the internal_user or internal_user_viewer role, and the key is always an llm_api key, so the team admin never holds a secret that reaches management routes. Asking for a management or read_only key for a member is refused

The unit tests now check the permission decision directly instead of replacing generate_key_helper_fn, and the saved key is checked against a real proxy in the team admin gate matrix

* style(proxy): sort the team admin field permission imports

* refactor(proxy): force the member key type on the request instead of merging a second dict

* test(proxy): drive member key creation through the key generation helper

The pure helpers were covered but the wiring in _common_key_generation_helper was not. Dropping the owner role lookup, the refusal call, or the user_id handed to common_key_access_checks left every unit test green

* fix(proxy): skip the owner role lookup when create_member_keys is off

The owner role was read before the verdict checked the setting, so with the setting off a failing user table read surfaced as a 500 instead of the 403 a team admin got before, and every such request paid an extra writer read

---------

Co-authored-by: Yuneng Jiang <yuneng@berri.ai>
2026-10-14 06:25:58 +00:00
ryan-crabbe-berri
4c78023db2
feat(teams): let proxy admins grant team admins the right to raise their team budget (#45404)
* feat(teams): let proxy admins grant team admins the right to raise their team budget

Adds a raise_max_budget entry to team_admin_editable_team_fields. With max_budget alone a team admin can still only keep or lower the team budget. Adding raise_max_budget lets them raise it, capped by the organization's max_budget when the team belongs to one, while removing the budget stays with proxy admins. The entry is rejected without max_budget, /team/info reports may_raise_max_budget to the caller, and the Admin UI nests the new checkbox under Max Budget with a tooltip and shows the team admin a hint under the budget field.

* fix(ui): shorten the raise_max_budget tooltip and link it to the docs

* fix(teams): pin the organization in the guarded team budget write

A granted raise is checked against the team's organization at read time, so the write now also requires organization_id to be unchanged. A concurrent move into a budgeted org returns 409 instead of landing an uncapped raise. Also types the new test helpers.

* test(teams): type the team row store methods and the touched race test arguments

* test(teams): annotate the last fixture and parametrize arguments in the raise_max_budget tests
2026-10-09 13:39:08 -07:00
Mateo Wang
58258409c9
refactor(proxy): expose public names for private proxy helpers (#45170)
* refactor(proxy): expose public names for private proxy helpers

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): keep original class names behind public aliases

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): preserve internal callback filtering

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): keep _PROXY_ class names for managed files hooks

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): keep old private names in package exports

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): preserve recursive auth helper name

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(proxy): align MCP limiter tests with server enforcement

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(proxy): match main's MCP limiter tests

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): keep old private names bound in importing modules

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): preserve compatibility imports through strict lint

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(proxy): use exact pyright suppression in password helper test

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* style(proxy): add reasons to compatibility import noqa comments

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(proxy): update IN-list baseline for renamed helpers

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-07 18:59:27 -07:00
ishaan-berri
5531169710
feat(ui): add Moyai cloud coding agent to the view switcher (#45196)
* feat(ui): add Moyai cloud coding agent to the view switcher

Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>

* fix(ui): restore hover scale on Moyai GitHub CTA

Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-08 00:41:13 +00:00
devin-ai-integration[bot]
837c6a7481
fix(security): remove the publicly known master key from the repo (#44718)
* fix(security): hash the publicly known master key

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* docs: replace weak master key examples and regenerate artifacts

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test: replace weak key fixtures with generated test keys

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* ci: generate master keys for proxy startup

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix: preserve lens dev key entropy

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix: restore proxy key compatibility in scrub examples

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix: scrub merged SSO fixture and refresh dashboard bundle

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(ci): stabilize test keys and metadata collection

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* chore: drop the rebuilt dashboard bundle

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: mateo <mateo@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-06 10:55:24 -07:00
moyai-devin-berriai[bot]
75b45e39c9
fix(proxy): enforce internal-user model creation prohibition (#44438)
Co-authored-by: moyai-devin-berriai[bot] <336287033+moyai-devin-berriai[bot]@users.noreply.github.com>
2026-10-05 11:32:05 -07:00
devin-ai-integration[bot]
25109a523b
test(proxy): move utils, agent_endpoints and endpoint tests into tests/unit/proxy (#44006)
* test(proxy): move utils, agent_endpoints and endpoint tests into tests/unit/proxy

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(proxy): package moved unit test directories

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(proxy): exclude proxy-db-owned files from the misc target

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(proxy): drop the redundant fixture docstrings in the proxy conftest

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: yuneng <yuneng@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-01 11:06:42 -07:00