Every release goes on the record. Including the ones it refuses.
Kapas is a release control plane that fails closed. It never runs your app — it decides whether your code is allowed to ship across your own Vercel, Fly, and Neon accounts, and writes down the reasoning either way.
| gates | lint ✓ typecheck ✓ test ✓ build ✓ — all green |
| step 3 | DEPS_AUDIT — floor: severity ≥ high, production tree |
| finding | GHSA-████-████ · next 16.2.9 — middleware/proxy authorization bypass |
| outcome | BLOCKED — the release did not proceed |
| blast | same advisory found in 3 more products of 4 checked |
| resolution | upgrade → 16.2.11 · re-released clean the same day |
Both of them ship green through ordinary CI.
The bad migration
The app connects as an all-powerful role. Migrations run at boot, unbacked. A dropped column meets last week's code mid-rollout, and "rollback" is a prayer.
The known-vulnerable dependency
The advisory was public. The scanner reported it — to a tab nobody reads. Nothing in the release path was willing to say no.
Sixteen steps. Any missing signal is a failure, never a pass.
Deploy steps run in your CI, with your secrets — Kapas never holds a credential that could deploy on its own. The steps marked in red are the control plane's: the gates it will not delegate, and the recovery that must work when your CI is the thing that broke.
| № | STEP | RUNS IN | WHAT IT GATES |
|---|---|---|---|
| 1 | PREFLIGHT | kapas | typed confirmation; tag equals deploy-branch HEAD; every adapter resolved |
| 2 | GATE | tenant CI | your own checks — lint, typecheck, test, build — must exit 0 |
| 3 | DEPS_AUDIT | tenant CI | no known-vulnerable dependency at or above the severity floor |
| 4 | ARTIFACT | tenant CI | built once; everything downstream deploys this exact digest |
| 5 | ROLLBACK_MARK | kapas | the rollback target is captured before anything mutates |
| 6 | DB_BACKUP | kapas | a restore point exists before any migration runs |
| 7 | MIGRATE | tenant CI | expand/contract enforced; runs as the owner role, never the app |
| 8 | GRANTS | tenant CI | the runtime role is re-granted exactly least-privilege CRUD |
| 9 | PRIV_CHECK | tenant CI | the app role owns nothing, cannot CREATE; caveats recorded, never hidden |
| 10 | CANARY | tenant CI | deployed without moving production traffic |
| 11 | HEALTH_CANARY | kapas | the canary answers healthy before any traffic moves |
| 12 | PROMOTE | kapas | traffic moves only to a health-checked canary |
| 13 | HEALTH_PROMO | kapas | production answers healthy after cutover — or the release rolls back |
| 14 | FANOUT | kapas | dependent surfaces deploy in dependency order, each through its own gates |
| 15 | ROLLBACK | kapas | on failure after a promote: every promoted surface restored to its mark |
| 16 | LEDGER | kapas | one immutable, machine-readable record of what happened and why |
Steps 6–9 (shaded) run only on surfaces that own a database — and are recorded as skipped where they don't apply. A skip is never a way to pass a failed step.
The audit gate is Kapas's own step — never an opaque script we hope you had.
On 25 July 2026, a dependency-audit gate blocked one of our releases: a middleware/proxy authorization bypass in Next — in an app whose entire access model is middleware — plus an advisory in the auth library, on a product with live users. Checking the rest of the portfolio, four products were affected.
A pipeline that only ran lint · typecheck · test · build would have shipped every one of them.
— the incident Kapas was extracted to prevent. The ledger record above is its receipt.
Below the floor, advisories stay visible without blocking. At or above it, a release stops — unless someone puts their name on the exception:
- id
- GHSA-mh99-v99m-4gvg · brace-expansion (ReDoS)
- reason
- every installed copy carries the backported fix; forcing v5 tree-wide breaks minimatch@3
- owner
- dushyant
- until
- 2026-10-01 — re-blocks on expiry
No owner, no reason, no expiry — no acceptance. Quietly lowering the floor is the failure mode this step is designed against.
The boundaries are the trust model.
Not a host
Kapas never runs your app or your database. Compute stays on your Vercel and Fly; data stays in your Neon. It orchestrates; it does not hold.
Not a keeper of god credentials
Deploy steps run in your GitHub Actions with your secrets. Kapas-run steps use short-lived, scoped, per-release tokens. A Kapas breach must not leak your deploy credentials; a Kapas outage must not touch your prod.
Not a lock-in
kapas init writes standard, reviewable artifacts into your repo — a workflow, a config, hooks. Delete Kapas and you still own a working pipeline. Ejectability is proven in our own test suite, not promised.
Not a pretender to more safety than exists
Where a platform ceiling can't be removed — a provider role that can't be made truly read-only — the check records the caveat instead of claiming it's gone. Honesty about the ceiling is a feature.
Extracted from production, not imagined.
This methodology was built by hand, first — the same gated sequence, re-implemented across our own products on different stacks, until the repetition itself was the product insight. Kapas is the extraction. It releases every one of them before it opens to anyone.