SSajidur Rahman Sajid
ACTIVE2026Backend / AI Engineer

InvoicePilot

AI invoice microservice + Web3 cryptographic seal engine

Python 3.11FastAPIFastifyPostgreSQLRedis StreamsBullMQReact 19SolidityFoundryViemTurnkey KMSMindee OCRCloudflare R2Docker

[ 01 ] — Context

Problem

  • Bookkeeping firms and small businesses drown in manual data entry — hours spent transcribing invoices, matching purchase orders, and reconciling duplicates.
  • Duplicate payments, PO mismatches, and fraud go undetected because there is no structured audit trail, and files are scattered across inboxes and drives.
  • Existing tools either cannot process varied invoice formats at enterprise scale or offer no tamper-evident record of what was processed, when, and by whom.

[ 02 ] — Response

Solution

InvoicePilot is a three-sub-system platform. The AI pipeline turns any invoice file — PDF, webp, jpeg, png — into structured, validated line data. An async engine absorbs spikes without blocking request threads. A Web3 seal kernel anchors every processed record on-chain.

The AI/ML service runs an 11-stage pipeline: file validation → Mindee OCR extraction (30+ fields, per-field confidence) → transformation → normalization (10 functions for currencies, vendor names, dates, emails, phones, URLs) → exact-match duplicate detection → a 12-rule business-logic engine → a 9-rule fraud engine → classification → validation → persistence.

Processing is decoupled through Redis Streams consumer groups. A Fastify API gateway fronts the system with JWT auth (Supabase JWKS), RBAC, sliding-window rate limiting, Redis query caching, and AES-256-GCM encryption for vendor bank details at rest.

[ 03 ] — Structure

Architecture

                     ┌───────────────────────────────────────────────┐
                     │  Fastify API Gateway                          │
                     │  JWT (Supabase JWKS) · RBAC · rate-limit      │
                     └──────────────┬────────────────────────────────┘
                                    │ HTTPS / multipart
                                    ▼
                     ┌───────────────────────────────────────────────┐
                     │  invoice-ai-service (FastAPI)                 │
                     │  11-stage pipeline · 30+ fields · validation  │
                     └──────────────┬────────────────────────────────┘
                                    │ XADD  (Redis Streams)
                                    ▼
                     ┌───────────────────────────────────────────────┐
                     │  Async workers  ·  asyncio.Semaphore(5)       │
                     │  retry (3×, backoff) · DLQ (7-day TTL)        │
                     └──────────────┬────────────────────────────────┘
                                    │  RLS + service role
                                    ▼
                     ┌───────────────────────────────────────────────┐
                     │  PostgreSQL (Supabase, Row-Level Security)    │
                     └──────────────┬────────────────────────────────┘
                                    │  hash + type + ts + signer
                                    ▼
                     ┌───────────────────────────────────────────────┐
                     │  BullMQ seal worker → SealRegistry.sol        │
                     │  Viem + Turnkey KMS · append-only · no PII    │
                     └───────────────────────────────────────────────┘

[ 04 ] — Trade-offs

Key engineering decisions

  1. 01

    Hash-only on-chain (privacy by design)

    The contract stores only {recordHash, recordType, sealedAt, sealedBy} — never invoice amounts or PII. Records are anchored with sha256(domainTag + canonicalJSON(payload)) using NFC normalization, minor-unit money, and RFC3339 UTC. Clients can verify a document without any sensitive data leaving their control.

  2. 02

    Provider-agnostic OCR boundary

    Exactly one file imports the Mindee SDK. Every other module consumes a neutral `DocumentFields` interface, so OCR vendors can be swapped or A/B-tested without touching the pipeline.

  3. 03

    Signer abstraction

    Seal signing runs in two modes — local keypair for dev, Turnkey enclave KMS for production — behind a single `SealSigner` interface. The audit logs record which signer produced each seal.

  4. 04

    RLS FORCE + service-role split

    Tenant isolation is enforced at the database, not the ORM. The API connects with a service role and row-level security FORCE policies keep multi-tenant reads scoped no matter how the query is written.

  5. 05

    Soft-ref seals, crash-safe reclaim

    Seals are soft references (no hard FK) so the ledger stays append-only, and the worker uses XCLAIM idle-reclaim so a crashed consumer's stream entries resume instead of silently dropping.

[ 05 ] — Under the hood

Engineering highlights

Canonical seal hash
from hashlib import sha256
from utils import canonical_json  # stable key order + NFC

def seal_hash(payload: dict) -> bytes:
    domain = b"invoice-pilot.v1"          # domain tag, versioned
    data = canonical_json(payload)        # deterministic serialization
    return sha256(domain + data.encode("utf-8")).digest()
Versioned domain tag prevents cross-domain replay of hashes.
Async engine with bounded concurrency
# Redis Streams consumer group
stream, group = "invoices:processing", "workers"

for message in stream.pending_and_new(group):
    async with asyncio.Semaphore(5):      # max 5 concurrent
        await asyncio.to_thread(run_pipeline, message)  # release GIL
        await xack(stream, group, message)              # commit offset
Concurrency capped at 5 to bound downstream load and DB connections.

[ 06 ] — Outcomes

Results

218
pytest cases passing
11
processing stages
9
fraud rules
12
business rules
5
bounded async workers
30+
extracted fields

[ 07 ] — Visuals

Screenshots

[ 08 ] — Where it's going

Status & next steps

  • QuickBooks / Xero OAuth two-way sync — currently the named biggest integration risk.
  • SOC 2 readiness suite (5 policy docs, trust center, RLS migrations) — continue toward audit.
  • Public demo environment with seeded sample invoices so the pipeline is explorable without credentials.