@vibecheckai/cli 3.5.0 → 3.5.2
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/bin/registry.js +214 -237
- package/bin/runners/cli-utils.js +33 -2
- package/bin/runners/context/analyzer.js +52 -1
- package/bin/runners/context/generators/cursor.js +2 -49
- package/bin/runners/context/git-context.js +3 -1
- package/bin/runners/context/team-conventions.js +33 -7
- package/bin/runners/lib/analysis-core.js +25 -5
- package/bin/runners/lib/analyzers.js +431 -481
- package/bin/runners/lib/default-config.js +127 -0
- package/bin/runners/lib/doctor/modules/security.js +3 -1
- package/bin/runners/lib/engine/ast-cache.js +210 -0
- package/bin/runners/lib/engine/auth-extractor.js +211 -0
- package/bin/runners/lib/engine/billing-extractor.js +112 -0
- package/bin/runners/lib/engine/enforcement-extractor.js +100 -0
- package/bin/runners/lib/engine/env-extractor.js +207 -0
- package/bin/runners/lib/engine/express-extractor.js +208 -0
- package/bin/runners/lib/engine/extractors.js +849 -0
- package/bin/runners/lib/engine/index.js +207 -0
- package/bin/runners/lib/engine/repo-index.js +514 -0
- package/bin/runners/lib/engine/types.js +124 -0
- package/bin/runners/lib/engines/accessibility-engine.js +18 -218
- package/bin/runners/lib/engines/api-consistency-engine.js +30 -335
- package/bin/runners/lib/engines/cross-file-analysis-engine.js +27 -292
- package/bin/runners/lib/engines/empty-catch-engine.js +17 -127
- package/bin/runners/lib/engines/mock-data-engine.js +10 -53
- package/bin/runners/lib/engines/performance-issues-engine.js +36 -176
- package/bin/runners/lib/engines/security-vulnerabilities-engine.js +54 -382
- package/bin/runners/lib/engines/type-aware-engine.js +39 -263
- package/bin/runners/lib/engines/vibecheck-engines/index.js +13 -122
- package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +291 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +83 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +198 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +275 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +167 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +73 -373
- package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +140 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +164 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +234 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +217 -0
- package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +78 -0
- package/bin/runners/lib/entitlements-v2.js +73 -97
- package/bin/runners/lib/error-handler.js +44 -3
- package/bin/runners/lib/error-messages.js +289 -0
- package/bin/runners/lib/evidence-pack.js +7 -1
- package/bin/runners/lib/finding-id.js +69 -0
- package/bin/runners/lib/finding-sorter.js +89 -0
- package/bin/runners/lib/html-proof-report.js +700 -350
- package/bin/runners/lib/missions/plan.js +6 -46
- package/bin/runners/lib/missions/templates.js +0 -232
- package/bin/runners/lib/next-action.js +560 -0
- package/bin/runners/lib/prerequisites.js +149 -0
- package/bin/runners/lib/route-detection.js +137 -68
- package/bin/runners/lib/scan-output.js +91 -76
- package/bin/runners/lib/scan-runner.js +135 -0
- package/bin/runners/lib/schemas/ajv-validator.js +464 -0
- package/bin/runners/lib/schemas/error-envelope.schema.json +105 -0
- package/bin/runners/lib/schemas/finding-v3.schema.json +151 -0
- package/bin/runners/lib/schemas/report-artifact.schema.json +120 -0
- package/bin/runners/lib/schemas/run-request.schema.json +108 -0
- package/bin/runners/lib/schemas/validator.js +27 -0
- package/bin/runners/lib/schemas/verdict.schema.json +140 -0
- package/bin/runners/lib/ship-output-enterprise.js +23 -23
- package/bin/runners/lib/ship-output.js +75 -31
- package/bin/runners/lib/terminal-ui.js +6 -113
- package/bin/runners/lib/truth.js +351 -10
- package/bin/runners/lib/unified-cli-output.js +430 -603
- package/bin/runners/lib/unified-output.js +13 -9
- package/bin/runners/runAIAgent.js +10 -5
- package/bin/runners/runAgent.js +0 -3
- package/bin/runners/runAllowlist.js +389 -0
- package/bin/runners/runApprove.js +0 -33
- package/bin/runners/runAuth.js +73 -45
- package/bin/runners/runCheckpoint.js +51 -11
- package/bin/runners/runClassify.js +85 -21
- package/bin/runners/runContext.js +0 -3
- package/bin/runners/runDoctor.js +41 -28
- package/bin/runners/runEvidencePack.js +362 -0
- package/bin/runners/runFirewall.js +0 -3
- package/bin/runners/runFirewallHook.js +0 -3
- package/bin/runners/runFix.js +66 -76
- package/bin/runners/runGuard.js +18 -411
- package/bin/runners/runInit.js +113 -30
- package/bin/runners/runLabs.js +424 -0
- package/bin/runners/runMcp.js +19 -25
- package/bin/runners/runPolish.js +64 -240
- package/bin/runners/runPromptFirewall.js +12 -5
- package/bin/runners/runProve.js +57 -22
- package/bin/runners/runQuickstart.js +531 -0
- package/bin/runners/runReality.js +59 -68
- package/bin/runners/runReport.js +38 -33
- package/bin/runners/runRuntime.js +8 -5
- package/bin/runners/runScan.js +1413 -190
- package/bin/runners/runShip.js +113 -719
- package/bin/runners/runTruth.js +0 -3
- package/bin/runners/runValidate.js +13 -9
- package/bin/runners/runWatch.js +23 -14
- package/bin/scan.js +6 -1
- package/bin/vibecheck.js +204 -185
- package/mcp-server/deprecation-middleware.js +282 -0
- package/mcp-server/handlers/index.ts +15 -0
- package/mcp-server/handlers/tool-handler.ts +554 -0
- package/mcp-server/index-v1.js +698 -0
- package/mcp-server/index.js +210 -238
- package/mcp-server/lib/cache-wrapper.cjs +383 -0
- package/mcp-server/lib/error-envelope.js +138 -0
- package/mcp-server/lib/executor.ts +499 -0
- package/mcp-server/lib/index.ts +19 -0
- package/mcp-server/lib/rate-limiter.js +166 -0
- package/mcp-server/lib/sandbox.test.ts +519 -0
- package/mcp-server/lib/sandbox.ts +395 -0
- package/mcp-server/lib/types.ts +267 -0
- package/mcp-server/package.json +12 -3
- package/mcp-server/registry/tool-registry.js +794 -0
- package/mcp-server/registry/tools.json +605 -0
- package/mcp-server/registry.test.ts +334 -0
- package/mcp-server/tests/tier-gating.test.js +297 -0
- package/mcp-server/tier-auth.js +378 -45
- package/mcp-server/tools-v3.js +353 -442
- package/mcp-server/tsconfig.json +37 -0
- package/mcp-server/vibecheck-2.0-tools.js +14 -1
- package/package.json +1 -1
- package/bin/runners/lib/agent-firewall/learning/learning-engine.js +0 -849
- package/bin/runners/lib/audit-logger.js +0 -532
- package/bin/runners/lib/authority/authorities/architecture.js +0 -364
- package/bin/runners/lib/authority/authorities/compliance.js +0 -341
- package/bin/runners/lib/authority/authorities/human.js +0 -343
- package/bin/runners/lib/authority/authorities/quality.js +0 -420
- package/bin/runners/lib/authority/authorities/security.js +0 -228
- package/bin/runners/lib/authority/index.js +0 -293
- package/bin/runners/lib/bundle/bundle-intelligence.js +0 -846
- package/bin/runners/lib/cli-charts.js +0 -368
- package/bin/runners/lib/cli-config-display.js +0 -405
- package/bin/runners/lib/cli-demo.js +0 -275
- package/bin/runners/lib/cli-errors.js +0 -438
- package/bin/runners/lib/cli-help-formatter.js +0 -439
- package/bin/runners/lib/cli-interactive-menu.js +0 -509
- package/bin/runners/lib/cli-prompts.js +0 -441
- package/bin/runners/lib/cli-scan-cards.js +0 -362
- package/bin/runners/lib/compliance-reporter.js +0 -710
- package/bin/runners/lib/conductor/index.js +0 -671
- package/bin/runners/lib/easy/README.md +0 -123
- package/bin/runners/lib/easy/index.js +0 -140
- package/bin/runners/lib/easy/interactive-wizard.js +0 -788
- package/bin/runners/lib/easy/one-click-firewall.js +0 -564
- package/bin/runners/lib/easy/zero-config-reality.js +0 -714
- package/bin/runners/lib/engines/async-patterns-engine.js +0 -444
- package/bin/runners/lib/engines/bundle-size-engine.js +0 -433
- package/bin/runners/lib/engines/confidence-scoring.js +0 -276
- package/bin/runners/lib/engines/context-detection.js +0 -264
- package/bin/runners/lib/engines/database-patterns-engine.js +0 -429
- package/bin/runners/lib/engines/duplicate-code-engine.js +0 -354
- package/bin/runners/lib/engines/env-variables-engine.js +0 -458
- package/bin/runners/lib/engines/error-handling-engine.js +0 -437
- package/bin/runners/lib/engines/false-positive-prevention.js +0 -630
- package/bin/runners/lib/engines/framework-adapters/index.js +0 -607
- package/bin/runners/lib/engines/framework-detection.js +0 -508
- package/bin/runners/lib/engines/import-order-engine.js +0 -429
- package/bin/runners/lib/engines/naming-conventions-engine.js +0 -544
- package/bin/runners/lib/engines/noise-reduction-engine.js +0 -452
- package/bin/runners/lib/engines/orchestrator.js +0 -334
- package/bin/runners/lib/engines/react-patterns-engine.js +0 -457
- package/bin/runners/lib/engines/vibecheck-engines/lib/ai-hallucination-engine.js +0 -806
- package/bin/runners/lib/engines/vibecheck-engines/lib/smart-fix-engine.js +0 -577
- package/bin/runners/lib/engines/vibecheck-engines/lib/vibe-score-engine.js +0 -543
- package/bin/runners/lib/engines/vibecheck-engines.js +0 -514
- package/bin/runners/lib/enhanced-features/index.js +0 -305
- package/bin/runners/lib/enhanced-output.js +0 -631
- package/bin/runners/lib/enterprise.js +0 -300
- package/bin/runners/lib/firewall/command-validator.js +0 -351
- package/bin/runners/lib/firewall/config.js +0 -341
- package/bin/runners/lib/firewall/content-validator.js +0 -519
- package/bin/runners/lib/firewall/index.js +0 -101
- package/bin/runners/lib/firewall/path-validator.js +0 -256
- package/bin/runners/lib/intelligence/cross-repo-intelligence.js +0 -817
- package/bin/runners/lib/mcp-utils.js +0 -425
- package/bin/runners/lib/output/index.js +0 -1022
- package/bin/runners/lib/policy-engine.js +0 -652
- package/bin/runners/lib/polish/autofix/accessibility-fixes.js +0 -333
- package/bin/runners/lib/polish/autofix/async-handlers.js +0 -273
- package/bin/runners/lib/polish/autofix/dead-code.js +0 -280
- package/bin/runners/lib/polish/autofix/imports-optimizer.js +0 -344
- package/bin/runners/lib/polish/autofix/index.js +0 -200
- package/bin/runners/lib/polish/autofix/remove-consoles.js +0 -209
- package/bin/runners/lib/polish/autofix/strengthen-types.js +0 -245
- package/bin/runners/lib/polish/backend-checks.js +0 -148
- package/bin/runners/lib/polish/documentation-checks.js +0 -111
- package/bin/runners/lib/polish/frontend-checks.js +0 -168
- package/bin/runners/lib/polish/index.js +0 -71
- package/bin/runners/lib/polish/infrastructure-checks.js +0 -131
- package/bin/runners/lib/polish/library-detection.js +0 -175
- package/bin/runners/lib/polish/performance-checks.js +0 -100
- package/bin/runners/lib/polish/security-checks.js +0 -148
- package/bin/runners/lib/polish/utils.js +0 -203
- package/bin/runners/lib/prompt-builder.js +0 -540
- package/bin/runners/lib/proof-certificate.js +0 -634
- package/bin/runners/lib/reality/accessibility-audit.js +0 -946
- package/bin/runners/lib/reality/api-contract-validator.js +0 -1012
- package/bin/runners/lib/reality/chaos-engineering.js +0 -1084
- package/bin/runners/lib/reality/performance-tracker.js +0 -1077
- package/bin/runners/lib/reality/scenario-generator.js +0 -1404
- package/bin/runners/lib/reality/visual-regression.js +0 -852
- package/bin/runners/lib/reality-profiler.js +0 -717
- package/bin/runners/lib/replay/flight-recorder-viewer.js +0 -1160
- package/bin/runners/lib/review/ai-code-review.js +0 -832
- package/bin/runners/lib/rules/custom-rule-engine.js +0 -985
- package/bin/runners/lib/sbom-generator.js +0 -641
- package/bin/runners/lib/scan-output-enhanced.js +0 -512
- package/bin/runners/lib/security/owasp-scanner.js +0 -939
- package/bin/runners/lib/validators/contract-validator.js +0 -283
- package/bin/runners/lib/validators/dead-export-detector.js +0 -279
- package/bin/runners/lib/validators/dep-audit.js +0 -245
- package/bin/runners/lib/validators/env-validator.js +0 -319
- package/bin/runners/lib/validators/index.js +0 -120
- package/bin/runners/lib/validators/license-checker.js +0 -252
- package/bin/runners/lib/validators/route-validator.js +0 -290
- package/bin/runners/runAuthority.js +0 -528
- package/bin/runners/runConductor.js +0 -772
- package/bin/runners/runContainer.js +0 -366
- package/bin/runners/runEasy.js +0 -410
- package/bin/runners/runIaC.js +0 -372
- package/bin/runners/runVibe.js +0 -791
- package/mcp-server/tools.js +0 -495
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* License Checker - Ship-only check
|
|
3
|
-
* Validates dependency licenses for compliance
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
"use strict";
|
|
7
|
-
|
|
8
|
-
const path = require("path");
|
|
9
|
-
const fs = require("fs");
|
|
10
|
-
|
|
11
|
-
// Licenses that are generally safe for commercial use
|
|
12
|
-
const PERMISSIVE_LICENSES = [
|
|
13
|
-
"MIT",
|
|
14
|
-
"ISC",
|
|
15
|
-
"BSD-2-Clause",
|
|
16
|
-
"BSD-3-Clause",
|
|
17
|
-
"Apache-2.0",
|
|
18
|
-
"0BSD",
|
|
19
|
-
"CC0-1.0",
|
|
20
|
-
"Unlicense",
|
|
21
|
-
"WTFPL",
|
|
22
|
-
"Zlib",
|
|
23
|
-
"BlueOak-1.0.0",
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
// Licenses that require attribution or have other requirements
|
|
27
|
-
const ATTRIBUTION_LICENSES = [
|
|
28
|
-
"CC-BY-4.0",
|
|
29
|
-
"CC-BY-3.0",
|
|
30
|
-
];
|
|
31
|
-
|
|
32
|
-
// Copyleft licenses that may require source disclosure
|
|
33
|
-
const COPYLEFT_LICENSES = [
|
|
34
|
-
"GPL-2.0",
|
|
35
|
-
"GPL-3.0",
|
|
36
|
-
"LGPL-2.1",
|
|
37
|
-
"LGPL-3.0",
|
|
38
|
-
"AGPL-3.0",
|
|
39
|
-
"MPL-2.0",
|
|
40
|
-
"EPL-1.0",
|
|
41
|
-
"EPL-2.0",
|
|
42
|
-
"CDDL-1.0",
|
|
43
|
-
"EUPL-1.1",
|
|
44
|
-
"EUPL-1.2",
|
|
45
|
-
];
|
|
46
|
-
|
|
47
|
-
// Licenses that may have issues
|
|
48
|
-
const PROBLEMATIC_LICENSES = [
|
|
49
|
-
"SSPL-1.0",
|
|
50
|
-
"BSL-1.0",
|
|
51
|
-
"Elastic-2.0",
|
|
52
|
-
"Commons-Clause",
|
|
53
|
-
];
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Check dependency licenses for compliance issues
|
|
57
|
-
*/
|
|
58
|
-
async function checkLicenses(projectPath) {
|
|
59
|
-
const findings = [];
|
|
60
|
-
const startTime = Date.now();
|
|
61
|
-
|
|
62
|
-
try {
|
|
63
|
-
const nodeModulesPath = path.join(projectPath, "node_modules");
|
|
64
|
-
|
|
65
|
-
if (!fs.existsSync(nodeModulesPath)) {
|
|
66
|
-
return {
|
|
67
|
-
findings,
|
|
68
|
-
duration: Date.now() - startTime,
|
|
69
|
-
type: "license-checker",
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Get direct dependencies from package.json
|
|
74
|
-
const packageJsonPath = path.join(projectPath, "package.json");
|
|
75
|
-
if (!fs.existsSync(packageJsonPath)) {
|
|
76
|
-
return {
|
|
77
|
-
findings,
|
|
78
|
-
duration: Date.now() - startTime,
|
|
79
|
-
type: "license-checker",
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
84
|
-
const dependencies = {
|
|
85
|
-
...packageJson.dependencies,
|
|
86
|
-
...packageJson.devDependencies,
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
const licenseStats = {
|
|
90
|
-
permissive: 0,
|
|
91
|
-
attribution: 0,
|
|
92
|
-
copyleft: 0,
|
|
93
|
-
problematic: 0,
|
|
94
|
-
unknown: 0,
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
const problematicPackages = [];
|
|
98
|
-
const copyleftPackages = [];
|
|
99
|
-
const unknownPackages = [];
|
|
100
|
-
|
|
101
|
-
// Check each dependency
|
|
102
|
-
for (const depName of Object.keys(dependencies)) {
|
|
103
|
-
const depPath = path.join(nodeModulesPath, depName);
|
|
104
|
-
const depPackageJson = path.join(depPath, "package.json");
|
|
105
|
-
|
|
106
|
-
if (!fs.existsSync(depPackageJson)) continue;
|
|
107
|
-
|
|
108
|
-
try {
|
|
109
|
-
const depInfo = JSON.parse(fs.readFileSync(depPackageJson, "utf8"));
|
|
110
|
-
const license = normalizeLicense(depInfo.license);
|
|
111
|
-
|
|
112
|
-
if (!license || license === "UNLICENSED") {
|
|
113
|
-
licenseStats.unknown++;
|
|
114
|
-
unknownPackages.push(depName);
|
|
115
|
-
} else if (PERMISSIVE_LICENSES.includes(license)) {
|
|
116
|
-
licenseStats.permissive++;
|
|
117
|
-
} else if (ATTRIBUTION_LICENSES.includes(license)) {
|
|
118
|
-
licenseStats.attribution++;
|
|
119
|
-
} else if (COPYLEFT_LICENSES.includes(license)) {
|
|
120
|
-
licenseStats.copyleft++;
|
|
121
|
-
copyleftPackages.push({ name: depName, license });
|
|
122
|
-
} else if (PROBLEMATIC_LICENSES.includes(license)) {
|
|
123
|
-
licenseStats.problematic++;
|
|
124
|
-
problematicPackages.push({ name: depName, license });
|
|
125
|
-
} else {
|
|
126
|
-
licenseStats.unknown++;
|
|
127
|
-
unknownPackages.push(depName);
|
|
128
|
-
}
|
|
129
|
-
} catch {
|
|
130
|
-
// Skip packages that can't be read
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Report problematic licenses
|
|
135
|
-
for (const pkg of problematicPackages) {
|
|
136
|
-
findings.push({
|
|
137
|
-
id: `LICENSE_PROBLEMATIC_${hashString(pkg.name)}`,
|
|
138
|
-
category: "LicenseCompliance",
|
|
139
|
-
severity: "WARN",
|
|
140
|
-
title: `Potentially problematic license: ${pkg.name}`,
|
|
141
|
-
message: `${pkg.name} uses ${pkg.license} which may have usage restrictions`,
|
|
142
|
-
confidence: "high",
|
|
143
|
-
type: "problematic_license",
|
|
144
|
-
details: {
|
|
145
|
-
package: pkg.name,
|
|
146
|
-
license: pkg.license,
|
|
147
|
-
},
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Report copyleft licenses
|
|
152
|
-
if (copyleftPackages.length > 0) {
|
|
153
|
-
findings.push({
|
|
154
|
-
id: "LICENSE_COPYLEFT_SUMMARY",
|
|
155
|
-
category: "LicenseCompliance",
|
|
156
|
-
severity: "WARN",
|
|
157
|
-
title: `${copyleftPackages.length} packages with copyleft licenses`,
|
|
158
|
-
message: `Copyleft licenses may require source disclosure: ${copyleftPackages.map(p => p.name).slice(0, 5).join(", ")}${copyleftPackages.length > 5 ? "..." : ""}`,
|
|
159
|
-
confidence: "medium",
|
|
160
|
-
type: "copyleft_licenses",
|
|
161
|
-
details: {
|
|
162
|
-
packages: copyleftPackages,
|
|
163
|
-
},
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// Report unknown licenses only if there are many
|
|
168
|
-
if (unknownPackages.length > 10) {
|
|
169
|
-
findings.push({
|
|
170
|
-
id: "LICENSE_UNKNOWN_SUMMARY",
|
|
171
|
-
category: "LicenseCompliance",
|
|
172
|
-
severity: "INFO",
|
|
173
|
-
title: `${unknownPackages.length} packages with unknown/no license`,
|
|
174
|
-
message: `These packages have no clear license: ${unknownPackages.slice(0, 5).join(", ")}${unknownPackages.length > 5 ? "..." : ""}`,
|
|
175
|
-
confidence: "low",
|
|
176
|
-
type: "unknown_licenses",
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Check for LICENSE file in project
|
|
181
|
-
const hasLicenseFile = fs.existsSync(path.join(projectPath, "LICENSE")) ||
|
|
182
|
-
fs.existsSync(path.join(projectPath, "LICENSE.md")) ||
|
|
183
|
-
fs.existsSync(path.join(projectPath, "LICENSE.txt"));
|
|
184
|
-
|
|
185
|
-
if (!hasLicenseFile && Object.keys(dependencies).length > 0) {
|
|
186
|
-
findings.push({
|
|
187
|
-
id: "LICENSE_NO_PROJECT_LICENSE",
|
|
188
|
-
category: "LicenseCompliance",
|
|
189
|
-
severity: "INFO",
|
|
190
|
-
title: "No LICENSE file in project",
|
|
191
|
-
message: "Consider adding a LICENSE file to clarify your project's licensing terms",
|
|
192
|
-
confidence: "high",
|
|
193
|
-
type: "no_license_file",
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
} catch (error) {
|
|
198
|
-
findings.push({
|
|
199
|
-
id: "LICENSE_CHECK_ERROR",
|
|
200
|
-
category: "LicenseCompliance",
|
|
201
|
-
severity: "INFO",
|
|
202
|
-
title: "License check incomplete",
|
|
203
|
-
message: `Could not complete license check: ${error.message}`,
|
|
204
|
-
confidence: "low",
|
|
205
|
-
type: "check_error",
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
return {
|
|
210
|
-
findings,
|
|
211
|
-
duration: Date.now() - startTime,
|
|
212
|
-
type: "license-checker",
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function normalizeLicense(license) {
|
|
217
|
-
if (!license) return null;
|
|
218
|
-
|
|
219
|
-
if (typeof license === "object") {
|
|
220
|
-
return license.type || license.name || null;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// Handle SPDX expressions like "MIT OR Apache-2.0"
|
|
224
|
-
const spdx = String(license).trim();
|
|
225
|
-
if (spdx.includes(" OR ")) {
|
|
226
|
-
// Take the first option
|
|
227
|
-
return spdx.split(" OR ")[0].trim();
|
|
228
|
-
}
|
|
229
|
-
if (spdx.includes(" AND ")) {
|
|
230
|
-
// All must be satisfied, take the most restrictive
|
|
231
|
-
return spdx.split(" AND ")[0].trim();
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
return spdx;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
function hashString(str) {
|
|
238
|
-
let hash = 0;
|
|
239
|
-
for (let i = 0; i < str.length; i++) {
|
|
240
|
-
const char = str.charCodeAt(i);
|
|
241
|
-
hash = ((hash << 5) - hash) + char;
|
|
242
|
-
hash = hash & hash;
|
|
243
|
-
}
|
|
244
|
-
return Math.abs(hash).toString(36).substring(0, 8);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
module.exports = {
|
|
248
|
-
checkLicenses,
|
|
249
|
-
PERMISSIVE_LICENSES,
|
|
250
|
-
COPYLEFT_LICENSES,
|
|
251
|
-
PROBLEMATIC_LICENSES,
|
|
252
|
-
};
|
|
@@ -1,290 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Route Validator - Ship-only check
|
|
3
|
-
* Validates that all routes resolve properly
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
"use strict";
|
|
7
|
-
|
|
8
|
-
const path = require("path");
|
|
9
|
-
const fs = require("fs");
|
|
10
|
-
const fg = require("fast-glob");
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Validate routes in the project
|
|
14
|
-
* Checks:
|
|
15
|
-
* - All Link href values resolve to actual routes
|
|
16
|
-
* - All API routes have handlers
|
|
17
|
-
* - No orphan routes (defined but unreachable)
|
|
18
|
-
* - Route parameters match between definition and usage
|
|
19
|
-
*/
|
|
20
|
-
async function validateRoutes(projectPath) {
|
|
21
|
-
const findings = [];
|
|
22
|
-
const startTime = Date.now();
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
// Get route definitions
|
|
26
|
-
const routeFiles = await findRouteFiles(projectPath);
|
|
27
|
-
const routeDefinitions = await extractRouteDefinitions(routeFiles, projectPath);
|
|
28
|
-
|
|
29
|
-
// Get route references (Links, fetches, navigations)
|
|
30
|
-
const codeFiles = fg.sync(["**/*.{ts,tsx,js,jsx}"], {
|
|
31
|
-
cwd: projectPath,
|
|
32
|
-
absolute: true,
|
|
33
|
-
ignore: [
|
|
34
|
-
"**/node_modules/**",
|
|
35
|
-
"**/dist/**",
|
|
36
|
-
"**/build/**",
|
|
37
|
-
"**/.next/**",
|
|
38
|
-
"**/*.test.*",
|
|
39
|
-
"**/*.spec.*",
|
|
40
|
-
],
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
const routeReferences = await extractRouteReferences(codeFiles, projectPath);
|
|
44
|
-
|
|
45
|
-
// Check for unresolved routes
|
|
46
|
-
const definedRoutes = new Set(routeDefinitions.map(r => r.path));
|
|
47
|
-
|
|
48
|
-
for (const ref of routeReferences) {
|
|
49
|
-
const normalizedPath = normalizeRoutePath(ref.path);
|
|
50
|
-
|
|
51
|
-
// Skip external URLs
|
|
52
|
-
if (isExternalUrl(ref.path)) continue;
|
|
53
|
-
|
|
54
|
-
// Skip dynamic routes that would match patterns
|
|
55
|
-
if (matchesDynamicRoute(normalizedPath, definedRoutes)) continue;
|
|
56
|
-
|
|
57
|
-
// Check if route exists
|
|
58
|
-
if (!routeExists(normalizedPath, routeDefinitions)) {
|
|
59
|
-
findings.push({
|
|
60
|
-
id: `ROUTE_UNRESOLVED_${hashString(ref.path)}`,
|
|
61
|
-
category: "RouteIntegrity",
|
|
62
|
-
severity: "WARN",
|
|
63
|
-
title: `Route reference may not resolve: ${ref.path}`,
|
|
64
|
-
message: `Link/fetch to ${ref.path} - no matching route found`,
|
|
65
|
-
file: ref.file,
|
|
66
|
-
line: ref.line,
|
|
67
|
-
confidence: "medium",
|
|
68
|
-
type: "unresolved_route",
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Check for orphan routes (defined but never referenced)
|
|
74
|
-
const referencedPaths = new Set(routeReferences.map(r => normalizeRoutePath(r.path)));
|
|
75
|
-
|
|
76
|
-
for (const route of routeDefinitions) {
|
|
77
|
-
if (isInternalRoute(route.path)) continue;
|
|
78
|
-
if (isApiRoute(route.path)) continue; // API routes may be called externally
|
|
79
|
-
|
|
80
|
-
const normalizedPath = normalizeRoutePath(route.path);
|
|
81
|
-
const isReferenced = Array.from(referencedPaths).some(ref =>
|
|
82
|
-
ref === normalizedPath || matchesDynamicPattern(ref, normalizedPath)
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
if (!isReferenced) {
|
|
86
|
-
findings.push({
|
|
87
|
-
id: `ROUTE_ORPHAN_${hashString(route.path)}`,
|
|
88
|
-
category: "RouteIntegrity",
|
|
89
|
-
severity: "INFO",
|
|
90
|
-
title: `Route may be orphaned: ${route.path}`,
|
|
91
|
-
message: `Route defined but not referenced in codebase`,
|
|
92
|
-
file: route.file,
|
|
93
|
-
line: route.line,
|
|
94
|
-
confidence: "low",
|
|
95
|
-
type: "orphan_route",
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
} catch (error) {
|
|
101
|
-
findings.push({
|
|
102
|
-
id: "ROUTE_VALIDATION_ERROR",
|
|
103
|
-
category: "RouteIntegrity",
|
|
104
|
-
severity: "INFO",
|
|
105
|
-
title: "Route validation incomplete",
|
|
106
|
-
message: `Could not fully validate routes: ${error.message}`,
|
|
107
|
-
confidence: "low",
|
|
108
|
-
type: "validation_error",
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return {
|
|
113
|
-
findings,
|
|
114
|
-
duration: Date.now() - startTime,
|
|
115
|
-
type: "route-validator",
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// ============================================================================
|
|
120
|
-
// HELPERS
|
|
121
|
-
// ============================================================================
|
|
122
|
-
|
|
123
|
-
async function findRouteFiles(projectPath) {
|
|
124
|
-
// Next.js App Router
|
|
125
|
-
const appRoutes = fg.sync(["**/app/**/page.{ts,tsx,js,jsx}", "**/app/**/route.{ts,tsx,js,jsx}"], {
|
|
126
|
-
cwd: projectPath,
|
|
127
|
-
absolute: true,
|
|
128
|
-
ignore: ["**/node_modules/**"],
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
// Next.js Pages Router
|
|
132
|
-
const pageRoutes = fg.sync(["**/pages/**/*.{ts,tsx,js,jsx}"], {
|
|
133
|
-
cwd: projectPath,
|
|
134
|
-
absolute: true,
|
|
135
|
-
ignore: ["**/node_modules/**", "**/pages/api/**"],
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
// API routes
|
|
139
|
-
const apiRoutes = fg.sync(["**/pages/api/**/*.{ts,tsx,js,jsx}", "**/app/api/**/route.{ts,tsx,js,jsx}"], {
|
|
140
|
-
cwd: projectPath,
|
|
141
|
-
absolute: true,
|
|
142
|
-
ignore: ["**/node_modules/**"],
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
return [...appRoutes, ...pageRoutes, ...apiRoutes];
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
async function extractRouteDefinitions(files, projectPath) {
|
|
149
|
-
const routes = [];
|
|
150
|
-
|
|
151
|
-
for (const file of files) {
|
|
152
|
-
const relativePath = path.relative(projectPath, file).replace(/\\/g, "/");
|
|
153
|
-
|
|
154
|
-
// Convert file path to route path
|
|
155
|
-
let routePath = relativePath
|
|
156
|
-
.replace(/^(src\/)?(app|pages)/, "")
|
|
157
|
-
.replace(/\/page\.(ts|tsx|js|jsx)$/, "")
|
|
158
|
-
.replace(/\/route\.(ts|tsx|js|jsx)$/, "")
|
|
159
|
-
.replace(/\/index\.(ts|tsx|js|jsx)$/, "")
|
|
160
|
-
.replace(/\.(ts|tsx|js|jsx)$/, "")
|
|
161
|
-
.replace(/\[\.\.\.(\w+)\]/g, "*") // Catch-all
|
|
162
|
-
.replace(/\[(\w+)\]/g, ":$1"); // Dynamic segments
|
|
163
|
-
|
|
164
|
-
if (!routePath.startsWith("/")) routePath = "/" + routePath;
|
|
165
|
-
if (routePath === "/") routePath = "/";
|
|
166
|
-
|
|
167
|
-
routes.push({
|
|
168
|
-
path: routePath,
|
|
169
|
-
file: relativePath,
|
|
170
|
-
line: 1,
|
|
171
|
-
type: relativePath.includes("/api/") ? "api" : "page",
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
return routes;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
async function extractRouteReferences(files, projectPath) {
|
|
179
|
-
const references = [];
|
|
180
|
-
|
|
181
|
-
for (const file of files) {
|
|
182
|
-
try {
|
|
183
|
-
const content = fs.readFileSync(file, "utf8");
|
|
184
|
-
const relativePath = path.relative(projectPath, file).replace(/\\/g, "/");
|
|
185
|
-
|
|
186
|
-
// Find Link hrefs
|
|
187
|
-
const linkMatches = content.matchAll(/href=["'`]([^"'`]+)["'`]/g);
|
|
188
|
-
for (const match of linkMatches) {
|
|
189
|
-
const line = content.substring(0, match.index).split("\n").length;
|
|
190
|
-
references.push({
|
|
191
|
-
path: match[1],
|
|
192
|
-
file: relativePath,
|
|
193
|
-
line,
|
|
194
|
-
type: "link",
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// Find router.push/replace
|
|
199
|
-
const routerMatches = content.matchAll(/(?:router|navigate)\.(?:push|replace)\s*\(\s*["'`]([^"'`]+)["'`]/g);
|
|
200
|
-
for (const match of routerMatches) {
|
|
201
|
-
const line = content.substring(0, match.index).split("\n").length;
|
|
202
|
-
references.push({
|
|
203
|
-
path: match[1],
|
|
204
|
-
file: relativePath,
|
|
205
|
-
line,
|
|
206
|
-
type: "navigation",
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Find fetch calls to API routes
|
|
211
|
-
const fetchMatches = content.matchAll(/fetch\s*\(\s*["'`](\/api[^"'`]+)["'`]/g);
|
|
212
|
-
for (const match of fetchMatches) {
|
|
213
|
-
const line = content.substring(0, match.index).split("\n").length;
|
|
214
|
-
references.push({
|
|
215
|
-
path: match[1],
|
|
216
|
-
file: relativePath,
|
|
217
|
-
line,
|
|
218
|
-
type: "fetch",
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
} catch {
|
|
222
|
-
// Skip files that can't be read
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
return references;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
function normalizeRoutePath(path) {
|
|
230
|
-
return path
|
|
231
|
-
.split("?")[0]
|
|
232
|
-
.split("#")[0]
|
|
233
|
-
.replace(/\/+$/, "") || "/";
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
function isExternalUrl(url) {
|
|
237
|
-
return /^(https?:)?\/\//.test(url) || url.startsWith("mailto:") || url.startsWith("tel:");
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
function isInternalRoute(path) {
|
|
241
|
-
return path.startsWith("/_") || path.includes("/_");
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
function isApiRoute(path) {
|
|
245
|
-
return path.startsWith("/api/") || path.includes("/api/");
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
function matchesDynamicRoute(path, definedRoutes) {
|
|
249
|
-
for (const route of definedRoutes) {
|
|
250
|
-
if (matchesDynamicPattern(path, route)) return true;
|
|
251
|
-
}
|
|
252
|
-
return false;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
function matchesDynamicPattern(path, pattern) {
|
|
256
|
-
const pathParts = path.split("/");
|
|
257
|
-
const patternParts = pattern.split("/");
|
|
258
|
-
|
|
259
|
-
if (patternParts.includes("*")) return true; // Catch-all
|
|
260
|
-
|
|
261
|
-
if (pathParts.length !== patternParts.length) return false;
|
|
262
|
-
|
|
263
|
-
for (let i = 0; i < patternParts.length; i++) {
|
|
264
|
-
const pp = patternParts[i];
|
|
265
|
-
if (pp.startsWith(":")) continue; // Dynamic segment matches anything
|
|
266
|
-
if (pp !== pathParts[i]) return false;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
return true;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
function routeExists(path, definitions) {
|
|
273
|
-
return definitions.some(def =>
|
|
274
|
-
def.path === path || matchesDynamicPattern(path, def.path)
|
|
275
|
-
);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
function hashString(str) {
|
|
279
|
-
let hash = 0;
|
|
280
|
-
for (let i = 0; i < str.length; i++) {
|
|
281
|
-
const char = str.charCodeAt(i);
|
|
282
|
-
hash = ((hash << 5) - hash) + char;
|
|
283
|
-
hash = hash & hash;
|
|
284
|
-
}
|
|
285
|
-
return Math.abs(hash).toString(36).substring(0, 8);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
module.exports = {
|
|
289
|
-
validateRoutes,
|
|
290
|
-
};
|