AI wrote you 10,000 lines of code in two days. Can you trust one of them?

Generated code can work and still be unsafe to ship. Here is a practical review path for authorization, concurrency, retries, edge cases and security.

A cobalt case-file tab beside the words AI code, production review, and 10,000 lines.
On this page
  1. Functional is not the same as production-ready
  2. BOLA / IDOR: changing an ID must not change whose data you can see
  3. Race conditions: two valid requests can still produce one invalid result
  4. Idempotency: retries should not repeat a real-world effect
  5. Edge cases and technical debt are part of the feature
  6. Security review: inspect authority, inputs and side effects
  7. A checklist before shipping AI-generated code
  8. The practical limit
  9. References

The number in this headline is an illustrative scenario, not a personal result or a measured claim. The question is still useful: if an AI assistant generates a large change quickly, what evidence should make you trust it?

The short answer is not the number of passing prompts, files, or lines. Trust comes from understanding the change, testing the important boundaries, and observing the system under realistic conditions. Generated code needs the same engineering review as code written by a person.

Functional is not the same as production-ready

“It works” usually means one expected path behaved correctly once. A production feature must also behave correctly for the wrong user, a repeated request, a concurrent request, missing data, a slow dependency, and a partial failure.

An AI-generated endpoint can return the expected response and still expose another customer’s record. A checkout flow can succeed in a demo and charge twice when a network retry repeats the request. A booking screen can show one remaining place while two people claim it at the same time.

Production readiness is a property of the whole path: interface, API, authorization, data constraints, retries, logs, deployment and recovery. Passing a happy-path test is useful evidence, but it is not evidence for cases the test never tried.

BOLA / IDOR: changing an ID must not change whose data you can see

Broken Object Level Authorization (BOLA), often discussed as IDOR, happens when a request identifies an object but the server does not verify that the current user may act on that object. An invoice URL such as /api/invoices/105 is not protected just because the user is signed in. If changing 105 to 106 returns somebody else’s invoice, the authorization boundary is missing.

The safe check belongs on the server and uses the authenticated identity together with the requested object. For example, the database query can require both the invoice ID and its owner or permitted organization. A hidden button, unpredictable ID, or client-side filter is not an access-control rule.

Review every object identifier that can arrive from a URL, form, background job or AI tool. Ask: whose identity is used, what relationship grants access, and what happens when the object exists but belongs to another person? OWASP describes this class as API1:2023 and recommends object-level authorization checks for every function that accesses data using an ID.

Race conditions: two valid requests can still produce one invalid result

Imagine one appointment slot remains. Two requests read remaining = 1; both decide the slot is available; both create a booking. Each request was valid in isolation, but the final state is impossible.

The protection must be atomic at the place where shared state changes. Depending on the data model, that can mean a conditional update, a database constraint, a transaction with appropriate isolation, or a lock. Then test two requests at the same time and verify that only one succeeds. A sequential test cannot demonstrate that the race is closed.

The same pattern appears in stock counts, seat reservations, coupons, credits and grade submissions. Ask what invariant must stay true, then enforce it where concurrent requests meet—not only in the interface.

Idempotency: retries should not repeat a real-world effect

Retries are normal. A browser may resend after a timeout, a payment provider may retry a webhook, and a queue may deliver a message again. If every delivery creates a new charge, order or email, the system has treated a retry as a new intention.

Give each operation a stable idempotency key or event identifier, store that identifier under a uniqueness rule, and apply the side effect only once. Keep recording the result so a retry can receive the original outcome. The key must be scoped to the user or operation and retained for an intentional period.

Stripe’s documentation is one concrete example of an API using idempotency keys. The general principle also applies to your own webhook and job handlers; the details depend on what must happen exactly once and what can safely be repeated.

Edge cases and technical debt are part of the feature

Generated code often mirrors the prompt’s visible path. It may not include what happens when a record is deleted during an operation, a list is empty, a value is stale, a request times out after the server committed, or two updates arrive out of order.

Technical debt is not proof that a feature is broken. It is future cost created by a shortcut or an unresolved constraint. Record the tradeoff, its impact, and a condition that would make it worth addressing. Do not hide it under a vague “TODO” or assume an AI can infer it later.

For each change, write down the invariant, the failure behavior, and the recovery path. Then add tests for the highest-risk cases: wrong owner, duplicate request, simultaneous update, missing record, invalid state transition and dependency failure.

Security review: inspect authority, inputs and side effects

Security problems are often ordinary logic errors at a boundary. Check that the server derives identity from a trusted session, validates every input, limits what a user can read or change, and does not expose secrets or internal errors. Check role changes and administrative operations separately from read access.

For AI features, also review which tools the model can call, which user’s permissions those tools use, what data enters the prompt, whether proposed actions require confirmation, and what gets logged or retained. A model instruction is not an authorization check. The application must enforce access in the tool implementation.

Use dependency and static-analysis reports as leads, not as a substitute for understanding the code path. A vulnerability scanner can identify known packages; a reviewer still needs to determine whether the affected code is reachable and how it is used.

A checklist before shipping AI-generated code

  • Read the full diff and explain each changed path without relying on the prompt.
  • Identify the data and permission boundary for every endpoint and tool.
  • Test an unauthorized object ID, not just an authorized example.
  • Exercise duplicate requests, concurrent updates and partial failures.
  • Verify database constraints and transaction behavior for important invariants.
  • Check validation, empty states, stale state, timeouts and recovery behavior.
  • Review secrets, logs, file access, dependency alerts and external calls.
  • Run the project’s type checks, tests and production build; inspect what those checks do not cover.
  • Keep a short list of accepted limitations and the evidence that would change the decision.

The practical limit

No checklist proves that a system is secure or bug-free. Tests cover chosen scenarios; reviews can miss assumptions; production behavior depends on data, traffic and configuration. The aim is to replace “the AI said it was done” with evidence that matches the risk of the change.

Generated code can be a useful accelerator. The engineering work is deciding what it is allowed to do, checking the boundaries, and owning what happens after it ships.

References

Working on a product or workflow like this?

Ask about AI integration