2026 · CUSTOMS SAAS

TariffRefunded

IEEPA tariff refund recovery for SMB importers, racing a 180-day protest window. Broker partnership in progress.

LIVE SITE ↗
START HERE The regulation in my build pipeline A federal statute constrains what my product is allowed to say. An audit found 18 violations in my own copy — so I wired the forbidden phrasings into the build and made shipping one impossible. Read the full story →
728COMMITS
426PULL REQUESTS
28BUILD DAYS
SOURCE: GITHUB COMMIT HISTORY · 2026-06-12
Build cadence — commits per active day
Apr 17 Heaviest day: 122 commits · Apr 23 Jun 10

Overview

A refund-recovery service for small importers after a Supreme Court ruling invalidated IEEPA tariffs: upload customs data, see what you're owed, get connected to licensed professionals to file — racing protest deadlines that expire on a fixed legal schedule. 728 commits and 426 merged pull requests in 28 active days.

Upload-to-broker flow
Customs entry data Refund analysis Protest-deadline flags Broker match

Project Design

Scaffolded in a single ~40-commit day. Privacy was a day-one decision, not a retrofit: analytics and error tracking shipped with importer-data scrubbing already wired in. A federal regulation shaped the product — a compliance audit of the site's own wording found 18 violations, and the forbidden phrasings were then wired into the build checks so a violation can't ship. Mid-build, the evidence forced a pivot from $79 self-serve filing to free analysis plus broker connection.

Anonymous-first analysis funnel — React SPA, Netlify Functions, Supabase RLS
Frontend
React 19 + ViteReact Router 7Tailwind 4Anonymous-first upload/analysis
API / edge
~20 Netlify FunctionsES-003 parser + entry validatorCAPE CSV generatorStripe + webhooksRAG chatbot (OpenAI)
Data
Supabase Postgres + RLS (28 migrations)Anon-session merge-on-authIOR privacy scrub (suffix key only)
External
Clerk (JWT ↔ RLS bridge)StripeResend emailPostHog + Sentry (entry-data denylist)

Key modules

Data

ES-003 parser

Parses ACE entry exports by header name and classifies IEEPA vs. Section 301/232 tariff lines.

Pipeline

Entry classifier

Runs an 8-category eligibility triage with CBP CAPE Stage-2 edge-case flags.

Data

CAPE CSV generator

Produces CBP-compliant declaration CSVs — deduped, check-digit validated, grouped by importer.

Auth

Clerk ↔ RLS bridge

Bridges non-UUID Clerk IDs into row-level security and merges anonymous sessions on sign-in.

Security

PII scrubbing

A four-layer denylist keeps entry numbers, HTS codes, and duty amounts out of analytics and error reports.

Pipeline

Lead scoring

Scores broker-match leads on refund size, deadline urgency, and complexity; disqualifies sub-threshold entries.

Key features

RAG chatbot — security checks in the code, not the prompt

The site's assistant is a retrieval-augmented chatbot — it answers from a fixed knowledge base of CBP guidance rather than the model's memory — and its defenses live in the request path, not just the system prompt. Every message runs a gauntlet before the model is called: input validation, a twelve-pattern prompt-injection scan that returns a 400, IP rate limiting, and a relevance gate where the retrieval step itself refuses anything that doesn't resemble the customs knowledge base. Underneath, row-level security and database grants revoked from the public roles mean a prompt talked into misbehaving still can't reach data it shouldn't. The signed-in version answers questions about a user's own analysis from aggregates, never raw entry rows.

MessageValidateInjection scan → 400Rate limitTopic gate (RAG)Model
The first four checks resolve before a token is spent — the perimeter is in the request path, not the prompt

Compliance-as-CI — honesty enforced in the build

A federal customs-broker regulation limits what an unlicensed tool may claim. Rather than rely on careful writing, TariffRefunded turned the rule into a build check: a denylist of forbidden phrasings ("we produce your CBP declaration," "these are good to go") is grepped on every change to the public marketing pages, and a match blocks the merge unless a reviewer justifies it inline. The first audit found 18 violations across the site; wiring the denylist into CI kept them from creeping back as the product pivoted. The honest caveat: the gate only covers the pages it's pointed at — a phrase outside that scope can still slip through, so the boundary definition is the real control.

Code changeCI greps the forbidden-phrase denylistMatch in a covered page?Blocked — fix or justify inlineMerge
The rule lives in the pipeline, not in a style guide — a violation can't ship past a covered page

Security & ops decisions

Importer-data protection
Importer customs data
Not stored: full importer-of-record numbers dropped from the schema — a suffix key and an opaque group ID stand in
Analytics autocapture off from day one — manual instrumentation only
Four-layer PII scrubber: client, server, error reports, breadcrumbs
Anonymous sessions: header-bound row access; the merge function raises rather than letting an unauthenticated caller hijack an account

Builder notes

Lessons learned

What carried forward

StackBadger was born here as the internal pentest harness. The PII-scrubbing patterns, the auth/data-isolation fix, and the decision-hygiene habit — a versioned strategy doc with an open-decisions table, plus dated site-vs-strategy audits — moved into everything after.

Posts from this project

SECURITY

A prompt is not a perimeter

My customs chatbot's system prompt politely asks attackers not to misbehave. That's the weakest control it has — the ones that actually hold are in the request path and the database.

JUN 2026 · 6 MIN
SECURITY

The regulation in my build pipeline

A federal statute constrains what my product is allowed to say. An audit found 18 violations in my own copy — so I wired the forbidden phrasings into the build and made shipping one impossible.

JUN 2026 · 5 MIN
CASE STUDY

Building for a market with an expiration date

A Supreme Court ruling created a multi-billion-dollar refund pool — one that shrinks every month on a fixed legal schedule. A decaying market changes every product decision.

JUN 2026 · 5 MIN
"A written rule is a suggestion. A gate is a control."
The operating principle behind every project here. The same bug shipped three times past written rules — and zero times past a CI gate. Deterministic enforcement beats advisory documentation, in agent harnesses and security programs alike.