ProofLens
Checks whether the documents you attach support the claim you are making. Rule checks run before the model, every cited passage is validated against the stored page, and the verdict points back to the exact sentence it rests on.
- 297
- Backend tests passing
- 4
- Verdicts, none called true
- 4
- AI providers, one interface
- 22
- API routes
- Role
- Author
- Year
- 2026
- Status
- Open source
- Type
- Claim and evidence verification
01Overview
ProofLens answers one question: does the evidence I supplied support the claim I am making? You write a claim, attach a PDF, a text file or a pasted passage, and get one of four verdicts with the reasoning and the page it came from.
A source can be real and still not say what a claim says. A study finds an association and the claim says it proves causation. A report says 1,200 participants and the claim says 10,000. ProofLens finds that gap, explains it in plain language and shows the sentence behind it.
I built it alone for GOMYCODE Nigeria's Come Build with AI 2026. The backend is FastAPI over PostgreSQL, the web client is Next.js 16 and the mobile client is Expo. It is not a chatbot or a web search: it reasons only over the evidence you attach.
02The problem
A language model asked to check a claim will answer confidently whether or not the document supports it. It can cite a page that does not exist, quote a sentence nobody wrote, or follow an instruction hidden in the document it was asked to read.
So the model could not be the authority. The verdict had to be something a person can check by opening the source, and the system had to fail visibly when reasoning is unavailable. An invented verdict is worse than no verdict.
The clients were the other risk. If a phone or a browser holds verification logic or an AI key, there are three places where the answer can differ. All of it had to live on the backend.
03Architecture
- 01
Six modules in four layers
The backend is split into users, claims, documents, evidence, verification and ai. Each module has a domain, an application layer of commands and queries, infrastructure and a presentation layer. The API is 22 routes under `/api/v1` over nine PostgreSQL tables, with async SQLAlchemy 2 and ten Alembic migrations.
- 02
Documents stored page by page
A PDF is parsed by PyMuPDF in a separate subprocess with a time limit and a memory limit, so a hostile file cannot take the API down. Text is stored per page. Evidence is a passage that keeps its document, page and section, which is what lets a result link back to the right place.
- 03
Rule checks before the model
Deterministic checks compare the claim with the best-matching passage: numbers, dates, names, negation, causation against association, and absolute or hedged wording. No model is involved. Each check becomes a finding the user can read, and the findings are passed to the model as input.
- 04
One provider interface, four providers
Groq, Google Gemini, NVIDIA NIM and Ollama sit behind one `InferenceProvider` interface. Which one runs is configuration. Every provider must answer in a strict JSON schema, and fallback models are tried in order when one errors, times out or keeps returning invalid output.
- 05
The backend validates the answer
The model's answer is parsed with Pydantic. A reference to a passage that was never supplied is dropped. A quote must appear word for word in the stored passage or it is cleared. Document and page always come from the database, never from the model.
- 06
Results keep their evidence
Each verification stores a snapshot of the evidence it used. A past result can be shown without calling the model again, and evidence that a stored result depends on cannot be deleted.
- 07
Two clients that hold no secrets
The web app keeps the session token in an httpOnly cookie and sends browser calls through a same-origin proxy. The mobile app keeps it in SecureStore. Neither client contains verification logic or calls an AI provider. AI and email keys exist only in the backend's environment.
04Key decisions
Rules can overrule the model
A conflict in a number, a date or a name overrides a model that says supported. A causation gap caps the verdict at partially supported. The model explains, but it does not get the last word on a fact the backend can check itself.
No verdict called true
The four verdicts are supported, partially supported, contradicted and insufficient evidence. Every one is a statement about the supplied evidence, not about the world. Insufficient evidence is its own outcome, so a source that does not cover the claim is never confused with a source that says the opposite.
Document text is untrusted data
Passages are wrapped as data before they reach the prompt, so a sentence inside a PDF cannot act as an instruction. The integration suite includes prompt-injection cases and a provider outage, and checks that the user sees an error with a retry instead of a made-up verdict.
Security controls that fail closed
Passwords use Argon2id. Session tokens are stored only as SHA-256 hashes and capped at five per user. Sign-up codes are hashed, single use and expire in ten minutes. Rate limits are stored in PostgreSQL and fail closed. Another user's claim or document answers 404, not 403.
05Stack
- Python
- FastAPI
- SQLAlchemy 2
- Alembic
- PostgreSQL 17
- Pydantic
- PyMuPDF
- Next.js 16
- React 19
- Expo
- TypeScript
- Groq
- Gemini
- NVIDIA NIM
- Ollama