
A saved message on screen does not prove that a record was actually saved. An app can look successful even when only the screen changed or the data stayed inside the current browser.
To make that difference visible, the test used one disposable local app with synthetic records. A browser-storage demo and the core record app appeared in the same interface, while the browser, a local API, and SQLite—the file-based datastore—were checked separately. This is not a comparison of AI app builders or a verdict on AI-built apps in general.
The test centered on three questions:
- Where was the record stored?
- Who confirmed the write?
- Who could access the data?
In this article
1. Where was the record stored?
The browser-storage demo saved one record five different ways: runtime memory, sessionStorage, localStorage, IndexedDB, and a deliberately discarded write. After a hard reload, the observed results were:
| Storage method | Observed after hard reload |
|---|---|
Runtime memory |
Empty |
sessionStorage |
Record returned |
localStorage |
Record returned |
IndexedDB |
Record returned |
Deliberately discarded write |
Empty |
According to the official documentation, sessionStorage lasts for the page's tab session, while localStorage can persist across browser sessions for the same origin. IndexedDB is also client-side structured storage. Those are documented properties, not additional results from this hard-reload check. Seeing a record after a refresh does not prove that it reached a server or could be recovered on another device. Browser storage can also be deleted or evicted (MDN: storage quotas and eviction criteria).
This browser check stopped at a hard reload. A full browser-process restart and a UI test in an independently proven clean browser profile were not performed. These two UI gaps sit outside the verifier's 25 machine-counted checkpoints described below. They are neither passes nor failures.
2. Who confirmed the write?
In the core app, synthetic user A created three records, updated one, and deleted another. The app's response was not treated as sufficient evidence. An independent verifier program read the SQLite file directly and compared the stored records with a frozen expected result. The local API route used for authoritative reads returned Cache-Control: no-store and identified its source as sqlite_authoritative, but those self-reported details were not treated as proof on their own. The API result was checked against the independent SQLite inspection. This does not prove that every possible cache layer was absent.
There were three attempts. In the first, the restricted environment blocked the local port, leaving 2 PASS, 20 FAIL, 2 INVALID, and 1 NOT RUN. In the second, the server process ended before the first request, leaving 3 PASS, 21 FAIL, 0 INVALID, and 1 NOT RUN. Neither attempt was used to judge the app. Those environment and process failures remain in the record. Only the third attempt, using the same frozen protocol in a normal local environment, was used as the observation of the app.
The valid machine-checked run produced 24 PASS, 0 FAIL, 0 INVALID, and 1 NOT RUN. This is not a feature-completeness score. It is the total across 25 predefined checkpoints, including create, update, delete, direct datastore reads, offline behavior, and access denials. The one machine-counted NOT RUN was local code-artifact replacement.
Here, INVALID means that the evidence was insufficient or ambiguous, the required boundary was not actually crossed, the inputs changed, or the state was contaminated. NOT RUN means that an optional checkpoint was deliberately skipped or a declared safety, account, or payment boundary prevented it. Neither status is the same as an app behavior that was validly tested and failed.
The verifier also checked that authoritative reads failed while the server was unavailable and recovered after it returned. This prevented an offline response from being mistaken for a server-confirmed success; it did not test every possible cache failure. In a separate local server-restart check, the same SQLite records remained after the server started again as a different process.
Replacing the local code artifact was not performed. Hosted deployment was also outside the executed 25-checkpoint local verifier and was not tested. A local server restart is not evidence of a hosted redeploy. Cloud durability, backup restoration, and long-term retention remain outside this experiment.
The direct monetary cost of this local run was USD 0.00. That figure excludes existing subscriptions, labor, electricity, hardware, and opportunity cost. Total end-to-end elapsed time was not captured.
3. Who could access the data?
Persistence is not enough if another user can retrieve the record. Synthetic user B first confirmed that it could create a record through its own allowed route. B then tried to read, update, and delete records created by A, using those records' known IDs. Those requests were denied with 404 responses—meaning the route reported that the record was not found—and A's SQLite state remained unchanged. A read request sent without the test-only X-Synthetic-Identity header returned 401, meaning authentication was required. The reverse attempt, A reading B's record, also returned 404.
This means that user separation worked only on the routes tested in this local setup. Fixed values in the X-Synthetic-Identity test header stood in for synthetic users. Omitting that header was not a real logout test, and this setup does not demonstrate production authentication or overall product security. Both Supabase's Row Level Security guide and Firebase's Security Rules documentation treat logging in and data permissions as separate questions.
Duplicate handling was another separate result. A's create request was replayed exactly once using the same operation ID, and only one record remained. That observation covers one controlled retry. It does not prove that every duplicate or concurrent request would be safe. Persistence, retry handling, and user isolation are three different questions; success in one cannot substitute for evidence in the others.
What to ask before trusting a saved state
For a non-developer building with AI, these three questions are more useful than a success message alone:
- Where was it stored? Ask whether the record stayed on screen or in this browser, or reached a server-side datastore.
- Who confirmed the write? Ask for an independent datastore read, not just the app's own success message. Also ask which boundary was actually crossed: reload, browser restart, server restart, code replacement, or deployment.
- Who could access it? Test both an allowed synthetic identity and one that must be denied, using synthetic data. Selected test routes and fixed headers are not production authentication or a security audit.
In this disposable local app, the limited create, read, update, and delete flow, one same-operation retry, selected user-isolation routes, the offline check, and one local server restart matched the frozen expected result. No broader claim follows from this test. Stronger evidence than a “saved” message on screen is a boundary-by-boundary record of where the data remained, who confirmed it, and who could not access it.
AI was used to assist with research and drafting. The author independently verified and edited the final article.
답글 남기기