2026 · FIRST BUILD

RiskScanAI

Shelved and continued as the basis for later work after the market verdict redirected the product question.

SHELVED Built the original agent workflow and learned the foundation patterns through production failures.
On this page

CONTEXT

The work started here.

A first product combined AI-written small-business security assessments, interviews, and exportable reports.

BUILD

What was built.

My first product: a small business answers ~25 questions and gets an AI-written security assessment, an AI interview that digs deeper, and an exportable report, across three paid tiers. Started off GitHub in late January; 160 commits over 15 active days once the repository existed.

RiskScanAI screenshot
  1. The pitch: a consultant-grade risk assessment that used to cost $10K+, delivered from plain-language questions.
  2. Take the free snapshot — the funnel starts unauthenticated by design; guest, free, and paid tiers gate at the paid features.
  3. A linked security-practices page — the one hardening day that replaced decorative token checks with real verification sits behind it.
  4. Plain language, a ~10-minute snapshot, no credit card — the conversion framing of the three tiers.

PROJECT DESIGN

How it was shaped.

First product, first agent workflow, and where the foundational patterns got paid for: the async background-work architecture from a six-day timeout war, a one-day security retrofit that replaced decorative token checks with real verification, and a failure taxonomy for AI output that maps what users see to which contract piece broke.

First build — React SPA, Netlify Functions, Supabase, Claude
Frontend
React 18 + ViteZustand storesReact Router SPA
API / edge
11 Netlify Functions + edge auth guardClerk JWT verification26s timeout pins + background functions
Data
Supabase Postgres + RLS (5 tables)Code-level ownership re-checks on service-role queriesAudit log
External
Claude (Sonnet 4, cached prompts)Clerk authStripe (idempotent webhooks)

Key modules

Pipeline

Snapshot engine

A 21-question, 5-section intake feeding deterministic domain scoring.

Data

Derived-signals processor

Computes risk tier, compliance tracks, and active signals server-side — stable for prompt caching.

AI

Summary pipeline

Returns a 202 and generates the Claude risk summary in a background function the frontend polls.

AI

Interview chat

A domain-by-domain CIS IG1 gap interview that emits structured state via delimiter blocks.

Pipeline

Report generation

Enriches findings into a NIST CSF view with PDF and PowerPoint exports.

Auth

Access & payments

Three-tier guest/free/paid gating over Clerk + Stripe with idempotent webhooks.

Key features

Never await an LLM — the async summary

Netlify cuts off an HTTP request at 26 seconds; a Claude summary under load can take longer. The first version called the model inline, so heavy requests returned a 504 error page that the frontend then tried to parse as JSON — and crashed. The fix splits the work: finishing the questionnaire returns immediately with a deterministic summary built from the derived signals, schedules the Claude call in a background function with a 15-minute budget, and the page polls every few seconds, swapping in the richer AI version when it's ready. The user never stares at a spinner waiting on the model.

Snapshot submitted202 + background task scheduledFallback summary shown (~3s)Claude finishes in backgroundPoll detects resultAI summary swapped in
The HTTP request never blocks on Claude — no 26s timeout, no 504

SECURITY & OPS

The operating decisions.

  • The early prototype skipped token signature verification — before any real users or data were on the site. One hardening commit added full verification, security headers, webhook idempotency, and timing-safe admin comparisons across 13 files.
  • Row-level security on all five tables keys on the JWT subject claim, with service-role functions re-enforcing ownership in code as a deliberate second layer.
  • The funnel starts unauthenticated by design: guest, free, and paid tiers were a conversion decision, with the gates at the paid features.
Tenant isolation
Authenticated request
Token signature verified — one hardening day replaced a decorative check with real verification
Row-level security on all five tables, keyed on the JWT subject claim (the user's stable ID from the signed token)
Service-role functions re-enforce ownership in code — a deliberate second layer

BUILDER NOTES

What the build taught.

  • Never await an LLM inside a serverless request: return 202 in under a second, run the model in a background function, poll for the result — the fix after a six-day timeout battle.
  • A model ID and its feature set are one unit: pin them together and document the pairing, or every upgrade silently breaks the prompt machinery built around the old model.
  • An autonomous overnight agent run produced ~20 commits from a written playbook with stop conditions — fixed test infrastructure, an error boundary, SEO, and five page redesigns.
  • Dead code was deleted with a documented restore path: ~8,700 lines removed, every deletion logged with its one-line git restore command.

LESSONS

What changed afterward.

  • Never make a user wait on an AI inside a web request: acknowledge instantly, work in the background, show progress. Perceived wait dropped from ~60 seconds to ~15.
  • The prototype's security was decorative until one hardening day made it real: verify tokens properly, allowlist origins, leak nothing in error messages.
  • An AI model and the prompt machinery around it are one unit. Swap one without the other and things break quietly.
  • Validate AI output before trusting it: reject incomplete responses and fall back to something deterministic the user can still use.

WHAT BROKE

A web request could not carry the AI wait.

A six-day timeout war established the background-work pattern: acknowledge promptly, run slow work outside the request, and show progress.

CONTROL

The constraint that held.

AI output is rejected when incomplete and replaced with deterministic fallback; token and origin handling were hardened after the prototype phase.

EVIDENCE

Where to inspect it next.

  • The early prototype skipped token signature verification — before any real users or data were on the site. One hardening commit added full verification, security headers, webhook idempotency, and timing-safe admin comparisons across 13 files.
  • Row-level security on all five tables keys on the JWT subject claim, with service-role functions re-enforcing ownership in code as a deliberate second layer.
  • The funnel starts unauthenticated by design: guest, free, and paid tiers were a conversion decision, with the gates at the paid features.
Featured field noteRead Never make a user wait on an AI

CARRIED FORWARD

What survived the project.

Everything: the successor is literally the same repository continued. Six agent skills and three reviewer agents survived into a roster that grew to 42 and 11, and the honest verdict (“nobody pays for an AI-interview risk assessment”) re-aimed the product at a question businesses do pay for.

WRITING

Field notes from this work.

Trust belongs in the schema, not the application.
The operating principle behind every project here. A rule the database enforces can't be forgotten in a hurry. Constraints, denied-by-default access, append-only logs — the controls that hold are the ones the system won't run without.