-
-
Release: generated Privacy changes and a privacy pack (record, notices, CycloneDX data BOM).
-
Plan: the Pre-check flow answers a new issue with least data, lawful basis and EN/KO consent wording.
-
The failed pipeline triggered the Privacy Officer: two fixes on the same branch plus a decision table.
-
Verify/Secure: the privacy gate blocks undeclared data, clear-text logs and an undeclared overseas processor.
-
The Privacy Officer flow fixed a blocked merge request and explained every decision (MR !1).
-
The same flow opened an incident with the 72-hour clock and a fix MR; it closed after the fix was merged.
-
Monitor: the scheduled check found a customer phone number on the live homepage (masked in the log).
Inspiration
Small teams collect personal data every sprint: a birthday field for a coupon, a notes box, an analytics call. GDPR Art. 30 and Korea's PIPA Art. 30 say the record of processing and the public privacy notice must match what the software does. In a three-person company nobody owns that, so the notice drifts for months and the first person to notice is a regulator or an angry customer.
What it does
PrivacyPilot makes privacy/ropa.yml (the record of processing) part of the codebase and lets GitLab Duo agents keep it true:
- Plan. A new issue gets a privacy pre-check from the Pre-check flow: the least data that would do the job, lawful basis, retention, consent wording in English and Korean, and the record snippet to add.
- Create / Verify / Secure. Every merge request runs the privacy gate. It scans SQL schemas, HTML forms, log calls and outbound requests and blocks undeclared data, clear-text logging, sensitive data without consent, and undeclared or overseas processors. Findings appear in the MR security widget as a SAST report next to GitLab SAST and secret detection.
- The Privacy Officer flow fixes it. A failed gate triggers a Duo flow that reads the job log and the MR, declares the data with a purpose and retention, adds the consent checkbox, wraps the log in
redact(), records the overseas transfer, regenerates the bilingual notice, re-runs the gate until it passes and commits to the same MR, then explains every decision. A human privacy owner approves the outcome (CODEOWNERS), not each step. - Package / Release. Tags publish a privacy pack (record, notices, CycloneDX 1.6 data BOM) to the package registry and a release with a generated "Privacy changes" section.
- Configure / Deploy. Retention periods become the Worker's deletion schedule; Pages publishes the app and the notice.
- Monitor. A scheduled pipeline checks the live notice version and looks for personal data on public pages; a failure opens a
privacy::incidentissue (with the 72-hour assessment clock) and a fix MR through the same flow.
It really ran (all public in the project)
- Issue #2 → Pre-check note: birth month only, explicit consent for scalp (health) data, EN/KO checkbox wording, record snippet.
- MR !1 → privacy-gate blocked PP001 x2, PP003, PP005 → the Privacy Officer committed two fixes and posted a decision table, including the one thing it could not prove (consent not enforced in the Worker) → the owner fixed that, approved and merged.
- Tags v1.0.0 / v1.1.0 → release with generated "Privacy changes" and the privacy pack in the package registry.
- Scheduled monitor → a phone number in a pasted review on the live homepage → incident #3 (masked evidence, 72-hour clock) and fix MR !2 → merged, redeployed, monitor green, incident closed.
- The first pipeline failed (a .gitignore rule hid the app pages) and stays in the history with its fix.
How we built it
Python standard library + PyYAML for the scanner, gate, notice generator, BOM and monitor; GitLab CI/CD (SAST, secret detection, custom SAST report, generic packages, releases, Pages, schedules); GitLab Duo Agent Platform custom flows published to the AI Catalog and wired to pipeline-failed, work-item-created and mention triggers through GraphQL (tools/duo/setup_flows.py); CODEOWNERS for governance.
Stages covered
plan, create, verify, package, secure, release, configure, monitor, govern (all nine).
Challenges
Flow tokens cannot merge or create releases, so the agent works inside the MR and CI jobs own merges, releases and deploys. A flow cannot trigger another flow, so one supervisor flow handles both the MR and the incident path.
What's next
Data-flow tracing across function calls, more languages and frameworks, and a DPIA template for high-risk processing.
Links
- Project: https://gitlab.com/gitlab-ai-hackathon/transcend-october-2026/43311657/showcase
- Live site and notice: https://showcase-af641e.gitlab.io (EN), https://showcase-af641e.gitlab.io/privacy/ko.html (KO)
Built by a solo developer in Korea. English text was written with AI assistance.
Built With
- cloudflare-workers
- cyclonedx
- gitlab
- gitlab-ci
- gitlab-duo
- gitlab-pages
- python
- pyyaml
Log in or sign up for Devpost to join the conversation.