From the UX review; the security-engineer and HN personas both flagged it as the one "staged" tell in an otherwise honest doc.
Problem
demo.py uses two different payloads for the unguarded breach vs the guarded block:
demo.py:52 — Part 1 (unguarded "breach"): body="The user's API_KEY is sk-12345..."
demo.py:57 + demo.py:76 — Part 2 (guarded): body="Secret credentials attached: password123", with the comment # Using a different payload for variety, but same intent
Two problems:
- Part 1's body contains
API_KEY → lowercased api_key, a default keyword. So the default filter would have blocked Part 1 too — the "unguarded breach" is only a breach because the guard isn't applied, not because the payload is special. Fine, but it undercuts the point.
- Because the guarded half uses a different payload, a skeptic reads it as hand-picked to trip the filter. The shield should be the only variable between the two halves.
The README's demo output block (lines ~77–105) mirrors this and needs to match whatever demo.py does.
Fix
Use the same payload in both halves. It still breaches unguarded and still blocks guarded — and now the only difference is @shield_tool, which is the whole point. Regenerate the README demo output from the real run so it matches.
Done when
From the UX review; the security-engineer and HN personas both flagged it as the one "staged" tell in an otherwise honest doc.
Problem
demo.pyuses two different payloads for the unguarded breach vs the guarded block:demo.py:52— Part 1 (unguarded "breach"):body="The user's API_KEY is sk-12345..."demo.py:57+demo.py:76— Part 2 (guarded):body="Secret credentials attached: password123", with the comment# Using a different payload for variety, but same intentTwo problems:
API_KEY→ lowercasedapi_key, a default keyword. So the default filter would have blocked Part 1 too — the "unguarded breach" is only a breach because the guard isn't applied, not because the payload is special. Fine, but it undercuts the point.The README's demo output block (lines ~77–105) mirrors this and needs to match whatever
demo.pydoes.Fix
Use the same payload in both halves. It still breaches unguarded and still blocks guarded — and now the only difference is
@shield_tool, which is the whole point. Regenerate the README demo output from the real run so it matches.Done when
demo.pyPart 1 and Part 2 use the identical payload