From 606a57b7edd1d5742a63cbb0b0fc86f4cd8432ef Mon Sep 17 00:00:00 2001 From: claude Date: Mon, 27 Jul 2026 15:15:44 +0000 Subject: [PATCH] docs: renumber PRD 0081 -> 0083 across the reconcile chunk Follows the base PR's renumber (0081 was already taken; main is on 0082). Update every `PRD 0081` reference in the gateway-attach code, tests, and ADR 0006, plus ADR 0006's link to the PRD file. No behaviour change. Refs #516, #519. Co-Authored-By: Claude Opus 4.8 --- bot_bottle/backend/base.py | 2 +- bot_bottle/backend/docker/backend.py | 2 +- bot_bottle/backend/docker/gateway.py | 2 +- bot_bottle/backend/docker/infra.py | 2 +- bot_bottle/backend/docker/infra_launch.py | 4 ++-- bot_bottle/backend/firecracker/infra.py | 2 +- bot_bottle/backend/firecracker/infra_launch.py | 2 +- bot_bottle/backend/gateway_attach.py | 4 ++-- bot_bottle/backend/macos_container/gateway.py | 2 +- bot_bottle/backend/macos_container/infra.py | 2 +- bot_bottle/backend/macos_container/infra_launch.py | 4 ++-- bot_bottle/gateway/__init__.py | 2 +- docs/decisions/0006-shared-behavior-in-base-backend.md | 6 +++--- tests/unit/test_architecture_guardrails.py | 2 +- tests/unit/test_backend_secret_reprovision.py | 4 ++-- tests/unit/test_docker_infra.py | 2 +- tests/unit/test_firecracker_gateway.py | 2 +- tests/unit/test_firecracker_infra.py | 2 +- tests/unit/test_macos_gateway.py | 2 +- tests/unit/test_macos_infra.py | 2 +- tests/unit/test_orchestrator_gateway.py | 4 ++-- 21 files changed, 28 insertions(+), 28 deletions(-) diff --git a/bot_bottle/backend/base.py b/bot_bottle/backend/base.py index c2ea5df1..b739ceff 100644 --- a/bot_bottle/backend/base.py +++ b/bot_bottle/backend/base.py @@ -528,7 +528,7 @@ class BottleBackend(ABC, Generic[PlanT, CleanupT, AttachTargetT]): def attach_bottled_agents_to_gateway(self) -> None: """Reconcile every running bottle against the freshly-(re)booted gateway - on the cold-boot bring-up path (PRD 0081). The shared flow + fail-hard + on the cold-boot bring-up path (PRD 0083). The shared flow + fail-hard policy live in `gateway_attach`; backends override only the three primitives below (ADR 0006).""" from .gateway_attach import reconcile_running_bottles diff --git a/bot_bottle/backend/docker/backend.py b/bot_bottle/backend/docker/backend.py index b332d594..ec0aa7ba 100644 --- a/bot_bottle/backend/docker/backend.py +++ b/bot_bottle/backend/docker/backend.py @@ -54,7 +54,7 @@ class DockerBottleBackend(BottleBackend["DockerBottlePlan", "DockerBottleCleanup def __init__(self, *, infra: "DockerInfraService | None" = None) -> None: # The infra service whose gateway just cold-booted, passed in on the - # bring-up reconcile path (PRD 0081) so `_gateway_attach_resources` + # bring-up reconcile path (PRD 0083) so `_gateway_attach_resources` # reads THAT gateway's CA rather than a fresh default-named service — # otherwise a non-default instance (an isolated integration test's # `-itest-` gateway) reads the default `bot-bottle-orch-gateway`, which diff --git a/bot_bottle/backend/docker/gateway.py b/bot_bottle/backend/docker/gateway.py index c0c87736..fa659f32 100644 --- a/bot_bottle/backend/docker/gateway.py +++ b/bot_bottle/backend/docker/gateway.py @@ -272,7 +272,7 @@ class DockerGateway(Gateway): if self._control_network: self._connect_control_network() # (Re)created a fresh container — signal a cold boot so the caller - # reconciles running bottles against it (PRD 0081). + # reconciles running bottles against it (PRD 0083). return True def _connect_control_network(self) -> None: diff --git a/bot_bottle/backend/docker/infra.py b/bot_bottle/backend/docker/infra.py index b2c3f666..8dcc4c92 100644 --- a/bot_bottle/backend/docker/infra.py +++ b/bot_bottle/backend/docker/infra.py @@ -147,7 +147,7 @@ class DockerInfraService(InfraService): ) # A (re)created gateway container minted/mounted its CA afresh and lost # every bottle's per-bottle state; reconcile the already-running bottles - # against it (PRD 0081). Skipped when a healthy current gateway was left + # against it (PRD 0083). Skipped when a healthy current gateway was left # untouched — no cold boot, nothing to reconcile. if cold_booted: from .backend import DockerBottleBackend diff --git a/bot_bottle/backend/docker/infra_launch.py b/bot_bottle/backend/docker/infra_launch.py index 224412f4..f16c79ae 100644 --- a/bot_bottle/backend/docker/infra_launch.py +++ b/bot_bottle/backend/docker/infra_launch.py @@ -83,7 +83,7 @@ def running_agent_containers( ) -> list[str]: """Every running agent container on the gateway `network` (the gateway itself excluded) — the bottles the bring-up reconcile attaches to the fresh - gateway (PRD 0081). Raises `OSError` if `docker` can't be run (fail hard: a + gateway (PRD 0083). Raises `OSError` if `docker` can't be run (fail hard: a reconcile that can't list its bottles must not look like "no bottles").""" proc = run_docker([ "docker", "network", "inspect", "--format", @@ -98,7 +98,7 @@ def running_agent_containers( def push_ca_to_container(container: str, ca_pem: str) -> None: """(Re)attach one running agent container to the current gateway: replace its trusted gateway CA with `ca_pem` and rebuild its trust store via - `docker cp` + `docker exec` (PRD 0081). Unconditional install — there is one + `docker cp` + `docker exec` (PRD 0083). Unconditional install — there is one gateway, so no fingerprint match is needed. Fail hard: raises `InfraLaunchError` (naming the container) on any failure — diff --git a/bot_bottle/backend/firecracker/infra.py b/bot_bottle/backend/firecracker/infra.py index 05886373..31b374a5 100644 --- a/bot_bottle/backend/firecracker/infra.py +++ b/bot_bottle/backend/firecracker/infra.py @@ -73,7 +73,7 @@ class FirecrackerInfraService(InfraService): # The fresh gateway rootfs minted a new CA and lost every bottle's # git-gate/token state; reconcile the already-running bottles against # it so a gateway rebuild doesn't silently break their egress - # (PRD 0081). Cold-boot only — the adopt fast-paths above never reach + # (PRD 0083). Cold-boot only — the adopt fast-paths above never reach # here, so a healthy current gateway is left untouched. if cold_booted: from .backend import FirecrackerBottleBackend diff --git a/bot_bottle/backend/firecracker/infra_launch.py b/bot_bottle/backend/firecracker/infra_launch.py index a55a7733..9fca2601 100644 --- a/bot_bottle/backend/firecracker/infra_launch.py +++ b/bot_bottle/backend/firecracker/infra_launch.py @@ -90,7 +90,7 @@ def persist_env_var_secret(private_key: Path, guest_ip: str, secret: str) -> Non def attach_ca_to_agent_vm(run_dir: Path, ca_pem: str) -> None: """(Re)attach one running agent VM (identified by its `run_dir`) to the current gateway: replace its trusted gateway CA with `ca_pem` and rebuild - its trust store over SSH (PRD 0081). Unconditional install — there is one + its trust store over SSH (PRD 0083). Unconditional install — there is one gateway, so no fingerprint match is needed. Bare-pipe input keeps the cert off argv. diff --git a/bot_bottle/backend/gateway_attach.py b/bot_bottle/backend/gateway_attach.py index 1f805671..21e0bae8 100644 --- a/bot_bottle/backend/gateway_attach.py +++ b/bot_bottle/backend/gateway_attach.py @@ -1,4 +1,4 @@ -"""The shared gateway-attach reconcile flow (PRD 0081). +"""The shared gateway-attach reconcile flow (PRD 0083). `BottleBackend.attach_bottled_agents_to_gateway()` delegates here so every backend reconciles running bottles against a freshly-booted gateway *the same @@ -21,7 +21,7 @@ if TYPE_CHECKING: @dataclass(frozen=True) class GatewayAttachResources: """Everything a running bottle needs to (re)attach to the current gateway on - a cold boot (PRD 0081). Gathered once per reconcile and handed to every + a cold boot (PRD 0083). Gathered once per reconcile and handed to every bottle. The CA now; egress secrets and git-gate state join as the reconcile grows (#516).""" diff --git a/bot_bottle/backend/macos_container/gateway.py b/bot_bottle/backend/macos_container/gateway.py index 0d388964..5d5bc1a0 100644 --- a/bot_bottle/backend/macos_container/gateway.py +++ b/bot_bottle/backend/macos_container/gateway.py @@ -112,7 +112,7 @@ class MacosGateway(Gateway): Always returns True: this recreates the gateway container unconditionally (a cold boot), so the caller reconciles running bottles against it - (PRD 0081).""" + (PRD 0083).""" self._orchestrator_url = orchestrator_url self._gateway_token = gateway_token # Fail closed on a missing policy source or token: the resolver-only data diff --git a/bot_bottle/backend/macos_container/infra.py b/bot_bottle/backend/macos_container/infra.py index f62c11eb..2127b5a6 100644 --- a/bot_bottle/backend/macos_container/infra.py +++ b/bot_bottle/backend/macos_container/infra.py @@ -142,7 +142,7 @@ class MacosInfraService(InfraService): url, orchestrator.mint_gateway_token()) # A (re)created gateway container minted/mounted its CA afresh and lost # every bottle's per-bottle state; reconcile the already-running bottles - # against it (PRD 0081). Skipped when a healthy current gateway was left + # against it (PRD 0083). Skipped when a healthy current gateway was left # untouched — no cold boot, nothing to reconcile. if cold_booted: from .backend import MacosContainerBottleBackend diff --git a/bot_bottle/backend/macos_container/infra_launch.py b/bot_bottle/backend/macos_container/infra_launch.py index 76890bfe..0578aa6c 100644 --- a/bot_bottle/backend/macos_container/infra_launch.py +++ b/bot_bottle/backend/macos_container/infra_launch.py @@ -99,7 +99,7 @@ def ensure_gateway( def running_agent_containers() -> list[str]: """Every running agent container's name — the bottles the bring-up reconcile - attaches to the fresh gateway (PRD 0081). Raises `EnumerationError` if the + attaches to the fresh gateway (PRD 0083). Raises `EnumerationError` if the live set can't be determined (fail hard rather than reconcile a partial set).""" return [f"{CONTAINER_NAME_PREFIX}{agent.slug}" for agent in enumerate_active()] @@ -108,7 +108,7 @@ def running_agent_containers() -> list[str]: def push_ca_to_container(name: str, ca_pem: str) -> None: """(Re)attach one running agent container to the current gateway: replace its trusted gateway CA with `ca_pem` and rebuild its trust store via - `container cp` + `container exec` (PRD 0081). Unconditional install — there + `container cp` + `container exec` (PRD 0083). Unconditional install — there is one gateway, so no fingerprint match is needed. Fail hard: raises `InfraLaunchError` (naming the container) on any failure — diff --git a/bot_bottle/gateway/__init__.py b/bot_bottle/gateway/__init__.py index d268aa82..a353f4c3 100644 --- a/bot_bottle/gateway/__init__.py +++ b/bot_bottle/gateway/__init__.py @@ -133,7 +133,7 @@ class Gateway(abc.ABC): so its mitmproxy minted a fresh CA and lost its per-bottle state), False when a healthy current gateway was left untouched. The bring-up flow uses this as the cold-boot signal that gates the running-bottle - reconcile (`attach_bottled_agents_to_gateway`, PRD 0081).""" + reconcile (`attach_bottled_agents_to_gateway`, PRD 0083).""" @abc.abstractmethod def is_running(self) -> bool: diff --git a/docs/decisions/0006-shared-behavior-in-base-backend.md b/docs/decisions/0006-shared-behavior-in-base-backend.md index 4817153a..e25afc61 100644 --- a/docs/decisions/0006-shared-behavior-in-base-backend.md +++ b/docs/decisions/0006-shared-behavior-in-base-backend.md @@ -15,7 +15,7 @@ macOS-container). Cross-backend operations can be expressed two ways: concrete method and each backend overrides small **primitives** it calls. Form 1 gives each backend total freedom, which is exactly the problem: the three -implementations drift. The bring-up reconcile (PRD 0081) first shipped as form 1 +implementations drift. The bring-up reconcile (PRD 0083) first shipped as form 1 and immediately diverged — each backend re-implemented "gather CA → list running bottles → push to each", and one backend's copy silently skipped failures while another's aborted, an inconsistency caught only in review (#519). The behaviour @@ -37,7 +37,7 @@ method that: - delegates only the irreducibly backend-specific steps to `@abstractmethod` primitives with narrow, well-typed signatures. -The first application is `attach_bottled_agents_to_gateway()` (PRD 0081): the +The first application is `attach_bottled_agents_to_gateway()` (PRD 0083): the base gathers resources once, attempts every running bottle, and raises an aggregate `InfraLaunchError` if any failed; backends supply only `_gateway_attach_resources()`, `_running_bottles()`, and @@ -60,6 +60,6 @@ operations whose *shape* should be uniform, not about banning abstract methods. ## Links -- PRD 0081 (`docs/prds/0081-reprovision-gateway-state-on-bringup.md`). +- PRD 0083 (`docs/prds/0083-reprovision-gateway-state-on-bringup.md`). - Review that prompted this: PR #519. - `bot_bottle/backend/base.py` (`BottleBackend.attach_bottled_agents_to_gateway`). diff --git a/tests/unit/test_architecture_guardrails.py b/tests/unit/test_architecture_guardrails.py index acfa6011..78da8d77 100644 --- a/tests/unit/test_architecture_guardrails.py +++ b/tests/unit/test_architecture_guardrails.py @@ -85,7 +85,7 @@ class TestRuntimeModuleSizes(unittest.TestCase): def test_backend_contract_does_not_absorb_preparation_logic(self) -> None: # base.py holds the backend *contract*; implementation lives elsewhere. # The cap is a tripwire against absorbing preparation/impl logic, not a - # ban on new contract surface — bumped 580->615 for the PRD 0081 + # ban on new contract surface — bumped 580->615 for the PRD 0083 # gateway-attach contract (delegator + 3 abstract primitives; the flow # itself lives in backend/gateway_attach.py, not here). caps = { diff --git a/tests/unit/test_backend_secret_reprovision.py b/tests/unit/test_backend_secret_reprovision.py index 60671cb0..4bce51bf 100644 --- a/tests/unit/test_backend_secret_reprovision.py +++ b/tests/unit/test_backend_secret_reprovision.py @@ -162,7 +162,7 @@ class TestFirecrackerReprovision(unittest.TestCase): class TestAttachFlow(unittest.TestCase): - """PRD 0081 / #519 review: the base backend owns the reconcile flow and + """PRD 0083 / #519 review: the base backend owns the reconcile flow and fails hard — gather resources, attempt every running bottle, then raise an aggregate if any failed (never silently skip).""" @@ -208,7 +208,7 @@ class TestAttachFlow(unittest.TestCase): class TestFirecrackerAttachPrimitive(unittest.TestCase): - """PRD 0081: attach_ca_to_agent_vm pushes the current gateway CA into one + """PRD 0083: attach_ca_to_agent_vm pushes the current gateway CA into one running agent VM over SSH, failing hard.""" def _run_dir(self, root: Path, ip: str = "10.243.0.3") -> Path: diff --git a/tests/unit/test_docker_infra.py b/tests/unit/test_docker_infra.py index 3f1c2dc0..f4af06a2 100644 --- a/tests/unit/test_docker_infra.py +++ b/tests/unit/test_docker_infra.py @@ -70,7 +70,7 @@ class TestDockerInfraService(unittest.TestCase): def test_cold_boot_reconciles_running_bottles(self) -> None: # A (re)created gateway (connect returns True) triggers the bring-up - # reconcile so running bottles re-trust the fresh gateway (PRD 0081). + # reconcile so running bottles re-trust the fresh gateway (PRD 0083). self.gw.connect_to_orchestrator.return_value = True self.svc.ensure_running() self.attach.assert_called_once_with() diff --git a/tests/unit/test_firecracker_gateway.py b/tests/unit/test_firecracker_gateway.py index 17304b1d..a61aa0e1 100644 --- a/tests/unit/test_firecracker_gateway.py +++ b/tests/unit/test_firecracker_gateway.py @@ -63,7 +63,7 @@ class TestFirecrackerGatewayConnect(unittest.TestCase): patch.object(infra_vm, "push_secret") as push: cold_booted = gw.connect_to_orchestrator(_ORCH_URL, _TOKEN) # The VM is booted fresh here (cold-boot path only), so it always - # signals a cold boot → the caller reconciles running bottles (PRD 0081). + # signals a cold boot → the caller reconciles running bottles (PRD 0083). self.assertTrue(cold_booted) # Booted on the gateway link with the gateway role; the orchestrator's # guest IP (parsed off the URL) rides the cmdline as bb_orch. diff --git a/tests/unit/test_firecracker_infra.py b/tests/unit/test_firecracker_infra.py index 47febd3d..1d2ad6a5 100644 --- a/tests/unit/test_firecracker_infra.py +++ b/tests/unit/test_firecracker_infra.py @@ -49,7 +49,7 @@ _ATTACH = ( class TestEnsureRunning(unittest.TestCase): def setUp(self) -> None: # The cold-boot branch reconciles running bottles against the fresh - # gateway (PRD 0081). Stub it so these composition tests stay isolated + # gateway (PRD 0083). Stub it so these composition tests stay isolated # from SSH; the wiring itself is asserted in test_cold_boot_reconciles*. ap = patch(_ATTACH) self.attach = ap.start() diff --git a/tests/unit/test_macos_gateway.py b/tests/unit/test_macos_gateway.py index 2eec42bd..45ead5e4 100644 --- a/tests/unit/test_macos_gateway.py +++ b/tests/unit/test_macos_gateway.py @@ -46,7 +46,7 @@ class TestMacosGatewayConnect(unittest.TestCase): def test_connect_signals_cold_boot(self) -> None: # The container is recreated unconditionally, so connect always signals - # a cold boot → the caller reconciles running bottles (PRD 0081). + # a cold boot → the caller reconciles running bottles (PRD 0083). run = Mock(return_value=_proc()) with patch(f"{_GW}.container_mod") as mod, \ patch(f"{_GW}.host_gateway_ca_dir", return_value=Path("/ca")): diff --git a/tests/unit/test_macos_infra.py b/tests/unit/test_macos_infra.py index 5a284d4b..ae2994c3 100644 --- a/tests/unit/test_macos_infra.py +++ b/tests/unit/test_macos_infra.py @@ -58,7 +58,7 @@ class TestInfraEnsureRunning(unittest.TestCase): def test_cold_boot_reconciles_running_bottles(self) -> None: # A (re)created gateway (connect returns True) triggers the bring-up - # reconcile so running bottles re-trust the fresh gateway (PRD 0081). + # reconcile so running bottles re-trust the fresh gateway (PRD 0083). self.gw.connect_to_orchestrator.return_value = True with patch(f"{_INFRA}.ensure_networks"): self.svc.ensure_running() diff --git a/tests/unit/test_orchestrator_gateway.py b/tests/unit/test_orchestrator_gateway.py index ec7b65d2..e5c3a638 100644 --- a/tests/unit/test_orchestrator_gateway.py +++ b/tests/unit/test_orchestrator_gateway.py @@ -90,7 +90,7 @@ class TestDockerGateway(unittest.TestCase): self.assertEqual([], [c for c in calls if c[:2] == ["docker", "run"]]) self.assertEqual([], [c for c in calls if c[:2] == ["docker", "rm"]]) # A healthy current gateway left untouched is not a cold boot — the - # bring-up flow skips the running-bottle reconcile (PRD 0081). + # bring-up flow skips the running-bottle reconcile (PRD 0083). self.assertFalse(cold_booted) def test_ensure_running_recreates_when_image_is_stale(self) -> None: @@ -113,7 +113,7 @@ class TestDockerGateway(unittest.TestCase): self.assertEqual(1, len([c for c in calls if c[:2] == ["docker", "run"]])) self.assertTrue(any(c[:2] == ["docker", "rm"] for c in calls)) # A recreated container minted/mounted its CA afresh — a cold boot that - # triggers the running-bottle reconcile (PRD 0081). + # triggers the running-bottle reconcile (PRD 0083). self.assertTrue(cold_booted) def test_ensure_running_starts_the_singleton_when_absent(self) -> None: