Address Greptile review: add contextual guards and negative tests

- Added keyword_pattern to eu_vat (VAT, tax number, fiscal code, etc.)
- Added keyword_pattern to eu_passport_generic (passport, travel document, etc.)
- Added 3 negative unit tests for false positive prevention
- Added 2 E2E tests verifying no masking without keyword context
- All patterns now require contextual keywords to prevent false positives
This commit is contained in:
Ishaan Jaffer 2026-02-16 14:20:56 -08:00
parent bca058e1c2
commit 4542f3256f

View file

@ -153,10 +153,11 @@ class TestGDPRPolicyE2E:
@pytest.mark.asyncio
async def test_eu_vat_masked(self):
"""
Test 4 - SHOULD MASK: EU VAT number is detected and masked
Test 4 - SHOULD MASK: EU VAT number with keyword context is detected and masked
"""
guardrail = self.setup_gdpr_guardrail()
# Include VAT keyword for contextual matching
text = "Company VAT number is FR12345678901"
guardrailed_inputs = await guardrail.apply_guardrail(
inputs={"texts": [text]},
@ -265,3 +266,44 @@ class TestGDPRPolicyE2E:
assert "jean@example.com" not in result
assert "+33612345678" not in result
assert "192057512345678" not in result
@pytest.mark.asyncio
async def test_vat_number_without_keyword_context_passes(self):
"""
Test 10 - SHOULD NOT MASK: VAT-like pattern without keyword context
Contextual keyword guard prevents false positives
"""
guardrail = self.setup_gdpr_guardrail()
# Text with VAT-like format but no VAT keyword context
text = "Product code FR12345678 for the shipment"
guardrailed_inputs = await guardrail.apply_guardrail(
inputs={"texts": [text]},
request_data={},
input_type="request",
)
result = guardrailed_inputs.get("texts", [])[0]
# Should not mask without VAT keyword context
assert "FR12345678" in result
assert "REDACTED" not in result
@pytest.mark.asyncio
async def test_passport_number_without_keyword_context_passes(self):
"""
Test 11 - SHOULD NOT MASK: Passport-like pattern without keyword context
Contextual keyword guard prevents false positives
"""
guardrail = self.setup_gdpr_guardrail()
# Text with passport-like format but no passport keyword context
text = "Reference number 12AB34567 for your order"
guardrailed_inputs = await guardrail.apply_guardrail(
inputs={"texts": [text]},
request_data={},
input_type="request",
)
result = guardrailed_inputs.get("texts", [])[0]
# Should not mask without passport keyword context
assert "12AB34567" in result
assert "REDACTED" not in result