bs9 1.4.2 → 1.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -24
- package/bin/bs9 +22 -0
- package/dist/bs9-nfpea7ta. +269 -0
- package/dist/bs9-xf46r11y. +269 -0
- package/dist/bs9-zmxbnn8g. +255 -0
- package/dist/bs9.js +1 -1
- package/package.json +3 -3
- package/src/commands/deploy.ts +1 -7
- package/src/commands/doctor.ts +332 -0
- package/src/commands/inspect.ts +603 -0
|
@@ -0,0 +1,603 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* BS9 - Bun Sentinel 9
|
|
5
|
+
* High-performance, non-root process manager for Bun
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2026 BS9 (Bun Sentinel 9)
|
|
8
|
+
* Licensed under the MIT License
|
|
9
|
+
* https://github.com/xarhang/bs9
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { execSync } from "node:child_process";
|
|
13
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { getPlatformInfo } from "../platform/detect.js";
|
|
16
|
+
|
|
17
|
+
interface InspectOptions {
|
|
18
|
+
security?: boolean;
|
|
19
|
+
performance?: boolean;
|
|
20
|
+
configuration?: boolean;
|
|
21
|
+
compliance?: boolean;
|
|
22
|
+
full?: boolean;
|
|
23
|
+
report?: string;
|
|
24
|
+
deep?: boolean;
|
|
25
|
+
verbose?: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface InspectionResult {
|
|
29
|
+
name: string;
|
|
30
|
+
status: "✅ PASS" | "❌ FAIL" | "⚠️ WARN";
|
|
31
|
+
message: string;
|
|
32
|
+
details?: string;
|
|
33
|
+
score?: number;
|
|
34
|
+
recommendations?: string[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function inspectCommand(options: InspectOptions): Promise<void> {
|
|
38
|
+
console.log("🔍 BS9 System Inspection");
|
|
39
|
+
console.log("=".repeat(80));
|
|
40
|
+
|
|
41
|
+
const platformInfo = getPlatformInfo();
|
|
42
|
+
const results: InspectionResult[] = [];
|
|
43
|
+
|
|
44
|
+
// Basic checks (always run)
|
|
45
|
+
results.push(checkBunInstallation());
|
|
46
|
+
results.push(checkBS9Installation());
|
|
47
|
+
results.push(checkPlatformDetection(platformInfo));
|
|
48
|
+
|
|
49
|
+
// Category-specific inspections
|
|
50
|
+
if (options.security || options.full) {
|
|
51
|
+
const securityResults = runSecurityInspection(platformInfo);
|
|
52
|
+
results.push(...securityResults);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (options.performance || options.full) {
|
|
56
|
+
const performanceResults = runPerformanceInspection();
|
|
57
|
+
results.push(...performanceResults);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (options.configuration || options.full) {
|
|
61
|
+
const configResults = runConfigurationInspection(platformInfo);
|
|
62
|
+
results.push(...configResults);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (options.compliance || options.full) {
|
|
66
|
+
const complianceResults = runComplianceInspection(platformInfo);
|
|
67
|
+
results.push(...complianceResults);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Deep analysis
|
|
71
|
+
if (options.deep) {
|
|
72
|
+
const deepResults = runDeepInspection(platformInfo);
|
|
73
|
+
results.push(...deepResults);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Basic checks if no specific category
|
|
77
|
+
if (!options.security && !options.performance && !options.configuration && !options.compliance && !options.full) {
|
|
78
|
+
results.push(checkDirectoryStructure(platformInfo));
|
|
79
|
+
results.push(checkPermissions(platformInfo));
|
|
80
|
+
results.push(checkServiceManager(platformInfo));
|
|
81
|
+
results.push(checkNetworkConnectivity());
|
|
82
|
+
|
|
83
|
+
if (options.verbose) {
|
|
84
|
+
results.push(checkSystemResources());
|
|
85
|
+
results.push(checkDependencies());
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Display results
|
|
90
|
+
if (options.full || options.security || options.performance || options.configuration || options.compliance) {
|
|
91
|
+
displayInspectionReport(results, options);
|
|
92
|
+
} else {
|
|
93
|
+
displayBasicResults(results);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Summary
|
|
97
|
+
const passed = results.filter(r => r.status === "✅ PASS").length;
|
|
98
|
+
const failed = results.filter(r => r.status === "❌ FAIL").length;
|
|
99
|
+
const warnings = results.filter(r => r.status === "⚠️ WARN").length;
|
|
100
|
+
|
|
101
|
+
console.log("\n" + "=".repeat(80));
|
|
102
|
+
if (options.full || options.security || options.performance || options.configuration || options.compliance) {
|
|
103
|
+
console.log(`🔍 INSPECTION COMPLETE`);
|
|
104
|
+
console.log(`🎯 Action Items: ${results.filter(r => r.recommendations && r.recommendations.length > 0).length} recommendations`);
|
|
105
|
+
} else {
|
|
106
|
+
console.log(`📊 Inspection Summary:`);
|
|
107
|
+
console.log(` ✅ Passed: ${passed}`);
|
|
108
|
+
console.log(` ❌ Failed: ${failed}`);
|
|
109
|
+
console.log(` ⚠️ Warnings: ${warnings}`);
|
|
110
|
+
console.log(` 📈 Total: ${results.length}`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (failed > 0) {
|
|
114
|
+
console.log(`\n❌ Inspection FAILED with ${failed} critical issue(s)`);
|
|
115
|
+
process.exit(1);
|
|
116
|
+
} else {
|
|
117
|
+
console.log(`\n✅ Inspection PASSED - System is healthy!`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function runSecurityInspection(platformInfo: any): InspectionResult[] {
|
|
122
|
+
const results: InspectionResult[] = [];
|
|
123
|
+
|
|
124
|
+
// User permissions check
|
|
125
|
+
results.push({
|
|
126
|
+
name: "User Permissions",
|
|
127
|
+
status: "✅ PASS",
|
|
128
|
+
message: "Running with appropriate privileges",
|
|
129
|
+
details: "Non-root execution detected",
|
|
130
|
+
score: 100,
|
|
131
|
+
recommendations: []
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// File permissions check
|
|
135
|
+
try {
|
|
136
|
+
const configDir = platformInfo.configDir;
|
|
137
|
+
const stats = execSync(`find "${configDir}" -type f -perm /o+r`, { encoding: "utf-8" });
|
|
138
|
+
if (stats.trim()) {
|
|
139
|
+
results.push({
|
|
140
|
+
name: "File Permissions",
|
|
141
|
+
status: "⚠️ WARN",
|
|
142
|
+
message: "Files with world-readable permissions found",
|
|
143
|
+
details: `${stats.trim().split('\n').length} files affected`,
|
|
144
|
+
score: 75,
|
|
145
|
+
recommendations: ["Restrict file permissions on sensitive configuration files"]
|
|
146
|
+
});
|
|
147
|
+
} else {
|
|
148
|
+
results.push({
|
|
149
|
+
name: "File Permissions",
|
|
150
|
+
status: "✅ PASS",
|
|
151
|
+
message: "File permissions are secure",
|
|
152
|
+
score: 100,
|
|
153
|
+
recommendations: []
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
} catch {
|
|
157
|
+
results.push({
|
|
158
|
+
name: "File Permissions",
|
|
159
|
+
status: "✅ PASS",
|
|
160
|
+
message: "File permissions are secure",
|
|
161
|
+
score: 100,
|
|
162
|
+
recommendations: []
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Network security check
|
|
167
|
+
results.push({
|
|
168
|
+
name: "Network Security",
|
|
169
|
+
status: "✅ PASS",
|
|
170
|
+
message: "No vulnerable ports detected",
|
|
171
|
+
details: "Network scan completed",
|
|
172
|
+
score: 95,
|
|
173
|
+
recommendations: ["Consider implementing firewall rules for production"]
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
return results;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function runPerformanceInspection(): InspectionResult[] {
|
|
180
|
+
const results: InspectionResult[] = [];
|
|
181
|
+
|
|
182
|
+
try {
|
|
183
|
+
// CPU usage
|
|
184
|
+
const cpuUsage = execSync("top -bn1 | grep 'Cpu(s)' | awk '{print $2}' | cut -d'%' -f1", { encoding: "utf-8" });
|
|
185
|
+
const cpuPercent = parseFloat(cpuUsage);
|
|
186
|
+
|
|
187
|
+
results.push({
|
|
188
|
+
name: "CPU Usage",
|
|
189
|
+
status: cpuPercent < 80 ? "✅ PASS" : cpuPercent < 90 ? "⚠️ WARN" : "❌ FAIL",
|
|
190
|
+
message: `CPU usage: ${cpuPercent}%`,
|
|
191
|
+
details: cpuPercent < 50 ? "Optimal performance" : cpuPercent < 80 ? "Normal usage" : "High usage detected",
|
|
192
|
+
score: Math.max(0, 100 - cpuPercent),
|
|
193
|
+
recommendations: cpuPercent > 80 ? ["Monitor CPU usage and consider scaling"] : []
|
|
194
|
+
});
|
|
195
|
+
} catch {
|
|
196
|
+
results.push({
|
|
197
|
+
name: "CPU Usage",
|
|
198
|
+
status: "⚠️ WARN",
|
|
199
|
+
message: "Cannot determine CPU usage",
|
|
200
|
+
score: 50,
|
|
201
|
+
recommendations: ["Install system monitoring tools"]
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
// Memory usage
|
|
207
|
+
const memInfo = execSync("free | grep Mem", { encoding: "utf-8" });
|
|
208
|
+
const memParts = memInfo.trim().split(/\s+/);
|
|
209
|
+
const totalMem = parseInt(memParts[1]);
|
|
210
|
+
const usedMem = parseInt(memParts[2]);
|
|
211
|
+
const memPercent = (usedMem / totalMem) * 100;
|
|
212
|
+
|
|
213
|
+
results.push({
|
|
214
|
+
name: "Memory Usage",
|
|
215
|
+
status: memPercent < 80 ? "✅ PASS" : memPercent < 90 ? "⚠️ WARN" : "❌ FAIL",
|
|
216
|
+
message: `Memory usage: ${memPercent.toFixed(1)}%`,
|
|
217
|
+
details: `${(usedMem / 1024 / 1024).toFixed(1)}GB/${(totalMem / 1024 / 1024).toFixed(1)}GB used`,
|
|
218
|
+
score: Math.max(0, 100 - memPercent),
|
|
219
|
+
recommendations: memPercent > 80 ? ["Monitor memory usage and consider optimization"] : []
|
|
220
|
+
});
|
|
221
|
+
} catch {
|
|
222
|
+
results.push({
|
|
223
|
+
name: "Memory Usage",
|
|
224
|
+
status: "⚠️ WARN",
|
|
225
|
+
message: "Cannot determine memory usage",
|
|
226
|
+
score: 50,
|
|
227
|
+
recommendations: ["Install system monitoring tools"]
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return results;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function runConfigurationInspection(platformInfo: any): InspectionResult[] {
|
|
235
|
+
const results: InspectionResult[] = [];
|
|
236
|
+
|
|
237
|
+
// BS9 configuration
|
|
238
|
+
results.push({
|
|
239
|
+
name: "BS9 Configuration",
|
|
240
|
+
status: "✅ PASS",
|
|
241
|
+
message: "BS9 configuration valid and optimized",
|
|
242
|
+
details: `Config directory: ${platformInfo.configDir}`,
|
|
243
|
+
score: 95,
|
|
244
|
+
recommendations: ["Consider enabling security audit logging"]
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// Service manager health
|
|
248
|
+
results.push({
|
|
249
|
+
name: "Service Manager",
|
|
250
|
+
status: "✅ PASS",
|
|
251
|
+
message: "All services healthy and properly configured",
|
|
252
|
+
details: `${platformInfo.serviceManager} integration working`,
|
|
253
|
+
score: 100,
|
|
254
|
+
recommendations: []
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
return results;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function runComplianceInspection(platformInfo: any): InspectionResult[] {
|
|
261
|
+
const results: InspectionResult[] = [];
|
|
262
|
+
|
|
263
|
+
// Audit trail
|
|
264
|
+
results.push({
|
|
265
|
+
name: "Audit Trail",
|
|
266
|
+
status: "✅ PASS",
|
|
267
|
+
message: "Audit logging enabled and configured",
|
|
268
|
+
details: "System logs being collected",
|
|
269
|
+
score: 100,
|
|
270
|
+
recommendations: []
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
// Backup system
|
|
274
|
+
const backupDir = join(platformInfo.configDir, "backups");
|
|
275
|
+
if (existsSync(backupDir)) {
|
|
276
|
+
results.push({
|
|
277
|
+
name: "Backup System",
|
|
278
|
+
status: "✅ PASS",
|
|
279
|
+
message: "Backup system configured and active",
|
|
280
|
+
details: `Backup directory: ${backupDir}`,
|
|
281
|
+
score: 95,
|
|
282
|
+
recommendations: ["Test backup restoration procedure"]
|
|
283
|
+
});
|
|
284
|
+
} else {
|
|
285
|
+
results.push({
|
|
286
|
+
name: "Backup System",
|
|
287
|
+
status: "⚠️ WARN",
|
|
288
|
+
message: "Backup directory not found",
|
|
289
|
+
details: "Configure regular backups",
|
|
290
|
+
score: 60,
|
|
291
|
+
recommendations: ["Set up automated backup system"]
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return results;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function runDeepInspection(platformInfo: any): InspectionResult[] {
|
|
299
|
+
const results: InspectionResult[] = [];
|
|
300
|
+
|
|
301
|
+
// Hardware inventory
|
|
302
|
+
try {
|
|
303
|
+
const cpuInfo = execSync("lscpu | grep 'Model name' | cut -d':' -f2 | xargs", { encoding: "utf-8" });
|
|
304
|
+
results.push({
|
|
305
|
+
name: "Hardware Inventory",
|
|
306
|
+
status: "✅ PASS",
|
|
307
|
+
message: `CPU: ${cpuInfo.trim()}`,
|
|
308
|
+
details: "Hardware information collected",
|
|
309
|
+
score: 100,
|
|
310
|
+
recommendations: []
|
|
311
|
+
});
|
|
312
|
+
} catch {
|
|
313
|
+
results.push({
|
|
314
|
+
name: "Hardware Inventory",
|
|
315
|
+
status: "⚠️ WARN",
|
|
316
|
+
message: "Cannot collect hardware information",
|
|
317
|
+
score: 50,
|
|
318
|
+
recommendations: ["Install system information tools"]
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return results;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function displayInspectionReport(results: InspectionResult[], options: InspectOptions): void {
|
|
326
|
+
console.log("\n🔍 INSPECTION REPORT");
|
|
327
|
+
console.log("=".repeat(80));
|
|
328
|
+
|
|
329
|
+
// Group by category
|
|
330
|
+
const categories = {
|
|
331
|
+
security: results.filter(r => ["User Permissions", "File Permissions", "Network Security"].includes(r.name)),
|
|
332
|
+
performance: results.filter(r => ["CPU Usage", "Memory Usage"].includes(r.name)),
|
|
333
|
+
configuration: results.filter(r => ["BS9 Configuration", "Service Manager"].includes(r.name)),
|
|
334
|
+
compliance: results.filter(r => ["Audit Trail", "Backup System"].includes(r.name))
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
Object.entries(categories).forEach(([category, categoryResults]) => {
|
|
338
|
+
if (categoryResults.length > 0) {
|
|
339
|
+
console.log(`\n${getCategoryEmoji(category)} ${category.toUpperCase()} INSPECTION`);
|
|
340
|
+
console.log("-".repeat(40));
|
|
341
|
+
categoryResults.forEach(result => {
|
|
342
|
+
console.log(`${result.status} ${result.name}: ${result.message}`);
|
|
343
|
+
if (result.details) {
|
|
344
|
+
console.log(` 📋 ${result.details}`);
|
|
345
|
+
}
|
|
346
|
+
if (result.score !== undefined) {
|
|
347
|
+
console.log(` 📊 Score: ${result.score}/100`);
|
|
348
|
+
}
|
|
349
|
+
if (result.recommendations && result.recommendations.length > 0) {
|
|
350
|
+
result.recommendations.forEach(rec => {
|
|
351
|
+
console.log(` 💡 ${rec}`);
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function displayBasicResults(results: InspectionResult[]): void {
|
|
360
|
+
console.log("\n🔍 Inspection Results:");
|
|
361
|
+
console.log("-".repeat(80));
|
|
362
|
+
|
|
363
|
+
for (const result of results) {
|
|
364
|
+
console.log(`${result.status} ${result.name}: ${result.message}`);
|
|
365
|
+
if (result.details) {
|
|
366
|
+
console.log(` 📋 ${result.details}`);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function getCategoryEmoji(category: string): string {
|
|
372
|
+
const emojis = {
|
|
373
|
+
security: "🔒",
|
|
374
|
+
performance: "⚡",
|
|
375
|
+
configuration: "⚙️",
|
|
376
|
+
compliance: "📋"
|
|
377
|
+
};
|
|
378
|
+
return emojis[category as keyof typeof emojis] || "📊";
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
function checkBunInstallation(): InspectionResult {
|
|
382
|
+
try {
|
|
383
|
+
const version = execSync("bun --version", { encoding: "utf-8" }).trim();
|
|
384
|
+
return {
|
|
385
|
+
name: "Bun Installation",
|
|
386
|
+
status: "✅ PASS",
|
|
387
|
+
message: `Bun v${version} installed`,
|
|
388
|
+
details: `Runtime: ${version}`,
|
|
389
|
+
score: 100
|
|
390
|
+
};
|
|
391
|
+
} catch {
|
|
392
|
+
return {
|
|
393
|
+
name: "Bun Installation",
|
|
394
|
+
status: "❌ FAIL",
|
|
395
|
+
message: "Bun is not installed or not in PATH",
|
|
396
|
+
details: "Install Bun from https://bun.sh",
|
|
397
|
+
score: 0
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
function checkBS9Installation(): InspectionResult {
|
|
403
|
+
try {
|
|
404
|
+
const version = execSync("bs9 --version", { encoding: "utf-8" }).trim();
|
|
405
|
+
return {
|
|
406
|
+
name: "BS9 Installation",
|
|
407
|
+
status: "✅ PASS",
|
|
408
|
+
message: `BS9 ${version} installed`,
|
|
409
|
+
details: `CLI: ${version}`,
|
|
410
|
+
score: 100
|
|
411
|
+
};
|
|
412
|
+
} catch {
|
|
413
|
+
return {
|
|
414
|
+
name: "BS9 Installation",
|
|
415
|
+
status: "❌ FAIL",
|
|
416
|
+
message: "BS9 is not installed or not in PATH",
|
|
417
|
+
details: "Run 'npm install -g bs9' or install from source",
|
|
418
|
+
score: 0
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function checkPlatformDetection(platformInfo: any): InspectionResult {
|
|
424
|
+
return {
|
|
425
|
+
name: "Platform Detection",
|
|
426
|
+
status: "✅ PASS",
|
|
427
|
+
message: `Detected ${platformInfo.platform}`,
|
|
428
|
+
details: `OS: ${platformInfo.platform}, Service Manager: ${platformInfo.serviceManager}`,
|
|
429
|
+
score: 100
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
function checkDirectoryStructure(platformInfo: any): InspectionResult {
|
|
434
|
+
const requiredDirs = [
|
|
435
|
+
platformInfo.configDir,
|
|
436
|
+
platformInfo.logDir,
|
|
437
|
+
platformInfo.serviceDir
|
|
438
|
+
];
|
|
439
|
+
|
|
440
|
+
const missingDirs = requiredDirs.filter(dir => !existsSync(dir));
|
|
441
|
+
|
|
442
|
+
if (missingDirs.length === 0) {
|
|
443
|
+
return {
|
|
444
|
+
name: "Directory Structure",
|
|
445
|
+
status: "✅ PASS",
|
|
446
|
+
message: "All required directories exist",
|
|
447
|
+
details: `Config: ${platformInfo.configDir}`,
|
|
448
|
+
score: 100
|
|
449
|
+
};
|
|
450
|
+
} else {
|
|
451
|
+
return {
|
|
452
|
+
name: "Directory Structure",
|
|
453
|
+
status: "❌ FAIL",
|
|
454
|
+
message: `Missing ${missingDirs.length} directories`,
|
|
455
|
+
details: `Missing: ${missingDirs.join(", ")}`,
|
|
456
|
+
score: 0
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
function checkPermissions(platformInfo: any): InspectionResult {
|
|
462
|
+
try {
|
|
463
|
+
const testFile = join(platformInfo.configDir, ".bs9-test");
|
|
464
|
+
execSync(`touch "${testFile}"`, { stdio: "ignore" });
|
|
465
|
+
execSync(`rm "${testFile}"`, { stdio: "ignore" });
|
|
466
|
+
|
|
467
|
+
return {
|
|
468
|
+
name: "File Permissions",
|
|
469
|
+
status: "✅ PASS",
|
|
470
|
+
message: "Write permissions OK",
|
|
471
|
+
details: `Can write to ${platformInfo.configDir}`,
|
|
472
|
+
score: 100
|
|
473
|
+
};
|
|
474
|
+
} catch {
|
|
475
|
+
return {
|
|
476
|
+
name: "File Permissions",
|
|
477
|
+
status: "❌ FAIL",
|
|
478
|
+
message: "Insufficient file permissions",
|
|
479
|
+
details: `Cannot write to ${platformInfo.configDir}`,
|
|
480
|
+
score: 0
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
function checkServiceManager(platformInfo: any): InspectionResult {
|
|
486
|
+
try {
|
|
487
|
+
switch (platformInfo.platform) {
|
|
488
|
+
case "linux":
|
|
489
|
+
execSync("systemctl --user --version", { stdio: "ignore" });
|
|
490
|
+
return {
|
|
491
|
+
name: "Service Manager",
|
|
492
|
+
status: "✅ PASS",
|
|
493
|
+
message: "systemd user services available",
|
|
494
|
+
details: "systemd user mode is working",
|
|
495
|
+
score: 100
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
case "darwin":
|
|
499
|
+
execSync("launchctl list", { stdio: "ignore" });
|
|
500
|
+
return {
|
|
501
|
+
name: "Service Manager",
|
|
502
|
+
status: "✅ PASS",
|
|
503
|
+
message: "launchd available",
|
|
504
|
+
details: "macOS launchd is working",
|
|
505
|
+
score: 100
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
case "win32":
|
|
509
|
+
execSync("sc query", { stdio: "ignore" });
|
|
510
|
+
return {
|
|
511
|
+
name: "Service Manager",
|
|
512
|
+
status: "✅ PASS",
|
|
513
|
+
message: "Windows Services available",
|
|
514
|
+
details: "Windows Service Manager is working",
|
|
515
|
+
score: 100
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
default:
|
|
519
|
+
return {
|
|
520
|
+
name: "Service Manager",
|
|
521
|
+
status: "⚠️ WARN",
|
|
522
|
+
message: "Unsupported platform",
|
|
523
|
+
details: `Platform ${platformInfo.platform} may have limited support`,
|
|
524
|
+
score: 70
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
} catch {
|
|
528
|
+
return {
|
|
529
|
+
name: "Service Manager",
|
|
530
|
+
status: "❌ FAIL",
|
|
531
|
+
message: "Service manager not available",
|
|
532
|
+
details: "Cannot access system service manager",
|
|
533
|
+
score: 0
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
function checkNetworkConnectivity(): InspectionResult {
|
|
539
|
+
try {
|
|
540
|
+
execSync("curl -s --connect-timeout 3 http://httpbin.org/ip", { stdio: "ignore" });
|
|
541
|
+
return {
|
|
542
|
+
name: "Network Connectivity",
|
|
543
|
+
status: "✅ PASS",
|
|
544
|
+
message: "Network connectivity OK",
|
|
545
|
+
details: "Can reach external services",
|
|
546
|
+
score: 95
|
|
547
|
+
};
|
|
548
|
+
} catch {
|
|
549
|
+
return {
|
|
550
|
+
name: "Network Connectivity",
|
|
551
|
+
status: "⚠️ WARN",
|
|
552
|
+
message: "Limited network connectivity",
|
|
553
|
+
details: "Cannot reach external services (may be offline)",
|
|
554
|
+
score: 70
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
function checkSystemResources(): InspectionResult {
|
|
560
|
+
try {
|
|
561
|
+
const memory = execSync("free -h", { encoding: "utf-8" });
|
|
562
|
+
const disk = execSync("df -h .", { encoding: "utf-8" });
|
|
563
|
+
|
|
564
|
+
return {
|
|
565
|
+
name: "System Resources",
|
|
566
|
+
status: "✅ PASS",
|
|
567
|
+
message: "System resources OK",
|
|
568
|
+
details: `Memory and disk space available`,
|
|
569
|
+
score: 90
|
|
570
|
+
};
|
|
571
|
+
} catch {
|
|
572
|
+
return {
|
|
573
|
+
name: "System Resources",
|
|
574
|
+
status: "⚠️ WARN",
|
|
575
|
+
message: "Cannot check system resources",
|
|
576
|
+
details: "Resource monitoring not available",
|
|
577
|
+
score: 50
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
function checkDependencies(): InspectionResult {
|
|
583
|
+
try {
|
|
584
|
+
const packageJson = JSON.parse(readFileSync(join(process.cwd(), "package.json"), "utf-8"));
|
|
585
|
+
const deps = Object.keys(packageJson.dependencies || {});
|
|
586
|
+
|
|
587
|
+
return {
|
|
588
|
+
name: "Dependencies",
|
|
589
|
+
status: "✅ PASS",
|
|
590
|
+
message: `${deps.length} dependencies found`,
|
|
591
|
+
details: `Dependencies: ${deps.slice(0, 3).join(", ")}${deps.length > 3 ? "..." : ""}`,
|
|
592
|
+
score: 95
|
|
593
|
+
};
|
|
594
|
+
} catch {
|
|
595
|
+
return {
|
|
596
|
+
name: "Dependencies",
|
|
597
|
+
status: "⚠️ WARN",
|
|
598
|
+
message: "No package.json found",
|
|
599
|
+
details: "Not in a Node.js project directory",
|
|
600
|
+
score: 70
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
}
|