refactor(egress): make Egress a service class in an egress package
tracker-policy-pr / check-pr (pull_request) Successful in 10s
test / integration-docker (pull_request) Successful in 17s
test / unit (pull_request) Successful in 46s
lint / lint (push) Failing after 2m44s
test / integration-firecracker (pull_request) Successful in 3m35s
test / coverage (pull_request) Successful in 20s
test / publish-infra (pull_request) Has been skipped
tracker-policy-pr / check-pr (pull_request) Successful in 10s
test / integration-docker (pull_request) Successful in 17s
test / unit (pull_request) Successful in 46s
lint / lint (push) Failing after 2m44s
test / integration-firecracker (pull_request) Successful in 3m35s
test / coverage (pull_request) Successful in 20s
test / publish-infra (pull_request) Has been skipped
Split the flat egress.py into an egress/ package: neutral DTOs (EgressRoute, EgressPlan) in plan.py, and the concrete Egress service class plus rendering/env helpers in service.py, behind a thin __getattr__ facade so leaf imports stay cheap. Egress drops ABC and becomes a concrete service the backends call: resolve_token_values / agent_env_entries / prepare are now methods. Backend launch paths (docker, firecracker, macos_container) call Egress().<method>(...) instead of the module-level functions. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
"""Per-agent egress (PRD 0017).
|
||||
|
||||
The egress gateway is a TLS-terminating forward proxy that allow-lists a
|
||||
bottle's outbound HTTP(S), scans payloads for secret exfil, and injects
|
||||
per-route upstream credentials the agent never sees.
|
||||
|
||||
Layout:
|
||||
|
||||
* `service` — the `Egress` host-side service (`prepare` the launch plan,
|
||||
`resolve_token_values`, `agent_env_entries`) + the route-building /
|
||||
rendering functions.
|
||||
* `plan` — `EgressPlan` / `EgressRoute`, the launch DTOs (in the backend
|
||||
contract).
|
||||
|
||||
The runtime enforcement (the mitmproxy addon) lives in
|
||||
`bot_bottle.gateway.egress_addon*`. Public names are re-exported lazily via
|
||||
`__getattr__`, so `from bot_bottle.egress import …` keeps working and importing
|
||||
`egress.plan` (the contract's dependency) stays light.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .plan import EgressPlan, EgressRoute
|
||||
from .service import (
|
||||
CLAUDE_HOST_CREDENTIAL_TOKEN_REF,
|
||||
CODEX_HOST_CREDENTIAL_TOKEN_REF,
|
||||
EGRESS_HOSTNAME,
|
||||
EGRESS_ROUTES_FILENAME,
|
||||
EGRESS_ROUTES_IN_CONTAINER,
|
||||
Egress,
|
||||
egress_agent_env_entries,
|
||||
egress_gateway_env_entries,
|
||||
egress_manifest_routes,
|
||||
egress_render_routes,
|
||||
egress_resolve_token_values,
|
||||
egress_routes_for_bottle,
|
||||
egress_token_env_map,
|
||||
)
|
||||
|
||||
|
||||
_LAZY: dict[str, str] = {
|
||||
"EgressPlan": ".plan",
|
||||
"EgressRoute": ".plan",
|
||||
"Egress": ".service",
|
||||
"CLAUDE_HOST_CREDENTIAL_TOKEN_REF": ".service",
|
||||
"CODEX_HOST_CREDENTIAL_TOKEN_REF": ".service",
|
||||
"EGRESS_HOSTNAME": ".service",
|
||||
"EGRESS_ROUTES_FILENAME": ".service",
|
||||
"EGRESS_ROUTES_IN_CONTAINER": ".service",
|
||||
"egress_agent_env_entries": ".service",
|
||||
"egress_gateway_env_entries": ".service",
|
||||
"egress_manifest_routes": ".service",
|
||||
"egress_render_routes": ".service",
|
||||
"egress_resolve_token_values": ".service",
|
||||
"egress_routes_for_bottle": ".service",
|
||||
"egress_token_env_map": ".service",
|
||||
}
|
||||
|
||||
|
||||
def __getattr__(name: str) -> Any:
|
||||
src = _LAZY.get(name)
|
||||
if src is None:
|
||||
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
||||
from importlib import import_module
|
||||
|
||||
value = getattr(import_module(src, __name__), name)
|
||||
globals()[name] = value
|
||||
return value
|
||||
|
||||
|
||||
__all__ = [
|
||||
"CLAUDE_HOST_CREDENTIAL_TOKEN_REF",
|
||||
"CODEX_HOST_CREDENTIAL_TOKEN_REF",
|
||||
"EGRESS_HOSTNAME",
|
||||
"EGRESS_ROUTES_FILENAME",
|
||||
"EGRESS_ROUTES_IN_CONTAINER",
|
||||
"Egress",
|
||||
"EgressPlan",
|
||||
"EgressRoute",
|
||||
"egress_manifest_routes",
|
||||
"egress_render_routes",
|
||||
"egress_resolve_token_values",
|
||||
"egress_routes_for_bottle",
|
||||
"egress_agent_env_entries",
|
||||
"egress_gateway_env_entries",
|
||||
"egress_token_env_map",
|
||||
]
|
||||
Reference in New Issue
Block a user