@continum/cli 0.1.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 (79) hide show
  1. package/README.md +481 -0
  2. package/SETUP.md +517 -0
  3. package/dist/api/client.d.ts +17 -0
  4. package/dist/api/client.d.ts.map +1 -0
  5. package/dist/api/client.js +70 -0
  6. package/dist/api/client.js.map +1 -0
  7. package/dist/commands/init.d.ts +4 -0
  8. package/dist/commands/init.d.ts.map +1 -0
  9. package/dist/commands/init.js +104 -0
  10. package/dist/commands/init.js.map +1 -0
  11. package/dist/commands/login.d.ts +2 -0
  12. package/dist/commands/login.d.ts.map +1 -0
  13. package/dist/commands/login.js +217 -0
  14. package/dist/commands/login.js.map +1 -0
  15. package/dist/commands/patterns.d.ts +3 -0
  16. package/dist/commands/patterns.d.ts.map +1 -0
  17. package/dist/commands/patterns.js +67 -0
  18. package/dist/commands/patterns.js.map +1 -0
  19. package/dist/commands/scan.d.ts +11 -0
  20. package/dist/commands/scan.d.ts.map +1 -0
  21. package/dist/commands/scan.js +219 -0
  22. package/dist/commands/scan.js.map +1 -0
  23. package/dist/commands/status.d.ts +2 -0
  24. package/dist/commands/status.d.ts.map +1 -0
  25. package/dist/commands/status.js +61 -0
  26. package/dist/commands/status.js.map +1 -0
  27. package/dist/commands/uninstall.d.ts +2 -0
  28. package/dist/commands/uninstall.d.ts.map +1 -0
  29. package/dist/commands/uninstall.js +87 -0
  30. package/dist/commands/uninstall.js.map +1 -0
  31. package/dist/config/default-config.d.ts +3 -0
  32. package/dist/config/default-config.d.ts.map +1 -0
  33. package/dist/config/default-config.js +25 -0
  34. package/dist/config/default-config.js.map +1 -0
  35. package/dist/config/loader.d.ts +11 -0
  36. package/dist/config/loader.d.ts.map +1 -0
  37. package/dist/config/loader.js +96 -0
  38. package/dist/config/loader.js.map +1 -0
  39. package/dist/git/git-utils.d.ts +8 -0
  40. package/dist/git/git-utils.d.ts.map +1 -0
  41. package/dist/git/git-utils.js +130 -0
  42. package/dist/git/git-utils.js.map +1 -0
  43. package/dist/index.d.ts +3 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +63 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/scanner/local-scan.d.ts +15 -0
  48. package/dist/scanner/local-scan.d.ts.map +1 -0
  49. package/dist/scanner/local-scan.js +227 -0
  50. package/dist/scanner/local-scan.js.map +1 -0
  51. package/dist/scanner/pattern-updater.d.ts +12 -0
  52. package/dist/scanner/pattern-updater.d.ts.map +1 -0
  53. package/dist/scanner/pattern-updater.js +110 -0
  54. package/dist/scanner/pattern-updater.js.map +1 -0
  55. package/dist/scanner/patterns.d.ts +5 -0
  56. package/dist/scanner/patterns.d.ts.map +1 -0
  57. package/dist/scanner/patterns.js +145 -0
  58. package/dist/scanner/patterns.js.map +1 -0
  59. package/dist/types.d.ts +59 -0
  60. package/dist/types.d.ts.map +1 -0
  61. package/dist/types.js +3 -0
  62. package/dist/types.js.map +1 -0
  63. package/package.json +40 -0
  64. package/src/api/client.ts +77 -0
  65. package/src/commands/init.ts +113 -0
  66. package/src/commands/login.ts +205 -0
  67. package/src/commands/patterns.ts +68 -0
  68. package/src/commands/scan.ts +257 -0
  69. package/src/commands/status.ts +57 -0
  70. package/src/commands/uninstall.ts +55 -0
  71. package/src/config/default-config.ts +23 -0
  72. package/src/config/loader.ts +67 -0
  73. package/src/git/git-utils.ts +95 -0
  74. package/src/index.ts +72 -0
  75. package/src/scanner/local-scan.ts +222 -0
  76. package/src/scanner/pattern-updater.ts +94 -0
  77. package/src/scanner/patterns.ts +156 -0
  78. package/src/types.ts +64 -0
  79. package/tsconfig.json +19 -0
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.initCommand = initCommand;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const prompts_1 = __importDefault(require("prompts"));
9
+ const loader_1 = require("../config/loader");
10
+ const git_utils_1 = require("../git/git-utils");
11
+ const client_1 = require("../api/client");
12
+ const default_config_1 = require("../config/default-config");
13
+ async function initCommand(options) {
14
+ if (!options.silent) {
15
+ console.log(chalk_1.default.blue.bold('\n🛡️ Continum CLI Setup\n'));
16
+ }
17
+ // Check if in git repository
18
+ if (!(0, git_utils_1.isGitRepository)()) {
19
+ console.log(chalk_1.default.red('✗ Not a git repository'));
20
+ console.log(chalk_1.default.gray(' Run this command in a git repository'));
21
+ process.exit(1);
22
+ }
23
+ // Check if already initialized
24
+ const existingConfig = (0, loader_1.loadConfig)();
25
+ const hasHook = (0, git_utils_1.hasPreCommitHook)();
26
+ if (existingConfig && hasHook && !options.silent) {
27
+ console.log(chalk_1.default.yellow('⚠️ Continum is already initialized in this repository'));
28
+ const { reinit } = await (0, prompts_1.default)({
29
+ type: 'confirm',
30
+ name: 'reinit',
31
+ message: 'Reinitialize?',
32
+ initial: false
33
+ });
34
+ if (!reinit) {
35
+ process.exit(0);
36
+ }
37
+ }
38
+ // Check for credentials - must be logged in first
39
+ const credentials = (0, loader_1.loadCredentials)();
40
+ if (!credentials.apiUrl || !credentials.apiKey) {
41
+ console.log(chalk_1.default.red('✗ Not logged in to Continum\n'));
42
+ console.log(chalk_1.default.gray('Please run `continum login` first to authenticate.\n'));
43
+ console.log(chalk_1.default.blue(' $ continum login\n'));
44
+ process.exit(1);
45
+ }
46
+ // Test connection
47
+ if (!options.silent) {
48
+ console.log(chalk_1.default.gray('\nTesting connection...'));
49
+ }
50
+ try {
51
+ const client = new client_1.ContinumApiClient(credentials.apiUrl, credentials.apiKey);
52
+ const status = await client.testConnection();
53
+ if (!options.silent) {
54
+ console.log(chalk_1.default.green(`✓ Connected to Continum (${status.customer})`));
55
+ }
56
+ }
57
+ catch (error) {
58
+ console.log(chalk_1.default.red('✗ Failed to connect to Continum API'));
59
+ console.log(chalk_1.default.gray(` ${error instanceof Error ? error.message : 'Unknown error'}`));
60
+ process.exit(1);
61
+ }
62
+ // Get sandbox configuration
63
+ let sandbox = existingConfig?.sandbox || 'default';
64
+ if (!options.silent) {
65
+ const sandboxResponse = await (0, prompts_1.default)({
66
+ type: 'text',
67
+ name: 'sandbox',
68
+ message: 'Sandbox name:',
69
+ initial: sandbox
70
+ });
71
+ if (sandboxResponse.sandbox) {
72
+ sandbox = sandboxResponse.sandbox;
73
+ }
74
+ }
75
+ // Create config file
76
+ const config = {
77
+ ...default_config_1.DEFAULT_CONFIG,
78
+ sandbox,
79
+ apiUrl: credentials.apiUrl,
80
+ apiKey: credentials.apiKey
81
+ };
82
+ (0, loader_1.saveConfig)(config);
83
+ if (!options.silent) {
84
+ console.log(chalk_1.default.green('✓ .continum.json created'));
85
+ }
86
+ // Install git hook
87
+ try {
88
+ (0, git_utils_1.installPreCommitHook)();
89
+ if (!options.silent) {
90
+ console.log(chalk_1.default.green('✓ Pre-commit hook installed'));
91
+ }
92
+ }
93
+ catch (error) {
94
+ console.log(chalk_1.default.red('✗ Failed to install pre-commit hook'));
95
+ console.log(chalk_1.default.gray(` ${error instanceof Error ? error.message : 'Unknown error'}`));
96
+ process.exit(1);
97
+ }
98
+ if (!options.silent) {
99
+ console.log(chalk_1.default.blue.bold('\n✓ Continum is ready!\n'));
100
+ console.log(chalk_1.default.gray('Every commit will now be scanned locally.'));
101
+ console.log(chalk_1.default.gray('Violations are also audited by the Continum sandbox.\n'));
102
+ }
103
+ }
104
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function loginCommand(): Promise<void>;
2
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAgBA,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CA+ClD"}
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.loginCommand = loginCommand;
40
+ const chalk_1 = __importDefault(require("chalk"));
41
+ const ora_1 = __importDefault(require("ora"));
42
+ const http_1 = require("http");
43
+ const url_1 = require("url");
44
+ const loader_1 = require("../config/loader");
45
+ const client_1 = require("../api/client");
46
+ const CALLBACK_PORT = 8765;
47
+ const CALLBACK_PATH = '/cli/callback';
48
+ async function loginCommand() {
49
+ console.log(chalk_1.default.blue.bold('\n🛡️ Continum CLI Login\n'));
50
+ const apiUrl = process.env.CONTINUM_API_URL || 'https://api.continum.dev';
51
+ const consoleUrl = process.env.CONTINUM_CONSOLE_URL || 'https://console.continum.dev';
52
+ // Generate a random state for security
53
+ const state = generateRandomState();
54
+ // Start local server to receive callback
55
+ const authPromise = startCallbackServer(state);
56
+ // Build auth URL
57
+ const authUrl = `${consoleUrl}/cli/auth?state=${state}&port=${CALLBACK_PORT}`;
58
+ console.log(chalk_1.default.gray('Opening browser for authentication...\n'));
59
+ console.log(chalk_1.default.gray(`If browser doesn't open, visit:\n${authUrl}\n`));
60
+ // Open browser
61
+ const open = await Promise.resolve().then(() => __importStar(require('open')));
62
+ await open.default(authUrl);
63
+ const spinner = (0, ora_1.default)('Waiting for authentication...').start();
64
+ try {
65
+ // Wait for callback
66
+ const authResponse = await authPromise;
67
+ spinner.succeed('Authentication successful!');
68
+ // Save credentials
69
+ (0, loader_1.saveCredentials)(authResponse.apiUrl || apiUrl, authResponse.apiKey);
70
+ // Test connection
71
+ console.log(chalk_1.default.gray('\nTesting connection...'));
72
+ const client = new client_1.ContinumApiClient(authResponse.apiUrl || apiUrl, authResponse.apiKey);
73
+ const status = await client.testConnection();
74
+ console.log(chalk_1.default.green(`✓ Connected to Continum (${status.customer})`));
75
+ console.log(chalk_1.default.blue.bold('\n✓ Login complete!\n'));
76
+ console.log(chalk_1.default.gray('You can now run `continum init` in your project.\n'));
77
+ process.exit(0);
78
+ }
79
+ catch (error) {
80
+ spinner.fail('Authentication failed');
81
+ console.log(chalk_1.default.red(`\n✗ ${error instanceof Error ? error.message : 'Unknown error'}\n`));
82
+ process.exit(1);
83
+ }
84
+ }
85
+ function generateRandomState() {
86
+ return Math.random().toString(36).substring(2, 15) +
87
+ Math.random().toString(36).substring(2, 15);
88
+ }
89
+ function startCallbackServer(expectedState) {
90
+ return new Promise((resolve, reject) => {
91
+ const timeout = setTimeout(() => {
92
+ server.close();
93
+ reject(new Error('Authentication timeout (5 minutes)'));
94
+ }, 5 * 60 * 1000); // 5 minutes
95
+ const server = (0, http_1.createServer)((req, res) => {
96
+ const parsedUrl = (0, url_1.parse)(req.url || '', true);
97
+ if (parsedUrl.pathname === CALLBACK_PATH) {
98
+ const { state, apiKey, apiUrl, customer, error } = parsedUrl.query;
99
+ // Check for errors
100
+ if (error) {
101
+ res.writeHead(400, { 'Content-Type': 'text/html' });
102
+ res.end(`
103
+ <!DOCTYPE html>
104
+ <html>
105
+ <head>
106
+ <title>Authentication Failed</title>
107
+ <style>
108
+ body { font-family: system-ui; max-width: 600px; margin: 100px auto; text-align: center; }
109
+ .error { color: #dc2626; font-size: 24px; margin-bottom: 20px; }
110
+ .message { color: #6b7280; }
111
+ </style>
112
+ </head>
113
+ <body>
114
+ <div class="error">❌ Authentication Failed</div>
115
+ <div class="message">${error}</div>
116
+ <p>You can close this window and try again.</p>
117
+ </body>
118
+ </html>
119
+ `);
120
+ clearTimeout(timeout);
121
+ server.close();
122
+ reject(new Error(error));
123
+ return;
124
+ }
125
+ // Verify state
126
+ if (state !== expectedState) {
127
+ res.writeHead(400, { 'Content-Type': 'text/html' });
128
+ res.end(`
129
+ <!DOCTYPE html>
130
+ <html>
131
+ <head>
132
+ <title>Authentication Failed</title>
133
+ <style>
134
+ body { font-family: system-ui; max-width: 600px; margin: 100px auto; text-align: center; }
135
+ .error { color: #dc2626; font-size: 24px; margin-bottom: 20px; }
136
+ </style>
137
+ </head>
138
+ <body>
139
+ <div class="error">❌ Invalid State</div>
140
+ <p>Security verification failed. Please try again.</p>
141
+ </body>
142
+ </html>
143
+ `);
144
+ clearTimeout(timeout);
145
+ server.close();
146
+ reject(new Error('Invalid state parameter'));
147
+ return;
148
+ }
149
+ // Success
150
+ res.writeHead(200, { 'Content-Type': 'text/html' });
151
+ res.end(`
152
+ <!DOCTYPE html>
153
+ <html>
154
+ <head>
155
+ <title>Authentication Successful</title>
156
+ <style>
157
+ body {
158
+ font-family: system-ui;
159
+ max-width: 600px;
160
+ margin: 100px auto;
161
+ text-align: center;
162
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
163
+ color: white;
164
+ padding: 40px;
165
+ }
166
+ .success { font-size: 48px; margin-bottom: 20px; }
167
+ .title { font-size: 32px; font-weight: bold; margin-bottom: 10px; }
168
+ .message { font-size: 18px; opacity: 0.9; }
169
+ .close {
170
+ margin-top: 30px;
171
+ padding: 12px 24px;
172
+ background: white;
173
+ color: #667eea;
174
+ border: none;
175
+ border-radius: 6px;
176
+ font-size: 16px;
177
+ cursor: pointer;
178
+ font-weight: 600;
179
+ }
180
+ .close:hover { background: #f3f4f6; }
181
+ </style>
182
+ </head>
183
+ <body>
184
+ <div class="success">✓</div>
185
+ <div class="title">Authentication Successful!</div>
186
+ <div class="message">You can now close this window and return to your terminal.</div>
187
+ <button class="close" onclick="window.close()">Close Window</button>
188
+ <script>
189
+ // Auto-close after 3 seconds
190
+ setTimeout(() => window.close(), 3000);
191
+ </script>
192
+ </body>
193
+ </html>
194
+ `);
195
+ clearTimeout(timeout);
196
+ server.close();
197
+ resolve({
198
+ apiKey: apiKey,
199
+ apiUrl: apiUrl,
200
+ customer: customer,
201
+ });
202
+ }
203
+ else {
204
+ res.writeHead(404);
205
+ res.end('Not found');
206
+ }
207
+ });
208
+ server.listen(CALLBACK_PORT, () => {
209
+ // Server started
210
+ });
211
+ server.on('error', (err) => {
212
+ clearTimeout(timeout);
213
+ reject(new Error(`Failed to start callback server: ${err.message}`));
214
+ });
215
+ });
216
+ }
217
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function patternsUpdateCommand(): Promise<void>;
2
+ export declare function patternsListCommand(): Promise<void>;
3
+ //# sourceMappingURL=patterns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../src/commands/patterns.ts"],"names":[],"mappings":"AAKA,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAuB3D;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAqCzD"}
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.patternsUpdateCommand = patternsUpdateCommand;
7
+ exports.patternsListCommand = patternsListCommand;
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const loader_1 = require("../config/loader");
10
+ const client_1 = require("../api/client");
11
+ const pattern_updater_1 = require("../scanner/pattern-updater");
12
+ async function patternsUpdateCommand() {
13
+ const credentials = (0, loader_1.loadCredentials)();
14
+ if (!credentials.apiUrl || !credentials.apiKey) {
15
+ console.log(chalk_1.default.red('✗ No API credentials configured'));
16
+ console.log(chalk_1.default.gray(' Run `continum init` to set up credentials'));
17
+ process.exit(1);
18
+ }
19
+ console.log(chalk_1.default.blue('Updating patterns...'));
20
+ try {
21
+ const client = new client_1.ContinumApiClient(credentials.apiUrl, credentials.apiKey);
22
+ const updater = new pattern_updater_1.PatternUpdater(client);
23
+ await updater.updatePatterns(true);
24
+ const patterns = updater.loadPatterns();
25
+ console.log(chalk_1.default.green(`✓ Updated ${patterns.length} patterns`));
26
+ }
27
+ catch (error) {
28
+ console.log(chalk_1.default.red('✗ Failed to update patterns'));
29
+ console.log(chalk_1.default.gray(` ${error instanceof Error ? error.message : 'Unknown error'}`));
30
+ process.exit(1);
31
+ }
32
+ }
33
+ async function patternsListCommand() {
34
+ const credentials = (0, loader_1.loadCredentials)();
35
+ if (!credentials.apiUrl || !credentials.apiKey) {
36
+ console.log(chalk_1.default.red('✗ No API credentials configured'));
37
+ console.log(chalk_1.default.gray(' Run `continum init` to set up credentials'));
38
+ process.exit(1);
39
+ }
40
+ try {
41
+ const client = new client_1.ContinumApiClient(credentials.apiUrl, credentials.apiKey);
42
+ const updater = new pattern_updater_1.PatternUpdater(client);
43
+ const patterns = updater.loadPatterns();
44
+ console.log(chalk_1.default.blue.bold('\n🛡️ Pattern Library\n'));
45
+ const byType = {};
46
+ patterns.forEach(p => {
47
+ if (!byType[p.patternType]) {
48
+ byType[p.patternType] = [];
49
+ }
50
+ byType[p.patternType].push(p);
51
+ });
52
+ for (const [type, typePatterns] of Object.entries(byType)) {
53
+ console.log(chalk_1.default.bold(`\n${type} (${typePatterns.length})`));
54
+ typePatterns.forEach(p => {
55
+ console.log(chalk_1.default.gray(` ${p.description}`));
56
+ console.log(chalk_1.default.gray(` Pattern: ${p.pattern}`));
57
+ console.log(chalk_1.default.gray(` Severity: ${p.severity}\n`));
58
+ });
59
+ }
60
+ }
61
+ catch (error) {
62
+ console.log(chalk_1.default.red('✗ Failed to load patterns'));
63
+ console.log(chalk_1.default.gray(` ${error instanceof Error ? error.message : 'Unknown error'}`));
64
+ process.exit(1);
65
+ }
66
+ }
67
+ //# sourceMappingURL=patterns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../src/commands/patterns.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ interface ScanOptions {
2
+ staged?: boolean;
3
+ hook?: boolean;
4
+ strict?: boolean;
5
+ autoApprove?: boolean;
6
+ warnOnly?: boolean;
7
+ files?: string[];
8
+ }
9
+ export declare function scanCommand(options: ScanOptions): Promise<void>;
10
+ export {};
11
+ //# sourceMappingURL=scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/commands/scan.ts"],"names":[],"mappings":"AAWA,UAAU,WAAW;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAyGrE"}
@@ -0,0 +1,219 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.scanCommand = scanCommand;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const prompts_1 = __importDefault(require("prompts"));
9
+ const local_scan_1 = require("../scanner/local-scan");
10
+ const loader_1 = require("../config/loader");
11
+ const git_utils_1 = require("../git/git-utils");
12
+ const client_1 = require("../api/client");
13
+ const pattern_updater_1 = require("../scanner/pattern-updater");
14
+ async function scanCommand(options) {
15
+ const config = (0, loader_1.loadConfig)();
16
+ const credentials = (0, loader_1.loadCredentials)();
17
+ // Update patterns if we have credentials
18
+ let customPatterns = [];
19
+ if (credentials.apiUrl && credentials.apiKey) {
20
+ try {
21
+ const client = new client_1.ContinumApiClient(credentials.apiUrl, credentials.apiKey);
22
+ const updater = new pattern_updater_1.PatternUpdater(client);
23
+ await updater.updatePatterns();
24
+ customPatterns = updater.loadPatterns();
25
+ }
26
+ catch (error) {
27
+ // Continue with built-in patterns only
28
+ }
29
+ }
30
+ // Determine which files to scan
31
+ let filesToScan = [];
32
+ if (options.staged) {
33
+ filesToScan = (0, git_utils_1.getStagedFiles)();
34
+ }
35
+ else if (options.files && options.files.length > 0) {
36
+ filesToScan = options.files;
37
+ }
38
+ else {
39
+ console.log(chalk_1.default.red('✗ No files specified'));
40
+ console.log(chalk_1.default.gray(' Use --staged to scan staged files, or provide file paths'));
41
+ process.exit(1);
42
+ }
43
+ if (filesToScan.length === 0) {
44
+ console.log(chalk_1.default.yellow('⚠️ No files to scan'));
45
+ process.exit(0);
46
+ }
47
+ // Run scan
48
+ if (!options.hook) {
49
+ console.log(chalk_1.default.blue(`\nContinum — scanning ${filesToScan.length} file(s)...\n`));
50
+ }
51
+ const scanner = new local_scan_1.LocalScanner(config, customPatterns);
52
+ const result = await scanner.scanFiles(filesToScan);
53
+ // Handle violations
54
+ if (result.violations.length > 0) {
55
+ console.log(chalk_1.default.red.bold('❌ BLOCKED\n'));
56
+ for (const violation of result.violations) {
57
+ const shouldBlock = config.block.includes(violation.severity);
58
+ const shouldWarn = config.warn.includes(violation.severity);
59
+ if (shouldBlock || shouldWarn) {
60
+ console.log(chalk_1.default.gray(`${violation.file} (line ${violation.line})`));
61
+ console.log(chalk_1.default.gray('─'.repeat(50)));
62
+ console.log(`Type: ${violation.type}`);
63
+ console.log(`Found: ${scanner.redactValue(violation.value)}`);
64
+ console.log(`Severity: ${getSeverityColor(violation.severity)(violation.severity)}`);
65
+ if (violation.message) {
66
+ console.log(`Message: ${violation.message}`);
67
+ }
68
+ console.log();
69
+ }
70
+ }
71
+ const blockedCount = result.violations.filter(v => config.block.includes(v.severity)).length;
72
+ if (blockedCount > 0 && !options.warnOnly) {
73
+ console.log(chalk_1.default.red('Fix these before committing.'));
74
+ console.log(chalk_1.default.gray('Override (not recommended): git commit --no-verify\n'));
75
+ process.exit(1);
76
+ }
77
+ }
78
+ // Handle unknown patterns
79
+ if (result.unknownPatterns.length > 0 && !options.autoApprove) {
80
+ for (const pattern of result.unknownPatterns) {
81
+ await handleUnknownPattern(pattern, scanner, credentials, options);
82
+ }
83
+ }
84
+ else if (result.unknownPatterns.length > 0 && options.autoApprove) {
85
+ // Auto-approve all patterns
86
+ for (const pattern of result.unknownPatterns) {
87
+ await approvePattern(pattern, scanner, credentials, 'HIGH');
88
+ }
89
+ }
90
+ // Send background audit if we have credentials
91
+ if (credentials.apiUrl && credentials.apiKey && options.staged) {
92
+ try {
93
+ const client = new client_1.ContinumApiClient(credentials.apiUrl, credentials.apiKey);
94
+ const diff = (0, git_utils_1.getStagedDiff)();
95
+ await client.sendSandboxAudit(diff, config.sandbox);
96
+ }
97
+ catch (error) {
98
+ // Silent fail for background audit
99
+ }
100
+ }
101
+ // Success
102
+ if (result.clean) {
103
+ if (!options.hook) {
104
+ console.log(chalk_1.default.green('✓ Clean\n'));
105
+ }
106
+ process.exit(0);
107
+ }
108
+ }
109
+ async function handleUnknownPattern(pattern, scanner, credentials, options) {
110
+ console.log(chalk_1.default.yellow('\n⚠️ POSSIBLE CREDENTIAL DETECTED\n'));
111
+ console.log(chalk_1.default.gray(`${pattern.context.file} (line ${pattern.context.line})`));
112
+ console.log(chalk_1.default.gray('─'.repeat(50)));
113
+ console.log(`Type: UNKNOWN_PATTERN (${pattern.confidence} confidence)`);
114
+ console.log(`Found: ${scanner.redactValue(pattern.value)}`);
115
+ console.log(`Pattern: ${pattern.suggestedPattern}`);
116
+ console.log('\nThis looks like a credential, but it\'s not in our pattern library.\n');
117
+ if (options.strict) {
118
+ console.log(chalk_1.default.red('Commit blocked (strict mode)'));
119
+ process.exit(1);
120
+ }
121
+ const { action } = await (0, prompts_1.default)({
122
+ type: 'select',
123
+ name: 'action',
124
+ message: 'What would you like to do?',
125
+ choices: [
126
+ { title: 'Block this commit', value: 'block' },
127
+ { title: 'Approve pattern and block (will catch in future)', value: 'approve' },
128
+ { title: 'Ignore this pattern', value: 'ignore' },
129
+ { title: 'Continue anyway (not recommended)', value: 'continue' }
130
+ ]
131
+ });
132
+ switch (action) {
133
+ case 'approve':
134
+ await approvePattern(pattern, scanner, credentials);
135
+ console.log(chalk_1.default.green('✓ Pattern saved to your library'));
136
+ console.log(chalk_1.default.green('✓ This pattern will now be caught locally on future commits\n'));
137
+ process.exit(1);
138
+ case 'block':
139
+ process.exit(1);
140
+ case 'ignore':
141
+ console.log(chalk_1.default.gray('Pattern ignored\n'));
142
+ break;
143
+ case 'continue':
144
+ console.log(chalk_1.default.yellow('⚠️ Continuing without blocking\n'));
145
+ break;
146
+ }
147
+ }
148
+ async function approvePattern(pattern, scanner, credentials, defaultSeverity) {
149
+ if (!credentials.apiUrl || !credentials.apiKey) {
150
+ console.log(chalk_1.default.red('✗ No API credentials configured'));
151
+ console.log(chalk_1.default.gray(' Run `continum init` to set up credentials'));
152
+ return;
153
+ }
154
+ let description = `Custom pattern for ${pattern.context.variableName || 'credential'}`;
155
+ let severity = defaultSeverity || 'HIGH';
156
+ if (!defaultSeverity) {
157
+ const response = await (0, prompts_1.default)([
158
+ {
159
+ type: 'text',
160
+ name: 'description',
161
+ message: 'Pattern description:',
162
+ initial: description
163
+ },
164
+ {
165
+ type: 'select',
166
+ name: 'severity',
167
+ message: 'Severity level:',
168
+ choices: [
169
+ { title: 'Critical', value: 'CRITICAL' },
170
+ { title: 'High', value: 'HIGH' },
171
+ { title: 'Medium', value: 'MEDIUM' }
172
+ ],
173
+ initial: 1
174
+ }
175
+ ]);
176
+ if (response.description)
177
+ description = response.description;
178
+ if (response.severity)
179
+ severity = response.severity;
180
+ }
181
+ try {
182
+ const client = new client_1.ContinumApiClient(credentials.apiUrl, credentials.apiKey);
183
+ await client.approvePattern({
184
+ pattern: pattern.suggestedPattern,
185
+ patternType: 'CUSTOM',
186
+ description,
187
+ severity,
188
+ exampleValue: scanner.redactValue(pattern.value),
189
+ confidence: pattern.confidence,
190
+ context: {
191
+ file: pattern.context.file,
192
+ line: pattern.context.line,
193
+ variableName: pattern.context.variableName
194
+ }
195
+ });
196
+ // Update local cache
197
+ const updater = new pattern_updater_1.PatternUpdater(client);
198
+ await updater.updatePatterns(true);
199
+ }
200
+ catch (error) {
201
+ console.log(chalk_1.default.red('✗ Failed to save pattern'));
202
+ console.log(chalk_1.default.gray(` ${error instanceof Error ? error.message : 'Unknown error'}`));
203
+ }
204
+ }
205
+ function getSeverityColor(severity) {
206
+ switch (severity) {
207
+ case 'CRITICAL':
208
+ return chalk_1.default.red.bold;
209
+ case 'HIGH':
210
+ return chalk_1.default.red;
211
+ case 'MEDIUM':
212
+ return chalk_1.default.yellow;
213
+ case 'LOW':
214
+ return chalk_1.default.gray;
215
+ default:
216
+ return chalk_1.default.white;
217
+ }
218
+ }
219
+ //# sourceMappingURL=scan.js.map