Watson Standard1
Sample report · a full written read Prepared by Bryce Watson

← Back to the main page

Sample report: a full read of a Lovable and Supabase app

This is a full written read of a public, open-source app, shared to show how I read code and what I look for. It isn't one of my offers as it stands: if you're about to launch, start with the $149 Launch Blocker Check. The app is a small hobby project, but the checks are the ones I run on any app about to take real users: who can change what, what can cost you money, what breaks quietly, and what you'd lose if the database went.

I've removed the app's name, author and address, and I describe security problems that someone could exploit only by type, not by how to do it. In a paid check, each blocker comes with the exact file and line, what I saw, and the first step to fix it. I read the public code only; I didn't run the app or touch the live site. That's why some answers below are conditional. The $149 check reads code only too, so it marks the same kind of finding "Needs checking" and says what would settle it; a fixed-price job or Fix the list can settle it with your dashboard access and test logins.

Prepared byBryce Watson
DeliveredSeptember 22, 2026
What I reviewedThe public code as it stood on one specific date: 2 database tables, 10 database migrations, 4 server functions, about 60 source files
Built withLovable; React, TypeScript, Vite; Supabase (database, sign-in, server functions, file storage); a paid web-scraping service
What the app doesA personal catalog: the public can browse it; only the owner is meant to change it
Access I hadThe public code only
Access I didn't haveThe Supabase dashboard, hosting, the scraping account, a test login, the live site. The $149 check doesn't use these either; a fix job can, with your read-only access. That's why several findings below are marked "Needs checking".

1 The short answer

Verdict Check one setting before relying on it.

That check takes five minutes in the Supabase dashboard. The app is meant to be owner-only for changes, and the page code looks that way, but the database rules don't actually know who the owner is. So how much this matters comes down to one setting that isn't in the code. Either way, the rules should name the owner directly, so a future settings change can't quietly open things up; that's the first fix.

Signed: Bryce Watson, Watson Standard. Code version [commit withheld], read on [date withheld]. This is my judgment on that version on that day, not a promise that nothing else is wrong.

2 What to do first

F-01 to F-12 are the 12 things I found. Click or tap any of them to jump to that finding's details under Findings.

  1. Check one dashboard setting (F-01).
  2. Tighten the database and storage rules so only the owner can change anything (F-01, F-03).
  3. Validate one kind of user-supplied value before it's saved and shown (F-02).

3 How to read this

Severity: Critical fix before real users, High before launch or in week one, Medium next few weeks, Low when you're in that code, Note no action now.

Confidence: Verified (confirmed directly), Likely (the code clearly allows it, but I didn't trigger it), Needs checking (couldn't confirm with the access I had; the finding says what would settle it). Only findings I could confirm from the code alone are Verified, because I had no test login. With test accounts in a fix job, most "Likely" items become "Verified".

4 Coverage

AreaStatusFindings
SecurityPartly checked: code and database rules read; live settings not seenF-01, F-02, F-03, F-08
Sign-in and accountsPartly checked: sign-in code read; account settings are in the dashboardF-01, F-11
Data handling and privacyChecked from code; backups not seenF-09, F-10
ReliabilityChecked from code; no logs seenF-05, F-06, F-07
DeploymentPartly checked: the builder publishes it; rollback not seenF-08, F-11
Cost risksChecked from code; plan and usage not seenF-04, F-05
Code healthCheckedF-11, F-12

5 Findings

Summary: 12 findings. How serious the first two are depends on the setting in F-01, so in this public version they're ranked "depends on setting". In a paid check, each blocker also comes with the exact file and line and the first step to fix it (see F-01).

Security findings, summarized for this public sample

#FindingSeverityConfidenceWhat the fix involves
F-01Access control. The database rules allow wider write access than the app's "owner only" design intends. How exposed the live app is depends on one dashboard setting that the code doesn't control.Depends on the setting; to confirmNeeds checkingCheck the setting today; then rewrite the table and storage rules so they name the owner, and add a test that proves no other account can write. Fix and price: Q-01
F-02Unsafe handling of a user-supplied value. One field is saved and shown on a public page without checking its format. It only matters if F-01 is open.Depends on F-01LikelyCheck the format in the database and when showing it. Fix and price: Q-02
F-03File storage limits. The public file bucket's size and type limits exist only in the browser, not on the server.Medium if F-01 is open; Low if notLikelySet the limits on the bucket itself, owner-only uploads. Fix and price: Q-01
F-04Paid-service abuse. The server functions that call a paid scraping service check that the caller is signed in, but not that it's the owner, and have no cap.Medium (High if F-01 is open)LikelyOwner-only check, a daily cap, input length limits, a spending alert. Fix and price: Q-03

These four are why the verdict hinges on one setting. The good news is that each fix is small and the app's structure makes them easy to get right.

What F-01 would look like in a paid check (details blacked out here)

SeverityDepends on [setting]
ConfidenceNeeds checking: the rules are certain from the code; the setting isn't visible without dashboard access
Where[4 migration files, 9 lines]; [2 data files, 9 lines]; [sign-in code, 2 files]
What I foundThe exact rules, quoted, and why each one is broader than "owner only"
Why it mattersWhat a stranger could do to your public pages, storage and bill, in plain words
How to check it yourselfThe dashboard page and setting name, and what "safe" looks like there. No steps that touch the live app.
Recommended fixThe rule change, plus a prompt you can paste into Lovable
EffortSmall to medium. Quote item Q-01.

Back to findings

F-05 A bulk-update feature probably runs past the server's time limit and reports the wrong numbers

Medium Likely (the time limit depends on the plan: Needs checking) · Reliability · The bulk-update server function (loop and response) and the page button that calls it

What I found. One call works through up to 20 items one after another, each needing two slow page fetches plus a pause. That adds up to at least 110 seconds before any network time, close to or past the 150 seconds Supabase typically allows. When it's cut off, the page says "failed" even though some items were updated. When it finishes, the message reads a number the function never sends, so it shows "out of undefined", and it says "complete" after the first 20 even when more are left.

Why it matters. Confusing results and wasted money: a timed-out run has already paid for its fetches.

How to check it yourself. Run it once while watching the function's logs in Supabase.

Recommended fix. Do 5 items per call, have the page repeat until done and show progress, and fix the message.

Effort. Small. Quote item Q-04.

Back to findings

F-06 Some scraped details can be silently wrong

Low Likely · Reliability, data quality · Three server functions' page-reading code

What I found. A duration is taken from the first "N min" anywhere on a fetched page, not from the labeled field. The bulk update takes the first search result whatever the edition. A price falls back to the first currency amount on the page, which may be a promotional banner.

Why it matters. Wrong values flow into the app's statistics with no sign they're guesses.

Recommended fix. Read from the labeled fields, match on year, and leave a blank rather than guess.

Effort. Small. Quote item Q-04 (same code as F-05).

Back to findings

F-07 Outside calls have no time limit, and failures are mostly invisible

Low Likely · Reliability · Four calls to outside services across three functions; one background sync in the page

What I found. No outside call sets a timeout. Errors go only to function logs; one function sends raw internal error text back to the browser, and the background sync hides every failure.

Why it matters. When something breaks, the owner finds out only by noticing missing data.

Recommended fix. 15-second timeouts, generic error messages, and a small notice in the page when the sync fails.

Effort. Small. Quote item Q-03.

Back to findings

F-08 The settings file is committed to the repository and not ignored

Low Verified (from the public repository) · Security, deployment · .env and .gitignore

What I found. The .env settings file is in the public repository. Today it holds only the project address and the key that every visitor's browser already receives, which Supabase designs to be public. I confirmed it's that public key, not the private key that bypasses all the rules, so nothing needs changing today. But the ignore file doesn't cover .env, so any real secret added later would be published with the next commit.

Why it matters. This is the finding that looks scariest and matters least. Automated scanners flag it loudly; the real question for this app was whether the database rules hold (F-01). Part of what you're paying for is knowing the difference.

Recommended fix. Ignore .env and keep the example file as a template, then confirm the builder still gets its settings.

Effort. Small. Quote item Q-05.

Back to findings

F-09 No visible backup or export of the owner's data

Medium Needs checking · Data handling · Whole project; the delete and upload code

What I found. Everything lives in one database with nothing in the code to back it up or export it. Whether the plan includes restorable backups isn't visible to me. Deleting a parent item deletes everything nested under it. Deleted items leave their images behind in storage, which keeps growing.

Why it matters. Years of data entry could be lost to one bad change or mistaken delete.

How to check it yourself. In Supabase, open Database > Backups.

Recommended fix. Confirm backups, add a one-command export to a dated file, and clean up images on delete.

Effort. Small. Quote item Q-06.

Back to findings

F-10 Some personal details are public by design

Note Verified (from the database rules) · Privacy

What I found. One public list shows prices, shops and purchase dates, plus the owner's internal account ID on every row. A third-party username is hard-coded in one function. No one else's personal data is stored.

Why it matters. Fine for a showcase, as long as it's a choice. Purchase dates are easy to overlook.

Recommended fix. None required; hide purchase dates from public reads if preferred.

Back to findings

F-11 Code health: the next change is riskier than it needs to be

Low Verified (from the repository) · Code health, deployment

What I found.

  • Owner-only buttons show for any signed-in account.
  • The only test is a placeholder that checks true equals true, and nothing runs checks on each change.
  • The project records its outside code in three different, competing ways, so what the builder installs can differ from what a developer's laptop installs.
  • The server functions pull in outside code without locking the version, so an update could change their behavior overnight.
  • Three page files are 18 to 25 KB each, mixing data, filters and layout.

Why it matters. Nothing breaks today, but every edit is harder to check, and the access rules in F-01 have no test to catch a regression.

Recommended fix. One lockfile, a small automatic check on every push (lint, tests, build), a test that a second account can't write, and owner checks in the page.

Effort. Small to medium. Quote item Q-05.

Back to findings

What's already done well

6 Fixed quote

These are the prices I put on this sample app's fixes when I wrote it; yours come from your own code. Every finding that needed work got a price. You choose which to fix. Once you approve the written scope, the price only changes if we both agree to a change in writing.

ItemWhat could go wrong, and the fixPrice
Q-01If the dashboard setting in F-01 is open, another account could change or wipe your data and fill your storage with its own files, on your bill. Fix: only you can change things, and uploads are checked on the server. (F-01, F-03)$300
Q-02If F-01 is open, someone could put harmful content on one of your public pages. Fix: that field is checked before it's saved or shown. (F-02)$100
Q-03Any signed-in account could run up your bill with the paid data service, with no cap. Fix: only you can use it, with a daily cap you set. (F-04, F-07)$250
Q-04Updating many items at once can stop halfway and report the wrong numbers, and some imported details can be quietly wrong. Fix: updates finish with the right counts, and the details are checked. (F-05, F-06)$250
Q-05Not urgent. Without it, the next change is more likely to break something without anyone noticing. Fix: a cleaner setup and tests that run on every change. (F-08, F-11)$200
Q-06One bad change or mistaken delete could erase years of entries. Fix: confirmed backups and a one-step export of everything. If the plan already had backups, this would have cost less. (F-09)$150

How it would go today: if a $149 check had named these as blockers, Fix the list would price the ones you chose as one list, with one fixed price and the time it takes. When I wrote this sample, the five fixes that matter before launch (Q-01 to Q-04 and Q-06) came to $1,050 in 5 business days. A check focuses on security, sign-in and payments, so its list would usually be shorter than this report.

Before each fix, we agree on a plain test of "done". If a fix fails that test on the exact version of the code I handed over, within 90 days of delivery, I fix it free.

The test of "done" for each fix
  • Q-01: The dashboard setting is confirmed. A second test account gets a permission error on every change and upload, through the app and directly through the database. The owner still can. The bucket rejects oversize and non-image files.
  • Q-02: The database rejects unsafe values in that field, and the page never renders one.
  • Q-03: Only the owner can call the paid functions, up to a daily cap you choose. Oversized input is rejected. Outside calls give up after 15 seconds with a generic error.
  • Q-04: A 60-item bulk update finishes from one click with a correct progress count and no timeout. Durations on 5 sample pages match the labeled field.
  • Q-05: Settings file ignored and the builder still works; one lockfile; automatic checks run on every push; a test proves a second account can't write; owner buttons hidden from others.
  • Q-06: Backups confirmed in writing; one command exports all data to a dated file; deleting an item removes its image.

The warranty doesn't cover later changes to the code, including your AI builder rewriting it, new features, or outages at Supabase, Stripe or your host. With Fix the list, you approve the list and its one price before you pay.

7 What I did and didn't do

What you'd give me on a fix job that I didn't have here: read-only dashboard access (account settings, live database rules, storage limits, backups, function logs), a screenshot of the paid service's usage page, and two test logins on a test copy. With those, F-01 and the other "Needs checking" items get a definite answer instead of a condition.

About to launch your own app? Start with the $149 Launch Blocker Check: I name every launch blocker I find in 1 business day, walk you through them on a 20-minute call and fix the one you pick if it's small.

Get the $149 check