Production verification framework -- smoke tests, architecture proofs, and infrastructure constraints for CI/CD pipelines.
- Smoke tests: Hit live endpoints sequentially, verify CSRF flows, authentication, rate limits, and custom business logic.
- Architecture proofs: Static analysis (via ts-morph) that proves guard composition, data flow, and config alignment invariants hold in source code.
- Infrastructure constraints: Verify DNS records, environment variables, and platform configuration match expectations.
pnpm add -D @production-verify/coreCreate a verify.config.ts in your project root:
import {
defineVerifyConfig,
csrfFlow,
csrfEnforcement,
bootstrapBurst,
turnstileBypass,
} from '@production-verify/core';
import { nestjs, nestjsDefaults } from '@production-verify/core/nestjs';
import { cloudflare, railway } from '@production-verify/core/infrastructure';
export default defineVerifyConfig({
target: {
baseUrl: 'https://www.example.com',
backendUrl: 'https://api.example.com',
},
smoke: {
session: turnstileBypass({ secret: process.env.TURNSTILE_BYPASS_SECRET }),
checks: [
csrfFlow(),
bootstrapBurst(8),
csrfEnforcement(),
// Add your own project-specific checks here
],
},
proof: nestjs({
srcPath: 'packages/backend/src',
tsconfigPath: 'packages/backend/tsconfig.json',
presets: [nestjsDefaults()],
contracts: {
JwtAuthGuard: { kind: 'strategy', writes: ['user'] },
SubscriptionGuard: {
kind: 'guard',
requires: ['JwtAuthGuard'],
writes: ['subscriptionTier'],
},
},
rules: {
'no-duplicate-guards': 'error',
'require-auth-for-user-reads': 'error',
'config-key-alignment': 'warn',
},
}),
infrastructure: [
cloudflare.dns({ domain: 'api.example.com', mode: 'dns-only' }),
railway.env({ required: ['MONGODB_URI', 'JWT_SECRET'] }),
],
policy: {
failOn: 'error',
reporters: ['console', 'github-actions'],
},
});Then run:
npx production-verifynpx production-verify # Run all (smoke + proof + infrastructure)
npx production-verify smoke # Smoke tests only
npx production-verify proof # Architecture proofs only
npx production-verify infrastructure # Infrastructure constraints only
npx production-verify --config path.ts # Explicit config file
npx production-verify --reporter json # Override reporter
npx production-verify --verbose # Debug outputThe CLI searches for config files in this order:
verify.config.tsverify.config.jsproduction-verify.config.ts--config <path>overrides all
TypeScript configs are loaded via jiti -- no compilation step needed.
| Factory | What it verifies |
|---|---|
csrfFlow() |
CSRF token endpoint returns JSON (not HTML challenge), sets cookie |
csrfEnforcement() |
Mutation without CSRF token is rejected with 403 |
bootstrapBurst(n, opts?) |
n parallel requests to common endpoints, none return 429 |
| Provider | Use case |
|---|---|
turnstileBypass({ secret }) |
CI environments -- bypasses Cloudflare Turnstile CAPTCHA |
refreshToken({ token }) |
Pre-established session via refresh token |
noAuth() |
Public endpoint checks only (no authentication) |
The @production-verify/core/nestjs subpath provides static analysis for NestJS backends using ts-morph.
import { nestjs, nestjsDefaults } from '@production-verify/core/nestjs';
const proof = nestjs({
srcPath: 'src',
tsconfigPath: 'tsconfig.json',
presets: [nestjsDefaults()],
contracts: {
JwtAuthGuard: { kind: 'strategy', writes: ['user'] },
},
rules: {
'no-duplicate-guards': 'error',
'config-key-alignment': 'warn',
'trust-proxy': { severity: 'error', expected: true },
},
});Contracts declare what each guard/middleware writes to the request object:
contracts: {
JwtAuthGuard: { kind: 'strategy', writes: ['user'] },
CsrfMiddleware: { kind: 'middleware', writes: ['csrfToken'] },
SubscriptionGuard: {
kind: 'guard',
requires: ['JwtAuthGuard'],
writes: ['subscriptionTier'],
},
}Contract kinds: 'guard', 'middleware', 'decorator', 'strategy'.
The broken-contract rule uses ts-morph to verify that contracts match actual source code -- if a contract says a guard writes user, but the code doesn't assign to req.user, you get a violation.
| Rule | Category | Description |
|---|---|---|
no-duplicate-guards |
guard-composition | APP_GUARD vs class/method @UseGuards duplication |
require-auth-for-user-reads |
data-flow | Controller reads req.user without auth guard in chain |
require-permission-implies-guard |
guard-composition | @RequirePermission without AdminGuard |
config-key-alignment |
topology | configService.get('KEY') vs Joi validation schema |
no-direct-env-for-validated-keys |
topology | process.env used where configService.get() should be |
trust-proxy |
topology | Express trust proxy setting matches expected value |
broken-contract |
data-flow | Contract declares writes that don't exist in source |
rules: {
'no-duplicate-guards': false, // disabled
'config-key-alignment': 'warn', // downgraded from 'error'
}Provides:
- Contract for
ThrottlerGuard(global guard, no writes) - Default severities for
no-duplicate-guards,config-key-alignment,trust-proxy
Project-specific guards must be declared by the consumer.
import type { NestJSProofPlugin, NestJSProofContext } from '@production-verify/core/nestjs';
const myPlugin: NestJSProofPlugin = {
name: 'my-custom-rules',
rules: [
{
name: 'my-custom-check',
defaultSeverity: 'error',
run(context: NestJSProofContext): ProofResult {
// Access context.routes, context.contracts, context.configKeys, etc.
return { rule: 'my-custom-check', category: 'custom', passed: true, severity: 'error', message: 'OK', violations: [] };
},
},
],
collectors: [
{
name: 'my-collector',
collect(project) { /* ts-morph Project instance */ },
},
],
};The @production-verify/core/infrastructure subpath provides constraint helpers for common platforms.
import { cloudflare, railway, vercel } from '@production-verify/core/infrastructure';
const constraints = [
cloudflare.dns({ domain: 'api.example.com', mode: 'dns-only' }),
railway.env({ required: ['MONGODB_URI', 'JWT_SECRET', 'ABLY_API_KEY'] }),
vercel.env({ required: ['NEXT_PUBLIC_API_URL'] }),
];| Helper | What it checks |
|---|---|
cloudflare.dns({ domain, mode }) |
DNS record proxy mode (proxied / dns-only) |
railway.env({ required }) |
Required env vars exist on Railway |
vercel.env({ required }) |
Required env vars exist on Vercel |
All infrastructure checks skip gracefully when API tokens are not available.
Implement the Reporter interface to create custom output formats:
import type { Reporter, CheckResult, ProofResult, VerificationReport } from '@production-verify/core';
const myReporter: Reporter = {
name: 'my-reporter',
onResult(result: CheckResult | ProofResult) {
// Called after each individual check/proof completes
},
onComplete(report: VerificationReport) {
// Called once with the full aggregated report
},
};
export default defineVerifyConfig({
// ...
policy: {
failOn: 'error',
reporters: ['console', myReporter],
},
});Built-in reporters: 'console', 'github-actions', 'json'.
| Import path | Contents |
|---|---|
@production-verify/core |
defineVerifyConfig, smoke checks, session providers, runner, reporters, types |
@production-verify/core/nestjs |
nestjs(), nestjsDefaults(), NestJS proof types |
@production-verify/core/infrastructure |
cloudflare, railway, vercel constraint helpers |
- Node.js >= 20.0.0
- ts-morph >= 23.0.0 (optional peer dependency -- only needed for
core/nestjsproof system)
MIT