This page is the short version of a rescue audit.
The full deal review adds a deal card for brokers, a risk map, costs in pounds, open source and IP, AI features, cost and scalability, privacy, questions for the seller and the evidence behind every finding.
Rescue audit, buyer-side, delivered in 7 working days
Sample Co. booking platform
B2B appointment-booking SaaS for small clinics. About 140 paying customers, listed at £9,400 monthly recurring revenue. Under offer to a non-technical buyer.
Stack
Next.js, Supabase, Stripe, Vercel. Partly built with Cursor
Access used
Read-only: repo, Vercel, Supabase, Stripe, test account
Verdict
Fix, don't rebuild. About 18 hours before completion.
The data model is sound and the product works. The serious problems are a handful of configuration and access mistakes, not a rotten codebase. Two of them expose every customer's data today and must be fixed before money changes hands. The rest can follow in the first month of ownership.
What this means for the deal
Before completion
Ask the seller to fix findings 1 to 3 and move the accounts in finding 5 into the business's name. About 14 hours of work. If they won't, agree who pays for it.
Revenue check
Stripe shows £9,050 a month, not the listed £9,400. Two annual plans were counted as monthly. Worth raising with the seller.
After close
Findings 4, 6, 7 and 8 fit into the first 30 days. None blocks the sale, but finding 6 is quietly leaking revenue.
Scorecard
Top findings
1. Admin database key shipped to every browser
- What
- The Supabase service key, which bypasses all security rules, is included in the front-end code. Anyone who opens the site's developer tools can copy it.
- Business risk
- Anyone can read, change or delete every customer's data. A breach here is a reportable data incident.
- Fix
- Rotate the key today, move the two calls that use it to the server. About 3 hours.
2. Customers can see other customers' bookings
- What
- Row-level security is switched off on 4 of 11 tables, including bookings and invoices. Changing one number in a request returned another clinic's records.
- Business risk
- Patient appointment data from one clinic is visible to others. Serious for trust and for UK GDPR.
- Fix
- Turn on and test rules for all 11 tables. About 6 hours.
3. Payment webhook can be faked
- What
- The endpoint Stripe calls after a payment doesn't check the signature, so anyone can send a fake "paid" message.
- Business risk
- Accounts can be upgraded without paying. No sign it has been abused yet.
- Fix
- Verify signatures and ignore repeats. About 3 hours.
4. Backups exist, restore never tested
- What
- Daily database backups are on, but nobody has ever restored one. Uploaded files (clinic logos, PDFs) aren't backed up at all.
- Business risk
- A bad migration or deletion could mean days of downtime, or permanent loss of uploaded files.
- Fix
- Test a restore on a copy, add storage backups, write a one-page recovery note. About 4 hours.
5. Key accounts belong to the founder personally
- What
- The domain, Vercel and Stripe accounts sit under the founder's personal email and card.
- Business risk
- If these don't transfer cleanly, the buyer doesn't fully own the business they paid for.
- Fix
- Move each into the company's name before completion. About 2 hours, plus the seller's time.
All findings
| # | Finding | Area | Severity | Hours |
|---|---|---|---|---|
| 1 | Service key in front-end bundle | Secrets | CRITICAL | 3 |
| 2 | Row-level security off on 4 tables | Data protection | CRITICAL | 6 |
| 3 | Webhook signature not verified | Payments | HIGH | 3 |
| 4 | Restore untested, files not backed up | Backups | HIGH | 4 |
| 5 | Accounts in founder's personal name | Hosting | HIGH | 2 |
| 6 | Cancelled plans keep access for 30 days on 2 of 3 code paths | Code health | MEDIUM | 10 |
| 7 | Framework two major versions behind; 3 high-severity package advisories | Dependencies | MEDIUM | 4 |
| 8 | No tests on billing; error alerts go to an inbox nobody reads | Monitoring | MEDIUM | 6 |
| 9 | README doesn't run; 14 unused routes | Code health | LOW | 3 |
| Critical and high total | 18 | |||
| All findings total | 41 | |||
Transfer checklist
Every account the business depends on, and whether it moves cleanly to the buyer.
| Account | Held by | Transfer route | Status |
|---|---|---|---|
| Domain | Founder, personal | Registrar account transfer | ACTION |
| Vercel hosting | Founder, personal | Move project to a company team | ACTION |
| Stripe | Founder, personal | Stripe account ownership change | ACTION |
| Supabase | Company organisation | Change organisation owner | READY |
| GitHub repo | Company organisation | Change organisation owner | READY |
| Email sending service | Company | Change account owner | READY |
| Analytics | Former contractor | Recreate under company | ACTION |
| Error tracking | Company | Change account owner | READY |
| SMS reminders API | Company | Check terms allow a change of owner | CHECK |
30-day fix plan
- Before completion: rotate the leaked key and move it server-side (1), switch on row-level security (2), verify webhooks (3), move accounts into the company's name (5).
- Week 1 of ownership: test a restore and add file backups (4). Recreate analytics under the company.
- Weeks 2 to 3: put cancellation logic in one place and close the 30-day access gap (6). Add tests around billing (8).
- Week 4: upgrade the framework and patch flagged packages (7). Route error alerts to someone who acts on them.
Keeping it safe after the fixes
Monthly: patch dependencies, check that backups ran and a restore still works, review error alerts and uptime, and remove access for anyone who has left. About 2 to 4 hours a month for an app this size.