Pre-flight checks that catch the bug classes unit tests miss.
Every check in this gate is a scar CWI already paid for. Unit tests are green, the deploy ships, and then boot dies on Black's phone — because the failure class lived in the seam between the tests and the deploy: a scope the tests never evaluated, a label hardcoded at build time, a cache split-brain between two changed files, a secret committed by accident. This gate encodes those scars as machine-checkable rules and runs before the deploy goes out.
A zero-dependency Node CLI (node >= 18). No network, no build step.
| Check | What it flags | The incident it encodes |
|---|---|---|
scope |
Identifier referenced from a scope where none of its declarations is visible.
Scope-identity analysis (parent-linked scopes, not bare brace depth) —
sibling scopes distinguished, var hoisting and braceless bodies handled. |
gear-ledger 2026-09-17 — DISTRICT_BEACONS declared const
inside a .then() callback, referenced at module top level →
ReferenceError killed boot before the first frame. 141 unit tests passed;
none evaluated the page's inline module script. |
labels |
Literal SAMPLE/LIVE badge with no mode variable driving it.
Passes on mode ternaries, mode-keyed label maps, and data bindings. |
3D world 2026-09-18 — billboard SAMPLE badge and ticker SIM tag
hardcoded at scene build, never followed the WorldClient mode. |
versioning |
Importer and its module both changed, but the import URL carries no
?v= query. Resolves relative module URLs from changed importers
(import/dynamic import()/<script src>/workers). |
Pages cache split-brain 2026-09-17 — new index.html + new
stage-logic.js shipped together; the browser served the OLD cached
module against the new page. |
secrets |
Secret-shaped filenames (.env, .pem, .key,
id_rsa*, *secret*, *credential*),
secret-shaped KEY/TOKEN/SECRET/PASSWORD/CREDENTIAL assignments,
private-key blocks. Values are never printed — findings name
file, line, and key shape only. |
Standing security order (2026-09-15): encrypt all CWI data — secrets never ship. Preventive. |
# scan the current tree (all checks)
node bin/deploy-gate.js .
# only some checks, machine output for CI
node bin/deploy-gate.js --checks scope,labels,versioning --json ./dist
# versioning check against an explicit changed-file list (no git needed)
node bin/deploy-gate.js --checks versioning --changed index.html,stage-logic.js ./dist
# skip paths
node bin/deploy-gate.js --exclude 'test/fixtures/secret-scan/**,docs/**' .
Exit codes: 0 = clean, 1 = findings, 2 = usage/operational error.
Per-line suppression for intentional exceptions:
billboard.textContent = 'SAMPLE'; // deploy-gate: allow — demo fixture
Ship gate per the trust-layer plan: the gate had to catch real historical bug classes in dry-run before v1 could ship. Full record with incident references: docs/CATCHES.md.
DISTRICT_BEACONS pattern → 2 findings, clean fixture → 0.key filename → 5 findings, values never printednode test/test.js — 21 tests, zero dependencies. Each historical incident is
reproduced as a fixture under test/fixtures/; the suite asserts the gate flags
the bug fixtures and passes the clean fixtures.
github.com/CumulativeWebInc/cwi-trust-deploy-gate · MIT license
Deploy Gate is a CWI Trust Layer product — pre-flight gates for teams shipping web artifacts, plus custom scar-encoding for your stack.
Contact hp@cumulativeweb.com Try the live docs →
A Cumulative Web Inc product. Pricing on request — no prices are published without approval.