Skip to content

Guard every tracked events.py against PII, not just Run and Actor - #796

Merged
xmap merged 1 commit into
mainfrom
worktree-agent-a41b3d5e283db7d11
Sep 10, 2026
Merged

Guard every tracked events.py against PII, not just Run and Actor#796
xmap merged 1 commit into
mainfrom
worktree-agent-a41b3d5e283db7d11

Conversation

@xmap

@xmap xmap commented Sep 10, 2026

Copy link
Copy Markdown
Owner

Summary

Two PII fitness tests existed, and each scanned exactly one hardcoded file: run/aggregates/run/events.py and access/aggregates/actor/events.py. Every other bounded context's events were scanned by nothing.

The deny-list was already correct and already listed observed_path, capture_path, path, directory, file_path, surname, proposal_number. It simply never ranged over the files where a violation would land. 2-BM's directory layout embeds {UserLastName}-{ProposalNumber}, and events are immutable and INSERT-only at the role level, so a path written into one can never be erased.

Found while designing a new Data BC event: it would have carried a capture path and shipped green.

Coverage: 2 files -> 43, across 18 bounded contexts.

Changes

  • Replaces both tests with test_events_carry_no_pii.py, discovering every events.py via tracked_python_files() (git-aware, never glob()/iterdir(), so the file set matches what pre-commit sees).
  • name / display_name stay scoped to Actor's own file. Globalizing them flags 28 ordinary entity-label fields across 15 files (equipment, recipe, campaign, dataset, procedure, sample, Trust zone) with no real PII among them, including RunStarted.name in the very file whose curated list already omitted bare name for that reason.
  • Net widening for both originally-covered files: Run's is now also checked for email / phone / orcid / affiliation, and Actor's for path / directory / surname / proposal_number.
  • event_activity_trail.py docstring asserted "the only two fitness tests ... cover exactly two of the twenty-five stream types", which this change falsifies; updated, and made more honest about what a field-name deny-list can and cannot guarantee.
  • Drops the em-dash allowlist entry for the deleted file.

Test plan

  • Mutation-verified: adding observed_path: str to a real Data BC event fails with data/aggregates/acquisition/events.py line 87: AcquisitionRecorded.observed_path. That field on that file shipped green before this change.
  • Measured coverage: 43 tracked events.py, 18 bounded contexts.
  • Ships a guard for the guard: test_pii_scan_discovers_events_file_for_every_bounded_context fails if discovery silently returns an empty or partial set, which would otherwise make the whole test pass over zero files.
  • Seeded-violation meta-test calls the real production walker, not a re-implemented copy.
  • Full architecture suite green.

🤖 Generated with Claude Code

test_run_events_carry_no_pii.py and test_actor_events_carry_no_pii.py
each hardcoded one file, so a new event anywhere else carrying a
2-BM directory path (which embeds a surname and proposal number) or
other PII-shaped field shipped with zero objection. Replace both with
test_events_carry_no_pii.py, which discovers every events.py via
tracked_python_files() and checks it against a shared deny-list, plus
an Actor-only extension for name/display_name (globalizing those two
terms flags 28 ordinary entity-label fields elsewhere with no real PII
among them, so they stay scoped to Actor's own file).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Coverage report

This PR does not seem to contain any modification to coverable code.

@xmap
xmap merged commit 9af5e20 into main Sep 10, 2026
19 checks passed
@xmap
xmap deleted the worktree-agent-a41b3d5e283db7d11 branch September 10, 2026 20:47
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