Sample report

Audit report: a booking app built with AI

This is a sample. The app, the company and every number in this report are fictional. The findings are the kind I often see in apps built quickly with AI tools such as Lovable, Bolt or Cursor. Real reports are shared only with the client.

Contents

  1. Summary
  2. What already works well
  3. Findings
  4. Fix plan
  5. Quick wins
  6. Scope and method

Appendix: How your system works

1. Summary

The app works and customers use it every day, but it is not yet safe to grow. Two problems need fixing this week: customer data can be read by anyone who knows where to look, and a key that bypasses every access rule is published in the website's code. Neither needs a rewrite. The first two take about two days to fix; everything in this report, apart from one gradual clean-up, about 14 days.

Top five risks for the business

  1. Anyone can download your customer list (S1). Names, emails, phone numbers and booking history of 1,800 people. Under the GDPR this is a personal data breach risk.
  2. A master key is public (S2). Whoever finds it can change or delete any data in the database.
  3. Bookings can be confirmed without paying (S3). Lost revenue, and studios stop trusting the numbers.
  4. Classes get overbooked (A1). 23 double bookings in the last 30 days, each one an unhappy customer and a refund.
  5. A lost database means a lost business (R1). No one has ever restored a backup, and there is no copy outside one account.

Short answers

Your questionShort answer
Will the code, including the AI-generated parts, hold up?Keep it and fix it. Fixing everything in this report takes about 14 days; rebuilding the app would take about 60 (A1, A2).
How safe are your data and access?Not safe yet: two critical issues expose customer data (S1, S2). Both take about two days to fix.
What will slow down or break as you grow?It holds with room to spare. On a test copy of your system, at twice your busiest time (80 virtual users at once), 95% of requests were answered within 0.6 seconds and none failed. At 100, the agreed limit, the studio schedule was the first page to slow down (D1), and 6 classes on the copy were overbooked during the test (A1). At ten times today's bookings, both would be daily problems. The test copy may be smaller or configured differently than the live system, so the numbers are indicative.
Are you overpaying for hosting and services?No. Running costs, about €70 a month, are reasonable for the current traffic.
Where do you stand on GDPR and accessibility (EAA)?The privacy policy doesn't name your processors or say how long data is kept (G1), and the booking form is hard to use without a mouse (G2). Together with S1, these are the gaps to close first. This is a technical view, not legal advice.
Can you release safely?Not yet. Every push to the main branch goes straight to production, with no tests and no staging in between (I1, M1). Rolling back the code takes a minute in Vercel, but database changes are made by hand and can't be rolled back. About 40 releases in the last three months; 3 had to be fixed or rolled back.
How is development run?One developer works directly on the main branch, partly through Lovable: about 9 in 10 changes go in without a pull request or review, and none come with tests (M1). Tasks live in a chat. That works for one person, but nobody else could take over without help today; the appendix to this report is a first step.

Findings by area

AreaMost severeFindings
SecurityCritical2 critical, 1 high, 1 medium, 1 low
Architecture and codeHigh1 high, 1 medium
ReliabilityHigh2 high
DatabaseMedium1 medium
Infrastructure and costsMedium1 medium; running costs are fine
PerformanceMedium1 medium; the load test on a test copy held with room to spare
MaintainabilityMedium1 medium
Data protection and accessibilityMedium2 medium

2. What already works well

  • Payments go through Stripe Checkout, so card details never touch the app.
  • Sign-up and login use Supabase Auth with email confirmation instead of a home-made system.
  • TypeScript runs in strict mode, and most of the code is readable and consistently formatted.
  • Running costs, about €70 a month, are reasonable for the current traffic.
  • The booking pages fit a phone screen without sideways scrolling, which matters because most bookings happen on phones.

3. Findings

Every finding has a severity, what it means for the business, a recommended fix and an estimate.

  • CriticalActive risk to data or money. Fix now.
  • HighLikely to cause real damage. Fix within weeks.
  • MediumSlows you down or adds risk over time. Plan within one to three months.
  • LowWorth fixing when convenient.

Security

S1 · SecurityCritical

Customer data can be read without logging in

Found
Row-level security is turned off for the bookings and profiles tables. The public API key, which is meant to be in the website's code, therefore gives read access to every customer's name, email, phone number and booking history. Checked, with your permission, from a logged-out session.
Impact
A personal data breach risk for about 1,800 people. If the data has already been accessed, the GDPR may require you to notify the data protection authority within 72 hours.
Fix
Turn on row-level security for every table; add policies so customers see only their own bookings and studios only theirs; add an automated test that tries to read data while logged out. Review the API logs for unusual reads and decide with your lawyer whether a notification is needed.
Effort
1.5 days
S2 · SecurityCritical

The database master key is published in the website's code

Found
The admin page uses the Supabase service_role key, which bypasses all access rules. Because it is stored in a VITE_ environment variable, it is bundled into the JavaScript that every visitor downloads.
Impact
Anyone who opens the browser's developer tools can read, change or delete all data.
Fix
Rotate the key today. Move the three admin actions to a server-side function that checks the user's role.
Effort
0.5 days
S3 · SecurityHigh

A booking is marked as paid by the browser, not by Stripe

Found
The booking is confirmed when the customer lands on the payment success page. The Stripe webhook exists, but it does not verify Stripe's signature and is not used to confirm payments.
Impact
Anyone who opens the success page address directly gets a confirmed booking without paying.
Fix
Confirm bookings only from the verified checkout.session.completed webhook, make it safe to receive twice, and reconcile the last three months against Stripe.
Effort
1.5 days
S4 · SecurityMedium

Outdated dependencies with known vulnerabilities

Found
31 packages are out of date; two of them have published high-severity security advisories.
Impact
Known holes are the first thing automated attacks try.
Fix
Update the two vulnerable packages now, the rest in small batches; turn on automatic update pull requests.
Effort
0.5 days
S5 · SecurityLow

Debug messages print customer emails in the browser console

Found
Leftover debug logging prints the logged-in customer's profile, including their email, on every page.
Impact
Small on its own, but personal data ends up in screenshots and support recordings.
Fix
Remove the debug logging and add a lint rule that blocks it in production builds.
Effort
2 hours

Architecture and code

A1 · ArchitectureHigh

Class capacity is checked in the browser, so classes get overbooked

Found
The app counts free spots in the browser and then saves the booking in a separate step. When two people book the last spot at the same moment, both succeed. The database shows 23 double bookings in the last 30 days.
Impact
Unhappy customers, refunds and extra work for studios; it gets worse as traffic grows.
Fix
Move the capacity check and the booking into a single database transaction, so the last spot can only be taken once.
Effort
2 days
A2 · CodeMedium

The same logic exists in several slightly different copies

Found
There are three versions of the booking form, and the class price is calculated in four places with small differences, a common result of generating code screen by screen.
Impact
Every change has to be made in several places; prices can already differ between the app and emails.
Fix
One shared booking form and one price function, merged step by step during regular maintenance. No rewrite.
Effort
Ongoing, as part of maintenance

Reliability

R1 · ReliabilityHigh

No one has ever restored a backup

Found
The provider takes database snapshots, but no restore has ever been tried, there is no copy outside the provider account, and uploaded files are not backed up at all.
Impact
An accidental deletion, a bad migration or a locked account could lose all bookings and customer data.
Fix
A daily encrypted backup of the database and files to a second provider, a written restore procedure and a restore drill every three months.
Effort
1 day
R2 · ReliabilityHigh

Errors are discovered by customers, not by you

Found
There is no error tracking and no uptime check. The last outage, a failed deployment, was reported by a studio owner two hours later.
Impact
Problems last longer than they need to, and studios lose bookings while nobody knows.
Fix
Error tracking for the app and server functions, an uptime check on the booking page, and alerts by email and phone.
Effort
0.5 days

Database

D1 · DatabaseMedium

The studio schedule is slow because of missing indexes

Found
The schedule query reads the whole bookings table every time; the slowest 5% of requests take 1.9 seconds, and the time grows with every new booking. In the load test on a test copy, it was the first page to slow down once the copy went past 80 virtual users.
Impact
The busiest page gets slower each month, and the database plan will need upgrading sooner than necessary.
Fix
Two indexes, on studio and start time, checked against the real query plans.
Effort
0.5 days

Infrastructure and costs

I1 · InfrastructureMedium

Every change goes straight to production

Found
There is no staging environment. Code is deployed on every push, and database changes are made by hand in the dashboard, so the repository does not describe the real database.
Impact
Each change is tested on real customers, and the database cannot be rebuilt from the code.
Fix
A staging copy with test data (the test copy made for the load test is a good start), database changes as migrations in the repository, and deployment to production only after staging passes.
Effort
1 day

Performance

P1 · PerformanceMedium

The booking page is heavy on phones

Found
The booking page loads 1.4 MB of JavaScript, including the admin screens. On a mid-range phone the main content appears after 4.2 seconds (Google's target is 2.5).
Impact
Slower pages mean fewer completed bookings and weaker search rankings.
Fix
Load the admin area separately, compress images and drop two unused libraries.
Effort
1 day

Maintainability

M1 · MaintainabilityMedium

No automated tests for booking and payment

Found
There are no automated tests. Changes are checked by clicking through the app by hand, when there is time.
Impact
Each new feature can silently break booking or payment, the two flows the business depends on.
Fix
End-to-end tests for sign-up, booking, payment and cancellation, run automatically before every deployment.
Effort
2 days

Data protection and accessibility

G1 · Data protectionMedium

The privacy policy does not match what the app does

Found
The policy does not name Supabase, Stripe or Vercel as processors, and there is no rule for deleting old bookings and closed accounts.
Impact
A gap the data protection authority would look at first, especially together with S1.
Fix
A list of processors and retention periods for your lawyer to review, and an automatic clean-up of data past its retention period.
Effort
0.5 days, plus your lawyer's review
G2 · AccessibilityMedium

The booking form is hard to use without a mouse

Found
Form fields have no labels for screen readers, the date picker cannot be used with a keyboard, and button text has a contrast ratio of 2.9:1 (the minimum is 4.5:1).
Impact
Some customers cannot book at all. If the European Accessibility Act applies to you, these issues block compliance.
Fix
Labels, a keyboard-friendly date picker and adjusted colours, then a check against WCAG 2.1 AA.
Effort
1 day

4. Fix plan

Ordered by risk, not by convenience. Estimates are for the work itself; if you want me to do the work, a fixed quote follows our call.

WhenWhatDays
This weekS2 rotate the key and move admin actions to the server; S1 access rules and log review; S5 debug logging2.25
Next 3 weeksS3 payments confirmed by Stripe; A1 overbooking; R1 backups and restore drill; R2 error tracking and alerts5
Next 1–2 monthsI1 staging and migrations; M1 end-to-end tests; D1 indexes; S4 dependencies; P1 page weight; G1 privacy; G2 accessibility6.5
OngoingA2 merge duplicated code during regular maintenance—
Total15 findings13.75

5. Quick wins

Five changes of half a day or less that remove the most risk per hour, about two days in total:

  • Rotate the leaked master key (S2).
  • Remove debug logging of customer data (S5).
  • Turn on error tracking and an uptime check (R2).
  • Add the two missing database indexes (D1).
  • Update the two packages with known vulnerabilities (S4).

6. Scope and method

What I reviewed

  • The code repository: all server functions, and the booking, payment and account flows line by line.
  • The database: schema, access rules, indexes, slow queries and backups.
  • Hosting and deployment settings, environment variables and logs.
  • Stripe settings: checkout, webhooks and how payments reach the app.
  • The booking page with Lighthouse and a manual accessibility check.
  • A load test on a test copy of your system: the main pages, the class schedule, login with test accounts and booking up to the payment page, up to 100 virtual users. Your developer set up the copy for the audit, with its own database, test data and Stripe in test mode.
  • The CI/CD pipeline and the release cycle: the GitHub Actions workflow, the rules on the main branch and 40 production deploys over the last three months.
  • How development is run: the Git history of the last 12 months (counts only, no names) and a 30-minute interview with your developer.

Not in scope

  • Load testing of the live system, and a full penetration test.
  • Legal advice: GDPR and accessibility findings are technical and need your lawyer's review.

After the report

A 60-minute call to walk through the findings and answer questions. The plan and the appendix are yours to use and share with any developer; if you want me to do the fixes, you get a fixed quote.

Appendix: How your system works

An overview for anyone who works on the system: a new developer, an agency or your own team. It describes the system as it was during the audit and contains no passwords, keys or personal data. Problems are in section 3; here they are only referred to by ID.

This sample shows three of its seven parts. The others are how data flows, third-party services, backups and monitoring, and how to run the app locally.

Components

ComponentWhat it doesBuilt withRuns on
Web appClass schedule, booking, payment and customer accounts; the studio admin pagesReact and TypeScriptVercel
Database, sign-in and file storageCustomers, studios, classes and bookings; uploaded photosSupabase (Postgres, Auth, Storage)Supabase
Server functionsThe Stripe webhook and booking emailsSupabase Edge FunctionsSupabase

Environments

EnvironmentWhat it is forDatabase and keysPayments
ProductionYour studios and customersProduction database and keysLive
Test copyThe load test in this audit; not used for releasesIts own database with test data, its own keysTest mode
StagingNone yet: changes go straight to production (see I1)——

How code reaches production

  1. Changes are made in Lovable or in the developer's editor and pushed straight to the main branch on GitHub. The branch has no protection rules.
  2. A GitHub Actions workflow runs the linter and the type check, but nothing waits for the result.
  3. Vercel deploys every push to the main branch to production. There is no staging step and no automated tests before a deploy (see I1, M1).
  4. Database changes are made by hand in the Supabase dashboard, not as migrations in the repository (see I1).
  5. To roll back the code: Vercel → Deployments → promote the previous deployment. Database changes have no rollback.

Want a report like this for your system?

A report like this comes with the full-coverage audit, from €1,900 excl. VAT (1–2 weeks). Not sure about the scope? Start with the one-day critical audit (€600): if you go on to the full-coverage audit after it, it costs less, because part of the system is already reviewed. Both start with a short message on WhatsApp or by email.

Sample report · fictional data · October 2026