Sample deliverable
Sample risk report
Judge the deliverable, not the pitch.
This is the report a Technical Risk Review produces — full structure, real severity language, evidence-led findings, and a fix order a board can read.
“Ledgerline” is fictional. Every finding below is a pattern we repeatedly see in AI-built apps, recombined so no client is identifiable. Client reports stay private.
Review docket
Ledgerline — B2B invoicing SaaS
- Build
- 7 weeks, AI pair tools + a SaaS template
- Team
- 2 founders, 1 contractor
- Stack
- Next.js · Postgres · Stripe
- Trigger
- First paying customers; seed diligence in 6 weeks
- Package
- Technical Risk Review
Executive summary
The launch date holds — after two P0 fixes.
Ledgerline is closer to launch-ready than most AI-built apps we review. The core flows are coherent and the data model is sound. Two findings block revenue: an account-takeover path in password reset, and cross-tenant access to invoice data.
Both are days of work, not weeks. Neither requires rearchitecting — but both need regression tests so they stay fixed.
The trust gaps (P1) don't block launch, but they will surface in enterprise procurement and diligence: unverified payment webhooks and no error visibility. The ordinary debt (P2) is schedulable and should delay nothing.
Risk map
Six findings. Severity, evidence, impact, fix path.
Real reports carry request traces, screenshots, and file references per finding. This sample keeps the structure and abbreviates the evidence.
P0 — Launch blockers
Auth · Password reset
Reset tokens never expire and survive reuse.
What we found
Reset links carry a raw token stored in plaintext. The token has no expiry and stays valid after use. We replayed a used link from an old email and set a new password in a second browser.
Why it matters
Anyone with access to an old email — a forwarded thread, a shared inbox, a breached mailbox — can take over the account. This is the quiet account-takeover path that turns into a disclosure event.
Fix path
Hash tokens at rest, 30-minute expiry, invalidate on use and on password change. Add a regression test that replays a used token and expects rejection.
Effort: ~1 day
Data · Tenant isolation
Invoice endpoints trust the ID, not the organization.
What we found
The invoice detail endpoint checks login but not organization membership, and IDs are sequential. Logged into tenant A, we fetched tenant B's invoices by decrementing the ID.
Why it matters
Cross-tenant exposure of customer names, amounts, and balances. For a finance product, one screenshot of this ends deals and can trigger notification duties.
Fix path
Enforce organization scoping in one shared query layer instead of per-route checks. Add a cross-tenant regression test that fails loud.
Effort: 2–3 days
P1 — Trust gaps
Payments · Webhooks
Stripe webhooks accepted without signature or idempotency.
What we found
The webhook route parses the event body directly — no signature verification, no replay guard. A crafted POST marks any invoice as paid.
Why it matters
Forged or duplicated events corrupt payment state. Silent today; an audit finding and a reconciliation nightmare later.
Fix path
Verify the Stripe signature, key handlers by event ID for idempotency, dead-letter unknown events.
Effort: ~1 day
Operations · Visibility
Errors vanish into a catch-all.
What we found
A global handler returns generic 500s with no contextual logging and no alerting. During review, a failing PDF render returned 500s for 40 minutes without leaving a trace.
Why it matters
You learn about outages from customers. Diligence teams read this as an operational-maturity gap.
Fix path
Structured logs with request IDs, error tracking with alerts on new error classes, basic uptime checks.
Effort: 1–2 days
P2 — Ordinary debt
Codebase · Duplication
Three copies of the invoice-total logic.
What we found
Totals are computed independently in the API, the PDF renderer, and the dashboard — already drifting on rounding behavior.
Why it matters
Ordinary AI-build debt. Becomes a billing-accuracy bug the next time tax rules change.
Fix path
Consolidate into one shared module the next time this code is touched. No dedicated sprint needed.
Effort: Opportunistic
Infra · Migrations
Schema migrates on boot, with no rollback path.
What we found
The app runs database migrations at startup. Two instances racing would corrupt the schema. Harmless on today's single instance.
Why it matters
Blocks horizontal scaling later; not a launch risk now.
Fix path
Move migrations into an explicit deploy step with rollback before running a second instance.
Effort: ~half a day, later
What happens next
The report ends in decisions, not homework.
60-minute readout
We walk founders and stakeholders through the verdict and risk map in plain language. Engineers get the technical appendix with traces and references.
A fix order that respects your date
P0s first, each with a named acceptance check. Nothing padded, nothing vague — every item is either scheduled or consciously accepted.
P0 retest
Once the blockers are fixed, we verify them against the original evidence and reissue the findings as closed.
Want this read on your app?
The sample above is a composite. Your report is specific: your stack, your risks, your fix order — private, under NDA on request.
Request reviewIf it's a fit, we reply within 48 hours. If it isn't, we tell you.