feat(manifest): add agent_provider.auth_token for Claude OAuth via egress

Operators can now declare:

  agent_provider:
    template: claude
    auth_token: BOT_BOTTLE_CLAUDE_OAUTH_TOKEN

and the provisioner injects a provider-owned api.anthropic.com egress
route (Bearer, tls_passthrough) rather than requiring a manually
declared route with the former claude_code_oauth role.

Changes:
- Add auth_token field to AgentProvider; validate claude-only.
- Remove claude_code_oauth from EGRESS_ROLES / PROVIDER_EGRESS_ROLES.
  Manifests that declare the role now fail at parse time with "unknown
  role" — the provisioner owns the route.
- agent_provision_plan: replace manifest_egress_routes/has_provider_auth
  with auth_token; Claude branch injects the api.anthropic.com route,
  placeholder env, and nonessential-traffic flags when auth_token is set.
- Add hidden_env_names: frozenset[str] to AgentProvisionPlan; Claude
  branch populates it with CLAUDE_CODE_OAUTH_TOKEN.
- Remove auth_role from AgentProviderRuntime and placeholder_env_for().
- print_util.visible_agent_env_names: accept hidden_env_names from the
  plan instead of dispatching on agent_provider_template.
- Both backends: drop manifest_egress_routes call, pass auth_token.
- PRD 0029 rescoped to cover both Codex and Claude provider auth.

Assisted-by: Claude Code
This commit is contained in:
2026-06-02 01:24:18 +00:00
committed by didericis
parent 952dcd7eec
commit de9bd7eb83
11 changed files with 136 additions and 113 deletions
+6 -10
View File
@@ -9,7 +9,6 @@ from __future__ import annotations
from typing import Sequence
from ..agent_provider import placeholder_env_for
from ..log import info
@@ -30,16 +29,13 @@ def print_multi(label: str, values: Sequence[str]) -> None:
def visible_agent_env_names(
env_names: Sequence[str], *, agent_provider_template: str,
env_names: Sequence[str], *, hidden_env_names: frozenset[str],
) -> list[str]:
"""Env names worth showing in launch summaries.
Provider auth placeholders (currently `CLAUDE_CODE_OAUTH_TOKEN`)
are implementation details: they are non-secret dummy values that
satisfy the provider CLI while egress injects the real upstream
Authorization header. Showing them in preflight makes the operator
think a real key is entering the agent, so hide only the active
provider-owned placeholder.
Provider-injected placeholder env vars are implementation details:
they are non-secret dummy values that satisfy provider CLIs while
egress injects the real Authorization header. The plan's
`hidden_env_names` carries exactly which names to suppress.
"""
hidden = {placeholder_env_for(agent_provider_template)}
return sorted({name for name in env_names if name and name not in hidden})
return sorted({name for name in env_names if name and name not in hidden_env_names})