@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.
Files changed (198) hide show
  1. package/README.md +345 -0
  2. package/dist/auth/ci-token.d.ts +49 -0
  3. package/dist/auth/ci-token.d.ts.map +1 -0
  4. package/dist/auth/ci-token.js +83 -0
  5. package/dist/auth/device-flow.d.ts +66 -0
  6. package/dist/auth/device-flow.d.ts.map +1 -0
  7. package/dist/auth/device-flow.js +156 -0
  8. package/dist/auth/token-store.d.ts +53 -0
  9. package/dist/auth/token-store.d.ts.map +1 -0
  10. package/dist/auth/token-store.js +78 -0
  11. package/dist/baseline/diff.d.ts +57 -0
  12. package/dist/baseline/diff.d.ts.map +1 -0
  13. package/dist/baseline/diff.js +152 -0
  14. package/dist/baseline/hash.d.ts +54 -0
  15. package/dist/baseline/hash.d.ts.map +1 -0
  16. package/dist/baseline/hash.js +66 -0
  17. package/dist/baseline/manager.d.ts +89 -0
  18. package/dist/baseline/manager.d.ts.map +1 -0
  19. package/dist/baseline/manager.js +157 -0
  20. package/dist/cache/index.d.ts +8 -0
  21. package/dist/cache/index.d.ts.map +1 -0
  22. package/dist/cache/index.js +7 -0
  23. package/dist/cache/route-cache.d.ts +119 -0
  24. package/dist/cache/route-cache.d.ts.map +1 -0
  25. package/dist/cache/route-cache.js +213 -0
  26. package/dist/ci/changed-routes.d.ts +95 -0
  27. package/dist/ci/changed-routes.d.ts.map +1 -0
  28. package/dist/ci/changed-routes.js +304 -0
  29. package/dist/ci/github-api.d.ts +68 -0
  30. package/dist/ci/github-api.d.ts.map +1 -0
  31. package/dist/ci/github-api.js +138 -0
  32. package/dist/ci/gitlab-api.d.ts +75 -0
  33. package/dist/ci/gitlab-api.d.ts.map +1 -0
  34. package/dist/ci/gitlab-api.js +180 -0
  35. package/dist/ci/index.d.ts +6 -0
  36. package/dist/ci/index.d.ts.map +1 -0
  37. package/dist/ci/index.js +4 -0
  38. package/dist/commands/audit.d.ts +58 -0
  39. package/dist/commands/audit.d.ts.map +1 -0
  40. package/dist/commands/audit.js +862 -0
  41. package/dist/commands/baseline.d.ts +22 -0
  42. package/dist/commands/baseline.d.ts.map +1 -0
  43. package/dist/commands/baseline.js +210 -0
  44. package/dist/commands/comment.d.ts +14 -0
  45. package/dist/commands/comment.d.ts.map +1 -0
  46. package/dist/commands/comment.js +363 -0
  47. package/dist/commands/diff.d.ts +24 -0
  48. package/dist/commands/diff.d.ts.map +1 -0
  49. package/dist/commands/diff.js +196 -0
  50. package/dist/commands/doctor.d.ts +58 -0
  51. package/dist/commands/doctor.d.ts.map +1 -0
  52. package/dist/commands/doctor.js +338 -0
  53. package/dist/commands/download.d.ts +12 -0
  54. package/dist/commands/download.d.ts.map +1 -0
  55. package/dist/commands/download.js +183 -0
  56. package/dist/commands/explain.d.ts +62 -0
  57. package/dist/commands/explain.d.ts.map +1 -0
  58. package/dist/commands/explain.js +302 -0
  59. package/dist/commands/init.d.ts +12 -0
  60. package/dist/commands/init.d.ts.map +1 -0
  61. package/dist/commands/init.js +212 -0
  62. package/dist/commands/login.d.ts +14 -0
  63. package/dist/commands/login.d.ts.map +1 -0
  64. package/dist/commands/login.js +222 -0
  65. package/dist/commands/policy.d.ts +13 -0
  66. package/dist/commands/policy.d.ts.map +1 -0
  67. package/dist/commands/policy.js +347 -0
  68. package/dist/commands/upload.d.ts +12 -0
  69. package/dist/commands/upload.d.ts.map +1 -0
  70. package/dist/commands/upload.js +158 -0
  71. package/dist/config/defaults.d.ts +21 -0
  72. package/dist/config/defaults.d.ts.map +1 -0
  73. package/dist/config/defaults.js +49 -0
  74. package/dist/config/loader.d.ts +66 -0
  75. package/dist/config/loader.d.ts.map +1 -0
  76. package/dist/config/loader.js +167 -0
  77. package/dist/config/schema.d.ts +55 -0
  78. package/dist/config/schema.d.ts.map +1 -0
  79. package/dist/config/schema.js +6 -0
  80. package/dist/index.d.ts +9 -0
  81. package/dist/index.d.ts.map +1 -0
  82. package/dist/index.js +1090 -0
  83. package/dist/interactive/fix-wizard.d.ts +44 -0
  84. package/dist/interactive/fix-wizard.d.ts.map +1 -0
  85. package/dist/interactive/fix-wizard.js +286 -0
  86. package/dist/interactive/init-wizard.d.ts +32 -0
  87. package/dist/interactive/init-wizard.d.ts.map +1 -0
  88. package/dist/interactive/init-wizard.js +193 -0
  89. package/dist/interactive/prompts.d.ts +62 -0
  90. package/dist/interactive/prompts.d.ts.map +1 -0
  91. package/dist/interactive/prompts.js +78 -0
  92. package/dist/monorepo/detector.d.ts +70 -0
  93. package/dist/monorepo/detector.d.ts.map +1 -0
  94. package/dist/monorepo/detector.js +278 -0
  95. package/dist/monorepo/index.d.ts +9 -0
  96. package/dist/monorepo/index.d.ts.map +1 -0
  97. package/dist/monorepo/index.js +8 -0
  98. package/dist/monorepo/workspace.d.ts +142 -0
  99. package/dist/monorepo/workspace.d.ts.map +1 -0
  100. package/dist/monorepo/workspace.js +171 -0
  101. package/dist/output/envelope.d.ts +21 -0
  102. package/dist/output/envelope.d.ts.map +1 -0
  103. package/dist/output/envelope.js +27 -0
  104. package/dist/output/factory.d.ts +73 -0
  105. package/dist/output/factory.d.ts.map +1 -0
  106. package/dist/output/factory.js +60 -0
  107. package/dist/output/formats.d.ts +11 -0
  108. package/dist/output/formats.d.ts.map +1 -0
  109. package/dist/output/formats.js +41 -0
  110. package/dist/output/html.d.ts +45 -0
  111. package/dist/output/html.d.ts.map +1 -0
  112. package/dist/output/html.js +607 -0
  113. package/dist/output/human.d.ts +41 -0
  114. package/dist/output/human.d.ts.map +1 -0
  115. package/dist/output/human.js +274 -0
  116. package/dist/output/json.d.ts +42 -0
  117. package/dist/output/json.d.ts.map +1 -0
  118. package/dist/output/json.js +37 -0
  119. package/dist/output/junit.d.ts +56 -0
  120. package/dist/output/junit.d.ts.map +1 -0
  121. package/dist/output/junit.js +135 -0
  122. package/dist/output/markdown.d.ts +77 -0
  123. package/dist/output/markdown.d.ts.map +1 -0
  124. package/dist/output/markdown.js +411 -0
  125. package/dist/output/sarif.d.ts +160 -0
  126. package/dist/output/sarif.d.ts.map +1 -0
  127. package/dist/output/sarif.js +207 -0
  128. package/dist/policy/evaluator.d.ts +111 -0
  129. package/dist/policy/evaluator.d.ts.map +1 -0
  130. package/dist/policy/evaluator.js +362 -0
  131. package/dist/policy/index.d.ts +15 -0
  132. package/dist/policy/index.d.ts.map +1 -0
  133. package/dist/policy/index.js +11 -0
  134. package/dist/policy/loader.d.ts +97 -0
  135. package/dist/policy/loader.d.ts.map +1 -0
  136. package/dist/policy/loader.js +281 -0
  137. package/dist/policy/schema.d.ts +297 -0
  138. package/dist/policy/schema.d.ts.map +1 -0
  139. package/dist/policy/schema.js +230 -0
  140. package/dist/quality-gate/evaluator.d.ts +58 -0
  141. package/dist/quality-gate/evaluator.d.ts.map +1 -0
  142. package/dist/quality-gate/evaluator.js +274 -0
  143. package/dist/quality-gate/index.d.ts +10 -0
  144. package/dist/quality-gate/index.d.ts.map +1 -0
  145. package/dist/quality-gate/index.js +7 -0
  146. package/dist/quality-gate/types.d.ts +103 -0
  147. package/dist/quality-gate/types.d.ts.map +1 -0
  148. package/dist/quality-gate/types.js +23 -0
  149. package/dist/templates/azure-devops.d.ts +25 -0
  150. package/dist/templates/azure-devops.d.ts.map +1 -0
  151. package/dist/templates/azure-devops.js +109 -0
  152. package/dist/templates/circleci.d.ts +28 -0
  153. package/dist/templates/circleci.d.ts.map +1 -0
  154. package/dist/templates/circleci.js +86 -0
  155. package/dist/templates/github-actions.d.ts +81 -0
  156. package/dist/templates/github-actions.d.ts.map +1 -0
  157. package/dist/templates/github-actions.js +393 -0
  158. package/dist/templates/gitlab-ci.d.ts +26 -0
  159. package/dist/templates/gitlab-ci.d.ts.map +1 -0
  160. package/dist/templates/gitlab-ci.js +70 -0
  161. package/dist/templates/index.d.ts +72 -0
  162. package/dist/templates/index.d.ts.map +1 -0
  163. package/dist/templates/index.js +112 -0
  164. package/dist/templates/jenkins.d.ts +26 -0
  165. package/dist/templates/jenkins.d.ts.map +1 -0
  166. package/dist/templates/jenkins.js +110 -0
  167. package/dist/ui/banner.d.ts +31 -0
  168. package/dist/ui/banner.d.ts.map +1 -0
  169. package/dist/ui/banner.js +84 -0
  170. package/dist/ui/diagnostics.d.ts +39 -0
  171. package/dist/ui/diagnostics.d.ts.map +1 -0
  172. package/dist/ui/diagnostics.js +153 -0
  173. package/dist/ui/spinner.d.ts +61 -0
  174. package/dist/ui/spinner.d.ts.map +1 -0
  175. package/dist/ui/spinner.js +101 -0
  176. package/dist/ui/table.d.ts +63 -0
  177. package/dist/ui/table.d.ts.map +1 -0
  178. package/dist/ui/table.js +236 -0
  179. package/dist/utils/client.d.ts +82 -0
  180. package/dist/utils/client.d.ts.map +1 -0
  181. package/dist/utils/client.js +128 -0
  182. package/dist/utils/detect-env.d.ts +59 -0
  183. package/dist/utils/detect-env.d.ts.map +1 -0
  184. package/dist/utils/detect-env.js +115 -0
  185. package/dist/utils/exit-codes.d.ts +47 -0
  186. package/dist/utils/exit-codes.d.ts.map +1 -0
  187. package/dist/utils/exit-codes.js +61 -0
  188. package/dist/utils/logger.d.ts +87 -0
  189. package/dist/utils/logger.d.ts.map +1 -0
  190. package/dist/utils/logger.js +185 -0
  191. package/dist/utils/sanitize.d.ts +36 -0
  192. package/dist/utils/sanitize.d.ts.map +1 -0
  193. package/dist/utils/sanitize.js +64 -0
  194. package/dist/utils/validators.d.ts +41 -0
  195. package/dist/utils/validators.d.ts.map +1 -0
  196. package/dist/utils/validators.js +123 -0
  197. package/package.json +63 -0
  198. package/schemas/vertaaux.config.schema.json +103 -0
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Secure token storage for VertaaUX CLI.
3
+ *
4
+ * Tokens are stored in ~/.vertaaux/credentials.json with restrictive permissions.
5
+ * This is separate from project config - tokens are user-scoped, not project-scoped.
6
+ */
7
+ /**
8
+ * Token data structure.
9
+ */
10
+ export interface TokenData {
11
+ /** OAuth access token */
12
+ accessToken: string;
13
+ /** OAuth refresh token (optional for CI tokens) */
14
+ refreshToken?: string;
15
+ /** Token expiration timestamp (ISO 8601) */
16
+ expiresAt?: string;
17
+ /** Token type: device (interactive) or ci (API key) */
18
+ type: "device" | "ci";
19
+ /** When token was saved */
20
+ savedAt: string;
21
+ }
22
+ /**
23
+ * Get the credentials file path.
24
+ * Uses ~/.vertaaux/credentials.json
25
+ */
26
+ export declare function getCredentialsPath(): string;
27
+ /**
28
+ * Save token data to credentials file.
29
+ *
30
+ * Creates ~/.vertaaux directory if needed.
31
+ * Writes with restrictive permissions (0o600).
32
+ *
33
+ * @param token - Token data to save
34
+ */
35
+ export declare function saveToken(token: TokenData): Promise<void>;
36
+ /**
37
+ * Load token data from credentials file.
38
+ *
39
+ * @returns Token data or null if file doesn't exist
40
+ */
41
+ export declare function loadToken(): Promise<TokenData | null>;
42
+ /**
43
+ * Clear stored token by deleting credentials file.
44
+ */
45
+ export declare function clearToken(): Promise<void>;
46
+ /**
47
+ * Check if token is expired.
48
+ *
49
+ * @param token - Token data to check
50
+ * @returns true if token is expired or will expire within 5 minutes
51
+ */
52
+ export declare function isTokenExpired(token: TokenData): boolean;
53
+ //# sourceMappingURL=token-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../src/auth/token-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,yBAAyB;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAY/D;AAED;;;;GAIG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAa3D;AAED;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAMhD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAUxD"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Secure token storage for VertaaUX CLI.
3
+ *
4
+ * Tokens are stored in ~/.vertaaux/credentials.json with restrictive permissions.
5
+ * This is separate from project config - tokens are user-scoped, not project-scoped.
6
+ */
7
+ import { readFile, writeFile, mkdir, unlink } from "fs/promises";
8
+ import { existsSync } from "fs";
9
+ import { homedir } from "os";
10
+ import { join, dirname } from "path";
11
+ /**
12
+ * Get the credentials file path.
13
+ * Uses ~/.vertaaux/credentials.json
14
+ */
15
+ export function getCredentialsPath() {
16
+ return join(homedir(), ".vertaaux", "credentials.json");
17
+ }
18
+ /**
19
+ * Save token data to credentials file.
20
+ *
21
+ * Creates ~/.vertaaux directory if needed.
22
+ * Writes with restrictive permissions (0o600).
23
+ *
24
+ * @param token - Token data to save
25
+ */
26
+ export async function saveToken(token) {
27
+ const credPath = getCredentialsPath();
28
+ const dir = dirname(credPath);
29
+ // Create directory if needed
30
+ if (!existsSync(dir)) {
31
+ await mkdir(dir, { recursive: true, mode: 0o700 });
32
+ }
33
+ // Write token with restrictive permissions
34
+ const content = JSON.stringify(token, null, 2);
35
+ await writeFile(credPath, content + "\n", { encoding: "utf-8", mode: 0o600 });
36
+ }
37
+ /**
38
+ * Load token data from credentials file.
39
+ *
40
+ * @returns Token data or null if file doesn't exist
41
+ */
42
+ export async function loadToken() {
43
+ const credPath = getCredentialsPath();
44
+ if (!existsSync(credPath)) {
45
+ return null;
46
+ }
47
+ try {
48
+ const content = await readFile(credPath, "utf-8");
49
+ return JSON.parse(content);
50
+ }
51
+ catch {
52
+ return null;
53
+ }
54
+ }
55
+ /**
56
+ * Clear stored token by deleting credentials file.
57
+ */
58
+ export async function clearToken() {
59
+ const credPath = getCredentialsPath();
60
+ if (existsSync(credPath)) {
61
+ await unlink(credPath);
62
+ }
63
+ }
64
+ /**
65
+ * Check if token is expired.
66
+ *
67
+ * @param token - Token data to check
68
+ * @returns true if token is expired or will expire within 5 minutes
69
+ */
70
+ export function isTokenExpired(token) {
71
+ if (!token.expiresAt) {
72
+ return false; // CI tokens don't expire
73
+ }
74
+ const expiresAt = new Date(token.expiresAt);
75
+ const now = new Date();
76
+ const fiveMinutes = 5 * 60 * 1000;
77
+ return expiresAt.getTime() - now.getTime() < fiveMinutes;
78
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Diff computation between audit runs.
3
+ *
4
+ * Compares current audit results against baseline or previous audit.
5
+ * Shows three categories:
6
+ * - New: Issues in current but not in baseline
7
+ * - Fixed: Issues in baseline but not in current
8
+ * - Present: Issues in both current and baseline
9
+ */
10
+ import { type Issue } from "./hash.js";
11
+ import type { BaselineFile, BaselineIssue } from "./manager.js";
12
+ /**
13
+ * Diff result with categorized issues.
14
+ */
15
+ export interface DiffResult {
16
+ /** New issues not in baseline */
17
+ new: Issue[];
18
+ /** Issues in baseline but fixed in current */
19
+ fixed: BaselineIssue[];
20
+ /** Issues still present (in both) */
21
+ present: Issue[];
22
+ /** Summary counts */
23
+ summary: {
24
+ newCount: number;
25
+ fixedCount: number;
26
+ presentCount: number;
27
+ };
28
+ }
29
+ /**
30
+ * Compute diff between current issues and baseline.
31
+ *
32
+ * @param currentIssues - Issues from current audit
33
+ * @param baseline - Baseline to compare against
34
+ * @returns Diff result with new/fixed/present categories
35
+ */
36
+ export declare function computeDiff(currentIssues: Issue[], baseline: BaselineFile): DiffResult;
37
+ /**
38
+ * Format diff result for human-readable output.
39
+ *
40
+ * Uses colors:
41
+ * - New issues: red
42
+ * - Fixed issues: green
43
+ * - Still present: dim
44
+ *
45
+ * @param diff - Diff result to format
46
+ * @param verbose - Show all present issues (default: false)
47
+ * @returns Formatted string for console output
48
+ */
49
+ export declare function formatDiffHuman(diff: DiffResult, verbose?: boolean): string;
50
+ /**
51
+ * Format diff result as JSON.
52
+ *
53
+ * @param diff - Diff result to format
54
+ * @returns JSON-formatted string
55
+ */
56
+ export declare function formatDiffJson(diff: DiffResult): string;
57
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/baseline/diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAuB,KAAK,KAAK,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,iCAAiC;IACjC,GAAG,EAAE,KAAK,EAAE,CAAC;IACb,8CAA8C;IAC9C,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,qCAAqC;IACrC,OAAO,EAAE,KAAK,EAAE,CAAC;IACjB,qBAAqB;IACrB,OAAO,EAAE;QACP,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,aAAa,EAAE,KAAK,EAAE,EACtB,QAAQ,EAAE,YAAY,GACrB,UAAU,CA2CZ;AA2CD;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,UAAQ,GAAG,MAAM,CAsCzE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAEvD"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Diff computation between audit runs.
3
+ *
4
+ * Compares current audit results against baseline or previous audit.
5
+ * Shows three categories:
6
+ * - New: Issues in current but not in baseline
7
+ * - Fixed: Issues in baseline but not in current
8
+ * - Present: Issues in both current and baseline
9
+ */
10
+ import chalk from "chalk";
11
+ import { generateFingerprint } from "./hash.js";
12
+ /**
13
+ * Compute diff between current issues and baseline.
14
+ *
15
+ * @param currentIssues - Issues from current audit
16
+ * @param baseline - Baseline to compare against
17
+ * @returns Diff result with new/fixed/present categories
18
+ */
19
+ export function computeDiff(currentIssues, baseline) {
20
+ // Build set of baseline fingerprints for fast lookup
21
+ const baselineFingerprints = new Set(baseline.issues.map((issue) => issue.fingerprint));
22
+ // Build map of current fingerprints to issues
23
+ const currentByFingerprint = new Map();
24
+ for (const issue of currentIssues) {
25
+ const fingerprint = generateFingerprint(issue);
26
+ currentByFingerprint.set(fingerprint, issue);
27
+ }
28
+ // Categorize issues
29
+ const newIssues = [];
30
+ const presentIssues = [];
31
+ for (const [fingerprint, issue] of currentByFingerprint) {
32
+ if (baselineFingerprints.has(fingerprint)) {
33
+ presentIssues.push(issue);
34
+ }
35
+ else {
36
+ newIssues.push(issue);
37
+ }
38
+ }
39
+ // Find fixed issues (in baseline but not in current)
40
+ const fixedIssues = [];
41
+ for (const baselineIssue of baseline.issues) {
42
+ if (!currentByFingerprint.has(baselineIssue.fingerprint)) {
43
+ fixedIssues.push(baselineIssue);
44
+ }
45
+ }
46
+ return {
47
+ new: newIssues,
48
+ fixed: fixedIssues,
49
+ present: presentIssues,
50
+ summary: {
51
+ newCount: newIssues.length,
52
+ fixedCount: fixedIssues.length,
53
+ presentCount: presentIssues.length,
54
+ },
55
+ };
56
+ }
57
+ /**
58
+ * Get rule ID from an issue, checking multiple field names.
59
+ */
60
+ function getRuleId(issue) {
61
+ return issue.ruleId || issue.rule_id || issue.id || "unknown";
62
+ }
63
+ /**
64
+ * Format severity badge for display.
65
+ */
66
+ function formatSeverityBadge(severity) {
67
+ const upper = (severity || "info").toUpperCase();
68
+ switch (upper) {
69
+ case "ERROR":
70
+ case "CRITICAL":
71
+ return chalk.red(`[${upper}]`);
72
+ case "WARNING":
73
+ case "SERIOUS":
74
+ return chalk.yellow(`[${upper}]`);
75
+ case "INFO":
76
+ case "MINOR":
77
+ return chalk.blue(`[${upper}]`);
78
+ default:
79
+ return chalk.gray(`[${upper}]`);
80
+ }
81
+ }
82
+ /**
83
+ * Format issue line for display.
84
+ */
85
+ function formatIssueLine(issue) {
86
+ const ruleId = "ruleId" in issue ? issue.ruleId : getRuleId(issue);
87
+ const description = "description" in issue
88
+ ? issue.description
89
+ : issue.description || issue.title || "";
90
+ const severity = issue.severity || "info";
91
+ return `${formatSeverityBadge(severity)} ${ruleId}: ${description}`;
92
+ }
93
+ /**
94
+ * Format diff result for human-readable output.
95
+ *
96
+ * Uses colors:
97
+ * - New issues: red
98
+ * - Fixed issues: green
99
+ * - Still present: dim
100
+ *
101
+ * @param diff - Diff result to format
102
+ * @param verbose - Show all present issues (default: false)
103
+ * @returns Formatted string for console output
104
+ */
105
+ export function formatDiffHuman(diff, verbose = false) {
106
+ const lines = [];
107
+ // New issues section (red)
108
+ lines.push(chalk.red.bold(`NEW ISSUES (${diff.summary.newCount})`));
109
+ if (diff.new.length === 0) {
110
+ lines.push(chalk.dim(" No new issues"));
111
+ }
112
+ else {
113
+ for (const issue of diff.new) {
114
+ lines.push(` ${formatIssueLine(issue)}`);
115
+ }
116
+ }
117
+ lines.push("");
118
+ // Fixed issues section (green)
119
+ lines.push(chalk.green.bold(`FIXED (${diff.summary.fixedCount})`));
120
+ if (diff.fixed.length === 0) {
121
+ lines.push(chalk.dim(" No issues fixed"));
122
+ }
123
+ else {
124
+ for (const issue of diff.fixed) {
125
+ lines.push(` ${formatIssueLine(issue)}`);
126
+ }
127
+ }
128
+ lines.push("");
129
+ // Still present section (dim)
130
+ lines.push(chalk.dim.bold(`STILL PRESENT (${diff.summary.presentCount})`));
131
+ if (diff.present.length === 0) {
132
+ lines.push(chalk.dim(" No baselined issues remain"));
133
+ }
134
+ else if (verbose) {
135
+ for (const issue of diff.present) {
136
+ lines.push(chalk.dim(` ${formatIssueLine(issue)}`));
137
+ }
138
+ }
139
+ else {
140
+ lines.push(chalk.dim(" (use --verbose to show all)"));
141
+ }
142
+ return lines.join("\n");
143
+ }
144
+ /**
145
+ * Format diff result as JSON.
146
+ *
147
+ * @param diff - Diff result to format
148
+ * @returns JSON-formatted string
149
+ */
150
+ export function formatDiffJson(diff) {
151
+ return JSON.stringify(diff, null, 2);
152
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Stable fingerprint generation for baseline matching.
3
+ *
4
+ * Generates hash-based fingerprints that remain stable across:
5
+ * - Code reformatting
6
+ * - Line number changes
7
+ * - Dynamic data attribute changes
8
+ *
9
+ * Matches SDK finding ID format for cross-surface consistency (CROSS-01).
10
+ */
11
+ /**
12
+ * Issue type from audit results.
13
+ */
14
+ export interface Issue {
15
+ id?: string;
16
+ title?: string;
17
+ severity?: string;
18
+ category?: string;
19
+ description?: string;
20
+ recommendation?: string;
21
+ recommended_fix?: string;
22
+ wcag_reference?: string;
23
+ selector?: string;
24
+ ruleId?: string;
25
+ rule_id?: string;
26
+ }
27
+ /**
28
+ * Normalize a CSS selector for stable fingerprinting.
29
+ *
30
+ * Removes dynamic/unstable parts:
31
+ * - data-* attributes (often contain generated IDs)
32
+ * - :nth-child indices (change with DOM order)
33
+ * - Extra whitespace
34
+ *
35
+ * @param selector - Raw CSS selector from audit
36
+ * @returns Normalized selector for hashing
37
+ */
38
+ export declare function normalizeSelector(selector: string): string;
39
+ /**
40
+ * Generate a stable fingerprint for an issue.
41
+ *
42
+ * Hash is based on:
43
+ * - Rule ID (type of issue)
44
+ * - Normalized selector (where the issue is)
45
+ * - First 50 chars of description (what the issue is)
46
+ *
47
+ * This matches SDK finding ID format: {ruleId}:{hash16}
48
+ * for cross-surface consistency (CROSS-01).
49
+ *
50
+ * @param issue - Issue from audit results
51
+ * @returns 16-character hex fingerprint
52
+ */
53
+ export declare function generateFingerprint(issue: Issue): string;
54
+ //# sourceMappingURL=hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/baseline/hash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAe1D;AASD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAWxD"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Stable fingerprint generation for baseline matching.
3
+ *
4
+ * Generates hash-based fingerprints that remain stable across:
5
+ * - Code reformatting
6
+ * - Line number changes
7
+ * - Dynamic data attribute changes
8
+ *
9
+ * Matches SDK finding ID format for cross-surface consistency (CROSS-01).
10
+ */
11
+ import { createHash } from "crypto";
12
+ /**
13
+ * Normalize a CSS selector for stable fingerprinting.
14
+ *
15
+ * Removes dynamic/unstable parts:
16
+ * - data-* attributes (often contain generated IDs)
17
+ * - :nth-child indices (change with DOM order)
18
+ * - Extra whitespace
19
+ *
20
+ * @param selector - Raw CSS selector from audit
21
+ * @returns Normalized selector for hashing
22
+ */
23
+ export function normalizeSelector(selector) {
24
+ if (!selector)
25
+ return "";
26
+ return (selector
27
+ // Remove data attributes: [data-testid="foo"], [data-v-abc123], etc.
28
+ .replace(/\[data-[^\]]+\]/g, "")
29
+ // Remove nth-child indices: :nth-child(2), :nth-of-type(5)
30
+ .replace(/:nth-(?:child|of-type)\(\d+\)/g, "")
31
+ // Normalize whitespace: collapse multiple spaces, trim
32
+ .replace(/\s+/g, " ")
33
+ .trim()
34
+ // Lowercase for consistency
35
+ .toLowerCase());
36
+ }
37
+ /**
38
+ * Get the rule ID from an issue, checking multiple field names.
39
+ */
40
+ function getRuleId(issue) {
41
+ return issue.ruleId || issue.rule_id || issue.id || "";
42
+ }
43
+ /**
44
+ * Generate a stable fingerprint for an issue.
45
+ *
46
+ * Hash is based on:
47
+ * - Rule ID (type of issue)
48
+ * - Normalized selector (where the issue is)
49
+ * - First 50 chars of description (what the issue is)
50
+ *
51
+ * This matches SDK finding ID format: {ruleId}:{hash16}
52
+ * for cross-surface consistency (CROSS-01).
53
+ *
54
+ * @param issue - Issue from audit results
55
+ * @returns 16-character hex fingerprint
56
+ */
57
+ export function generateFingerprint(issue) {
58
+ const ruleId = getRuleId(issue);
59
+ const normalizedSelector = normalizeSelector(issue.selector || "");
60
+ const descriptionPrefix = (issue.description || "").slice(0, 50);
61
+ // Combine fields for hashing
62
+ const input = `${ruleId}|${normalizedSelector}|${descriptionPrefix}`;
63
+ // SHA-256 hash, take first 16 hex chars
64
+ const hash = createHash("sha256").update(input).digest("hex");
65
+ return hash.slice(0, 16);
66
+ }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Baseline file management for tracking technical debt.
3
+ *
4
+ * Enables teams to:
5
+ * - Create baselines from audit results
6
+ * - Add individual issues to baseline (ignore)
7
+ * - Load and save baseline files
8
+ *
9
+ * Baseline is stored in .vertaaux/baseline.json and committed to git.
10
+ */
11
+ import { type Issue } from "./hash.js";
12
+ /**
13
+ * Current baseline file format version.
14
+ */
15
+ export declare const BASELINE_VERSION = 1;
16
+ /**
17
+ * Default baseline file path.
18
+ */
19
+ export declare const DEFAULT_BASELINE_PATH = ".vertaaux/baseline.json";
20
+ /**
21
+ * Issue stored in baseline with metadata.
22
+ */
23
+ export interface BaselineIssue {
24
+ /** Stable fingerprint for matching */
25
+ fingerprint: string;
26
+ /** Rule/issue type ID */
27
+ ruleId: string;
28
+ /** Severity: error, warning, info */
29
+ severity: string;
30
+ /** Category: accessibility, ux, performance, etc. */
31
+ category: string;
32
+ /** Issue description */
33
+ description: string;
34
+ /** CSS selector where issue occurs */
35
+ selector?: string;
36
+ /** Reason for baselining (optional) */
37
+ reason?: string;
38
+ /** When issue was added to baseline */
39
+ baselinedAt: string;
40
+ /** Who added the issue (from git config) */
41
+ baselinedBy?: string;
42
+ }
43
+ /**
44
+ * Baseline file structure.
45
+ */
46
+ export interface BaselineFile {
47
+ /** File format version */
48
+ version: number;
49
+ /** When baseline was first created */
50
+ created: string;
51
+ /** When baseline was last updated */
52
+ updated: string;
53
+ /** URL that was audited */
54
+ url: string;
55
+ /** Baselined issues */
56
+ issues: BaselineIssue[];
57
+ }
58
+ /**
59
+ * Load a baseline file from disk.
60
+ *
61
+ * @param path - Path to baseline file (default: .vertaaux/baseline.json)
62
+ * @returns Baseline file contents or null if file doesn't exist
63
+ */
64
+ export declare function loadBaseline(path?: string): Promise<BaselineFile | null>;
65
+ /**
66
+ * Save a baseline file to disk.
67
+ *
68
+ * @param baseline - Baseline file contents
69
+ * @param path - Path to baseline file (default: .vertaaux/baseline.json)
70
+ */
71
+ export declare function saveBaseline(baseline: BaselineFile, path?: string): Promise<void>;
72
+ /**
73
+ * Create a new baseline from audit issues.
74
+ *
75
+ * @param issues - Issues from audit results
76
+ * @param url - URL that was audited
77
+ * @returns New baseline file
78
+ */
79
+ export declare function createBaseline(issues: Issue[], url: string): BaselineFile;
80
+ /**
81
+ * Add an issue to an existing baseline.
82
+ *
83
+ * @param baseline - Existing baseline file
84
+ * @param issue - Issue to add
85
+ * @param reason - Optional reason for baselining
86
+ * @returns Updated baseline file
87
+ */
88
+ export declare function addToBaseline(baseline: BaselineFile, issue: Issue, reason?: string): BaselineFile;
89
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/baseline/manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,EAAuB,KAAK,KAAK,EAAE,MAAM,WAAW,CAAC;AAE5D;;GAEG;AACH,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC;;GAEG;AACH,eAAO,MAAM,qBAAqB,4BAA4B,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,wBAAwB;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,0BAA0B;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,2BAA2B;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,uBAAuB;IACvB,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AA0BD;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,IAAI,GAAE,MAA8B,GACnC,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAwB9B;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,YAAY,EACtB,IAAI,GAAE,MAA8B,GACnC,OAAO,CAAC,IAAI,CAAC,CAYf;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAsBzE;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,YAAY,EACtB,KAAK,EAAE,KAAK,EACZ,MAAM,CAAC,EAAE,MAAM,GACd,YAAY,CAoCd"}