fix: gate LLM features for users without an assigned model#568
Merged
Conversation
IliaAvdeev
force-pushed
the
fix/capability-access-gating
branch
from
June 13, 2026 19:26
755e073 to
a40a525
Compare
The turn path (chat/partners/mastery via turn_runtime) already enforces LLM-grant access at its single enforcement point and surfaces a clear terminal "no model assigned" rejection — so require_llm_access was never wired to any endpoint and only duplicated that logic. Drop it (and its guard-only tests) and have turn_runtime reuse has_capability_access, giving the gate one source of truth shared with the frontend lock. Frontend fixes kept from the original PR plus two corrections: - capabilityForPath now matches on a path-segment boundary, so a sibling route like /booket can't be swallowed by the /book prefix (+ regression). - fix the misleading Knowledge sidebar comment — Knowledge needs no per-user grant and is never gated. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Collaborator
|
Thanks for your contribution. I think this is great, i'll do the rest and merge it~ |
vaskoyudha
added a commit
to vaskoyudha/deeptutor-for-programmer-fork
that referenced
this pull request
Jul 25, 2026
…ting fix: gate LLM features for users without an assigned model
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.
Description
A non-admin user with no LLM model assigned could open Chat / Partners / etc.
but silently failed: the turn died into an empty "Delete"-only bubble and the
conversation stayed stuck on "New chat", with no hint that an admin must assign
a model first.
This PR replaces that dead-end with a single capability-access gate applied
across every LLM-consuming surface, so an unprovisioned user sees a clear,
locked UI instead of a broken one.
Frontend
CapabilityAccessProviderprobes/api/v1/settings(catalog presence = adminsignal) plus the grant-filtered
/api/v1/settings/llm-options, and exposeshas(capability). It re-checks on tab focus/visibility, so a mid-session grantchange is reflected without polling.
CapabilityGate+RequireCapabilitylock LLM feature pages (Chat, Partners,Co-Writer, Book, Mastery Path, Playground) with a "contact your administrator"
notice. Sidebar entries for locked features render greyed with a lock badge and
do not navigate.
web/lib/capability-routes.ts, so anew gated feature is declared in a single place.
Backend (defense in depth — the UI gate can be bypassed)
has_capability_access()helper, admin-aware, matching the redacted model viewthe frontend reads.
require_llm_accessdependency returning a typed403withcode: "NO_MODEL_ACCESS".Related Issues
Module(s) Affected
agentsapiconfigcoreknowledgeloggingservicestoolsutilsweb(Frontend)docs(Documentation)scriptstestsmulti_userChecklist
pre-commitand fixed any issues (ruff, ruff-format, prettier, mypy, bandit, detect-secrets all pass on the changed files).Additional Notes
Screenshots
Before — an unprovisioned user hit a dead chat: the turn failed into a
"Delete"-only bubble and the sidebar stayed stuck on "New chat":
After — feature page is locked with a clear "contact admin" notice:
After — sidebar shows LLM features greyed with a lock; Knowledge / Space /
Memory stay reachable:
tests/multi_user/test_capability_access.py(7/7) covershas_capability_accessand therequire_llm_accessguard; frontendweb/tests/capability-access.test.ts(3/3) coverscapabilityForPath.zhtranslationscan follow via
i18n:audit.