Skip to content

JowiAoun/MapleVault

Repository files navigation

Provenance — Cryptographic Provenance for Canadian Supply Chains

Ottawa Defence Hackathon · AVSS Cryptographic Provenance Challenge

"Buy Canadian" procurement turns on whether a product is Product of Canada or Made in Canada — but those claims rest on unverifiable supplier self-reporting. This project makes provenance cryptographic: every supplier contribution is a signed attestation, attestations hash-link across tiers into a tamper-evident chain, and that chain is independently verified to compute the Canadian-content designation while detecting forgery, tampering, replay, and statistical anomalies.

The backend POST /verify is the automatically-scored deliverable. It scores 98.3% on the 1,000-chain training corpus, with 100% on every deterministic attack family and zero false positives on clean chains. Everything else (the two UIs, the design system, infra) supports the demo and judging.

System architecture

Container architecture: the stateless /verify backend, the two UIs, and how a request flows. Full diagram set — verification pipeline, anomaly taxonomy, crypto contract — in docs/system-diagrams.md.


TL;DR — run it

Grade the scored backend (exactly what the harness does — no profiles, no .env):

cd backend && docker compose up --build      # serves POST /verify on :8000

Run the full demo stack (both UIs + backend, from the repo root):

cp .env.example .env                          # optional: add OPENAI_API_KEY for the AI panel
docker compose --profile dev  up --build      # hot-reload dev  → web :5173, backend :8000
docker compose --profile prod up --build      # built demo      → web :8080, backend :8000

Then open the web app and try the Purchaser page — six sample products walk every verdict the verifier produces (see Demo guide).


What we built (three deliverables)

# Deliverable Where Scored?
1 Verification backendPOST /verify over the signed attestation DAG backend/ ✅ auto-graded
2 Supplier UI (issue a signed attestation) + Purchaser UI (scan/look up a product, see its provenance) web/ judged in demo
3 Judge presentation — approach, architecture, attack detection, live UI walkthrough docs/ judged

How verification works

Given a product's attestation chain, the backend:

  1. Builds the DAG from each attestation's parents (order-independent).
  2. Computes Canadian content — cost (material_cad + labour_cost_cad) summed by each step's performed_in_country, as a % of total.
  3. Finds the last substantial transformation — the qualifying component_manufacture/subassembly/final_integration (≥ 4 labour hours) closest to the product leaf.
  4. Decides the designation — last transformation in CA and ≥ 98 → Product of Canada; ≥ 51 → Made in Canada; else none.
  5. Runs two tiers of anomaly detection and returns the offending attestation(s):
    • Hard rules (deterministic): invalid / unknown-supplier signatures, parent-hash & unit mismatch, dangling parents, cycles, timestamp inversion, global mass-balance over-consumption, implausible transformations, extreme labour rates, duplicate ids, anchor-registry rewrite / cross-product reuse, plus structural-plausibility invariants that catch unnamed attack classes at zero cost to clean precision.
    • Statistical (t4_*): legal on every rule but anomalous versus how genuine chains look — non-canonical timestamps, labour/cost above the genuine ceiling, and foreign suppliers falsely claiming Canadian origin. Thresholds carry a safety margin above the genuine maximum because detection is F1-scored — precision is protected over recall.

Threat model: the kit ships every supplier private key, so an adversary can produce a correctly-signed malicious chain. A valid signature proves a message wasn't garbled — not that the claim is true. Our value is the forensic detection layer that reasons about whether a chain is internally consistent and economically plausible, not just whether it's signed.

Full write-ups: docs/backend-explained.md, docs/system-diagrams.md, docs/backend-technical-presentation.md.


Repo layout

Path What it is
backend/ Scored component. Python 3.13 + FastAPI POST /verify (Gunicorn + Uvicorn workers). Stateless DAG verification, designation, two-tier detection, opt-in AI audit. Self-contained docker-compose.yml is the grader entry point. See backend/README.md.
web/ Vite + React frontend — Supplier (issue) and Purchaser (verify) UIs. Talks to the live backend; six published demo chains under web/public/chains/.
provenance-hackathon/ Official starter kit — specs, byte-exact reference_lib/, key/anchor registries, training_corpus.jsonl, self_test.py, worked example.
design-system/ Design tokens, components, fonts, icons, motion.
caddy/ TLS sidecar config (optional tls profile — HTTPS for phone-camera QR scans).
docs/ Architecture & verification diagrams, backend teaching guide, presentation guide.
docker-compose.yml Full-stack orchestration with dev / prod / tls profiles.
.env.example Single annotated environment template — copy to .env.

Ports

Service Port URL Profile
web (prod, nginx) 8080 http://localhost:8080 prod
web (dev, Vite HMR) 5173 http://localhost:5173 dev
backend (FastAPI) 8000 http://localhost:8000 dev / prod
Caddy TLS sidecar 443 https://<LAN-IP>/ tls

The web app proxies /api → backend:8000 (nginx in prod, Vite in dev), so the browser only ever talks same-origin.


Test & grade

# 1. Grade /verify against the official labels (backend running on :8000):
python3 provenance-hackathon/self_test.py http://localhost:8000/verify
#    → overall: 98.3%  (1000 cases)

# 2. Backend unit / API / corpus-guard suite:
cd backend && pip install -e ".[dev]" && pytest          # 50 passed

# 3. Byte-exact crypto core (canonical serialization + Ed25519 golden vectors):
cd provenance-hackathon && pip install -r reference_lib/requirements.txt
python3 -m reference_lib.tests.test_golden               # 5/5

# 4. Web suite:
cd web && npm install && npm test                        # 114 passed

Demo guide

The Purchaser page ships six published chains (web/public/chains/), each a real signed chain verified live against /verify — covering every verdict:

Product Verdict Demonstrates
Recovery-Capable ISR Drone ✅ Made in Canada · 58.4% the happy path (worked example)
Foam-lined Equipment Case ✅ Product of Canada · 100% the top designation
Body-Armor Plate Carrier Kit ✅ Not Canadian · 0% an honest foreign product
Man-Portable Solar Kit ❌ Failed tamper → mass-balance violation
Machined Mounting Bracket ❌ Failed forged signature (still claims 92% CA)
Gas-Turbine APU / Genset ❌ Failed subtle statistical origin anomaly

The mounting-bracket + APU pair is the highlight: one looks 92% Canadian but its signature is forged; the other breaks no rule yet is statistically anomalous — showing both detection tiers.


Configuration

All config lives in one root .env (copy from .env.example).

  • Public, browser-inlined: only VITE_* values. Never give a provider secret a VITE_ prefix.

  • Backend-only secret — optional AI audit: the backend exposes an opt-in POST /audit/root-cause that uses an LLM to group detected anomalies into root causes for an auditor. It's off by default and never touches the scored /verify path. Enable it on the backend with:

    ENABLE_AI=true
    OPENAI_API_KEY=sk-...                 # backend-only; rotate if ever exposed
    OPENAI_AUDIT_MODEL=gpt-5.4            # any model your key can call
    OPENAI_AUDIT_TIMEOUT_SECONDS=15

    Without these the endpoint returns a clean 503 — the grader never enables it.


How it's judged

Total 33 points; only Technical Implementation (10) is auto-graded as 10 × (harness score ÷ 100) — our 98.3% maps to ≈ 9.8/10. The other 23 points (Entrepreneurial Drive, Algorithm Approach, Feasibility & Scalability, Storytelling) come from the submission, demo, and presentation. See provenance-hackathon/CHALLENGE.md.

Feasibility & scalability: the backend is stateless — every request carries the whole chain, no database. It scales vertically (Gunicorn master + N Uvicorn workers, CPU-bound Ed25519) and horizontally (N identical replicas behind a load balancer, no coordination). ~4 ms/chain; ~1,372 req/s on 8 workers.


Conventions

  • Commits: Conventional Commits, enforced by commitlint + Husky (see .claude/rules/committing.md).
  • Web lint/format: Prettier + ESLint + a design-token linter via lint-staged on staged web/ files.

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors