Skip to content

docs: lead the README with what the package does and a quick start - #23

Merged
abrichr merged 6 commits into
mainfrom
docs/plain-readme
Oct 14, 2026
Merged

abrichr merged 6 commits into
mainfrom
docs/plain-readme

Conversation

@abrichr

@abrichr abrichr commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

Summary

Rewrites the README for a developer who finds openadapt-privacy on GitHub or PyPI, and fixes the small issues the old README described instead of fixing.

README

  • The first screen says what the package removes, who it is for, and gives a two-command install with a one-line example.
  • Every Python example was run against this branch. tests/test_readme.py checks the quick start, scrub_dict, and recording outputs against the scrubber, so the README can't drift from the code.
  • Limits are in one short section: synthetic test data, English only, context-dependent placeholder names (a Luhn-failing card number such as 4111 1111 1111 1112 keeps its first eight digits), labelled street addresses only, OCR misses, and a regex-only CI scan.
  • Operator material (fail-closed behavior, the provenance record, review steps, the repository lifecycle link) moved to docs/COMPLIANCE.md, linked once.
  • Configuration is now documented through the config object. The old example built a PrivacyConfig that nothing read.
  • Adds the Tesseract requirement for screenshot scrubbing, which was missing.
  • The scrubbed demo screenshot is regenerated with current code. The old image came from the first release and showed the card number unredacted. The new one shows the real output, including the name in the dark title bar that Tesseract doesn't read; the README says so.
  • Image and link URLs are absolute, so they render on PyPI.

Code fixes

  • fix: Field labels stay readable: SSN: 923-45-6789 now scrubs to SSN: <US_SSN> instead of <ORGANIZATION>: <US_SSN>, and Email: ... to Email: <EMAIL_ADDRESS>. A label is dropped from the findings only when its whole text is a known label and another finding starts right after it, so the identifier is always still redacted. Labels that are also surnames (Ip, Sin) are not in the list, so Dr. Sin: 555-123-4567 still redacts the name, as 1.1.1 did.
  • fix: The street-address recognizer fired only after Home address: or Mail to, so Address: 42 Elm Road passed through unredacted. It now fires after any label ending in address:. The synthetic recall set grows from 26 to 27 cases.
  • fix: The SCRUB_FILL_COLOR docstring said the default was blue; it fills red (Pillow reads the integer as 0xBBGGRR).
  • fix: openadapt-privacy-scan --help printed maintainer notes from the module docstring. It now describes the scan and its exit codes, and a failed scan prints PHI scan failed: instead of PHI / clinic-path scan failed:.
  • CLAUDE.md used a class name that doesn't exist (PresidioScrubber). The PyPI summary is clearer.

Testing

  • uv run pytest: 178 passed (Python 3.12, Presidio and en_core_web_sm installed).
  • CI's no-Presidio job, reproduced on Python 3.10: 124 passed, 8 skipped.
  • Fresh venv: pip install "openadapt-privacy[presidio]" and python -m spacy download en_core_web_sm, then the quick start, using the published 1.1.1.
  • openadapt-privacy-scan --self-test and --root on a fresh install.
  • uv build, scripts/check_source_boundary.py --require-dist, and twine check: all pass.

Notes

  • Because of the fix: commits, merging triggers the semantic-release workflow to publish a patch release, which is also what updates the README on PyPI.
  • Not changed: the image path still sends OCR text straight to Presidio, so it doesn't apply the label or UI-imperative filters the text path uses (field labels next to identifiers are still boxed in screenshots), and Tesseract doesn't read light text on dark backgrounds. The OCR miss is listed under Limits; the extra label boxes only over-redact.

🤖 Generated with Claude Code

abrichr and others added 6 commits October 14, 2026 03:20
…label

The spaCy model read common field labels as entities, so "SSN: 923-45-6789"
came back as "<ORGANIZATION>: <US_SSN>" and "Email: john@example.com" as
"<PERSON>: <EMAIL_ADDRESS>". The README showed this as a surprise to work
around. A PERSON or ORGANIZATION span is now dropped when its whole text is a
known label (SSN, Email, DOB, MRN, and similar) and another finding starts
right after it. The identifier is still redacted; a label with nothing after
it, and a name in front of an identifier, are still redacted.

The street-address recognizer only fired after "Home address:" or "Mail to",
so "Address: 42 Elm Road" passed through. It now fires after any label that
ends in "address:". The synthetic recall set grows from 26 to 27 cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PrivacyConfig documented the default SCRUB_FILL_COLOR (0x0000FF) as blue.
Pillow reads an integer colour as 0xBBGGRR, so the default fills red, which
is what the demo screenshot shows. The docstring and comment now say so.

openadapt-privacy-scan --help printed the module docstring, including notes
for maintainers. It now describes what the scan checks and lists the exit
codes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rewrite the README for a developer who finds the package on GitHub or PyPI.
The first screen says what it removes, who it is for, and a two-command
install with a one-line example. Every Python example was run against the
current code, and tests/test_readme.py checks the quick start, scrub_dict,
and recording outputs against the scrubber.

- Put the limits in one Limits section: synthetic test data, English only,
  context-dependent labels, labelled street addresses only, OCR misses, and
  a regex-only CI scan.
- Move operator material (fail-closed behavior, the provenance record,
  review steps, and the repository lifecycle link) to docs/COMPLIANCE.md,
  linked once from the README.
- Document configuration through the config object. The old example built a
  PrivacyConfig that nothing read.
- Say that screenshot scrubbing needs the Tesseract binary.
- Regenerate the scrubbed demo screenshot with the current code; the old one
  came from the first release and showed the card number unredacted.
- Use absolute image and link URLs so they render on PyPI.
- Replace the README text pin in tests/test_scan.py with tests/test_readme.py.
- Fix the class name in CLAUDE.md (PresidioScrubber does not exist) and
  sharpen the PyPI summary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The field-label filter dropped a PERSON span whose whole text was a label
in front of another finding. "Ip" and "Sin" were in the label list, and both
are surnames, so "Dr. Sin: 555-123-4567" came back as
"Dr. Sin: <PHONE_NUMBER>" and "Sin john@example.com" as
"Sin <EMAIL_ADDRESS>". Release 1.1.1 redacted the name in both.

Remove "ip" and "sin" from the list. "IP address" and "social insurance
number" stay. "SIN:" and "IP:" labels go back to being redacted along with
the identifier after them, which over-redacts but leaks nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
openadapt-privacy-scan printed "PHI / clinic-path scan failed:" on a hit,
and scan_tree's docstring referred to an internal scanner. The message is
now "PHI scan failed:" and the docstring says what each line holds. The
help text says the scan checks the files in a directory, since it also runs
outside a git repository.

The config module docstring still said you could create a new PrivacyConfig.
Nothing reads one, so it now points to the module-level config instance.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Limits said a card number that fails the Luhn check is still redacted as
  <DATE_TIME>. "4111 1111 1111 1112" comes back as "4111 1111 <DATE_TIME>".
  The README now gives both cases, and tests/test_readme.py checks them.
- The scan section said it checks "a git tree". It checks the files in a
  directory, and in a git repository the tracked and unignored untracked
  files, not the history.
- gitleaks.toml and phi-patterns.txt carry the text patterns, not the
  file-type checks, so they aren't "the same rules".
- Spell out RPA, say the scan runs without Presidio instead of "needs no
  other packages", and explain the `uv pip install pip` step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@abrichr
abrichr merged commit 7b77e2c into main Oct 14, 2026
4 checks passed
@abrichr
abrichr deleted the docs/plain-readme branch October 14, 2026 09:28
abrichr added a commit that referenced this pull request Oct 18, 2026
* fix: keep field labels readable and find addresses after any address label

The spaCy model read common field labels as entities, so "SSN: 923-45-6789"
came back as "<ORGANIZATION>: <US_SSN>" and "Email: john@example.com" as
"<PERSON>: <EMAIL_ADDRESS>". The README showed this as a surprise to work
around. A PERSON or ORGANIZATION span is now dropped when its whole text is a
known label (SSN, Email, DOB, MRN, and similar) and another finding starts
right after it. The identifier is still redacted; a label with nothing after
it, and a name in front of an identifier, are still redacted.

The street-address recognizer only fired after "Home address:" or "Mail to",
so "Address: 42 Elm Road" passed through. It now fires after any label that
ends in "address:". The synthetic recall set grows from 26 to 27 cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: correct the fill colour docs and give the scan CLI real help text

PrivacyConfig documented the default SCRUB_FILL_COLOR (0x0000FF) as blue.
Pillow reads an integer colour as 0xBBGGRR, so the default fills red, which
is what the demo screenshot shows. The docstring and comment now say so.

openadapt-privacy-scan --help printed the module docstring, including notes
for maintainers. It now describes what the scan checks and lists the exit
codes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: lead the README with what the package does and a quick start

Rewrite the README for a developer who finds the package on GitHub or PyPI.
The first screen says what it removes, who it is for, and a two-command
install with a one-line example. Every Python example was run against the
current code, and tests/test_readme.py checks the quick start, scrub_dict,
and recording outputs against the scrubber.

- Put the limits in one Limits section: synthetic test data, English only,
  context-dependent labels, labelled street addresses only, OCR misses, and
  a regex-only CI scan.
- Move operator material (fail-closed behavior, the provenance record,
  review steps, and the repository lifecycle link) to docs/COMPLIANCE.md,
  linked once from the README.
- Document configuration through the config object. The old example built a
  PrivacyConfig that nothing read.
- Say that screenshot scrubbing needs the Tesseract binary.
- Regenerate the scrubbed demo screenshot with the current code; the old one
  came from the first release and showed the card number unredacted.
- Use absolute image and link URLs so they render on PyPI.
- Replace the README text pin in tests/test_scan.py with tests/test_readme.py.
- Fix the class name in CLAUDE.md (PresidioScrubber does not exist) and
  sharpen the PyPI summary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: keep a surname that matches a label abbreviation redacted

The field-label filter dropped a PERSON span whose whole text was a label
in front of another finding. "Ip" and "Sin" were in the label list, and both
are surnames, so "Dr. Sin: 555-123-4567" came back as
"Dr. Sin: <PHONE_NUMBER>" and "Sin john@example.com" as
"Sin <EMAIL_ADDRESS>". Release 1.1.1 redacted the name in both.

Remove "ip" and "sin" from the list. "IP address" and "social insurance
number" stay. "SIN:" and "IP:" labels go back to being redacted along with
the identifier after them, which over-redacts but leaks nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix: drop internal wording from the scan output and config docs

openadapt-privacy-scan printed "PHI / clinic-path scan failed:" on a hit,
and scan_tree's docstring referred to an internal scanner. The message is
now "PHI scan failed:" and the docstring says what each line holds. The
help text says the scan checks the files in a directory, since it also runs
outside a git repository.

The config module docstring still said you could create a new PrivacyConfig.
Nothing reads one, so it now points to the module-level config instance.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: make the README's card, scan, and setup claims match the code

- Limits said a card number that fails the Luhn check is still redacted as
  <DATE_TIME>. "4111 1111 1111 1112" comes back as "4111 1111 <DATE_TIME>".
  The README now gives both cases, and tests/test_readme.py checks them.
- The scan section said it checks "a git tree". It checks the files in a
  directory, and in a git repository the tracked and unignored untracked
  files, not the history.
- gitleaks.toml and phi-patterns.txt carry the text patterns, not the
  file-type checks, so they aren't "the same rules".
- Spell out RPA, say the scan runs without Presidio instead of "needs no
  other packages", and explain the `uv pip install pip` step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant