torusguard 1.3.3 → 1.3.5

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