Back to Work

Priority Soft (2026–Present): ACA Compliance Platform

A healthcare-compliance platform for a US tax resolution practice that automates IRS ACA reporting: Form 1094-C/1095-C generation, employee coverage tracking, payroll ingestion, and validation. Built solo, architected to commercialize as a SaaS product.

Next.js 16
React 19
TypeScript
Tailwind CSS 4
Drizzle ORM
PostgreSQL
BullMQ
Redis
Turborepo
Playwright
Railway

Problem

US employers must file IRS Forms 1094-C and 1095-C to prove Affordable Care Act coverage, or face per-return penalties. The data is scattered across payroll exports in inconsistent formats, and reconciling coverage month-by-month for every employee is manual, slow, and error-prone. A tax resolution practice needed to do this reliably at scale and eventually sell it as a product.

Architecture

A Turborepo monorepo with strict package boundaries that separate regulatory business rules, algorithms, infrastructure adapters, and the Next.js 16 application, so ACA logic stays isolated from framework code and is independently testable. A unified Drizzle ORM + PostgreSQL data layer sits behind migration guardrails enforced in CI. Heavy work (payroll parsing, form PDF generation) runs on BullMQ + Redis background workers to keep the app responsive. An LLM-assisted normalization step maps varied payroll formats into a single canonical data model. Quality is enforced with a Playwright E2E suite, a quality-scorecard ratchet, and Railway-based staging CI/CD.

Key Design Decisions

  • Isolated regulatory business rules in dedicated packages behind strict boundaries. Tax rules change yearly; keeping them out of framework code makes them auditable and safe to update
  • Ran parsing and PDF generation on background workers (BullMQ + Redis) rather than in request handlers. Batch filing operations are heavy and must not block the UI
  • Used LLM-assisted normalization to ingest varied payroll formats into one canonical model, instead of hand-writing a parser per client format
  • Wrote a migration drift-guard (after two real staging outages) that validates every Drizzle migration as a SQL + snapshot + journal triplet and fails CI on any drift, orphan SQL, or non-monotonic timestamp, and reports every problem at once instead of just the first
  • Gated CI behind a 7-dimension quality-scorecard ratchet (tsc, eslint, type-coverage at 100%, knip, dependency-cruiser, file-size, tests) that fails on any regression from baseline. The ratchet itself is unit-tested.
  • Enforced architecture boundaries with dependency-cruiser as CI errors: domain can't import Next or infrastructure, and the algorithms/parsing packages stay framework-agnostic
  • Built state-specific ACA filing validators (NJ/RI fixed-width, DC CSV) on top of the federal 1094-C/1095-C logic, plus line-15/line-16, COBRA, ICHRA, and lookback-period modeling
  • Built as a monorepo from day one to keep a future multi-tenant SaaS split cheap

Tradeoffs

  • The strict package boundaries cost me some ceremony and indirection up front. The payoff shows up when a tax rule changes (and it will, every year): the regulatory logic is isolated and safe to touch.
  • Letting an LLM normalize payroll formats absorbs the messy inputs a rigid parser chokes on. The price is a validation layer that assumes the model will occasionally be wrong.
  • Redis and a queue to babysit are more moving parts than I'd like. But filing runs are heavy, and I wasn't going to block the UI on them.

Outcome

In active development as the sole engineer on the platform (an 11-package Turborepo, ~90K lines of source, 100+ test files), owning the full stack from database schema to deployment pipeline. Replaces manual, penalty-prone ACA reconciliation with automated 1094-C/1095-C generation, validation, and cross-reference diagnostics, and it's built from the start to become a commercial multi-tenant SaaS.

Lessons Learned

  • On a compliance product, the quality gates are the product. A wrong number here isn't a bug, it's a mis-filed federal return, so the E2E suite and migration guards earn their keep.
  • Two staging outages taught me to treat every migration as a SQL + snapshot + journal triplet and fail CI on any drift. That guardrail came from getting burned, not from a best-practices article.
  • An LLM is a great parser for input you can't predict, right up until you trust it without a deterministic check sitting underneath.