fix(tools): scope builtin tool default-credential clear to tenant#35887
Merged
Conversation
When two workspace members each set their own credential as the default for the same provider, both rows ended up with is_default=True for the same (tenant_id, provider). The clear UPDATE was filtered by user_id, so it only reset the caller's own defaults and left other members' defaults intact. The consumer (`get_builtin_provider`) is tenant-scoped and picks an arbitrary winner via the created_at tiebreak when multiple defaults exist, producing user-visible inconsistencies. Drop user_id from the clear filter so default selection becomes properly tenant-scoped, matching `DatasourceProviderService.set_default_datasource_provider`. Adds a regression test that asserts the compiled UPDATE WHERE clause contains tenant_id/provider but not user_id.
Contributor
Pyrefly Type Coverage
|
3 tasks
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #35887 +/- ##
==========================================
+ Coverage 85.80% 85.81% +0.01%
==========================================
Files 4456 4462 +6
Lines 208899 208769 -130
Branches 39075 38961 -114
==========================================
- Hits 179242 179159 -83
+ Misses 26482 26434 -48
- Partials 3175 3176 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
wylswz
reviewed
May 8, 2026
wylswz
approved these changes
May 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
is_default=Truefor the same(tenant_id, provider).clear-defaultUPDATE inBuiltinToolManageService.set_default_providerwas filtered byuser_id, so it only reset the caller's own defaults. The consumer (get_builtin_provider) is tenant-scoped and breaks ties viacreated_at, producing user-visible inconsistencies (UI shows credential B as default while runtime uses credential A).user_idfrom the clear filter, mirroringDatasourceProviderService.set_default_datasource_provider. Theis_defaultflag is now correctly tenant-scoped (one default per provider per workspace).Reproduction
cred1(provider P), sets it as defaultcred2(provider P), sets it as defaultis_default=True— DB has two defaults for the same(tenant_id, provider)Reproduced on production and on
console-platform.dify.dev.Test plan
TestSetDefaultProvider::test_clear_default_is_tenant_scoped_not_user_scoped— asserts the compiled UPDATE WHERE clause containstenant_id/providerbut notuser_id. Verified failing on pre-fix code, passing on fixed code.TestSetDefaultProvidertests still pass.Notes
is_default=Truerows in a narrow window). A partial unique indexUNIQUE (tenant_id, provider) WHERE is_defaultwould close this — out of scope here, flagging for follow-up.lts/1.13.xin a separate PR.user_idparameter retained onset_default_providersignature: still passed by the controller via kwargs and may be used by EE callers; removing it would be a breaking change for kwarg callers.