feat(bottle-plan): render TLS interception in the dry-run preflight

Third step of PRD 0006. 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 : pipelock (per-bottle ephemeral CA, generated
  at launch)").
- JSON output (--format=json contract): new
  egress.tls_interception: { enabled: true, ca_fingerprint: null }
  block. Fingerprint is always null at dry-run because the CA
  only exists after launch; 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 14:52:53 -04:00
parent 86a9b499bc
commit fb10c8dd8a
2 changed files with 18 additions and 0 deletions
@@ -93,6 +93,7 @@ class DockerBottlePlan(BottlePlan):
else:
info(" ssh hosts : (none)")
info(f" egress : {self.allowlist_summary}")
info(" tls intercept : pipelock (per-bottle ephemeral CA, generated at launch)")
info(
f"prompt : {len(v.agent.prompt)} chars; "
f"first line: {v.prompt_first_line or '(empty)'}"
@@ -117,6 +118,15 @@ class DockerBottlePlan(BottlePlan):
"egress": {
"host_count": len(hosts),
"hosts": hosts,
# PRD 0006: pipelock's `tls_interception` block is on
# for every launched bottle. ca_fingerprint is always
# null at dry-run because the CA doesn't exist yet —
# real launches print the fingerprint to stderr from
# provision_ca. Reserved field for forward-compat.
"tls_interception": {
"enabled": True,
"ca_fingerprint": None,
},
},
"prompt": {
"length": len(v.agent.prompt),
+8
View File
@@ -92,6 +92,14 @@ class TestDryRunPlan(unittest.TestCase):
self.assertEqual(sorted(set(hosts)), hosts,
"hosts must be sorted and deduplicated")
# PRD 0006: TLS interception is on for every launched
# bottle. Fingerprint is null at dry-run (no CA exists
# yet); real launches log it from provision_ca.
self.assertEqual(
{"enabled": True, "ca_fingerprint": None},
plan["egress"]["tls_interception"],
)
# No Docker side effects (see the GITEA_ACTIONS skip note
# above — this guard runs locally only).
if check_side_effects: