torusguard 1.3.4 → 1.3.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.
Files changed (319) hide show
  1. package/.torusguard/.manifest.json +66 -63
  2. package/.torusguard/rules/business-logic/TG-BIZ-001-client-controlled-sensitive-business-value.md +30 -14
  3. package/.torusguard/rules/business-logic/TG-BIZ-002-replayable-one-time-operation.md +33 -16
  4. package/.torusguard/rules/business-logic/TG-BIZ-003-missing-workflow-state-validation.md +31 -15
  5. package/.torusguard/rules/business-logic/TG-BIZ-004-unrestricted-sensitive-business-flow.md +26 -16
  6. package/.torusguard/rules/cache/TG-CACHE-001-sensitive-response-publicly-cacheable.md +24 -16
  7. package/.torusguard/rules/cache/TG-CACHE-002-missing-user-cache-isolation.md +32 -18
  8. package/.torusguard/rules/cache/TG-CACHE-003-sensitive-data-in-url.md +24 -17
  9. package/.torusguard/rules/csrf/TG-CSRF-001-missing-csrf-protection.md +31 -18
  10. package/.torusguard/rules/csrf/TG-CSRF-002-unsafe-credentialed-cross-origin-request.md +28 -17
  11. package/.torusguard/rules/graphql/TG-GQL-002-resolver-missing-authorization.md +33 -17
  12. package/.torusguard/rules/graphql/TG-GQL-003-unbounded-graphql-pagination-or-batching.md +31 -16
  13. package/.torusguard/rules/graphql/TG-GQL-004-unnecessary-production-introspection.md +25 -16
  14. package/.torusguard/rules/secrets/TG-SEC-005-secret-in-git-history.md +24 -19
  15. package/.torusguard/rules/secrets/TG-SEC-006-secret-in-build-artifact.md +36 -19
  16. package/.torusguard/rules/secrets/TG-SEC-007-secret-in-test-or-example-fixture.md +21 -16
  17. package/.torusguard/rules/ssrf/TG-SSRF-002-missing-internal-network-protection.md +45 -18
  18. package/.torusguard/rules/ssrf/TG-SSRF-003-unsafe-redirect-following.md +20 -16
  19. package/.torusguard/rules/ssrf/TG-SSRF-004-unbounded-outbound-request.md +28 -19
  20. package/.torusguard/rules/supply-chain/TG-SUPPLY-001-missing-or-ignored-dependency-lockfile.md +25 -18
  21. package/.torusguard/rules/supply-chain/TG-SUPPLY-003-unsafe-ci-cd-secret-exposure.md +29 -19
  22. package/.torusguard/rules/supply-chain/TG-SUPPLY-004-unpinned-ci-action.md +23 -18
  23. package/.torusguard/rules/supply-chain/TG-SUPPLY-005-unsafe-dependency-install-script.md +23 -18
  24. package/.torusguard/rules/webhook/TG-WEBHOOK-001-missing-webhook-signature-verification.md +36 -16
  25. package/.torusguard/rules/webhook/TG-WEBHOOK-002-replayable-webhook.md +26 -17
  26. package/.torusguard/rules/webhook/TG-WEBHOOK-003-missing-webhook-idempotency.md +30 -16
  27. package/.torusguard/rules/webhook/TG-WEBHOOK-004-unvalidated-webhook-event-type.md +25 -16
  28. package/.torusguard/rules/websocket/TG-WS-002-missing-channel-level-authorization.md +28 -17
  29. package/.torusguard/rules/websocket/TG-WS-003-unvalidated-websocket-message.md +31 -17
  30. package/.torusguard/rules/websocket/TG-WS-004-unbounded-websocket-connections.md +31 -17
  31. package/.torusguard/rules_catalog.json +520 -0
  32. package/.torusguard/runs/report-latest.html +2700 -232
  33. package/.torusguard/runs/results-latest.sarif +20 -0
  34. package/.torusguard/runs/run-20260912-214110-audit/findings.json +1256 -0
  35. package/.torusguard/runs/run-20260912-214110-audit/findings.md +534 -0
  36. package/.torusguard/runs/run-20260912-214110-audit/manifest.json +12 -0
  37. package/.torusguard/runs/run-20260912-214110-audit/summary.md +5 -0
  38. package/.torusguard/runs/run-20260912-214813-audit/findings.json +992 -0
  39. package/.torusguard/runs/run-20260912-214813-audit/findings.md +422 -0
  40. package/.torusguard/runs/run-20260912-214813-audit/manifest.json +12 -0
  41. package/.torusguard/runs/run-20260912-214813-audit/summary.md +5 -0
  42. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-auth-003-49-7c96f3/metadata.json +17 -0
  43. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-auth-003-49-7c96f3/minimal_patch_plan.md +21 -0
  44. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-auth-003-49-7c96f3/patch.diff +9 -0
  45. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-input-003-53-d167b4/metadata.json +17 -0
  46. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-input-003-53-d167b4/minimal_patch_plan.md +21 -0
  47. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-input-003-53-d167b4/patch.diff +9 -0
  48. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-platform-001-12-cf8156/metadata.json +17 -0
  49. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-platform-001-12-cf8156/minimal_patch_plan.md +21 -0
  50. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-platform-001-12-cf8156/patch.diff +9 -0
  51. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-rate-001-26-affcfa/metadata.json +17 -0
  52. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-rate-001-26-affcfa/minimal_patch_plan.md +21 -0
  53. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-rate-001-26-affcfa/patch.diff +9 -0
  54. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-sec-001-9-e22e50/metadata.json +17 -0
  55. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-sec-001-9-e22e50/minimal_patch_plan.md +21 -0
  56. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-sec-001-9-e22e50/patch.diff +9 -0
  57. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-ssrf-004-9-9803ad/metadata.json +17 -0
  58. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-ssrf-004-9-9803ad/minimal_patch_plan.md +21 -0
  59. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-ssrf-004-9-9803ad/patch.diff +9 -0
  60. package/.torusguard/runs/run-20260912-215555-audit/findings.json +530 -0
  61. package/.torusguard/runs/run-20260912-215555-audit/findings.md +232 -0
  62. package/.torusguard/runs/run-20260912-215555-audit/manifest.json +13 -0
  63. package/.torusguard/runs/run-20260912-215555-audit/remediation.md +102 -0
  64. package/.torusguard/runs/run-20260912-215555-audit/summary.md +5 -0
  65. package/.torusguard/runs/run-20260912-215731-audit/apply_plan.md +6 -0
  66. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-client-001-7-587129/metadata.json +17 -0
  67. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-client-001-7-587129/minimal_patch_plan.md +21 -0
  68. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-client-001-7-587129/patch.diff +9 -0
  69. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-db-002-9-5f7850/metadata.json +17 -0
  70. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-db-002-9-5f7850/minimal_patch_plan.md +21 -0
  71. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-db-002-9-5f7850/patch.diff +9 -0
  72. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-001-27-2486f1/metadata.json +17 -0
  73. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-001-27-2486f1/minimal_patch_plan.md +22 -0
  74. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-001-27-2486f1/patch.diff +10 -0
  75. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-003-53-d167b4/metadata.json +17 -0
  76. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-003-53-d167b4/minimal_patch_plan.md +21 -0
  77. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-003-53-d167b4/patch.diff +9 -0
  78. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-001-12-cf8156/metadata.json +17 -0
  79. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-001-12-cf8156/minimal_patch_plan.md +21 -0
  80. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-001-12-cf8156/patch.diff +9 -0
  81. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-17-876973/metadata.json +17 -0
  82. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-17-876973/minimal_patch_plan.md +23 -0
  83. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-17-876973/patch.diff +11 -0
  84. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-5-40c794/metadata.json +17 -0
  85. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-5-40c794/minimal_patch_plan.md +23 -0
  86. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-5-40c794/patch.diff +11 -0
  87. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-001-26-affcfa/metadata.json +17 -0
  88. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-001-26-affcfa/minimal_patch_plan.md +21 -0
  89. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-001-26-affcfa/patch.diff +9 -0
  90. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-002-54-0b38d2/metadata.json +17 -0
  91. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-002-54-0b38d2/minimal_patch_plan.md +21 -0
  92. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-002-54-0b38d2/patch.diff +9 -0
  93. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-18-a3c1e8/metadata.json +17 -0
  94. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-18-a3c1e8/minimal_patch_plan.md +21 -0
  95. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-18-a3c1e8/patch.diff +9 -0
  96. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-9-e22e50/metadata.json +17 -0
  97. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-9-e22e50/minimal_patch_plan.md +21 -0
  98. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-9-e22e50/patch.diff +9 -0
  99. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-28-a1a0a1/metadata.json +17 -0
  100. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-28-a1a0a1/minimal_patch_plan.md +21 -0
  101. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-28-a1a0a1/patch.diff +9 -0
  102. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-30-00569e/metadata.json +17 -0
  103. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-30-00569e/minimal_patch_plan.md +21 -0
  104. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-30-00569e/patch.diff +9 -0
  105. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-ssrf-004-9-9803ad/metadata.json +17 -0
  106. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-ssrf-004-9-9803ad/minimal_patch_plan.md +21 -0
  107. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-ssrf-004-9-9803ad/patch.diff +9 -0
  108. package/.torusguard/runs/run-20260912-215731-audit/diff_summary.md +186 -0
  109. package/.torusguard/runs/run-20260912-215731-audit/findings.json +497 -0
  110. package/.torusguard/runs/run-20260912-215731-audit/findings.md +218 -0
  111. package/.torusguard/runs/run-20260912-215731-audit/manifest.json +14 -0
  112. package/.torusguard/runs/run-20260912-215731-audit/recheck.md +76 -0
  113. package/.torusguard/runs/run-20260912-215731-audit/remediation.md +234 -0
  114. package/.torusguard/runs/run-20260912-215731-audit/summary.md +5 -0
  115. package/.torusguard/runs/run-20260912-220134-audit/findings.json +68 -0
  116. package/.torusguard/runs/run-20260912-220134-audit/findings.md +36 -0
  117. package/.torusguard/runs/run-20260912-220134-audit/manifest.json +12 -0
  118. package/.torusguard/runs/run-20260912-220134-audit/summary.md +5 -0
  119. package/.torusguard/runs/run-20260912-220200-audit/findings.json +1 -0
  120. package/.torusguard/runs/run-20260912-220200-audit/findings.md +8 -0
  121. package/.torusguard/runs/run-20260912-220200-audit/manifest.json +12 -0
  122. package/.torusguard/runs/run-20260912-220200-audit/recheck.md +6 -0
  123. package/.torusguard/runs/run-20260912-220200-audit/summary.md +5 -0
  124. package/.torusguard/runs/run-20260912-220227-audit/findings.json +1 -0
  125. package/.torusguard/runs/run-20260912-220227-audit/findings.md +8 -0
  126. package/.torusguard/runs/run-20260912-220227-audit/manifest.json +12 -0
  127. package/.torusguard/runs/run-20260912-220227-audit/recheck.md +6 -0
  128. package/.torusguard/runs/run-20260912-220227-audit/summary.md +5 -0
  129. package/.torusguard/runs/run-20260918-104221-audit/findings.json +1 -0
  130. package/.torusguard/runs/run-20260918-104221-audit/findings.md +8 -0
  131. package/.torusguard/runs/run-20260918-104221-audit/manifest.json +12 -0
  132. package/.torusguard/runs/run-20260918-104221-audit/summary.md +5 -0
  133. package/.torusguard/runs/run-20260918-104236-audit/findings.json +2314 -0
  134. package/.torusguard/runs/run-20260918-104236-audit/findings.md +960 -0
  135. package/.torusguard/runs/run-20260918-104236-audit/manifest.json +12 -0
  136. package/.torusguard/runs/run-20260918-104236-audit/summary.md +5 -0
  137. package/.torusguard/runs/run-20260918-105723-audit/findings.json +2382 -0
  138. package/.torusguard/runs/run-20260918-105723-audit/findings.md +960 -0
  139. package/.torusguard/runs/run-20260918-105723-audit/manifest.json +12 -0
  140. package/.torusguard/runs/run-20260918-105723-audit/summary.md +5 -0
  141. package/.torusguard/runs/run-20260918-105731-audit/findings.json +1 -0
  142. package/.torusguard/runs/run-20260918-105731-audit/findings.md +8 -0
  143. package/.torusguard/runs/run-20260918-105731-audit/manifest.json +12 -0
  144. package/.torusguard/runs/run-20260918-105731-audit/summary.md +5 -0
  145. package/.torusguard/runs/run-20260918-105940-audit/findings.json +1 -0
  146. package/.torusguard/runs/run-20260918-105940-audit/findings.md +8 -0
  147. package/.torusguard/runs/run-20260918-105940-audit/manifest.json +12 -0
  148. package/.torusguard/runs/run-20260918-105940-audit/summary.md +5 -0
  149. package/.torusguard/scripts/__pycache__/apply_runner.cpython-314.pyc +0 -0
  150. package/.torusguard/scripts/__pycache__/audit_runner.cpython-311.pyc +0 -0
  151. package/.torusguard/scripts/__pycache__/audit_runner.cpython-314.pyc +0 -0
  152. package/.torusguard/scripts/__pycache__/diff_guard.cpython-314.pyc +0 -0
  153. package/.torusguard/scripts/__pycache__/finding_scorer.cpython-311.pyc +0 -0
  154. package/.torusguard/scripts/__pycache__/finding_scorer.cpython-314.pyc +0 -0
  155. package/.torusguard/scripts/__pycache__/harden_runner.cpython-314.pyc +0 -0
  156. package/.torusguard/scripts/__pycache__/html_reporter.cpython-314.pyc +0 -0
  157. package/.torusguard/scripts/__pycache__/manifest_builder.cpython-314.pyc +0 -0
  158. package/.torusguard/scripts/__pycache__/memory_engine.cpython-314.pyc +0 -0
  159. package/.torusguard/scripts/__pycache__/monorepo_detector.cpython-314.pyc +0 -0
  160. package/.torusguard/scripts/__pycache__/recheck_runner.cpython-314.pyc +0 -0
  161. package/.torusguard/scripts/__pycache__/report_sync.cpython-311.pyc +0 -0
  162. package/.torusguard/scripts/__pycache__/report_sync.cpython-314.pyc +0 -0
  163. package/.torusguard/scripts/__pycache__/run_manager.cpython-314.pyc +0 -0
  164. package/.torusguard/scripts/__pycache__/sarif_exporter.cpython-314.pyc +0 -0
  165. package/.torusguard/scripts/__pycache__/stack_detect.cpython-314.pyc +0 -0
  166. package/.torusguard/scripts/__pycache__/term_ui.cpython-311.pyc +0 -0
  167. package/.torusguard/scripts/__pycache__/term_ui.cpython-314.pyc +0 -0
  168. package/.torusguard/scripts/apply_runner.py +389 -377
  169. package/.torusguard/scripts/audit_runner.py +1513 -653
  170. package/.torusguard/scripts/finding_scorer.py +14 -2
  171. package/.torusguard/scripts/harden_runner.py +628 -455
  172. package/.torusguard/scripts/html_reporter.py +2668 -648
  173. package/.torusguard/scripts/recheck_runner.py +248 -238
  174. package/.torusguard/scripts/recipes_runner.py +137 -137
  175. package/.torusguard/scripts/report_sync.py +719 -0
  176. package/.torusguard/scripts/sarif_exporter.py +156 -116
  177. package/.torusguard/scripts/stack_detect.py +44 -2
  178. package/.torusguard/scripts/term_ui.py +162 -162
  179. package/.torusguard/skills/torusguard/SKILL.md +75 -72
  180. package/.torusguard/skills/torusguard-apply/SKILL.md +84 -80
  181. package/.torusguard/skills/torusguard-audit/SKILL.md +87 -83
  182. package/.torusguard/skills/torusguard-authorize/SKILL.md +7 -2
  183. package/.torusguard/skills/torusguard-exploit-check/SKILL.md +7 -2
  184. package/.torusguard/skills/torusguard-full/SKILL.md +7 -2
  185. package/.torusguard/skills/torusguard-harden/SKILL.md +98 -94
  186. package/.torusguard/skills/torusguard-init/SKILL.md +68 -64
  187. package/.torusguard/skills/torusguard-recheck/SKILL.md +81 -77
  188. package/.torusguard/skills/torusguard-report/SKILL.md +93 -72
  189. package/.torusguard/skills/torusguard-status/SKILL.md +62 -58
  190. package/.torusguard/skills/torusguard-verify/SKILL.md +7 -2
  191. package/.torusguard/skills/torusguard-web-validate/SKILL.md +7 -2
  192. package/.torusguard/snapshots/run-20260912-215731-audit/demo/playground/vulnerable_nextjs/actions.ts.bak +24 -0
  193. package/.torusguard/snapshots/run-20260912-215731-audit/examples/hardened-react-express/server/index.js.bak +121 -0
  194. package/.torusguard/snapshots/run-20260912-215731-audit/examples/python/fastapi-vuln/main.py.bak +20 -0
  195. package/.torusguard/snapshots/run-20260912-215731-audit/examples/vulnerable-react-express/client/src/App.jsx.bak +63 -0
  196. package/.torusguard/snapshots/run-20260912-215731-audit/examples/vulnerable-react-express/client/vite.config.js.bak +12 -0
  197. package/.torusguard/snapshots/run-20260912-215731-audit/examples/vulnerable-react-express/server/index.js.bak +82 -0
  198. package/.torusguard/workflows/apply.md +11 -4
  199. package/.torusguard/workflows/audit.md +7 -1
  200. package/.torusguard/workflows/authorize.md +2 -1
  201. package/.torusguard/workflows/exploit-check.md +2 -1
  202. package/.torusguard/workflows/harden.md +7 -1
  203. package/.torusguard/workflows/init.md +6 -1
  204. package/.torusguard/workflows/memory.md +2 -1
  205. package/.torusguard/workflows/recheck.md +7 -1
  206. package/.torusguard/workflows/report.md +7 -1
  207. package/.torusguard/workflows/status.md +6 -1
  208. package/.torusguard/workflows/verify.md +6 -1
  209. package/.torusguard/workflows/web-validate.md +2 -1
  210. package/README.md +476 -345
  211. package/bin/torusguard.js +586 -545
  212. package/package.json +1 -1
  213. package/skills/torusguard/SKILL.md +73 -72
  214. package/skills/torusguard/bootstrap.py +7 -2
  215. package/skills/torusguard/payload/.manifest.json +66 -63
  216. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-001-client-controlled-sensitive-business-value.md +30 -14
  217. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-002-replayable-one-time-operation.md +33 -16
  218. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-003-missing-workflow-state-validation.md +31 -15
  219. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-004-unrestricted-sensitive-business-flow.md +26 -16
  220. package/skills/torusguard/payload/rules/cache/TG-CACHE-001-sensitive-response-publicly-cacheable.md +24 -16
  221. package/skills/torusguard/payload/rules/cache/TG-CACHE-002-missing-user-cache-isolation.md +32 -18
  222. package/skills/torusguard/payload/rules/cache/TG-CACHE-003-sensitive-data-in-url.md +24 -17
  223. package/skills/torusguard/payload/rules/csrf/TG-CSRF-001-missing-csrf-protection.md +31 -18
  224. package/skills/torusguard/payload/rules/csrf/TG-CSRF-002-unsafe-credentialed-cross-origin-request.md +28 -17
  225. package/skills/torusguard/payload/rules/graphql/TG-GQL-002-resolver-missing-authorization.md +33 -17
  226. package/skills/torusguard/payload/rules/graphql/TG-GQL-003-unbounded-graphql-pagination-or-batching.md +31 -16
  227. package/skills/torusguard/payload/rules/graphql/TG-GQL-004-unnecessary-production-introspection.md +25 -16
  228. package/skills/torusguard/payload/rules/secrets/TG-SEC-005-secret-in-git-history.md +24 -19
  229. package/skills/torusguard/payload/rules/secrets/TG-SEC-006-secret-in-build-artifact.md +36 -19
  230. package/skills/torusguard/payload/rules/secrets/TG-SEC-007-secret-in-test-or-example-fixture.md +21 -16
  231. package/skills/torusguard/payload/rules/ssrf/TG-SSRF-002-missing-internal-network-protection.md +45 -18
  232. package/skills/torusguard/payload/rules/ssrf/TG-SSRF-003-unsafe-redirect-following.md +20 -16
  233. package/skills/torusguard/payload/rules/ssrf/TG-SSRF-004-unbounded-outbound-request.md +28 -19
  234. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-001-missing-or-ignored-dependency-lockfile.md +25 -18
  235. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-003-unsafe-ci-cd-secret-exposure.md +29 -19
  236. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-004-unpinned-ci-action.md +23 -18
  237. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-005-unsafe-dependency-install-script.md +23 -18
  238. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-001-missing-webhook-signature-verification.md +36 -16
  239. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-002-replayable-webhook.md +26 -17
  240. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-003-missing-webhook-idempotency.md +30 -16
  241. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-004-unvalidated-webhook-event-type.md +25 -16
  242. package/skills/torusguard/payload/rules/websocket/TG-WS-002-missing-channel-level-authorization.md +28 -17
  243. package/skills/torusguard/payload/rules/websocket/TG-WS-003-unvalidated-websocket-message.md +31 -17
  244. package/skills/torusguard/payload/rules/websocket/TG-WS-004-unbounded-websocket-connections.md +31 -17
  245. package/skills/torusguard/payload/rules_catalog.json +520 -0
  246. package/skills/torusguard/payload/scripts/__pycache__/apply_runner.cpython-314.pyc +0 -0
  247. package/skills/torusguard/payload/scripts/__pycache__/audit_runner.cpython-311.pyc +0 -0
  248. package/skills/torusguard/payload/scripts/__pycache__/audit_runner.cpython-314.pyc +0 -0
  249. package/skills/torusguard/payload/scripts/__pycache__/diff_guard.cpython-311.pyc +0 -0
  250. package/skills/torusguard/payload/scripts/__pycache__/diff_guard.cpython-314.pyc +0 -0
  251. package/skills/torusguard/payload/scripts/__pycache__/finding_scorer.cpython-311.pyc +0 -0
  252. package/skills/torusguard/payload/scripts/__pycache__/finding_scorer.cpython-314.pyc +0 -0
  253. package/skills/torusguard/payload/scripts/__pycache__/harden_runner.cpython-314.pyc +0 -0
  254. package/skills/torusguard/payload/scripts/__pycache__/html_reporter.cpython-311.pyc +0 -0
  255. package/skills/torusguard/payload/scripts/__pycache__/html_reporter.cpython-314.pyc +0 -0
  256. package/skills/torusguard/payload/scripts/__pycache__/manifest_builder.cpython-314.pyc +0 -0
  257. package/skills/torusguard/payload/scripts/__pycache__/memory_engine.cpython-311.pyc +0 -0
  258. package/skills/torusguard/payload/scripts/__pycache__/memory_engine.cpython-314.pyc +0 -0
  259. package/skills/torusguard/payload/scripts/__pycache__/monorepo_detector.cpython-311.pyc +0 -0
  260. package/skills/torusguard/payload/scripts/__pycache__/monorepo_detector.cpython-314.pyc +0 -0
  261. package/skills/torusguard/payload/scripts/__pycache__/recheck_runner.cpython-314.pyc +0 -0
  262. package/skills/torusguard/payload/scripts/__pycache__/report_sync.cpython-311.pyc +0 -0
  263. package/skills/torusguard/payload/scripts/__pycache__/report_sync.cpython-314.pyc +0 -0
  264. package/skills/torusguard/payload/scripts/__pycache__/rules_sync.cpython-311.pyc +0 -0
  265. package/skills/torusguard/payload/scripts/__pycache__/run_manager.cpython-311.pyc +0 -0
  266. package/skills/torusguard/payload/scripts/__pycache__/run_manager.cpython-314.pyc +0 -0
  267. package/skills/torusguard/payload/scripts/__pycache__/sarif_exporter.cpython-314.pyc +0 -0
  268. package/skills/torusguard/payload/scripts/__pycache__/stack_detect.cpython-311.pyc +0 -0
  269. package/skills/torusguard/payload/scripts/__pycache__/stack_detect.cpython-314.pyc +0 -0
  270. package/skills/torusguard/payload/scripts/__pycache__/term_ui.cpython-311.pyc +0 -0
  271. package/skills/torusguard/payload/scripts/__pycache__/term_ui.cpython-314.pyc +0 -0
  272. package/skills/torusguard/payload/scripts/apply_runner.py +389 -377
  273. package/skills/torusguard/payload/scripts/audit_runner.py +1513 -653
  274. package/skills/torusguard/payload/scripts/finding_scorer.py +14 -2
  275. package/skills/torusguard/payload/scripts/harden_runner.py +628 -455
  276. package/skills/torusguard/payload/scripts/html_reporter.py +2668 -648
  277. package/skills/torusguard/payload/scripts/recheck_runner.py +248 -238
  278. package/skills/torusguard/payload/scripts/recipes_runner.py +137 -137
  279. package/skills/torusguard/payload/scripts/report_sync.py +719 -0
  280. package/skills/torusguard/payload/scripts/sarif_exporter.py +156 -116
  281. package/skills/torusguard/payload/scripts/stack_detect.py +44 -2
  282. package/skills/torusguard/payload/scripts/term_ui.py +162 -162
  283. package/skills/torusguard/payload/skills/torusguard/SKILL.md +75 -72
  284. package/skills/torusguard/payload/skills/torusguard-apply/SKILL.md +84 -80
  285. package/skills/torusguard/payload/skills/torusguard-audit/SKILL.md +87 -83
  286. package/skills/torusguard/payload/skills/torusguard-authorize/SKILL.md +7 -2
  287. package/skills/torusguard/payload/skills/torusguard-exploit-check/SKILL.md +7 -2
  288. package/skills/torusguard/payload/skills/torusguard-full/SKILL.md +7 -2
  289. package/skills/torusguard/payload/skills/torusguard-harden/SKILL.md +98 -94
  290. package/skills/torusguard/payload/skills/torusguard-init/SKILL.md +68 -64
  291. package/skills/torusguard/payload/skills/torusguard-recheck/SKILL.md +81 -77
  292. package/skills/torusguard/payload/skills/torusguard-report/SKILL.md +93 -72
  293. package/skills/torusguard/payload/skills/torusguard-status/SKILL.md +62 -58
  294. package/skills/torusguard/payload/skills/torusguard-verify/SKILL.md +7 -2
  295. package/skills/torusguard/payload/skills/torusguard-web-validate/SKILL.md +7 -2
  296. package/skills/torusguard/payload/workflows/apply.md +11 -4
  297. package/skills/torusguard/payload/workflows/audit.md +7 -1
  298. package/skills/torusguard/payload/workflows/authorize.md +2 -1
  299. package/skills/torusguard/payload/workflows/exploit-check.md +2 -1
  300. package/skills/torusguard/payload/workflows/harden.md +7 -1
  301. package/skills/torusguard/payload/workflows/init.md +6 -1
  302. package/skills/torusguard/payload/workflows/memory.md +2 -1
  303. package/skills/torusguard/payload/workflows/recheck.md +7 -1
  304. package/skills/torusguard/payload/workflows/report.md +7 -1
  305. package/skills/torusguard/payload/workflows/status.md +6 -1
  306. package/skills/torusguard/payload/workflows/verify.md +6 -1
  307. package/skills/torusguard/payload/workflows/web-validate.md +2 -1
  308. package/skills/torusguard-apply/SKILL.md +84 -80
  309. package/skills/torusguard-audit/SKILL.md +87 -83
  310. package/skills/torusguard-authorize/SKILL.md +7 -2
  311. package/skills/torusguard-exploit-check/SKILL.md +7 -2
  312. package/skills/torusguard-full/SKILL.md +7 -2
  313. package/skills/torusguard-harden/SKILL.md +98 -94
  314. package/skills/torusguard-init/SKILL.md +68 -64
  315. package/skills/torusguard-recheck/SKILL.md +81 -77
  316. package/skills/torusguard-report/SKILL.md +93 -72
  317. package/skills/torusguard-status/SKILL.md +62 -58
  318. package/skills/torusguard-verify/SKILL.md +7 -2
  319. package/skills/torusguard-web-validate/SKILL.md +7 -2
@@ -1,238 +1,248 @@
1
- #!/usr/bin/env python3
2
- """
3
- TorusGuard Targeted Differential Recheck Engine (v1.3.3)
4
- Executes scoped differential re-audits verifying only impacted files and adjacent boundaries.
5
- Evaluates formal status transitions (Confirmed Fixed vs Regressed vs Unresolved), updates run manifest,
6
- and records verification telemetry in the persistent security memory subsystem.
7
- Standardized 75-column terminal UI formatting.
8
-
9
- Pure Python 3.10+ standard library (zero external dependencies).
10
- """
11
-
12
- import sys
13
- import os
14
- import re
15
- import json
16
- import argparse
17
- import datetime
18
- from pathlib import Path
19
- from typing import Dict, List, Any, Optional
20
-
21
- # Ensure scripts dir is in sys.path for term_ui import
22
- scripts_dir = Path(__file__).resolve().parent
23
- if str(scripts_dir) not in sys.path:
24
- sys.path.insert(0, str(scripts_dir))
25
-
26
- try:
27
- import term_ui
28
- except ImportError:
29
- term_ui = None
30
-
31
- # Windows console UTF-8 support
32
- if sys.stdout and hasattr(sys.stdout, "reconfigure"):
33
- try:
34
- getattr(sys.stdout, "reconfigure")(encoding="utf-8", errors="replace")
35
- except Exception:
36
- pass
37
-
38
- # ─── Timezone Configuration: Indian Standard Time (IST, UTC+05:30) ───────────
39
- IST = datetime.timezone(datetime.timedelta(hours=5, minutes=30), name="IST")
40
-
41
- def get_ist_now() -> datetime.datetime:
42
- return datetime.datetime.now(IST)
43
-
44
- # ─── Formatting Helpers ────────────────────────────────────────────────────────
45
- BOLD = "\033[1m"
46
- DIM = "\033[2m"
47
- RESET = "\033[0m"
48
- CYAN = "\033[36m"
49
- GREEN = "\033[32m"
50
- YELLOW = "\033[33m"
51
- WHITE = "\033[97m"
52
- GRAY = "\033[90m"
53
- RED = "\033[31m"
54
-
55
- def box_line(content: str, width: int = 67, border: str = "│", border_color: str = CYAN) -> str:
56
- if term_ui:
57
- return term_ui.format_box_line(content, width=width, border=border, border_color=border_color)
58
- return f" {border_color}{border}{RESET} {content}"
59
-
60
- def box_header(title: str, subtitle: str = "", version: str = "v1.3.3", border_color: str = CYAN) -> str:
61
- if term_ui:
62
- return term_ui.card_header(title, subtitle, version, border_color)
63
- return f"=== {title} ({version}) ==="
64
-
65
- def border_top(title: str = "", border_color: str = CYAN, double: bool = False) -> str:
66
- if term_ui:
67
- return term_ui.card_border_top(title, border_color=border_color, double=double)
68
- return "┌" + "─" * 71 + "┐"
69
-
70
- def border_bottom(border_color: str = CYAN, double: bool = False) -> str:
71
- if term_ui:
72
- return term_ui.card_border_bottom(border_color=border_color, double=double)
73
- return "└" + "─" * 71 + "┘"
74
-
75
-
76
- def find_latest_audit_run(runs_dir: Path) -> Optional[Path]:
77
- if not runs_dir.is_dir():
78
- return None
79
- runs = sorted(runs_dir.glob("run-*-audit"), key=lambda p: p.stat().st_mtime, reverse=True)
80
- return runs[0] if runs else None
81
-
82
-
83
- def execute_recheck(target_root: Path, run_id_arg: Optional[str] = None) -> Dict[str, Any]:
84
- runs_dir = target_root / ".torusguard" / "runs"
85
- if run_id_arg:
86
- run_folder = runs_dir / run_id_arg
87
- else:
88
- run_folder = find_latest_audit_run(runs_dir)
89
-
90
- if not run_folder or not run_folder.is_dir():
91
- print(f"\n {RED}✖ No audit run found to recheck.{RESET}\n")
92
- sys.exit(1)
93
-
94
- # Import audit scanner and memory engine
95
- try:
96
- import audit_runner
97
- except ImportError:
98
- audit_runner = None
99
- try:
100
- import memory_engine
101
- except ImportError:
102
- memory_engine = None
103
-
104
- bundles_dir = run_folder / "bundles"
105
- bundle_meta_files = list(bundles_dir.glob("*/metadata.json")) if bundles_dir.is_dir() else []
106
-
107
- # Header Card
108
- print()
109
- print(box_header("🛡️ TORUSGUARD DIFFERENTIAL RECHECK ENGINE", "Targeted Differential AST Scan & Regression Verification", "v1.3.3"))
110
- print()
111
-
112
- print(border_top("Recheck Verification Scope"))
113
- print(box_line(f"Active Run: {WHITE}{run_folder.name}{RESET}"))
114
- print(box_line(f"Target Root: {WHITE}{target_root}{RESET}"))
115
- print(border_bottom())
116
- print()
117
-
118
- recheck_results = []
119
- confirmed_count = 0
120
- regressed_count = 0
121
- unresolved_count = 0
122
-
123
- recheck_md_lines = [
124
- f"# TorusGuard Differential Recheck Report",
125
- f"**Run ID:** `{run_folder.name}` ",
126
- f"**Timestamp:** `{get_ist_now().strftime('%Y-%m-%d %H:%M:%S IST')}` \n",
127
- "---",
128
- "## Recheck Transition Catalog\n"
129
- ]
130
-
131
- for mf in bundle_meta_files:
132
- try:
133
- bdata = json.loads(mf.read_text(encoding="utf-8"))
134
- except Exception:
135
- continue
136
-
137
- rule_id = bdata.get("rule_id", "")
138
- rel_path = bdata.get("target_file", "")
139
- target_path = target_root / rel_path
140
-
141
- if not target_path.is_file():
142
- continue
143
-
144
- # Differential scan on this single modified file
145
- if audit_runner:
146
- file_findings = audit_runner.scan_file(target_path, target_root)
147
- matching_rule_findings = [f for f in file_findings if f.get("rule_id") == rule_id]
148
- else:
149
- matching_rule_findings = []
150
-
151
- if not matching_rule_findings:
152
- outcome = "Confirmed Fixed"
153
- confirmed_count += 1
154
- status_icon = f"{GREEN}✔ [Confirmed Fixed]{RESET}"
155
- # Record in memory
156
- if memory_engine:
157
- try:
158
- memory_engine.record_event("fix_verified", {
159
- "rule_id": rule_id,
160
- "file_path": rel_path,
161
- "verification_result": "fixed"
162
- }, root_dir=target_root)
163
- except Exception:
164
- pass
165
- else:
166
- outcome = "Unresolved"
167
- unresolved_count += 1
168
- status_icon = f"{YELLOW}⚠ [Unresolved]{RESET}"
169
-
170
- recheck_results.append({
171
- "rule_id": rule_id,
172
- "target_file": rel_path,
173
- "outcome": outcome,
174
- "title": bdata.get("title", rule_id)
175
- })
176
-
177
- recheck_md_lines.append(f"### [{rule_id}] {bdata.get('title')}")
178
- recheck_md_lines.append(f"- **File:** `{rel_path}`")
179
- recheck_md_lines.append(f"- **Outcome:** `{outcome}`")
180
- recheck_md_lines.append(f"- **Verification Timestamp:** {get_ist_now().strftime('%Y-%m-%d %H:%M:%S IST')}\n")
181
-
182
- print(f" {status_icon} {WHITE}{rule_id}{RESET} on {rel_path}")
183
-
184
- # Write recheck.md
185
- (run_folder / "recheck.md").write_text("\n".join(recheck_md_lines), encoding="utf-8")
186
-
187
- # Update manifest
188
- manifest_file = run_folder / "manifest.json"
189
- if manifest_file.is_file():
190
- try:
191
- mdata = json.loads(manifest_file.read_text(encoding="utf-8"))
192
- mdata["status"] = "verified_fixed" if regressed_count == 0 and unresolved_count == 0 else "recheck_completed"
193
- mdata["confirmed_fixed_count"] = confirmed_count
194
- mdata["regressed_count"] = regressed_count
195
- manifest_file.write_text(json.dumps(mdata, indent=2), encoding="utf-8")
196
- except Exception:
197
- pass
198
-
199
- print()
200
- print(border_top("Recheck Summary"))
201
- print(box_line(f"Confirmed Fixed:{GREEN}{confirmed_count} vulnerabilities verified closed{RESET}"))
202
- print(box_line(f"Regressed: {RED if regressed_count > 0 else GREEN}{regressed_count} regressions detected{RESET}"))
203
- print(box_line(f"Unresolved: {YELLOW if unresolved_count > 0 else GREEN}{unresolved_count} unresolved{RESET}"))
204
- print(box_line(f"Memory Sync: {GREEN}Verification events synced to persistent memory engine{RESET}"))
205
- print(border_bottom())
206
- print()
207
-
208
- print(border_top("Next Governed Action", border_color=GREEN, double=True))
209
- print(box_line(f"Visual Dashboard: {BOLD}{WHITE}npx torusguard report --html{RESET} (Updated posture score)", border="║", border_color=GREEN))
210
- print(box_line(f"View Recipes: {CYAN}npx torusguard recipes{RESET} (Active golden fix recipes)", border="║", border_color=GREEN))
211
- print(border_bottom(border_color=GREEN, double=True))
212
- print()
213
-
214
- return {
215
- "run_folder": str(run_folder),
216
- "confirmed_fixed_count": confirmed_count,
217
- "regressed_count": regressed_count,
218
- "unresolved_count": unresolved_count,
219
- "results": recheck_results
220
- }
221
-
222
-
223
- def main():
224
- parser = argparse.ArgumentParser(description="TorusGuard Differential Recheck Engine")
225
- parser.add_argument("path", nargs="?", default=".", help="Target project root directory")
226
- parser.add_argument("--run", "-r", help="Explicit run ID to recheck")
227
- parser.add_argument("--json", action="store_true", help="Output raw JSON")
228
- args = parser.parse_args()
229
-
230
- target = Path(args.path).resolve()
231
- result = execute_recheck(target, run_id_arg=args.run)
232
-
233
- if args.json:
234
- print(json.dumps(result, indent=2))
235
-
236
-
237
- if __name__ == "__main__":
238
- main()
1
+ #!/usr/bin/env python3
2
+ """
3
+ TorusGuard Targeted Differential Recheck Engine (v1.3.6)
4
+ Executes scoped differential re-audits verifying only impacted files and adjacent boundaries.
5
+ Evaluates formal status transitions (Confirmed Fixed vs Regressed vs Unresolved), updates run manifest,
6
+ and records verification telemetry in the persistent security memory subsystem.
7
+ Standardized 75-column terminal UI formatting.
8
+
9
+ Pure Python 3.10+ standard library (zero external dependencies).
10
+ """
11
+
12
+ import sys
13
+ import os
14
+ import re
15
+ import json
16
+ import argparse
17
+ import datetime
18
+ from pathlib import Path
19
+ from typing import Dict, List, Any, Optional
20
+
21
+ # Ensure scripts dir is in sys.path for term_ui import
22
+ scripts_dir = Path(__file__).resolve().parent
23
+ if str(scripts_dir) not in sys.path:
24
+ sys.path.insert(0, str(scripts_dir))
25
+
26
+ try:
27
+ import term_ui
28
+ except ImportError:
29
+ term_ui = None
30
+
31
+ # Windows console UTF-8 support
32
+ if sys.stdout and hasattr(sys.stdout, "reconfigure"):
33
+ try:
34
+ getattr(sys.stdout, "reconfigure")(encoding="utf-8", errors="replace")
35
+ except Exception:
36
+ pass
37
+
38
+ # ─── Timezone Configuration: Indian Standard Time (IST, UTC+05:30) ───────────
39
+ IST = datetime.timezone(datetime.timedelta(hours=5, minutes=30), name="IST")
40
+
41
+ def get_ist_now() -> datetime.datetime:
42
+ return datetime.datetime.now(IST)
43
+
44
+ # ─── Formatting Helpers ────────────────────────────────────────────────────────
45
+ BOLD = "\033[1m"
46
+ DIM = "\033[2m"
47
+ RESET = "\033[0m"
48
+ CYAN = "\033[36m"
49
+ GREEN = "\033[32m"
50
+ YELLOW = "\033[33m"
51
+ WHITE = "\033[97m"
52
+ GRAY = "\033[90m"
53
+ RED = "\033[31m"
54
+
55
+ def box_line(content: str, width: int = 67, border: str = "│", border_color: str = CYAN) -> str:
56
+ if term_ui:
57
+ return term_ui.format_box_line(content, width=width, border=border, border_color=border_color)
58
+ return f" {border_color}{border}{RESET} {content}"
59
+
60
+ def box_header(title: str, subtitle: str = "", version: str = "v1.3.6", border_color: str = CYAN) -> str:
61
+ if term_ui:
62
+ return term_ui.card_header(title, subtitle, version, border_color)
63
+ return f"=== {title} ({version}) ==="
64
+
65
+ def border_top(title: str = "", border_color: str = CYAN, double: bool = False) -> str:
66
+ if term_ui:
67
+ return term_ui.card_border_top(title, border_color=border_color, double=double)
68
+ return "┌" + "─" * 71 + "┐"
69
+
70
+ def border_bottom(border_color: str = CYAN, double: bool = False) -> str:
71
+ if term_ui:
72
+ return term_ui.card_border_bottom(border_color=border_color, double=double)
73
+ return "└" + "─" * 71 + "┘"
74
+
75
+
76
+ def find_latest_audit_run(runs_dir: Path) -> Optional[Path]:
77
+ if not runs_dir.is_dir():
78
+ return None
79
+ runs = sorted(runs_dir.glob("run-*-audit"), key=lambda p: p.stat().st_mtime, reverse=True)
80
+ return runs[0] if runs else None
81
+
82
+
83
+ def execute_recheck(target_root: Path, run_id_arg: Optional[str] = None) -> Dict[str, Any]:
84
+ runs_dir = target_root / ".torusguard" / "runs"
85
+ if run_id_arg:
86
+ run_folder = runs_dir / run_id_arg
87
+ else:
88
+ run_folder = find_latest_audit_run(runs_dir)
89
+
90
+ if not run_folder or not run_folder.is_dir():
91
+ print(f"\n {RED}✖ No audit run found to recheck.{RESET}\n")
92
+ sys.exit(1)
93
+
94
+ # Import audit scanner and memory engine
95
+ try:
96
+ import audit_runner
97
+ except ImportError:
98
+ audit_runner = None
99
+ try:
100
+ import memory_engine
101
+ except ImportError:
102
+ memory_engine = None
103
+
104
+ bundles_dir = run_folder / "bundles"
105
+ bundle_meta_files = list(bundles_dir.glob("*/metadata.json")) if bundles_dir.is_dir() else []
106
+
107
+ # Header Card
108
+ print()
109
+ print(box_header("🛡️ TORUSGUARD DIFFERENTIAL RECHECK ENGINE", "Targeted Differential AST Scan & Regression Verification", "v1.3.6"))
110
+ print()
111
+
112
+ print(border_top("Recheck Verification Scope"))
113
+ print(box_line(f"Active Run: {WHITE}{run_folder.name}{RESET}"))
114
+ print(box_line(f"Target Root: {WHITE}{target_root}{RESET}"))
115
+ print(border_bottom())
116
+ print()
117
+
118
+ recheck_results = []
119
+ confirmed_count = 0
120
+ regressed_count = 0
121
+ unresolved_count = 0
122
+
123
+ recheck_md_lines = [
124
+ f"# TorusGuard Differential Recheck Report",
125
+ f"**Run ID:** `{run_folder.name}` ",
126
+ f"**Timestamp:** `{get_ist_now().strftime('%Y-%m-%d %H:%M:%S IST')}` \n",
127
+ "---",
128
+ "## Recheck Transition Catalog\n"
129
+ ]
130
+
131
+ for mf in bundle_meta_files:
132
+ try:
133
+ bdata = json.loads(mf.read_text(encoding="utf-8"))
134
+ except Exception:
135
+ continue
136
+
137
+ rule_id = bdata.get("rule_id", "")
138
+ rel_path = bdata.get("target_file", "")
139
+ target_path = target_root / rel_path
140
+
141
+ if not target_path.is_file():
142
+ continue
143
+
144
+ # Differential scan on this single modified file
145
+ if audit_runner:
146
+ file_findings = audit_runner.scan_file(target_path, target_root)
147
+ matching_rule_findings = [f for f in file_findings if f.get("rule_id") == rule_id]
148
+ else:
149
+ matching_rule_findings = []
150
+
151
+ if not matching_rule_findings:
152
+ outcome = "Confirmed Fixed"
153
+ confirmed_count += 1
154
+ status_icon = f"{GREEN}✔ [Confirmed Fixed]{RESET}"
155
+ # Record in memory
156
+ if memory_engine:
157
+ try:
158
+ memory_engine.record_event("fix_verified", {
159
+ "rule_id": rule_id,
160
+ "file_path": rel_path,
161
+ "verification_result": "fixed"
162
+ }, root_dir=target_root)
163
+ except Exception:
164
+ pass
165
+ else:
166
+ outcome = "Unresolved"
167
+ unresolved_count += 1
168
+ status_icon = f"{YELLOW}⚠ [Unresolved]{RESET}"
169
+
170
+ recheck_results.append({
171
+ "rule_id": rule_id,
172
+ "target_file": rel_path,
173
+ "outcome": outcome,
174
+ "title": bdata.get("title", rule_id)
175
+ })
176
+
177
+ recheck_md_lines.append(f"### [{rule_id}] {bdata.get('title')}")
178
+ recheck_md_lines.append(f"- **File:** `{rel_path}`")
179
+ recheck_md_lines.append(f"- **Outcome:** `{outcome}`")
180
+ recheck_md_lines.append(f"- **Verification Timestamp:** {get_ist_now().strftime('%Y-%m-%d %H:%M:%S IST')}\n")
181
+
182
+ print(f" {status_icon} {WHITE}{rule_id}{RESET} on {rel_path}")
183
+
184
+ # Write recheck.md
185
+ (run_folder / "recheck.md").write_text("\n".join(recheck_md_lines), encoding="utf-8")
186
+ try:
187
+ import report_sync
188
+ report_sync.record_recheck_results(target_root, {
189
+ "fixed": [r for r in recheck_results if r.get("outcome") == "Confirmed Fixed"],
190
+ "regressed": [r for r in recheck_results if r.get("outcome") == "Regressed"],
191
+ "remaining": [r for r in recheck_results if r.get("outcome") == "Unresolved"]
192
+ }, run_folder.name)
193
+ except Exception:
194
+ pass
195
+
196
+ # Update manifest
197
+ manifest_file = run_folder / "manifest.json"
198
+ if manifest_file.is_file():
199
+ try:
200
+ mdata = json.loads(manifest_file.read_text(encoding="utf-8"))
201
+ mdata["status"] = "verified_fixed" if regressed_count == 0 and unresolved_count == 0 else "recheck_completed"
202
+ mdata["confirmed_fixed_count"] = confirmed_count
203
+ mdata["regressed_count"] = regressed_count
204
+ manifest_file.write_text(json.dumps(mdata, indent=2), encoding="utf-8")
205
+ except Exception:
206
+ pass
207
+
208
+ print()
209
+ print(border_top("Recheck Summary"))
210
+ print(box_line(f"Confirmed Fixed:{GREEN}{confirmed_count} vulnerabilities verified closed{RESET}"))
211
+ print(box_line(f"Regressed: {RED if regressed_count > 0 else GREEN}{regressed_count} regressions detected{RESET}"))
212
+ print(box_line(f"Unresolved: {YELLOW if unresolved_count > 0 else GREEN}{unresolved_count} unresolved{RESET}"))
213
+ print(box_line(f"Memory Sync: {GREEN}Verification events synced to persistent memory engine{RESET}"))
214
+ print(border_bottom())
215
+ print()
216
+
217
+ print(border_top("Next Governed Action", border_color=GREEN, double=True))
218
+ print(box_line(f"Living Report: {CYAN}security_report.md (verified closures recorded){RESET}", border="║", border_color=GREEN))
219
+ print(box_line(f"Visual Dashboard: {BOLD}{WHITE}npx torusguard report --html{RESET} (Updated posture score)", border="║", border_color=GREEN))
220
+ print(box_line(f"View Recipes: {CYAN}npx torusguard recipes{RESET} (Active golden fix recipes)", border="║", border_color=GREEN))
221
+ print(border_bottom(border_color=GREEN, double=True))
222
+ print()
223
+
224
+ return {
225
+ "run_folder": str(run_folder),
226
+ "confirmed_fixed_count": confirmed_count,
227
+ "regressed_count": regressed_count,
228
+ "unresolved_count": unresolved_count,
229
+ "results": recheck_results
230
+ }
231
+
232
+
233
+ def main():
234
+ parser = argparse.ArgumentParser(description="TorusGuard Differential Recheck Engine")
235
+ parser.add_argument("path", nargs="?", default=".", help="Target project root directory")
236
+ parser.add_argument("--run", "-r", help="Explicit run ID to recheck")
237
+ parser.add_argument("--json", action="store_true", help="Output raw JSON")
238
+ args = parser.parse_args()
239
+
240
+ target = Path(args.path).resolve()
241
+ result = execute_recheck(target, run_id_arg=args.run)
242
+
243
+ if args.json:
244
+ print(json.dumps(result, indent=2))
245
+
246
+
247
+ if __name__ == "__main__":
248
+ main()