torusguard 1.3.6 → 2.0.0-alpha

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 (110) hide show
  1. package/.torusguard/.manifest.json +9 -8
  2. package/.torusguard/auth.json +5 -0
  3. package/.torusguard/rules_catalog.json +242 -518
  4. package/.torusguard/runs/report-latest.html +3529 -364
  5. package/.torusguard/runs/run-20260918-105940-audit/manifest.json +2 -1
  6. package/.torusguard/runs/run-20260918-105940-audit/remediation.md +7 -0
  7. package/.torusguard/runs/run-20260919-145701-audit/findings.json +1 -0
  8. package/.torusguard/runs/run-20260919-145701-audit/findings.md +8 -0
  9. package/.torusguard/runs/run-20260919-145701-audit/manifest.json +12 -0
  10. package/.torusguard/runs/run-20260919-145701-audit/summary.md +5 -0
  11. package/.torusguard/runs/run-20260919-151729-audit/findings.json +1 -0
  12. package/.torusguard/runs/run-20260919-151729-audit/findings.md +8 -0
  13. package/.torusguard/runs/run-20260919-151729-audit/manifest.json +13 -0
  14. package/.torusguard/runs/run-20260919-151729-audit/remediation.md +7 -0
  15. package/.torusguard/runs/run-20260919-151729-audit/summary.md +5 -0
  16. package/.torusguard/runs/run-20260919-152340-audit/findings.json +1 -0
  17. package/.torusguard/runs/run-20260919-152340-audit/findings.md +8 -0
  18. package/.torusguard/runs/run-20260919-152340-audit/manifest.json +12 -0
  19. package/.torusguard/runs/run-20260919-152340-audit/summary.md +5 -0
  20. package/.torusguard/runs/run-20260919-152345-audit/findings.json +1 -0
  21. package/.torusguard/runs/run-20260919-152345-audit/findings.md +8 -0
  22. package/.torusguard/runs/run-20260919-152345-audit/manifest.json +12 -0
  23. package/.torusguard/runs/run-20260919-152345-audit/summary.md +5 -0
  24. package/.torusguard/runs/run-20260919-153500-audit/findings.json +1 -0
  25. package/.torusguard/runs/run-20260919-153500-audit/findings.md +8 -0
  26. package/.torusguard/runs/run-20260919-153500-audit/manifest.json +12 -0
  27. package/.torusguard/runs/run-20260919-153500-audit/summary.md +5 -0
  28. package/.torusguard/scripts/__pycache__/apply_runner.cpython-314.pyc +0 -0
  29. package/.torusguard/scripts/__pycache__/audit_runner.cpython-314.pyc +0 -0
  30. package/.torusguard/scripts/__pycache__/harden_runner.cpython-314.pyc +0 -0
  31. package/.torusguard/scripts/__pycache__/html_reporter.cpython-314.pyc +0 -0
  32. package/.torusguard/scripts/__pycache__/manifest_builder.cpython-314.pyc +0 -0
  33. package/.torusguard/scripts/__pycache__/recipes_runner.cpython-314.pyc +0 -0
  34. package/.torusguard/scripts/__pycache__/report_sync.cpython-314.pyc +0 -0
  35. package/.torusguard/scripts/apply_runner.py +101 -8
  36. package/.torusguard/scripts/audit_runner.py +116 -11
  37. package/.torusguard/scripts/harden_runner.py +122 -68
  38. package/.torusguard/scripts/html_reporter.py +1170 -253
  39. package/.torusguard/scripts/manifest_builder.py +2 -0
  40. package/.torusguard/scripts/recheck_runner.py +2 -1
  41. package/.torusguard/scripts/recipes_runner.py +91 -8
  42. package/.torusguard/scripts/report_sync.py +134 -7
  43. package/.torusguard/scripts/status_runner.py +267 -0
  44. package/.torusguard/snapshots/20260921-182638/go.mod.bak +11 -0
  45. package/.torusguard/snapshots/20260921-185213/file.go.bak +5 -0
  46. package/README.md +314 -364
  47. package/bin/torusguard.js +190 -20
  48. package/package.json +6 -2
  49. package/skills/torusguard/__pycache__/bootstrap.cpython-314.pyc +0 -0
  50. package/skills/torusguard/bootstrap.py +45 -6
  51. package/skills/torusguard/payload/.manifest.json +29 -14
  52. package/skills/torusguard/payload/TORUSGUARD.md +145 -145
  53. package/skills/torusguard/payload/agents/auditor.md +41 -41
  54. package/skills/torusguard/payload/agents/profiler.md +49 -49
  55. package/skills/torusguard/payload/agents/remediator.md +41 -41
  56. package/skills/torusguard/payload/agents/reviewer.md +39 -39
  57. package/skills/torusguard/payload/agents/validator.md +46 -46
  58. package/skills/torusguard/payload/config/scope.json +24 -24
  59. package/skills/torusguard/payload/references/csharp-security.md +41 -41
  60. package/skills/torusguard/payload/references/go-security.md +41 -41
  61. package/skills/torusguard/payload/references/java-security.md +40 -40
  62. package/skills/torusguard/payload/references/polyglot-security-matrix.md +25 -25
  63. package/skills/torusguard/payload/references/rust-security.md +40 -40
  64. package/skills/torusguard/payload/rules/custom/.gitkeep +1 -1
  65. package/skills/torusguard/payload/rules/custom/README.md +30 -30
  66. package/skills/torusguard/payload/scripts/__pycache__/audit_runner.cpython-314.pyc +0 -0
  67. package/skills/torusguard/payload/scripts/__pycache__/html_reporter.cpython-314.pyc +0 -0
  68. package/skills/torusguard/payload/scripts/__pycache__/report_sync.cpython-314.pyc +0 -0
  69. package/skills/torusguard/payload/scripts/__pycache__/sarif_exporter.cpython-314.pyc +0 -0
  70. package/skills/torusguard/payload/scripts/__pycache__/term_ui.cpython-314.pyc +0 -0
  71. package/skills/torusguard/payload/scripts/apply_runner.py +101 -8
  72. package/skills/torusguard/payload/scripts/audit_runner.py +116 -11
  73. package/skills/torusguard/payload/scripts/harden_runner.py +122 -68
  74. package/skills/torusguard/payload/scripts/html_reporter.py +1170 -253
  75. package/skills/torusguard/payload/scripts/manifest_builder.py +2 -0
  76. package/skills/torusguard/payload/scripts/recheck_runner.py +2 -1
  77. package/skills/torusguard/payload/scripts/recipes_runner.py +91 -8
  78. package/skills/torusguard/payload/scripts/report_sync.py +134 -7
  79. package/skills/torusguard/payload/scripts/rules_sync.py +321 -321
  80. package/skills/torusguard/payload/scripts/safety_gate.py +64 -64
  81. package/skills/torusguard/payload/scripts/status_runner.py +267 -0
  82. package/skills/torusguard/payload/skills/torusguard/references/csharp-security.md +41 -41
  83. package/skills/torusguard/payload/skills/torusguard/references/go-security.md +41 -41
  84. package/skills/torusguard/payload/skills/torusguard/references/java-security.md +40 -40
  85. package/skills/torusguard/payload/skills/torusguard/references/polyglot-security-matrix.md +25 -25
  86. package/skills/torusguard/payload/skills/torusguard/references/rust-security.md +40 -40
  87. package/skills/torusguard/payload/templates/audit-report.template.md +54 -54
  88. package/skills/torusguard/payload/templates/authorization.template.md +34 -34
  89. package/skills/torusguard/payload/templates/finding-card.template.md +32 -32
  90. package/skills/torusguard/payload/templates/remediation-bundle.template.md +35 -35
  91. package/skills/torusguard/payload/workflows/apply.md +9 -1
  92. package/skills/torusguard/payload/workflows/audit.md +8 -2
  93. package/skills/torusguard/payload/workflows/harden.md +6 -1
  94. package/skills/torusguard/payload/workflows/init.md +7 -1
  95. package/skills/torusguard/payload/workflows/recipes.md +55 -0
  96. package/skills/torusguard/payload/workflows/report.md +59 -55
  97. package/skills/torusguard/payload/workflows/status.md +4 -1
  98. package/skills/torusguard/payload/workflows/torusguard-apply.md +110 -0
  99. package/skills/torusguard/payload/workflows/torusguard-audit.md +105 -0
  100. package/skills/torusguard/payload/workflows/torusguard-authorize.md +96 -0
  101. package/skills/torusguard/payload/workflows/torusguard-exploit-check.md +98 -0
  102. package/skills/torusguard/payload/workflows/torusguard-harden.md +104 -0
  103. package/skills/torusguard/payload/workflows/torusguard-init.md +106 -0
  104. package/skills/torusguard/payload/workflows/torusguard-recheck.md +101 -0
  105. package/skills/torusguard/payload/workflows/torusguard-recipes.md +55 -0
  106. package/skills/torusguard/payload/workflows/torusguard-report.md +105 -0
  107. package/skills/torusguard/payload/workflows/torusguard-status.md +103 -0
  108. package/skills/torusguard/payload/workflows/torusguard-verify.md +100 -0
  109. package/skills/torusguard/payload/workflows/torusguard-web-validate.md +96 -0
  110. package/skills/torusguard/payload/workflows/torusguard.md +19 -0
package/bin/torusguard.js CHANGED
@@ -15,6 +15,51 @@ const command = args[0] || 'init';
15
15
  const rootDir = path.resolve(__dirname, '..');
16
16
  const cwd = process.cwd();
17
17
 
18
+ // Parse version flag immediately
19
+ if (command === '--version' || command === '-v' || command === 'version') {
20
+ let ver = '1.4.0';
21
+ try {
22
+ const pkg = JSON.parse(fs.readFileSync(path.join(rootDir, 'package.json'), 'utf-8'));
23
+ ver = pkg.version || ver;
24
+ } catch (e) {}
25
+ console.log(`torusguard v${ver}`);
26
+ process.exit(0);
27
+ }
28
+
29
+ function parseTargetAndArgs(cliArgs) {
30
+ let target = '.';
31
+ const remaining = [];
32
+ for (let i = 1; i < cliArgs.length; i++) {
33
+ const a = cliArgs[i];
34
+ if (a === '--target' || a === '-t' || a === '--root') {
35
+ if (i + 1 < cliArgs.length) {
36
+ target = cliArgs[i + 1];
37
+ i++;
38
+ }
39
+ } else if (a.startsWith('--target=') || a.startsWith('--root=')) {
40
+ target = a.split('=')[1];
41
+ } else {
42
+ remaining.push(a);
43
+ }
44
+ }
45
+ if (target === '.' && remaining.length > 0 && !remaining[0].startsWith('-')) {
46
+ target = remaining.shift();
47
+ }
48
+ return { target, remaining };
49
+ }
50
+
51
+ function compareSemver(a, b) {
52
+ const pa = a.replace(/^v/, '').split('.').map(n => parseInt(n, 10) || 0);
53
+ const pb = b.replace(/^v/, '').split('.').map(n => parseInt(n, 10) || 0);
54
+ for (let i = 0; i < 3; i++) {
55
+ const na = pa[i] || 0;
56
+ const nb = pb[i] || 0;
57
+ if (na > nb) return 1;
58
+ if (na < nb) return -1;
59
+ }
60
+ return 0;
61
+ }
62
+
18
63
  // ─── ANSI Color Helpers ───────────────────────────────────────────────────────
19
64
  const BOLD = '\x1b[1m';
20
65
  const DIM = '\x1b[2m';
@@ -169,12 +214,13 @@ function cardHeader(title, subtitle = '', version = 'v1.3.6', borderColor = CYAN
169
214
 
170
215
  function printHelp() {
171
216
  console.log();
172
- console.log(cardHeader('🛡️ T O R U S G U A R D C L I', 'Autonomous Security Engine for AI-Built Applications', 'v1.3.6'));
217
+ console.log(cardHeader('🛡️ T O R U S G U A R D C L I', 'Autonomous Security Engine for AI-Built Applications', 'v1.4.0'));
173
218
  console.log(`\n ${BOLD}Usage:${RESET} ${GREEN}npx torusguard${RESET} ${WHITE}[command]${RESET} ${GRAY}[options]${RESET}\n`);
174
219
 
175
220
  console.log(cardBorderTop('Commands'));
176
221
  console.log(formatBoxLine(`${GREEN}init${RESET} Scaffold ${BOLD}.torusguard/${RESET} workspace + unlock slash commands`));
177
222
  console.log(formatBoxLine(`${GREEN}status${RESET} Display active security posture, memory, rules, & stack`));
223
+ console.log(formatBoxLine(`${GREEN}update${RESET} Check npm registry for updates (--install to auto-upgrade)`));
178
224
  console.log(formatBoxLine(`${GREEN}rules${RESET} Auto-sync memory to AI IDE rules (.cursorrules, CLAUDE.md)`));
179
225
  console.log(formatBoxLine(`${GREEN}memory${RESET} Manage persistent security memory (export, hook, learn)`));
180
226
  console.log(formatBoxLine(`${GREEN}audit${RESET} Run static AST security scan on target project`));
@@ -198,6 +244,7 @@ function printHelp() {
198
244
  console.log(formatBoxLine(`${GRAY}--target <dir>${RESET} Target directory to analyze or scaffold ${DIM}(default: .)${RESET}`));
199
245
  console.log(formatBoxLine(`${GRAY}--force${RESET} Overwrite existing workspace and re-scaffold`));
200
246
  console.log(formatBoxLine(`${GRAY}--yes, -y${RESET} Non-interactive auto-approval for patch application`));
247
+ console.log(formatBoxLine(`${GRAY}--version, -v${RESET} Display TorusGuard package version`));
201
248
  console.log(cardBorderBottom());
202
249
 
203
250
  console.log(`\n ${BOLD}AI Chat Commands:${RESET}`);
@@ -219,7 +266,18 @@ if (command === 'help' || command === '--help' || command === '-h') {
219
266
  }
220
267
 
221
268
  if (command === 'status') {
222
- const cfgPath = path.join(cwd, '.torusguard', 'config', 'torusguard.json');
269
+ const { target, remaining } = parseTargetAndArgs(args);
270
+ const targetDir = path.resolve(cwd, target);
271
+ const statusScript = path.join(targetDir, '.torusguard', 'scripts', 'status_runner.py');
272
+ const fallbackStatusScript = path.join(rootDir, '.torusguard', 'scripts', 'status_runner.py');
273
+ const actualStatusScript = fs.existsSync(statusScript) ? statusScript : fallbackStatusScript;
274
+
275
+ if (fs.existsSync(actualStatusScript)) {
276
+ const proc = spawnSync(pythonCmd, [actualStatusScript, targetDir, ...remaining], { stdio: 'inherit', cwd: targetDir });
277
+ process.exit(proc.status !== null ? proc.status : 0);
278
+ }
279
+
280
+ const cfgPath = path.join(targetDir, '.torusguard', 'config', 'torusguard.json');
223
281
  if (fs.existsSync(cfgPath)) {
224
282
  try {
225
283
  const cfg = JSON.parse(fs.readFileSync(cfgPath, 'utf-8'));
@@ -441,11 +499,13 @@ if (command === 'rules') {
441
499
 
442
500
  // Subcommand: audit
443
501
  if (command === 'audit') {
444
- const auditScript = path.join(cwd, '.torusguard', 'scripts', 'audit_runner.py');
502
+ const { target, remaining } = parseTargetAndArgs(args);
503
+ const targetDir = path.resolve(cwd, target);
504
+ const auditScript = path.join(targetDir, '.torusguard', 'scripts', 'audit_runner.py');
445
505
  const fallbackAuditScript = path.join(rootDir, '.torusguard', 'scripts', 'audit_runner.py');
446
506
  const actualAuditScript = fs.existsSync(fallbackAuditScript) ? fallbackAuditScript : auditScript;
447
507
 
448
- const proc = spawnSync(pythonCmd, [actualAuditScript, ...args.slice(1)], { stdio: 'inherit', cwd });
508
+ const proc = spawnSync(pythonCmd, [actualAuditScript, targetDir, ...remaining], { stdio: 'inherit', cwd: targetDir });
449
509
  process.exit(proc.status !== null ? proc.status : 0);
450
510
  }
451
511
 
@@ -455,7 +515,7 @@ if (command === 'report') {
455
515
  const wantSarif = args.includes('--sarif') || (!wantHtml && args[1] !== 'html');
456
516
 
457
517
  // Resolve target directory (supports --target and --root)
458
- const rootIdx = args.indexOf('--root') !== -1 ? args.indexOf('--root') : args.indexOf('--target');
518
+ const rootIdx = args.indexOf('--root') !== -1 ? args.indexOf('--root') : (args.indexOf('--target') !== -1 ? args.indexOf('--target') : args.indexOf('-t'));
459
519
  let targetRoot = cwd;
460
520
  if (rootIdx !== -1 && args[rootIdx + 1]) {
461
521
  targetRoot = path.resolve(cwd, args[rootIdx + 1]);
@@ -518,69 +578,179 @@ if (command === 'report') {
518
578
 
519
579
  // Subcommand: harden
520
580
  if (command === 'harden') {
521
- const scriptPath = path.join(cwd, '.torusguard', 'scripts', 'harden_runner.py');
581
+ const { target, remaining } = parseTargetAndArgs(args);
582
+ const targetDir = path.resolve(cwd, target);
583
+ const scriptPath = path.join(targetDir, '.torusguard', 'scripts', 'harden_runner.py');
522
584
  const fallbackScript = path.join(rootDir, '.torusguard', 'scripts', 'harden_runner.py');
523
585
  const actualScript = fs.existsSync(fallbackScript) ? fallbackScript : scriptPath;
524
586
 
525
- const proc = spawnSync(pythonCmd, [actualScript, ...args.slice(1)], { stdio: 'inherit', cwd });
587
+ const proc = spawnSync(pythonCmd, [actualScript, targetDir, ...remaining], { stdio: 'inherit', cwd: targetDir });
526
588
  process.exit(proc.status !== null ? proc.status : 0);
527
589
  }
528
590
 
529
591
  // Subcommand: apply
530
592
  if (command === 'apply') {
531
- const scriptPath = path.join(cwd, '.torusguard', 'scripts', 'apply_runner.py');
593
+ const { target, remaining } = parseTargetAndArgs(args);
594
+ const targetDir = path.resolve(cwd, target);
595
+ const scriptPath = path.join(targetDir, '.torusguard', 'scripts', 'apply_runner.py');
532
596
  const fallbackScript = path.join(rootDir, '.torusguard', 'scripts', 'apply_runner.py');
533
597
  const actualScript = fs.existsSync(fallbackScript) ? fallbackScript : scriptPath;
534
598
 
535
- const proc = spawnSync(pythonCmd, [actualScript, ...args.slice(1)], { stdio: 'inherit', cwd });
599
+ const proc = spawnSync(pythonCmd, [actualScript, targetDir, ...remaining], { stdio: 'inherit', cwd: targetDir });
536
600
  process.exit(proc.status !== null ? proc.status : 0);
537
601
  }
538
602
 
539
603
  // Subcommand: rollback
540
604
  if (command === 'rollback') {
541
- const scriptPath = path.join(cwd, '.torusguard', 'scripts', 'apply_runner.py');
605
+ const { target, remaining } = parseTargetAndArgs(args);
606
+ const targetDir = path.resolve(cwd, target);
607
+ const scriptPath = path.join(targetDir, '.torusguard', 'scripts', 'apply_runner.py');
542
608
  const fallbackScript = path.join(rootDir, '.torusguard', 'scripts', 'apply_runner.py');
543
609
  const actualScript = fs.existsSync(fallbackScript) ? fallbackScript : scriptPath;
544
610
 
545
- const proc = spawnSync(pythonCmd, [actualScript, '--rollback', ...args.slice(1)], { stdio: 'inherit', cwd });
611
+ const proc = spawnSync(pythonCmd, [actualScript, targetDir, '--rollback', ...remaining], { stdio: 'inherit', cwd: targetDir });
546
612
  process.exit(proc.status !== null ? proc.status : 0);
547
613
  }
548
614
 
549
615
  // Subcommand: recheck / verify
550
616
  if (command === 'recheck' || command === 'verify') {
551
- const scriptPath = path.join(cwd, '.torusguard', 'scripts', 'recheck_runner.py');
617
+ const { target, remaining } = parseTargetAndArgs(args);
618
+ const targetDir = path.resolve(cwd, target);
619
+ const scriptPath = path.join(targetDir, '.torusguard', 'scripts', 'recheck_runner.py');
552
620
  const fallbackScript = path.join(rootDir, '.torusguard', 'scripts', 'recheck_runner.py');
553
621
  const actualScript = fs.existsSync(fallbackScript) ? fallbackScript : scriptPath;
554
622
 
555
- const proc = spawnSync(pythonCmd, [actualScript, ...args.slice(1)], { stdio: 'inherit', cwd });
623
+ const proc = spawnSync(pythonCmd, [actualScript, targetDir, ...remaining], { stdio: 'inherit', cwd: targetDir });
556
624
  process.exit(proc.status !== null ? proc.status : 0);
557
625
  }
558
626
 
559
627
  // Subcommand: recipes
560
628
  if (command === 'recipes') {
561
- const scriptPath = path.join(cwd, '.torusguard', 'scripts', 'recipes_runner.py');
629
+ const { target, remaining } = parseTargetAndArgs(args);
630
+ const targetDir = path.resolve(cwd, target);
631
+ const scriptPath = path.join(targetDir, '.torusguard', 'scripts', 'recipes_runner.py');
562
632
  const fallbackScript = path.join(rootDir, '.torusguard', 'scripts', 'recipes_runner.py');
563
633
  const actualScript = fs.existsSync(fallbackScript) ? fallbackScript : scriptPath;
564
634
 
565
- const proc = spawnSync(pythonCmd, [actualScript, ...args.slice(1)], { stdio: 'inherit', cwd });
635
+ const proc = spawnSync(pythonCmd, [actualScript, targetDir, ...remaining], { stdio: 'inherit', cwd: targetDir });
566
636
  process.exit(proc.status !== null ? proc.status : 0);
567
637
  }
568
638
 
569
639
  // Subcommand: init (scaffold workspace)
570
640
  if (command === 'init') {
641
+ const { target, remaining } = parseTargetAndArgs(args);
642
+ const targetDir = path.resolve(cwd, target);
571
643
  const localBootstrap = path.join(rootDir, 'skills', 'torusguard', 'bootstrap.py');
572
644
  const localInstall = path.join(rootDir, 'install.py');
573
645
  const scriptToRun = fs.existsSync(localBootstrap) ? localBootstrap : localInstall;
574
646
 
575
- const scriptArgs = [scriptToRun, '--full-commands', ...args.slice(1)];
647
+ const scriptArgs = [scriptToRun, '--full-commands', '--target', targetDir, ...remaining];
576
648
  const proc = spawnSync(pythonCmd, scriptArgs, {
577
649
  stdio: 'inherit',
578
- cwd: cwd,
650
+ cwd: targetDir,
579
651
  });
580
652
  process.exit(proc.status !== null ? proc.status : 0);
581
653
  }
582
654
 
655
+ // Subcommand: update
656
+ if (command === 'update') {
657
+ const https = require('https');
658
+ const pkgJsonPath = path.join(rootDir, 'package.json');
659
+ let currentVersion = '1.4.0';
660
+ try {
661
+ if (fs.existsSync(pkgJsonPath)) {
662
+ currentVersion = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8')).version || currentVersion;
663
+ }
664
+ } catch (e) {}
665
+
666
+ console.log();
667
+ console.log(cardHeader('🛡️ TORUSGUARD UPDATE CHECK', 'Package Distribution & Registry Verifier', `v${currentVersion}`));
668
+ console.log(`\n ${DIM}Checking npm registry for updates...${RESET}`);
669
+
670
+ const autoInstall = args.includes('--install') || args.includes('-i') || args.includes('--yes') || args.includes('-y');
671
+
672
+ function printUpdateOffline(reason) {
673
+ console.log();
674
+ console.log(cardBorderTop('Offline / Registry Unreachable', YELLOW));
675
+ console.log(formatBoxLine(`Current: ${WHITE}v${currentVersion}${RESET}`, 67, '│', YELLOW));
676
+ console.log(formatBoxLine(`Notice: ${DIM}${reason}${RESET}`, 67, '│', YELLOW));
677
+ console.log(formatBoxLine(`Manual: ${BOLD}${CYAN}npm update torusguard${RESET} or ${BOLD}${CYAN}npm i -g torusguard@latest${RESET}`, 67, '│', YELLOW));
678
+ console.log(cardBorderBottom(YELLOW));
679
+ console.log();
680
+ process.exit(0);
681
+ }
682
+
683
+ const req = https.get('https://registry.npmjs.org/torusguard/latest', {
684
+ headers: { 'User-Agent': `torusguard-cli/${currentVersion}` },
685
+ timeout: 6000
686
+ }, (res) => {
687
+ let raw = '';
688
+ res.on('data', chunk => raw += chunk);
689
+ res.on('end', () => {
690
+ try {
691
+ const data = JSON.parse(raw);
692
+ const latestVersion = data.version;
693
+ if (!latestVersion) {
694
+ printUpdateOffline('No version field returned in npm registry response');
695
+ return;
696
+ }
697
+
698
+ const isNewer = compareSemver(latestVersion, currentVersion) > 0;
699
+ console.log();
700
+ console.log(cardBorderTop('Version Telemetry', CYAN));
701
+ console.log(formatBoxLine(`Installed Version: ${WHITE}v${currentVersion}${RESET}`));
702
+ console.log(formatBoxLine(`Latest on NPM: ${BOLD}${GREEN}v${latestVersion}${RESET}`));
703
+ console.log(cardBorderBottom(CYAN));
704
+ console.log();
705
+
706
+ if (isNewer) {
707
+ console.log(cardBorderTop('Update Available', YELLOW, true));
708
+ console.log(formatBoxLine(`${YELLOW}A new version of TorusGuard is available!${RESET}`, 67, '║', YELLOW));
709
+ console.log(formatBoxLine(`Global: ${BOLD}${WHITE}npm install -g torusguard@latest${RESET}`, 67, '║', YELLOW));
710
+ console.log(formatBoxLine(`Local: ${BOLD}${WHITE}npm install torusguard@latest${RESET}`, 67, '║', YELLOW));
711
+ console.log(cardBorderBottom(YELLOW, true));
712
+ console.log();
713
+
714
+ if (autoInstall) {
715
+ console.log(` ${CYAN}Auto-installing latest version via npm...${RESET}`);
716
+ const npmProc = spawnSync('npm', ['install', '-g', 'torusguard@latest'], { stdio: 'inherit' });
717
+ if (npmProc.status === 0) {
718
+ console.log(`\n ${GREEN}✔ Successfully upgraded TorusGuard to v${latestVersion}!${RESET}\n`);
719
+ } else {
720
+ console.error(`\n ${RED}✖ Failed to auto-install update. Run: npm install -g torusguard@latest${RESET}\n`);
721
+ }
722
+ } else {
723
+ console.log(` ${DIM}Tip: Run with ${CYAN}npx torusguard update --install${DIM} to auto-upgrade.${RESET}\n`);
724
+ }
725
+ } else {
726
+ console.log(cardBorderTop('Status: Up To Date', GREEN, true));
727
+ console.log(formatBoxLine(`${GREEN}✔ TorusGuard is up to date (v${currentVersion})${RESET}`, 67, '║', GREEN));
728
+ console.log(cardBorderBottom(GREEN, true));
729
+ console.log();
730
+ }
731
+ process.exit(0);
732
+ } catch (err) {
733
+ printUpdateOffline(err.message);
734
+ }
735
+ });
736
+ });
737
+
738
+ req.on('error', (err) => printUpdateOffline(err.message));
739
+ req.on('timeout', () => {
740
+ req.destroy();
741
+ printUpdateOffline('npm registry request timed out (6000ms)');
742
+ });
743
+ }
744
+
583
745
  // Unknown command fallback
584
- console.error(`\n ${RED}✖ Unknown command:${RESET} ${WHITE}${command}${RESET}`);
585
- console.error(` Run ${GREEN}npx torusguard help${RESET} for available commands.\n`);
586
- process.exit(1);
746
+ const KNOWN_COMMANDS = new Set([
747
+ 'init', 'status', 'rules', 'memory', 'diff-guard', 'audit',
748
+ 'report', 'harden', 'apply', 'rollback', 'recheck', 'verify',
749
+ 'recipes', 'update', 'help', '--help', '-h', '--version', '-v', 'version'
750
+ ]);
751
+
752
+ if (!KNOWN_COMMANDS.has(command)) {
753
+ console.error(`\n ${RED}✖ Unknown command:${RESET} ${WHITE}${command}${RESET}`);
754
+ console.error(` Run ${GREEN}npx torusguard help${RESET} for available commands.\n`);
755
+ process.exit(1);
756
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "torusguard",
3
- "version": "1.3.6",
3
+ "version": "2.0.0-alpha",
4
4
  "description": "Security guardrails, governed remediation, and authorized runtime validation for AI-built web applications.",
5
5
  "main": "bin/torusguard.js",
6
6
  "bin": {
@@ -17,8 +17,12 @@
17
17
  "scripts": {
18
18
  "test": "python harness/runner.py",
19
19
  "init": "node bin/torusguard.js init",
20
+ "status": "node bin/torusguard.js status",
20
21
  "audit": "node bin/torusguard.js audit",
21
- "status": "node bin/torusguard.js status"
22
+ "harden": "node bin/torusguard.js harden",
23
+ "apply": "node bin/torusguard.js apply",
24
+ "recipes": "node bin/torusguard.js recipes",
25
+ "update": "node bin/torusguard.js update"
22
26
  },
23
27
  "keywords": [
24
28
  "security",
@@ -135,7 +135,7 @@ def print_header():
135
135
  print(f"""
136
136
  {CYAN}╭─────────────────────────────────────────────────────────────────────────╮{RESET}
137
137
  {CYAN}│{RESET} {CYAN}│{RESET}
138
- {CYAN}│{RESET} {BOLD}{WHITE}🛡️ T O R U S G U A R D{RESET} {GRAY}v1.3.0{RESET} {CYAN}│{RESET}
138
+ {CYAN}│{RESET} {BOLD}{WHITE}🛡️ T O R U S G U A R D{RESET} {GRAY}v1.4.0{RESET} {CYAN}│{RESET}
139
139
  {CYAN}│{RESET} {DIM}Autonomous Security Engine for AI-Built Applications{RESET} {CYAN}│{RESET}
140
140
  {CYAN}│{RESET} {CYAN}│{RESET}
141
141
  {CYAN}╰─────────────────────────────────────────────────────────────────────────╯{RESET}
@@ -220,7 +220,7 @@ def print_already_initialized(target_root, cfg):
220
220
 
221
221
  {BOLD}▸ Project Root:{RESET} {GREEN}{target_root}{RESET}
222
222
  {BOLD}▸ Workspace:{RESET} {GREEN}.torusguard/{RESET} {DIM}(Already Initialized){RESET}
223
- {BOLD}▸ Version:{RESET} {CYAN}{cfg.get('version', '1.3.0')}{RESET}
223
+ {BOLD}▸ Version:{RESET} {CYAN}{cfg.get('version', '1.4.0')}{RESET}
224
224
  {BOLD}▸ Severity Floor:{RESET} {YELLOW}{cfg.get('severity_threshold', 'medium')}{RESET}
225
225
 
226
226
  {DIM}To refresh templates or re-scaffold, run:{RESET}
@@ -228,7 +228,7 @@ def print_already_initialized(target_root, cfg):
228
228
  """)
229
229
 
230
230
 
231
- def scaffold_workspace(target_root=None, force=False, full_commands=False):
231
+ def scaffold_workspace(target_root=None, force=False, full_commands=False, template=None, run_audit=False):
232
232
  """Scaffold the .torusguard workspace into the target project root."""
233
233
  target_root = Path(target_root or find_project_root()).resolve()
234
234
  torusguard_target = target_root / ".torusguard"
@@ -379,12 +379,26 @@ def scaffold_workspace(target_root=None, force=False, full_commands=False):
379
379
  except Exception:
380
380
  detected_stack = None
381
381
 
382
+ TEMPLATE_MAP = {
383
+ "golang": {"language": "Go", "framework": "Gin/Fiber", "data_layer": "database/sql"},
384
+ "go": {"language": "Go", "framework": "Gin/Fiber", "data_layer": "database/sql"},
385
+ "nextjs": {"language": "TypeScript", "framework": "Next.js", "data_layer": "Prisma ORM"},
386
+ "fastapi": {"language": "Python", "framework": "FastAPI", "data_layer": "SQLAlchemy"},
387
+ "express": {"language": "JavaScript", "framework": "Express", "data_layer": "Mongoose"},
388
+ "django": {"language": "Python", "framework": "Django", "data_layer": "Django ORM"},
389
+ "react": {"language": "JavaScript/TypeScript", "framework": "React / Vite", "data_layer": "Supabase"}
390
+ }
391
+ if template and template.lower() in TEMPLATE_MAP:
392
+ detected_stack = TEMPLATE_MAP[template.lower()]
393
+
382
394
  config_file = torusguard_target / "config" / "torusguard.json"
383
395
  if config_file.exists():
384
396
  try:
385
397
  with open(config_file, "r", encoding="utf-8") as f:
386
398
  cfg = json.load(f)
387
- if detected_stack and detected_stack.get("framework") != "None":
399
+ if template and template.lower() in TEMPLATE_MAP:
400
+ cfg["detected_stack"] = TEMPLATE_MAP[template.lower()]
401
+ elif detected_stack and detected_stack.get("framework") != "None":
388
402
  cfg["detected_stack"] = {
389
403
  "language": detected_stack.get("language"),
390
404
  "framework": detected_stack.get("framework"),
@@ -516,15 +530,40 @@ Parse the requested action from `$ARGUMENTS` (e.g. `audit`, `verify`, `web-valid
516
530
 
517
531
  # ── Success Card ────────────────────────────────────────────────────────
518
532
  print_success_card()
533
+
534
+ # ── Optional Immediate Audit ────────────────────────────────────────────
535
+ if run_audit:
536
+ audit_script = torusguard_target / "scripts" / "audit_runner.py"
537
+ if audit_script.is_file():
538
+ print(f"\n {CYAN}▸ Running immediate baseline security audit (--audit)...{RESET}\n")
539
+ try:
540
+ import importlib.util
541
+ spec = importlib.util.spec_from_file_location("audit_runner", str(audit_script))
542
+ if spec and spec.loader:
543
+ ar_mod = importlib.util.module_from_spec(spec)
544
+ spec.loader.exec_module(ar_mod)
545
+ if hasattr(ar_mod, "execute_audit"):
546
+ ar_mod.execute_audit(target_root)
547
+ except Exception as e:
548
+ print(f" {YELLOW}⚠ Immediate audit notice: {e}{RESET}")
549
+
519
550
  return True
520
551
 
521
552
 
522
553
  if __name__ == "__main__":
523
554
  parser = argparse.ArgumentParser(description="TorusGuard Autonomous Workspace Bootstrapper")
524
- parser.add_argument("--target", type=str, help="Target project root directory")
555
+ parser.add_argument("--target", "-t", type=str, help="Target project root directory")
525
556
  parser.add_argument("--force", action="store_true", help="Force overwrite existing workspace")
526
557
  parser.add_argument("--full-commands", action="store_true", help="Unlock and register all 11 individual slash commands")
558
+ parser.add_argument("--template", choices=["golang", "go", "nextjs", "fastapi", "express", "django", "react"], help="Pre-configure target framework stack template")
559
+ parser.add_argument("--audit", action="store_true", help="Execute immediate baseline audit post-initialization")
527
560
  args = parser.parse_args()
528
561
 
529
- success = scaffold_workspace(target_root=args.target, force=args.force, full_commands=args.full_commands)
562
+ success = scaffold_workspace(
563
+ target_root=args.target,
564
+ force=args.force,
565
+ full_commands=args.full_commands,
566
+ template=args.template,
567
+ run_audit=args.audit
568
+ )
530
569
  sys.exit(0 if success else 1)
@@ -142,23 +142,24 @@
142
142
  "schemas/remediation.schema.json": "544904239f871dec9552973e01e09dc1f40dbb8330f20d98c319f3b24031d630",
143
143
  "schemas/retest.schema.json": "97c0407ca4365a524020c430912f686f698cc0de90043194621071e9fc681cc7",
144
144
  "schemas/runtime-evidence.schema.json": "929d2b094c1cd1f7f9db07be1eba5994e8002477eab3fd24140e1e973fd18cc1",
145
- "scripts/apply_runner.py": "f9c5374ea213b77069293e45ed3d878d7f3f0e31497c55bc97885efc14bfa57c",
146
- "scripts/audit_runner.py": "98a3975ff79f8ffb0343d5606dd84a603fd35d741e2def6d70f83bc1ee8f01ff",
145
+ "scripts/apply_runner.py": "b145a68a4bc10fcacb853f972aee81fa3607e32d282b2b850c5a63d8e72da890",
146
+ "scripts/audit_runner.py": "bc1e06ea5153ae326c4ad1de5d0cbb9503e618186623bea7cb8bb64d7b7b05ec",
147
147
  "scripts/diff_guard.py": "0dc178cdde1ac0ae1a1ea4b2eb2ce1756b2126f6156909cf55d85249f115fcbd",
148
148
  "scripts/finding_scorer.py": "a5315be6ee256c01c4539da3d1905ebc8d0840a356b83c55f9f6f2654a9f0c60",
149
- "scripts/harden_runner.py": "f6f6922f2ade98b40f3de3e211459c62483e8aa274cbe4515dbd0d308956e6b4",
150
- "scripts/html_reporter.py": "e9901a1dbeddd7b1dccd04afc9005d64954ccc1f14ba6ec4bdb4aa0ea8c2c66c",
151
- "scripts/manifest_builder.py": "c0137927789a9e40a08243e630ac3c6990beb1b87807934e98906c8ad0b99a97",
149
+ "scripts/harden_runner.py": "5d5a40029c088ccb66790a9b0128bdefcd35883ef1dac78088ceb9531392a8f1",
150
+ "scripts/html_reporter.py": "655c57be39e13c177db8842ef471664e5853f3e43b9f2a63e590df40ff9c16cb",
151
+ "scripts/manifest_builder.py": "18db6979b341a87e9bf38fe06525365d12b07d532c0dbfd2ac3ef0f539dc1f6f",
152
152
  "scripts/memory_engine.py": "b715d0ca030e95eb06ad6eda99027535df8a7e37d64897c023be6a291cf13dc6",
153
153
  "scripts/monorepo_detector.py": "5603674136a5294ebfff89efeca0a546dd4a7deb1d184a2592ff21aff2131f73",
154
- "scripts/recheck_runner.py": "dd6f35c98f6fd3d41d641bca419bb90739551c4900724a65447882b6d7dd4f54",
155
- "scripts/recipes_runner.py": "6e057860e7d0e3b612a5b444b577255c9b7009b5dce0352098ab7d6c8c6659e7",
156
- "scripts/report_sync.py": "c5f37c69e2e074c8ffd5953811907cf7c95e4c56f406ea16f3b5b9d878cfb774",
154
+ "scripts/recheck_runner.py": "89e93fcc6843493d7e5f0bf97065dbdb40106273a00e07f903250665ca25f6fb",
155
+ "scripts/recipes_runner.py": "090c06ef0de3c640a111c5646837233ceeaca494b161bd5edc630cc1371dca0e",
156
+ "scripts/report_sync.py": "5ebef684690200694a53af30db850d9808d03ec710ed21ef75c4de52b5e5217c",
157
157
  "scripts/rules_sync.py": "4101b2ca8036ff4f468800b32a8d08898e8640a74d14124af53d454706a62d3a",
158
158
  "scripts/run_manager.py": "b738ff70879e46547d32fac6befc61de9599f676411384280fb9819ea3ad7035",
159
159
  "scripts/safety_gate.py": "3379b7534b2590cf563717a448983ad8ed7e8f174f0ad65683d33e8a10f51558",
160
160
  "scripts/sarif_exporter.py": "86700765212adb3ab590ca72614bf3ad4ce7ce60e3193f7f3bd1a04d34d10f6e",
161
161
  "scripts/stack_detect.py": "c05a1ade4c8692025476bf7ea080a8f07c92e5d8e9a04f94c1654386352ffbdc",
162
+ "scripts/status_runner.py": "4c358c91950c7874bcc6a5f23f2d3fda62b0752efcf6c6b658adf02ed77c7752",
162
163
  "scripts/term_ui.py": "ca69398f85c86fe89526d6334b3ee866c890273997351113c3cc1765b7bd20c3",
163
164
  "skills/torusguard/SKILL.md": "4d5b8e43fa3c09e5e1079cbc3e2184654219a2c47b2272db394da749969318f8",
164
165
  "skills/torusguard/bootstrap.py": "3d946f388cb4befa739c9d3b1404255d9a8ea5770ebbb79e5a1b9839589e9bc7",
@@ -206,16 +207,30 @@
206
207
  "templates/authorization.template.md": "81ef843d42a19412c369f383b787465ac24173c0b14c1f5f211786eab3d10e8b",
207
208
  "templates/finding-card.template.md": "8f756edbd3e4139d3da2fb96f35bd2d2b267b33b754f187b590a89584265c1e6",
208
209
  "templates/remediation-bundle.template.md": "4d85a540e3a2e74f9b21fc8a2a1072e27ca03e97cd67ca482f529cfe722acc4d",
209
- "workflows/apply.md": "8dd37fecc44e2820e82c29e2c6b2970936734ed5102d36950889a9eb8b19dbab",
210
- "workflows/audit.md": "7e78ebb885176d65e86ed45a90a4326b942d484c2b5c8bff1d7bda141790de2f",
210
+ "workflows/apply.md": "67e1002fc6e9d68e0c7d871c40b6f3c3b9c3919c8e02106a579882729c0f6b9f",
211
+ "workflows/audit.md": "eac9102ca88d53f71da474cd55717d431fd9c3b08c66d0760da9b53a659cf89a",
211
212
  "workflows/authorize.md": "28ca58cfc656e956f7cec8160f2aadc152abcde3eb5ad5588df149007afb0df8",
212
213
  "workflows/exploit-check.md": "41e77afe912be9266c5bc1e00fd796baff22a67973eb6e86d196d34f4d7bdfa4",
213
- "workflows/harden.md": "24c62ea0233bf5cb21308497869790fa6f24b6cbb563fd2ebf858ff02b09bba9",
214
- "workflows/init.md": "9a9aeaff6bd2217323ad72fb4043f46057deaa45eb3380f679d9aef3d36bfc8b",
214
+ "workflows/harden.md": "7d92132973ff867b99e0425e3aee3c4e91868cb5193ec601069af2e857b6697f",
215
+ "workflows/init.md": "611418577ff9d5719df459f56b3fa53b91eb3717b02c4b4e5e86ed483bed3bfa",
215
216
  "workflows/memory.md": "8ad2ec154176e2540c2859a28eff9f7c2dbca0217aa29d0f4aa88b87c43f8bef",
216
217
  "workflows/recheck.md": "42eecc3ba194564d48a6a88d8003e86cafe003503e887dc565314d4aa558e8fd",
217
- "workflows/report.md": "b98652ee0552b7bb73eeb78dc80d2b0a108cc505523cbd1b3ada6064409e4629",
218
- "workflows/status.md": "dfbc2b75ba45ff70b60522addca4032a667241364b0907cd77a43bf9271dfa56",
218
+ "workflows/recipes.md": "300c1fed0167e1a299fcd33c07db05630116b18a71ec2513c385862bba0f179b",
219
+ "workflows/report.md": "ecbd67bfa95bde3c0f51e06aac6fad70d5989b0be82245116cd7ba367f378a4c",
220
+ "workflows/status.md": "7f07e726bbb0488e48b718c2f36971634b1422bc2ddfbb381eb3e1ea67c1cfbf",
221
+ "workflows/torusguard-apply.md": "67e1002fc6e9d68e0c7d871c40b6f3c3b9c3919c8e02106a579882729c0f6b9f",
222
+ "workflows/torusguard-audit.md": "eac9102ca88d53f71da474cd55717d431fd9c3b08c66d0760da9b53a659cf89a",
223
+ "workflows/torusguard-authorize.md": "28ca58cfc656e956f7cec8160f2aadc152abcde3eb5ad5588df149007afb0df8",
224
+ "workflows/torusguard-exploit-check.md": "41e77afe912be9266c5bc1e00fd796baff22a67973eb6e86d196d34f4d7bdfa4",
225
+ "workflows/torusguard-harden.md": "7d92132973ff867b99e0425e3aee3c4e91868cb5193ec601069af2e857b6697f",
226
+ "workflows/torusguard-init.md": "611418577ff9d5719df459f56b3fa53b91eb3717b02c4b4e5e86ed483bed3bfa",
227
+ "workflows/torusguard-recheck.md": "42eecc3ba194564d48a6a88d8003e86cafe003503e887dc565314d4aa558e8fd",
228
+ "workflows/torusguard-recipes.md": "300c1fed0167e1a299fcd33c07db05630116b18a71ec2513c385862bba0f179b",
229
+ "workflows/torusguard-report.md": "ecbd67bfa95bde3c0f51e06aac6fad70d5989b0be82245116cd7ba367f378a4c",
230
+ "workflows/torusguard-status.md": "7f07e726bbb0488e48b718c2f36971634b1422bc2ddfbb381eb3e1ea67c1cfbf",
231
+ "workflows/torusguard-verify.md": "6412e123a9346240e5ba898a0da73d3409d9a215d6e8f202ab2eb5719b663731",
232
+ "workflows/torusguard-web-validate.md": "3b2a3d02b69469539b4a48ed3bd355362927cc21470dbcdeccba564a9e68a371",
233
+ "workflows/torusguard.md": "4b5da6d38dae6be277bd52782121cdb181a75f1400068041310ca69deae89589",
219
234
  "workflows/verify.md": "6412e123a9346240e5ba898a0da73d3409d9a215d6e8f202ab2eb5719b663731",
220
235
  "workflows/web-validate.md": "3b2a3d02b69469539b4a48ed3bd355362927cc21470dbcdeccba564a9e68a371"
221
236
  }