Skip to content

Count harness-carried model auth in surface config and admin onboarding - #128

Open
haramiya wants to merge 1 commit into
yc-software:mainfrom
haramiya:claude/unruffled-shaw-9b122a
Open

Count harness-carried model auth in surface config and admin onboarding#128
haramiya wants to merge 1 commit into
yc-software:mainfrom
haramiya:claude/unruffled-shaw-9b122a

Conversation

@haramiya

@haramiya haramiya commented Aug 2, 2026

Copy link
Copy Markdown

Bug

Running HARNESS=claude on a Claude subscription (CLAUDE_CODE_OAUTH_TOKEN from claude setup-token, no ANTHROPIC_API_KEY) serves turns fine, but the deployment tells everyone it isn't set up:

  • /v1/surface-config reports modelProviderConfigured: false, so the portal 503s non-admins and bounces admins to onboarding (Route the first admin to onboarding instead of a 403 web UI #29's gate).
  • The admin onboarding view says Needs a key / "claude-opus-5 cannot run until its Anthropic key is configured" — while the assistant answers happily underneath.

Root cause: both read only the model credential store, which counts anthropic/openai/openrouter API keys (env or admin-managed) and knows nothing about auth the harness carries itself. #67 and #109 both hit this and proposed fixes at different layers.

Fix

harnessCarriedModelAuth(config) in src/config.ts names the provider a harness authenticates on its own:

  • claudeanthropic when CLAUDE_CODE_OAUTH_TOKEN or ANTHROPIC_AUTH_TOKEN is in claudeProcessEnv
  • codexopenai when CODEX_ACCESS_TOKEN is in codexProcessEnv
  • otherwise undefined (env API keys are already counted through the credential store's fallback, so they aren't double-counted here)

Wired as an optional ServerDeps.harnessCarriedModelAuth and surfaced at the two places that were lying:

  • Surface gate: getSurfaceConfig ORs it into modelProviderConfigured. Unlike making modelProviderAvailabilityFor unconditionally report claude as available (adr: smaller fix for the keyless-harness model gate #109's noted downside), a claude deployment with no token anywhere still reports unconfigured and keeps the onboarding gate.
  • Admin API: GET /v1/admin/model-providers gains a sibling harnessAuth: { harnessId, provider } field. The credential-store providers statuses are deliberately untouched — anthropic keeps reporting absent when no key is stored, because those keys feed pi-transport calls and adding/deleting them is independent of harness OAuth. Old admin UI against new core ignores the extra field; new UI against old core sees no harnessAuth and behaves exactly as before (blue-green safe).
  • Admin onboarding view: the model-provider step shows Ready when the base model's provider is store-configured or harness-authenticated, with the summary "claude-opus-5 · authenticated by the claude harness — no API key needed." Stored-key summaries keep precedence; the key form stays usable for feeding pi-transport.

Screenshots

Admin → Onboarding, HARNESS=claude with only CLAUDE_CODE_OAUTH_TOKEN:

Before After
before after

Rendered against the admin page served with realistic stubbed API fixtures (the machine's only dev-instance Slack slot was held by another live instance, so this wasn't exercised on a booted stack; the same states are covered by the tests below).

Tests

  • test/model-credential-route.test.ts: claude harness + OAuth token → modelProviderConfigured: true, harnessAuth: { harnessId: "claude", provider: "anthropic" }, and the anthropic status still { configured: false, source: "absent" }; claude harness with no token → still unconfigured, no harnessAuth field. start() now derives the dep from the test config the same way src/index.ts does.
  • plugins/admin/test/onboarding-view.test.ts: runs the real loadOnboarding() (vm-extracted from index.html) against stubbed endpoints — harness auth alone → Ready badge + harness summary; no harness auth → Needs a key; stored admin key + harness auth → Ready with the stored-key summary.

Verification

  • test/model-credential-route.test.ts 13/13, test/external-slack-participants.test.ts + test/admin-resources.test.ts 20/20, plugins/admin onboarding suite 7/7
  • tsc --noEmit (root and plugins/admin), eslint ., prettier --check — clean (lint:ox has a pre-existing missing-native-binding failure locally; CI covers it)
  • Independent fresh-context adversarial review of the diff — findings resolved before merge

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

…oarding

Under HARNESS=claude with only CLAUDE_CODE_OAUTH_TOKEN (or ANTHROPIC_AUTH_TOKEN),
turns work but the deployment reported itself unconfigured: surface-config's
modelProviderConfigured only consulted the credential store, and the admin
onboarding badge said 'Needs a key'.

harnessCarriedModelAuth(config) names the provider a harness authenticates on
its own (claude -> anthropic via OAuth/auth token, codex -> openai via
CODEX_ACCESS_TOKEN). It is OR'd into modelProviderConfigured and exposed to the
admin as a sibling harnessAuth field on GET /v1/admin/model-providers. The
credential-store statuses stay untouched: anthropic still reports absent,
because those keys feed pi-transport calls and deleting or adding them is
independent of harness OAuth.
@16francej 16francej added code-pr Code submitted instead of an ADR bug Something isn't working labels Aug 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working code-pr Code submitted instead of an ADR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants