@kevinrabun/judges 3.41.0 → 3.43.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 +30 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +126 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/assign-findings.d.ts +37 -0
- package/dist/commands/assign-findings.d.ts.map +1 -0
- package/dist/commands/assign-findings.js +178 -0
- package/dist/commands/assign-findings.js.map +1 -0
- package/dist/commands/auto-triage.d.ts +32 -0
- package/dist/commands/auto-triage.d.ts.map +1 -0
- package/dist/commands/auto-triage.js +126 -0
- package/dist/commands/auto-triage.js.map +1 -0
- package/dist/commands/ci-template.d.ts +15 -0
- package/dist/commands/ci-template.d.ts.map +1 -0
- package/dist/commands/ci-template.js +212 -0
- package/dist/commands/ci-template.js.map +1 -0
- package/dist/commands/coverage-map.d.ts +23 -0
- package/dist/commands/coverage-map.d.ts.map +1 -0
- package/dist/commands/coverage-map.js +223 -0
- package/dist/commands/coverage-map.js.map +1 -0
- package/dist/commands/diff-only.d.ts +34 -0
- package/dist/commands/diff-only.d.ts.map +1 -0
- package/dist/commands/diff-only.js +152 -0
- package/dist/commands/diff-only.js.map +1 -0
- package/dist/commands/false-negatives.d.ts +35 -0
- package/dist/commands/false-negatives.d.ts.map +1 -0
- package/dist/commands/false-negatives.js +166 -0
- package/dist/commands/false-negatives.js.map +1 -0
- package/dist/commands/group-findings.d.ts +23 -0
- package/dist/commands/group-findings.d.ts.map +1 -0
- package/dist/commands/group-findings.js +155 -0
- package/dist/commands/group-findings.js.map +1 -0
- package/dist/commands/hook-install.d.ts +22 -0
- package/dist/commands/hook-install.d.ts.map +1 -0
- package/dist/commands/hook-install.js +143 -0
- package/dist/commands/hook-install.js.map +1 -0
- package/dist/commands/policy-audit.d.ts +53 -0
- package/dist/commands/policy-audit.d.ts.map +1 -0
- package/dist/commands/policy-audit.js +161 -0
- package/dist/commands/policy-audit.js.map +1 -0
- package/dist/commands/pr-summary.d.ts +26 -0
- package/dist/commands/pr-summary.d.ts.map +1 -0
- package/dist/commands/pr-summary.js +188 -0
- package/dist/commands/pr-summary.js.map +1 -0
- package/dist/commands/profile.d.ts +38 -0
- package/dist/commands/profile.d.ts.map +1 -0
- package/dist/commands/profile.js +102 -0
- package/dist/commands/profile.js.map +1 -0
- package/dist/commands/regression-alert.d.ts +32 -0
- package/dist/commands/regression-alert.d.ts.map +1 -0
- package/dist/commands/regression-alert.js +216 -0
- package/dist/commands/regression-alert.js.map +1 -0
- package/dist/commands/remediation.d.ts +21 -0
- package/dist/commands/remediation.d.ts.map +1 -0
- package/dist/commands/remediation.js +257 -0
- package/dist/commands/remediation.js.map +1 -0
- package/dist/commands/sla-track.d.ts +57 -0
- package/dist/commands/sla-track.d.ts.map +1 -0
- package/dist/commands/sla-track.js +269 -0
- package/dist/commands/sla-track.js.map +1 -0
- package/dist/commands/smart-select.d.ts +27 -0
- package/dist/commands/smart-select.d.ts.map +1 -0
- package/dist/commands/smart-select.js +346 -0
- package/dist/commands/smart-select.js.map +1 -0
- package/dist/commands/ticket-sync.d.ts +26 -0
- package/dist/commands/ticket-sync.d.ts.map +1 -0
- package/dist/commands/ticket-sync.js +236 -0
- package/dist/commands/ticket-sync.js.map +1 -0
- package/dist/commands/upload.d.ts +14 -0
- package/dist/commands/upload.d.ts.map +1 -0
- package/dist/commands/upload.js +173 -0
- package/dist/commands/upload.js.map +1 -0
- package/dist/commands/validate-config.d.ts +17 -0
- package/dist/commands/validate-config.d.ts.map +1 -0
- package/dist/commands/validate-config.js +268 -0
- package/dist/commands/validate-config.js.map +1 -0
- package/dist/commands/warm-cache.d.ts +31 -0
- package/dist/commands/warm-cache.d.ts.map +1 -0
- package/dist/commands/warm-cache.js +166 -0
- package/dist/commands/warm-cache.js.map +1 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"false-negatives.js","sourceRoot":"","sources":["../../src/commands/false-negatives.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finding grouping — group related findings by category, file, or rule
|
|
3
|
+
* for better review UX and digest-style reporting.
|
|
4
|
+
*/
|
|
5
|
+
import type { Finding } from "../types.js";
|
|
6
|
+
export type GroupByKey = "category" | "severity" | "file" | "rule" | "judge";
|
|
7
|
+
export interface FindingGroup {
|
|
8
|
+
key: string;
|
|
9
|
+
label: string;
|
|
10
|
+
findings: Finding[];
|
|
11
|
+
count: number;
|
|
12
|
+
criticalCount: number;
|
|
13
|
+
highCount: number;
|
|
14
|
+
}
|
|
15
|
+
export interface GroupedReport {
|
|
16
|
+
groupBy: GroupByKey;
|
|
17
|
+
groups: FindingGroup[];
|
|
18
|
+
totalFindings: number;
|
|
19
|
+
totalGroups: number;
|
|
20
|
+
}
|
|
21
|
+
export declare function groupFindings(findings: Finding[], groupBy: GroupByKey): GroupedReport;
|
|
22
|
+
export declare function runGroupFindings(argv: string[]): void;
|
|
23
|
+
//# sourceMappingURL=group-findings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"group-findings.d.ts","sourceRoot":"","sources":["../../src/commands/group-findings.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAI3C,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE7E,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,UAAU,CAAC;IACpB,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;CACrB;AA4ED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,UAAU,GAAG,aAAa,CA2BrF;AAID,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAmErD"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finding grouping — group related findings by category, file, or rule
|
|
3
|
+
* for better review UX and digest-style reporting.
|
|
4
|
+
*/
|
|
5
|
+
// ─── Category Classification ────────────────────────────────────────────────
|
|
6
|
+
const RULE_CATEGORIES = {
|
|
7
|
+
// Security
|
|
8
|
+
"SEC-": "Security",
|
|
9
|
+
"AUTH-": "Authentication",
|
|
10
|
+
"CRYPTO-": "Cryptography",
|
|
11
|
+
"INJECT-": "Injection",
|
|
12
|
+
"XSS-": "Cross-Site Scripting",
|
|
13
|
+
"SSRF-": "Server-Side Request Forgery",
|
|
14
|
+
"IDOR-": "Broken Access Control",
|
|
15
|
+
// Quality
|
|
16
|
+
"PERF-": "Performance",
|
|
17
|
+
"ERR-": "Error Handling",
|
|
18
|
+
"LOG-": "Logging",
|
|
19
|
+
"TEST-": "Testing",
|
|
20
|
+
"DOC-": "Documentation",
|
|
21
|
+
"MAINT-": "Maintainability",
|
|
22
|
+
"STRUCT-": "Code Structure",
|
|
23
|
+
// Reliability
|
|
24
|
+
"CONCUR-": "Concurrency",
|
|
25
|
+
"RACE-": "Race Conditions",
|
|
26
|
+
"SCALE-": "Scalability",
|
|
27
|
+
"CACHE-": "Caching",
|
|
28
|
+
"RATE-": "Rate Limiting",
|
|
29
|
+
// Compliance
|
|
30
|
+
"COMPLY-": "Compliance",
|
|
31
|
+
"DATA-": "Data Protection",
|
|
32
|
+
"PII-": "Privacy",
|
|
33
|
+
// AI
|
|
34
|
+
"AI-": "AI Safety",
|
|
35
|
+
"HALLUC-": "Hallucination",
|
|
36
|
+
"FW-": "Framework Safety",
|
|
37
|
+
// Infrastructure
|
|
38
|
+
"IAC-": "Infrastructure as Code",
|
|
39
|
+
"CICD-": "CI/CD",
|
|
40
|
+
"CLOUD-": "Cloud Readiness",
|
|
41
|
+
"DB-": "Database",
|
|
42
|
+
// Accessibility / UX
|
|
43
|
+
"A11Y-": "Accessibility",
|
|
44
|
+
"I18N-": "Internationalization",
|
|
45
|
+
"UX-": "User Experience",
|
|
46
|
+
};
|
|
47
|
+
function classifyRule(ruleId) {
|
|
48
|
+
for (const [prefix, category] of Object.entries(RULE_CATEGORIES)) {
|
|
49
|
+
if (ruleId.toUpperCase().startsWith(prefix))
|
|
50
|
+
return category;
|
|
51
|
+
}
|
|
52
|
+
return "Other";
|
|
53
|
+
}
|
|
54
|
+
// ─── Grouping Logic ─────────────────────────────────────────────────────────
|
|
55
|
+
function getGroupKey(finding, groupBy) {
|
|
56
|
+
switch (groupBy) {
|
|
57
|
+
case "category":
|
|
58
|
+
return classifyRule(finding.ruleId);
|
|
59
|
+
case "severity":
|
|
60
|
+
return finding.severity;
|
|
61
|
+
case "file":
|
|
62
|
+
return "(grouped)";
|
|
63
|
+
case "rule":
|
|
64
|
+
return finding.ruleId;
|
|
65
|
+
case "judge":
|
|
66
|
+
return finding.judgeId || "(unknown)";
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export function groupFindings(findings, groupBy) {
|
|
70
|
+
const groups = new Map();
|
|
71
|
+
for (const f of findings) {
|
|
72
|
+
const key = getGroupKey(f, groupBy);
|
|
73
|
+
const arr = groups.get(key) || [];
|
|
74
|
+
arr.push(f);
|
|
75
|
+
groups.set(key, arr);
|
|
76
|
+
}
|
|
77
|
+
const sortedGroups = [...groups.entries()]
|
|
78
|
+
.map(([key, items]) => ({
|
|
79
|
+
key,
|
|
80
|
+
label: key,
|
|
81
|
+
findings: items,
|
|
82
|
+
count: items.length,
|
|
83
|
+
criticalCount: items.filter((f) => f.severity === "critical").length,
|
|
84
|
+
highCount: items.filter((f) => f.severity === "high").length,
|
|
85
|
+
}))
|
|
86
|
+
.sort((a, b) => b.criticalCount - a.criticalCount || b.highCount - a.highCount || b.count - a.count);
|
|
87
|
+
return {
|
|
88
|
+
groupBy,
|
|
89
|
+
groups: sortedGroups,
|
|
90
|
+
totalFindings: findings.length,
|
|
91
|
+
totalGroups: sortedGroups.length,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
95
|
+
export function runGroupFindings(argv) {
|
|
96
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
97
|
+
console.log(`
|
|
98
|
+
judges group — Group findings by category, severity, file, rule, or judge
|
|
99
|
+
|
|
100
|
+
Usage:
|
|
101
|
+
judges group --input results.json Group by category (default)
|
|
102
|
+
judges group --input results.json --by severity Group by severity
|
|
103
|
+
judges group --input results.json --by file Group by file
|
|
104
|
+
|
|
105
|
+
Options:
|
|
106
|
+
--input <path> Path to JSON results file (required)
|
|
107
|
+
--by <key> Group by: category, severity, file, rule, judge (default: category)
|
|
108
|
+
--format json JSON output
|
|
109
|
+
--help, -h Show this help
|
|
110
|
+
`);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const { readFileSync, existsSync } = require("fs");
|
|
114
|
+
const inputPath = argv.find((_a, i) => argv[i - 1] === "--input");
|
|
115
|
+
if (!inputPath || !existsSync(inputPath)) {
|
|
116
|
+
console.error("Error: --input <path> required (JSON results file)");
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
const byArg = argv.find((_a, i) => argv[i - 1] === "--by") || "category";
|
|
120
|
+
const validKeys = new Set(["category", "severity", "file", "rule", "judge"]);
|
|
121
|
+
if (!validKeys.has(byArg)) {
|
|
122
|
+
console.error(`Error: --by must be one of: ${[...validKeys].join(", ")}`);
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
126
|
+
const data = JSON.parse(readFileSync(inputPath, "utf-8"));
|
|
127
|
+
const findings = data.evaluations
|
|
128
|
+
? data.evaluations.flatMap((e) => e.findings || [])
|
|
129
|
+
: data.findings || data;
|
|
130
|
+
const report = groupFindings(findings, byArg);
|
|
131
|
+
if (format === "json") {
|
|
132
|
+
console.log(JSON.stringify(report, null, 2));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
console.log(`\n Findings Grouped by ${report.groupBy}\n`);
|
|
136
|
+
console.log(` Total: ${report.totalFindings} findings in ${report.totalGroups} groups\n`);
|
|
137
|
+
for (const g of report.groups) {
|
|
138
|
+
const badges = [];
|
|
139
|
+
if (g.criticalCount > 0)
|
|
140
|
+
badges.push(`🔴 ${g.criticalCount} critical`);
|
|
141
|
+
if (g.highCount > 0)
|
|
142
|
+
badges.push(`🟠 ${g.highCount} high`);
|
|
143
|
+
const badge = badges.length > 0 ? ` (${badges.join(", ")})` : "";
|
|
144
|
+
console.log(` 📁 ${g.label} — ${g.count} findings${badge}`);
|
|
145
|
+
for (const f of g.findings.slice(0, 5)) {
|
|
146
|
+
const loc = f.lineNumbers?.length ? `:${f.lineNumbers[0]}` : "";
|
|
147
|
+
console.log(` ${f.severity.padEnd(8)} ${f.ruleId}: ${f.title.slice(0, 80)}${loc}`);
|
|
148
|
+
}
|
|
149
|
+
if (g.findings.length > 5) {
|
|
150
|
+
console.log(` ... and ${g.findings.length - 5} more`);
|
|
151
|
+
}
|
|
152
|
+
console.log("");
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=group-findings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"group-findings.js","sourceRoot":"","sources":["../../src/commands/group-findings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook install — install and configure git hooks for pre-commit
|
|
3
|
+
* and pre-push evaluation with Judges.
|
|
4
|
+
*
|
|
5
|
+
* Supports husky, simple-git-hooks, and direct .git/hooks installation.
|
|
6
|
+
*/
|
|
7
|
+
export interface HookConfig {
|
|
8
|
+
/** Hook type: pre-commit or pre-push */
|
|
9
|
+
hook: "pre-commit" | "pre-push";
|
|
10
|
+
/** Only evaluate staged files */
|
|
11
|
+
stagedOnly: boolean;
|
|
12
|
+
/** Fail on findings of this severity or higher */
|
|
13
|
+
failSeverity: string;
|
|
14
|
+
/** Timeout in seconds */
|
|
15
|
+
timeout: number;
|
|
16
|
+
/** Run in parallel */
|
|
17
|
+
parallel: boolean;
|
|
18
|
+
/** Use smart judge selection */
|
|
19
|
+
smartSelect: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare function runHookInstall(argv: string[]): void;
|
|
22
|
+
//# sourceMappingURL=hook-install.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-install.d.ts","sourceRoot":"","sources":["../../src/commands/hook-install.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,UAAU;IACzB,wCAAwC;IACxC,IAAI,EAAE,YAAY,GAAG,UAAU,CAAC;IAChC,iCAAiC;IACjC,UAAU,EAAE,OAAO,CAAC;IACpB,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,sBAAsB;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,gCAAgC;IAChC,WAAW,EAAE,OAAO,CAAC;CACtB;AAoFD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAoEnD"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook install — install and configure git hooks for pre-commit
|
|
3
|
+
* and pre-push evaluation with Judges.
|
|
4
|
+
*
|
|
5
|
+
* Supports husky, simple-git-hooks, and direct .git/hooks installation.
|
|
6
|
+
*/
|
|
7
|
+
// ─── Hook Scripts ───────────────────────────────────────────────────────────
|
|
8
|
+
function generateHookScript(config) {
|
|
9
|
+
const flags = [];
|
|
10
|
+
if (config.stagedOnly)
|
|
11
|
+
flags.push("--staged-only");
|
|
12
|
+
if (config.failSeverity !== "info")
|
|
13
|
+
flags.push(`--min-severity ${config.failSeverity}`);
|
|
14
|
+
flags.push("--fail-on-findings");
|
|
15
|
+
flags.push("--summary");
|
|
16
|
+
return `#!/bin/sh
|
|
17
|
+
# Judges ${config.hook} hook
|
|
18
|
+
# Auto-generated by: judges hook-install
|
|
19
|
+
|
|
20
|
+
# Skip if JUDGES_SKIP_HOOK is set
|
|
21
|
+
if [ -n "$JUDGES_SKIP_HOOK" ]; then
|
|
22
|
+
echo "Judges: hook skipped (JUDGES_SKIP_HOOK is set)"
|
|
23
|
+
exit 0
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# Timeout protection (${config.timeout}s)
|
|
27
|
+
timeout_cmd=""
|
|
28
|
+
if command -v timeout > /dev/null 2>&1; then
|
|
29
|
+
timeout_cmd="timeout ${config.timeout}"
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
echo "🔍 Judges: evaluating..."
|
|
33
|
+
$timeout_cmd npx judges eval ${flags.join(" ")} 2>&1
|
|
34
|
+
exit_code=$?
|
|
35
|
+
|
|
36
|
+
if [ $exit_code -ne 0 ] && [ $exit_code -ne 124 ]; then
|
|
37
|
+
echo ""
|
|
38
|
+
echo "❌ Judges: findings detected. Fix or skip with JUDGES_SKIP_HOOK=1"
|
|
39
|
+
exit 1
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
if [ $exit_code -eq 124 ]; then
|
|
43
|
+
echo "⚠️ Judges: evaluation timed out (${config.timeout}s). Proceeding."
|
|
44
|
+
fi
|
|
45
|
+
`;
|
|
46
|
+
}
|
|
47
|
+
// ─── Installation Methods ───────────────────────────────────────────────────
|
|
48
|
+
function installDirect(hookType, script) {
|
|
49
|
+
const { writeFileSync, mkdirSync, chmodSync, existsSync } = require("fs");
|
|
50
|
+
const { join } = require("path");
|
|
51
|
+
const hooksDir = join(".git", "hooks");
|
|
52
|
+
if (!existsSync(".git")) {
|
|
53
|
+
console.error("Error: not a git repository");
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
mkdirSync(hooksDir, { recursive: true });
|
|
57
|
+
const hookPath = join(hooksDir, hookType);
|
|
58
|
+
writeFileSync(hookPath, script, { mode: 0o755 });
|
|
59
|
+
try {
|
|
60
|
+
chmodSync(hookPath, 0o755);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
/* Windows */
|
|
64
|
+
}
|
|
65
|
+
console.log(` ✅ Installed ${hookPath}`);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
function installHusky(hookType, script) {
|
|
69
|
+
const { existsSync, writeFileSync, mkdirSync } = require("fs");
|
|
70
|
+
const { join } = require("path");
|
|
71
|
+
if (!existsSync(".husky")) {
|
|
72
|
+
console.log(" Husky directory not found. Creating .husky/");
|
|
73
|
+
mkdirSync(".husky", { recursive: true });
|
|
74
|
+
}
|
|
75
|
+
const hookPath = join(".husky", hookType);
|
|
76
|
+
writeFileSync(hookPath, script, { mode: 0o755 });
|
|
77
|
+
console.log(` ✅ Installed ${hookPath} (husky)`);
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
81
|
+
export function runHookInstall(argv) {
|
|
82
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
83
|
+
console.log(`
|
|
84
|
+
judges hook-install — Install git hooks for automatic code review
|
|
85
|
+
|
|
86
|
+
Usage:
|
|
87
|
+
judges hook-install Install pre-commit hook
|
|
88
|
+
judges hook-install --hook pre-push Install pre-push hook
|
|
89
|
+
judges hook-install --method husky Use husky for hook management
|
|
90
|
+
|
|
91
|
+
Options:
|
|
92
|
+
--hook <type> Hook type: pre-commit (default) or pre-push
|
|
93
|
+
--method <method> Installation: direct (default), husky
|
|
94
|
+
--severity <level> Fail on findings of this severity+ (default: high)
|
|
95
|
+
--timeout <seconds> Timeout in seconds (default: 60)
|
|
96
|
+
--no-staged-only Evaluate all files, not just staged
|
|
97
|
+
--uninstall Remove the hook
|
|
98
|
+
--show Show current hook script without installing
|
|
99
|
+
--help, -h Show this help
|
|
100
|
+
|
|
101
|
+
Environment:
|
|
102
|
+
JUDGES_SKIP_HOOK=1 Skip the hook for a single commit
|
|
103
|
+
`);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const hookType = (argv.find((_a, i) => argv[i - 1] === "--hook") || "pre-commit");
|
|
107
|
+
const method = argv.find((_a, i) => argv[i - 1] === "--method") || "direct";
|
|
108
|
+
const severity = argv.find((_a, i) => argv[i - 1] === "--severity") || "high";
|
|
109
|
+
const timeoutStr = argv.find((_a, i) => argv[i - 1] === "--timeout");
|
|
110
|
+
const timeout = timeoutStr ? parseInt(timeoutStr, 10) : 60;
|
|
111
|
+
if (argv.includes("--uninstall")) {
|
|
112
|
+
const { unlinkSync, existsSync } = require("fs");
|
|
113
|
+
const { join } = require("path");
|
|
114
|
+
const paths = [join(".git", "hooks", hookType), join(".husky", hookType)];
|
|
115
|
+
for (const p of paths) {
|
|
116
|
+
if (existsSync(p)) {
|
|
117
|
+
unlinkSync(p);
|
|
118
|
+
console.log(` ✅ Removed ${p}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const config = {
|
|
124
|
+
hook: hookType,
|
|
125
|
+
stagedOnly: !argv.includes("--no-staged-only"),
|
|
126
|
+
failSeverity: severity,
|
|
127
|
+
timeout,
|
|
128
|
+
parallel: true,
|
|
129
|
+
smartSelect: true,
|
|
130
|
+
};
|
|
131
|
+
const script = generateHookScript(config);
|
|
132
|
+
if (argv.includes("--show")) {
|
|
133
|
+
console.log(script);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (method === "husky") {
|
|
137
|
+
installHusky(hookType, script);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
installDirect(hookType, script);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=hook-install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-install.js","sourceRoot":"","sources":["../../src/commands/hook-install.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAmBH,+EAA+E;AAE/E,SAAS,kBAAkB,CAAC,MAAkB;IAC5C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,MAAM,CAAC,UAAU;QAAE,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACnD,IAAI,MAAM,CAAC,YAAY,KAAK,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,kBAAkB,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;IACxF,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACjC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAExB,OAAO;WACE,MAAM,CAAC,IAAI;;;;;;;;;wBASE,MAAM,CAAC,OAAO;;;yBAGb,MAAM,CAAC,OAAO;;;;+BAIR,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;;;;;;;;;;4CAUF,MAAM,CAAC,OAAO;;CAEzD,CAAC;AACF,CAAC;AAED,+EAA+E;AAE/E,SAAS,aAAa,CAAC,QAAgB,EAAE,MAAc;IACrD,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEjC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAC7C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC1C,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACjD,IAAI,CAAC;QACH,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,aAAa;IACf,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,iBAAiB,QAAQ,EAAE,CAAC,CAAC;IACzC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,YAAY,CAAC,QAAgB,EAAE,MAAc;IACpD,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEjC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;QAC7D,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC1C,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,iBAAiB,QAAQ,UAAU,CAAC,CAAC;IACjD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,cAAc,CAAC,IAAc;IAC3C,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;CAoBf,CAAC,CAAC;QACC,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,QAAQ,CAAC,IAAI,YAAY,CAElF,CAAC;IACf,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU,CAAC,IAAI,QAAQ,CAAC;IAC5F,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,YAAY,CAAC,IAAI,MAAM,CAAC;IAC9F,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC;IACrF,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAE3D,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QACjC,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QACjC,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC1E,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;gBAClB,UAAU,CAAC,CAAC,CAAC,CAAC;gBACd,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;QACD,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAe;QACzB,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QAC9C,YAAY,EAAE,QAAQ;QACtB,OAAO;QACP,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,IAAI;KAClB,CAAC;IAEF,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAE1C,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpB,OAAO;IACT,CAAC;IAED,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;QACvB,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACjC,CAAC;SAAM,CAAC;QACN,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAClC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy audit trail — record which rules/judges were active at evaluation
|
|
3
|
+
* time, creating an immutable local audit log for compliance proof.
|
|
4
|
+
*
|
|
5
|
+
* Enables SOC2/ISO27001 auditors to verify that security policies were
|
|
6
|
+
* enforced at the time of each evaluation. All data stays local.
|
|
7
|
+
*/
|
|
8
|
+
import type { TribunalVerdict, JudgesConfig } from "../types.js";
|
|
9
|
+
export interface PolicySnapshot {
|
|
10
|
+
/** SHA-256 hash of the combined policy state */
|
|
11
|
+
policyHash: string;
|
|
12
|
+
/** ISO timestamp */
|
|
13
|
+
timestamp: string;
|
|
14
|
+
/** Config file path */
|
|
15
|
+
configPath: string;
|
|
16
|
+
/** Active preset(s) */
|
|
17
|
+
presets: string[];
|
|
18
|
+
/** Judges that were enabled */
|
|
19
|
+
enabledJudges: string[];
|
|
20
|
+
/** Judges that were disabled */
|
|
21
|
+
disabledJudges: string[];
|
|
22
|
+
/** Disabled rules */
|
|
23
|
+
disabledRules: string[];
|
|
24
|
+
/** Rule overrides */
|
|
25
|
+
ruleOverrides: Record<string, unknown>;
|
|
26
|
+
/** Min severity threshold */
|
|
27
|
+
minSeverity: string;
|
|
28
|
+
/** Git commit at evaluation time */
|
|
29
|
+
gitCommit?: string;
|
|
30
|
+
/** Evaluator version */
|
|
31
|
+
version: string;
|
|
32
|
+
}
|
|
33
|
+
export interface AuditEntry {
|
|
34
|
+
id: string;
|
|
35
|
+
timestamp: string;
|
|
36
|
+
policySnapshot: PolicySnapshot;
|
|
37
|
+
verdictSummary: {
|
|
38
|
+
verdict: string;
|
|
39
|
+
score: number;
|
|
40
|
+
criticalCount: number;
|
|
41
|
+
highCount: number;
|
|
42
|
+
totalFindings: number;
|
|
43
|
+
};
|
|
44
|
+
filesEvaluated: number;
|
|
45
|
+
}
|
|
46
|
+
export interface AuditLog {
|
|
47
|
+
entries: AuditEntry[];
|
|
48
|
+
version: string;
|
|
49
|
+
}
|
|
50
|
+
export declare function capturePolicySnapshot(config: JudgesConfig, configPath: string, enabledJudges: string[], version: string): PolicySnapshot;
|
|
51
|
+
export declare function recordAuditEntry(policySnapshot: PolicySnapshot, verdict: TribunalVerdict, filesEvaluated: number): AuditEntry;
|
|
52
|
+
export declare function runPolicyAudit(argv: string[]): void;
|
|
53
|
+
//# sourceMappingURL=policy-audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-audit.d.ts","sourceRoot":"","sources":["../../src/commands/policy-audit.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIjE,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,uBAAuB;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,uBAAuB;IACvB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,+BAA+B;IAC/B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gCAAgC;IAChC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,qBAAqB;IACrB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,qBAAqB;IACrB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,EAAE;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAID,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EAAE,EACvB,OAAO,EAAE,MAAM,GACd,cAAc,CAoChB;AAuBD,wBAAgB,gBAAgB,CAC9B,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE,eAAe,EACxB,cAAc,EAAE,MAAM,GACrB,UAAU,CA4BZ;AAID,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAgFnD"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy audit trail — record which rules/judges were active at evaluation
|
|
3
|
+
* time, creating an immutable local audit log for compliance proof.
|
|
4
|
+
*
|
|
5
|
+
* Enables SOC2/ISO27001 auditors to verify that security policies were
|
|
6
|
+
* enforced at the time of each evaluation. All data stays local.
|
|
7
|
+
*/
|
|
8
|
+
import { createHash } from "crypto";
|
|
9
|
+
// ─── Policy Snapshot ────────────────────────────────────────────────────────
|
|
10
|
+
export function capturePolicySnapshot(config, configPath, enabledJudges, version) {
|
|
11
|
+
const { execSync } = require("child_process");
|
|
12
|
+
let gitCommit;
|
|
13
|
+
try {
|
|
14
|
+
gitCommit = execSync("git rev-parse HEAD", { encoding: "utf-8" }).trim();
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
/* not in git */
|
|
18
|
+
}
|
|
19
|
+
const snapshot = {
|
|
20
|
+
policyHash: "",
|
|
21
|
+
timestamp: new Date().toISOString(),
|
|
22
|
+
configPath,
|
|
23
|
+
presets: config.preset ? [config.preset] : [],
|
|
24
|
+
enabledJudges,
|
|
25
|
+
disabledJudges: config.disabledJudges || [],
|
|
26
|
+
disabledRules: config.disabledRules || [],
|
|
27
|
+
ruleOverrides: config.ruleOverrides || {},
|
|
28
|
+
minSeverity: config.minSeverity || "info",
|
|
29
|
+
gitCommit,
|
|
30
|
+
version,
|
|
31
|
+
};
|
|
32
|
+
// Compute deterministic hash of policy state
|
|
33
|
+
const hashInput = JSON.stringify({
|
|
34
|
+
presets: snapshot.presets,
|
|
35
|
+
enabledJudges: snapshot.enabledJudges.sort(),
|
|
36
|
+
disabledJudges: snapshot.disabledJudges.sort(),
|
|
37
|
+
disabledRules: snapshot.disabledRules.sort(),
|
|
38
|
+
ruleOverrides: snapshot.ruleOverrides,
|
|
39
|
+
minSeverity: snapshot.minSeverity,
|
|
40
|
+
});
|
|
41
|
+
snapshot.policyHash = createHash("sha256").update(hashInput).digest("hex").slice(0, 16);
|
|
42
|
+
return snapshot;
|
|
43
|
+
}
|
|
44
|
+
// ─── Audit Log Management ──────────────────────────────────────────────────
|
|
45
|
+
const AUDIT_FILE = ".judges-audit.json";
|
|
46
|
+
function loadAuditLog() {
|
|
47
|
+
const { readFileSync, existsSync } = require("fs");
|
|
48
|
+
if (existsSync(AUDIT_FILE)) {
|
|
49
|
+
try {
|
|
50
|
+
return JSON.parse(readFileSync(AUDIT_FILE, "utf-8"));
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
/* corrupt file */
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return { entries: [], version: "1.0" };
|
|
57
|
+
}
|
|
58
|
+
function saveAuditLog(log) {
|
|
59
|
+
const { writeFileSync } = require("fs");
|
|
60
|
+
writeFileSync(AUDIT_FILE, JSON.stringify(log, null, 2), "utf-8");
|
|
61
|
+
}
|
|
62
|
+
export function recordAuditEntry(policySnapshot, verdict, filesEvaluated) {
|
|
63
|
+
const entry = {
|
|
64
|
+
id: createHash("sha256")
|
|
65
|
+
.update(policySnapshot.timestamp + policySnapshot.policyHash)
|
|
66
|
+
.digest("hex")
|
|
67
|
+
.slice(0, 12),
|
|
68
|
+
timestamp: policySnapshot.timestamp,
|
|
69
|
+
policySnapshot,
|
|
70
|
+
verdictSummary: {
|
|
71
|
+
verdict: verdict.overallVerdict,
|
|
72
|
+
score: verdict.overallScore,
|
|
73
|
+
criticalCount: verdict.criticalCount,
|
|
74
|
+
highCount: verdict.highCount,
|
|
75
|
+
totalFindings: verdict.findings.length,
|
|
76
|
+
},
|
|
77
|
+
filesEvaluated,
|
|
78
|
+
};
|
|
79
|
+
const log = loadAuditLog();
|
|
80
|
+
log.entries.push(entry);
|
|
81
|
+
// Keep last 1000 entries
|
|
82
|
+
if (log.entries.length > 1000) {
|
|
83
|
+
log.entries = log.entries.slice(-1000);
|
|
84
|
+
}
|
|
85
|
+
saveAuditLog(log);
|
|
86
|
+
return entry;
|
|
87
|
+
}
|
|
88
|
+
// ─── CLI ────────────────────────────────────────────────────────────────────
|
|
89
|
+
export function runPolicyAudit(argv) {
|
|
90
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
91
|
+
console.log(`
|
|
92
|
+
judges policy-audit — View and manage the policy audit trail
|
|
93
|
+
|
|
94
|
+
Usage:
|
|
95
|
+
judges policy-audit Show recent audit entries
|
|
96
|
+
judges policy-audit --last 10 Show last 10 entries
|
|
97
|
+
judges policy-audit --diff Compare current policy to last evaluation
|
|
98
|
+
judges policy-audit --export audit.json Export full audit log
|
|
99
|
+
|
|
100
|
+
Options:
|
|
101
|
+
--last <n> Show last N entries (default: 5)
|
|
102
|
+
--diff Show policy changes since last evaluation
|
|
103
|
+
--export <path> Export audit log to file
|
|
104
|
+
--format json JSON output
|
|
105
|
+
--help, -h Show this help
|
|
106
|
+
|
|
107
|
+
The audit trail records which rules, judges, and configs were active at
|
|
108
|
+
each evaluation time. Useful for SOC2/ISO27001 compliance proof.
|
|
109
|
+
`);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const { readFileSync, existsSync, writeFileSync } = require("fs");
|
|
113
|
+
const format = argv.find((_a, i) => argv[i - 1] === "--format") || "text";
|
|
114
|
+
const lastN = parseInt(argv.find((_a, i) => argv[i - 1] === "--last") || "5", 10);
|
|
115
|
+
const exportPath = argv.find((_a, i) => argv[i - 1] === "--export");
|
|
116
|
+
if (!existsSync(AUDIT_FILE)) {
|
|
117
|
+
console.log("\n No audit trail found. Run an evaluation first.\n");
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const log = JSON.parse(readFileSync(AUDIT_FILE, "utf-8"));
|
|
121
|
+
if (exportPath) {
|
|
122
|
+
writeFileSync(exportPath, JSON.stringify(log, null, 2), "utf-8");
|
|
123
|
+
console.log(` Exported ${log.entries.length} audit entries to ${exportPath}`);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const entries = log.entries.slice(-lastN);
|
|
127
|
+
if (format === "json") {
|
|
128
|
+
console.log(JSON.stringify(entries, null, 2));
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (argv.includes("--diff") && log.entries.length >= 2) {
|
|
132
|
+
const prev = log.entries[log.entries.length - 2].policySnapshot;
|
|
133
|
+
const curr = log.entries[log.entries.length - 1].policySnapshot;
|
|
134
|
+
console.log("\n Policy Diff (last two evaluations)\n");
|
|
135
|
+
if (prev.policyHash !== curr.policyHash) {
|
|
136
|
+
console.log(" ⚠️ Policy changed!\n");
|
|
137
|
+
const addedJudges = curr.enabledJudges.filter((j) => !prev.enabledJudges.includes(j));
|
|
138
|
+
const removedJudges = prev.enabledJudges.filter((j) => !curr.enabledJudges.includes(j));
|
|
139
|
+
if (addedJudges.length)
|
|
140
|
+
console.log(` + Added judges: ${addedJudges.join(", ")}`);
|
|
141
|
+
if (removedJudges.length)
|
|
142
|
+
console.log(` - Removed judges: ${removedJudges.join(", ")}`);
|
|
143
|
+
if (prev.minSeverity !== curr.minSeverity)
|
|
144
|
+
console.log(` ~ Severity: ${prev.minSeverity} → ${curr.minSeverity}`);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
console.log(" ✅ No policy changes\n");
|
|
148
|
+
}
|
|
149
|
+
console.log("");
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
console.log(`\n Policy Audit Trail (last ${entries.length} of ${log.entries.length})\n`);
|
|
153
|
+
for (const e of entries) {
|
|
154
|
+
const v = e.verdictSummary;
|
|
155
|
+
console.log(` ${e.id} ${e.timestamp}`);
|
|
156
|
+
console.log(` Policy: ${e.policySnapshot.policyHash} Judges: ${e.policySnapshot.enabledJudges.length} Commit: ${e.policySnapshot.gitCommit?.slice(0, 8) || "N/A"}`);
|
|
157
|
+
console.log(` Verdict: ${v.verdict} Score: ${v.score} Critical: ${v.criticalCount} High: ${v.highCount} Findings: ${v.totalFindings}`);
|
|
158
|
+
console.log("");
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=policy-audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-audit.js","sourceRoot":"","sources":["../../src/commands/policy-audit.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAiDpC,+EAA+E;AAE/E,MAAM,UAAU,qBAAqB,CACnC,MAAoB,EACpB,UAAkB,EAClB,aAAuB,EACvB,OAAe;IAEf,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAE9C,IAAI,SAA6B,CAAC;IAClC,IAAI,CAAC;QACH,SAAS,GAAG,QAAQ,CAAC,oBAAoB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,gBAAgB;IAClB,CAAC;IAED,MAAM,QAAQ,GAAmB;QAC/B,UAAU,EAAE,EAAE;QACd,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,UAAU;QACV,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;QAC7C,aAAa;QACb,cAAc,EAAE,MAAM,CAAC,cAAc,IAAI,EAAE;QAC3C,aAAa,EAAE,MAAM,CAAC,aAAa,IAAI,EAAE;QACzC,aAAa,EAAE,MAAM,CAAC,aAAa,IAAI,EAAE;QACzC,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,MAAM;QACzC,SAAS;QACT,OAAO;KACR,CAAC;IAEF,6CAA6C;IAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAC/B,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,aAAa,EAAE,QAAQ,CAAC,aAAa,CAAC,IAAI,EAAE;QAC5C,cAAc,EAAE,QAAQ,CAAC,cAAc,CAAC,IAAI,EAAE;QAC9C,aAAa,EAAE,QAAQ,CAAC,aAAa,CAAC,IAAI,EAAE;QAC5C,aAAa,EAAE,QAAQ,CAAC,aAAa;QACrC,WAAW,EAAE,QAAQ,CAAC,WAAW;KAClC,CAAC,CAAC;IACH,QAAQ,CAAC,UAAU,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAExF,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,8EAA8E;AAE9E,MAAM,UAAU,GAAG,oBAAoB,CAAC;AAExC,SAAS,YAAY;IACnB,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,kBAAkB;QACpB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AACzC,CAAC;AAED,SAAS,YAAY,CAAC,GAAa;IACjC,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,cAA8B,EAC9B,OAAwB,EACxB,cAAsB;IAEtB,MAAM,KAAK,GAAe;QACxB,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC;aACrB,MAAM,CAAC,cAAc,CAAC,SAAS,GAAG,cAAc,CAAC,UAAU,CAAC;aAC5D,MAAM,CAAC,KAAK,CAAC;aACb,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;QACf,SAAS,EAAE,cAAc,CAAC,SAAS;QACnC,cAAc;QACd,cAAc,EAAE;YACd,OAAO,EAAE,OAAO,CAAC,cAAc;YAC/B,KAAK,EAAE,OAAO,CAAC,YAAY;YAC3B,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,aAAa,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM;SACvC;QACD,cAAc;KACf,CAAC;IAEF,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;IAC3B,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAExB,yBAAyB;IACzB,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;QAC9B,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,YAAY,CAAC,GAAG,CAAC,CAAC;IAClB,OAAO,KAAK,CAAC;AACf,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,cAAc,CAAC,IAAc;IAC3C,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;CAkBf,CAAC,CAAC;QACC,OAAO;IACT,CAAC;IAED,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU,CAAC,IAAI,MAAM,CAAC;IAC1F,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,QAAQ,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;IAClG,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC;IAEpF,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;QACpE,OAAO;IACT,CAAC;IAED,MAAM,GAAG,GAAa,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;IAEpE,IAAI,UAAU,EAAE,CAAC;QACf,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,OAAO,CAAC,MAAM,qBAAqB,UAAU,EAAE,CAAC,CAAC;QAC/E,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;IAE1C,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC9C,OAAO;IACT,CAAC;IAED,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACvD,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC;QAChE,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC;QAEhE,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;QACxD,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,UAAU,EAAE,CAAC;YACxC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;YACvC,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9F,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;YAChG,IAAI,WAAW,CAAC,MAAM;gBAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACnF,IAAI,aAAa,CAAC,MAAM;gBAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACzF,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,WAAW;gBAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,CAAC,WAAW,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QACpH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,gCAAgC,OAAO,CAAC,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC;IAC1F,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CACT,eAAe,CAAC,CAAC,cAAc,CAAC,UAAU,aAAa,CAAC,CAAC,cAAc,CAAC,aAAa,CAAC,MAAM,aAAa,CAAC,CAAC,cAAc,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,EAAE,CAC5J,CAAC;QACF,OAAO,CAAC,GAAG,CACT,gBAAgB,CAAC,CAAC,OAAO,YAAY,CAAC,CAAC,KAAK,eAAe,CAAC,CAAC,aAAa,WAAW,CAAC,CAAC,SAAS,eAAe,CAAC,CAAC,aAAa,EAAE,CACjI,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PR summary comment — post a top-level comment on a GitHub PR
|
|
3
|
+
* with the overall Judges verdict, score, and finding counts.
|
|
4
|
+
*
|
|
5
|
+
* Uses the GitHub API to create or update a comment with a distinctive
|
|
6
|
+
* marker so subsequent runs update in-place rather than spamming.
|
|
7
|
+
*/
|
|
8
|
+
import type { TribunalVerdict } from "../types.js";
|
|
9
|
+
export interface PrSummaryOptions {
|
|
10
|
+
owner: string;
|
|
11
|
+
repo: string;
|
|
12
|
+
prNumber: number;
|
|
13
|
+
token: string;
|
|
14
|
+
verdict: TribunalVerdict;
|
|
15
|
+
baseUrl?: string;
|
|
16
|
+
}
|
|
17
|
+
interface PrSummaryResult {
|
|
18
|
+
commentId: number;
|
|
19
|
+
updated: boolean;
|
|
20
|
+
url: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function formatPrSummary(verdict: TribunalVerdict): string;
|
|
23
|
+
export declare function postPrSummary(options: PrSummaryOptions): Promise<PrSummaryResult>;
|
|
24
|
+
export declare function runPrSummary(argv: string[]): Promise<void>;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=pr-summary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-summary.d.ts","sourceRoot":"","sources":["../../src/commands/pr-summary.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAInD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,eAAe,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,eAAe;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAmBD,wBAAgB,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAoDhE;AAsBD,wBAAsB,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAiCvF;AAID,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAiFhE"}
|