Skip to content

fix: project-only provider_access must not hide user-level providers - #6601

Closed
ttmouse wants to merge 2 commits into
esengine:main-v2from
ttmouse:fix/model-menu-project-custom
Closed

fix: project-only provider_access must not hide user-level providers#6601
ttmouse wants to merge 2 commits into
esengine:main-v2from
ttmouse:fix/model-menu-project-custom

Conversation

@ttmouse

@ttmouse ttmouse commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Summary

When the user config (~/.reasonix/config.toml) does not declare desktop.provider_access (implicit "allow all"), a project-level reasonix.toml that defines provider_access currently restricts the desktop model switcher to only those listed providers — hiding the user-level providers that exist outside the project-scoped access list.

Root cause: mergeTOMLProviderAccess merges provider_access as a union across config sources. When only the project config declares it (user config does not), the union equals the project's list alone. The user's default "allow all" is lost.

Fix: Track whether the user-level config explicitly declared provider_access. If only the project declares it (user did not), skip the restriction so all configured providers remain visible in the model switcher.

Verification

  • TestMergeTOMLProviderAccessProjectOnlyDoesNotRestrictWhenUserUndefined — NEW: project-only restriction is correctly skipped
  • TestMergeTOMLProviderAccessUserAndProjectMergeAsUnion — NEW: both user and project declare → union merge unchanged
  • TestMergeTOMLProviderAccessNoDeclarations — NEW: neither declares → no restriction
  • TestMergeTOMLProviderAccessUserDeclaresEmptyList — NEW: user declares [], project has list → project list takes effect (user explicitly opted into per-project control)
  • TestModelsForTabKeepsUserProvidersWithProjectConfig — EXISTING PASS: user + project both declare → union unchanged
  • go test ./internal/config/... — all pass
  • go build ./... — all pass

Cache impact

Cache-impact: none — only a small logic change in config loading, no system prompt or provider changes
Cache-guard: existing config tests and desktop ModelsForTab tests cover the behavior
System-prompt-review: N/A

Related PRs


🤖 This contribution was prepared with Reasonix (DeepSeek fork of Claude Code), no additional plugins installed.

ttmouse added 2 commits July 16, 2026 18:08
When the user config does not declare desktop.provider_access (implicit
'allow all'), a project-level provider_access restriction should not
override it. The mergeTOMLProviderAccess function now tracks whether
the user config explicitly declares the list; if only the project
config does, the restriction is skipped so account-level providers
remain visible in the desktop model switcher.

Fixes: project-level reasonix.toml with provider_access hiding
user-configured providers that are not in the project's access list.
Add four unit tests for mergeTOMLProviderAccess:

1. TestMergeTOMLProviderAccessProjectOnlyDoesNotRestrictWhenUserUndefined
   — core scenario: user has no provider_access (implicit allow all),
     project declares a restricted list. Must return ok=false.
2. TestMergeTOMLProviderAccessUserAndProjectMergeAsUnion
   — both user and project declare provider_access: union merged.
3. TestMergeTOMLProviderAccessNoDeclarations
   — neither declares: ok=false, no restriction.
4. TestMergeTOMLProviderAccessUserDeclaresEmptyList
   — user explicitly declares [] (allow all but declared), project
     has a list: ok=true, project restriction takes effect.
@github-actions github-actions Bot added v2 Go rewrite (1.x) — main-v2 branch, active development config Configuration & setup (internal/config) labels Jul 17, 2026
@esengine

esengine commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Thanks — the diagnosis is right and the fix is the correct shape. An undeclared user-level provider_access means "allow all", and unioning it with a project-only declaration silently narrows the switcher to whatever the project happens to name. That's exactly the case #4492's union was meant to prevent and didn't.

I've landed it as #7395 rather than merging this branch: mergeTOMLProviderAccess was reworked after you opened this (statConfigPath, meta.IsDefined on the declaration, explicit-empty preservation), so the diff no longer applies. Your approach and the userDeclared guard carried over as-is, and you're credited as co-author on the commit.

One semantic call I made on top of your version: TestMergeTOMLProviderAccessPreservesExplicitEmpty now writes to the user config path. Explicit-empty ("I removed every provider") stays meaningful where it can be expressed — the user config — while a project's empty list no longer blanks the switcher, which follows from the same rule.

Closing this in favour of #7395. Thanks for the careful root-cause write-up — it made the port trivial.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

config Configuration & setup (internal/config) v2 Go rewrite (1.x) — main-v2 branch, active development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants