AI builders have made it normal to go from idea to working app in a weekend. That is a real achievement, and we are not going to pretend otherwise.
What has not changed is the list of things that go wrong when strangers start using software. The tools are good at the parts you can see. The parts you cannot see are where the trouble is, and they look exactly the same in a safe app as in an exposed one.
This is the checklist we work through at the start of every rescue, whichever tool the app came from. It is broader than our Supabase RLS walkthrough, which goes deep on one item. Here the aim is coverage: twelve checks, each with a way to prove it rather than assume it.
If you only have two minutes, our production readiness check scores the big ones. If you have an afternoon, keep reading.
When this list starts to matter
Not on day one. A prototype that only you and a few testers use does not need hardening, and spending money on it is premature.
It starts to matter the moment any of these is true:
- People who are not you are signing up
- The app stores personal data: names, emails, addresses, anything uploaded
- Money moves through it, or it calls a paid API on your account
Once one of those is true, every item below is worth an hour.
Accounts and sign-in
1. Every page and endpoint checks who is asking
AI-generated apps often protect pages by hiding them. The link disappears when you are signed out, but the page, or the API behind it, still answers if you ask directly.
Test: sign out, then paste the URL of an account page or an admin screen straight into the browser. Then open the network tab while signed in, copy a request the app makes, and replay it from a private window with no session. Anything that comes back with data is unprotected.
2. Password reset and email change cannot be hijacked
Reset links should expire, work once, and be tied to the account that requested them. Changing the email on an account should require the current password or a confirmation sent to the old address. Otherwise anyone who gets into a session for a minute can take the account permanently.
Test: request two reset links and check the first stops working. Use a link twice. Try changing your email without re-entering your password.
3. Admin is a role the server checks
"Is this user an admin?" should be answered by the database or the server, never by a flag the browser sends or a field the user can edit on their own profile.
Test: look at the request that loads or updates your profile. If there is a role, is_admin or similar field in it, try changing it.
Data
4. The database enforces who sees what
This is the one that matters most, and the one we find broken most often. On Supabase it means row-level security on every table, with policies that tie each row to its owner. On other stacks it means the server filters every query by the signed-in user, rather than trusting an ID from the URL.
Test: two browsers, two accounts. In the second, try to load the first account's records by changing an ID in the URL or in a replayed request. If anything comes back, your access rules live in the interface. Our Lovable and Supabase security guide has the SQL to find every unprotected table and every policy that is too loose.
5. Uploaded files are private unless meant to be public
Storage buckets have their own rules, separate from your tables, and they are the thing most often forgotten. Invoices, ID documents and anything a customer uploaded should not sit in a bucket that serves files to anyone with the link.
Test: upload a file as one user, copy its URL, and open it in a private window. Then check each bucket's settings for "public".
6. Inputs have limits
A form that accepts any length of text, or an upload that accepts any file of any size, is an easy way to fill your storage or your bill. Set maximum sizes, allowed file types and sensible length limits on the server, not just in the form.
Secrets and money
7. No secret keys in the front end
Anything in the JavaScript the browser downloads is public. That includes keys pasted into a prompt "just to get it working".
Test: open developer tools, search all sources for service_role, sk_live, sk- and the first few characters of each key in your dashboard. Anything you find has to be rotated, not just deleted, because it has been readable since the day it shipped.
8. The server decides the price
If the amount, quantity or discount arrives from the browser and is charged as sent, a customer can change it. The server should look up what things cost and calculate the total itself.
Test: in the network tab, find the request that starts checkout. If you can see a price in it, try lowering it.
9. Payment webhooks are verified
Your app learns that a payment succeeded from a webhook. If it does not verify the signature on that request, anyone who finds the URL can tell your app they have paid. Stripe, and most other providers, sign every webhook so you can check it genuinely came from them.
10. Anything that costs you money is rate limited
Sign-up, login, password reset, anything that sends an email or a text, and anything that calls an AI API. Without a limit, one script can run up a bill or lock out your users in an evening. This matters most for edge functions and API routes that call paid services on your account.
Test: submit the same form twenty times quickly. If all twenty go through, so would twenty thousand.
Running it
11. You have restored a backup
Backups being switched on is not the same as backups working. Restore one into a separate project, check the data is all there, and write down how long it took. That number is how long you would be down on your worst day.
12. You would know if something went wrong
Errors should go somewhere a person will see them, and logs should be kept long enough to answer "who accessed this, and when?" If you ever had to report a breach, under UK GDPR that is within 72 hours of becoming aware of it, and you cannot assess what happened without logs.
While you are here, check the dependencies. AI builders pin whatever versions were current on the day the code was written, and nobody updates them afterwards. Running npm audit takes a minute and tells you whether any of them have known problems.
What to do with the results
Sort what you found into three piles.
Fix today: exposed keys (rotate them), tables or buckets anyone can read, prices the browser can set. These are the ones that turn into incidents.
Fix before launch: unprotected endpoints, unverified webhooks, missing rate limits, an untested backup.
Fix as you go: input limits, logging, dependency updates. Important, but nothing is on fire.
None of this means the app was a mistake or needs rebuilding. In most of the AI-built apps we review, the application code is a reasonable starting point. What is missing is the protection around it, and that is days of work, not months. If you are weighing up the bigger question of whether to keep the codebase at all, we have written about when to keep an AI-built app and when to rebuild.
If you would rather hand it over
We do this every week. Send us the code through our Lovable page and a senior developer will come back within two working days with a written review: what is risky, what is fine, and what fixing it would cost. It is free, and the report is yours either way.
If you go ahead, the two-week sprint is £1,950 for a small codebase and covers everything on this list, fixed rather than just reported. Larger codebases are quoted in the review. For the wider picture of getting live, see what it takes to take a Lovable app to production.


