PROOFCHAIN turns regulated document bundles into verified, human-approved and auditable actions.
Instead of treating AI extraction as truth, it links every material claim to its source document and page, checks whether the documents agree with each other, corroborates selected facts against live public data, applies an explicit confidence and policy gate, escalates unresolved uncertainty to an accountable human, and keeps enough of the trail to reconstruct why the final action happened.
The hard problem is not extracting the field. It is knowing what to do when two correctly extracted fields disagree.
A supplier submits five documents. The invoice states an IBAN ending 3382. The bank confirmation letter states one ending 9931.
Both values were extracted correctly. This is not an OCR failure. The underlying evidence disagrees — and something is about to be paid.
Generic document AI answers what does this document say. PROOFCHAIN answers can we act on what these documents say.
DOCUMENTS → CLAIMS → EVIDENCE → CONFLICTS → EXTERNAL VERIFICATION
→ CONFIDENCE → DECISION GATE → HUMAN REVIEW → AUTHORISED ACTION → REPLAY
Running the hero case end to end produces, from the real pipeline over real PDFs:
| Documents processed | 5 |
| Claims extracted, each linked to document + page | 26 |
| Evidence groups built | 11 |
| External corroboration checks | 4 |
| Critical conflicts detected | 1 (bank account) |
| Bank Account confidence | 57% |
| Case confidence | 79% → REVIEW_REQUIRED |
| After a named human resolves it | 95% → READY_FOR_APPROVAL |
| Final decision | APPROVED_WITH_REVIEW, fully replayable |
Two services: the Proof Engine (FastAPI, port 8000) and the workspace (Next.js, port 3000).
You need Python 3.11 or newer and Node 18 or newer. Nothing else — no database to install, no API keys, no accounts.
macOS and Linux
git clone <repo> && cd proofchain
make doctor # reports anything missing before you start
make setup # venv, dependencies, demo PDFs, .env filesWindows — make assumes a POSIX shell, which PowerShell is not, so use the
scripts:
cd proofchain
powershell -ExecutionPolicy Bypass -File scripts\setup.ps1Backend dependencies install into .venv; nothing touches your system Python.
Recent Debian, Ubuntu and Homebrew refuse a plain pip install anyway (PEP 668).
If the interpreter is not found automatically, pass it:
make setup PY=python3.12.
make run # engine → http://localhost:8000/docs
make run-web # workspace → http://localhost:3000.\scripts\run-engine.ps1
.\scripts\run-web.ps1Go to http://localhost:3000.
The workspace starts empty, so the sign-in screen offers to load the demo case and sign you in. One click. It reads five supplier documents, extracts 26 source-linked claims, and lands on a case that cannot be approved because two documents disagree about where to send the money.
Then sign in as any of these — password proofchain for all four:
| Can | |
|---|---|
analyst@proofchain.demo |
create cases, upload, view evidence |
reviewer@proofchain.demo |
+ settle contradictions |
manager@proofchain.demo |
+ authorise decisions |
admin@proofchain.demo |
+ configure policy |
Start with the manager to walk the whole flow. Then watch the system refuse: signed in as the analyst, settling the contradiction returns 403 — the role is not permitted. Signed in as the manager, approving before the contradiction is settled returns 409 — the gate has stopped the case, and clicking harder does not move it.
make test # 117 backend tests, no network, ~11s
make typecheck # frontend typesEverything above works with no credentials at all. Both sponsor integrations
fall back to local processing and label every result cached in the interface —
nothing is presented as live that was not.
To run them for real, add keys to services/proof-engine/.env and check what
actually happens:
make check # does each provider answer?
make check-demo # is the case actually using them?See docs/NUTRIENT_SETUP.md, docs/XANO_SETUP.md and docs/FOXIT_SETUP.md.
| Symptom | Cause |
|---|---|
Python est introuvable, or the Microsoft Store opens |
That is the Store stub, not Python. Install from python.org with "Add python.exe to PATH" ticked, then open a new terminal |
| Sign-in returns 401 on a fresh install | No accounts exist yet. The sign-in screen offers to create them; or POST /api/v1/demo/seed |
Documents read cached although a key is set |
A document is read once. Reseed: make reset RESEED=1 |
429 from Xano |
The free tier rate-limits a full seed. See docs/XANO_SETUP.md |
The engine will not start after editing .env |
Every key must map to a real setting — a test asserts this. Compare with .env.example |
| What you want | macOS / Linux | Windows PowerShell |
|---|---|---|
| Check your tools | make doctor |
— (setup reports what is missing) |
| Install everything | make setup |
.\scripts\setup.ps1 |
| Start the engine | make run |
.\scripts\run-engine.ps1 |
| Start the workspace | make run-web |
.\scripts\run-web.ps1 |
| Does each provider answer? | make check |
.\scripts\check.ps1 |
| What does the case contain? | make check-demo |
.\scripts\check-demo.ps1 |
| Freeze the demo state | make snapshot |
.\scripts\snapshot.ps1 |
| Restore before a take | make reset |
.\scripts\reset.ps1 |
| Force a full rebuild | make reset RESEED=1 |
.\scripts\reset.ps1 -Reseed |
| Run the tests | make test |
.venv\Scripts\python.exe -m pytest from services\proof-engine |
Git Bash and WSL run the make column unchanged.
Five screens, no more. The blueprint's rule was that the product should feel like an operational decision workspace rather than a dashboard, so there is no analytics page and no chat.
| Screen | Answers |
|---|---|
| Cases | What needs attention? |
| Case overview | Can this case be acted on, and why not yet? |
| Evidence | Which facts agree, which disagree, and where did each come from? |
| Review | Two source documents side by side, and a decision to record |
| Trail | Why did the organisation act? |
Three deliberate choices in the interface:
- The decision gate is drawn, not stated. A band shows where confidence sits on the policy's scale and the fact that position on the scale is not sufficient — a case at 96% still stops when two documents contradict each other. When the marker and the verdict disagree, the band says so in words.
- Conflicting values are aligned character by character. Deciding between two IBANs is easier when you can see that four digits differ rather than reading two long strings in sequence. The interface marks where they diverge and never suggests which is correct.
- Colour never carries meaning alone. Every status ships with a glyph and a text label, so the screen survives greyscale and colour blindness.
Fonts are bundled rather than fetched from Google's CDN: a workspace handling supplier documents should not make a third-party request on every page load, and the demo has to build with no network.
proofchain/
├── apps/web/ Next.js workspace — 9 routes
│ └── src/
│ ├── app/ five screens plus sign-in
│ ├── components/ evidence table, drawer, gate band, source viewer
│ └── lib/ typed API client, session, status vocabulary
├── services/proof-engine/ FastAPI service — 41 endpoints
│ ├── app/
│ │ ├── api/ thin routes; they never decide anything
│ │ ├── core/ config, errors, security, ids, clock
│ │ ├── domain/ enums, versioned policy, schemas
│ │ ├── db/ SQLAlchemy models mirroring the Xano schema
│ │ ├── repositories/ persistence port + Xano and SQL adapters
│ │ ├── engine/ normalisation, comparison, confidence, gate, replay
│ │ ├── integrations/ nutrient, serpapi, foxit, llm
│ │ └── services/ orchestration and audit
│ └── tests/ 117 tests
├── integrations/xano/ schema.json, seed_policy.json
├── fixtures/documents/ the five generated supplier PDFs
├── scripts/ demo document generator
└── docs/ ARCHITECTURE, API, XANO_SETUP, DECISIONS
docs/DECISIONS.md records every judgement call, including two places where the
specification contradicted itself and how the contradiction was resolved, and
five defects that only surfaced when the project was installed from a clean
checkout.
Provider setup, including how hackathon participants get credentials and
credits: docs/NUTRIENT_SETUP.md, docs/XANO_SETUP.md, docs/FOXIT_SETUP.md.
docs/DEVPOST_SUBMISSION.md is the submission copy, written from what was
actually measured.
docs/DEMO_SCRIPT.md is the three-minute shooting script, written against the
software as built rather than against the planning documents — including a
pre-recording checklist and the figures that moved.
CHANGELOG.md says what was built in each phase and which files it touched.
./scripts/manifest.sh lists the tree newest-first — modification times are
meaningful, so the files at the top are from the most recent session. After the
initial commit, git log and git diff take over.
make setup writes both files for you: .env.example →
services/proof-engine/.env configures the engine, and
apps/web/.env.local.example → apps/web/.env.local holds one variable,
PROOF_ENGINE_URL, telling Next where to proxy /api/v1/*.
Every key in .env.example maps to a real setting — a test asserts it, so a key
that would silently do nothing cannot be shipped.
Three integration modes govern the sponsor services:
| Mode | Behaviour |
|---|---|
live |
Always call the API; fail loudly if unavailable |
fixture |
Never call it; use local fallbacks, labelled CACHED_FIXTURE |
auto |
Call it, fall back on failure — recommended for a recorded demo |
Every stored result carries source_mode, so cached output is never presented as
live.
Configurable workflow templates, stronger document annotations, role-controlled policy management, automated evidence-pack generation and production-grade external verification connectors.
The invariant stays the same:
No consequential action without a traceable evidence path.