I built an application with AI. Real users, real data, in daily use, replacing a spreadsheet that had run out of road. I am a business analyst. I have never been a software engineer, and I did not become one by prompting well.
That was fine while it was a pilot. The awkward question arrived when the business wanted to roll it out wider: is this thing safe to depend on? I could not answer that, and I knew I could not. So we commissioned an independent engineering review of the code, and before it started I wrote down what I expected them to find.
They found those. Then they kept going.
The bit I got right.
The review opened with the finding I care most about. The data model was clean. The core workflow held together. The stack was mainstream and boring, which in software is a compliment. Their recommendation was to build on the prototype rather than start again, because the hardest part, working out what the business needed and modelling it correctly, had already been done.
That is the business analyst's job, and it turns out it travels into code. Twenty years of asking "what are you actually trying to do?" produced a domain model an engineer was happy to inherit. The AI did the typing. The judgement about what to type was mine, and it held up under someone else's scrutiny.
Whether a BA can build was settled months earlier, by the demo. What a demo leaves unanswered is the subject of the rest of this note.
What the reviewers saw.
Everything below is anonymised, and none of it is exotic. The reviewers described the pattern as typical of an AI-assisted prototype. That is the useful part: if the gaps are predictable, they can be planned for.
Where the rules live. There was a backend, in the sense that a hosted service handled sign-in and stored the data. Two AI assistants had walked me through setting it up, step by step, and the steps were right. What there was not was a server layer of ours between the browser and that data. Every rule in the app ran in the user's browser: import, validation, working out what had changed, access control, export. A change the app marked as "verified" had been verified by the same browser the user was sitting in front of. Once signed in, nothing stood between a user and the database except rules I had not written.
Who is allowed in, and what they can do. Getting in was controlled. Sign-in was restricted to the company email domain and to accounts I had registered myself. Once in, every user was an editor with read and write access to everything. That was a decision, and I want to be precise about it, because it is the one most vibe builders miss and I did not miss it. The app started with a view-only role. With only a handful of users ever likely to touch it, view-only added friction without adding value, so I dropped it and kept things simple. The reviewers had no quarrel with the intent. Their objection was where the decision lived. The editor upgrade was applied by code running in the user's browser, my own email address was hardcoded as administrator in both the app and the database rules, and the database itself let any signed-in user read every record. Simple was fine for a handful of people who all knew each other. Roll it out to a department and a choice made for convenience becomes the access model, enforced nowhere a user could not reach.
Everyone an editor was a deliberate choice for a handful of users. The review's objection was where the choice lived, and how many users it would survive.
Who owns the box. The production environment and its data sat in a personal cloud account. Mine. If I left, or was off sick for a month, the business's tool went with me. I had flagged this as my number one concern before the review started. The reviewers agreed and rated it critical.
Whether anyone else could change it. The whole application lived in one file of roughly 3,200 lines: interface, sign-in, roles, data access and export, all in together. No automated tests. No build pipeline. About 70 places where the type checking had been switched off to make something compile. My own README said the file needed splitting up, which is easy to write and, when you are the only person who can safely touch the file, hard to act on.
What came along for the ride. Two dependencies were doing nothing. One of them existed to power a cosmetic feature, generating a little icon for the browser tab, and to do that it shipped an AI API key into the browser bundle where anyone could read it. A feature nobody asked for, carrying a secret nobody was watching.
What nobody wrote down. No backup or restore plan beyond a single snapshot. No monitoring. Web analytics quietly running on an internal staff tool, which is a data-protection question nobody had thought to ask.
One caveat, and it matters. This was a code review. No penetration test, no load test, no access to the live console. Some findings were inferred from the code and from my own notes. It gave us a route to production. Certification would be a separate exercise, with a separate invoice.
What is safe to vibe on your own.
Not every app needs the treatment above. The risks the reviewers found only bite when certain things are true: other people use it, it holds data that is not yours, it writes to something the business relies on, and it has to survive you being away. Take those away and a non-engineer can build with a clear conscience. Four questions do the sorting.
Who else uses it? If the answer is nobody, there is no permissions model to get wrong. Personal dashboards, calculators, converters, trackers and one-off analysis scripts are the safest things anyone can vibe, because the blast radius is you.
Whose data is in it? Your own, or made-up data, is fine. Other people's names, anything about customers or staff, anything a regulator has a view on, moves the app straight into review territory, because the mistakes stop being yours to absorb.
What does it write to? A tool that only reads, over an exported spreadsheet or a copy of a report, can be wrong without being dangerous; you check the chart and run it again. Anything that writes back to a system the business relies on needs someone who can prove the write is correct.
What happens when it breaks, or you leave? A throwaway prototype built to show stakeholders what a workflow could look like is meant to die. So is a first-draft generator whose output a human reads before it goes anywhere. Static content, a landing page or a microsite with no login and no form of its own, has nothing to breach beyond the page. None of these need a recovery plan, because nothing is lost.
Answer "me, mine, nothing that matters, I run it again" and vibe away. Each answer that drifts (a second user, a colleague's name, a write to a live system, a job that runs while you sleep) is a reason to bring in a reviewer before anyone depends on it. My app drifted on all four, which is exactly why it got reviewed.
The scaffolding engineers stopped noticing.
Two ideas ran underneath the whole review, and non-engineers rarely meet either of them. Neither is difficult. They are invisible until someone points at them, and then you cannot unsee them.
The first is the lifecycle. Every piece of software, from a bank's core system to the thing you built on Saturday, passes through the same stages whether or not anyone names them: decide what it should do, decide how it will be built, build it, test it, release it, then run it and fix it for as long as it lives. Engineers call this the software development lifecycle, SDLC if you want the badge, and it exists because every stage you skip comes back later as an incident. Vibe coding did something remarkable to exactly one of those stages. Building went from weeks to an afternoon. The other five cost what they always cost. The trap in a fast build is that it tempts you to jump from "decide what" straight to "show people" and treat the gap between them as done. As a business analyst I had spent twenty years inside the first stage. What I had never owned were the stages after "build", and the review was, in effect, an itemised list of them.
The second is the pipeline, which engineers shorten to CI/CD. Continuous integration means that every time the code changes, a machine checks it automatically: does it still build, do the tests still pass, did this change break something three files away. Continuous delivery means the checked code travels to where it runs by the same automated route every time, rather than someone copying files across from a laptop. A spell-checker for behaviour, plus a delivery van that drives the same route every day.
Why should someone who is not an engineer care? Because the AI writes code quickly, and every change it makes can quietly undo one it made last week. My app had no pipeline. The test was me clicking around, and the release was whatever happened to be on my machine. A small tweak on a Friday could break Monday morning, and only I could put it back. A pipeline is how a business stops depending on the builder's memory. The tests remember what the app is supposed to do. The route remembers how it reaches production. Neither needs me in the building.
The cost of this has collapsed along with everything else. The same assistant that built the app will set up version control (a complete undo history, every change recorded with a note on why), write a first set of tests, and wire a pipeline that runs them on every change and deploys only when they pass. An hour, once, if you ask before the first feature. I asked after the fiftieth, which is to say the reviewers asked for me. It is now the first item on my own list.
How far can we close the gap?
Here is the ledger. Of the ten risks logged, I had already identified about half. The hosting, the monolith, the missing tests, the tab-icon nonsense: I knew. What I could not do was fix them safely, and I could not prove the other half were not there. Knowing your code has a problem and knowing your code has no others are different skills. Only the second one lets you ship.
So can self-improvement get a non-engineer to safely shippable? Further than the sceptics think, provided the effort goes in before the first prompt rather than after the first incident. The gaps above were predictable, and predictable gaps can be specified out. Where does the logic run. Who can do what, enforced where. Who owns the environment. How many users does this design assume. How is the code split. What is the test for each change. How does a change get from my laptop to live. A viber who writes that down up front produces a very different prototype from one who opens a blank chat and describes a screen. Two assistants walked me through authentication step by step, and both were right about the steps. Neither asked where the access rules would be enforced or how many users the design assumed, because I had not asked either. An assistant will build the decision you give it. Checking whether that decision holds at scale is your job.
What no amount of reading replaces is the person who inspects the result and signs it. The aim is to change the engineer's job from rescue to sign-off. A review that says "build the missing backend and rework the front end around it" is a rescue. A review that says "two rules to tighten, ship it" is a sign-off. Same reviewer, same day rate, a fraction of the hours.
If you have an internal engineering team, ask them to review before the pilot goes wide, and hand them the brief above so they know what they are marking. If you have no engineers, an external agency can review a small tool in days. Either way, give them the code, your notes and permission to be blunt. The blunt version is the one you are paying for.
The up-front list exists as a one-page best practice sheet, written for non-engineers who build with AI. The four-question gate test above, what to write down before the first prompt, how to structure the build so it can be reviewed, how to get changes to live without hand-carrying them, and what to hand the reviewer. If you would like it, leave your email and I’ll take you to it.