Why I built this
I work as an auditor in Romania. When I check public information, finding a number is often the easy part. The harder part is tracing where it came from, seeing whether another official source says something different, and understanding what still needs to be verified.
I built Ministry of Transparency around one simple rule: when sources disagree, do not hide the disagreement.
The Build Week demo uses clearly labelled synthetic records. Two records describe the same contract. Four fields agree, one field is missing, and the contract value differs by 42 RON. Instead of selecting one version, the product keeps both values, preserves the missing field as not_available, and attaches evidence to every comparison.
It does not pretend to know which source is right. It makes the disagreement clear enough for a person to investigate it.
How it works
The comparison is deterministic. Dates, amounts, and text are normalized before each field is classified as:
- consistent;
- missing from one source;
- or conflicting.
Formatting differences such as 18.07.2026 and 18/07/2026 do not become false conflicts. Missing information is not converted into zero. When two real values disagree, both remain visible with their evidence IDs and the result is marked for manual verification.
AI has a deliberately small role.
If the user requests an explanation, the server rebuilds the deterministic comparison and sends the model a redacted, allowlisted evidence bundle. The response must cite supplied evidence IDs and explain what agrees, what conflicts, what is missing, and what should be checked next.
The model cannot choose a winning source, allege wrongdoing, or change review or publication state. If its response breaks those rules, it is rejected and the deterministic result remains available.
A user can also select Report analysis error. This opens a prefilled correction request for human review. It does not silently edit the public record.
What is live in this submission
- The contract comparison is deployed, API-backed, and uses synthetic records.
- The optional OpenAI explanation runs server-side and only when requested.
- The correction workflow creates a review record without changing publication state.
- The public-official and institution views are deterministic browser-side fixtures showing how the same evidence-first approach could extend to other records.
- Live Romanian source ingestion, production identity resolution, and real-world impact measurement are not implemented or claimed.
How I built it
This is the first AI application I have built and deployed. My background is audit rather than software, and that shaped the process: identify the failure modes, define a control for each one, and test whether the control actually holds.
The frontend uses Next.js, React, and TypeScript on Vercel. The API uses FastAPI, Python, and Pydantic on Render, with PostgreSQL as the system of record. The optional explanation uses the OpenAI Responses API. GitHub Actions, automated tests, and Playwright verify the main judge workflow.
The controls I cared about most were:
| Failure mode | Control | Result |
|---|---|---|
| Two sources disagree | Keep both values and both evidence records | No automatic winner |
| A field is missing | Preserve not_available |
Missing information is not presented as zero |
| The model cites unknown evidence or overstates a conclusion | Reject the response | The deterministic comparison remains available |
| A user challenges a result | Send it to human review | Published history does not change automatically |
The OpenAI key stays server-side, requests use store=false, and the browser never receives the key.
How I used Codex and GPT-5.6
I used Codex with GPT-5.6 throughout the build: connecting the frontend, API, and database; designing the structured AI response; writing tests; reviewing failure cases; and verifying the deployed product.
My audit experience shaped the questions I kept asking while working with Codex:
- What evidence supports this value?
- What happens when information is missing?
- Can the model make a claim the evidence does not support?
- Can any public action change publication state automatically?
Those questions became product controls and automated tests.
GPT-5.6 was used through Codex to build and verify the project. The optional explanation in the deployed application uses a separately configured production model. The final live test returned model identifier gpt-5.1-2025-11-13.
The hardest part
The hardest decision was how much authority to give the AI.
Asking the model which source “looks more credible” would have produced an easy demo. But the supplied evidence does not justify that conclusion, so I did not build it.
The explanation layer explains; it does not arbitrate. Making that boundary reliable required structured outputs, evidence-ID validation, language checks, redaction, and a safe failure path.
What I learned
AI became more useful when I reduced its authority.
The explanation can help a reviewer because it cannot decide what is true. It can only explain what the supplied evidence shows and identify what still needs checking.
I also learned that transparency is not simply showing more data. A useful system must be able to say:
- this information is unavailable;
- these sources disagree;
- this requires human verification.
Those states are more honest than an artificially complete answer.
What’s next
The first realistic use case is a source-conflict review workspace for auditors, investigative journalists, academic researchers, students working with public data, civil-society organizations, and oversight teams.
Future work could include legally reviewed Romanian public-data integrations, user-provided document comparison, stronger entity resolution, and signed evidence exports.
The goal is not to replace public portals. It is to make disagreement visible without turning uncertainty into accusation.
Built With
- codex
- docker
- fastapi
- github-actions
- gpt-5.6
- next.js
- openai-responses-api
- playwright
- postgresql
- pydantic
- python
- react
- render
- typescript
- vercel