Operator limits: managed key mode with the operator's own LLM key
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 25/100
- Issue type
- Feature
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- typescript
Research direction
Start with src/llm/resolve.ts (resolveWorkspaceLlmAccess) and src/secrets/names.ts, then read docs/decisions/0001-editions-setup-and-accounts.md section 2.8. The issue depends on #271, so check that first. Done when unit tests T01-T05 pass for the resolver, and the integration tests T06-T10 cover the admin form, the operator API refusal, claim masking and the managed settings note.
Written by the indexing model from the issue text.
Description
Part of #268. Depends on #271.
Problem
src/llm/resolve.ts resolves a job's LLM access: the workspace's own key, then "the operator's key, if the operator offers included usage" — a stub that is off (operator is always null; docs/decisions/0001-editions-setup-and-accounts.md, section 2.8 reserved the place). There is no way for an operator to store a key of its own, and no way to say that a workspace uses it instead of its own.
Behavior
- A new secret
operator_llm_keyin the encrypted store (src/secrets/names.ts), entered by the instance admin in the admin portal (write-only, status and last four characters only, exactly like the other credentials; provider OpenRouter). It is not settable through the operator API: whoever holds the API token must not hold the key. resolveWorkspaceLlmAccessgets its second step:- Effective entitlements
key_mode = managedand an operator key present: the job uses the operator's key (sourceoperator). The workspace's own stored key is ignored (not deleted). key_mode = managedand no readable operator key: fail closed withllm_not_configuredand the new reasonoperator_key_missing(oroperator_key_unreadable). Never falls back to the workspace key: the entitlement says which key is used.key_mode = own, no entitlements at all, or an instance with no operator key: exactly today's behavior. The operator key is never used for a workspace that is notmanaged.
- Effective entitlements
- The key never reaches a workspace member, the browser, a log line or a result: the claim response carries it to the runner as the workspace key does today, it is remembered encrypted for masking in
job_claimed_keys, andmaskSecretInTextmasks it in results. - The workspace's LLM access settings page shows, for a
managedworkspace, that access is provided by the instance and hides the key form; the routes that save, test or remove a workspace key keep working (the key is simply not used while managed). - Instance admin overview shows whether the operator key is configured.
Scope
Secret name, admin portal form (reuse the secret form pattern of SMTP), resolver, assemble/shared wiring, the workspace settings message, masking, docs (src/llm/README.md, the decision record section 2.8 gets an addendum), tests.
Out of scope
Limits (#277), tiers (#280), per-workspace sub-keys, other providers.
Test cases
| ID | kind | level | case | expected |
|---|---|---|---|---|
| T01 | regression | unit | no entitlements, a workspace key, an operator key configured | workspace key used; operator key untouched |
| T02 | behavior | unit | managed, operator key present, workspace key present |
operator key used, source operator |
| T03 | negative | unit | managed, no operator key |
llm_not_configured / operator_key_missing, workspace key not used |
| T04 | negative | unit | managed, operator key unreadable (another APP_SECRET) |
fails closed, operator_key_unreadable |
| T05 | behavior | unit | key_mode = own or unlimited, operator key configured |
operator key never used, even with no workspace key (no_key) |
| T06 | security | integration | admin saves the operator key | stored encrypted; no answer, page, log or error holds it; only status and last four |
| T07 | security | integration | a non-admin and the operator API | cannot read or write the operator key |
| T08 | security | integration | claim of a managed job | key delivered to the runner only; masked in a stored result |
| T09 | behavior | integration | workspace settings of a managed workspace | no key form, a note that access is provided; Member sees the same note |
| T10 | regression | integration | the existing claim and key route suites | unchanged |
- Dominant language
- TypeScript
- Stars
- 0
- Forks
- 1
- Avg merge
- 1h 18m
- Merged PRs (30d)
- 186
Getting set up
- Ships a Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from ExpidetGames/code-reviewer
-
area: app type: bug
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
ExpidetGames/code-reviewer#308 ·
Maintainers usually reply within 1 day
-
type: docs
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
ExpidetGames/code-reviewer#94 ·
Maintainers usually reply within 1 day
-
area: app post-mvp type: feature
Difficulty 5/5 Over a week Newbie friendliness 12/100
ExpidetGames/code-reviewer#339 ·
Maintainers usually reply within 1 day
-
area: runner post-mvp type: feature
Difficulty 5/5 Over a week Newbie friendliness 18/100
ExpidetGames/code-reviewer#338 ·
Maintainers usually reply within 1 day
-
area: runner post-mvp type: feature
Difficulty 5/5 Over a week Newbie friendliness 12/100
ExpidetGames/code-reviewer#337 ·
Maintainers usually reply within 1 day
All issues in ExpidetGames/code-reviewer
Similar issues
-
documentation good first issue
Difficulty 2/5 Half a day Newbie friendliness 72/100
sujithputta02/Esapay#13 ·
-
Share dialog: the address book's contact count reads "1 contacts" (no singular form in any language)Possibly taken @chibenwa claimed this today. Openai-driven-qa bug claude Cosmetic
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
linagora/twake-contacts-frontend#271 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Koenkk/zigbee2mqtt#33402 ·
Maintainers usually reply within 1 day
-
dx P2 platform Stellar Wave Wave 10
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
winsznx/routedock#579 · 1 comment ·
Maintainers usually reply within 1 day
-
area:ui effort:S enhancement priority:P2
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day