refactor: provision egress routes via AgentProvisionPlan
Remove provider-specific branching from egress.py and pipelock.py. Previously, `egress_routes_for_bottle` and `pipelock_effective_tls_passthrough` both contained `template == "codex"` checks — the same pattern the rest of the PR moved out of the backends. Root cause: `EgressRoute` had no `tls_passthrough` field, so pipelock couldn't learn from the synthesised Codex routes that they needed passthrough. Fix: - Add `EgressRoute.tls_passthrough: bool`. `egress_manifest_routes` lifts the existing `pipelock.tls_passthrough` manifest flag here; provider routes set it directly. - Add `AgentProvisionPlan.egress_routes`. `agent_provision_plan` populates it for Codex + `forward_host_credentials`, including `tls_passthrough=True`. - Replace Codex-specific `egress_routes_for_bottle` logic with a generic `_merge_provider_route` helper. Backends call `egress_routes_for_bottle(bottle, plan.egress_routes)`; no provider type checks inside egress or pipelock. - Rewrite `pipelock_effective_tls_passthrough` to read `route.tls_passthrough` from the merged route set instead of re-implementing the provider check. - Both backends now call `agent_provision_plan` before `Egress.prepare` and `PipelockProxy.prepare`, threading `plan.egress_routes` to both. `has_provider_auth` is derived from `egress_manifest_routes` (manifest routes only — provider routes carry no auth roles, so the result is identical). Assisted-by: Claude Code
This commit is contained in:
@@ -5,6 +5,8 @@ git-gate (PRD 0008)."""
|
||||
|
||||
import unittest
|
||||
|
||||
from bot_bottle.agent_provider import CODEX_HOST_CREDENTIAL_HOSTS
|
||||
from bot_bottle.egress import CODEX_HOST_CREDENTIAL_TOKEN_REF, EgressRoute
|
||||
from bot_bottle.manifest import Manifest
|
||||
from bot_bottle.pipelock import (
|
||||
pipelock_effective_allowlist,
|
||||
@@ -116,17 +118,23 @@ class TestTlsPassthrough(unittest.TestCase):
|
||||
def test_forward_host_credentials_passes_through_codex_hosts(self):
|
||||
# Egress injects the host bearer on the Codex API hosts; pipelock
|
||||
# must pass them through or its header DLP blocks the injected JWT
|
||||
# ("request header contains secret"). These routes are auto-added
|
||||
# (not in bottle.egress.routes), so passthrough is host-derived.
|
||||
passthrough = pipelock_effective_tls_passthrough(_bottle({
|
||||
"agent_provider": {
|
||||
"template": "codex",
|
||||
"forward_host_credentials": True,
|
||||
},
|
||||
}))
|
||||
# ("request header contains secret"). Provider routes carry
|
||||
# tls_passthrough=True; pipelock reads this via egress_routes_for_bottle.
|
||||
provider_routes = tuple(
|
||||
EgressRoute(
|
||||
host=host,
|
||||
auth_scheme="Bearer",
|
||||
token_ref=CODEX_HOST_CREDENTIAL_TOKEN_REF,
|
||||
tls_passthrough=True,
|
||||
)
|
||||
for host in CODEX_HOST_CREDENTIAL_HOSTS
|
||||
)
|
||||
passthrough = pipelock_effective_tls_passthrough(
|
||||
_bottle({}), provider_routes,
|
||||
)
|
||||
self.assertEqual(["api.openai.com", "chatgpt.com"], passthrough)
|
||||
|
||||
def test_no_codex_passthrough_without_forward_host_credentials(self):
|
||||
def test_no_codex_passthrough_without_provider_routes(self):
|
||||
passthrough = pipelock_effective_tls_passthrough(_bottle({
|
||||
"agent_provider": {"template": "codex"},
|
||||
}))
|
||||
|
||||
Reference in New Issue
Block a user