feat(mitmproxy): render mitmproxy in the dry-run preflight

Third step of PRD 0005. The preflight now surfaces the TLS-
intercept layer so the operator sees it before agreeing to launch.

- Text output: one new line under the egress summary —
  "tls intercept : mitmproxy (per-bottle ephemeral CA, generated
  at launch)".
- JSON output (--format=json contract): new
  egress.mitm: { enabled: true, ca_fingerprint: null } block.
  Fingerprint is always null at dry-run because the CA only
  exists after the sidecar starts; real launches print it as a
  stderr log line from provision_ca.
- Pin the new shape in the dry-run integration test.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-12 13:40:31 -04:00
parent 21054212d4
commit c4de42ea3c
2 changed files with 15 additions and 0 deletions
@@ -95,6 +95,7 @@ class DockerBottlePlan(BottlePlan):
else:
info(" ssh hosts : (none)")
info(f" egress : {self.allowlist_summary}")
info(" tls intercept : mitmproxy (per-bottle ephemeral CA, generated at launch)")
info(
f"prompt : {len(v.agent.prompt)} chars; "
f"first line: {v.prompt_first_line or '(empty)'}"
@@ -119,6 +120,14 @@ class DockerBottlePlan(BottlePlan):
"egress": {
"host_count": len(hosts),
"hosts": hosts,
# Reserved for PRD 0005: TLS interception via mitmproxy.
# ca_fingerprint is always null at dry-run because the
# CA is generated by the sidecar at launch time. Real
# launches print the fingerprint to stderr.
"mitm": {
"enabled": True,
"ca_fingerprint": None,
},
},
"prompt": {
"length": len(v.agent.prompt),
+6
View File
@@ -92,6 +92,12 @@ class TestDryRunPlan(unittest.TestCase):
self.assertEqual(sorted(set(hosts)), hosts,
"hosts must be sorted and deduplicated")
# PRD 0005: TLS interception block is part of the JSON
# contract. Fingerprint is null at dry-run (CA doesn't
# exist yet); real launches print it to stderr.
self.assertEqual({"enabled": True, "ca_fingerprint": None},
plan["egress"]["mitm"])
# No Docker side effects (see the GITEA_ACTIONS skip note
# above — this guard runs locally only).
if check_side_effects: