Local Privacy Gateway
Inspiration
AI can be useful for making dense administrative letters easier to understand. The problem is that the normal workflow sends the original document to the AI before the user has a chance to remove names, addresses, case numbers, and other personal information.
I wanted to reverse that order.
Local Privacy Gateway first looks for likely personal information on the user’s own computer. The user reviews every proposed redaction and decides what should actually be removed. Only after they approve the sanitized version can that text be sent to the model.
The general idea of local, deterministic redaction existed before Build Week. During Build Week, I narrowed it into a small vertical slice that could be tested from beginning to end.
What it does
The prototype runs as a localhost application and accepts plain-text documents.
Ordinary deterministic Python rules look for likely:
- names
- addresses
- phone numbers
- email addresses
- SSN-like values
- birth dates
- account numbers
- case identifiers
These are only proposed redactions. The program does not automatically decide that every match should be removed.
The user reviews each proposal and creates a sanitized preview. Analysis stays disabled until the user explicitly approves that preview.
At the model boundary, the adapter rejects the original text and any unexpected fields. It then creates an OpenAI Responses API request where the document input is exactly the sanitized text the user approved.
The analyzer returns:
- a plain-language summary
- important dates
- possible next actions
- uncertainties or things that may need clarification
The project also works without an API key. In that case, it runs in a clearly labeled local mock mode rather than pretending a real model request occurred.
A local audit record stores:
- the SHA-256 hash of the original document
- the exact sanitized payload
- metadata about the applied redactions
- whether the run used mock or live mode
- the model name
- the OpenAI response ID, when available
The audit record does not store the original document.
How we built it
The prototype uses:
- a Python standard-library HTTP server bound to
127.0.0.1 - deterministic Python regular expressions and narrow name-detection heuristics
- plain HTML, CSS, and browser JavaScript for redaction review and approval
- an OpenAI Responses API adapter using GPT-5.6
- strict Structured Outputs for summaries, dates, actions, and uncertainties
- Python
unittestcoverage for redaction behavior, boundary rejection, the HTTP workflow, audit behavior, localhost binding, and live-request construction - Codex for implementation, debugging, verification, and preparing the submission materials
Challenges
One of the largest problems was that the imported vertical slice passed all of its Python tests while the browser workflow did absolutely nothing.
The JavaScript bundle started with an invalid character, so none of the browser controls worked. The Python tests did not catch it because they were not actually using the application the way a person would. Browser-level verification exposed the problem immediately.
The synthetic test document also exposed an overly permissive account-number rule. The phrase “case remains open” caused the word “remains” to be proposed as an identifier.
I tightened the required label format and added a regression test for that exact failure. This fixed the false positive without making the detector broader or more aggressive.
The most important challenge was making the privacy claim narrow enough that it could actually be tested.
The adapter rejects unknown fields. The tests verify that the document input sent to OpenAI is exactly the sanitized text approved by the user.
That supports a specific claim about this prototype’s boundary. It does not prove that the detector will find every piece of personal information, and it is not a compliance claim.
Accomplishments
The completed prototype now has:
- a full synthetic workflow that works in the browser
- human approval that is visibly and programmatically required
- HTTP 400 responses when original-text or debug fields are sent to the analysis boundary
- audit output with no original-document field
- no API key in the browser JavaScript
- a server that binds only to localhost
- validation that accepted redaction spans match the source text
- 37 passing automated tests
- a truthful mock mode that does not pretend a live model call occurred
What we learned
Passing unit tests was not enough for this project.
The privacy workflow depends on a human review step, so the browser itself is part of the security boundary. The interface has to be tested as an actual user would experience it.
We also learned that deterministic redaction rules need negative tests based on realistic language. A pattern can look reasonable and still silently redact ordinary words.
Separating the model instructions from the document input also made the boundary easier to inspect. The exact approved sanitized text is placed in input. The instruction not to reconstruct removed information stays separately in instructions.
That separation makes it much easier to verify what document content actually crossed the model boundary.
What’s next
Both the automated adapter test and my human-reviewed live GPT-5.6 test succeeded using a server-side environment variable. The actual OpenAI response ID was recorded.
The GitHub repository is published. The following materials are also prepared locally:
- screenshots
- a narrated demonstration video
- the Codex
/feedbackconfirmation ID - the repository-publication checklist
The next step is evaluating future format-specific local extraction, such as PDF or DOCX, while preserving the same privacy boundary.
No real sensitive document should be used for the demonstration.
Important limitations
This prototype can miss identifiers. It can also produce false positives.
Human review is mandatory.
The audit log provides local evidence about what the application processed, but it is not a tamper-proof attestation.
The project is not production-ready. It does not make any legal, medical, financial, HIPAA, privacy, regulatory, or compliance claim.
Built With
- api
- codex
- css3
- gpt-5.6
- html5
- javascript
- openai
- python
- responses
Log in or sign up for Devpost to join the conversation.