fix(codex): provision dummy user auth state
This commit is contained in:
@@ -9,7 +9,11 @@ import unittest
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
from bot_bottle.codex_auth import codex_auth_path, codex_host_access_token
|
||||
from bot_bottle.codex_auth import (
|
||||
codex_auth_path,
|
||||
codex_dummy_auth_json,
|
||||
codex_host_access_token,
|
||||
)
|
||||
from bot_bottle.log import Die
|
||||
|
||||
|
||||
@@ -59,6 +63,15 @@ class TestCodexHostAccessToken(unittest.TestCase):
|
||||
with self.assertRaises(Die):
|
||||
codex_host_access_token({"CODEX_HOME": str(self.home)})
|
||||
|
||||
def test_user_auth_mode_is_allowed(self):
|
||||
token = _jwt(2000000000)
|
||||
self._write({"auth_mode": "user", "tokens": {"access_token": token}})
|
||||
out = codex_host_access_token(
|
||||
{"CODEX_HOME": str(self.home)},
|
||||
now=datetime(2026, 1, 1, tzinfo=timezone.utc),
|
||||
)
|
||||
self.assertEqual(token, out)
|
||||
|
||||
def test_expired_token_dies(self):
|
||||
self._write({
|
||||
"auth_mode": "chatgpt",
|
||||
@@ -78,6 +91,37 @@ class TestCodexHostAccessToken(unittest.TestCase):
|
||||
with self.assertRaises(Die):
|
||||
codex_host_access_token({"CODEX_HOME": str(self.home)})
|
||||
|
||||
def test_dummy_auth_preserves_mode_and_redacts_tokens(self):
|
||||
access = _jwt(2000000000)
|
||||
refresh = "host-refresh-token"
|
||||
self._write({
|
||||
"auth_mode": "chatgpt",
|
||||
"OPENAI_API_KEY": None,
|
||||
"tokens": {
|
||||
"access_token": access,
|
||||
"id_token": _jwt(2000000000),
|
||||
"refresh_token": refresh,
|
||||
"account_id": "acct-host",
|
||||
},
|
||||
"last_refresh": "2026-05-29T00:00:00.000Z",
|
||||
})
|
||||
dummy = json.loads(codex_dummy_auth_json(
|
||||
{"CODEX_HOME": str(self.home)},
|
||||
now=datetime(2026, 1, 1, tzinfo=timezone.utc),
|
||||
))
|
||||
self.assertEqual("chatgpt", dummy["auth_mode"])
|
||||
self.assertIsNone(dummy["OPENAI_API_KEY"])
|
||||
self.assertNotEqual(access, dummy["tokens"]["access_token"])
|
||||
self.assertNotEqual(refresh, dummy["tokens"]["refresh_token"])
|
||||
self.assertEqual("bot-bottle-placeholder", dummy["tokens"]["refresh_token"])
|
||||
self.assertEqual("bot-bottle-placeholder", dummy["tokens"]["account_id"])
|
||||
self.assertIsNotNone(
|
||||
codex_host_access_token(
|
||||
{"CODEX_HOME": str(self.home)},
|
||||
now=datetime(2026, 1, 1, tzinfo=timezone.utc),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
"""Unit: docker provider auth marker provisioning."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
from bot_bottle.backend import BottleSpec
|
||||
from bot_bottle.backend.docker.bottle_plan import DockerBottlePlan
|
||||
from bot_bottle.backend.docker.provision import provider_auth as _provider_auth
|
||||
from bot_bottle.egress import EgressPlan
|
||||
from bot_bottle.git_gate import GitGatePlan
|
||||
from bot_bottle.manifest import Manifest
|
||||
from bot_bottle.pipelock import PipelockProxyPlan
|
||||
|
||||
|
||||
def _plan(*, codex_auth_file: Path | None = None) -> DockerBottlePlan:
|
||||
manifest = Manifest.from_json_obj({
|
||||
"bottles": {"dev": {"agent_provider": {"template": "codex"}}},
|
||||
"agents": {"demo": {"skills": [], "prompt": "", "bottle": "dev"}},
|
||||
})
|
||||
return DockerBottlePlan(
|
||||
spec=BottleSpec(
|
||||
manifest=manifest,
|
||||
agent_name="demo",
|
||||
copy_cwd=False,
|
||||
user_cwd="/tmp/x",
|
||||
),
|
||||
stage_dir=Path("/tmp/stage"),
|
||||
slug="demo-abc12",
|
||||
container_name="bot-bottle-demo-abc12",
|
||||
container_name_pinned=False,
|
||||
image="bot-bottle-codex:latest",
|
||||
derived_image="",
|
||||
runtime_image="bot-bottle-codex:latest",
|
||||
dockerfile_path="",
|
||||
env_file=Path("/tmp/agent.env"),
|
||||
forwarded_env={},
|
||||
prompt_file=Path("/tmp/prompt.txt"),
|
||||
proxy_plan=PipelockProxyPlan(
|
||||
yaml_path=Path("/tmp/pipelock.yaml"),
|
||||
slug="demo-abc12",
|
||||
),
|
||||
git_gate_plan=GitGatePlan(
|
||||
slug="demo-abc12",
|
||||
entrypoint_script=Path("/tmp/git-gate-entrypoint.sh"),
|
||||
hook_script=Path("/tmp/git-gate-hook"),
|
||||
access_hook_script=Path("/tmp/git-gate-access-hook"),
|
||||
upstreams=(),
|
||||
),
|
||||
egress_plan=EgressPlan(
|
||||
slug="demo-abc12",
|
||||
routes_path=Path("/tmp/routes.yaml"),
|
||||
routes=(),
|
||||
token_env_map={},
|
||||
),
|
||||
supervise_plan=None,
|
||||
use_runsc=False,
|
||||
agent_command="codex",
|
||||
agent_provider_template="codex",
|
||||
codex_auth_file=codex_auth_file,
|
||||
)
|
||||
|
||||
|
||||
class TestProvisionProviderAuth(unittest.TestCase):
|
||||
def test_noop_without_codex_auth_file(self):
|
||||
with patch.object(_provider_auth.subprocess, "run") as run:
|
||||
_provider_auth.provision_provider_auth(
|
||||
_plan(), "bot-bottle-demo-abc12",
|
||||
)
|
||||
self.assertEqual(0, run.call_count)
|
||||
|
||||
def test_copies_dummy_auth_json_to_codex_home(self):
|
||||
with patch.object(_provider_auth.subprocess, "run") as run:
|
||||
_provider_auth.provision_provider_auth(
|
||||
_plan(codex_auth_file=Path("/tmp/codex-auth.json")),
|
||||
"bot-bottle-demo-abc12",
|
||||
)
|
||||
argvs = [call.args[0] for call in run.call_args_list]
|
||||
self.assertIn(
|
||||
["docker", "exec", "-u", "0", "bot-bottle-demo-abc12",
|
||||
"mkdir", "-p", "/home/node/.codex"],
|
||||
argvs,
|
||||
)
|
||||
self.assertIn(
|
||||
["docker", "cp", "/tmp/codex-auth.json",
|
||||
"bot-bottle-demo-abc12:/home/node/.codex/auth.json"],
|
||||
argvs,
|
||||
)
|
||||
self.assertIn(
|
||||
["docker", "exec", "-u", "0", "bot-bottle-demo-abc12",
|
||||
"chown", "node:node", "/home/node/.codex/auth.json"],
|
||||
argvs,
|
||||
)
|
||||
self.assertIn(
|
||||
["docker", "exec", "-u", "0", "bot-bottle-demo-abc12",
|
||||
"chmod", "600", "/home/node/.codex/auth.json"],
|
||||
argvs,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -21,6 +21,7 @@ from bot_bottle.backend.smolmachines.provision import (
|
||||
ca as _ca,
|
||||
git as _git,
|
||||
prompt as _prompt,
|
||||
provider_auth as _provider_auth,
|
||||
skills as _skills,
|
||||
supervise as _supervise,
|
||||
)
|
||||
@@ -55,6 +56,7 @@ def _plan(
|
||||
bundle_ip: str = "192.168.50.2",
|
||||
agent_git_gate_host: str = "127.0.0.1:55555",
|
||||
agent_supervise_url: str = "http://127.0.0.1:55556/",
|
||||
codex_auth_file: Path | None = None,
|
||||
) -> SmolmachinesBottlePlan:
|
||||
bottle_json: dict = {}
|
||||
git_json: dict = {}
|
||||
@@ -129,6 +131,7 @@ def _plan(
|
||||
supervise_plan=supervise_plan,
|
||||
agent_git_gate_host=agent_git_gate_host,
|
||||
agent_supervise_url=agent_supervise_url,
|
||||
codex_auth_file=codex_auth_file,
|
||||
)
|
||||
|
||||
|
||||
@@ -189,6 +192,42 @@ class TestProvisionPrompt(unittest.TestCase):
|
||||
)
|
||||
|
||||
|
||||
class TestProvisionProviderAuth(unittest.TestCase):
|
||||
def test_noop_without_codex_auth_file(self):
|
||||
with patch(
|
||||
"bot_bottle.backend.smolmachines.provision.provider_auth._smolvm.machine_cp"
|
||||
) as cp, patch(
|
||||
"bot_bottle.backend.smolmachines.provision.provider_auth._smolvm.machine_exec"
|
||||
) as ex:
|
||||
_provider_auth.provision_provider_auth(
|
||||
_plan(), "bot-bottle-demo-abc12",
|
||||
)
|
||||
self.assertEqual(0, cp.call_count)
|
||||
self.assertEqual(0, ex.call_count)
|
||||
|
||||
def test_copies_dummy_auth_json_to_codex_home(self):
|
||||
with patch(
|
||||
"bot_bottle.backend.smolmachines.provision.provider_auth._smolvm.machine_cp"
|
||||
) as cp, patch(
|
||||
"bot_bottle.backend.smolmachines.provision.provider_auth._smolvm.machine_exec"
|
||||
) as ex:
|
||||
_provider_auth.provision_provider_auth(
|
||||
_plan(codex_auth_file=Path("/tmp/codex-auth.json")),
|
||||
"bot-bottle-demo-abc12",
|
||||
)
|
||||
cp.assert_called_once_with(
|
||||
"/tmp/codex-auth.json",
|
||||
"bot-bottle-demo-abc12:/home/node/.codex/auth.json",
|
||||
)
|
||||
argv_seen = [call.args[1] for call in ex.call_args_list]
|
||||
self.assertIn(["mkdir", "-p", "/home/node/.codex"], argv_seen)
|
||||
self.assertIn(
|
||||
["chown", "node:node", "/home/node/.codex/auth.json"],
|
||||
argv_seen,
|
||||
)
|
||||
self.assertIn(["chmod", "600", "/home/node/.codex/auth.json"], argv_seen)
|
||||
|
||||
|
||||
class TestProvisionSkills(unittest.TestCase):
|
||||
def _patch_host_skill_dir(self, returns: dict[str, str]):
|
||||
return patch(
|
||||
|
||||
Reference in New Issue
Block a user