Cover HIPAA §(J) account numbers; split hipaa.rs by posture - #395
Merged
Conversation
Before this change HIPAA Safe Harbor / Limited Data Set / Expert
Determination scoped `bank_account` alone under §(J). Real §(J) —
"account numbers" per §164.514(b)(2)(i)(J) and §164.514(e)(2)(x) —
covers every individual-linked account identifier the pattern set
detects: also `iban`, `payment_card`, and (under the §(R)
catch-all reading) `crypto_address`.
Add a `HipaaAccountNumbers` enum on `PolicyTemplate::HipaaDeidentification`
picking the account label scope:
- `Standard` (default): `bank_account` + `iban` + `payment_card`.
The traditional §(J) reading; matches every de-ID vendor's
Safe Harbor preset.
- `Extended`: adds `crypto_address`. Deployments where wallet
addresses can appear in patient-facing artifacts opt in.
Both tiers apply uniformly across Safe Harbor, LDS, and Expert
Determination — §(J) scope is a property of the identifier list,
not the removal method. Threaded through `hipaa::template()` and
the three per-method builders. Caller-side change is one new
`accounts` field on the wire (`#[serde(default)]` so callers
already sending `{"method": "safe_harbor"}` continue to work).
While in there, split the 800-line `hipaa.rs` into a `hipaa/`
folder — one file per posture (`safe_harbor.rs`, `limited_data_set.rs`,
`expert_determination.rs`), one file for the account-tier enum
(`account_numbers.rs`), shared items and tests in `mod.rs`. Each
posture owns its own constants and UUIDs; Expert Determination
reaches into `safe_harbor` for the shared 18-identifier label set.
New tests:
- `standard_accounts_cover_the_traditional_section_j_set` — pins
the Standard tier.
- `extended_accounts_add_crypto_to_the_standard_set` — pins
Extended.
- `account_tier_lands_in_every_hipaa_method` — verifies the tier
widens every method's policy scope.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Before this change HIPAA Safe Harbor / Limited Data Set / Expert Determination scoped `bank_account` alone under `§(J)`. Real `§(J)` — "account numbers" per `§164.514(b)(2)(i)(J)` and `§164.514(e)(2)(x)` — covers every individual-linked account identifier the pattern set detects: also `iban`, `payment_card`, and (under the `§(R)` catch-all reading) `crypto_address`.
That's why the customer-onboarding CSV under HIPAA Expert Determination silently left IBAN, credit-card, and crypto values untouched.
API
Adds a `HipaaAccountNumbers` enum on `PolicyTemplate::HipaaDeidentification`:
Both tiers apply uniformly across Safe Harbor, LDS, and Expert Determination — `§(J)` scope is a property of the identifier list, not the removal method. Threaded through `hipaa::template()` and the three per-method builders. `accounts` is `#[serde(default)]`, so callers already sending `{"method": "safe_harbor"}` continue to work.
Research
HHS OCR's 2012 guidance doesn't narrow "account numbers"; in practice covered entities and de-ID vendors (AWS Comprehend Medical, Google Cloud DLP, etc.) treat bank accounts + IBAN + payment cards as the core §(J) set. The reg does NOT sanction a "Basic vs Extended" split within the four labels themselves — every account identifier is a removable §(J) item — but there IS meaningful ambiguity around crypto wallets (a newer instrument that the reg reads via §(R) catch-all), which is exactly what `Standard` vs `Extended` splits.
Folder split
While in there, split the 800-line `hipaa.rs` into a `hipaa/` folder:
Each posture owns its own labels; Expert Determination reaches into `safe_harbor` for the shared 18-identifier label set.
New tests
Test plan
🤖 Generated with Claude Code