Skip to content

Wire all secret callers to scoped and user providers#4465

Merged
amirejaz merged 6 commits intomainfrom
phase3-wire-callers
Apr 1, 2026
Merged

Wire all secret callers to scoped and user providers#4465
amirejaz merged 6 commits intomainfrom
phase3-wire-callers

Conversation

@amirejaz
Copy link
Copy Markdown
Contributor

@amirejaz amirejaz commented Mar 31, 2026

Summary

Type of change

  • New feature or functionality

Changes

File Change
cmd/thv/app/registry_login.go Use WithScope(ScopeRegistry) for registry login credential storage
cmd/thv/app/header_flags.go Use WithUserFacing() for user-facing header flag secret reads
cmd/thv/app/secret.go Use WithUserFacing() for user-facing secret management commands
pkg/api/v1/secrets.go Use WithUserFacing() for REST API secret endpoints
pkg/auth/secrets/secrets.go Use WithScope(ScopeWorkloads) for workload auth tokens
pkg/mcp/server/list_secrets.go Use WithUserFacing() for MCP list_secrets tool
pkg/mcp/server/set_secret.go Use WithUserFacing() for MCP set_secret tool
pkg/runner/env.go Use WithUserFacing() for env var secret injection
pkg/runner/protocol.go Use WithScope(ScopeWorkloads) for protocol-level workload secrets
pkg/runner/runner.go Use WithUserFacing() for runner secret access
pkg/workloads/manager.go Use WithScope(ScopeWorkloads) for workload manager secret access
pkg/secrets/scoped.go Add migration window fallback in ScopedProvider.GetSecret (from #4386)
pkg/secrets/scoped_test.go Tests for fallback behaviour and scope invariants

Does this introduce a user-facing change?

User-facing thv secret commands now reject any key name starting with __thv_ with a clear error message. Internal workload secrets (registry tokens, OAuth refresh tokens) are transparently namespaced under __thv_<scope>_<name> and are invisible to user commands.

Test plan

  • Unit tests pass (task test)
  • E2E tests for thv secret commands verify that __thv_* keys are blocked
  • Build succeeds (task build)

Generated with Claude Code

amirejaz and others added 5 commits March 31, 2026 20:36
When a user upgrades ToolHive, system secrets may still exist under
bare keys (e.g. BEARER_TOKEN_foo) until the secret scope migration
completes. If migration fails or hasn't run yet, ScopedProvider
callers would be unable to find their secrets under the new scoped
key (__thv_workloads_BEARER_TOKEN_foo), breaking workload auth.

Add a transparent fallback in ScopedProvider.GetSecret: on a
not-found response for the scoped key, also try the bare (pre-
migration) key. Once migration completes and bare keys are deleted,
the fallback finds nothing and becomes a natural no-op — no config
check or injection needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add t.Parallel() to TestScopedProvider_GetSecret_MigrationFallback and
its subtests to satisfy the paralleltest linter requirement.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Update every call site that creates a secrets provider to use the
appropriate wrapper introduced in Phase 1:

- System callers (workload auth tokens, registry credentials, build auth
  files) now use CreateScopedSecretProvider, placing secrets under the
  __thv_<scope>_ prefix and hiding them from user-facing commands.
- User-facing callers (thv secret commands, REST API, MCP tool server,
  header secrets, build-env-from-secrets) now use CreateUserSecretProvider,
  blocking access to __thv_* reserved keys.
- RunConfig.WithSecrets and ValidateSecrets now accept separate system and
  user providers so auth-token resolution and --secret flag resolution use
  the correct scope independently.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Verify that the UserProvider wiring in CLI secret commands correctly
blocks access to __thv_* keys:

- set with __thv_ prefix is rejected
- get with __thv_ prefix is rejected with "reserved for system use"
- delete with __thv_ prefix is rejected
- two distinct __thv_ key names are blocked, confirming the check is
  not tied to a single hardcoded name

Each test uses an isolated XDG_CONFIG_HOME/HOME temp directory so the
user's real secrets store is never touched.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add GetUserSecretsProvider() to pkg/auth/secrets alongside the
  existing GetSecretsManager(), centralising the config-read +
  CreateUserSecretProvider boilerplate in one place

- Remove getScopedWorkloadsSecretsManager() from config_buildauthfile.go;
  it was identical to authsecrets.GetSecretsManager() — use that directly

- Replace inline boilerplate in config_buildenv.go/validateSecretExists
  and secret.go/getSecretsManager with calls to GetUserSecretsProvider(),
  eliminating duplicated setup-check + provider-create blocks

- Rename local variable manager → provider in GetSecretsManager() to
  match the naming convention used throughout the new provider code

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot added size/M Medium PR: 300-599 lines changed and removed size/M Medium PR: 300-599 lines changed labels Mar 31, 2026
@amirejaz amirejaz requested a review from reyortiz3 March 31, 2026 15:44
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 31, 2026

Codecov Report

❌ Patch coverage is 31.91489% with 32 lines in your changes missing coverage. Please review.
✅ Project coverage is 69.64%. Comparing base (e69251a) to head (8dabc6a).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
pkg/auth/secrets/secrets.go 0.00% 15 Missing ⚠️
pkg/runner/runner.go 0.00% 6 Missing ⚠️
pkg/runner/config.go 66.66% 2 Missing and 1 partial ⚠️
pkg/runner/protocol.go 0.00% 2 Missing ⚠️
pkg/workloads/manager.go 0.00% 2 Missing ⚠️
pkg/api/v1/secrets.go 0.00% 1 Missing ⚠️
pkg/mcp/server/list_secrets.go 0.00% 1 Missing ⚠️
pkg/mcp/server/set_secret.go 0.00% 1 Missing ⚠️
pkg/runner/env.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4465      +/-   ##
==========================================
- Coverage   69.64%   69.64%   -0.01%     
==========================================
  Files         491      491              
  Lines       50304    50327      +23     
==========================================
+ Hits        35036    35050      +14     
- Misses      12580    12595      +15     
+ Partials     2688     2682       -6     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
Replace CreateUserSecretProvider and CreateScopedSecretProvider with
the new CreateProvider(managerType, WithUserFacing()) and
CreateProvider(managerType, WithScope(scope)) API introduced in the
phase2-factory-helpers PR.

Affected callers:
- cmd/thv/app/registry_login.go
- cmd/thv/app/header_flags.go
- pkg/auth/secrets/secrets.go
- pkg/runner/env.go
- pkg/runner/runner.go
- pkg/runner/protocol.go
- pkg/mcp/server/set_secret.go
- pkg/mcp/server/list_secrets.go
- pkg/workloads/manager.go
- pkg/api/v1/secrets.go

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@amirejaz amirejaz force-pushed the phase3-wire-callers branch from d9168dc to 8dabc6a Compare March 31, 2026 16:16
@github-actions github-actions bot added size/M Medium PR: 300-599 lines changed and removed size/M Medium PR: 300-599 lines changed labels Mar 31, 2026
@amirejaz amirejaz merged commit 03ae494 into main Apr 1, 2026
52 of 53 checks passed
@amirejaz amirejaz deleted the phase3-wire-callers branch April 1, 2026 09:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/M Medium PR: 300-599 lines changed

3 participants