The problem nobody wants to own
Every organisation processing personal data in the EU is required by GDPR Article 30 to maintain a Record of Processing Activities what personal data it holds, why, where it flows and who receives it.
In practice, this register is a stale spreadsheet written once for an audit and never updated. The codebase moves; the register doesn't.
The information the register needs already exists it's just encoded in schemas, API calls and SDK imports where no compliance officer can read it.
Article30 reads it for them.
What it does
Point it at a repository:
article30 scan ./your-repo
It then:
Finds personal data - parses database schemas & models and uses GPT-5.6 to semantically classify each field: is it personal data, which category (identity, contact, financial, special category) and why. Regex finds
email; GPT-5.6 findsguardian_contactanddietary_notes.Traces where it flows - detects third-party recipients (payment, email, analytics SDKs) and flags cross-border transfers.
Catches leaks - finds personal data written into log statements, the most common silent GDPR violation in real codebases.
Generates the register - a draft Article 30 Record of Processing Activities as a clean HTML report plus structured JSON, ready for DPO review.
It is a draft generator, not legal advice - the output is explicitly framed for review by a human data protection officer.
How I built it
The entire core was built in a single Codex session with GPT-5.6 Terra. I front-loaded the architecture into one detailed opening prompt - four-stage engine (scanner → classifier → flow tracer → report), CLI plus a framework-free FastAPI web UI and a strict build order. Codex delivered a runnable skeleton with passing tests in under an hour. A second prompt built the sample-app fixture and made Codex verify its own output against explicit checks: three planted log leaks, two deliberately ambiguous fields, two SDK recipients. All passed on the real API path.
GPT-5.6 plays two roles in this project:
As the builder - via Codex with GPT-5.6 Terra., writing the scanner, the flow tracer, and the report generator. Two moments stood out: Codex caught that gpt-5.6-luna requires its default temperature and fixed the request handling on its own and it added an unprompted local-heuristic fallback so the tool runs without an API key which became the judges' zero-setup testing path. It also hardened .env loading without being asked.
Inside the product — the semantic classification layer is a GPT-5.6 call. Field classification is a judgment problem, not a pattern-matching problem, and this is exactly the kind of judgment the model does well with structured output.
Challenges
Determinism versus judgment. A compliance artifact can't change between runs, but classification is a judgment call. The answer was response caching keyed on field, type, table, and model - the first scan asks GPT-5.6 Luna, every subsequent scan is instant and identical. The second challenge was trust: Codex reported "done" after 45 minutes, and the real work was verification - forcing the scan onto the live model path (not the fallback) and checking the planted fields and leaks actually surfaced before believing it.
What I learned
The leverage isn't in prompting the code - it's in specifying the verification. The build succeeded because the prompts contained explicit pass/fail checks Codex had to satisfy and printed which classification mode ran so a demo could never silently use the fallback. Spec the proof, not just the product.
What's next
CI integration (fail the build when new personal data appears without a register entry), more ecosystem parsers and diff mode - showing what changed in your data map between releases. Moreover, other EU regulatory/compliance checks can be added to make it a whole package.
Built With
- codex
- fastapi
- gdpr
- gpt-5.6
- javascript
- openai
- python
Log in or sign up for Devpost to join the conversation.