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
@time-attack

Copy link
Copy Markdown

This appears more precise than #267 because it checks actual harness-carried authentication rather than the harness name alone. Please rebase and run current CI; if it remains green, I recommend treating this as canonical for the harness-readiness portion of #290/#268. @16francej, can you confirm the preferred implementation?

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.

4 participants