@bouncesecurity/aghast 0.0.13

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 (97) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +111 -0
  3. package/config/prompts/generic-instructions.md +56 -0
  4. package/config/prompts/test-cheaper-instructions.md +57 -0
  5. package/dist/check-library.d.ts +87 -0
  6. package/dist/check-library.d.ts.map +1 -0
  7. package/dist/check-library.js +374 -0
  8. package/dist/check-library.js.map +1 -0
  9. package/dist/claude-code-provider.d.ts +26 -0
  10. package/dist/claude-code-provider.d.ts.map +1 -0
  11. package/dist/claude-code-provider.js +247 -0
  12. package/dist/claude-code-provider.js.map +1 -0
  13. package/dist/cli.d.ts +13 -0
  14. package/dist/cli.d.ts.map +1 -0
  15. package/dist/cli.js +78 -0
  16. package/dist/cli.js.map +1 -0
  17. package/dist/colors.d.ts +7 -0
  18. package/dist/colors.d.ts.map +1 -0
  19. package/dist/colors.js +18 -0
  20. package/dist/colors.js.map +1 -0
  21. package/dist/error-codes.d.ts +42 -0
  22. package/dist/error-codes.d.ts.map +1 -0
  23. package/dist/error-codes.js +60 -0
  24. package/dist/error-codes.js.map +1 -0
  25. package/dist/formatters/index.d.ts +10 -0
  26. package/dist/formatters/index.d.ts.map +1 -0
  27. package/dist/formatters/index.js +23 -0
  28. package/dist/formatters/index.js.map +1 -0
  29. package/dist/formatters/json-formatter.d.ts +11 -0
  30. package/dist/formatters/json-formatter.d.ts.map +1 -0
  31. package/dist/formatters/json-formatter.js +11 -0
  32. package/dist/formatters/json-formatter.js.map +1 -0
  33. package/dist/formatters/sarif-formatter.d.ts +18 -0
  34. package/dist/formatters/sarif-formatter.d.ts.map +1 -0
  35. package/dist/formatters/sarif-formatter.js +103 -0
  36. package/dist/formatters/sarif-formatter.js.map +1 -0
  37. package/dist/formatters/types.d.ts +11 -0
  38. package/dist/formatters/types.d.ts.map +1 -0
  39. package/dist/formatters/types.js +6 -0
  40. package/dist/formatters/types.js.map +1 -0
  41. package/dist/index.d.ts +7 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +406 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/logging.d.ts +26 -0
  46. package/dist/logging.d.ts.map +1 -0
  47. package/dist/logging.js +79 -0
  48. package/dist/logging.js.map +1 -0
  49. package/dist/mock-ai-provider.d.ts +18 -0
  50. package/dist/mock-ai-provider.d.ts.map +1 -0
  51. package/dist/mock-ai-provider.js +28 -0
  52. package/dist/mock-ai-provider.js.map +1 -0
  53. package/dist/new-check.d.ts +13 -0
  54. package/dist/new-check.d.ts.map +1 -0
  55. package/dist/new-check.js +405 -0
  56. package/dist/new-check.js.map +1 -0
  57. package/dist/prompt-template.d.ts +12 -0
  58. package/dist/prompt-template.d.ts.map +1 -0
  59. package/dist/prompt-template.js +35 -0
  60. package/dist/prompt-template.js.map +1 -0
  61. package/dist/provider-registry.d.ts +15 -0
  62. package/dist/provider-registry.d.ts.map +1 -0
  63. package/dist/provider-registry.js +27 -0
  64. package/dist/provider-registry.js.map +1 -0
  65. package/dist/repository-analyzer.d.ts +68 -0
  66. package/dist/repository-analyzer.d.ts.map +1 -0
  67. package/dist/repository-analyzer.js +230 -0
  68. package/dist/repository-analyzer.js.map +1 -0
  69. package/dist/response-parser.d.ts +12 -0
  70. package/dist/response-parser.d.ts.map +1 -0
  71. package/dist/response-parser.js +109 -0
  72. package/dist/response-parser.js.map +1 -0
  73. package/dist/runtime-config.d.ts +15 -0
  74. package/dist/runtime-config.d.ts.map +1 -0
  75. package/dist/runtime-config.js +73 -0
  76. package/dist/runtime-config.js.map +1 -0
  77. package/dist/sarif-parser.d.ts +20 -0
  78. package/dist/sarif-parser.d.ts.map +1 -0
  79. package/dist/sarif-parser.js +76 -0
  80. package/dist/sarif-parser.js.map +1 -0
  81. package/dist/scan-runner.d.ts +29 -0
  82. package/dist/scan-runner.d.ts.map +1 -0
  83. package/dist/scan-runner.js +559 -0
  84. package/dist/scan-runner.js.map +1 -0
  85. package/dist/semgrep-runner.d.ts +25 -0
  86. package/dist/semgrep-runner.d.ts.map +1 -0
  87. package/dist/semgrep-runner.js +100 -0
  88. package/dist/semgrep-runner.js.map +1 -0
  89. package/dist/snippet-extractor.d.ts +25 -0
  90. package/dist/snippet-extractor.d.ts.map +1 -0
  91. package/dist/snippet-extractor.js +56 -0
  92. package/dist/snippet-extractor.js.map +1 -0
  93. package/dist/types.d.ts +206 -0
  94. package/dist/types.d.ts.map +1 -0
  95. package/dist/types.js +19 -0
  96. package/dist/types.js.map +1 -0
  97. package/package.json +55 -0
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Claude Code AI provider implementation.
3
+ * Uses @anthropic-ai/claude-agent-sdk per spec Section 6.2 / Appendix C.8.
4
+ */
5
+ import { DEFAULT_AI_MODEL, FatalProviderError } from './types.js';
6
+ // import { parseAIResponse } from './response-parser.js';
7
+ import { logProgress, logDebug, logDebugFull, createTimer } from './logging.js';
8
+ const TAG = 'ai-provider';
9
+ const HEARTBEAT_INTERVAL_MS = 15000; // Log heartbeat every 15s if no activity
10
+ const MAX_API_ERROR_RETRIES = 3; // Fail after this many consecutive API errors
11
+ // JSON schema for structured output (matches spec Section 4.4)
12
+ const OUTPUT_SCHEMA = {
13
+ type: 'object',
14
+ properties: {
15
+ issues: {
16
+ type: 'array',
17
+ items: {
18
+ type: 'object',
19
+ properties: {
20
+ file: { type: 'string' },
21
+ startLine: { type: 'integer' },
22
+ endLine: { type: 'integer' },
23
+ description: { type: 'string' },
24
+ dataFlow: {
25
+ type: 'array',
26
+ items: {
27
+ type: 'object',
28
+ properties: {
29
+ file: { type: 'string' },
30
+ lineNumber: { type: 'integer' },
31
+ label: { type: 'string' },
32
+ },
33
+ required: ['file', 'lineNumber', 'label'],
34
+ additionalProperties: false,
35
+ },
36
+ },
37
+ },
38
+ required: ['file', 'startLine', 'endLine', 'description'],
39
+ additionalProperties: false,
40
+ },
41
+ },
42
+ },
43
+ required: ['issues'],
44
+ additionalProperties: false,
45
+ };
46
+ export class ClaudeCodeProvider {
47
+ apiKey;
48
+ useLocalClaude = false;
49
+ model = DEFAULT_AI_MODEL;
50
+ _queryFn;
51
+ debugEnabled = false;
52
+ constructor(options) {
53
+ this._queryFn = options?._queryFn;
54
+ }
55
+ async initialize(config) {
56
+ this.useLocalClaude = process.env.AGHAST_LOCAL_CLAUDE === 'true';
57
+ this.apiKey = config.apiKey ?? process.env.ANTHROPIC_API_KEY;
58
+ // Model selection priority: config.model (from AGHAST_AI_MODEL env or runtime config) > DEFAULT_AI_MODEL
59
+ if (config.model) {
60
+ this.model = config.model;
61
+ }
62
+ if (!this.apiKey && !this.useLocalClaude) {
63
+ throw new Error('ANTHROPIC_API_KEY is required (or set AGHAST_LOCAL_CLAUDE=true to use your local Claude Code session)');
64
+ }
65
+ if (this.useLocalClaude) {
66
+ logProgress(TAG, 'Using local Claude Code session for authentication');
67
+ }
68
+ else {
69
+ logDebug(TAG, 'Using API key for authentication');
70
+ }
71
+ logDebug(TAG, `Provider initialized with model ${this.model}`);
72
+ }
73
+ getModelName() {
74
+ return this.model;
75
+ }
76
+ enableDebug() {
77
+ this.debugEnabled = true;
78
+ }
79
+ async executeCheck(instructions, repositoryPath, logPrefix) {
80
+ const queryFn = this._queryFn ?? (await import('@anthropic-ai/claude-agent-sdk')).query;
81
+ const timer = createTimer();
82
+ const prefix = logPrefix ? `${logPrefix} ` : '';
83
+ const prompt = instructions;
84
+ logDebug(TAG, `${prefix}Starting query: model=${this.model}, cwd=${repositoryPath}, promptLen=${prompt.length}`);
85
+ if (this.debugEnabled) {
86
+ logDebugFull(TAG, `${prefix}Full prompt sent to AI`, prompt);
87
+ }
88
+ const conversation = queryFn({
89
+ prompt,
90
+ options: {
91
+ model: this.model,
92
+ cwd: repositoryPath,
93
+ allowedTools: ['Read', 'Glob', 'Grep', 'Bash', 'WebSearch', 'WebFetch'],
94
+ maxTurns: 100,
95
+ permissionMode: 'bypassPermissions',
96
+ outputFormat: {
97
+ type: 'json_schema',
98
+ schema: OUTPUT_SCHEMA,
99
+ },
100
+ },
101
+ });
102
+ // Consume all messages from the async generator to get the result
103
+ let resultText = '';
104
+ let structuredOutput;
105
+ let errorMessage;
106
+ let turnCount = 0;
107
+ let toolCallCount = 0;
108
+ let tokenUsage;
109
+ let consecutiveApiErrors = 0;
110
+ let currentToolName;
111
+ let lastActivityTime = Date.now();
112
+ // Background heartbeat timer - logs if no activity for a while
113
+ const heartbeatInterval = setInterval(() => {
114
+ const silentSeconds = Math.round((Date.now() - lastActivityTime) / 1000);
115
+ if (silentSeconds >= HEARTBEAT_INTERVAL_MS / 1000) {
116
+ const status = currentToolName ? `running ${currentToolName}` : 'waiting';
117
+ logProgress(TAG, `${prefix}Still ${status}... (${timer.elapsedStr()})`);
118
+ }
119
+ }, HEARTBEAT_INTERVAL_MS);
120
+ try {
121
+ for await (const message of conversation) {
122
+ lastActivityTime = Date.now();
123
+ // Tool progress events - emitted during long-running tool executions
124
+ if (message.type === 'tool_progress') {
125
+ const progress = message;
126
+ currentToolName = progress.tool_name;
127
+ logProgress(TAG, `${prefix}Running ${progress.tool_name}... (${Math.round(progress.elapsed_time_seconds)}s)`);
128
+ }
129
+ if (message.type === 'assistant') {
130
+ turnCount++;
131
+ currentToolName = undefined;
132
+ // Simple activity indicator at info level
133
+ logProgress(TAG, `${prefix}Turn ${turnCount} (${timer.elapsedStr()})`);
134
+ const content = message.message?.content;
135
+ if (Array.isArray(content)) {
136
+ // Count and log tool calls at debug level (compact)
137
+ for (const block of content) {
138
+ if (block?.type === 'tool_use') {
139
+ toolCallCount++;
140
+ currentToolName = block.name;
141
+ const inputStr = JSON.stringify(block.input);
142
+ const inputPreview = inputStr.length > 100 ? inputStr.slice(0, 100) + '...' : inputStr;
143
+ logDebug(TAG, `${prefix}Tool[${toolCallCount}]: ${block.name} ${inputPreview}`);
144
+ }
145
+ }
146
+ // Log assistant text at debug level
147
+ const textChunks = content
148
+ .filter((c) => c?.type === 'text' && typeof c.text === 'string')
149
+ .map((c) => c.text.trim())
150
+ .filter(Boolean);
151
+ if (textChunks.length > 0) {
152
+ logDebug(TAG, `${prefix}Assistant: ${textChunks.join(' | ')}`);
153
+ // Detect rate-limit messages — fail immediately since retrying won't help
154
+ const rateLimitMatch = textChunks.find((t) => /you've hit your limit|rate limit/i.test(t));
155
+ if (rateLimitMatch) {
156
+ throw new FatalProviderError(`AI provider rate limit reached: ${rateLimitMatch}`);
157
+ }
158
+ // Detect authentication errors (401) — fail immediately, unrecoverable
159
+ const authErrorMatch = textChunks.find((t) => /API Error:\s*401/i.test(t));
160
+ if (authErrorMatch) {
161
+ throw new FatalProviderError(`AI provider authentication failed (401): ${authErrorMatch}`);
162
+ }
163
+ // Detect API errors surfaced as assistant text by the SDK
164
+ const apiErrorMatch = textChunks.find((t) => t.includes('API Error:'));
165
+ if (apiErrorMatch) {
166
+ consecutiveApiErrors++;
167
+ if (consecutiveApiErrors >= MAX_API_ERROR_RETRIES) {
168
+ throw new Error(`AI provider API error (after ${MAX_API_ERROR_RETRIES} attempts): ${apiErrorMatch}`);
169
+ }
170
+ }
171
+ else {
172
+ consecutiveApiErrors = 0;
173
+ }
174
+ }
175
+ }
176
+ }
177
+ if (message.type === 'result') {
178
+ if (message.subtype === 'success') {
179
+ resultText = message.result;
180
+ // Extract structured output if available
181
+ const resultMsg = message;
182
+ if (resultMsg.structured_output) {
183
+ structuredOutput = resultMsg.structured_output;
184
+ logDebug(TAG, `${prefix}Structured output: ${structuredOutput.issues.length} issues`);
185
+ }
186
+ // Extract token usage if available.
187
+ // Prefer modelUsage (camelCase, per-model breakdown) over usage (snake_case, raw API).
188
+ if (resultMsg.modelUsage && Object.keys(resultMsg.modelUsage).length > 0) {
189
+ let inputTokens = 0;
190
+ let outputTokens = 0;
191
+ for (const model of Object.values(resultMsg.modelUsage)) {
192
+ inputTokens += model.inputTokens;
193
+ outputTokens += model.outputTokens;
194
+ }
195
+ tokenUsage = { inputTokens, outputTokens, totalTokens: inputTokens + outputTokens };
196
+ logDebug(TAG, `${prefix}Token usage: ${tokenUsage.inputTokens} in, ${tokenUsage.outputTokens} out, ${tokenUsage.totalTokens} total`);
197
+ }
198
+ else if (resultMsg.usage) {
199
+ tokenUsage = {
200
+ inputTokens: resultMsg.usage.input_tokens,
201
+ outputTokens: resultMsg.usage.output_tokens,
202
+ totalTokens: resultMsg.usage.input_tokens + resultMsg.usage.output_tokens,
203
+ };
204
+ logDebug(TAG, `${prefix}Token usage: ${tokenUsage.inputTokens} in, ${tokenUsage.outputTokens} out, ${tokenUsage.totalTokens} total`);
205
+ }
206
+ logProgress(TAG, `${prefix}Completed in ${timer.elapsedStr()} (${turnCount} turns, ${toolCallCount} tool calls)`);
207
+ }
208
+ else {
209
+ const errorResult = message;
210
+ errorMessage = errorResult.errors?.join('; ') ?? `AI provider error: ${errorResult.subtype}`;
211
+ logProgress(TAG, `${prefix}Failed: ${errorResult.subtype} (${timer.elapsedStr()})`);
212
+ }
213
+ }
214
+ }
215
+ }
216
+ finally {
217
+ clearInterval(heartbeatInterval);
218
+ }
219
+ if (errorMessage) {
220
+ logDebug(TAG, `${prefix}Error: ${errorMessage}`);
221
+ throw new Error(errorMessage);
222
+ }
223
+ if (!resultText && !structuredOutput && !errorMessage) {
224
+ throw new Error('AI provider returned no result');
225
+ }
226
+ logDebug(TAG, `${prefix}Result: ${resultText.length} chars`);
227
+ if (this.debugEnabled) {
228
+ logDebugFull(TAG, `${prefix}Full AI response`, resultText);
229
+ }
230
+ // Structured output from SDK is required - we enforce JSON schema output mode.
231
+ // The response parser (parseAIResponse) is kept in the codebase as a potential
232
+ // fallback for future use cases (e.g., alternative AI providers that don't support
233
+ // structured output), but this provider always requires structured output.
234
+ if (structuredOutput) {
235
+ return { raw: resultText, parsed: structuredOutput, tokenUsage };
236
+ }
237
+ // No fallback parsing - structured output is mandatory for this provider.
238
+ // If needed in the future, uncomment:
239
+ // const parsed = parseAIResponse(resultText);
240
+ // return { raw: resultText, parsed: parsed ?? undefined };
241
+ throw new Error('AI provider did not return structured output');
242
+ }
243
+ async validateConfig() {
244
+ return !!this.apiKey || this.useLocalClaude;
245
+ }
246
+ }
247
+ //# sourceMappingURL=claude-code-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code-provider.js","sourceRoot":"","sources":["../src/claude-code-provider.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Unified CLI entry point for aghast.
4
+ * Subcommand router: delegates to `scan` or `new-check`.
5
+ *
6
+ * Usage:
7
+ * aghast scan <repo-path> [options]
8
+ * aghast new-check [options]
9
+ * aghast --help
10
+ * aghast --version
11
+ */
12
+ import 'dotenv/config';
13
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG;AAEH,OAAO,eAAe,CAAC"}
package/dist/cli.js ADDED
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Unified CLI entry point for aghast.
4
+ * Subcommand router: delegates to `scan` or `new-check`.
5
+ *
6
+ * Usage:
7
+ * aghast scan <repo-path> [options]
8
+ * aghast new-check [options]
9
+ * aghast --help
10
+ * aghast --version
11
+ */
12
+ import 'dotenv/config';
13
+ import { createRequire } from 'node:module';
14
+ import { ERROR_CODES, formatError, formatFatalError } from './error-codes.js';
15
+ // Signal to subcommand modules that they're being imported, not run directly
16
+ process.env._AGHAST_CLI = '1';
17
+ const USAGE = `Usage: aghast <command> [options]
18
+
19
+ Commands:
20
+ scan Run security checks against a repository
21
+ new-check Scaffold a new security check
22
+
23
+ Options:
24
+ --help Show this help message
25
+ --version Show version number
26
+
27
+ Run 'aghast <command> --help' for more information on a command.`;
28
+ function getVersion() {
29
+ const require = createRequire(import.meta.url);
30
+ const pkg = require('../package.json');
31
+ return pkg.version;
32
+ }
33
+ function printVersion() {
34
+ console.log(getVersion());
35
+ }
36
+ async function main() {
37
+ // Graceful shutdown on POSIX signals
38
+ process.on('SIGINT', () => {
39
+ process.exit(130);
40
+ });
41
+ process.on('SIGTERM', () => {
42
+ process.exit(143);
43
+ });
44
+ const args = process.argv.slice(2);
45
+ const command = args[0];
46
+ if (!command || command === '--help' || command === '-h') {
47
+ console.log(USAGE);
48
+ process.exit(0);
49
+ }
50
+ if (command === '--version' || command === '-V') {
51
+ printVersion();
52
+ process.exit(0);
53
+ }
54
+ const subArgs = args.slice(1);
55
+ switch (command) {
56
+ case 'scan': {
57
+ const { runScan } = await import('./index.js');
58
+ await runScan(subArgs);
59
+ break;
60
+ }
61
+ case 'new-check': {
62
+ const { runNewCheck } = await import('./new-check.js');
63
+ await runNewCheck(subArgs);
64
+ break;
65
+ }
66
+ default:
67
+ console.error(formatError(ERROR_CODES.E1002, `Unknown command: ${command}`));
68
+ console.error('');
69
+ console.error(USAGE);
70
+ process.exit(1);
71
+ }
72
+ }
73
+ main().catch((err) => {
74
+ console.error('');
75
+ console.error(formatFatalError(err instanceof Error ? err.message : String(err), getVersion()));
76
+ process.exit(1);
77
+ });
78
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Color helpers for CLI output.
3
+ * Uses picocolors which automatically respects NO_COLOR env var and non-TTY.
4
+ */
5
+ export declare function colorStatus(status: string): string;
6
+ export declare function colorError(message: string): string;
7
+ //# sourceMappingURL=colors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../src/colors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAQlD;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAElD"}
package/dist/colors.js ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Color helpers for CLI output.
3
+ * Uses picocolors which automatically respects NO_COLOR env var and non-TTY.
4
+ */
5
+ import pc from 'picocolors';
6
+ export function colorStatus(status) {
7
+ switch (status) {
8
+ case 'PASS': return pc.green(status);
9
+ case 'FAIL': return pc.red(status);
10
+ case 'FLAG': return pc.yellow(status);
11
+ case 'ERROR': return pc.red(status);
12
+ default: return status;
13
+ }
14
+ }
15
+ export function colorError(message) {
16
+ return pc.red(message);
17
+ }
18
+ //# sourceMappingURL=colors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colors.js","sourceRoot":"","sources":["../src/colors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACrC,KAAK,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACnC,KAAK,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACtC,KAAK,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpC,OAAO,CAAC,CAAC,OAAO,MAAM,CAAC;IACzB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAe;IACxC,OAAO,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACzB,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Trackable error codes for CLI error paths.
3
+ *
4
+ * Numbering scheme:
5
+ * E1xxx — CLI parsing (argument/flag/command errors)
6
+ * E2xxx — Configuration (config dir, checks, runtime config)
7
+ * E3xxx — AI provider
8
+ * E4xxx — Repository/target validation
9
+ * E5xxx — Semgrep
10
+ * E9xxx — Internal/fatal
11
+ */
12
+ export interface ErrorCode {
13
+ code: string;
14
+ label: string;
15
+ }
16
+ export declare const ERROR_CODES: {
17
+ readonly E1001: ErrorCode;
18
+ readonly E1002: ErrorCode;
19
+ readonly E1003: ErrorCode;
20
+ readonly E2001: ErrorCode;
21
+ readonly E2002: ErrorCode;
22
+ readonly E2003: ErrorCode;
23
+ readonly E2004: ErrorCode;
24
+ readonly E2005: ErrorCode;
25
+ readonly E3001: ErrorCode;
26
+ readonly E3002: ErrorCode;
27
+ readonly E3003: ErrorCode;
28
+ readonly E4001: ErrorCode;
29
+ readonly E5001: ErrorCode;
30
+ readonly E5002: ErrorCode;
31
+ readonly E9001: ErrorCode;
32
+ };
33
+ /**
34
+ * Format an error message with a trackable error code.
35
+ * Output: "Error [E1001]: <message>"
36
+ */
37
+ export declare function formatError(errorCode: ErrorCode, message: string): string;
38
+ /**
39
+ * Format a fatal error with version and bug report URL.
40
+ */
41
+ export declare function formatFatalError(message: string, version: string): string;
42
+ //# sourceMappingURL=error-codes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-codes.d.ts","sourceRoot":"","sources":["../src/error-codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAMD,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;CA2Bd,CAAC;AAEX;;;GAGG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEzE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAWzE"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Trackable error codes for CLI error paths.
3
+ *
4
+ * Numbering scheme:
5
+ * E1xxx — CLI parsing (argument/flag/command errors)
6
+ * E2xxx — Configuration (config dir, checks, runtime config)
7
+ * E3xxx — AI provider
8
+ * E4xxx — Repository/target validation
9
+ * E5xxx — Semgrep
10
+ * E9xxx — Internal/fatal
11
+ */
12
+ function ec(code, label) {
13
+ return { code, label };
14
+ }
15
+ export const ERROR_CODES = {
16
+ // E1xxx — CLI parsing
17
+ E1001: ec('E1001', 'Missing required flag argument'),
18
+ E1002: ec('E1002', 'Unknown command'),
19
+ E1003: ec('E1003', 'Required input missing'),
20
+ // E2xxx — Configuration
21
+ E2001: ec('E2001', 'Config directory not specified'),
22
+ E2002: ec('E2002', 'Config directory structure invalid'),
23
+ E2003: ec('E2003', 'No checks found'),
24
+ E2004: ec('E2004', 'Invalid check definition'),
25
+ E2005: ec('E2005', 'Configuration error'),
26
+ // E3xxx — AI provider
27
+ E3001: ec('E3001', 'API key missing'),
28
+ E3002: ec('E3002', 'Unknown AI provider'),
29
+ E3003: ec('E3003', 'Mock AI response file not found'),
30
+ // E4xxx — Repository/target validation
31
+ E4001: ec('E4001', 'Repository path not found'),
32
+ // E5xxx — Semgrep
33
+ E5001: ec('E5001', 'Semgrep not installed'),
34
+ E5002: ec('E5002', 'Semgrep execution failed'),
35
+ // E9xxx — Internal
36
+ E9001: ec('E9001', 'Fatal internal error'),
37
+ };
38
+ /**
39
+ * Format an error message with a trackable error code.
40
+ * Output: "Error [E1001]: <message>"
41
+ */
42
+ export function formatError(errorCode, message) {
43
+ return `Error [${errorCode.code}]: ${message}`;
44
+ }
45
+ /**
46
+ * Format a fatal error with version and bug report URL.
47
+ */
48
+ export function formatFatalError(message, version) {
49
+ const title = encodeURIComponent(`[Bug] ${message}`);
50
+ const body = encodeURIComponent(`**Version:** ${version}\n\n**Error:**\n${message}`);
51
+ const url = `https://github.com/BounceSecurity/aghast/issues/new?title=${title}&body=${body}&labels=bug`;
52
+ return [
53
+ `AGHAST Fatal Error [${ERROR_CODES.E9001.code}]: ${message}`,
54
+ `Version: ${version}`,
55
+ '',
56
+ `If this is unexpected, please report it:`,
57
+ ` ${url}`,
58
+ ].join('\n');
59
+ }
60
+ //# sourceMappingURL=error-codes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-codes.js","sourceRoot":"","sources":["../src/error-codes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,SAAS,EAAE,CAAC,IAAY,EAAE,KAAa;IACrC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,sBAAsB;IACtB,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,gCAAgC,CAAC;IACpD,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACrC,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,wBAAwB,CAAC;IAE5C,wBAAwB;IACxB,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,gCAAgC,CAAC;IACpD,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,oCAAoC,CAAC;IACxD,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACrC,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,0BAA0B,CAAC;IAC9C,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,qBAAqB,CAAC;IAEzC,sBAAsB;IACtB,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACrC,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,qBAAqB,CAAC;IACzC,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,iCAAiC,CAAC;IAErD,uCAAuC;IACvC,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,2BAA2B,CAAC;IAE/C,kBAAkB;IAClB,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,uBAAuB,CAAC;IAC3C,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,0BAA0B,CAAC;IAE9C,mBAAmB;IACnB,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,sBAAsB,CAAC;CAClC,CAAC;AAEX;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,SAAoB,EAAE,OAAe;IAC/D,OAAO,UAAU,SAAS,CAAC,IAAI,MAAM,OAAO,EAAE,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,OAAe;IAC/D,MAAM,KAAK,GAAG,kBAAkB,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,kBAAkB,CAAC,gBAAgB,OAAO,mBAAmB,OAAO,EAAE,CAAC,CAAC;IACrF,MAAM,GAAG,GAAG,6DAA6D,KAAK,SAAS,IAAI,aAAa,CAAC;IACzG,OAAO;QACL,uBAAuB,WAAW,CAAC,KAAK,CAAC,IAAI,MAAM,OAAO,EAAE;QAC5D,YAAY,OAAO,EAAE;QACrB,EAAE;QACF,0CAA0C;QAC1C,KAAK,GAAG,EAAE;KACX,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Formatter registry — resolves output format IDs to formatter instances.
3
+ */
4
+ import type { OutputFormatter } from './types.js';
5
+ export type { OutputFormatter } from './types.js';
6
+ /** Returns the formatter for the given ID, or throws listing available formats. */
7
+ export declare function getFormatter(id: string): OutputFormatter;
8
+ /** Returns all registered format IDs. */
9
+ export declare function getAvailableFormats(): string[];
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/formatters/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAIlD,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAOlD,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,CAOxD;AAED,yCAAyC;AACzC,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAE9C"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Formatter registry — resolves output format IDs to formatter instances.
3
+ */
4
+ import { JsonFormatter } from './json-formatter.js';
5
+ import { SarifFormatter } from './sarif-formatter.js';
6
+ const formatters = new Map([
7
+ ['json', new JsonFormatter()],
8
+ ['sarif', new SarifFormatter()],
9
+ ]);
10
+ /** Returns the formatter for the given ID, or throws listing available formats. */
11
+ export function getFormatter(id) {
12
+ const formatter = formatters.get(id);
13
+ if (!formatter) {
14
+ const available = getAvailableFormats().join(', ');
15
+ throw new Error(`Unknown output format "${id}". Available formats: ${available}`);
16
+ }
17
+ return formatter;
18
+ }
19
+ /** Returns all registered format IDs. */
20
+ export function getAvailableFormats() {
21
+ return Array.from(formatters.keys());
22
+ }
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/formatters/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAItD,MAAM,UAAU,GAAG,IAAI,GAAG,CAA0B;IAClD,CAAC,MAAM,EAAE,IAAI,aAAa,EAAE,CAAC;IAC7B,CAAC,OAAO,EAAE,IAAI,cAAc,EAAE,CAAC;CAChC,CAAC,CAAC;AAEH,mFAAmF;AACnF,MAAM,UAAU,YAAY,CAAC,EAAU;IACrC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACrC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,SAAS,GAAG,mBAAmB,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,0BAA0B,EAAE,yBAAyB,SAAS,EAAE,CAAC,CAAC;IACpF,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,mBAAmB;IACjC,OAAO,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * JSON output formatter — reproduces current default behavior.
3
+ */
4
+ import type { ScanResults } from '../types.js';
5
+ import type { OutputFormatter } from './types.js';
6
+ export declare class JsonFormatter implements OutputFormatter {
7
+ readonly id = "json";
8
+ readonly fileExtension = ".json";
9
+ format(results: ScanResults): string;
10
+ }
11
+ //# sourceMappingURL=json-formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-formatter.d.ts","sourceRoot":"","sources":["../../src/formatters/json-formatter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,qBAAa,aAAc,YAAW,eAAe;IACnD,QAAQ,CAAC,EAAE,UAAU;IACrB,QAAQ,CAAC,aAAa,WAAW;IAEjC,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM;CAGrC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * JSON output formatter — reproduces current default behavior.
3
+ */
4
+ export class JsonFormatter {
5
+ id = 'json';
6
+ fileExtension = '.json';
7
+ format(results) {
8
+ return JSON.stringify(results, null, 2);
9
+ }
10
+ }
11
+ //# sourceMappingURL=json-formatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-formatter.js","sourceRoot":"","sources":["../../src/formatters/json-formatter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,OAAO,aAAa;IACf,EAAE,GAAG,MAAM,CAAC;IACZ,aAAa,GAAG,OAAO,CAAC;IAEjC,MAAM,CAAC,OAAoB;QACzB,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC1C,CAAC;CACF"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * SARIF 2.1.0 output formatter.
3
+ * Maps ScanResults to the SARIF schema for integration with
4
+ * code scanning UIs (e.g. GitHub Code Scanning) and SARIF viewers.
5
+ */
6
+ import type { ScanResults } from '../types.js';
7
+ import type { OutputFormatter } from './types.js';
8
+ /** Maps aghast severity to SARIF result level. */
9
+ export declare function mapSeverityToLevel(severity: string | undefined): 'error' | 'warning' | 'note';
10
+ export declare class SarifFormatter implements OutputFormatter {
11
+ readonly id = "sarif";
12
+ readonly fileExtension = ".sarif";
13
+ format(results: ScanResults): string;
14
+ private buildRules;
15
+ private buildResults;
16
+ private buildCodeFlow;
17
+ }
18
+ //# sourceMappingURL=sarif-formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sarif-formatter.d.ts","sourceRoot":"","sources":["../../src/formatters/sarif-formatter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAA+B,MAAM,aAAa,CAAC;AAC5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,kDAAkD;AAClD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAY7F;AA0DD,qBAAa,cAAe,YAAW,eAAe;IACpD,QAAQ,CAAC,EAAE,WAAW;IACtB,QAAQ,CAAC,aAAa,YAAY;IAElC,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM;IAwBpC,OAAO,CAAC,UAAU;IAclB,OAAO,CAAC,YAAY;IAgCpB,OAAO,CAAC,aAAa;CAiBtB"}