@kevinrabun/judges 3.55.0 → 3.57.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/CHANGELOG.md +24 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +112 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/api-versioning-audit.d.ts +6 -0
- package/dist/commands/api-versioning-audit.d.ts.map +1 -0
- package/dist/commands/api-versioning-audit.js +234 -0
- package/dist/commands/api-versioning-audit.js.map +1 -0
- package/dist/commands/boundary-enforce.d.ts +6 -0
- package/dist/commands/boundary-enforce.d.ts.map +1 -0
- package/dist/commands/boundary-enforce.js +256 -0
- package/dist/commands/boundary-enforce.js.map +1 -0
- package/dist/commands/cache-audit.d.ts +5 -0
- package/dist/commands/cache-audit.d.ts.map +1 -0
- package/dist/commands/cache-audit.js +220 -0
- package/dist/commands/cache-audit.js.map +1 -0
- package/dist/commands/comment-drift.d.ts +5 -0
- package/dist/commands/comment-drift.d.ts.map +1 -0
- package/dist/commands/comment-drift.js +229 -0
- package/dist/commands/comment-drift.js.map +1 -0
- package/dist/commands/error-taxonomy.d.ts +6 -0
- package/dist/commands/error-taxonomy.d.ts.map +1 -0
- package/dist/commands/error-taxonomy.js +227 -0
- package/dist/commands/error-taxonomy.js.map +1 -0
- package/dist/commands/error-ux.d.ts +5 -0
- package/dist/commands/error-ux.d.ts.map +1 -0
- package/dist/commands/error-ux.js +253 -0
- package/dist/commands/error-ux.js.map +1 -0
- package/dist/commands/event-leak.d.ts +5 -0
- package/dist/commands/event-leak.d.ts.map +1 -0
- package/dist/commands/event-leak.js +263 -0
- package/dist/commands/event-leak.js.map +1 -0
- package/dist/commands/idempotency-audit.d.ts +5 -0
- package/dist/commands/idempotency-audit.d.ts.map +1 -0
- package/dist/commands/idempotency-audit.js +223 -0
- package/dist/commands/idempotency-audit.js.map +1 -0
- package/dist/commands/log-quality.d.ts +6 -0
- package/dist/commands/log-quality.d.ts.map +1 -0
- package/dist/commands/log-quality.js +212 -0
- package/dist/commands/log-quality.js.map +1 -0
- package/dist/commands/null-safety-audit.d.ts +6 -0
- package/dist/commands/null-safety-audit.d.ts.map +1 -0
- package/dist/commands/null-safety-audit.js +222 -0
- package/dist/commands/null-safety-audit.js.map +1 -0
- package/dist/commands/ownership-map.d.ts +6 -0
- package/dist/commands/ownership-map.d.ts.map +1 -0
- package/dist/commands/ownership-map.js +229 -0
- package/dist/commands/ownership-map.js.map +1 -0
- package/dist/commands/privilege-path.d.ts +5 -0
- package/dist/commands/privilege-path.d.ts.map +1 -0
- package/dist/commands/privilege-path.js +234 -0
- package/dist/commands/privilege-path.js.map +1 -0
- package/dist/commands/retry-pattern-audit.d.ts +6 -0
- package/dist/commands/retry-pattern-audit.d.ts.map +1 -0
- package/dist/commands/retry-pattern-audit.js +216 -0
- package/dist/commands/retry-pattern-audit.js.map +1 -0
- package/dist/commands/test-isolation.d.ts +6 -0
- package/dist/commands/test-isolation.d.ts.map +1 -0
- package/dist/commands/test-isolation.js +235 -0
- package/dist/commands/test-isolation.js.map +1 -0
- package/dist/commands/timeout-audit.d.ts +5 -0
- package/dist/commands/timeout-audit.d.ts.map +1 -0
- package/dist/commands/timeout-audit.js +211 -0
- package/dist/commands/timeout-audit.js.map +1 -0
- package/dist/commands/type-boundary.d.ts +5 -0
- package/dist/commands/type-boundary.d.ts.map +1 -0
- package/dist/commands/type-boundary.js +236 -0
- package/dist/commands/type-boundary.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error taxonomy — classify and standardize error codes, messages, and
|
|
3
|
+
* hierarchies across a codebase.
|
|
4
|
+
*/
|
|
5
|
+
import { readFileSync, readdirSync, statSync } from "fs";
|
|
6
|
+
import { join, extname } from "path";
|
|
7
|
+
// ─── File Collection ────────────────────────────────────────────────────────
|
|
8
|
+
const CODE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".go", ".rs"]);
|
|
9
|
+
function collectFiles(dir, max = 300) {
|
|
10
|
+
const files = [];
|
|
11
|
+
function walk(d) {
|
|
12
|
+
if (files.length >= max)
|
|
13
|
+
return;
|
|
14
|
+
let entries;
|
|
15
|
+
try {
|
|
16
|
+
entries = readdirSync(d);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
for (const e of entries) {
|
|
22
|
+
if (files.length >= max)
|
|
23
|
+
return;
|
|
24
|
+
if (e.startsWith(".") || e === "node_modules" || e === "dist" || e === "build")
|
|
25
|
+
continue;
|
|
26
|
+
const full = join(d, e);
|
|
27
|
+
try {
|
|
28
|
+
if (statSync(full).isDirectory())
|
|
29
|
+
walk(full);
|
|
30
|
+
else if (CODE_EXTS.has(extname(full)))
|
|
31
|
+
files.push(full);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
/* skip */
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
walk(dir);
|
|
39
|
+
return files;
|
|
40
|
+
}
|
|
41
|
+
// ─── Extraction ─────────────────────────────────────────────────────────────
|
|
42
|
+
function extractErrors(filepath) {
|
|
43
|
+
const errors = [];
|
|
44
|
+
let content;
|
|
45
|
+
try {
|
|
46
|
+
content = readFileSync(filepath, "utf-8");
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return errors;
|
|
50
|
+
}
|
|
51
|
+
const lines = content.split("\n");
|
|
52
|
+
for (let i = 0; i < lines.length; i++) {
|
|
53
|
+
const line = lines[i];
|
|
54
|
+
// Error class definitions
|
|
55
|
+
const classMatch = line.match(/class\s+(\w*Error\w*)\s+extends/);
|
|
56
|
+
if (classMatch) {
|
|
57
|
+
errors.push({ file: filepath, line: i + 1, code: classMatch[1], message: "", kind: "class" });
|
|
58
|
+
}
|
|
59
|
+
// Error code constants
|
|
60
|
+
const constMatch = line.match(/(?:const|export\s+const|static\s+readonly)\s+(\w*(?:ERR|ERROR|CODE)\w*)\s*[:=]\s*['"]([^'"]+)['"]/i);
|
|
61
|
+
if (constMatch) {
|
|
62
|
+
errors.push({ file: filepath, line: i + 1, code: constMatch[1], message: constMatch[2], kind: "constant" });
|
|
63
|
+
}
|
|
64
|
+
// throw new Error
|
|
65
|
+
const throwMatch = line.match(/throw\s+new\s+(\w*Error)\s*\(\s*['"`]([^'"`]{3,}?)['"`]/);
|
|
66
|
+
if (throwMatch) {
|
|
67
|
+
errors.push({ file: filepath, line: i + 1, code: throwMatch[1], message: throwMatch[2], kind: "throw" });
|
|
68
|
+
}
|
|
69
|
+
// HTTP status codes in responses
|
|
70
|
+
const statusMatch = line.match(/(?:status|statusCode|res\.status)\s*[:=(]\s*(\d{3})/);
|
|
71
|
+
if (statusMatch) {
|
|
72
|
+
const msgMatch = line.match(/(?:message|msg|error)\s*[:=]\s*['"`]([^'"`]+)['"`]/);
|
|
73
|
+
errors.push({
|
|
74
|
+
file: filepath,
|
|
75
|
+
line: i + 1,
|
|
76
|
+
code: `HTTP_${statusMatch[1]}`,
|
|
77
|
+
message: msgMatch?.[1] || "",
|
|
78
|
+
kind: "status",
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return errors;
|
|
83
|
+
}
|
|
84
|
+
// ─── Analysis ───────────────────────────────────────────────────────────────
|
|
85
|
+
function analyzeErrors(allErrors) {
|
|
86
|
+
const issues = [];
|
|
87
|
+
// Duplicate error messages
|
|
88
|
+
const msgMap = new Map();
|
|
89
|
+
for (const e of allErrors) {
|
|
90
|
+
if (e.message) {
|
|
91
|
+
const key = e.message.toLowerCase().trim();
|
|
92
|
+
if (!msgMap.has(key))
|
|
93
|
+
msgMap.set(key, []);
|
|
94
|
+
msgMap.get(key).push(e);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const dupes = [...msgMap.entries()].filter(([, v]) => v.length > 1);
|
|
98
|
+
if (dupes.length > 0) {
|
|
99
|
+
issues.push({
|
|
100
|
+
issue: `${dupes.length} duplicate error message(s)`,
|
|
101
|
+
severity: "medium",
|
|
102
|
+
detail: "Same message thrown from multiple places — consolidate into error constants",
|
|
103
|
+
examples: dupes.slice(0, 5).map(([msg, defs]) => `"${msg}" in ${defs.length} places`),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
// Inconsistent naming
|
|
107
|
+
const errorClasses = allErrors.filter((e) => e.kind === "class").map((e) => e.code);
|
|
108
|
+
const mixedCase = errorClasses.filter((c) => /Error$/i.test(c) && !/Error$/.test(c));
|
|
109
|
+
if (mixedCase.length > 0) {
|
|
110
|
+
issues.push({
|
|
111
|
+
issue: "Inconsistent error class naming",
|
|
112
|
+
severity: "low",
|
|
113
|
+
detail: "Some error classes don't follow PascalCase + Error suffix convention",
|
|
114
|
+
examples: mixedCase.slice(0, 5),
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
// Bare Error throws (no custom class)
|
|
118
|
+
const bareThrows = allErrors.filter((e) => e.kind === "throw" && e.code === "Error");
|
|
119
|
+
if (bareThrows.length > 5) {
|
|
120
|
+
issues.push({
|
|
121
|
+
issue: `${bareThrows.length} bare Error throws`,
|
|
122
|
+
severity: "high",
|
|
123
|
+
detail: "Throwing plain Error makes catch handling harder — use typed error classes",
|
|
124
|
+
examples: bareThrows.slice(0, 5).map((e) => `${e.file}:${e.line} — "${e.message.slice(0, 50)}"`),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
// Missing error codes
|
|
128
|
+
const constants = allErrors.filter((e) => e.kind === "constant");
|
|
129
|
+
const throws = allErrors.filter((e) => e.kind === "throw");
|
|
130
|
+
if (throws.length > 10 && constants.length === 0) {
|
|
131
|
+
issues.push({
|
|
132
|
+
issue: "No error code constants",
|
|
133
|
+
severity: "high",
|
|
134
|
+
detail: "Define error codes for machine-readable error handling (e.g., ERR_AUTH_FAILED)",
|
|
135
|
+
examples: throws.slice(0, 3).map((t) => `${t.file}:${t.line}`),
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
// Inconsistent HTTP status usage
|
|
139
|
+
const statusDefs = allErrors.filter((e) => e.kind === "status");
|
|
140
|
+
const statusCodes = new Map();
|
|
141
|
+
for (const s of statusDefs) {
|
|
142
|
+
statusCodes.set(s.code, (statusCodes.get(s.code) || 0) + 1);
|
|
143
|
+
}
|
|
144
|
+
const overusedStatuses = [...statusCodes.entries()].filter(([, count]) => count > 10);
|
|
145
|
+
if (overusedStatuses.length > 0) {
|
|
146
|
+
issues.push({
|
|
147
|
+
issue: "HTTP status code overuse",
|
|
148
|
+
severity: "medium",
|
|
149
|
+
detail: "Same status code used extensively — consider more specific error responses",
|
|
150
|
+
examples: overusedStatuses.map(([code, count]) => `${code} used ${count} times`),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
// Generic messages
|
|
154
|
+
const genericMsgs = allErrors.filter((e) => e.message && /^(error|something went wrong|unknown error|internal error|failed)$/i.test(e.message.trim()));
|
|
155
|
+
if (genericMsgs.length > 0) {
|
|
156
|
+
issues.push({
|
|
157
|
+
issue: `${genericMsgs.length} generic error message(s)`,
|
|
158
|
+
severity: "high",
|
|
159
|
+
detail: "Vague error messages impede debugging — include context (what failed, why, and what to try)",
|
|
160
|
+
examples: genericMsgs.slice(0, 5).map((e) => `${e.file}:${e.line} — "${e.message}"`),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
return issues;
|
|
164
|
+
}
|
|
165
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
166
|
+
export function runErrorTaxonomy(argv) {
|
|
167
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
168
|
+
console.log(`
|
|
169
|
+
judges error-taxonomy — Classify and standardize error codes and messages
|
|
170
|
+
|
|
171
|
+
Usage:
|
|
172
|
+
judges error-taxonomy [dir]
|
|
173
|
+
judges error-taxonomy src/ --format json
|
|
174
|
+
|
|
175
|
+
Options:
|
|
176
|
+
[dir] Directory to scan (default: .)
|
|
177
|
+
--format json JSON output
|
|
178
|
+
--help, -h Show this help
|
|
179
|
+
|
|
180
|
+
Checks: duplicate messages, inconsistent naming, bare Error throws, missing error codes,
|
|
181
|
+
generic messages, HTTP status overuse.
|
|
182
|
+
`);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
186
|
+
const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
|
|
187
|
+
const files = collectFiles(dir);
|
|
188
|
+
const allErrors = [];
|
|
189
|
+
for (const f of files)
|
|
190
|
+
allErrors.push(...extractErrors(f));
|
|
191
|
+
const issues = analyzeErrors(allErrors);
|
|
192
|
+
const highCount = issues.filter((i) => i.severity === "high").length;
|
|
193
|
+
const score = Math.max(0, 100 - highCount * 15 - issues.length * 5);
|
|
194
|
+
if (format === "json") {
|
|
195
|
+
console.log(JSON.stringify({
|
|
196
|
+
errors: allErrors.length,
|
|
197
|
+
issues,
|
|
198
|
+
score,
|
|
199
|
+
summary: {
|
|
200
|
+
classes: allErrors.filter((e) => e.kind === "class").length,
|
|
201
|
+
constants: allErrors.filter((e) => e.kind === "constant").length,
|
|
202
|
+
throws: allErrors.filter((e) => e.kind === "throw").length,
|
|
203
|
+
issues: issues.length,
|
|
204
|
+
},
|
|
205
|
+
timestamp: new Date().toISOString(),
|
|
206
|
+
}, null, 2));
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
const badge = score >= 80 ? "✅ CONSISTENT" : score >= 50 ? "⚠️ INCONSISTENT" : "❌ CHAOTIC";
|
|
210
|
+
console.log(`\n Error Taxonomy: ${badge} (${score}/100)\n ─────────────────────────────`);
|
|
211
|
+
console.log(` Error definitions: ${allErrors.length} | Classes: ${allErrors.filter((e) => e.kind === "class").length} | Constants: ${allErrors.filter((e) => e.kind === "constant").length} | Throws: ${allErrors.filter((e) => e.kind === "throw").length}\n`);
|
|
212
|
+
if (issues.length === 0) {
|
|
213
|
+
console.log(" No taxonomy issues detected.\n");
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
for (const issue of issues) {
|
|
217
|
+
const icon = issue.severity === "high" ? "🔴" : issue.severity === "medium" ? "🟡" : "🔵";
|
|
218
|
+
console.log(` ${icon} ${issue.issue}`);
|
|
219
|
+
console.log(` ${issue.detail}`);
|
|
220
|
+
for (const ex of issue.examples) {
|
|
221
|
+
console.log(` • ${ex}`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
console.log(`\n Score: ${score}/100\n`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=error-taxonomy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-taxonomy.js","sourceRoot":"","sources":["../../src/commands/error-taxonomy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-ux.d.ts","sourceRoot":"","sources":["../../src/commands/error-ux.ts"],"names":[],"mappings":"AAAA;;GAEG;AA8NH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA+D/C"}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error UX — audit user-facing error messages for actionability, consistency, and info leakage.
|
|
3
|
+
*/
|
|
4
|
+
import { readFileSync, readdirSync, statSync } from "fs";
|
|
5
|
+
import { join, extname } from "path";
|
|
6
|
+
// ─── File Collection ────────────────────────────────────────────────────────
|
|
7
|
+
const CODE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".go", ".rs"]);
|
|
8
|
+
function collectFiles(dir, max = 300) {
|
|
9
|
+
const files = [];
|
|
10
|
+
function walk(d) {
|
|
11
|
+
if (files.length >= max)
|
|
12
|
+
return;
|
|
13
|
+
let entries;
|
|
14
|
+
try {
|
|
15
|
+
entries = readdirSync(d);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
for (const e of entries) {
|
|
21
|
+
if (files.length >= max)
|
|
22
|
+
return;
|
|
23
|
+
if (e.startsWith(".") || e === "node_modules" || e === "dist" || e === "build")
|
|
24
|
+
continue;
|
|
25
|
+
const full = join(d, e);
|
|
26
|
+
try {
|
|
27
|
+
if (statSync(full).isDirectory())
|
|
28
|
+
walk(full);
|
|
29
|
+
else if (CODE_EXTS.has(extname(full)))
|
|
30
|
+
files.push(full);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
/* skip */
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
walk(dir);
|
|
38
|
+
return files;
|
|
39
|
+
}
|
|
40
|
+
// ─── Analysis ───────────────────────────────────────────────────────────────
|
|
41
|
+
function analyzeFile(filepath) {
|
|
42
|
+
const issues = [];
|
|
43
|
+
let content;
|
|
44
|
+
try {
|
|
45
|
+
content = readFileSync(filepath, "utf-8");
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return issues;
|
|
49
|
+
}
|
|
50
|
+
const lines = content.split("\n");
|
|
51
|
+
// Skip test and fixture files
|
|
52
|
+
if (/\.test\.|\.spec\.|__test__|fixture|mock/i.test(filepath))
|
|
53
|
+
return issues;
|
|
54
|
+
for (let i = 0; i < lines.length; i++) {
|
|
55
|
+
const line = lines[i];
|
|
56
|
+
// Generic unhelpful error messages
|
|
57
|
+
if (/(?:throw\s+new\s+Error|res\.status.*\.(?:json|send))\s*\(\s*['"]([^'"]+)['"]\s*\)/.test(line)) {
|
|
58
|
+
const msgMatch = line.match(/['"]([^'"]+)['"]/);
|
|
59
|
+
if (msgMatch) {
|
|
60
|
+
const msg = msgMatch[1];
|
|
61
|
+
if (/^(?:error|something went wrong|an error occurred|internal error|unknown error|bad request|failed|invalid)$/i.test(msg.trim())) {
|
|
62
|
+
issues.push({
|
|
63
|
+
file: filepath,
|
|
64
|
+
line: i + 1,
|
|
65
|
+
issue: "Generic error message",
|
|
66
|
+
severity: "medium",
|
|
67
|
+
detail: `"${msg}" — provide actionable guidance: what went wrong and how to fix it`,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Stack trace leaked to client
|
|
73
|
+
if (/(?:res\.(?:json|send)|response\.(?:json|send))\s*\(/.test(line)) {
|
|
74
|
+
const block = lines.slice(i, Math.min(i + 5, lines.length)).join("\n");
|
|
75
|
+
if (/\.stack|stackTrace|stack_trace|err\.message|error\.message/i.test(block)) {
|
|
76
|
+
if (!/production|NODE_ENV|process\.env/i.test(block)) {
|
|
77
|
+
issues.push({
|
|
78
|
+
file: filepath,
|
|
79
|
+
line: i + 1,
|
|
80
|
+
issue: "Stack trace may leak to client",
|
|
81
|
+
severity: "high",
|
|
82
|
+
detail: "Error details sent in response without environment check — may expose internals in production",
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Internal paths leaked in error messages
|
|
88
|
+
if (/(?:throw|console\.error|res\..*(?:json|send))\s*\(/.test(line)) {
|
|
89
|
+
if (/(?:\/home\/|\/var\/|\/usr\/|C:\\|D:\\|\/opt\/|__dirname|__filename)/i.test(line)) {
|
|
90
|
+
issues.push({
|
|
91
|
+
file: filepath,
|
|
92
|
+
line: i + 1,
|
|
93
|
+
issue: "Internal file path in error output",
|
|
94
|
+
severity: "medium",
|
|
95
|
+
detail: "Server filesystem path in error — reveals deployment structure to attacker",
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// SQL/DB error details sent to client
|
|
100
|
+
if (/catch\s*\(/.test(line)) {
|
|
101
|
+
const catchBlock = lines.slice(i, Math.min(i + 10, lines.length)).join("\n");
|
|
102
|
+
if (/(?:sql|query|database|ECONNREFUSED|ETIMEDOUT)/i.test(catchBlock)) {
|
|
103
|
+
if (/res\.(?:json|send|status)|response\.(?:json|send)/i.test(catchBlock)) {
|
|
104
|
+
if (/err\.message|error\.message|e\.message/i.test(catchBlock)) {
|
|
105
|
+
issues.push({
|
|
106
|
+
file: filepath,
|
|
107
|
+
line: i + 1,
|
|
108
|
+
issue: "Database error details sent to client",
|
|
109
|
+
severity: "high",
|
|
110
|
+
detail: "DB error message forwarded to response — may expose table names, SQL syntax, or connection info",
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Error message with jargon (internal codes exposed)
|
|
117
|
+
if (/(?:throw\s+new\s+Error|\.send|\.json)\s*\(/.test(line)) {
|
|
118
|
+
const msgMatch = line.match(/['"]([^'"]{10,})['"]/);
|
|
119
|
+
if (msgMatch) {
|
|
120
|
+
const msg = msgMatch[1];
|
|
121
|
+
if (/(?:ENOENT|EACCES|EPERM|SIGTERM|ENOMEM|OOM|segfault|null pointer|NullReferenceException)/i.test(msg)) {
|
|
122
|
+
issues.push({
|
|
123
|
+
file: filepath,
|
|
124
|
+
line: i + 1,
|
|
125
|
+
issue: "Technical jargon in user-facing error",
|
|
126
|
+
severity: "medium",
|
|
127
|
+
detail: `"${msg.slice(0, 50)}" — replace system-level jargon with plain language for end users`,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Empty catch blocks (silent failures)
|
|
133
|
+
if (/catch\s*\(\s*\w*\s*\)\s*\{\s*\}/.test(line) || /catch\s*\(\s*\w*\s*\)\s*\{\s*\/\//i.test(line)) {
|
|
134
|
+
issues.push({
|
|
135
|
+
file: filepath,
|
|
136
|
+
line: i + 1,
|
|
137
|
+
issue: "Silent error swallowing",
|
|
138
|
+
severity: "medium",
|
|
139
|
+
detail: "Empty catch block hides failures — log the error or surface a user-friendly message",
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
// HTTP status code mismatch
|
|
143
|
+
if (/res\.status\s*\(\s*(\d+)\s*\)/.test(line)) {
|
|
144
|
+
const statusMatch = line.match(/res\.status\s*\(\s*(\d+)\s*\)/);
|
|
145
|
+
const msgMatch2 = line.match(/['"]([^'"]+)['"]/);
|
|
146
|
+
if (statusMatch && msgMatch2) {
|
|
147
|
+
const status = parseInt(statusMatch[1], 10);
|
|
148
|
+
const msg = msgMatch2[1].toLowerCase();
|
|
149
|
+
if (status === 200 && /error|fail|invalid|denied/i.test(msg)) {
|
|
150
|
+
issues.push({
|
|
151
|
+
file: filepath,
|
|
152
|
+
line: i + 1,
|
|
153
|
+
issue: "Success status with error message",
|
|
154
|
+
severity: "medium",
|
|
155
|
+
detail: `HTTP 200 with error message "${msg.slice(0, 40)}" — use appropriate 4xx/5xx status code`,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
if (status === 500 && /not found|unauthorized|forbidden/i.test(msg)) {
|
|
159
|
+
issues.push({
|
|
160
|
+
file: filepath,
|
|
161
|
+
line: i + 1,
|
|
162
|
+
issue: "Incorrect HTTP status code",
|
|
163
|
+
severity: "low",
|
|
164
|
+
detail: `HTTP 500 for "${msg.slice(0, 30)}" — use 404/401/403 for client errors`,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Error without remediation hint
|
|
170
|
+
if (/throw\s+new\s+Error\s*\(\s*['"]([^'"]{15,})['"]\s*\)/.test(line)) {
|
|
171
|
+
const errMsg = line.match(/throw\s+new\s+Error\s*\(\s*['"]([^'"]+)['"]\s*\)/)?.[1] || "";
|
|
172
|
+
if (!/please|try|check|ensure|make sure|verify|see|refer|visit|use|run|set|configure|install/i.test(errMsg)) {
|
|
173
|
+
issues.push({
|
|
174
|
+
file: filepath,
|
|
175
|
+
line: i + 1,
|
|
176
|
+
issue: "Error without remediation hint",
|
|
177
|
+
severity: "low",
|
|
178
|
+
detail: `"${errMsg.slice(0, 50)}" — add guidance on how the user can resolve the issue`,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// Inconsistent error format (mix of throw/console.error/process.exit)
|
|
183
|
+
if (/process\.exit\s*\(\s*1\s*\)/.test(line)) {
|
|
184
|
+
const block = lines.slice(Math.max(0, i - 3), i + 1).join("\n");
|
|
185
|
+
if (!/console\.error|console\.log|logger|log\./i.test(block)) {
|
|
186
|
+
issues.push({
|
|
187
|
+
file: filepath,
|
|
188
|
+
line: i + 1,
|
|
189
|
+
issue: "process.exit without error message",
|
|
190
|
+
severity: "medium",
|
|
191
|
+
detail: "Process exits with code 1 but no error message — user sees nothing about what went wrong",
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return issues;
|
|
197
|
+
}
|
|
198
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
199
|
+
export function runErrorUx(argv) {
|
|
200
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
201
|
+
console.log(`
|
|
202
|
+
judges error-ux — Audit user-facing error messages for quality and safety
|
|
203
|
+
|
|
204
|
+
Usage:
|
|
205
|
+
judges error-ux [dir]
|
|
206
|
+
judges error-ux src/ --format json
|
|
207
|
+
|
|
208
|
+
Options:
|
|
209
|
+
[dir] Directory to scan (default: .)
|
|
210
|
+
--format json JSON output
|
|
211
|
+
--help, -h Show this help
|
|
212
|
+
|
|
213
|
+
Checks: generic messages, stack trace leaks, internal path exposure, DB error forwarding,
|
|
214
|
+
jargon in user errors, silent catch blocks, HTTP status mismatches, missing remediation hints.
|
|
215
|
+
`);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
219
|
+
const dir = argv.find((a) => !a.startsWith("-") && argv.indexOf(a) > 0) || ".";
|
|
220
|
+
const files = collectFiles(dir);
|
|
221
|
+
const allIssues = [];
|
|
222
|
+
for (const f of files)
|
|
223
|
+
allIssues.push(...analyzeFile(f));
|
|
224
|
+
const highCount = allIssues.filter((i) => i.severity === "high").length;
|
|
225
|
+
const medCount = allIssues.filter((i) => i.severity === "medium").length;
|
|
226
|
+
const score = Math.max(0, 100 - highCount * 8 - medCount * 3);
|
|
227
|
+
if (format === "json") {
|
|
228
|
+
console.log(JSON.stringify({
|
|
229
|
+
issues: allIssues,
|
|
230
|
+
score,
|
|
231
|
+
summary: { high: highCount, medium: medCount, total: allIssues.length },
|
|
232
|
+
timestamp: new Date().toISOString(),
|
|
233
|
+
}, null, 2));
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
const badge = score >= 80 ? "✅ CLEAR" : score >= 50 ? "⚠️ MIXED" : "❌ POOR";
|
|
237
|
+
console.log(`\n Error UX Quality: ${badge} (${score}/100)\n ─────────────────────────────`);
|
|
238
|
+
if (allIssues.length === 0) {
|
|
239
|
+
console.log(" No error UX issues detected.\n");
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
for (const issue of allIssues.slice(0, 25)) {
|
|
243
|
+
const icon = issue.severity === "high" ? "🔴" : issue.severity === "medium" ? "🟡" : "🔵";
|
|
244
|
+
console.log(` ${icon} ${issue.issue}`);
|
|
245
|
+
console.log(` ${issue.file}:${issue.line}`);
|
|
246
|
+
console.log(` ${issue.detail}`);
|
|
247
|
+
}
|
|
248
|
+
if (allIssues.length > 25)
|
|
249
|
+
console.log(` ... and ${allIssues.length - 25} more`);
|
|
250
|
+
console.log(`\n Total: ${allIssues.length} | High: ${highCount} | Medium: ${medCount} | Score: ${score}/100\n`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
//# sourceMappingURL=error-ux.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-ux.js","sourceRoot":"","sources":["../../src/commands/error-ux.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-leak.d.ts","sourceRoot":"","sources":["../../src/commands/event-leak.ts"],"names":[],"mappings":"AAAA;;GAEG;AAwOH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CA+DjD"}
|