@veestack-tools/cli 3.0.2 → 3.0.4

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.
@@ -1,409 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import crypto from 'crypto';
4
- import { fileURLToPath } from 'url';
5
-
6
- const __filename = fileURLToPath(import.meta.url);
7
- const __dirname = path.dirname(__filename);
8
-
9
- export interface WasmEngineConfig {
10
- apiUrl: string;
11
- apiKey: string;
12
- licenseKey?: string;
13
- sessionId: string;
14
- }
15
-
16
- export interface RemoteRulesResponse {
17
- success: boolean;
18
- rules_version: string;
19
- rules_count: number;
20
- encrypted_rules: string;
21
- encrypted_session_key: string;
22
- expires_at: string;
23
- licensed: boolean;
24
- }
25
-
26
- export interface WasmAnalysisResult {
27
- findings: WasmFinding[];
28
- metrics: WasmMetrics;
29
- execution_time_ms: number;
30
- }
31
-
32
- export interface WasmFinding {
33
- rule_id: string;
34
- file_path: string;
35
- line_number: number;
36
- severity: 'critical' | 'high' | 'medium' | 'low' | 'info';
37
- message: string;
38
- context_hash: string;
39
- }
40
-
41
- export interface WasmMetrics {
42
- files_scanned: number;
43
- rules_applied: number;
44
- patterns_matched: number;
45
- }
46
-
47
- export interface WasmSnapshot {
48
- version: string;
49
- project_id: string;
50
- files: WasmFileInfo[];
51
- dependencies: WasmDependency[];
52
- metadata: WasmMetadata;
53
- }
54
-
55
- export interface WasmFileInfo {
56
- path: string;
57
- path_hash: string;
58
- content_hash: string;
59
- extension: string;
60
- size_bytes: number;
61
- estimated_lines: number;
62
- depth: number;
63
- }
64
-
65
- export interface WasmDependency {
66
- name_hash: string;
67
- version_major: number;
68
- version_minor: number;
69
- category: 'dev' | 'prod' | 'peer';
70
- }
71
-
72
- export interface WasmMetadata {
73
- total_files: number;
74
- total_dependencies: number;
75
- framework: string;
76
- language: string;
77
- }
78
-
79
- export class WasmEngineLoader {
80
- private config: WasmEngineConfig;
81
- private wasmModule: WebAssembly.Module | null = null;
82
- private wasmInstance: WebAssembly.Instance | null = null;
83
- private sessionKey: string = '';
84
- private rules: any[] = [];
85
-
86
- constructor(config: WasmEngineConfig) {
87
- this.config = config;
88
- }
89
-
90
- /**
91
- * Load and initialize the WASM engine
92
- */
93
- async initialize(): Promise<boolean> {
94
- try {
95
- // Find WASM file path
96
- const wasmPath = this.findWasmFile();
97
-
98
- if (!wasmPath) {
99
- console.error('❌ WASM engine not found');
100
- return false;
101
- }
102
-
103
- // Read WASM file
104
- const wasmBuffer = fs.readFileSync(wasmPath);
105
-
106
- // Compile WASM module
107
- this.wasmModule = await WebAssembly.compile(wasmBuffer);
108
-
109
- // Create import object with required imports
110
- const importObject = {
111
- env: {
112
- memory: new WebAssembly.Memory({ initial: 256, maximum: 512 }),
113
- __memory_base: 0,
114
- __table_base: 0,
115
- abort: (msg: number, file: number, line: number, column: number) => {
116
- console.error(`WASM abort: ${msg} at ${file}:${line}:${column}`);
117
- },
118
- // Add console.log for debugging
119
- log: (ptr: number, len: number) => {
120
- const memory = (this.wasmInstance?.exports.memory as WebAssembly.Memory);
121
- if (memory) {
122
- const bytes = new Uint8Array(memory.buffer, ptr, len);
123
- const message = new TextDecoder().decode(bytes);
124
- console.log(`[WASM] ${message}`);
125
- }
126
- }
127
- },
128
- console: {
129
- log: (message: string) => {
130
- console.log(`[WASM Engine] ${message}`);
131
- }
132
- }
133
- };
134
-
135
- // Instantiate WASM module
136
- this.wasmInstance = await WebAssembly.instantiate(this.wasmModule, importObject);
137
-
138
- console.log('✅ WASM engine initialized successfully');
139
- return true;
140
- } catch (error) {
141
- console.error('❌ Failed to initialize WASM engine:', error);
142
- return false;
143
- }
144
- }
145
-
146
- /**
147
- * Fetch encrypted rules from remote server
148
- */
149
- async fetchRemoteRules(framework: string, language: string): Promise<boolean> {
150
- try {
151
- const response = await fetch(`${this.config.apiUrl}/functions/v1/rules`, {
152
- method: 'POST',
153
- headers: {
154
- 'Content-Type': 'application/json',
155
- 'Authorization': `Bearer ${this.config.apiKey}`
156
- },
157
- body: JSON.stringify({
158
- framework,
159
- language,
160
- version: '1.0.0',
161
- session_id: this.config.sessionId,
162
- license_key: this.config.licenseKey
163
- })
164
- });
165
-
166
- if (!response.ok) {
167
- const error = await response.text();
168
- console.error('❌ Failed to fetch rules:', error);
169
- return false;
170
- }
171
-
172
- const data: RemoteRulesResponse = await response.json();
173
-
174
- if (!data.success) {
175
- console.error('❌ Rules API returned unsuccessful response');
176
- return false;
177
- }
178
-
179
- // Decrypt session key
180
- this.sessionKey = this.decryptSessionKey(data.encrypted_session_key);
181
-
182
- // Decrypt rules
183
- const decryptedRules = this.decryptRules(data.encrypted_rules);
184
- this.rules = JSON.parse(decryptedRules);
185
-
186
- console.log(`✅ Loaded ${this.rules.length} security rules (v${data.rules_version})`);
187
-
188
- return true;
189
- } catch (error) {
190
- console.error('❌ Error fetching remote rules:', error);
191
- return false;
192
- }
193
- }
194
-
195
- /**
196
- * Analyze a snapshot using WASM engine
197
- */
198
- async analyzeSnapshot(
199
- snapshot: WasmSnapshot,
200
- fileContents: Map<string, string>
201
- ): Promise<WasmAnalysisResult | null> {
202
- if (!this.wasmInstance) {
203
- console.error('❌ WASM engine not initialized');
204
- return null;
205
- }
206
-
207
- try {
208
- const exports = this.wasmInstance.exports as any;
209
-
210
- // Initialize session in WASM
211
- const encryptedKey = this.encryptString(this.sessionKey);
212
-
213
- // Convert strings to WASM memory
214
- const snapshotJson = JSON.stringify(snapshot);
215
- const contentsJson = JSON.stringify(Object.fromEntries(fileContents));
216
-
217
- // Allocate memory for input
218
- const snapshotPtr = this.allocateString(snapshotJson);
219
- const contentsPtr = this.allocateString(contentsJson);
220
- const sessionPtr = this.allocateString(encryptedKey);
221
-
222
- // Call WASM functions
223
- const initResult = exports.initialize_session(sessionPtr);
224
- if (!initResult) {
225
- console.error('❌ Failed to initialize WASM session');
226
- return null;
227
- }
228
-
229
- // Load encrypted rules into WASM
230
- const rulesJson = JSON.stringify(this.rules);
231
- const encryptedRules = this.encryptString(rulesJson);
232
- const rulesPtr = this.allocateString(encryptedRules);
233
-
234
- const loadResult = exports.load_rules(rulesPtr);
235
- if (loadResult !== 0) {
236
- console.error('❌ Failed to load rules into WASM');
237
- return null;
238
- }
239
-
240
- // Run analysis
241
- const resultPtr = exports.analyze_snapshot(snapshotPtr, contentsPtr);
242
-
243
- // Read result from WASM memory
244
- const resultJson = this.readString(resultPtr);
245
-
246
- // Free allocated memory (if WASM exports free function)
247
- if (exports.free) {
248
- exports.free(snapshotPtr);
249
- exports.free(contentsPtr);
250
- exports.free(sessionPtr);
251
- exports.free(rulesPtr);
252
- exports.free(resultPtr);
253
- }
254
-
255
- // Parse result
256
- const result: WasmAnalysisResult = JSON.parse(resultJson);
257
-
258
- return result;
259
- } catch (error) {
260
- console.error('❌ Analysis error:', error);
261
- return null;
262
- }
263
- }
264
-
265
- /**
266
- * Validate license key
267
- */
268
- validateLicense(hardwareId: string): boolean {
269
- if (!this.wasmInstance) return false;
270
-
271
- try {
272
- const exports = this.wasmInstance.exports as any;
273
- const licensePtr = this.allocateString(this.config.licenseKey || '');
274
- const hardwarePtr = this.allocateString(hardwareId);
275
-
276
- const result = exports.validate_license(licensePtr, hardwarePtr);
277
-
278
- return result === 1;
279
- } catch (error) {
280
- console.error('❌ License validation error:', error);
281
- return false;
282
- }
283
- }
284
-
285
- /**
286
- * Generate content fingerprint
287
- */
288
- generateFingerprint(content: string): string {
289
- if (!this.wasmInstance) {
290
- // Fallback to Node.js crypto
291
- return crypto.createHash('sha256').update(content).digest('hex');
292
- }
293
-
294
- try {
295
- const exports = this.wasmInstance.exports as any;
296
- const contentPtr = this.allocateString(content);
297
- const resultPtr = exports.generate_fingerprint(contentPtr);
298
- return this.readString(resultPtr);
299
- } catch {
300
- return crypto.createHash('sha256').update(content).digest('hex');
301
- }
302
- }
303
-
304
- /**
305
- * Generate unique session ID
306
- */
307
- static generateSessionId(): string {
308
- return crypto.randomUUID();
309
- }
310
-
311
- /**
312
- * Generate hardware fingerprint
313
- */
314
- static generateHardwareId(): string {
315
- const components = [
316
- process.platform,
317
- process.arch,
318
- process.version,
319
- require('os').hostname(),
320
- 'veestack'
321
- ];
322
-
323
- const combined = components.join('|');
324
- return crypto.createHash('sha256').update(combined).digest('hex');
325
- }
326
-
327
- // Private helper methods
328
-
329
- private findWasmFile(): string | null {
330
- // Search for WASM file in multiple locations
331
- const possiblePaths = [
332
- path.join(__dirname, '../../wasm-engine/target/wasm32-unknown-unknown/release/veestack_wasm_engine.wasm'),
333
- path.join(__dirname, '../engine.wasm'),
334
- path.join(process.cwd(), 'node_modules/@veestack-tools/wasm-engine/engine.wasm'),
335
- path.join(__dirname, '../../../wasm-engine/pkg/veestack_wasm_engine_bg.wasm'),
336
- ];
337
-
338
- for (const wasmPath of possiblePaths) {
339
- if (fs.existsSync(wasmPath)) {
340
- return wasmPath;
341
- }
342
- }
343
-
344
- return null;
345
- }
346
-
347
- private allocateString(str: string): number {
348
- if (!this.wasmInstance) return 0;
349
-
350
- const encoder = new TextEncoder();
351
- const bytes = encoder.encode(str + '\0');
352
-
353
- const exports = this.wasmInstance.exports as any;
354
- const ptr = exports.malloc ? exports.malloc(bytes.length) : 0;
355
-
356
- if (ptr === 0) {
357
- // Fallback: use memory directly
358
- const memory = exports.memory as WebAssembly.Memory;
359
- const view = new Uint8Array(memory.buffer);
360
- const offset = 1024; // Use a fixed offset
361
- view.set(bytes, offset);
362
- return offset;
363
- }
364
-
365
- const memory = exports.memory as WebAssembly.Memory;
366
- const view = new Uint8Array(memory.buffer);
367
- view.set(bytes, ptr);
368
-
369
- return ptr;
370
- }
371
-
372
- private readString(ptr: number): string {
373
- if (!this.wasmInstance) return '';
374
-
375
- const exports = this.wasmInstance.exports as any;
376
- const memory = exports.memory as WebAssembly.Memory;
377
- const view = new Uint8Array(memory.buffer);
378
-
379
- // Find null terminator
380
- let end = ptr;
381
- while (view[end] !== 0 && end < view.length) {
382
- end++;
383
- }
384
-
385
- const bytes = view.slice(ptr, end);
386
- return new TextDecoder().decode(bytes);
387
- }
388
-
389
- private decryptSessionKey(encrypted: string): string {
390
- const decoded = Buffer.from(encrypted, 'base64');
391
- return decoded.toString('utf-8');
392
- }
393
-
394
- private decryptRules(encrypted: string): string {
395
- const decoded = Buffer.from(encrypted, 'base64');
396
- const key = Buffer.from(this.sessionKey);
397
-
398
- const decrypted = decoded.map((byte, i) => byte ^ key[i % key.length]);
399
- return decrypted.toString('utf-8');
400
- }
401
-
402
- private encryptString(str: string): string {
403
- const key = Buffer.from('veestack_session_key_2024');
404
- const data = Buffer.from(str);
405
-
406
- const encrypted = data.map((byte, i) => byte ^ key[i % key.length]);
407
- return encrypted.toString('base64');
408
- }
409
- }
package/tsconfig.json DELETED
@@ -1,19 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "ESNext",
5
- "lib": ["ES2022"],
6
- "moduleResolution": "bundler",
7
- "outDir": "./dist",
8
- "rootDir": "./src",
9
- "strict": true,
10
- "esModuleInterop": true,
11
- "skipLibCheck": true,
12
- "forceConsistentCasingInFileNames": true,
13
- "declaration": true,
14
- "declarationMap": true,
15
- "types": ["node"]
16
- },
17
- "include": ["src/**/*"],
18
- "exclude": ["node_modules", "dist"]
19
- }
package/tsup.config.ts DELETED
@@ -1,11 +0,0 @@
1
- import { defineConfig } from 'tsup';
2
-
3
- export default defineConfig({
4
- entry: ['src/index.ts'],
5
- format: ['esm'],
6
- dts: false,
7
- clean: true,
8
- external: ['@veestack/types', '@veestack/engine', '@veestack/utils'],
9
- splitting: false,
10
- // No banner here - we'll add shebang in package.json bin
11
- });