@vertaaux/cli 0.2.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/README.md +345 -0
- package/dist/auth/ci-token.d.ts +49 -0
- package/dist/auth/ci-token.d.ts.map +1 -0
- package/dist/auth/ci-token.js +83 -0
- package/dist/auth/device-flow.d.ts +66 -0
- package/dist/auth/device-flow.d.ts.map +1 -0
- package/dist/auth/device-flow.js +156 -0
- package/dist/auth/token-store.d.ts +53 -0
- package/dist/auth/token-store.d.ts.map +1 -0
- package/dist/auth/token-store.js +78 -0
- package/dist/baseline/diff.d.ts +57 -0
- package/dist/baseline/diff.d.ts.map +1 -0
- package/dist/baseline/diff.js +152 -0
- package/dist/baseline/hash.d.ts +54 -0
- package/dist/baseline/hash.d.ts.map +1 -0
- package/dist/baseline/hash.js +66 -0
- package/dist/baseline/manager.d.ts +89 -0
- package/dist/baseline/manager.d.ts.map +1 -0
- package/dist/baseline/manager.js +157 -0
- package/dist/cache/index.d.ts +8 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +7 -0
- package/dist/cache/route-cache.d.ts +119 -0
- package/dist/cache/route-cache.d.ts.map +1 -0
- package/dist/cache/route-cache.js +213 -0
- package/dist/ci/changed-routes.d.ts +95 -0
- package/dist/ci/changed-routes.d.ts.map +1 -0
- package/dist/ci/changed-routes.js +304 -0
- package/dist/ci/github-api.d.ts +68 -0
- package/dist/ci/github-api.d.ts.map +1 -0
- package/dist/ci/github-api.js +138 -0
- package/dist/ci/gitlab-api.d.ts +75 -0
- package/dist/ci/gitlab-api.d.ts.map +1 -0
- package/dist/ci/gitlab-api.js +180 -0
- package/dist/ci/index.d.ts +6 -0
- package/dist/ci/index.d.ts.map +1 -0
- package/dist/ci/index.js +4 -0
- package/dist/commands/audit.d.ts +58 -0
- package/dist/commands/audit.d.ts.map +1 -0
- package/dist/commands/audit.js +862 -0
- package/dist/commands/baseline.d.ts +22 -0
- package/dist/commands/baseline.d.ts.map +1 -0
- package/dist/commands/baseline.js +210 -0
- package/dist/commands/comment.d.ts +14 -0
- package/dist/commands/comment.d.ts.map +1 -0
- package/dist/commands/comment.js +363 -0
- package/dist/commands/diff.d.ts +24 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +196 -0
- package/dist/commands/doctor.d.ts +58 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +338 -0
- package/dist/commands/download.d.ts +12 -0
- package/dist/commands/download.d.ts.map +1 -0
- package/dist/commands/download.js +183 -0
- package/dist/commands/explain.d.ts +62 -0
- package/dist/commands/explain.d.ts.map +1 -0
- package/dist/commands/explain.js +302 -0
- package/dist/commands/init.d.ts +12 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +212 -0
- package/dist/commands/login.d.ts +14 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +222 -0
- package/dist/commands/policy.d.ts +13 -0
- package/dist/commands/policy.d.ts.map +1 -0
- package/dist/commands/policy.js +347 -0
- package/dist/commands/upload.d.ts +12 -0
- package/dist/commands/upload.d.ts.map +1 -0
- package/dist/commands/upload.js +158 -0
- package/dist/config/defaults.d.ts +21 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +49 -0
- package/dist/config/loader.d.ts +66 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +167 -0
- package/dist/config/schema.d.ts +55 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +6 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1090 -0
- package/dist/interactive/fix-wizard.d.ts +44 -0
- package/dist/interactive/fix-wizard.d.ts.map +1 -0
- package/dist/interactive/fix-wizard.js +286 -0
- package/dist/interactive/init-wizard.d.ts +32 -0
- package/dist/interactive/init-wizard.d.ts.map +1 -0
- package/dist/interactive/init-wizard.js +193 -0
- package/dist/interactive/prompts.d.ts +62 -0
- package/dist/interactive/prompts.d.ts.map +1 -0
- package/dist/interactive/prompts.js +78 -0
- package/dist/monorepo/detector.d.ts +70 -0
- package/dist/monorepo/detector.d.ts.map +1 -0
- package/dist/monorepo/detector.js +278 -0
- package/dist/monorepo/index.d.ts +9 -0
- package/dist/monorepo/index.d.ts.map +1 -0
- package/dist/monorepo/index.js +8 -0
- package/dist/monorepo/workspace.d.ts +142 -0
- package/dist/monorepo/workspace.d.ts.map +1 -0
- package/dist/monorepo/workspace.js +171 -0
- package/dist/output/envelope.d.ts +21 -0
- package/dist/output/envelope.d.ts.map +1 -0
- package/dist/output/envelope.js +27 -0
- package/dist/output/factory.d.ts +73 -0
- package/dist/output/factory.d.ts.map +1 -0
- package/dist/output/factory.js +60 -0
- package/dist/output/formats.d.ts +11 -0
- package/dist/output/formats.d.ts.map +1 -0
- package/dist/output/formats.js +41 -0
- package/dist/output/html.d.ts +45 -0
- package/dist/output/html.d.ts.map +1 -0
- package/dist/output/html.js +607 -0
- package/dist/output/human.d.ts +41 -0
- package/dist/output/human.d.ts.map +1 -0
- package/dist/output/human.js +274 -0
- package/dist/output/json.d.ts +42 -0
- package/dist/output/json.d.ts.map +1 -0
- package/dist/output/json.js +37 -0
- package/dist/output/junit.d.ts +56 -0
- package/dist/output/junit.d.ts.map +1 -0
- package/dist/output/junit.js +135 -0
- package/dist/output/markdown.d.ts +77 -0
- package/dist/output/markdown.d.ts.map +1 -0
- package/dist/output/markdown.js +411 -0
- package/dist/output/sarif.d.ts +160 -0
- package/dist/output/sarif.d.ts.map +1 -0
- package/dist/output/sarif.js +207 -0
- package/dist/policy/evaluator.d.ts +111 -0
- package/dist/policy/evaluator.d.ts.map +1 -0
- package/dist/policy/evaluator.js +362 -0
- package/dist/policy/index.d.ts +15 -0
- package/dist/policy/index.d.ts.map +1 -0
- package/dist/policy/index.js +11 -0
- package/dist/policy/loader.d.ts +97 -0
- package/dist/policy/loader.d.ts.map +1 -0
- package/dist/policy/loader.js +281 -0
- package/dist/policy/schema.d.ts +297 -0
- package/dist/policy/schema.d.ts.map +1 -0
- package/dist/policy/schema.js +230 -0
- package/dist/quality-gate/evaluator.d.ts +58 -0
- package/dist/quality-gate/evaluator.d.ts.map +1 -0
- package/dist/quality-gate/evaluator.js +274 -0
- package/dist/quality-gate/index.d.ts +10 -0
- package/dist/quality-gate/index.d.ts.map +1 -0
- package/dist/quality-gate/index.js +7 -0
- package/dist/quality-gate/types.d.ts +103 -0
- package/dist/quality-gate/types.d.ts.map +1 -0
- package/dist/quality-gate/types.js +23 -0
- package/dist/templates/azure-devops.d.ts +25 -0
- package/dist/templates/azure-devops.d.ts.map +1 -0
- package/dist/templates/azure-devops.js +109 -0
- package/dist/templates/circleci.d.ts +28 -0
- package/dist/templates/circleci.d.ts.map +1 -0
- package/dist/templates/circleci.js +86 -0
- package/dist/templates/github-actions.d.ts +81 -0
- package/dist/templates/github-actions.d.ts.map +1 -0
- package/dist/templates/github-actions.js +393 -0
- package/dist/templates/gitlab-ci.d.ts +26 -0
- package/dist/templates/gitlab-ci.d.ts.map +1 -0
- package/dist/templates/gitlab-ci.js +70 -0
- package/dist/templates/index.d.ts +72 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +112 -0
- package/dist/templates/jenkins.d.ts +26 -0
- package/dist/templates/jenkins.d.ts.map +1 -0
- package/dist/templates/jenkins.js +110 -0
- package/dist/ui/banner.d.ts +31 -0
- package/dist/ui/banner.d.ts.map +1 -0
- package/dist/ui/banner.js +84 -0
- package/dist/ui/diagnostics.d.ts +39 -0
- package/dist/ui/diagnostics.d.ts.map +1 -0
- package/dist/ui/diagnostics.js +153 -0
- package/dist/ui/spinner.d.ts +61 -0
- package/dist/ui/spinner.d.ts.map +1 -0
- package/dist/ui/spinner.js +101 -0
- package/dist/ui/table.d.ts +63 -0
- package/dist/ui/table.d.ts.map +1 -0
- package/dist/ui/table.js +236 -0
- package/dist/utils/client.d.ts +82 -0
- package/dist/utils/client.d.ts.map +1 -0
- package/dist/utils/client.js +128 -0
- package/dist/utils/detect-env.d.ts +59 -0
- package/dist/utils/detect-env.d.ts.map +1 -0
- package/dist/utils/detect-env.js +115 -0
- package/dist/utils/exit-codes.d.ts +47 -0
- package/dist/utils/exit-codes.d.ts.map +1 -0
- package/dist/utils/exit-codes.js +61 -0
- package/dist/utils/logger.d.ts +87 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +185 -0
- package/dist/utils/sanitize.d.ts +36 -0
- package/dist/utils/sanitize.d.ts.map +1 -0
- package/dist/utils/sanitize.js +64 -0
- package/dist/utils/validators.d.ts +41 -0
- package/dist/utils/validators.d.ts.map +1 -0
- package/dist/utils/validators.js +123 -0
- package/package.json +63 -0
- package/schemas/vertaaux.config.schema.json +103 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SARIF 2.1.0 output formatter for CLI.
|
|
3
|
+
*
|
|
4
|
+
* Generates SARIF (Static Analysis Results Interchange Format) output
|
|
5
|
+
* for integration with GitHub Code Scanning and other SARIF consumers.
|
|
6
|
+
*
|
|
7
|
+
* @see https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html
|
|
8
|
+
* @see https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning
|
|
9
|
+
*/
|
|
10
|
+
import { generateFingerprint } from "../baseline/hash.js";
|
|
11
|
+
// Package version for tool.driver.version
|
|
12
|
+
const CLI_VERSION = "0.1.0";
|
|
13
|
+
// GitHub Code Scanning limits
|
|
14
|
+
const MAX_RESULTS = 25000;
|
|
15
|
+
/**
|
|
16
|
+
* Map CLI/API severity to SARIF level.
|
|
17
|
+
*
|
|
18
|
+
* - error/critical -> error
|
|
19
|
+
* - warning/serious -> warning
|
|
20
|
+
* - info/minor -> note
|
|
21
|
+
*/
|
|
22
|
+
function mapSeverityToLevel(severity) {
|
|
23
|
+
const sev = (severity || "info").toLowerCase();
|
|
24
|
+
switch (sev) {
|
|
25
|
+
case "error":
|
|
26
|
+
case "critical":
|
|
27
|
+
return "error";
|
|
28
|
+
case "warning":
|
|
29
|
+
case "serious":
|
|
30
|
+
return "warning";
|
|
31
|
+
case "info":
|
|
32
|
+
case "minor":
|
|
33
|
+
case "moderate":
|
|
34
|
+
return "note";
|
|
35
|
+
default:
|
|
36
|
+
return "note";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get rule ID from issue, checking multiple field names.
|
|
41
|
+
*/
|
|
42
|
+
function getRuleId(issue) {
|
|
43
|
+
return issue.ruleId || issue.rule_id || issue.id || "unknown";
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Normalize issues from various API response formats.
|
|
47
|
+
*/
|
|
48
|
+
function normalizeIssues(issues) {
|
|
49
|
+
if (Array.isArray(issues))
|
|
50
|
+
return issues;
|
|
51
|
+
if (issues && typeof issues === "object") {
|
|
52
|
+
const values = Object.values(issues);
|
|
53
|
+
return values.flatMap((value) => Array.isArray(value) ? value : []);
|
|
54
|
+
}
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Build unique rules array from issues.
|
|
59
|
+
*/
|
|
60
|
+
function buildRules(issues) {
|
|
61
|
+
const ruleMap = new Map();
|
|
62
|
+
for (const issue of issues) {
|
|
63
|
+
const ruleId = getRuleId(issue);
|
|
64
|
+
if (ruleMap.has(ruleId))
|
|
65
|
+
continue;
|
|
66
|
+
const rule = {
|
|
67
|
+
id: ruleId,
|
|
68
|
+
shortDescription: {
|
|
69
|
+
text: issue.title || issue.description?.slice(0, 100) || ruleId,
|
|
70
|
+
},
|
|
71
|
+
defaultConfiguration: {
|
|
72
|
+
level: mapSeverityToLevel(issue.severity),
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
// Add full description if different from short
|
|
76
|
+
if (issue.description && issue.description.length > 100) {
|
|
77
|
+
rule.fullDescription = { text: issue.description };
|
|
78
|
+
}
|
|
79
|
+
// Add help URI from WCAG reference
|
|
80
|
+
if (issue.wcag_reference) {
|
|
81
|
+
// Extract WCAG criterion and build URL
|
|
82
|
+
const wcagMatch = issue.wcag_reference.match(/\d+\.\d+\.\d+/);
|
|
83
|
+
if (wcagMatch) {
|
|
84
|
+
rule.helpUri = `https://www.w3.org/WAI/WCAG21/Understanding/${wcagMatch[0].replace(/\./g, "-")}.html`;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Add category as property
|
|
88
|
+
if (issue.category) {
|
|
89
|
+
rule.properties = {
|
|
90
|
+
category: issue.category,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
ruleMap.set(ruleId, rule);
|
|
94
|
+
}
|
|
95
|
+
return Array.from(ruleMap.values());
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get artifact URI from issue and base URL.
|
|
99
|
+
*
|
|
100
|
+
* Returns relative path if possible, otherwise full URL.
|
|
101
|
+
*/
|
|
102
|
+
function getArtifactUri(issue, baseUrl) {
|
|
103
|
+
// If we have a selector, use a relative path based on URL
|
|
104
|
+
// Otherwise use the base URL or a placeholder
|
|
105
|
+
if (baseUrl) {
|
|
106
|
+
try {
|
|
107
|
+
const url = new URL(baseUrl);
|
|
108
|
+
// Return path portion as relative URI
|
|
109
|
+
return url.pathname || "/";
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return baseUrl;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return "index.html";
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Build SARIF result from issue.
|
|
119
|
+
*/
|
|
120
|
+
function buildResult(issue, baseUrl, options) {
|
|
121
|
+
const ruleId = getRuleId(issue);
|
|
122
|
+
const fingerprint = generateFingerprint(issue);
|
|
123
|
+
const result = {
|
|
124
|
+
ruleId,
|
|
125
|
+
message: {
|
|
126
|
+
text: issue.description || issue.title || "No description provided",
|
|
127
|
+
},
|
|
128
|
+
level: mapSeverityToLevel(issue.severity),
|
|
129
|
+
locations: [
|
|
130
|
+
{
|
|
131
|
+
physicalLocation: {
|
|
132
|
+
artifactLocation: {
|
|
133
|
+
uri: getArtifactUri(issue, baseUrl),
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
partialFingerprints: {
|
|
139
|
+
primaryLocationLineHash: fingerprint,
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
// Add suppression if issue is baselined
|
|
143
|
+
if (options?.includeBaseline && options.baselineFingerprints?.has(fingerprint)) {
|
|
144
|
+
result.suppressions = [
|
|
145
|
+
{
|
|
146
|
+
kind: "external",
|
|
147
|
+
justification: "Issue was baselined as existing technical debt",
|
|
148
|
+
},
|
|
149
|
+
];
|
|
150
|
+
}
|
|
151
|
+
return result;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Format audit result as SARIF 2.1.0 JSON.
|
|
155
|
+
*
|
|
156
|
+
* @param result - Audit result from API
|
|
157
|
+
* @param options - Formatting options
|
|
158
|
+
* @returns SARIF 2.1.0 JSON string
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* ```typescript
|
|
162
|
+
* const sarif = formatSarif(auditResult, {
|
|
163
|
+
* workingDirectory: process.cwd(),
|
|
164
|
+
* includeBaseline: true,
|
|
165
|
+
* baselineFingerprints: new Set(['abc123...'])
|
|
166
|
+
* });
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
export function formatSarif(result, options) {
|
|
170
|
+
const issues = normalizeIssues(result.issues);
|
|
171
|
+
const rules = buildRules(issues);
|
|
172
|
+
const results = issues.map((issue) => buildResult(issue, result.url, options));
|
|
173
|
+
// Warn if approaching GitHub limits
|
|
174
|
+
if (results.length > MAX_RESULTS * 0.9) {
|
|
175
|
+
console.error(`Warning: ${results.length} results approaching GitHub limit of ${MAX_RESULTS}`);
|
|
176
|
+
}
|
|
177
|
+
// Truncate if exceeding limit
|
|
178
|
+
const truncatedResults = results.slice(0, MAX_RESULTS);
|
|
179
|
+
if (results.length > MAX_RESULTS) {
|
|
180
|
+
console.error(`Warning: Truncated ${results.length - MAX_RESULTS} results to meet GitHub limit`);
|
|
181
|
+
}
|
|
182
|
+
const sarifLog = {
|
|
183
|
+
$schema: "https://json.schemastore.org/sarif-2.1.0.json",
|
|
184
|
+
version: "2.1.0",
|
|
185
|
+
runs: [
|
|
186
|
+
{
|
|
187
|
+
tool: {
|
|
188
|
+
driver: {
|
|
189
|
+
name: "VertaaUX",
|
|
190
|
+
version: CLI_VERSION,
|
|
191
|
+
informationUri: "https://vertaaux.ai",
|
|
192
|
+
rules,
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
results: truncatedResults,
|
|
196
|
+
},
|
|
197
|
+
],
|
|
198
|
+
};
|
|
199
|
+
// Add invocation if working directory specified
|
|
200
|
+
if (options?.workingDirectory) {
|
|
201
|
+
sarifLog.runs[0].invocation = {
|
|
202
|
+
workingDirectory: { uri: `file://${options.workingDirectory}` },
|
|
203
|
+
executionSuccessful: !result.error,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
return JSON.stringify(sarifLog, null, 2);
|
|
207
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy evaluation against audit results.
|
|
3
|
+
*
|
|
4
|
+
* Evaluates audit results against policy assertions,
|
|
5
|
+
* applying rule overrides and path exclusions.
|
|
6
|
+
*
|
|
7
|
+
* Implements CICD-17: Policy-as-code support.
|
|
8
|
+
*/
|
|
9
|
+
import type { PolicyFile, RuleOverride } from "./schema.js";
|
|
10
|
+
import type { Issue } from "../baseline/hash.js";
|
|
11
|
+
/**
|
|
12
|
+
* Audit result subset needed for policy evaluation.
|
|
13
|
+
*/
|
|
14
|
+
export interface AuditResultForPolicy {
|
|
15
|
+
/** Issues found during audit */
|
|
16
|
+
issues?: Issue[] | Record<string, Issue[]>;
|
|
17
|
+
/** Score breakdown */
|
|
18
|
+
scores?: Record<string, number | unknown>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Policy violation details.
|
|
22
|
+
*/
|
|
23
|
+
export interface PolicyViolation {
|
|
24
|
+
/** Type of violation */
|
|
25
|
+
type: "score_threshold" | "issue_limit" | "severity_breach";
|
|
26
|
+
/** Human-readable message */
|
|
27
|
+
message: string;
|
|
28
|
+
/** Actual value that caused violation */
|
|
29
|
+
actual: number;
|
|
30
|
+
/** Threshold that was breached */
|
|
31
|
+
threshold: number;
|
|
32
|
+
/** Additional context */
|
|
33
|
+
context?: {
|
|
34
|
+
category?: string;
|
|
35
|
+
severity?: string;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Result of policy evaluation.
|
|
40
|
+
*/
|
|
41
|
+
export interface PolicyEvaluationResult {
|
|
42
|
+
/** Whether policy passed */
|
|
43
|
+
passed: boolean;
|
|
44
|
+
/** List of policy violations */
|
|
45
|
+
violations: PolicyViolation[];
|
|
46
|
+
/** Issues with applied rule overrides */
|
|
47
|
+
adjustedIssues: Issue[];
|
|
48
|
+
/** Rules that were ignored by policy */
|
|
49
|
+
ignoredRules: string[];
|
|
50
|
+
/** Summary of evaluation */
|
|
51
|
+
summary: {
|
|
52
|
+
/** Issues by severity after adjustments */
|
|
53
|
+
issueCounts: {
|
|
54
|
+
error: number;
|
|
55
|
+
warning: number;
|
|
56
|
+
info: number;
|
|
57
|
+
};
|
|
58
|
+
/** Number of issues ignored by rule overrides */
|
|
59
|
+
ignoredCount: number;
|
|
60
|
+
/** Score breakdown */
|
|
61
|
+
scores: Record<string, number>;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Apply rule overrides to issues.
|
|
66
|
+
*
|
|
67
|
+
* Returns adjusted issues with modified severities,
|
|
68
|
+
* and list of issues that were ignored.
|
|
69
|
+
*
|
|
70
|
+
* @param issues - Original issues from audit
|
|
71
|
+
* @param rules - Rule override configuration
|
|
72
|
+
* @param currentPath - Current file path for path-specific overrides
|
|
73
|
+
* @returns Adjusted issues and list of ignored rule IDs
|
|
74
|
+
*/
|
|
75
|
+
export declare function applyRuleOverrides(issues: Issue[], rules: Record<string, RuleOverride>, currentPath?: string): {
|
|
76
|
+
adjusted: Issue[];
|
|
77
|
+
ignored: Issue[];
|
|
78
|
+
ignoredRules: string[];
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Filter issues by excluded paths.
|
|
82
|
+
*
|
|
83
|
+
* @param issues - Issues to filter
|
|
84
|
+
* @param excludePaths - Path patterns to exclude
|
|
85
|
+
* @returns Filtered issues
|
|
86
|
+
*/
|
|
87
|
+
export declare function filterExcludedPaths(issues: Issue[], excludePaths: string[]): Issue[];
|
|
88
|
+
/**
|
|
89
|
+
* Evaluate audit result against policy.
|
|
90
|
+
*
|
|
91
|
+
* Evaluation order:
|
|
92
|
+
* 1. Apply rule overrides (change severity, ignore rules)
|
|
93
|
+
* 2. Filter issues for excluded paths
|
|
94
|
+
* 3. Check threshold assertions
|
|
95
|
+
* 4. Check issue count limits
|
|
96
|
+
* 5. Check severity breach
|
|
97
|
+
*
|
|
98
|
+
* @param auditResult - Audit result with issues and scores
|
|
99
|
+
* @param newIssues - New issues only (from baseline diff)
|
|
100
|
+
* @param policy - Policy configuration
|
|
101
|
+
* @param options - Additional options
|
|
102
|
+
* @returns Evaluation result with pass/fail status and violations
|
|
103
|
+
*/
|
|
104
|
+
export declare function evaluatePolicy(auditResult: AuditResultForPolicy, newIssues: Issue[], policy: PolicyFile, options?: {
|
|
105
|
+
currentPath?: string;
|
|
106
|
+
}): PolicyEvaluationResult;
|
|
107
|
+
/**
|
|
108
|
+
* Format policy evaluation result for human-readable output.
|
|
109
|
+
*/
|
|
110
|
+
export declare function formatPolicyResult(result: PolicyEvaluationResult): string;
|
|
111
|
+
//# sourceMappingURL=evaluator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../../src/policy/evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAoB,MAAM,aAAa,CAAC;AAC9E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,gCAAgC;IAChC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3C,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;CAC3C;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,IAAI,EAAE,iBAAiB,GAAG,aAAa,GAAG,iBAAiB,CAAC;IAC5D,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,yBAAyB;IACzB,OAAO,CAAC,EAAE;QACR,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,4BAA4B;IAC5B,MAAM,EAAE,OAAO,CAAC;IAEhB,gCAAgC;IAChC,UAAU,EAAE,eAAe,EAAE,CAAC;IAE9B,yCAAyC;IACzC,cAAc,EAAE,KAAK,EAAE,CAAC;IAExB,wCAAwC;IACxC,YAAY,EAAE,MAAM,EAAE,CAAC;IAEvB,4BAA4B;IAC5B,OAAO,EAAE;QACP,2CAA2C;QAC3C,WAAW,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;QAC9D,iDAAiD;QACjD,YAAY,EAAE,MAAM,CAAC;QACrB,sBAAsB;QACtB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAChC,CAAC;CACH;AAkGD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,KAAK,EAAE,EACf,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,EACnC,WAAW,CAAC,EAAE,MAAM,GACnB;IAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAAC,OAAO,EAAE,KAAK,EAAE,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,CAsCjE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,KAAK,EAAE,EACf,YAAY,EAAE,MAAM,EAAE,GACrB,KAAK,EAAE,CAcT;AA8ID;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,oBAAoB,EACjC,SAAS,EAAE,KAAK,EAAE,EAClB,MAAM,EAAE,UAAU,EAClB,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACjC,sBAAsB,CA2CxB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,sBAAsB,GAAG,MAAM,CAiDzE"}
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy evaluation against audit results.
|
|
3
|
+
*
|
|
4
|
+
* Evaluates audit results against policy assertions,
|
|
5
|
+
* applying rule overrides and path exclusions.
|
|
6
|
+
*
|
|
7
|
+
* Implements CICD-17: Policy-as-code support.
|
|
8
|
+
*/
|
|
9
|
+
import { minimatch } from "minimatch";
|
|
10
|
+
/** Severity ranking for comparison */
|
|
11
|
+
const SEVERITY_RANK = {
|
|
12
|
+
error: 3,
|
|
13
|
+
critical: 3,
|
|
14
|
+
warning: 2,
|
|
15
|
+
serious: 2,
|
|
16
|
+
info: 1,
|
|
17
|
+
minor: 1,
|
|
18
|
+
moderate: 1,
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Get severity rank for comparison.
|
|
22
|
+
*/
|
|
23
|
+
function severityRank(severity) {
|
|
24
|
+
return SEVERITY_RANK[severity.toLowerCase()] ?? 0;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Normalize severity to canonical values.
|
|
28
|
+
*/
|
|
29
|
+
function normalizeSeverity(severity) {
|
|
30
|
+
const lower = (severity || "info").toLowerCase();
|
|
31
|
+
switch (lower) {
|
|
32
|
+
case "error":
|
|
33
|
+
case "critical":
|
|
34
|
+
return "error";
|
|
35
|
+
case "warning":
|
|
36
|
+
case "serious":
|
|
37
|
+
return "warning";
|
|
38
|
+
default:
|
|
39
|
+
return "info";
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get the rule ID from an issue, checking multiple field names.
|
|
44
|
+
*/
|
|
45
|
+
function getRuleId(issue) {
|
|
46
|
+
return issue.ruleId || issue.rule_id || issue.id || "";
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Normalize issues from various API response formats to array.
|
|
50
|
+
*/
|
|
51
|
+
function normalizeIssues(issues) {
|
|
52
|
+
if (Array.isArray(issues)) {
|
|
53
|
+
return issues;
|
|
54
|
+
}
|
|
55
|
+
if (issues && typeof issues === "object") {
|
|
56
|
+
const values = Object.values(issues);
|
|
57
|
+
return values.flatMap((value) => Array.isArray(value) ? value : []);
|
|
58
|
+
}
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Extract numeric scores from audit result.
|
|
63
|
+
*/
|
|
64
|
+
function extractScores(scores) {
|
|
65
|
+
const result = {};
|
|
66
|
+
if (!scores)
|
|
67
|
+
return result;
|
|
68
|
+
for (const [key, value] of Object.entries(scores)) {
|
|
69
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
70
|
+
result[key] = value;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Count issues by normalized severity.
|
|
77
|
+
*/
|
|
78
|
+
function countBySeverity(issues) {
|
|
79
|
+
const counts = { error: 0, warning: 0, info: 0 };
|
|
80
|
+
for (const issue of issues) {
|
|
81
|
+
const normalized = normalizeSeverity(issue.severity || "info");
|
|
82
|
+
counts[normalized]++;
|
|
83
|
+
}
|
|
84
|
+
return counts;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Check if a path matches any of the given patterns.
|
|
88
|
+
*/
|
|
89
|
+
function pathMatches(filePath, patterns) {
|
|
90
|
+
return patterns.some((pattern) => minimatch(filePath, pattern));
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Apply rule overrides to issues.
|
|
94
|
+
*
|
|
95
|
+
* Returns adjusted issues with modified severities,
|
|
96
|
+
* and list of issues that were ignored.
|
|
97
|
+
*
|
|
98
|
+
* @param issues - Original issues from audit
|
|
99
|
+
* @param rules - Rule override configuration
|
|
100
|
+
* @param currentPath - Current file path for path-specific overrides
|
|
101
|
+
* @returns Adjusted issues and list of ignored rule IDs
|
|
102
|
+
*/
|
|
103
|
+
export function applyRuleOverrides(issues, rules, currentPath) {
|
|
104
|
+
const adjusted = [];
|
|
105
|
+
const ignored = [];
|
|
106
|
+
const ignoredRules = new Set();
|
|
107
|
+
for (const issue of issues) {
|
|
108
|
+
const ruleId = getRuleId(issue);
|
|
109
|
+
const override = rules[ruleId];
|
|
110
|
+
// No override for this rule
|
|
111
|
+
if (!override) {
|
|
112
|
+
adjusted.push(issue);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
// Check path filter if specified
|
|
116
|
+
if (override.paths && currentPath) {
|
|
117
|
+
if (!pathMatches(currentPath, override.paths)) {
|
|
118
|
+
// Path doesn't match, skip override
|
|
119
|
+
adjusted.push(issue);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Apply severity override
|
|
124
|
+
if (override.severity === "ignore") {
|
|
125
|
+
ignored.push(issue);
|
|
126
|
+
ignoredRules.add(ruleId);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
// Change severity
|
|
130
|
+
adjusted.push({
|
|
131
|
+
...issue,
|
|
132
|
+
severity: override.severity,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return { adjusted, ignored, ignoredRules: Array.from(ignoredRules) };
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Filter issues by excluded paths.
|
|
140
|
+
*
|
|
141
|
+
* @param issues - Issues to filter
|
|
142
|
+
* @param excludePaths - Path patterns to exclude
|
|
143
|
+
* @returns Filtered issues
|
|
144
|
+
*/
|
|
145
|
+
export function filterExcludedPaths(issues, excludePaths) {
|
|
146
|
+
if (!excludePaths || excludePaths.length === 0) {
|
|
147
|
+
return issues;
|
|
148
|
+
}
|
|
149
|
+
return issues.filter((issue) => {
|
|
150
|
+
// If issue has a path/file, check if it's excluded
|
|
151
|
+
const issuePath = issue.path;
|
|
152
|
+
if (issuePath && pathMatches(issuePath, excludePaths)) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
return true;
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Check score threshold violations.
|
|
160
|
+
*/
|
|
161
|
+
function checkScoreThresholds(scores, assertions) {
|
|
162
|
+
const violations = [];
|
|
163
|
+
// Map assertion keys to score keys
|
|
164
|
+
const thresholdMap = [
|
|
165
|
+
{
|
|
166
|
+
assertionKey: "overall_score",
|
|
167
|
+
scoreKeys: ["overall", "total", "ux"],
|
|
168
|
+
label: "overall",
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
assertionKey: "accessibility_score",
|
|
172
|
+
scoreKeys: ["accessibility", "a11y"],
|
|
173
|
+
label: "accessibility",
|
|
174
|
+
},
|
|
175
|
+
{ assertionKey: "ux_score", scoreKeys: ["ux", "usability"], label: "UX" },
|
|
176
|
+
{
|
|
177
|
+
assertionKey: "performance_score",
|
|
178
|
+
scoreKeys: ["performance", "perf"],
|
|
179
|
+
label: "performance",
|
|
180
|
+
},
|
|
181
|
+
];
|
|
182
|
+
for (const { assertionKey, scoreKeys, label } of thresholdMap) {
|
|
183
|
+
const threshold = assertions[assertionKey];
|
|
184
|
+
if (threshold === undefined)
|
|
185
|
+
continue;
|
|
186
|
+
// Find the score value using multiple possible keys
|
|
187
|
+
let actual;
|
|
188
|
+
for (const key of scoreKeys) {
|
|
189
|
+
if (scores[key] !== undefined) {
|
|
190
|
+
actual = scores[key];
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (actual !== undefined && actual < threshold) {
|
|
195
|
+
violations.push({
|
|
196
|
+
type: "score_threshold",
|
|
197
|
+
message: `${label} score ${actual} is below minimum ${threshold}`,
|
|
198
|
+
actual,
|
|
199
|
+
threshold,
|
|
200
|
+
context: { category: label },
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return violations;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Check issue count violations.
|
|
208
|
+
*/
|
|
209
|
+
function checkIssueLimits(counts, assertions) {
|
|
210
|
+
const violations = [];
|
|
211
|
+
// Check max_new_errors
|
|
212
|
+
if (assertions.max_new_errors !== undefined &&
|
|
213
|
+
counts.error > assertions.max_new_errors) {
|
|
214
|
+
violations.push({
|
|
215
|
+
type: "issue_limit",
|
|
216
|
+
message: `${counts.error} error-severity issues exceed maximum ${assertions.max_new_errors}`,
|
|
217
|
+
actual: counts.error,
|
|
218
|
+
threshold: assertions.max_new_errors,
|
|
219
|
+
context: { severity: "error" },
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
// Check max_new_warnings
|
|
223
|
+
if (assertions.max_new_warnings !== undefined &&
|
|
224
|
+
counts.warning > assertions.max_new_warnings) {
|
|
225
|
+
violations.push({
|
|
226
|
+
type: "issue_limit",
|
|
227
|
+
message: `${counts.warning} warning-severity issues exceed maximum ${assertions.max_new_warnings}`,
|
|
228
|
+
actual: counts.warning,
|
|
229
|
+
threshold: assertions.max_new_warnings,
|
|
230
|
+
context: { severity: "warning" },
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
// Check max_new_total
|
|
234
|
+
const total = counts.error + counts.warning + counts.info;
|
|
235
|
+
if (assertions.max_new_total !== undefined && total > assertions.max_new_total) {
|
|
236
|
+
violations.push({
|
|
237
|
+
type: "issue_limit",
|
|
238
|
+
message: `${total} total issues exceed maximum ${assertions.max_new_total}`,
|
|
239
|
+
actual: total,
|
|
240
|
+
threshold: assertions.max_new_total,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
return violations;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Check severity-based violations.
|
|
247
|
+
*/
|
|
248
|
+
function checkSeverityBreach(issues, assertions) {
|
|
249
|
+
if (!assertions.fail_on)
|
|
250
|
+
return [];
|
|
251
|
+
const failOnRank = severityRank(assertions.fail_on);
|
|
252
|
+
const breachingIssues = issues.filter((issue) => severityRank(issue.severity || "info") >= failOnRank);
|
|
253
|
+
if (breachingIssues.length > 0) {
|
|
254
|
+
return [
|
|
255
|
+
{
|
|
256
|
+
type: "severity_breach",
|
|
257
|
+
message: `${breachingIssues.length} issues at or above ${assertions.fail_on} severity`,
|
|
258
|
+
actual: breachingIssues.length,
|
|
259
|
+
threshold: 0,
|
|
260
|
+
context: { severity: assertions.fail_on },
|
|
261
|
+
},
|
|
262
|
+
];
|
|
263
|
+
}
|
|
264
|
+
return [];
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Evaluate audit result against policy.
|
|
268
|
+
*
|
|
269
|
+
* Evaluation order:
|
|
270
|
+
* 1. Apply rule overrides (change severity, ignore rules)
|
|
271
|
+
* 2. Filter issues for excluded paths
|
|
272
|
+
* 3. Check threshold assertions
|
|
273
|
+
* 4. Check issue count limits
|
|
274
|
+
* 5. Check severity breach
|
|
275
|
+
*
|
|
276
|
+
* @param auditResult - Audit result with issues and scores
|
|
277
|
+
* @param newIssues - New issues only (from baseline diff)
|
|
278
|
+
* @param policy - Policy configuration
|
|
279
|
+
* @param options - Additional options
|
|
280
|
+
* @returns Evaluation result with pass/fail status and violations
|
|
281
|
+
*/
|
|
282
|
+
export function evaluatePolicy(auditResult, newIssues, policy, options) {
|
|
283
|
+
const { currentPath } = options || {};
|
|
284
|
+
// 1. Apply rule overrides
|
|
285
|
+
const { adjusted, ignored, ignoredRules } = policy.rules
|
|
286
|
+
? applyRuleOverrides(newIssues, policy.rules, currentPath)
|
|
287
|
+
: { adjusted: newIssues, ignored: [], ignoredRules: [] };
|
|
288
|
+
// 2. Filter excluded paths
|
|
289
|
+
const filtered = policy.exclude_paths
|
|
290
|
+
? filterExcludedPaths(adjusted, policy.exclude_paths)
|
|
291
|
+
: adjusted;
|
|
292
|
+
// 3. Extract scores
|
|
293
|
+
const scores = extractScores(auditResult.scores);
|
|
294
|
+
// 4. Count issues by severity
|
|
295
|
+
const issueCounts = countBySeverity(filtered);
|
|
296
|
+
// 5. Collect violations
|
|
297
|
+
const violations = [];
|
|
298
|
+
// Score thresholds
|
|
299
|
+
violations.push(...checkScoreThresholds(scores, policy.assertions));
|
|
300
|
+
// Issue limits (applied to new issues)
|
|
301
|
+
violations.push(...checkIssueLimits(issueCounts, policy.assertions));
|
|
302
|
+
// Severity breach
|
|
303
|
+
violations.push(...checkSeverityBreach(filtered, policy.assertions));
|
|
304
|
+
// 6. Determine result
|
|
305
|
+
return {
|
|
306
|
+
passed: violations.length === 0,
|
|
307
|
+
violations,
|
|
308
|
+
adjustedIssues: filtered,
|
|
309
|
+
ignoredRules,
|
|
310
|
+
summary: {
|
|
311
|
+
issueCounts,
|
|
312
|
+
ignoredCount: ignored.length,
|
|
313
|
+
scores,
|
|
314
|
+
},
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Format policy evaluation result for human-readable output.
|
|
319
|
+
*/
|
|
320
|
+
export function formatPolicyResult(result) {
|
|
321
|
+
const lines = [];
|
|
322
|
+
// Header
|
|
323
|
+
if (result.passed) {
|
|
324
|
+
lines.push("Policy: PASSED");
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
lines.push("Policy: FAILED");
|
|
328
|
+
}
|
|
329
|
+
// Summary
|
|
330
|
+
lines.push("");
|
|
331
|
+
lines.push("Issue Summary (after adjustments):");
|
|
332
|
+
lines.push(` Errors: ${result.summary.issueCounts.error}, Warnings: ${result.summary.issueCounts.warning}, Info: ${result.summary.issueCounts.info}`);
|
|
333
|
+
if (result.summary.ignoredCount > 0) {
|
|
334
|
+
lines.push(` Ignored by policy: ${result.summary.ignoredCount}`);
|
|
335
|
+
}
|
|
336
|
+
// Ignored rules
|
|
337
|
+
if (result.ignoredRules.length > 0) {
|
|
338
|
+
lines.push("");
|
|
339
|
+
lines.push(`Ignored rules: ${result.ignoredRules.join(", ")}`);
|
|
340
|
+
}
|
|
341
|
+
// Scores
|
|
342
|
+
const scoreEntries = Object.entries(result.summary.scores);
|
|
343
|
+
if (scoreEntries.length > 0) {
|
|
344
|
+
lines.push("");
|
|
345
|
+
lines.push("Scores:");
|
|
346
|
+
for (const [category, score] of scoreEntries) {
|
|
347
|
+
lines.push(` ${category}: ${score}`);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
// Violations
|
|
351
|
+
if (result.violations.length > 0) {
|
|
352
|
+
lines.push("");
|
|
353
|
+
lines.push(`Violations (${result.violations.length}):`);
|
|
354
|
+
for (const violation of result.violations) {
|
|
355
|
+
const context = violation.context
|
|
356
|
+
? ` [${Object.values(violation.context).filter(Boolean).join(", ")}]`
|
|
357
|
+
: "";
|
|
358
|
+
lines.push(` - ${violation.message}${context}`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return lines.join("\n");
|
|
362
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy module for VertaaUX CLI.
|
|
3
|
+
*
|
|
4
|
+
* Provides policy-as-code support for organizations to define
|
|
5
|
+
* quality standards committed to the repository.
|
|
6
|
+
*
|
|
7
|
+
* Implements CICD-17: Policy-as-code support.
|
|
8
|
+
*/
|
|
9
|
+
export type { PolicyFile, PolicyAssertions, RuleOverride, BranchPolicy, PolicyTemplate, } from "./schema.js";
|
|
10
|
+
export { policyJsonSchema, DEFAULT_POLICY, POLICY_TEMPLATES, } from "./schema.js";
|
|
11
|
+
export type { PolicyLoadResult, PolicyValidationResult } from "./loader.js";
|
|
12
|
+
export { loadPolicy, loadPolicyFile, validatePolicy, resolveBranchPolicy, getEffectivePolicy, PolicyValidationError, PolicyLoadError, } from "./loader.js";
|
|
13
|
+
export type { AuditResultForPolicy, PolicyViolation, PolicyEvaluationResult, } from "./evaluator.js";
|
|
14
|
+
export { evaluatePolicy, applyRuleOverrides, filterExcludedPaths, formatPolicyResult, } from "./evaluator.js";
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,YAAY,EACV,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAGrB,YAAY,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EACL,UAAU,EACV,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,EACrB,eAAe,GAChB,MAAM,aAAa,CAAC;AAGrB,YAAY,EACV,oBAAoB,EACpB,eAAe,EACf,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC"}
|