Back to blog
July 10, 2026

Why we gate every release

AI can generate software faster than any team can review it. Our answer is not to review less — it is to make the review automatic, and to make it a gate.

The uncomfortable truth about AI-generated code is that volume outruns scrutiny. When a system can produce a working feature in minutes, the bottleneck moves to the question nobody demos: is this safe and good enough to ship? XAIO’s position is that this question should never depend on someone remembering to ask it.

Four gates, one pipeline

Every publish runs the same sequence, over a frozen snapshot of exactly the code that would go live: tests, security analysis, code quality, and a check of the API surface. Testing, security and code quality are on for every project by default; Deep Quality (a full SonarQube analysis) and API linting can be switched on per project. Here is what each gate does — and why it exists.

Gate 1: Tests against a frozen snapshot

The generated test suite — Vitest for the frontend, pytest for the backend — runs in an isolated build environment with its own fresh test database. It runs against a frozen snapshot of the release, so the tested bytes are exactly the bytes that ship: you can keep working in the workspace while the release runs, and nothing you change mid-flight leaks into the verification. Genuine test failures block the publish.

Why it exists: a test suite that runs “sometimes”, or against a moving target, proves nothing. Freezing the snapshot is what turns tests from a ritual into evidence.

Gate 2: Security analysis over the shipping code

Two scanners look at the release from different angles:

  • Semgrep with an XAIO-curated ruleset: SQL injection, unsafe deserialization, JWT and TLS misconfiguration, wildcard CORS, debug mode left on, dangerous HTML injection, hardcoded credentials.
  • Trivy: known CVEs in dependencies, secret scanning (including custom patterns for key formats), and infrastructure misconfigurations.

One policy detail matters here: the gate blocks on fixable CVEs only. A vulnerability with no released fix must not wedge your release forever — it is still shown, loudly, but it does not take the publish hostage.

And for projects that want to go further, an optional dynamic scan (OWASP ZAP) probes a throwaway copy of the running app from the outside — security headers, cookie flags, CORS, information leakage — including signed-in pages when the testing integration is on. Its findings are advisory and land in the same problems view.

Gate 3: Code quality — up to a full SonarQube analysis

Ruff checks the Python backend: error-handling gaps, async pitfalls, naive datetimes, performance traps and a security ruleset. Biome checks the TypeScript/React frontend. Projects with the Deep Quality integration additionally get a full SonarQube analysis at publish: bugs, vulnerabilities, code smells and duplication, on exactly the shipping sources.

Why it exists: quality findings rarely break the demo — they break month six. Surfacing them at every release keeps the codebase maintainable while it grows.

Gate 4: The API surface

The generated OpenAPI specification is linted (Spectral, extended with API-security rules). And the open-endpoints gate lists every backend route that is reachable without authentication — the publish pauses until you confirm that list. Routes that are public by design are declared in code with a mandatory reason, so the decision is auditable instead of silent.

Why it exists: the most common real-world data leak is not an exotic exploit — it is an endpoint that was never meant to be public. This gate makes “public” an explicit decision, every time.

Why some findings block and others advise

Not everything stops the release, and that is deliberate. Blocking is reserved for low-false-positive, high-impact findings: injection risks, exposed secrets, TLS/JWT misconfiguration, debug mode, wildcard CORS, fixable CVEs, failing tests, unacknowledged open endpoints. Noisier classes — style, maintainability, most misconfigurations — are surfaced as advisory findings instead.

The reason is behavioral, not technical: a gate that cries wolf gets disabled, and a disabled gate protects nobody. And an infrastructure error in a scanner never blocks a release — only real findings do.

What happens when checks fail

A failing gate blocks the publish — that is the point. Findings show up in the deployment view with the full report one click away, and most of them come with a one-click AI fix: XAIO proposes the change, applies it, and re-runs the checks. Every publish attempt gets its own version number, so failed tries are clearly told apart from what is actually live.

The result is a property that prototype-first tools cannot offer: not because their models are worse, but because nothing in their pipeline is allowed to say no. A quality bar only exists if something enforces it.