PutThrough Product engineering studio
Book a free call

Free checklist

The pre-launch checklist for AI-built apps.

The same twenty things our paid audit checks, written so you can test your own app — most take a few minutes each. Tick each one that passes. Whatever you can’t tick, or can’t check, is where to look first.

  • Free, no sign-up
  • Twenty checks
  • About an hour

Run these only on an app you own or have written permission to test. Probing someone else’s app without permission is unauthorized access, however good the intention.

01The checklist

Twenty checks, in the order the audit runs them.

Tick a check once your app passes it. The mobile four only apply if you ship to the App Store or Google Play.

Security

  1. How to check
    In the Supabase dashboard, open Advisors → Security Advisor and look for tables flagged with row-level security disabled. Then sign out of your app, copy one of its own database requests from the browser’s Network tab (a URL containing /rest/v1/) and run it again.
    Passes if
    No table holding user data is flagged, and the signed-out request returns nothing private.
    Why it matters

    Row-level security was never switched on, so the browser key that ships in your JavaScript bundle can read every row in every table — including other customers’ records. From the outside the app looks completely normal.

  2. How to check
    Open your live site, go to the Sources tab in the browser’s developer tools, and search the JavaScript for “service_role”, “sb_secret_”, “sk_live_” and “secret”.
    Passes if
    Only publishable keys reach the browser — the Supabase anon or publishable key, a Stripe pk_ key — and nothing that can bypass your access rules.
    Why it matters

    An admin-level key was used in client code to work around access rules that were never configured. It bypasses every policy you add later, so fixing the policies alone changes nothing.

  3. How to check
    As an admin, copy the request an admin-only action sends (Network tab → Copy as cURL). Sign in as an ordinary test user, swap that user’s session token into the copied request, and send it.
    Passes if
    The request is refused by the server or the database, not merely hidden in the interface.
    Why it matters

    The role check lives in the React component. The endpoints behind it have none, so anyone who calls them directly can perform administrative actions — including changing their own role.

  4. How to check
    Create two test accounts in two separate organizations. Signed in as the first, copy a request that loads one of its records, change the ID to one of the second account’s records, and send it.
    Passes if
    Nothing belonging to the second account comes back.
    Why it matters

    The tenant identifier used to filter queries is read from a value the client sends. Change it in the request and another organization’s records come back, because the server never checks it against the session.

  5. How to check
    Upload a file as a test user, copy the file’s URL, and open it in a private window while signed out. In Supabase, Storage shows whether each bucket is public.
    Passes if
    Private files only open through a signed URL that expires; the bare URL shows nothing to a signed-out visitor.
    Why it matters

    The storage bucket was left open and filenames are predictable. Invoices, identity documents and private images are readable without logging in, and enumerable by anyone who guesses the pattern.

Payments

  1. How to check
    In test mode, buy with the test card 4242 4242 4242 4242. Check the webhook deliveries to your endpoint in the payment provider’s dashboard, then the buyer’s plan in your database. In your webhook code, look for a signature check (in Stripe, constructEvent with your webhook signing secret).
    Passes if
    Every delivery gets a 2xx response, the account upgrades within seconds, and the handler rejects events without a valid signature.
    Why it matters

    The card is charged, the customer sees a success screen, and the account is never upgraded. Almost always the webhook is unverified, unhandled, or never arrives at a handler that does anything.

  2. How to check
    In the payment provider’s dashboard, resend a webhook event that has already been delivered successfully, then look at the buyer’s rows in your database.
    Passes if
    Still one subscription and one payment record: the handler recognises events it has already processed.
    Why it matters

    Payment providers retry webhooks by design and occasionally deliver duplicates in normal operation. The handler inserts a row each time, so your database quietly disagrees with the provider about what was bought.

  3. How to check
    In test mode, cancel a test subscription and refund a test payment from the provider’s dashboard, then sign in as that test user.
    Passes if
    Access ends when it should and the refund shows up in your own data — not only in the provider’s.
    Why it matters

    One event is handled — the successful checkout — and nothing else. Canceled customers keep their access, refunded customers still count as revenue, and failed renewals are invisible.

  4. How to check
    Find the server code that creates the checkout session and see where the amount or price ID comes from.
    Passes if
    The server looks the price up from your own product list. The browser only says which product, never how much.
    Why it matters

    The amount to charge is sent from the client to the checkout session. Anyone can change it in the request before it is sent, and pay whatever they like.

Reliability

  1. How to check
    Run a production build on your own machine (your build command, then start or preview) and compare the environment variable names your code reads with the ones set on your host.
    Passes if
    The production build runs locally, and every variable the code reads is set on the host.
    Why it matters

    Different environment variables, a missing build step, a server-only library imported into client code, a database connection that works from your laptop and not from the host. The error is a 500 with nothing behind it.

  2. How to check
    Ask yourself: if the app broke at 3am, who would be told, and how? Look for an error tracker receiving events from production and an uptime monitor checking the site.
    Passes if
    An alert reaches you within minutes, and production errors arrive in a tracker with enough detail to diagnose.
    Why it matters

    No error tracking, no uptime check, no alerting. A broken payment path or a failing migration is reported by whoever happens to hit it, and there is no trace left to diagnose from afterwards.

  3. How to check
    Load your busiest page with the Network tab open and note the slowest requests. In Supabase, Advisors → Performance Advisor flags missing indexes.
    Passes if
    Key pages load in about a second, and no query on a growing table runs without an index.
    Why it matters

    Missing indexes, queries issued inside a loop, whole tables fetched and then filtered in memory. All of it is fine with fifty rows and none of it is fine with fifty thousand.

  4. How to check
    Open your host’s list of previous deployments and check that each one maps to a commit, and that you could put the previous one back live.
    Passes if
    Deploys come from git, not a laptop, and you know how to roll back in under five minutes.
    Why it matters

    Deploys go out from a laptop, there is no record of what shipped, and the only way to undo a release is to write the old behavior again by hand under pressure.

Data

  1. How to check
    Find where your database backups live and whether your plan includes them, then ask when one was last restored — even into a scratch project.
    Passes if
    Automatic backups exist, and one has been restored at least once.
    Why it matters

    Running on defaults with no export schedule, or with backups nobody has ever restored from. A backup that has not been restored is an assumption, not a recovery plan.

  2. How to check
    Compare the database URL set for preview or staging deployments with the one set for production.
    Passes if
    They are different databases; previews never touch real customer data.
    Why it matters

    One connection string across every environment. Preview deployments mutate real customer data, and a migration tested on a branch runs against production. There is also nowhere safe to rehearse a restore.

  3. How to check
    Look for a migrations folder in your repository (for Supabase, supabase/migrations) and check that its newest file matches the last change you made to the database.
    Passes if
    Every schema change is a migration file in git, and a fresh database can be built from them alone.
    Why it matters

    Columns added in a dashboard, no migration files, no history. Environments drift apart and nobody can recreate the database from scratch — including whoever has to recover it.

Mobile

  1. How to check
    List what the app does that your website cannot: push notifications, offline use, the camera, native navigation. Read it against Apple’s App Review Guideline 4.2.
    Passes if
    The app does real things a browser cannot. It is not a web view of your site.
    Why it matters

    A web view with nothing a browser could not do. Resubmitting the same build with a better description does not change the outcome, and each attempt costs a review cycle.

  2. How to check
    Find the Android target SDK in your project (targetSdkVersion in android/app/build.gradle, or your Expo config) and compare it with the minimum Google Play currently requires.
    Passes if
    The target SDK meets Google Play’s current minimum.
    Why it matters

    Google raises the target API floor every year and refuses new builds below it before review even begins. The upgrade then surfaces layout and orientation changes the app never handled.

  3. How to check
    List every SDK in the app that collects data — analytics, crash reporting, ads, sign-in — and compare the list with your App Store privacy answers and your Play data safety form.
    Passes if
    Every data type the app sends is declared, and the iOS build includes a privacy manifest.
    Why it matters

    The data safety form declares no collection while the app ships analytics and account data. That mismatch is itself a policy violation, independent of the collection it fails to declare.

  4. How to check
    Install a release build on a real phone (TestFlight, or a Play internal testing track), send yourself a push notification, and tap a link to your domain from another app.
    Passes if
    The notification arrives and the link opens the app, not the browser.
    Why it matters

    Certificates, entitlements and associated domains were never configured for a release build, so notifications silently fail and links open the browser instead of the app.

Ticked of 20 Send us your results

02What next

What your ticks mean.

  • All twenty ticked

    Launch. Keep the error tracker and the backups running, and run the list again after any large change.

  • A few unticked

    Fix the security and payments ones before you take money. The rest can follow in your first weeks.

  • Several you couldn’t check

    That is normal — some need you to read code you did not write. It is exactly what the audit is for.

Rather have it checked for you? How the audit works

The reasoning behind the checks, at length: From Lovable demo to production: a checklist

Free review

Send us your results.

We’ll reply within one business day with the two or three things we would fix first. Free, written, and no call required.

  • Your ticks are sent with the form
  • Read by the engineer who does the audits
  • No mailing list — we only reply to this
Built with

Optional. Your ticks are sent with this, so you don’t need to list them.

When do you launch?

Rather we checked it for you?

The audit runs all twenty against your code with read-only access, plus the problems specific to your app, and ranks every finding with a fix estimate. Two business days, $349.

Prefer to write? Send your requirements

What do you need?

What it should do, who will use it, the must-haves, and any links. A few sentences is plenty.

Budget, if you have one in mind
When would you like to start?