Skip to content

fix(server): mirror personal API keys into OpenCode v2 - #6465

Merged
benjaminshafii merged 5 commits into
devfrom
fix/v2-local-provider-mirror
Oct 24, 2026
Merged

benjaminshafii merged 5 commits into
devfrom
fix/v2-local-provider-mirror

Conversation

@benjaminshafii

Copy link
Copy Markdown
Member

What is this about?

On OpenCode v2, API keys added in AI Providers (OpenRouter, OpenAI, Anthropic) reach the chat model picker, and AI Providers says when v2 can't use a provider.

What problem does it solve?

Personal keys never reached v2. Fixing only that would let any auth.json key reach v2 even when the organization allows only its own providers.

What was the situation before?

After saving an OpenRouter key, AI Providers listed nothing and the picker said "OpenRouter isn't connected in this workspace". A ChatGPT sign-in looked connected but was missing from chat.

How is this implemented?

  • opencode-v2-local-auth.ts translates v1's Provider.Info to the shape the mirror reads. Keys come only from auth.json; catalog keys, baseURL and headers are dropped; the trusted-origin check stays. Skips are reported as skippedProviders: [{id, reason}].
  • Security gate: organization-provider-gate.ts is the one rule for v1 enabled_providers and the v2 mirror, independent of the flag.
  • After a key save or sign-in, the server mirrors it and refreshes v1's provider list for that folder when idle.
  • AI Providers reads the skipped list; ProviderStatus gains a locked tone.
  • Behind localProviderMirror (cloud and self-hosted, off). Off keeps today's mirror.

What else changed?

  • CI runs the v2 provider mapping tests.

Release note

With "Only models you provide", providers added on a computer no longer reach the new engine's model picker, matching the classic engine.

Evidence

evals/proofs/v2-local-provider-mirror.proof.test.ts — before: the engine skips the saved key; after: Ready to use, OpenRouter in the picker, sign-in "Not available on the new engine yet", blocked row locked. Fails on dev at step 2.

dev this branch
dev: picker says OpenRouter isn't connected branch: OpenRouter models in the picker
branch: AI Providers ready branch: sign-in not available on the new engine yet
branch: Acme manages AI providers, locked branch: OpenRouter gone from the picker under the policy

Follow-up: ENG-888 (share with team, ask an admin, OAuth on v2).

Design: P1, P4, P5, C5, P10

The bundled OpenCode v1 answers GET /provider with Provider.Info: no
top-level npm or api, the package and endpoint live on each model, and
models describe capabilities. The v2 mirror read the models.dev shape,
so every key added in AI Providers (OpenRouter, OpenAI, Anthropic) was
skipped and never reached the chat model picker.

Behind localProviderMirror (off), the mirror translates Provider.Info,
keeps the trusted-origin check, never takes a key, baseURL or header
from the catalog, and reports every provider it does not mirror with a
reason (policy, oauth, unsupported, metadata, credentials) in a new
skippedProviders status field.

Independently of the rollout, "Only models you provide" now applies
to the v2 mirror the same way v1 applies enabled_providers: personal
providers, local or configured, never reach v2 when the organization
allows only its own. Both engines share one rule.

Signed-off-by: Benjamin Shafii <benjamin.shafii@gmail.com>
On the new engine, Settings › AI Providers reads the server's skipped
list instead of assuming every key on this device works: a provider the
organization does not allow keeps its row with a lock and
"<organization> manages AI providers", and a sign-in the new engine
cannot use yet reads "Not available on the new engine yet". A skipped
provider never shows Ready to use. Older servers and the rollout
switched off keep today's rows.

Signed-off-by: Benjamin Shafii <benjamin.shafii@gmail.com>
AI Providers lists providers from OpenCode v1, which caches them per
folder. On v2 the app no longer disposes v1 after saving a key, so a new
key stayed invisible in AI Providers until a restart. With the
localProviderMirror rollout, the server rebuilds v1's provider state for
the folder right after it mirrors the change into v2, never while v1 is
running work. Provider sign-in callbacks now trigger the same mirror.

The rollout is read from Den on every mirror with a short wait; a slow
or unreachable Den falls back to the answer last verified for the
sign-in, and cloud provider sync re-checks it so turning the rollout
off applies without a restart.

Signed-off-by: Benjamin Shafii <benjamin.shafii@gmail.com>
A signed-in Acme owner on v2 saves an OpenRouter key: with the rollout
off the engine drops it and the picker says OpenRouter isn't connected;
with it on, AI Providers reads Ready to use and the picker lists its
models. A ChatGPT sign-in reads Not available on the new engine yet,
and once Acme allows only its own providers OpenRouter leaves the
picker while its row stays with a lock.

Signed-off-by: Benjamin Shafii <benjamin.shafii@gmail.com>
Adds the author and internal docs link the registry now requires, with
screenshots of the picker and AI Providers states from the proof run.

Signed-off-by: Benjamin Shafii <benjamin.shafii@gmail.com>
@vercel

vercel Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
openwork-app Ready Ready Preview Oct 24, 2026 1:21am UTC
openwork-den Ready Ready Preview Oct 24, 2026 1:21am UTC
openwork-diagnostics Ready Ready Preview Oct 24, 2026 1:21am UTC
openwork-landing Ready Ready Preview, v0 Oct 24, 2026 1:21am UTC

Request Review

@benjaminshafii benjaminshafii changed the title fix(server): mirror personal API keys into OpenCode v2 behind a policy gate fix(server): mirror personal API keys into OpenCode v2 Oct 24, 2026
@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

OpenWork evidence

Status Commit Preview Updated
🔴 Preview unavailable 4911832 View run 2026-10-24 01:52:55 UTC

Evidence run interrupted

@diff-warden diff-warden Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warden clearance. Complete security and confidentiality review of 491183238ca0ed1422b51f27407bf59a95b73b20 found no high or medium security findings and no confidentiality findings. Any new push dismisses this approval. Analysis run

@diff-warden

diff-warden Bot commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

Warden: approved

No high or medium security findings and no confidentiality findings.

Reviewed 491183238ca0 · Warden run · Updates after every Warden run.

@benjaminshafii
benjaminshafii marked this pull request as ready for review October 24, 2026 13:19
@benjaminshafii
benjaminshafii merged commit 6159b3a into dev Oct 24, 2026
49 of 52 checks passed
@benjaminshafii
benjaminshafii deployed to pr-internal-specs October 24, 2026 13:20 — with GitHub Actions Active

This branch was successfully deployed

5 active deployments
Preview – openwork-app — 49118323 Deployed Oct 24, 2026 by vercel[bot]
Preview – openwork-den — 49118323 Deployed Oct 24, 2026 by vercel[bot]
Preview – openwork-landing — 49118323 Deployed Oct 24, 2026 by vercel[bot]
Preview – openwork-diagnostics — 49118323 Deployed Oct 24, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant