How We Built a GDPR-Compliant Anti-Corruption Platform with 9 Institutional Roles
When a Bulgarian civic rights organisation approached us with a vision to transform how citizens report corruption, we knew this would be one of our most technically demanding and socially meaningful projects. Moite Prava (moiteprava.bg) needed a platform that could do what email chains and paper forms never could: give citizens a secure, anonymous way to report corruption while giving government institutions the structure to actually investigate and resolve those complaints.
The stakes were real. In Bulgaria, corruption complaints submitted via email or paper often disappeared into bureaucratic black holes. Citizens had no way to track whether their complaint was being reviewed, investigated, or ignored. Government agents lacked structured workflows, and there was no accountability trail. Moite Prava wanted to change that with technology - and they came to us to build it.
Project: moiteprava.bg
The Challenge
This was not a standard web application. The platform needed to serve two fundamentally different user groups with opposing requirements. Citizens needed simplicity, privacy, and trust. Government agents needed power, structure, and oversight. Bridging that gap while maintaining strict data boundaries was the core architectural challenge.
The specific requirements included:
- A citizen-facing side that was simple enough for anyone to use, with guided forms and real-time complaint tracking
- An institutional side supporting 9 distinct roles, each with tailored dashboards and permissions
- Strict anonymity: government agents must never see citizen identity data, even accidentally
- Full GDPR compliance with data export, deletion rights, and consent management
- A public-facing transparency dashboard showing aggregated statistics without exposing case details
- Complete audit logging of every action taken on every case
The complexity was compounded by the fact that this platform would handle sensitive data about corruption allegations. A single data leak or privacy violation could undermine the entire initiative and put whistleblowers at risk. Security and privacy could not be afterthoughts - they had to be fundamental to the architecture.
Our Solution
We built the platform on Next.js and Supabase, leveraging Supabase Row-Level Security (RLS) as the backbone of the privacy architecture. Rather than relying on application-level access controls alone, we pushed data isolation down to the database layer. This meant that even if a bug existed in the frontend, the database itself would refuse to serve citizen identity data to institutional users.
Citizen-Facing Platform
For citizens, we built a guided complaint submission form that walks users through the process step by step. Instead of a blank text field, citizens answer structured questions about the type of corruption, the institution involved, dates, and supporting evidence. This structured approach helps investigators and reassures citizens that their complaint is being taken seriously.
Once submitted, each complaint enters an 8-stage tracking pipeline: Submitted, Registered, Under Review, Investigation, Legal Assessment, Decision, Resolution, and Closed. Citizens see a real-time progress bar and receive email notifications via Resend at each stage transition. The cryptographic separation means their identity is linked to the case through a one-way reference that institutional users cannot reverse.
Institutional Platform
The institutional side was where the real complexity lived. We implemented 9 distinct roles, each with a purpose-built dashboard:
- Registrar: Receives incoming complaints, validates them, and assigns them to the appropriate department
- Expert: Conducts detailed investigation, adds notes, uploads documents, and requests additional information
- Department Head: Reviews investigation findings and approves or escalates cases
- Lawyer: Provides legal assessment and ensures compliance with regulatory frameworks
- Accountant: Handles financial aspects of cases involving monetary corruption
- Auditor: Performs compliance checks and verifies that procedures were followed correctly
- Administrator, Super Admin, and Observer: System management, full access oversight, and read-only reporting respectively
Each role has granular permissions controlling which cases they can see, what actions they can take, and what data fields are visible. Case management includes internal notes, document attachments, stage transitions, and a complete audit log. Every action - from opening a case to adding a note to changing a status - is recorded with the user, timestamp, and action detail.
Public Transparency Dashboard
To build public trust, we created a statistics dashboard accessible without login. It shows aggregated data: total complaints received, average resolution time, complaints by category and region, and resolution rates. The dashboard uses Recharts for interactive visualisations. All data is pre-aggregated so that no individual case details can be inferred. This transparency layer was critical for Moite Prava mission of public accountability.
The Results
The platform delivered a complete transformation of how corruption complaints are handled in Bulgaria. What was once an opaque, paper-based process became a structured, transparent, and accountable digital workflow.
- 8-stage complaint tracking gives citizens real-time visibility into their case progress
- Privacy-by-design anonymisation ensures agents never access citizen identities through database-level enforcement
- 9 institutional roles with granular permissions mirror real government oversight structures
- Complete audit trail logs every action for accountability and compliance
- Public accountability dashboard builds civic trust through transparent statistics
- Full GDPR compliance with data export, deletion, consent management, and retention policies
Technology Stack
| Technology | Purpose |
|---|---|
| Next.js | Server-side rendering, routing, and API layer |
| React + TypeScript | Type-safe component architecture for both citizen and institutional interfaces |
| Supabase (RLS) | Database with Row-Level Security for privacy-by-design data isolation |
| Recharts | Interactive data visualisations for the public transparency dashboard |
| Resend | Transactional email notifications for complaint status updates |
| Zod + React Hook Form | Schema validation and guided complaint submission forms |
The choice of Supabase was strategic. Its Row-Level Security policies allowed us to enforce data boundaries at the database level, meaning that even a compromised frontend could not expose citizen data to institutional users. Combined with Next.js server-side rendering for fast initial loads and Zod for rigorous input validation, the stack delivered both security and usability.