"""Unit: the addon's verdict function pinning pipelock-block vs. relayed-upstream 4xx. The fingerprint shape is the contract the addon depends on; this test should break loudly if pipelock changes its 403-body prefix under a version bump.""" from __future__ import annotations import unittest from claude_bottle.mitmproxy.addon import is_pipelock_block class TestIsPipelockBlock(unittest.TestCase): def test_block_dlp_body(self): # Pipelock v2.3.0 DLP block, captured in the impl spike. self.assertTrue(is_pipelock_block( 403, b"blocked: request body contains secret: GitHub Token", )) def test_block_allowlist_body(self): # Pipelock v2.3.0 allowlist block, captured in the impl spike. self.assertTrue(is_pipelock_block( 403, b"blocked: domain not in allowlist: example.com", )) def test_block_header_dlp_body(self): # Header DLP path; same body prefix per the spike. self.assertTrue(is_pipelock_block( 403, b"blocked: request header Authorization contains secret", )) def test_403_without_blocked_prefix_is_not_a_block(self): # A real-upstream 403 relayed by pipelock — body is whatever # the upstream sent, almost certainly not starting with # `blocked: `. Must be treated as allow so the addon hands # the flow back to mitmproxy. self.assertFalse(is_pipelock_block( 403, b'{"error":"forbidden","detail":"insufficient permissions"}', )) def test_non_403_with_blocked_prefix_is_not_a_block(self): # Defensive: if some intermediate ever returns 502/504 with # a body that happens to begin `blocked: `, we should still # not short-circuit. Block status is always 403 by contract. self.assertFalse(is_pipelock_block(502, b"blocked: ...")) def test_200_is_not_a_block(self): # Allow path, normal forwarded response. self.assertFalse(is_pipelock_block(200, b'{"ok":true}')) def test_empty_body_is_not_a_block(self): self.assertFalse(is_pipelock_block(403, b"")) if __name__ == "__main__": unittest.main()