Portfolio project · C# / .NET + AI integration

LedgerLens

AI-assisted transaction mapping for messy financial data.

Live demo available C# / .NET 9 ASP.NET Core EF Core + SQLite Mock AI

The problem

Real-world transaction data is not clean. A bank or payment processor hands you strings like these:

AMZN Mktp US*8H2K91 SQ *LOCAL COFFEE PAYPAL *DIGITALOCEAN OPENAI *CHATGPT SUBSCRIPTION WM SUPERCENTER #2857

Categorizing these by hand is tedious and error-prone at scale. Handing the problem entirely to an AI model introduces a different risk: opaque decisions, inconsistent outputs, and no way to audit why a transaction was labeled the way it was.

Neither extreme fits real enterprise software. You want deterministic rules where rules work, AI assistance where they don't, and a human in the loop before anything gets committed.

The solution

LedgerLens routes every transaction through a fixed, ordered pipeline. Each step only runs if the previous one didn't resolve the transaction.

  1. 01
    Normalize

    Strip noise characters, collapse whitespace, uppercase the description. Turn SQ *LOCAL COFFEE into LOCAL COFFEE.

  2. 02
    Match existing rules

    Walk the rule library in priority order — exact match first, then prefix rules, then regex patterns. First match wins. No AI call needed.

  3. 03
    Ask AI

    If no rule matches, send the normalized description to OpenAI and request a structured JSON response: vendor, category, subcategory, confidence score.

  4. 04
    Queue for review

    AI output never goes directly into the database. It enters a review queue. A human sees the suggestion before anything is committed.

  5. 05
    Approve, edit, or reject

    The reviewer accepts the suggestion, modifies the category, or rejects it. Every outcome is recorded with a timestamp and user identifier.

  6. 06
    Write a rule

    An approved suggestion becomes a new mapping rule. The next identical or similar transaction matches the rule and never touches the AI layer.

  7. 07
    Append to audit log

    Every action — rule match, AI suggestion, approval, rejection, rule creation — is written to an append-only audit table with timestamp and user. Nothing is overwritten.

Architecture

Five focused project layers, each with one job and one direction of dependency. The core business logic has no infrastructure dependencies — no EF Core, no HTTP, no OpenAI. Fully unit-testable.

LedgerLens.Web
Review queue UI, approval interface, and rule browser. React or minimal HTMX — not yet decided. Communicates only with the API layer.
LedgerLens.Api
ASP.NET Core Minimal API. Endpoints for transaction import, queue management, rule CRUD, and audit log queries. Orchestrates the pipeline.
LedgerLens.Core
Business logic only. Normalizer, RuleMatcher, ReviewQueue. No infrastructure dependencies — no EF Core, no HTTP, no OpenAI. Fully testable in isolation.
LedgerLens.AI
OpenAI / Azure OpenAI integration. Structured output schema, confidence scoring, fallback handling. Isolated so the AI provider is swappable without touching the pipeline.
LedgerLens.Data
EF Core DbContext and migrations. SQLite for local development and the live demo. Swappable for SQL Server or Postgres with no application-layer changes.

Interactive demo

The full .NET app is deployed and running. Import a transaction, watch the pipeline normalize and classify it, generate a mock AI suggestion, then approve or reject it to create a reusable mapping rule.

Open live demo →

shippedbysayre.com/ledgerlens is this writeup. ledgerlens.shippedbysayre.com is the deployed app.

Demo safety

  • All transactions are synthetic — fabricated for demo purposes.
  • The AI provider is a local mock. No external AI service is called.
  • No paid APIs are used. No API keys are required.
  • No real financial data is stored or processed.
  • Data entered is visible to other demo visitors — do not enter personal information.

Static preview (what the interface looks like)

Live demo available Mock AI only Preview below is a static mockup · visit the link above for the real app
Review queue 8
    AI suggestion

    Why this project

    The transaction mapper is the vehicle. The point is to show what responsible AI integration looks like inside a real .NET codebase — the engineering parts that actually matter in production.

    Validation at the boundary
    AI responses are validated against a strict schema before they touch the application. Malformed or out-of-schema outputs are rejected and logged, not silently accepted.
    Human review
    No AI output is written directly to the database. Every suggestion passes through a queue and requires a human decision. The AI assists — it doesn't decide.
    Deterministic fallback
    Rules are evaluated first. Predictable, auditable, and free. AI is the fallback, not the primary path. The rule library grows over time and AI calls become rarer.
    Auditability
    Every categorization is traceable to a specific rule match or a specific reviewer decision at a specific timestamp. Nothing is a black box.
    Cost-conscious AI usage
    Approved suggestions become reusable rules. The next similar transaction never hits the API. Token usage decreases as the rule library matures.
    Clean persistence
    EF Core with a focused DbContext, append-only audit table, and no God-object repositories. The data layer is deliberately boring.

    Roadmap

    The project is in early planning. Architecture is defined; the build starts with the core pipeline.

    Current focus

    MVP

    • Static demo page with sample transactions
    • EF Core schema and migrations
    • Normalizer and rule matching engine
    • Minimal API endpoints for import and queue
    • OpenAI structured output integration
    • Review queue and approval workflow
    • SQLite persistence
    • Append-only audit log
    • Deployment-ready web demo
    Planned

    Extended features

    • CSV transaction upload
    • User-defined category taxonomy
    • Rule priority editor
    • Dashboard: match rate, AI fallback rate, cost metrics
    • Export approved mappings
    • Rule conflict detection