feat(workspace): trust resolved project path
This commit is contained in:
@@ -7,6 +7,7 @@ command, default image, and prompt/auth behavior.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
@@ -136,9 +137,11 @@ def agent_provision_plan(
|
||||
auth_token: str = "",
|
||||
forward_host_credentials: bool = False,
|
||||
host_env: dict[str, str] | None = None,
|
||||
trusted_project_path: str = "",
|
||||
) -> AgentProvisionPlan:
|
||||
runtime = runtime_for(template)
|
||||
resolved_guest_env = dict(guest_env or {})
|
||||
trusted_path = trusted_project_path or guest_home
|
||||
env_vars: dict[str, str] = {}
|
||||
provisioned_env: dict[str, str] = {}
|
||||
dirs: list[AgentProvisionDir] = []
|
||||
@@ -156,8 +159,9 @@ def agent_provision_plan(
|
||||
dirs.append(AgentProvisionDir(auth_dir))
|
||||
config_path = f"{auth_dir}/config.toml"
|
||||
config_file = state_dir / "codex-config.toml"
|
||||
toml_path = trusted_path.replace("\\", "\\\\").replace('"', '\\"')
|
||||
config_file.write_text(
|
||||
f'[projects."{guest_home}"]\n'
|
||||
f'[projects."{toml_path}"]\n'
|
||||
'trust_level = "trusted"\n'
|
||||
)
|
||||
config_file.chmod(0o600)
|
||||
@@ -202,6 +206,19 @@ def agent_provision_plan(
|
||||
if template == PROVIDER_CLAUDE:
|
||||
env_vars["CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC"] = "1"
|
||||
env_vars["DISABLE_ERROR_REPORTING"] = "1"
|
||||
claude_config = state_dir / "claude.json"
|
||||
claude_projects = {
|
||||
guest_home: {"hasTrustDialogAccepted": True},
|
||||
}
|
||||
claude_projects[trusted_path] = {"hasTrustDialogAccepted": True}
|
||||
claude_config.write_text(json.dumps({
|
||||
"hasCompletedOnboarding": True,
|
||||
"theme": "dark",
|
||||
"bypassPermissionsModeAccepted": True,
|
||||
"projects": claude_projects,
|
||||
}, indent=2) + "\n")
|
||||
claude_config.chmod(0o600)
|
||||
files.append(AgentProvisionFile(claude_config, f"{guest_home}/.claude.json"))
|
||||
egress_routes.append(EgressRoute(
|
||||
host="api.anthropic.com",
|
||||
auth_scheme="Bearer" if auth_token else "",
|
||||
|
||||
@@ -184,6 +184,7 @@ def resolve_plan(
|
||||
forward_host_credentials=provider.forward_host_credentials,
|
||||
auth_token=provider.auth_token,
|
||||
host_env=dict(os.environ),
|
||||
trusted_project_path=workspace_plan.workdir,
|
||||
)
|
||||
guest_env = dict(agent_provision.guest_env)
|
||||
for key, val in agent_provision.env_vars.items():
|
||||
|
||||
@@ -138,6 +138,7 @@ def resolve_plan(
|
||||
forward_host_credentials=provider.forward_host_credentials,
|
||||
auth_token=provider.auth_token,
|
||||
host_env=dict(os.environ),
|
||||
trusted_project_path=workspace_plan.workdir,
|
||||
)
|
||||
merged_guest_env = dict(agent_provision.guest_env)
|
||||
for key, val in agent_provision.env_vars.items():
|
||||
|
||||
@@ -31,6 +31,7 @@ class TestAgentProviderRuntime(unittest.TestCase):
|
||||
dockerfile="/tmp/Dockerfile.codex",
|
||||
state_dir=Path(tmp),
|
||||
)
|
||||
config = Path(tmp, "codex-config.toml").read_text()
|
||||
self.assertEqual("codex", plan.template)
|
||||
self.assertEqual("codex", plan.command)
|
||||
self.assertEqual("read_prompt_file", plan.prompt_mode)
|
||||
@@ -45,6 +46,18 @@ class TestAgentProviderRuntime(unittest.TestCase):
|
||||
("/home/node/.codex/config.toml",),
|
||||
tuple(f.guest_path for f in plan.files),
|
||||
)
|
||||
self.assertIn('[projects."/home/node"]', config)
|
||||
|
||||
def test_codex_trusts_requested_project_path(self):
|
||||
with tempfile.TemporaryDirectory(prefix="bb-provider.") as tmp:
|
||||
agent_provision_plan(
|
||||
template="codex",
|
||||
dockerfile="",
|
||||
state_dir=Path(tmp),
|
||||
trusted_project_path="/home/node/workspace",
|
||||
)
|
||||
config = Path(tmp, "codex-config.toml").read_text()
|
||||
self.assertIn('[projects."/home/node/workspace"]', config)
|
||||
|
||||
def test_codex_forward_host_credentials_adds_auth_and_verify(self):
|
||||
with tempfile.TemporaryDirectory(prefix="bb-provider.") as tmp:
|
||||
@@ -79,6 +92,7 @@ class TestAgentProviderRuntime(unittest.TestCase):
|
||||
state_dir=Path(tmp),
|
||||
auth_token="BOT_BOTTLE_CLAUDE_OAUTH_TOKEN",
|
||||
)
|
||||
claude_config = json.loads(Path(tmp, "claude.json").read_text())
|
||||
self.assertEqual(1, len(plan.egress_routes))
|
||||
route = plan.egress_routes[0]
|
||||
self.assertEqual("api.anthropic.com", route.host)
|
||||
@@ -89,6 +103,20 @@ class TestAgentProviderRuntime(unittest.TestCase):
|
||||
self.assertEqual("1", plan.env_vars["CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC"])
|
||||
self.assertEqual("1", plan.env_vars["DISABLE_ERROR_REPORTING"])
|
||||
self.assertEqual(frozenset({"CLAUDE_CODE_OAUTH_TOKEN"}), plan.hidden_env_names)
|
||||
self.assertIn("/home/node", claude_config["projects"])
|
||||
self.assertIn("/home/node/.claude.json", {f.guest_path for f in plan.files})
|
||||
|
||||
def test_claude_trusts_requested_project_path(self):
|
||||
with tempfile.TemporaryDirectory(prefix="bb-provider.") as tmp:
|
||||
agent_provision_plan(
|
||||
template="claude",
|
||||
dockerfile="",
|
||||
state_dir=Path(tmp),
|
||||
trusted_project_path="/home/node/workspace",
|
||||
)
|
||||
config = json.loads(Path(tmp, "claude.json").read_text())
|
||||
self.assertIn("/home/node", config["projects"])
|
||||
self.assertIn("/home/node/workspace", config["projects"])
|
||||
|
||||
def test_codex_forward_host_credentials_populates_egress_routes(self):
|
||||
with tempfile.TemporaryDirectory(prefix="bb-provider.") as tmp:
|
||||
|
||||
Reference in New Issue
Block a user