refactor(de-sidecar): purge the "sidecar" name from live code, tests, and current docs
Completes the de-sidecar cleanup: no live code, test, current doc, script, or nix file mentions or is named "sidecar" any more. Only the dated PRD/research docs keep the term as historical record (agreed on the #385 thread). - Rename `sidecar_init.py`→`gateway_init.py` was done earlier; this pass sweeps the remaining descriptive uses: the egress / git-gate / supervise components are the gateway's *daemons*, the shared container is the *gateway*, the old per-bottle container was the *companion container*. - Rename `tests/integration/test_sidecar_bundle_image.py`→`test_gateway_image.py` and its class; update `docs/ci.md` + `tests/README.md` for the renamed/ removed integration tests. - `SIDECAR_PORTS` shell var in `scripts/firecracker-netpool.sh`→`GATEWAY_PORTS`. Full unit suite green (bar the pre-existing `/bin/sleep`-missing env errors in test_gateway_init); docker integration — gateway singleton, broker, real two-bottle multitenant isolation, and the gateway-image build — all pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WBMWTEtQdJ4W5UrWuLHCck
This commit is contained in:
@@ -5,7 +5,7 @@ no test ever reads or writes the real ``~/.bot-bottle`` (state, queue,
|
||||
and audit dirs all derive from ``paths.bot_bottle_root()`` →
|
||||
``Path.home()``). Without this, a test that takes a ``flock`` on the
|
||||
real audit log can **block indefinitely** when a live bottle's supervise
|
||||
sidecar holds that lock — observed as a hung ``coverage run`` at 0% CPU —
|
||||
gateway holds that lock — observed as a hung ``coverage run`` at 0% CPU —
|
||||
and unisolated tests otherwise pollute the developer's home dir.
|
||||
|
||||
Individual tests that need their own ``HOME`` still override
|
||||
|
||||
@@ -19,8 +19,8 @@ class TestConsolidatedAgentCompose(unittest.TestCase):
|
||||
plan = type(plan)(**{**vars(plan), "use_runsc": True}) # type: ignore[arg-type]
|
||||
return consolidated_agent_compose(plan, gateway_ip=_GW, source_ip=_IP, network=_NET)
|
||||
|
||||
def test_only_agent_service_no_sidecars(self) -> None:
|
||||
# The whole point of consolidation: no per-bottle sidecar bundle.
|
||||
def test_only_agent_service_no_companion_container(self) -> None:
|
||||
# The whole point of consolidation: no per-bottle gateway.
|
||||
self.assertEqual(["agent"], list(self._spec()["services"]))
|
||||
|
||||
def test_agent_pinned_on_external_gateway_network(self) -> None:
|
||||
@@ -35,7 +35,7 @@ class TestConsolidatedAgentCompose(unittest.TestCase):
|
||||
# git-http + supervise on the gateway must bypass the egress proxy.
|
||||
self.assertTrue(any(e.startswith("NO_PROXY=") and _GW in e for e in env))
|
||||
|
||||
def test_no_sidecar_dependency(self) -> None:
|
||||
def test_no_companion_container_dependency(self) -> None:
|
||||
self.assertNotIn("depends_on", self._spec()["services"]["agent"])
|
||||
|
||||
def test_runsc_runtime_when_enabled(self) -> None:
|
||||
|
||||
@@ -586,7 +586,7 @@ class TestCanaryGeneration(unittest.TestCase):
|
||||
|
||||
|
||||
class TestEgressEnvEntries(unittest.TestCase):
|
||||
def test_sidecar_entries_include_route_tokens_and_canary_scan_prefix(self):
|
||||
def test_gateway_entries_include_route_tokens_and_canary_scan_prefix(self):
|
||||
plan = EgressPlan(
|
||||
slug="s",
|
||||
routes_path=Path("/tmp/r.yaml"),
|
||||
|
||||
@@ -951,7 +951,7 @@ class TestScanOutbound(unittest.TestCase):
|
||||
body='{"jsonrpc":"2.0","method":"initialize"}',
|
||||
)
|
||||
self.assertIsNone(scan_outbound(route, text, {
|
||||
"EGRESS_TOKEN_0": "sidecar-owned-secret",
|
||||
"EGRESS_TOKEN_0": "gateway-owned-secret",
|
||||
}))
|
||||
|
||||
def test_token_in_body_blocked(self):
|
||||
@@ -1302,7 +1302,7 @@ class TestScanOutboundEnhanced(unittest.TestCase):
|
||||
self.assertEqual("warn", result.severity)
|
||||
|
||||
def test_bot_bottle_sensitive_prefixes_env_var(self):
|
||||
# When the sidecar env contains BOT_BOTTLE_SENSITIVE_PREFIXES,
|
||||
# When the gateway env contains BOT_BOTTLE_SENSITIVE_PREFIXES,
|
||||
# scan_outbound should scan those additional prefixes.
|
||||
secret = "extra-sensitive-value-abc"
|
||||
env = {
|
||||
@@ -1324,7 +1324,7 @@ class TestScanOutboundEnhanced(unittest.TestCase):
|
||||
self.assertIsNotNone(result)
|
||||
|
||||
def test_canary_detected_via_random_secret_env_name(self):
|
||||
# The fake secret uses a randomized env name that the sidecar marks
|
||||
# The fake secret uses a randomized env name that the gateway marks
|
||||
# as sensitive through BOT_BOTTLE_SENSITIVE_PREFIXES.
|
||||
canary = "canaryvalue12345abcdef"
|
||||
env = {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Unit: LOG_FULL credential redaction in _log_request / _log_response (issue #257).
|
||||
|
||||
egress_addon.py is sidecar-only code that depends on mitmproxy, which is
|
||||
egress_addon.py is gateway-only code that depends on mitmproxy, which is
|
||||
not installed on the host. This file pre-populates sys.modules with the
|
||||
minimum mocks needed so EgressAddon can be imported and tested without the
|
||||
real mitmproxy package."""
|
||||
@@ -17,7 +17,7 @@ from unittest.mock import patch
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Sidecar-import shims — must run before importing egress_addon
|
||||
# Gateway-import shims — must run before importing egress_addon
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def _ensure_shims() -> None:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Unit: EgressAddon request/response decision flow (issue #286).
|
||||
|
||||
`egress_addon.py` is the sidecar-only mitmproxy adapter that wires the
|
||||
`egress_addon.py` is the gateway-only mitmproxy adapter that wires the
|
||||
host-importable decision logic in `egress_addon_core` into mitmproxy's
|
||||
request/response hooks. The core logic is exercised directly by
|
||||
`test_egress_addon_core.py`; the redaction logging by
|
||||
@@ -13,7 +13,7 @@ from coverage.
|
||||
mitmproxy is not installed on the host, so we pre-populate `sys.modules`
|
||||
with the minimum stubs needed to import the adapter (a `mitmproxy.http`
|
||||
module exposing a `Response` with `.make`, plus the flat
|
||||
`egress_addon_core` name the sidecar uses)."""
|
||||
`egress_addon_core` name the gateway uses)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -158,7 +158,7 @@ class _WebSocketData:
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Sidecar-import shims — must run before importing egress_addon
|
||||
# Gateway-import shims — must run before importing egress_addon
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -303,9 +303,9 @@ class TestAuthInjection(unittest.TestCase):
|
||||
route = Route(host="api.example.com", auth_scheme="Bearer", token_env="EGRESS_TOKEN_0")
|
||||
addon = _addon(Config(routes=(route,)))
|
||||
flow = _Flow(_Request(host="api.example.com", headers={"authorization": "Bearer agent-faked"}))
|
||||
with patch.dict("os.environ", {"EGRESS_TOKEN_0": "real-sidecar-token"}):
|
||||
with patch.dict("os.environ", {"EGRESS_TOKEN_0": "real-gateway-token"}):
|
||||
_run_request(addon, flow)
|
||||
self.assertEqual("Bearer real-sidecar-token", flow.request.headers.get("authorization"))
|
||||
self.assertEqual("Bearer real-gateway-token", flow.request.headers.get("authorization"))
|
||||
self.assertIsNone(flow.response)
|
||||
|
||||
def test_auth_route_with_unset_env_blocks(self) -> None:
|
||||
|
||||
@@ -72,7 +72,7 @@ class TestApplyRoutesChange(unittest.TestCase):
|
||||
|
||||
def test_apply_routes_change_fails_closed_after_companion_removal(self):
|
||||
# The per-bottle companion container that live route-apply used to
|
||||
# signal was removed in the de-sidecar cleanup (#385); apply now
|
||||
# signal was removed in the companion-container removal (#385); apply now
|
||||
# fails closed until the gateway-side apply lands.
|
||||
with self.assertRaises(EgressApplyError) as cm:
|
||||
applicator.apply_routes_change(
|
||||
|
||||
@@ -218,9 +218,9 @@ class TestHookRender(unittest.TestCase):
|
||||
self.assertIn("supervisor approved # gitleaks:allow", hook)
|
||||
self.assertIn("supervisor rejected # gitleaks:allow", hook)
|
||||
|
||||
def test_inline_gitleaks_allow_python_imports_work_in_sidecar_layout(self):
|
||||
def test_inline_gitleaks_allow_python_imports_work_in_gateway_layout(self):
|
||||
hook = git_gate_render_hook()
|
||||
# The sidecar image copies supervise.py flat under /app, while
|
||||
# The gateway image copies supervise.py flat under /app, while
|
||||
# host-side tests import it through the bot_bottle package.
|
||||
# Hooks execute from the bare repo directory, so the embedded
|
||||
# Python must include /app and support both import layouts.
|
||||
|
||||
@@ -220,7 +220,7 @@ class TestGitHttpBackend(unittest.TestCase):
|
||||
|
||||
def test_subprocess_calls_include_timeout(self):
|
||||
"""Both subprocess.run calls (access-hook and git http-backend) must
|
||||
pass timeout= so a hung upstream cannot wedge the sidecar."""
|
||||
pass timeout= so a hung upstream cannot wedge the gateway."""
|
||||
from http.server import ThreadingHTTPServer
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
|
||||
@@ -16,12 +16,12 @@ class TestMacosContainerCleanup(unittest.TestCase):
|
||||
completed = cleanup.subprocess.CompletedProcess(
|
||||
args=[],
|
||||
returncode=0,
|
||||
stdout="bot-bottle-a\nbot-bottle-sidecars-a\nother\n",
|
||||
stdout="bot-bottle-a\nbot-bottle-b\nother\n",
|
||||
stderr="",
|
||||
)
|
||||
with patch.object(cleanup.subprocess, "run", return_value=completed):
|
||||
self.assertEqual(
|
||||
["bot-bottle-a", "bot-bottle-sidecars-a"],
|
||||
["bot-bottle-a", "bot-bottle-b"],
|
||||
cleanup._list_prefixed_containers(),
|
||||
)
|
||||
|
||||
@@ -44,7 +44,7 @@ class TestMacosContainerCleanup(unittest.TestCase):
|
||||
|
||||
class TestMacosContainerEnumerate(unittest.TestCase):
|
||||
def test_enumerate_active_is_empty_while_disabled(self):
|
||||
# The macOS backend is disabled during the de-sidecar cleanup
|
||||
# The macOS backend is disabled during the companion-container removal cleanup
|
||||
# (#385); it launches nothing, so there is nothing to enumerate.
|
||||
self.assertEqual([], enum_mod.enumerate_active())
|
||||
|
||||
|
||||
@@ -267,7 +267,7 @@ resolver #2
|
||||
self.assertEqual(
|
||||
"192.168.128.2",
|
||||
util.container_ipv4_on_network(
|
||||
"bot-bottle-sidecars-demo",
|
||||
"bot-bottle-demo",
|
||||
"bot-bottle-net-demo",
|
||||
),
|
||||
)
|
||||
|
||||
@@ -28,7 +28,7 @@ def _plan(routes: tuple[EgressRoute, ...], *, slug: str = "demo", log: int = 0)
|
||||
class TestEgressPolicy(unittest.TestCase):
|
||||
def test_policy_round_trips_through_load_config(self) -> None:
|
||||
# The policy the gateway serves must parse back to the same allow-list
|
||||
# the per-bottle sidecar applied — moving onto the shared gateway must
|
||||
# the per-bottle gateway applied — moving onto the shared gateway must
|
||||
# not change a bottle's egress.
|
||||
routes = (EgressRoute(host="api.example.com"), EgressRoute(host="pypi.org"))
|
||||
cfg = load_config(egress_policy(_plan(routes)))
|
||||
|
||||
@@ -26,7 +26,7 @@ class TestGitGateGitconfigRender(unittest.TestCase):
|
||||
bottle = fixture_with_git().bottles["dev"]
|
||||
out = git_gate_render_gitconfig(bottle.git, GIT_GATE_HOSTNAME)
|
||||
# Both entries map to a [url ...] block keyed on the gate's
|
||||
# short network alias (`git-gate`) inside the sidecar bundle.
|
||||
# short network alias (`git-gate`) inside the gateway.
|
||||
self.assertIn(
|
||||
'[url "git://git-gate/bot-bottle.git"]',
|
||||
out,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""Unit: supervise sidecar MCP server (PRD 0013)."""
|
||||
"""Unit: supervise daemon MCP server (PRD 0013)."""
|
||||
|
||||
import http.client
|
||||
import json
|
||||
|
||||
Reference in New Issue
Block a user