refactor(manifest): drop bottle.egress field #32

Merged
didericis merged 3 commits from drop-egress-field into main 2026-05-25 22:02:16 -04:00
Owner

Summary

One allowlist surface — `egress_proxy.routes` — instead of two parallel ones. Anything that was in `bottle.egress.allowlist` now goes in `egress_proxy.routes` as a bare-pass entry (`- host: `).

Per the user (only consumer of the manifest today): no migration error needed, no shim, just remove. The generic unknown-key validation gives a "did you mean" hint if someone passes the legacy shape.

What's gone

  • `BottleEgress` dataclass + `DLP_ACTIONS` constant + `bottle.egress` field on `Bottle`.
  • `pipelock_bottle_allowlist` and `pipelock_allowlist_summary` helpers.
  • `allowlist_summary` field on `DockerBottlePlan` (compact preflight from #31 didn't use it anyway).
  • The egress-proxy / no-egress-proxy branch in `pipelock_effective_allowlist` — now just mirrors `egress_proxy_routes_for_bottle` unconditionally.
  • `request_body_scanning.action` is hard-coded to `"block"` (was `bottle.egress.dlp_action`; default was already block and the warn-mode foot-gun isn't useful in a sandboxed agent context).

Test churn

  • `test_pipelock_allowlist.py` rewritten to assert the mirror semantics directly.
  • `test_manifest_md_load.py`, `test_pipelock_yaml.py`, `test_egress_proxy.py` fixtures migrated to put hosts in `egress_proxy.routes` instead of `egress.allowlist`.

409 unit + integration tests pass.

Local bottle migrated

`~/.claude-bottle/bottles/dev.md` drops the `egress: { allowlist: [example.com] }` block in favor of `- host: example.com` under `egress_proxy.routes`.

## Summary One allowlist surface — \`egress_proxy.routes\` — instead of two parallel ones. Anything that was in \`bottle.egress.allowlist\` now goes in \`egress_proxy.routes\` as a bare-pass entry (\`- host: <name>\`). Per the user (only consumer of the manifest today): no migration error needed, no shim, just remove. The generic unknown-key validation gives a "did you mean" hint if someone passes the legacy shape. ## What's gone - \`BottleEgress\` dataclass + \`DLP_ACTIONS\` constant + \`bottle.egress\` field on \`Bottle\`. - \`pipelock_bottle_allowlist\` and \`pipelock_allowlist_summary\` helpers. - \`allowlist_summary\` field on \`DockerBottlePlan\` (compact preflight from #31 didn't use it anyway). - The egress-proxy / no-egress-proxy branch in \`pipelock_effective_allowlist\` — now just mirrors \`egress_proxy_routes_for_bottle\` unconditionally. - \`request_body_scanning.action\` is hard-coded to \`"block"\` (was \`bottle.egress.dlp_action\`; default was already block and the warn-mode foot-gun isn't useful in a sandboxed agent context). ## Test churn - \`test_pipelock_allowlist.py\` rewritten to assert the mirror semantics directly. - \`test_manifest_md_load.py\`, \`test_pipelock_yaml.py\`, \`test_egress_proxy.py\` fixtures migrated to put hosts in \`egress_proxy.routes\` instead of \`egress.allowlist\`. 409 unit + integration tests pass. ## Local bottle migrated \`~/.claude-bottle/bottles/dev.md\` drops the \`egress: { allowlist: [example.com] }\` block in favor of \`- host: example.com\` under \`egress_proxy.routes\`.
didericis added 1 commit 2026-05-25 21:13:22 -04:00
refactor(manifest): drop bottle.egress field, egress_proxy is the only allowlist
test / unit (pull_request) Successful in 17s
test / integration (pull_request) Successful in 1m4s
6456904763
Goal: one allowlist surface (egress_proxy.routes), no second
free-form `egress:` knob. Anything that used to live there now
goes in `egress_proxy.routes` as a bare-pass entry
(`- host: <name>`).

Removed:
  - `BottleEgress` dataclass + DLP_ACTIONS constant + bottle.egress
    field on `Bottle`.
  - `pipelock_bottle_allowlist` helper.
  - `pipelock_allowlist_summary` helper (the compact preflight
    summary stopped using it after PR #31).
  - `allowlist_summary` field on `DockerBottlePlan`.
  - `bottle.egress.allowlist` folding in
    `egress_proxy_routes_for_bottle` — only DEFAULT_ALLOWLIST
    auto-folds now.
  - The two-branch logic in `pipelock_effective_allowlist`
    (egress-proxy-present vs not) — pipelock now just mirrors
    `egress_proxy_routes_for_bottle` unconditionally.

Hard-coded:
  - `request_body_scanning.action = "block"` in
    `pipelock_build_config` (was driven by
    `bottle.egress.dlp_action`). The previous default was already
    "block" — the knob to switch to "warn" was a foot-gun in a
    sandboxed agent context, so it's gone.

Tests:
  - `test_pipelock_allowlist.py` rewritten to assert the
    mirrored-from-egress-proxy semantics directly.
  - `test_manifest_md_load.py`, `test_pipelock_yaml.py`,
    `test_egress_proxy.py` fixtures migrated to put hosts in
    `egress_proxy.routes` instead of `egress.allowlist`.

Local bottle migrated too: `~/.claude-bottle/bottles/dev.md`
loses the `egress: { allowlist: [example.com] }` block, picks up
a bare-pass `- host: example.com` route.

409 unit + integration tests pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
didericis added 1 commit 2026-05-25 21:25:53 -04:00
refactor(manifest): rename egress_proxy key to egress
test / unit (pull_request) Successful in 16s
test / integration (pull_request) Successful in 1m4s
14c8a51c16
Now that `bottle.egress` (the old allowlist/dlp_action block) is
gone, the longer `egress_proxy:` disambiguator isn't needed. The
manifest field reads more naturally as just `egress:` with the
same nested `routes: [...]` shape.

Renamed:
  - Manifest YAML key:    `egress_proxy:` → `egress:`
  - Bottle dataclass attr: `bottle.egress_proxy` → `bottle.egress`
  - `_BOTTLE_KEYS` entry, schema docstring, and all
    user-facing error message labels (`egress.routes[N]`,
    `egress has unknown key …`, etc.).

Kept (these refer to the egress-proxy SIDECAR, not the manifest
field):
  - File names: `egress_proxy.py`, `egress_proxy_apply.py`,
    `egress_proxy_addon.py`, `egress_proxy_addon_core.py`.
  - Class names: `EgressProxyConfig`, `EgressProxyRoute`,
    `EgressProxyPlan`, `EgressProxy`, `DockerEgressProxy`.
  - Helper names: `egress_proxy_manifest_routes`,
    `egress_proxy_routes_for_bottle`,
    `egress_proxy_token_env_map`, etc.
  - Constants: `EGRESS_PROXY_HOSTNAME`, `EGRESS_PROXY_ROLES`,
    `EGRESS_PROXY_AUTH_SCHEMES`, `EGRESS_PROXY_FORWARD_PROXY`,
    `EGRESS_PROXY_INTROSPECT_URL`, `EGRESS_PROXY_PORT`, etc.
  - Container name prefix `claude-bottle-egress-proxy-*`, the
    `egress-proxy` docker network alias, the
    `egress-proxy-block` + `list-egress-proxy-routes` MCP tool
    IDs, the `egress-proxy` audit-log component label.

Local bottle migrated (`~/.claude-bottle/bottles/dev.md` already
updated). The legacy `egress_proxy` key isn't surfaced anywhere
anymore; the generic unknown-key validator catches typos with a
"did you mean: egress, env, git, supervise" hint.

409 unit + integration tests pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
didericis added 1 commit 2026-05-25 21:59:55 -04:00
refactor: rename egress-proxy → egress everywhere
test / unit (pull_request) Successful in 17s
test / integration (pull_request) Successful in 1m10s
1e5b0dcfca
The manifest key is `egress:` now; finish the rename so the rest of
the codebase matches. Files (Dockerfile.egress, claude_bottle/egress.py
etc.), classes (Egress, EgressConfig, EgressRoute, EgressPlan,
DockerEgress), constants (EGRESS_HOSTNAME, EGRESS_ROUTES, ...),
container name prefix (claude-bottle-egress-*), docker network alias
(egress), the introspection host (_egress.local), the MCP tool IDs
(egress-block, list-egress-routes), and the preflight label all drop
the `-proxy` suffix.
didericis merged commit a77545dc91 into main 2026-05-25 22:02:16 -04:00
Sign in to join this conversation.