From 6066bb4d4c5443a504c3acd74caa5a3185b9a534 Mon Sep 17 00:00:00 2001 From: didericis Date: Mon, 25 May 2026 08:28:29 -0400 Subject: [PATCH] fix(dashboard): show the literal new allowlist line in green, no prefix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "→ would allow host: api.github.com" framing added narration where none was needed. Just render the host on its own line in green — that's literally the text that gets appended to pipelock's allowlist on approve, and the green color carries "what's about to change". The URL (with path) is still right above for context. Co-Authored-By: Claude Opus 4.7 --- claude_bottle/cli/dashboard.py | 7 +++++- tests/unit/test_dashboard_detail_lines.py | 30 +++++++++++------------ 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/claude_bottle/cli/dashboard.py b/claude_bottle/cli/dashboard.py index 8880b5a..de8c154 100644 --- a/claude_bottle/cli/dashboard.py +++ b/claude_bottle/cli/dashboard.py @@ -637,8 +637,13 @@ def _detail_lines( if p.tool == TOOL_PIPELOCK_BLOCK: host = _failed_url_host(p.proposed_file) if host: + # Show the literal line that will be appended to the + # bottle's pipelock allowlist on approve. Green so it + # reads as "what changes"; the URL above carries the + # path context (which pipelock can't enforce — see the + # follow-up note on _apply_pipelock_url). out.append(("", 0)) - out.append((f"→ would allow host: {host}", green_attr)) + out.append((host, green_attr)) return out diff --git a/tests/unit/test_dashboard_detail_lines.py b/tests/unit/test_dashboard_detail_lines.py index 99a1c87..918ceb3 100644 --- a/tests/unit/test_dashboard_detail_lines.py +++ b/tests/unit/test_dashboard_detail_lines.py @@ -40,38 +40,35 @@ class TestPipelockHostHighlight(unittest.TestCase): _qp(TOOL_PIPELOCK_BLOCK, "https://api.github.com/repos/foo/bar"), green_attr=self.GREEN, ) - host_lines = [ - (text, attr) for text, attr in lines - if text.startswith("→ would allow host:") - ] - self.assertEqual(1, len(host_lines)) - text, attr = host_lines[0] - self.assertEqual("→ would allow host: api.github.com", text) - self.assertEqual(self.GREEN, attr) + # The host appears as its own green-tagged line — literal + # text of what gets appended to pipelock's allowlist on + # approve. + green_lines = [text for text, attr in lines if attr == self.GREEN] + self.assertEqual(["api.github.com"], green_lines) - def test_no_host_line_for_cred_proxy_block(self): + def test_no_green_lines_for_cred_proxy_block(self): lines = dashboard._detail_lines( _qp(TOOL_CRED_PROXY_BLOCK, '{"routes": []}'), green_attr=self.GREEN, ) - self.assertFalse(any("would allow host" in t for t, _ in lines)) + self.assertEqual([], [t for t, a in lines if a == self.GREEN]) - def test_no_host_line_for_capability_block(self): + def test_no_green_lines_for_capability_block(self): lines = dashboard._detail_lines( _qp(TOOL_CAPABILITY_BLOCK, "FROM python:3.13\n"), green_attr=self.GREEN, ) - self.assertFalse(any("would allow host" in t for t, _ in lines)) + self.assertEqual([], [t for t, a in lines if a == self.GREEN]) def test_skips_host_line_when_url_unparseable(self): # Shouldn't happen in production — supervise_server validates # the URL before queuing — but if a malformed payload ever - # reaches the dashboard, don't add a misleading host line. + # reaches the dashboard, don't render a misleading host line. lines = dashboard._detail_lines( _qp(TOOL_PIPELOCK_BLOCK, "garbage-not-a-url"), green_attr=self.GREEN, ) - self.assertFalse(any("would allow host" in t for t, _ in lines)) + self.assertEqual([], [t for t, a in lines if a == self.GREEN]) def test_no_green_attr_passed_still_renders_host(self): # Even without color support (green_attr=0), the host line @@ -80,8 +77,9 @@ class TestPipelockHostHighlight(unittest.TestCase): _qp(TOOL_PIPELOCK_BLOCK, "https://api.github.com/x"), green_attr=0, ) - host_lines = [t for t, _ in lines if t.startswith("→ would allow host:")] - self.assertEqual(["→ would allow host: api.github.com"], host_lines) + # Last non-empty line should be the host. + non_empty = [t for t, _ in lines if t] + self.assertEqual("api.github.com", non_empty[-1]) class TestFailedUrlHost(unittest.TestCase):