@behavioral-contracts/verify-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +119 -0
- package/README.md +694 -0
- package/dist/analyze-results.js +253 -0
- package/dist/analyzer.d.ts +366 -0
- package/dist/analyzer.d.ts.map +1 -0
- package/dist/analyzer.js +2592 -0
- package/dist/analyzer.js.map +1 -0
- package/dist/analyzers/async-error-analyzer.d.ts +72 -0
- package/dist/analyzers/async-error-analyzer.d.ts.map +1 -0
- package/dist/analyzers/async-error-analyzer.js +243 -0
- package/dist/analyzers/async-error-analyzer.js.map +1 -0
- package/dist/analyzers/event-listener-analyzer.d.ts +102 -0
- package/dist/analyzers/event-listener-analyzer.d.ts.map +1 -0
- package/dist/analyzers/event-listener-analyzer.js +253 -0
- package/dist/analyzers/event-listener-analyzer.js.map +1 -0
- package/dist/analyzers/react-query-analyzer.d.ts +66 -0
- package/dist/analyzers/react-query-analyzer.d.ts.map +1 -0
- package/dist/analyzers/react-query-analyzer.js +341 -0
- package/dist/analyzers/react-query-analyzer.js.map +1 -0
- package/dist/analyzers/return-value-analyzer.d.ts +61 -0
- package/dist/analyzers/return-value-analyzer.d.ts.map +1 -0
- package/dist/analyzers/return-value-analyzer.js +225 -0
- package/dist/analyzers/return-value-analyzer.js.map +1 -0
- package/dist/code-snippet.d.ts +48 -0
- package/dist/code-snippet.d.ts.map +1 -0
- package/dist/code-snippet.js +84 -0
- package/dist/code-snippet.js.map +1 -0
- package/dist/corpus-loader.d.ts +33 -0
- package/dist/corpus-loader.d.ts.map +1 -0
- package/dist/corpus-loader.js +155 -0
- package/dist/corpus-loader.js.map +1 -0
- package/dist/fixture-tester.d.ts +28 -0
- package/dist/fixture-tester.d.ts.map +1 -0
- package/dist/fixture-tester.js +176 -0
- package/dist/fixture-tester.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +375 -0
- package/dist/index.js.map +1 -0
- package/dist/package-discovery.d.ts +62 -0
- package/dist/package-discovery.d.ts.map +1 -0
- package/dist/package-discovery.js +299 -0
- package/dist/package-discovery.js.map +1 -0
- package/dist/reporter.d.ts +43 -0
- package/dist/reporter.d.ts.map +1 -0
- package/dist/reporter.js +347 -0
- package/dist/reporter.js.map +1 -0
- package/dist/reporters/benchmarking.d.ts +70 -0
- package/dist/reporters/benchmarking.d.ts.map +1 -0
- package/dist/reporters/benchmarking.js +191 -0
- package/dist/reporters/benchmarking.js.map +1 -0
- package/dist/reporters/d3-visualizer.d.ts +40 -0
- package/dist/reporters/d3-visualizer.d.ts.map +1 -0
- package/dist/reporters/d3-visualizer.js +803 -0
- package/dist/reporters/d3-visualizer.js.map +1 -0
- package/dist/reporters/health-score.d.ts +33 -0
- package/dist/reporters/health-score.d.ts.map +1 -0
- package/dist/reporters/health-score.js +149 -0
- package/dist/reporters/health-score.js.map +1 -0
- package/dist/reporters/index.d.ts +11 -0
- package/dist/reporters/index.d.ts.map +1 -0
- package/dist/reporters/index.js +11 -0
- package/dist/reporters/index.js.map +1 -0
- package/dist/reporters/package-breakdown.d.ts +48 -0
- package/dist/reporters/package-breakdown.d.ts.map +1 -0
- package/dist/reporters/package-breakdown.js +185 -0
- package/dist/reporters/package-breakdown.js.map +1 -0
- package/dist/reporters/positive-evidence.d.ts +42 -0
- package/dist/reporters/positive-evidence.d.ts.map +1 -0
- package/dist/reporters/positive-evidence.js +436 -0
- package/dist/reporters/positive-evidence.js.map +1 -0
- package/dist/tsconfig-generator.d.ts +17 -0
- package/dist/tsconfig-generator.d.ts.map +1 -0
- package/dist/tsconfig-generator.js +107 -0
- package/dist/tsconfig-generator.js.map +1 -0
- package/dist/types.d.ts +298 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,694 @@
|
|
|
1
|
+
# @behavioral-contracts/verify-cli
|
|
2
|
+
|
|
3
|
+
**Verify TypeScript code against behavioral contracts.**
|
|
4
|
+
|
|
5
|
+
This CLI tool analyzes TypeScript codebases to detect violations of documented behavioral contracts from npm packages.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## What This Does
|
|
10
|
+
|
|
11
|
+
This tool answers: **"Does this code handle package error states correctly?"**
|
|
12
|
+
|
|
13
|
+
Not with opinions. With **verifiable checks against documented contracts**.
|
|
14
|
+
|
|
15
|
+
### The Problem
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
// Is this code production-ready?
|
|
19
|
+
const response = await axios.get('/api/data');
|
|
20
|
+
return response.data;
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Answer:** No. This crashes on network errors, ignores rate limiting, and doesn't check error.response exists.
|
|
24
|
+
|
|
25
|
+
### The Solution
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx @behavioral-contracts/verify-cli --tsconfig ./tsconfig.json
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Output:**
|
|
32
|
+
```
|
|
33
|
+
❌ axios-network-failure
|
|
34
|
+
src/api.ts:42:5
|
|
35
|
+
No try-catch block found. Network failures will crash the application.
|
|
36
|
+
Fix: Check error.response exists before accessing error.response.status
|
|
37
|
+
Docs: https://axios-http.com/docs/handling_errors
|
|
38
|
+
|
|
39
|
+
❌ axios-rate-limited-429
|
|
40
|
+
src/api.ts:42:5
|
|
41
|
+
Rate limit response (429) is not explicitly handled.
|
|
42
|
+
Fix: Implement retry logic or handle 429 as terminal error
|
|
43
|
+
Docs: https://axios-http.com/docs/handling_errors
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Installation
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npm install -D @behavioral-contracts/verify-cli
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Or run directly:
|
|
55
|
+
```bash
|
|
56
|
+
npx @behavioral-contracts/verify-cli
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Usage
|
|
62
|
+
|
|
63
|
+
### Basic Usage
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npx verify-cli --tsconfig ./tsconfig.json
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Options
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npx verify-cli \
|
|
73
|
+
--tsconfig ./tsconfig.json \
|
|
74
|
+
--corpus ../corpus \
|
|
75
|
+
--output ./audit.json \
|
|
76
|
+
--fail-on-warnings
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Options:**
|
|
80
|
+
- `--tsconfig <path>` - Path to tsconfig.json (default: ./tsconfig.json)
|
|
81
|
+
- `--corpus <path>` - Path to corpus directory (default: auto-detect)
|
|
82
|
+
- `--output <path>` - Output path for audit JSON (default: ./behavioral-audit.json)
|
|
83
|
+
- `--no-terminal` - Disable terminal output, JSON only
|
|
84
|
+
- `--fail-on-warnings` - Exit with error code if warnings found
|
|
85
|
+
- `--include-tests` - Include test files in analysis (default: false)
|
|
86
|
+
|
|
87
|
+
### Test File Handling
|
|
88
|
+
|
|
89
|
+
**By default, verify-cli excludes test files from analysis.**
|
|
90
|
+
|
|
91
|
+
**Why?**
|
|
92
|
+
- Tests intentionally expect errors to be thrown
|
|
93
|
+
- Test frameworks (Jest, Vitest, Mocha) provide automatic error handling
|
|
94
|
+
- 90%+ of test file violations are false positives
|
|
95
|
+
|
|
96
|
+
**Excluded patterns:**
|
|
97
|
+
- `/__tests__/` - Jest convention
|
|
98
|
+
- `/__mocks__/` - Mock files
|
|
99
|
+
- `.test.ts`, `.spec.ts` - Test files
|
|
100
|
+
- `.test.tsx`, `.spec.tsx` - React test files
|
|
101
|
+
- `/tests/`, `/test/` - Test directories
|
|
102
|
+
|
|
103
|
+
**To include test files:**
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
npx verify-cli --tsconfig ./tsconfig.json --include-tests
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**When to use `--include-tests`:**
|
|
110
|
+
- Analyzing test utility/helper functions
|
|
111
|
+
- Auditing test infrastructure code
|
|
112
|
+
- Reviewing test code quality
|
|
113
|
+
- Checking integration test error handling
|
|
114
|
+
|
|
115
|
+
**Example:** In production code, you might have 200 violations. With test files included, you might see 600+ violations (300% more), but 400+ are false positives from test code patterns.
|
|
116
|
+
|
|
117
|
+
**Decision rationale:** We default to excluding tests to maximize precision and focus on production code issues. Most CI/CD pipelines care about production code quality, not test file violations.
|
|
118
|
+
|
|
119
|
+
### CI Integration
|
|
120
|
+
|
|
121
|
+
**GitHub Actions:**
|
|
122
|
+
```yaml
|
|
123
|
+
- name: Verify behavioral contracts
|
|
124
|
+
run: npx @behavioral-contracts/verify-cli --tsconfig ./tsconfig.json
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**GitLab CI:**
|
|
128
|
+
```yaml
|
|
129
|
+
verify:
|
|
130
|
+
script:
|
|
131
|
+
- npx @behavioral-contracts/verify-cli --tsconfig ./tsconfig.json
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Output
|
|
137
|
+
|
|
138
|
+
### Terminal Output
|
|
139
|
+
|
|
140
|
+
Human-readable report with violations grouped by severity:
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
Behavioral Contract Verification Report
|
|
144
|
+
────────────────────────────────────────────────────────────────────────────
|
|
145
|
+
|
|
146
|
+
Summary:
|
|
147
|
+
Files analyzed: 47
|
|
148
|
+
Packages: axios, prisma
|
|
149
|
+
Contracts applied: 12
|
|
150
|
+
Timestamp: 2026-02-23T14:30:00Z
|
|
151
|
+
Git commit: abc123de
|
|
152
|
+
|
|
153
|
+
Violations:
|
|
154
|
+
|
|
155
|
+
Errors (2):
|
|
156
|
+
|
|
157
|
+
✗ src/api/client.ts:34:5
|
|
158
|
+
axios.get() called without handling 429 rate limit response
|
|
159
|
+
Package: axios.get()
|
|
160
|
+
Contract: rate-limited-429
|
|
161
|
+
Fix: Add handling for error.response?.status === 429
|
|
162
|
+
Docs: https://axios-http.com/docs/handling_errors
|
|
163
|
+
|
|
164
|
+
────────────────────────────────────────────────────────────────────────────
|
|
165
|
+
|
|
166
|
+
Summary:
|
|
167
|
+
Total violations: 2
|
|
168
|
+
Errors: 2
|
|
169
|
+
Warnings: 0
|
|
170
|
+
Info: 0
|
|
171
|
+
|
|
172
|
+
✗ FAILED
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### JSON Output (Audit Record)
|
|
176
|
+
|
|
177
|
+
Machine-readable artifact for CI/CD pipelines and compliance:
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"tool": "@behavioral-contracts/verify-cli",
|
|
182
|
+
"tool_version": "0.1.0",
|
|
183
|
+
"corpus_version": "1.0.0",
|
|
184
|
+
"timestamp": "2026-02-23T14:30:00Z",
|
|
185
|
+
"git_commit": "abc123def456",
|
|
186
|
+
"git_branch": "main",
|
|
187
|
+
"tsconfig": "./tsconfig.json",
|
|
188
|
+
"packages_analyzed": ["axios@1.6.2"],
|
|
189
|
+
"contracts_applied": 5,
|
|
190
|
+
"files_analyzed": 47,
|
|
191
|
+
"violations": [
|
|
192
|
+
{
|
|
193
|
+
"id": "axios-rate-limited-429",
|
|
194
|
+
"severity": "error",
|
|
195
|
+
"file": "src/api/client.ts",
|
|
196
|
+
"line": 34,
|
|
197
|
+
"column": 5,
|
|
198
|
+
"package": "axios",
|
|
199
|
+
"function": "get",
|
|
200
|
+
"contract_clause": "rate-limited-429",
|
|
201
|
+
"description": "axios.get() called without handling 429 rate limit response",
|
|
202
|
+
"source_doc": "https://axios-http.com/docs/handling_errors",
|
|
203
|
+
"suggested_fix": "Add handling for error.response?.status === 429"
|
|
204
|
+
}
|
|
205
|
+
],
|
|
206
|
+
"summary": {
|
|
207
|
+
"total_violations": 1,
|
|
208
|
+
"error_count": 1,
|
|
209
|
+
"warning_count": 0,
|
|
210
|
+
"info_count": 0,
|
|
211
|
+
"passed": false
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## How It Works
|
|
219
|
+
|
|
220
|
+
The verification pipeline:
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
TypeScript Code
|
|
224
|
+
↓
|
|
225
|
+
1. PARSE — TypeScript Compiler API reads AST
|
|
226
|
+
↓
|
|
227
|
+
2. RESOLVE — Find all call sites for corpus packages
|
|
228
|
+
↓
|
|
229
|
+
3. ANALYZE — Determine what error states are handled
|
|
230
|
+
↓
|
|
231
|
+
4. COMPARE — Match against contract requirements
|
|
232
|
+
↓
|
|
233
|
+
Audit Record (JSON + Terminal)
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### What Gets Checked
|
|
237
|
+
|
|
238
|
+
For each function call to a corpus package:
|
|
239
|
+
- ✅ Is there a try-catch block?
|
|
240
|
+
- ✅ Does the catch block check error.response exists?
|
|
241
|
+
- ✅ Are specific status codes (like 429) handled?
|
|
242
|
+
- ✅ Is there retry logic with backoff?
|
|
243
|
+
- ✅ Are null returns checked before use?
|
|
244
|
+
|
|
245
|
+
**Not checked:** Code style, formatting, naming conventions. This is behavioral verification only.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Corpus
|
|
250
|
+
|
|
251
|
+
Contracts come from the [behavioral-contracts/corpus](https://github.com/behavioral-contracts/corpus) repository.
|
|
252
|
+
|
|
253
|
+
**Currently supported packages:**
|
|
254
|
+
- axios (HTTP errors, rate limiting, network failures)
|
|
255
|
+
- jsonwebtoken (coming soon)
|
|
256
|
+
- prisma (coming soon)
|
|
257
|
+
- stripe (coming soon)
|
|
258
|
+
- bullmq (coming soon)
|
|
259
|
+
|
|
260
|
+
To add contracts for more packages, contribute to the corpus repository.
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Architecture
|
|
265
|
+
|
|
266
|
+
```
|
|
267
|
+
verify-cli/
|
|
268
|
+
├── src/
|
|
269
|
+
│ ├── index.ts # CLI entry point
|
|
270
|
+
│ ├── analyzer.ts # TypeScript AST analysis
|
|
271
|
+
│ ├── corpus-loader.ts # Loads YAML contracts
|
|
272
|
+
│ ├── reporter.ts # Generates reports
|
|
273
|
+
│ └── types.ts # Shared TypeScript types
|
|
274
|
+
└── tests/
|
|
275
|
+
├── fixtures/ # Test files with known violations
|
|
276
|
+
└── analyzer.test.ts # Test suite
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**Key technologies:**
|
|
280
|
+
- **TypeScript Compiler API** - AST analysis and type checking
|
|
281
|
+
- **YAML + JSON Schema** - Contract format and validation
|
|
282
|
+
- **Vitest** - Testing framework
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Bulk Analysis & Cross-Repo Scanning
|
|
287
|
+
|
|
288
|
+
For analyzing multiple repositories at once (e.g., testing against Top 50 TypeScript repos), use the bulk scanner.
|
|
289
|
+
|
|
290
|
+
### Quick Start
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
# From the workspace root (parent of verify-cli)
|
|
294
|
+
./tools/scan-all-repos.sh
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
This will:
|
|
298
|
+
1. Build verify-cli (skip with `--skip-build`)
|
|
299
|
+
2. Scan all repos in `test-repos/`
|
|
300
|
+
3. Generate comprehensive reports with unique run IDs
|
|
301
|
+
4. Create per-repo and per-package breakdowns
|
|
302
|
+
|
|
303
|
+
### Output Structure
|
|
304
|
+
|
|
305
|
+
Each run creates a timestamped directory with complete analysis results:
|
|
306
|
+
|
|
307
|
+
```
|
|
308
|
+
verify-cli/output/runs/20260224-163824-9192ca6/
|
|
309
|
+
├── run-metadata.json # Run metadata (timestamp, git hash, stats)
|
|
310
|
+
├── summary.md # Main overview table (all repos)
|
|
311
|
+
└── <repo-name>/
|
|
312
|
+
├── summary.md # Per-repo package breakdown
|
|
313
|
+
├── audit.json # Machine-readable violations
|
|
314
|
+
├── output.txt # Human-readable violations
|
|
315
|
+
└── packages/ # Per-package violation files
|
|
316
|
+
├── INDEX.md
|
|
317
|
+
├── axios/
|
|
318
|
+
│ ├── violations.json
|
|
319
|
+
│ └── violations.txt
|
|
320
|
+
├── zod/
|
|
321
|
+
│ ├── violations.json
|
|
322
|
+
│ └── violations.txt
|
|
323
|
+
└── ...
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Navigation Workflow
|
|
327
|
+
|
|
328
|
+
**1. Start at Main Summary** (`summary.md`)
|
|
329
|
+
|
|
330
|
+
Overview table showing all repos:
|
|
331
|
+
|
|
332
|
+
| Repo | Version | Git Hash | Passed | Files | Packages | Contracts | Total | Errors | Warnings | Info | Details |
|
|
333
|
+
|------|---------|----------|--------|-------|----------|-----------|-------|--------|----------|------|---------|
|
|
334
|
+
| [angular](./angular/) | 0.1.0 | 98e64c5 | ❌ | 1178 | 10 | 44 | 15 | 9 | 6 | 0 | [📊 Summary](./angular/summary.md) · [📦 Packages](./angular/packages/) · [📄 JSON](./angular/audit.json) · [📝 TXT](./angular/output.txt) |
|
|
335
|
+
|
|
336
|
+
Click:
|
|
337
|
+
- **Repo name** → Navigate to repo directory
|
|
338
|
+
- **📊 Summary** → View per-repo package breakdown
|
|
339
|
+
- **📦 Packages** → View per-package violation index
|
|
340
|
+
- **📄 JSON** → Machine-readable audit
|
|
341
|
+
- **📝 TXT** → Human-readable violations with code context
|
|
342
|
+
|
|
343
|
+
**2. Repo Summary** (`<repo>/summary.md`)
|
|
344
|
+
|
|
345
|
+
Shows which packages were analyzed and which had violations:
|
|
346
|
+
|
|
347
|
+
| Package | Contracts | Total | Errors | Warnings | Info | Status | Details |
|
|
348
|
+
|---------|-----------|-------|--------|----------|------|--------|---------|
|
|
349
|
+
| react-hook-form | 2 | 12 | 6 | 6 | 0 | ❌ Failed | [📄 JSON](./packages/react-hook-form/violations.json) · [📝 TXT](./packages/react-hook-form/violations.txt) |
|
|
350
|
+
| zod | 0 | 0 | 0 | 0 | 0 | ✅ Passed | - |
|
|
351
|
+
|
|
352
|
+
**Sorted automatically:**
|
|
353
|
+
- ❌ Failed packages (with violations) at top
|
|
354
|
+
- ✅ Passed packages at bottom
|
|
355
|
+
|
|
356
|
+
**3. Package Violations** (`<repo>/packages/<package>/`)
|
|
357
|
+
|
|
358
|
+
Individual violation files for cross-repo analysis:
|
|
359
|
+
- `violations.json` - Machine-readable violations for this package in this repo
|
|
360
|
+
- `violations.txt` - Human-readable with code snippets
|
|
361
|
+
|
|
362
|
+
### Cross-Repo Analysis
|
|
363
|
+
|
|
364
|
+
#### Find all violations for a specific package
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
# Find all axios violations across all runs
|
|
368
|
+
find verify-cli/output/runs -path "*/packages/axios/violations.json"
|
|
369
|
+
|
|
370
|
+
# Find axios violations in latest run
|
|
371
|
+
find verify-cli/output/runs -path "*/packages/axios/violations.json" | sort | tail -1
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
#### Count violations per repo for a package
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
# How many zod violations in each repo?
|
|
378
|
+
find verify-cli/output/runs/20260224-163824-9192ca6 \
|
|
379
|
+
-path "*/packages/zod/violations.json" \
|
|
380
|
+
-exec sh -c 'echo -n "$(dirname $1 | xargs dirname | xargs basename): "; jq .total_violations "$1"' sh {} \;
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
**Output:**
|
|
384
|
+
```
|
|
385
|
+
angular: 8
|
|
386
|
+
nextjs: 15
|
|
387
|
+
vitest: 3
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
#### Extract all violation descriptions for a package
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
# See all zod violation types across repos
|
|
394
|
+
find verify-cli/output/runs/20260224-163824-9192ca6 \
|
|
395
|
+
-path "*/packages/zod/violations.json" \
|
|
396
|
+
-exec jq -r '.violations[].description' {} \; | sort | uniq
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
#### Compare package usage between repos
|
|
400
|
+
|
|
401
|
+
```bash
|
|
402
|
+
# Which repos use axios?
|
|
403
|
+
find verify-cli/output/runs/20260224-163824-9192ca6 \
|
|
404
|
+
-path "*/packages/axios" -type d | \
|
|
405
|
+
xargs dirname | xargs basename
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
#### Aggregate statistics for a package
|
|
409
|
+
|
|
410
|
+
```bash
|
|
411
|
+
# Total violations for react-hook-form across all repos
|
|
412
|
+
find verify-cli/output/runs/20260224-163824-9192ca6 \
|
|
413
|
+
-path "*/packages/react-hook-form/violations.json" \
|
|
414
|
+
-exec jq '.total_violations' {} \; | \
|
|
415
|
+
awk '{sum+=$1} END {print "Total:", sum}'
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### Run Metadata
|
|
419
|
+
|
|
420
|
+
Each run includes `run-metadata.json` with:
|
|
421
|
+
|
|
422
|
+
```json
|
|
423
|
+
{
|
|
424
|
+
"run_id": "20260224-163824-9192ca6",
|
|
425
|
+
"timestamp": "2026-02-24T16:38:24Z",
|
|
426
|
+
"git_commit": "9192ca6f...",
|
|
427
|
+
"git_branch": "main",
|
|
428
|
+
"scanner_version": "0.1.0",
|
|
429
|
+
"trigger": "manual",
|
|
430
|
+
"repos_scanned": 50,
|
|
431
|
+
"repos_failed": 0,
|
|
432
|
+
"total_files": 45832,
|
|
433
|
+
"total_packages": 500,
|
|
434
|
+
"total_contracts": 2200,
|
|
435
|
+
"total_violations": 3456,
|
|
436
|
+
"total_errors": 2100,
|
|
437
|
+
"total_warnings": 1200,
|
|
438
|
+
"total_info": 156
|
|
439
|
+
}
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
### Advanced Usage
|
|
443
|
+
|
|
444
|
+
#### Analyze specific repos only
|
|
445
|
+
|
|
446
|
+
```bash
|
|
447
|
+
# Remove unwanted repos from test-repos/ first
|
|
448
|
+
rm -rf test-repos/unwanted-repo
|
|
449
|
+
./tools/scan-all-repos.sh
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
#### Skip build for faster iteration
|
|
453
|
+
|
|
454
|
+
```bash
|
|
455
|
+
# If verify-cli hasn't changed
|
|
456
|
+
./tools/scan-all-repos.sh --skip-build
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
#### Compare runs over time
|
|
460
|
+
|
|
461
|
+
```bash
|
|
462
|
+
# List all runs
|
|
463
|
+
ls -1 verify-cli/output/runs/
|
|
464
|
+
|
|
465
|
+
# Compare violation counts
|
|
466
|
+
echo "Run 1:" && jq .total_violations verify-cli/output/runs/20260224-163824-9192ca6/run-metadata.json
|
|
467
|
+
echo "Run 2:" && jq .total_violations verify-cli/output/runs/20260224-170000-abc123d/run-metadata.json
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
#### Deep-dive analysis for a specific violation
|
|
471
|
+
|
|
472
|
+
```bash
|
|
473
|
+
# Find all occurrences of a specific contract violation
|
|
474
|
+
find verify-cli/output/runs -name "*.json" \
|
|
475
|
+
-exec jq -r '.violations[] | select(.contract_clause == "empty-catch-block-silent-failure") | .file + ":" + (.line|tostring)' {} \;
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
### Integration with CI/CD
|
|
479
|
+
|
|
480
|
+
**Track violations over time:**
|
|
481
|
+
|
|
482
|
+
```yaml
|
|
483
|
+
# .github/workflows/contracts.yml
|
|
484
|
+
- name: Run contract scanner
|
|
485
|
+
run: |
|
|
486
|
+
./tools/scan-all-repos.sh
|
|
487
|
+
|
|
488
|
+
- name: Upload results
|
|
489
|
+
uses: actions/upload-artifact@v3
|
|
490
|
+
with:
|
|
491
|
+
name: contract-violations-${{ github.sha }}
|
|
492
|
+
path: verify-cli/output/runs/latest/
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
**Fail on new violations:**
|
|
496
|
+
|
|
497
|
+
```bash
|
|
498
|
+
# Compare current run with baseline
|
|
499
|
+
BASELINE_VIOLATIONS=$(jq .total_violations baseline/run-metadata.json)
|
|
500
|
+
CURRENT_VIOLATIONS=$(jq .total_violations verify-cli/output/runs/latest/run-metadata.json)
|
|
501
|
+
|
|
502
|
+
if [ $CURRENT_VIOLATIONS -gt $BASELINE_VIOLATIONS ]; then
|
|
503
|
+
echo "❌ New violations introduced!"
|
|
504
|
+
exit 1
|
|
505
|
+
fi
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
## Development
|
|
511
|
+
|
|
512
|
+
### Setup
|
|
513
|
+
|
|
514
|
+
```bash
|
|
515
|
+
git clone https://github.com/behavioral-contracts/verify-cli.git
|
|
516
|
+
cd verify-cli
|
|
517
|
+
npm install
|
|
518
|
+
npm run build
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
### Run Tests
|
|
522
|
+
|
|
523
|
+
```bash
|
|
524
|
+
npm test
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
### Run on Sample Project
|
|
528
|
+
|
|
529
|
+
```bash
|
|
530
|
+
npm run build
|
|
531
|
+
node dist/index.js --tsconfig ./tests/tsconfig.test.json
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
---
|
|
535
|
+
|
|
536
|
+
## Roadmap
|
|
537
|
+
|
|
538
|
+
### v0.1.0 (MVP) - Current
|
|
539
|
+
- ✅ Core analysis engine
|
|
540
|
+
- ✅ Axios contract support
|
|
541
|
+
- ✅ Terminal + JSON output
|
|
542
|
+
- ✅ CI integration
|
|
543
|
+
|
|
544
|
+
### v0.2.0
|
|
545
|
+
- [ ] jsonwebtoken, prisma, stripe, bullmq contracts
|
|
546
|
+
- [ ] Performance optimization (sub-1min for 50K LOC)
|
|
547
|
+
- [ ] Severity threshold filtering
|
|
548
|
+
|
|
549
|
+
### v0.3.0
|
|
550
|
+
- [ ] IDE integration (VS Code extension)
|
|
551
|
+
- [ ] Watch mode for development
|
|
552
|
+
- [ ] Custom contract overlays
|
|
553
|
+
|
|
554
|
+
### v1.0.0
|
|
555
|
+
- [ ] 20+ package contracts
|
|
556
|
+
- [ ] Production-tested on 100+ codebases
|
|
557
|
+
- [ ] Enterprise features (SIEM integration, compliance reports)
|
|
558
|
+
|
|
559
|
+
---
|
|
560
|
+
|
|
561
|
+
## FAQ
|
|
562
|
+
|
|
563
|
+
**Q: Is this a linter?**
|
|
564
|
+
A: No. Linters check style and patterns. This verifies behavioral correctness against documented contracts.
|
|
565
|
+
|
|
566
|
+
**Q: Does this replace tests?**
|
|
567
|
+
A: No. This catches missing error handling. Tests verify business logic.
|
|
568
|
+
|
|
569
|
+
**Q: What about false positives?**
|
|
570
|
+
A: Contracts are designed to minimize false positives. Test files are excluded by default because they have different error handling patterns (90%+ of test violations are false positives). For production code, precision is >95%. If you find a false positive, report it.
|
|
571
|
+
|
|
572
|
+
**Q: Can I use this with JavaScript?**
|
|
573
|
+
A: Not yet. TypeScript is required for AST type resolution. JavaScript support is on the roadmap.
|
|
574
|
+
|
|
575
|
+
**Q: How is this different from TypeScript types?**
|
|
576
|
+
A: Types specify structure. Contracts specify behavior. "Throws on 429" is not in the type system.
|
|
577
|
+
|
|
578
|
+
**Q: Why are test files excluded by default?**
|
|
579
|
+
A: Test files have fundamentally different error handling patterns. Tests *expect* errors to be thrown (e.g., `expect(() => fn()).toThrow()`), and test frameworks automatically catch errors. Including test files creates 90%+ false positives, reducing precision from ~98% to ~85%. Use `--include-tests` if you want to analyze test utilities or infrastructure.
|
|
580
|
+
|
|
581
|
+
---
|
|
582
|
+
|
|
583
|
+
## License
|
|
584
|
+
|
|
585
|
+
**GNU Affero General Public License v3.0 (AGPL-3.0)**
|
|
586
|
+
|
|
587
|
+
This CLI tool is free and open source software.
|
|
588
|
+
|
|
589
|
+
### What This Means for You
|
|
590
|
+
|
|
591
|
+
**Individual Developers:**
|
|
592
|
+
- ✅ Use freely in your projects (free forever)
|
|
593
|
+
- ✅ Run locally without restrictions
|
|
594
|
+
- ✅ Contribute improvements back (open source)
|
|
595
|
+
|
|
596
|
+
**Companies (Internal Use):**
|
|
597
|
+
- ✅ Run in your CI/CD pipelines (free forever)
|
|
598
|
+
- ✅ Self-host for your organization (free forever)
|
|
599
|
+
- ✅ Modify for internal use (no restrictions)
|
|
600
|
+
- ✅ Integrate into your development workflow
|
|
601
|
+
|
|
602
|
+
**Companies (Building SaaS):**
|
|
603
|
+
- ⚠️ If you offer this tool as a **web service** (SaaS), you must open source your modifications
|
|
604
|
+
- ⚠️ Or contact us for commercial licensing
|
|
605
|
+
|
|
606
|
+
### Why AGPL-3.0?
|
|
607
|
+
|
|
608
|
+
**The AGPL protects open source from cloud providers:**
|
|
609
|
+
|
|
610
|
+
If Sentry (or any competitor) wants to use our analyzer:
|
|
611
|
+
- ✅ They can use it for free
|
|
612
|
+
- ✅ They can modify it
|
|
613
|
+
- ❌ But if they offer it as SaaS, they must open source their version
|
|
614
|
+
- ❌ Or pay for a commercial license
|
|
615
|
+
|
|
616
|
+
**What happened to Redis:**
|
|
617
|
+
- Redis: BSD license (permissive)
|
|
618
|
+
- AWS: Forked Redis → ElastiCache (proprietary SaaS)
|
|
619
|
+
- Redis Labs: Lost revenue to AWS
|
|
620
|
+
- Result: Redis Labs had to change license (too late)
|
|
621
|
+
|
|
622
|
+
**What we learned:**
|
|
623
|
+
- Use AGPL from day 1
|
|
624
|
+
- Prevent proprietary SaaS forks
|
|
625
|
+
- Ensure improvements flow back to community
|
|
626
|
+
|
|
627
|
+
### Examples
|
|
628
|
+
|
|
629
|
+
**✅ Allowed without restrictions:**
|
|
630
|
+
```bash
|
|
631
|
+
# Run in GitHub Actions
|
|
632
|
+
- name: Verify contracts
|
|
633
|
+
run: npx @behavioral-contracts/verify-cli
|
|
634
|
+
|
|
635
|
+
# Self-host for company
|
|
636
|
+
docker run verify-cli --tsconfig ./tsconfig.json
|
|
637
|
+
|
|
638
|
+
# Integrate into VSCode extension (if extension is open source)
|
|
639
|
+
import { analyze } from '@behavioral-contracts/verify-cli'
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
**⚠️ Requires open sourcing OR commercial license:**
|
|
643
|
+
```
|
|
644
|
+
# Building "ContractCheckr.com" (SaaS)
|
|
645
|
+
# Offering verify-cli as a web service
|
|
646
|
+
# Must either:
|
|
647
|
+
# 1. Open source your SaaS (AGPL compliance)
|
|
648
|
+
# 2. Get commercial license from us
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
### Dual Licensing
|
|
652
|
+
|
|
653
|
+
For organizations that cannot comply with AGPL-3.0, we offer commercial licenses.
|
|
654
|
+
|
|
655
|
+
**Commercial licenses include:**
|
|
656
|
+
- Proprietary SaaS rights
|
|
657
|
+
- No source code disclosure requirements
|
|
658
|
+
- Priority support
|
|
659
|
+
- Custom SLA
|
|
660
|
+
|
|
661
|
+
Contact: [Coming soon]
|
|
662
|
+
|
|
663
|
+
### Corpus License
|
|
664
|
+
|
|
665
|
+
The contract corpus is licensed separately under **CC BY-SA 4.0**.
|
|
666
|
+
|
|
667
|
+
See [corpus/LICENSE](../corpus/LICENSE) for details.
|
|
668
|
+
|
|
669
|
+
---
|
|
670
|
+
|
|
671
|
+
**Related:**
|
|
672
|
+
- Full license text: [LICENSE](./LICENSE)
|
|
673
|
+
- License FAQ: [Why AGPL?](https://www.gnu.org/licenses/why-affero-gpl.html)
|
|
674
|
+
- Commercial licensing: [Contact us]
|
|
675
|
+
|
|
676
|
+
---
|
|
677
|
+
|
|
678
|
+
## Contributing
|
|
679
|
+
|
|
680
|
+
See the main [behavioral-contracts](https://github.com/behavioral-contracts) organization for contribution guidelines.
|
|
681
|
+
|
|
682
|
+
To add contracts for new packages, contribute to the [corpus repository](https://github.com/behavioral-contracts/corpus).
|
|
683
|
+
|
|
684
|
+
---
|
|
685
|
+
|
|
686
|
+
## Support
|
|
687
|
+
|
|
688
|
+
- **Issues**: https://github.com/behavioral-contracts/verify-cli/issues
|
|
689
|
+
- **Discussions**: https://github.com/behavioral-contracts/verify-cli/discussions
|
|
690
|
+
- **Corpus Questions**: https://github.com/behavioral-contracts/corpus/issues
|
|
691
|
+
|
|
692
|
+
---
|
|
693
|
+
|
|
694
|
+
Built with the belief that **AI-generated code should be auditable, not just plausible**.
|