Split launch() into named per-step helpers, replace time.sleep(1.5) with
a readiness poll, and file-lock loopback alias allocation. Addresses the
three actionable items from the #117 hotspot review of smolmachines/launch.py.
Expands scope to cover both remaining egress hotspot tasks from #117:
- Replaces the named-helper design with a flat provisioned-wins merge
(provider routes own their hosts; manifest fills gaps; no upgrade or
conflict-detection logic needed).
- Adds _route_to_yaml_fields as the single authoritative EgressRoute→Route
mapping to prevent silent type drift between host and addon.
- Notes that the mitmproxy pure-function split is already clean (decide +
is_git_push_request) and requires no structural change.
Revises the Design section to describe the implemented solution:
provisioned_env on AgentProvisionPlan rather than an intermediate
egress_resolve_token_values_with_provider function. Drops the old
sentinel/lazy-import design narrative.
Extracts the forward_host_credentials / CODEX_HOST_CREDENTIAL_TOKEN_REF
resolution block, currently copy-pasted in both docker and smolmachines
launch files, into a single shared function in bot_bottle/egress.py.
Closes#118. Found via #117 hotspot review.
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
Debugging a live codex smolmachines bottle surfaced three independent
failures past the sign-in screen; fix each so forward_host_credentials
works end to end:
- codex_auth: dummy access/id tokens now inherit the *real* host token's
exp instead of now+1h. Codex (0.135) refreshes when its local token's
JWT exp lapses; with a placeholder refresh_token that refresh fails and
drops to the sign-in screen. Aligning exp tracks the real token's life.
- prepare: set CODEX_CA_CERTIFICATE to the agent CA bundle for codex
bottles. Codex is rustls and ignores the system store / NODE_EXTRA_CA_
CERTS; it reads CODEX_CA_CERTIFICATE (fallback SSL_CERT_FILE) for custom
roots across HTTPS + wss, so it must be pointed at the egress MITM CA or
injection can't work without tls_passthrough.
- pipelock: auto tls_passthrough the Codex API hosts when
forward_host_credentials is on. Egress injects the bearer before
pipelock, whose header DLP then flags the JWT ("request header contains
secret") and the retry storm trips its 429. passthrough host-gates the
CONNECT but skips decrypt+rescan of egress-owned auth. The auto-added
routes aren't in bottle.egress.routes, so the hosts are added explicitly.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
git-gate's pre-receive scans the full ancestry of a new branch, so the
repo's historical test-fixture findings block every new-branch push
(issue #106). Scope the new-ref scan to incoming commits
(`$new --not --all`) with no loss of coverage, and harden the forward
ssh against hangs.
Refs #106
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
We use Gitea, not an abstract forge. Reword the docs added in this
branch: "forge thread" -> "Gitea thread", and the research note's
generic "forge" -> "Gitea" / "hosting provider" as context demands,
keeping its portability argument coherent.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Remove the one-line docs/INDEX.md (its directory pointers are covered
by docs/README.md's "when to write which document" table). Add
docs/prds/README.md documenting the PRD naming, Status lifecycle, and
section format. Repoint the AGENTS.md repository-layout list at the
new READMEs and add the decisions/ dir.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add an "Alternatives considered" section enumerating the design
options from issue #88 (duplicate bottles / agent-side bottle_config
/ bottle-side extends) and why extends won, so the PRD stands without
the forge thread. Repoint the two phrases that depended on the #88
comment thread at the new section.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
We use Gitea, not an abstract forge. Reword the pre-existing research
and PRD docs: the generic "Forge-API gate"/"forge tokens" become
"Git-host-API gate"/"Git-host tokens" (the gate still spans Gitea /
GitHub / GitLab), "Git/forge history" -> "Git/Gitea history", and the
KNOWN_FORGE_HOSTS / forge: manifest-field examples -> KNOWN_GIT_HOSTS
/ git_host:. Meaning preserved; only the word "forge" is dropped.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Flip Status: Draft -> Active for the 23 PRDs whose work has shipped to
main (including 0027, now that PR #95 has merged). Leaves the
terminal-status PRDs unchanged: 0007 and 0010 (Superseded) and 0014
(Retargeted) were replaced, not shipped as-is.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Lift git.user (name/email) to the agent layer with a per-field
overlay onto the referenced bottle, mirroring the extends: merge.
git.remotes stays bottle-only. Includes identity provenance in
preflight/info and an example collapse.
Refs #94
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>