The Theatrical Code Review: Securing Architecture When AI Writes the Logic

Architectural illustration of code resting on structured data, protected keys and an inspection gateway

A quick approval on an AI-generated pull request cannot tell you whether the change preserves your data, permissions or public contracts.

If your team uses AI to produce application code, the review process needs to account for more than whether a diff looks reasonable. A feature can compile while introducing a destructive migration, an overly broad permission or an endpoint that exposes customer records. This guide is for engineering leads and founders running .NET services with relational or document databases. It explains how to make schema changes, sensitive-data access and release checks independently verifiable. Start with one repository and one critical workflow. The aim is to reduce the cost of recovering from mistakes while keeping engineers responsible for the decisions that affect customers.

Table of contents

When does code review become theatre?

Review becomes theatre when an approval signals confidence that nobody has established. The problem is not specific to AI. Generated code makes it particularly easy to produce a plausible implementation and equally plausible tests that share the same mistaken assumption.

Consider a fictional subscription platform. A generated endpoint checks that the caller is logged in, but never checks whether the requested invoice belongs to that caller’s organisation. Its happy-path test passes. Neither the code’s readability nor another AI’s approval proves the tenant boundary holds.

The useful change is to ask for evidence about the behaviour: can one tenant retrieve another tenant’s invoice, can an old application version run against the proposed schema, and can the release identity modify key permissions? Use repeatable checks for those questions, then reserve human review for the architectural decisions behind them.

How do you protect the database schema?

Test the resulting schema and the migration’s effect on data. Reading a migration file remains useful, but it is only one part of that assessment.

Build disposable databases from the approved baseline and the proposed branch. Compare tables, columns, constraints and indexes. Run representative queries against the migrated database, and inspect row counts, tenant relationships and business totals. Use synthetic or properly sanitised fixtures rather than copying production personal data into CI.

For EF Core 8 or later, check whether entity-model changes have a corresponding migration:

dotnet ef migrations has-pending-model-changes

This compares the model with its migration snapshot. It does not prove that a live database matches the snapshot, or that a backfill preserves data. Those need separate checks. Microsoft’s migration guidance describes the command and the need to inspect generated migrations.

Produce a reviewed script or migration bundle from the release commit. Apply it through a controlled deployment step with a separate schema-changing identity. Keep the ordinary application identity limited to its runtime needs. Microsoft documents these deployment options.

For a busy PostgreSQL table, consider an expand-and-contract sequence: add a compatible field, backfill in bounded batches, switch readers and writers, then remove the old field in a later release. Rehearse lock behaviour and recovery. PostgreSQL’s ALTER TABLE documentation explains that lock requirements depend on the operation; not every column change has the same impact.

MongoDB needs an explicit record contract too. Use collection validators for the shapes and types your application depends on, and review validator changes alongside data migrations. Check existing documents before tightening a rule. MongoDB schema validation supports this control, but introducing a validator does not automatically repair historical records.

What does encryption protect, and where does it stop?

Encryption can reduce exposure from database or backup access. It does not replace authorisation, and it cannot stop an authorised application from returning plaintext to the wrong caller.

That distinction matters when evaluating field-level encryption. MongoDB offers client-side field-level and Queryable Encryption. Check the supported driver, server edition, query types and deployment requirements before choosing an approach.

SQL Server’s Always Encrypted uses client-side encryption to separate protected values from database access. For PostgreSQL, an application-side encryption design needs its own reviewed implementation and key-management boundary.

In each case, identify which process may decrypt each field. Keep key administration separate from routine application and agent credentials. Use established libraries behind a narrow interface, and test that logs, exports and error messages do not expose protected values.

For the fictional invoice platform, encrypting a customer’s sensitive identifier helps against some storage-level threats. It does not fix an export endpoint that decrypts every tenant’s records. Test both the storage protection and the endpoint’s permissions.

Which checks belong in the pipeline?

Require checks that exercise the failure modes your architecture must prevent. More tools do not automatically create better coverage.

BoundaryEvidence to require
Application behaviourIndependent acceptance tests, including invalid input and denied access
Data modelMigration rehearsal, schema comparison and checks for unintended data changes
Tenant isolationRequests made as another tenant and as a lower-privilege user
DependenciesProvenance, vulnerability review and a reason for each new package
Secrets and infrastructureSecret scanning, policy checks and review of permission changes
DeploymentA checked artifact, controlled promotion and live release verification

Combine appropriate static analysis, dependency scanning and secret detection. Evaluate a second analyser if it adds useful coverage to your stack; do not assume that any fixed number of scanners makes a release secure.

For critical paths, mutation testing can help reveal tests that pass despite broken behaviour. Code coverage alone only tells you which code ran. An AI review can suggest overlooked issues, but it should supply evidence for review rather than serve as the sole release authority.

Read our CI/CD guide for small product teams for the delivery foundations that support these controls.

How do you enforce the checks before a merge?

Put the policy in repository settings, and test whether it actually blocks an unacceptable change.

On GitHub, configure rulesets with required pull requests, named status checks and appropriate ownership approvals. Restrict bypass permissions and audit their use. Where available, bind required checks to their producing GitHub App. A merge queue can test changes against the proposed combined branch state, provided CI handles its events. Availability depends on the repository and plan. GitHub’s ruleset documentation explains these controls.

On Bitbucket Cloud, pair branch restrictions with merge checks. Confirm that your plan and configuration enforce failures rather than displaying advice. Atlassian’s merge-check documentation describes approvals, build requirements and enforcement options.

A useful acceptance test is a deliberately failing, disposable pull request. It should not merge through the normal contributor path. Also check what happens after a new commit invalidates an earlier approval.

What should a human reviewer still decide?

Keep a human responsible for changes to data meaning, security boundaries and public contracts. Automation can reveal a mismatch; it cannot decide whether a new business rule is acceptable.

Route migration, authentication, authorisation and key-management changes to appropriate owners. Protect the ownership rules and pipeline files themselves. An agent should not be able to remove a gate in the same change that needs to pass it.

For ASP.NET Core, require both authentication and checks on the requested resource. Microsoft’s protected-data example illustrates ownership-aware authorisation. Add denied-access tests instead of relying on the presence of an attribute.

Repository instructions should document approved data-access methods, tenant boundaries, migration patterns and forbidden shortcuts. They help an agent produce a better first attempt. Enforced permissions and tests remain necessary when those instructions are missed.

What does a practical first engagement take?

Start with one service, its database and one deployment path. Agree on the protected business behaviour before selecting tools.

A scoped architecture review can produce a schema-change policy, a sensitive-data map, a permissions review and a working set of release checks. Choose a representative workflow such as invoice export or account provisioning, and demonstrate that its negative tests fail when a boundary is broken.

The work depends on database size, existing test coverage, deployment privileges and the recovery process. Establish access requirements and acceptance criteria before estimating cost or schedule. There is no universal price or timeline that fits those conditions.

If you are still deciding how much autonomy to give an agent, our build-versus-buy guide offers a starting point for that implementation choice.

Which common mistakes should you avoid?

  • Treating a successful build as proof of safe data migration.
  • Running tests written from the same assumptions as the generated feature, without independent acceptance cases.
  • Assuming encrypted fields remain confidential after an authorised application decrypts them.
  • Using a label as approval when an agent can assign that label itself.
  • Requiring a check whose workflow can be edited or bypassed by the change author.
  • Applying migrations from a laptop without a retained artifact and recovery plan.

What evidence should a reviewer ask for

For data changes, review the migrations and compare the resulting schema with the approved baseline. Check that backfills preserve agreed totals and relationships on representative fixtures.

For access and sensitive data, include denied requests in tenant and resource-level tests. Document sensitive fields, decryption identities and key administrators.

For release control, require checks that block merging and restrict and audit bypass access. Ownership approval must cover security, migrations and the checks themselves. Promote the tested artifact and name the owners of recovery and post-deployment verification.

FAQ

Can AI review AI-generated code safely?

It can help find issues, but another model’s approval is not proof of correct behaviour. Combine it with independent tests, enforced checks and accountable architectural review.

Does EF Core’s pending-model check prove my database is correct?

No. It detects differences between the entity model and the migration snapshot. Rehearse the migration and compare the resulting database separately.

Does field-level encryption prevent data leaks from an API?

Not when the application can decrypt the data and returns it to an unauthorised caller. You still need resource-level permissions, restricted exports and denied-access tests.

Should every AI-generated change need an architect’s approval?

Apply ownership review to changes that affect data, security or contracts. Routine changes can follow normal review, with the required automated checks still enforced.

What should we fix first in a .NET repository using AI agents?

Start with a critical workflow’s access tests, migration checks and merge enforcement. Verify that deliberately incorrect changes are blocked before expanding the policy.

Where should you start with Zimozi?

Bring one repository, its deployment flow and the data boundaries you need to protect. Book a scoped architecture call with Zimozi to identify the first checks worth implementing.