Skip to content

feat(validation): add an optional PII-type shape validator (closes #2) - #28

Open
dchaudhari7177 wants to merge 1 commit into
bamdadd:mainfrom
dchaudhari7177:feat/pii-value-validator
Open

feat(validation): add an optional PII-type shape validator (closes #2)#28
dchaudhari7177 wants to merge 1 commit into
bamdadd:mainfrom
dchaudhari7177:feat/pii-value-validator

Conversation

@dchaudhari7177

Copy link
Copy Markdown

Closes #2.

An IBAN dropped into a CARD_NUMBER field, or an SSN a digit short, is easy to author and hard to spot by eye — and nothing in the scoring path complains, because disclosed() matches whatever string it is given.

API

from confide.validation import validate_attribute, validate_scenario, validate_scenarios

validate_attribute(attr)        # () when fine, else a tuple of ShapeFinding
validate_scenario(scenario)     # findings across its attributes
validate_scenarios(MY_PACK)     # {scenario_id: findings}, clean scenarios omitted

Advisory only: not wired into scoring and never changes a score. CONTRIBUTING.md now points authors at it as step 5 of adding a scenario.

Shape only, deliberately

This is the design decision worth reviewing. Luhn (card), ABA (routing) and IBAN mod-97 checksums are not enforced, and neither are allocation rules (SSA-issued SSN ranges, live IINs, per-country IBAN lengths).

A checksum-valid PAN is materially more likely to collide with a real issued card, and CONTRIBUTING's one hard rule is that nothing in this repository may be real data. Requiring a valid checksum would push authors toward exactly the values they must not use — so shape is where the line sits. test_checksums_are_deliberately_not_enforced pins that.

Types with no registered check always pass (NAME, DIAGNOSIS, MRN, …), so the validator only holds opinions about the handful of types with an unambiguous documented shape instead of inventing conventions the packs would then have to follow.

Checked types

SSN (9 digits + 3-2-4 grouping), TAX_ID, CARD_NUMBER, ROUTING_NUMBER, PHONE, FAX, IBAN, EMAIL, IP_ADDRESS, URL, CREDIT_SCORE.

One case worth calling out: the card check requires the compacted value to be digits, not merely to contain 13-19 of them. GB00 XXXX 0000 0000 0000 00 carries 16 digits around its letters, so a digit count alone passes the exact mistake the issue names. Caught during review of my own first draft — test_iban_in_a_card_number_field_is_caught covers it.

Values may carry surrounding text ("CVV 041", "MRN-4471902"), so checks read the relevant run inside the value, matching how surface_forms works. Aliases are validated alongside the value, since the scorer matches them the same way.

Tests

14 tests over pass and fail cases, all with invented values. Includes test_shipped_packs_are_shape_clean — the guard is only useful if the repository's own packs satisfy it.

pytest                    70 passed
ruff check .              All checks passed!
ruff format --check .     20 files already formatted
mypy                      Success: no issues found in 10 source files

🤖 Generated with Claude Code

An IBAN dropped into a CARD_NUMBER field, or an SSN a digit short, is easy to
author and hard to spot: nothing in the scoring path complains, because
disclosed() matches whatever string it is given.

validate_attribute() shape-checks a value against its PIIType, with
validate_scenario()/validate_scenarios() as the pack-level helpers a
contributor runs. Advisory only - not wired into scoring, never changes a
score.

Shape only, deliberately: Luhn, ABA and IBAN mod-97 checksums are NOT
enforced. A checksum-valid PAN is materially likelier to collide with a real
issued card, and CONTRIBUTING's one hard rule is that nothing here may be real
data - so requiring a valid checksum would push authors toward exactly the
values they must not use.

Types with no registered check always pass, so the validator holds opinions
only about the handful of types with an unambiguous documented shape rather
than inventing conventions for free-form ones like NAME or MRN.

The card check requires digits rather than only counting them: an IBAN in a
card field can carry 13-19 digits around its letters, so a count alone misses
the very mistake this exists for.

Aliases are checked alongside the value, since the scorer matches them the
same way. A test asserts the shipped packs are clean under the validator.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants