Verification Platform for Renewable Energy Certificates

Client: Eric Arnold, Viro Trade
Role: Sole engineer — architecture, backend, frontend, data pipeline, deployment
Domain: Renewable energy certificate (REC) verification and audit
Status: Built and deployed; engagement concluded before full rollout

Executive Summary

Viro Trade audits renewable energy certificates, confirming that RECs a buyer paid for were genuinely issued, retired, and not double-counted. Every audit was manual assembly across registry exports, PDFs, and emails, and ran to days. I built the platform that ingests proof in whatever form a registry emits, extracts it with AI, and checks it against the registries down a second independent path, so a fault in one can't manufacture agreement with the other. Sole engineer, architecture through deployment.


1. The Project

Viro Trade performs independent verification audits on renewable energy
certificates — confirming that RECs a buyer paid for were genuinely issued,
genuinely retired, and not double-counted. The firm reports that its team now
audits roughly 30% of all voluntary REC transactions in the United States
each year
.

Every audit was performed by hand, against spreadsheets accumulated across
multiple files and several years of trading. The auditor's real work wasn't
judgment — it was assembly: opening registry exports, chasing down the PDF or
email evidencing a particular retirement, cross-checking figures between
workbooks never designed to be joined. A single audit ran to days, and
scaled only by hiring more auditors.

The brief was to automate that assembly and turn weeks into seconds — not
just to absorb more volume, but to make the capability sellable to other
firms as automated auditing. That second goal set the engineering bar: a
system sold to peers and subject to scrutiny has to be auditable and
traceable by construction, not by careful use.

The hard part is that RECs are issued and retired through several independent
registries — WREGIS, M-RETS, NAR, ERCOT, Green-e — sharing no common format
and no common export. Proof of a transaction arrives as whatever the registry
or counterparty emitted: a CSV, a PDF certificate, an email, a screenshot, a
chat transcript. Viro ingests any of those, uses AI models to extract the
transaction data, and retains every original file linked to the records
derived from it. Separately, it pulls data directly from the registries. Those
two sources — what the paperwork claims and what the registry shows — are
what a verification compares.

Scope of delivery. Built and deployed solo, architecture through
deployment. The end-to-end path runs for a subset of the target registries,
and real registry documents were processed through the extraction pipeline.
The engagement wound down before the remaining registries were completed and
before the platform entered day-to-day audit work, so no complete audit was
executed through it and the weeks-to-seconds objective was never measured.
What follows describes what was designed and built, not an operational
result.


2. Technical Details

Stack

LayerTechnology
LanguageJava 21
FrameworkSpring Boot 3.5.5 (Web, Data JPA, Security, Validation)
BuildGradle 8.14.3 (multi-module)
DatabaseMySQL (AWS RDS)
MigrationsLiquibase
AuthSpring Security + JWT (jjwt)
API docsspringdoc-openapi / Swagger UI
AI integrationSpring AI (OpenAI, Anthropic, Google GenAI providers)
Document processingApache PDFBox, tabula-java
FrontendReact 19, TypeScript, Vite 7, Tailwind CSS 4
Frontend data/stateTanStack React Query 5, React Hook Form + Zod
Frontend testingVitest, Testing Library, MSW
Automationn8n (workflow orchestration)
OS targetUbuntu 24.04

Architecture

A seven-module Gradle build, separated by responsibility rather than by feature, so that each layer can be developed and tested independently.

Viro Trade architecture

Multi-Provider AI Layer

The most substantial piece of engineering in the system is the ai-provider module: a vendor abstraction that lets the platform talk to four AI providers — OpenAI, Anthropic, Google Gemini, and OpenRouter — through a single interface.

This was a deliberate architectural decision rather than a convenience. Most AI-backed platforms hard-wire themselves to one vendor and inherit that vendor's pricing, availability, and model deprecation schedule as a business risk. Viro selects a client per request, with a configured fallback, so a price change or an outage at any one provider is a configuration change, not a rearchitecture. Different document types can also be routed to whichever model handles them best or most cheaply.

Built on that abstraction:

Two of those capabilities matter more here than they would in a typical AI product. Audit logging of every model call means the extraction step is itself auditable — for a verification firm, "a model read it off the PDF" is only acceptable if there's a record of which model, which prompt, and what it returned. Database-managed prompts mean extraction can be corrected and re-versioned as registry document formats change, without a deployment and without losing the history of how a given record was originally extracted.

This layer is the most complete part of the system: it is deployed and has processed real registry documents, driving the AI extraction paths for retirement certificate ingestion.

Ingestion Pipeline

The two sides are gathered by completely independent paths, which is what makes the comparison meaningful: the document side never informs the registry side. The frontend queries the REST API to review discrepancies, correct extraction errors, and produce reporting.

Document ingestion pipeline

Frontend

A React 19 + TypeScript single-page application built with Vite, communicating with the backend exclusively over REST/JSON. TanStack React Query handles server state, React Hook Form with Zod schemas handles form validation, and Recharts drives the reporting views. Tested with Vitest, Testing Library, and MSW.

Engineering Practices