torusguard 1.3.0 → 1.3.2

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 (378) hide show
  1. package/.torusguard/.manifest.json +113 -9
  2. package/.torusguard/rules/README.md +93 -62
  3. package/.torusguard/rules/TG-AUTH-001-weak-password-storage.md +103 -0
  4. package/.torusguard/rules/TG-AUTH-002-client-only-authorization.md +85 -0
  5. package/.torusguard/rules/TG-AUTH-003-missing-object-authorization.md +85 -0
  6. package/.torusguard/rules/TG-AUTH-004-insecure-session-cookie.md +96 -0
  7. package/.torusguard/rules/TG-AUTH-005-unsafe-password-reset.md +104 -0
  8. package/.torusguard/rules/TG-CLIENT-001-public-production-source-maps.md +102 -0
  9. package/.torusguard/rules/TG-CLIENT-002-sensitive-client-bundle-content.md +102 -0
  10. package/.torusguard/rules/TG-DB-001-frontend-database-query.md +83 -0
  11. package/.torusguard/rules/TG-DB-002-privileged-database-credential.md +86 -0
  12. package/.torusguard/rules/TG-DB-003-frontend-admin-sdk.md +91 -0
  13. package/.torusguard/rules/TG-DB-004-missing-tenant-query-isolation.md +103 -0
  14. package/.torusguard/rules/TG-INPUT-001-missing-server-validation.md +98 -0
  15. package/.torusguard/rules/TG-INPUT-002-raw-sql-concatenation.md +94 -0
  16. package/.torusguard/rules/TG-INPUT-003-unsafe-html-or-code-execution.md +102 -0
  17. package/.torusguard/rules/TG-INPUT-004-unrestricted-file-upload.md +92 -0
  18. package/.torusguard/rules/TG-INPUT-005-unsafe-template-rendering-and-escaping.md +102 -0
  19. package/.torusguard/rules/TG-INPUT-006-unsafe-file-path-traversal.md +131 -0
  20. package/.torusguard/rules/TG-PLATFORM-001-wildcard-cors-with-credentials.md +101 -0
  21. package/.torusguard/rules/TG-PLATFORM-002-missing-security-headers.md +95 -0
  22. package/.torusguard/rules/TG-PLATFORM-003-production-stack-trace-exposure.md +94 -0
  23. package/.torusguard/rules/TG-PLATFORM-004-missing-request-size-limits.md +102 -0
  24. package/.torusguard/rules/TG-RATE-001-unlimited-auth-endpoint.md +112 -0
  25. package/.torusguard/rules/TG-RATE-002-unlimited-public-write-endpoint.md +109 -0
  26. package/.torusguard/rules/TG-RATE-003-unbounded-resource-consumption.md +105 -0
  27. package/.torusguard/rules/TG-SEC-001-hardcoded-secrets.md +83 -0
  28. package/.torusguard/rules/TG-SEC-002-public-environment-secrets.md +83 -0
  29. package/.torusguard/rules/TG-SEC-003-tracked-env-file.md +79 -0
  30. package/.torusguard/rules/TG-SEC-004-sensitive-logging.md +83 -0
  31. package/.torusguard/rules/active/TG-AUTH-001-weak-password-storage.md +103 -0
  32. package/.torusguard/rules/active/TG-AUTH-002-client-only-authorization.md +85 -0
  33. package/.torusguard/rules/active/TG-AUTH-003-missing-object-authorization.md +85 -0
  34. package/.torusguard/rules/active/TG-AUTH-004-insecure-session-cookie.md +96 -0
  35. package/.torusguard/rules/active/TG-AUTH-005-unsafe-password-reset.md +104 -0
  36. package/.torusguard/rules/active/TG-CLIENT-001-public-production-source-maps.md +102 -0
  37. package/.torusguard/rules/active/TG-CLIENT-002-sensitive-client-bundle-content.md +102 -0
  38. package/.torusguard/rules/active/TG-DB-001-frontend-database-query.md +83 -0
  39. package/.torusguard/rules/active/TG-DB-002-privileged-database-credential.md +86 -0
  40. package/.torusguard/rules/active/TG-DB-003-frontend-admin-sdk.md +91 -0
  41. package/.torusguard/rules/active/TG-DB-004-missing-tenant-query-isolation.md +103 -0
  42. package/.torusguard/rules/active/TG-INPUT-001-missing-server-validation.md +98 -0
  43. package/.torusguard/rules/active/TG-INPUT-002-raw-sql-concatenation.md +94 -0
  44. package/.torusguard/rules/active/TG-INPUT-003-unsafe-html-or-code-execution.md +102 -0
  45. package/.torusguard/rules/active/TG-INPUT-004-unrestricted-file-upload.md +92 -0
  46. package/.torusguard/rules/active/TG-INPUT-005-unsafe-template-rendering-and-escaping.md +102 -0
  47. package/.torusguard/rules/active/TG-INPUT-006-unsafe-file-path-traversal.md +131 -0
  48. package/.torusguard/rules/active/TG-PLATFORM-001-wildcard-cors-with-credentials.md +101 -0
  49. package/.torusguard/rules/active/TG-PLATFORM-002-missing-security-headers.md +95 -0
  50. package/.torusguard/rules/active/TG-PLATFORM-003-production-stack-trace-exposure.md +94 -0
  51. package/.torusguard/rules/active/TG-PLATFORM-004-missing-request-size-limits.md +102 -0
  52. package/.torusguard/rules/active/TG-RATE-001-unlimited-auth-endpoint.md +112 -0
  53. package/.torusguard/rules/active/TG-RATE-002-unlimited-public-write-endpoint.md +109 -0
  54. package/.torusguard/rules/active/TG-RATE-003-unbounded-resource-consumption.md +105 -0
  55. package/.torusguard/rules/active/TG-SEC-001-hardcoded-secrets.md +83 -0
  56. package/.torusguard/rules/active/TG-SEC-002-public-environment-secrets.md +83 -0
  57. package/.torusguard/rules/active/TG-SEC-003-tracked-env-file.md +79 -0
  58. package/.torusguard/rules/active/TG-SEC-004-sensitive-logging.md +83 -0
  59. package/.torusguard/rules/agent/TG-AGENT-001-prompt-injection-system-context.md +56 -0
  60. package/.torusguard/rules/agent/TG-AGENT-002-unsafe-tool-dispatch-unsandboxed-execution.md +68 -0
  61. package/.torusguard/rules/agent/TG-AGENT-003-broad-mcp-tool-scoping.md +53 -0
  62. package/.torusguard/rules/agent/TG-AGENT-004-persistent-memory-cross-session-leakage.md +67 -0
  63. package/.torusguard/rules/authorization/TG-AUTH-006-mass-assignment.md +70 -0
  64. package/.torusguard/rules/authorization/TG-AUTH-007-missing-property-level-authorization.md +71 -0
  65. package/.torusguard/rules/authorization/TG-AUTH-008-untrusted-role-header-injection.md +112 -0
  66. package/.torusguard/rules/business-logic/TG-BIZ-001-client-controlled-sensitive-business-value.md +37 -0
  67. package/.torusguard/rules/business-logic/TG-BIZ-002-replayable-one-time-operation.md +37 -0
  68. package/.torusguard/rules/business-logic/TG-BIZ-003-missing-workflow-state-validation.md +37 -0
  69. package/.torusguard/rules/business-logic/TG-BIZ-004-unrestricted-sensitive-business-flow.md +37 -0
  70. package/.torusguard/rules/cache/TG-CACHE-001-sensitive-response-publicly-cacheable.md +37 -0
  71. package/.torusguard/rules/cache/TG-CACHE-002-missing-user-cache-isolation.md +37 -0
  72. package/.torusguard/rules/cache/TG-CACHE-003-sensitive-data-in-url.md +37 -0
  73. package/.torusguard/rules/csrf/TG-CSRF-001-missing-csrf-protection.md +37 -0
  74. package/.torusguard/rules/csrf/TG-CSRF-002-unsafe-credentialed-cross-origin-request.md +37 -0
  75. package/.torusguard/rules/edge/TG-EDGE-001-serverless-global-state-leak.md +83 -0
  76. package/.torusguard/rules/edge/TG-EDGE-003-aws-lambda-ephemeral-cold-start.md +76 -0
  77. package/.torusguard/rules/graphql/TG-GQL-001-missing-query-depth-or-complexity-limits.md +64 -0
  78. package/.torusguard/rules/graphql/TG-GQL-002-resolver-missing-authorization.md +37 -0
  79. package/.torusguard/rules/graphql/TG-GQL-003-unbounded-graphql-pagination-or-batching.md +37 -0
  80. package/.torusguard/rules/graphql/TG-GQL-004-unnecessary-production-introspection.md +37 -0
  81. package/.torusguard/rules/secrets/TG-SEC-005-secret-in-git-history.md +37 -0
  82. package/.torusguard/rules/secrets/TG-SEC-006-secret-in-build-artifact.md +37 -0
  83. package/.torusguard/rules/secrets/TG-SEC-007-secret-in-test-or-example-fixture.md +37 -0
  84. package/.torusguard/rules/ssrf/TG-SSRF-001-user-controlled-server-side-url-fetch.md +68 -0
  85. package/.torusguard/rules/ssrf/TG-SSRF-002-missing-internal-network-protection.md +37 -0
  86. package/.torusguard/rules/ssrf/TG-SSRF-003-unsafe-redirect-following.md +37 -0
  87. package/.torusguard/rules/ssrf/TG-SSRF-004-unbounded-outbound-request.md +37 -0
  88. package/.torusguard/rules/supply-chain/TG-SUPPLY-001-missing-or-ignored-dependency-lockfile.md +37 -0
  89. package/.torusguard/rules/supply-chain/TG-SUPPLY-002-vulnerable-dependency-review-missing.md +94 -0
  90. package/.torusguard/rules/supply-chain/TG-SUPPLY-003-unsafe-ci-cd-secret-exposure.md +37 -0
  91. package/.torusguard/rules/supply-chain/TG-SUPPLY-004-unpinned-ci-action.md +37 -0
  92. package/.torusguard/rules/supply-chain/TG-SUPPLY-005-unsafe-dependency-install-script.md +37 -0
  93. package/.torusguard/rules/supply-chain/TG-SUPPLY-006-container-build-secret-persistence.md +61 -0
  94. package/.torusguard/rules/webhook/TG-WEBHOOK-001-missing-webhook-signature-verification.md +37 -0
  95. package/.torusguard/rules/webhook/TG-WEBHOOK-002-replayable-webhook.md +37 -0
  96. package/.torusguard/rules/webhook/TG-WEBHOOK-003-missing-webhook-idempotency.md +37 -0
  97. package/.torusguard/rules/webhook/TG-WEBHOOK-004-unvalidated-webhook-event-type.md +37 -0
  98. package/.torusguard/rules/websocket/TG-WS-001-unauthenticated-websocket-handshake.md +82 -0
  99. package/.torusguard/rules/websocket/TG-WS-002-missing-channel-level-authorization.md +37 -0
  100. package/.torusguard/rules/websocket/TG-WS-003-unvalidated-websocket-message.md +37 -0
  101. package/.torusguard/rules/websocket/TG-WS-004-unbounded-websocket-connections.md +37 -0
  102. package/.torusguard/runs/report-latest.html +62 -20
  103. package/.torusguard/runs/run-20260908-112648-audit/findings.json +1520 -0
  104. package/.torusguard/runs/run-20260908-112648-audit/findings.md +560 -0
  105. package/.torusguard/runs/run-20260908-112648-audit/manifest.json +12 -0
  106. package/.torusguard/runs/run-20260908-112648-audit/summary.md +5 -0
  107. package/.torusguard/runs/run-20260908-112722-audit/findings.json +1520 -0
  108. package/.torusguard/runs/run-20260908-112722-audit/findings.md +560 -0
  109. package/.torusguard/runs/run-20260908-112722-audit/manifest.json +12 -0
  110. package/.torusguard/runs/run-20260908-112722-audit/summary.md +5 -0
  111. package/.torusguard/runs/run-20260908-113004-audit/findings.json +1520 -0
  112. package/.torusguard/runs/run-20260908-113004-audit/findings.md +560 -0
  113. package/.torusguard/runs/run-20260908-113004-audit/manifest.json +12 -0
  114. package/.torusguard/runs/run-20260908-113004-audit/summary.md +5 -0
  115. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-115-9a059e/metadata.json +15 -0
  116. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-115-9a059e/minimal_patch_plan.md +21 -0
  117. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-115-9a059e/patch.diff +9 -0
  118. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-119-61557c/metadata.json +15 -0
  119. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-119-61557c/minimal_patch_plan.md +21 -0
  120. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-119-61557c/patch.diff +9 -0
  121. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-265-996ca3/metadata.json +15 -0
  122. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-265-996ca3/minimal_patch_plan.md +21 -0
  123. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-265-996ca3/patch.diff +9 -0
  124. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-334-cb819d/metadata.json +15 -0
  125. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-334-cb819d/minimal_patch_plan.md +21 -0
  126. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-334-cb819d/patch.diff +9 -0
  127. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-503-d11cf8/metadata.json +15 -0
  128. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-503-d11cf8/minimal_patch_plan.md +21 -0
  129. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-503-d11cf8/patch.diff +9 -0
  130. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-79-91f41f/metadata.json +15 -0
  131. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-79-91f41f/minimal_patch_plan.md +21 -0
  132. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-79-91f41f/patch.diff +9 -0
  133. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-107-516a40/metadata.json +15 -0
  134. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-107-516a40/minimal_patch_plan.md +21 -0
  135. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-107-516a40/patch.diff +9 -0
  136. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-128-7809a1/metadata.json +15 -0
  137. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-128-7809a1/minimal_patch_plan.md +21 -0
  138. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-128-7809a1/patch.diff +9 -0
  139. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-232-1b45d1/metadata.json +15 -0
  140. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-232-1b45d1/minimal_patch_plan.md +21 -0
  141. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-232-1b45d1/patch.diff +9 -0
  142. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-003-53-d167b4/metadata.json +15 -0
  143. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-003-53-d167b4/minimal_patch_plan.md +21 -0
  144. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-003-53-d167b4/patch.diff +9 -0
  145. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-209-4f6424/metadata.json +15 -0
  146. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-209-4f6424/minimal_patch_plan.md +21 -0
  147. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-209-4f6424/patch.diff +9 -0
  148. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-257-89bf34/metadata.json +15 -0
  149. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-257-89bf34/minimal_patch_plan.md +21 -0
  150. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-257-89bf34/patch.diff +9 -0
  151. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-341-ce228c/metadata.json +15 -0
  152. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-341-ce228c/minimal_patch_plan.md +21 -0
  153. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-341-ce228c/patch.diff +9 -0
  154. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-355-7b190b/metadata.json +15 -0
  155. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-355-7b190b/minimal_patch_plan.md +21 -0
  156. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-355-7b190b/patch.diff +9 -0
  157. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-64-5af31a/metadata.json +15 -0
  158. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-64-5af31a/minimal_patch_plan.md +21 -0
  159. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-64-5af31a/patch.diff +9 -0
  160. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-9-f51467/metadata.json +15 -0
  161. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-9-f51467/minimal_patch_plan.md +21 -0
  162. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-9-f51467/patch.diff +9 -0
  163. package/.torusguard/runs/run-20260908-113127-audit/findings.json +1520 -0
  164. package/.torusguard/runs/run-20260908-113127-audit/findings.md +560 -0
  165. package/.torusguard/runs/run-20260908-113127-audit/manifest.json +13 -0
  166. package/.torusguard/runs/run-20260908-113127-audit/remediation.md +262 -0
  167. package/.torusguard/runs/run-20260908-113127-audit/summary.md +5 -0
  168. package/.torusguard/runs/run-20260908-115240-audit/apply_plan.md +6 -0
  169. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-115-9a059e/metadata.json +15 -0
  170. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-115-9a059e/minimal_patch_plan.md +21 -0
  171. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-115-9a059e/patch.diff +9 -0
  172. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-119-61557c/metadata.json +15 -0
  173. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-119-61557c/minimal_patch_plan.md +21 -0
  174. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-119-61557c/patch.diff +9 -0
  175. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-265-996ca3/metadata.json +15 -0
  176. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-265-996ca3/minimal_patch_plan.md +21 -0
  177. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-265-996ca3/patch.diff +9 -0
  178. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-334-cb819d/metadata.json +15 -0
  179. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-334-cb819d/minimal_patch_plan.md +21 -0
  180. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-334-cb819d/patch.diff +9 -0
  181. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-503-d11cf8/metadata.json +15 -0
  182. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-503-d11cf8/minimal_patch_plan.md +21 -0
  183. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-503-d11cf8/patch.diff +9 -0
  184. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-79-91f41f/metadata.json +15 -0
  185. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-79-91f41f/minimal_patch_plan.md +21 -0
  186. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-79-91f41f/patch.diff +9 -0
  187. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-107-516a40/metadata.json +15 -0
  188. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-107-516a40/minimal_patch_plan.md +21 -0
  189. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-107-516a40/patch.diff +9 -0
  190. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-128-7809a1/metadata.json +15 -0
  191. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-128-7809a1/minimal_patch_plan.md +21 -0
  192. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-128-7809a1/patch.diff +9 -0
  193. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-232-1b45d1/metadata.json +15 -0
  194. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-232-1b45d1/minimal_patch_plan.md +21 -0
  195. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-232-1b45d1/patch.diff +9 -0
  196. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-003-53-d167b4/metadata.json +15 -0
  197. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-003-53-d167b4/minimal_patch_plan.md +21 -0
  198. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-003-53-d167b4/patch.diff +9 -0
  199. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-platform-001-168-5027cb/metadata.json +15 -0
  200. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-platform-001-168-5027cb/minimal_patch_plan.md +21 -0
  201. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-platform-001-168-5027cb/patch.diff +9 -0
  202. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-209-4f6424/metadata.json +15 -0
  203. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-209-4f6424/minimal_patch_plan.md +21 -0
  204. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-209-4f6424/patch.diff +9 -0
  205. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-257-89bf34/metadata.json +15 -0
  206. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-257-89bf34/minimal_patch_plan.md +21 -0
  207. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-257-89bf34/patch.diff +9 -0
  208. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-341-ce228c/metadata.json +15 -0
  209. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-341-ce228c/minimal_patch_plan.md +21 -0
  210. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-341-ce228c/patch.diff +9 -0
  211. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-355-7b190b/metadata.json +15 -0
  212. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-355-7b190b/minimal_patch_plan.md +21 -0
  213. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-355-7b190b/patch.diff +9 -0
  214. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-64-5af31a/metadata.json +15 -0
  215. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-64-5af31a/minimal_patch_plan.md +21 -0
  216. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-64-5af31a/patch.diff +9 -0
  217. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-9-f51467/metadata.json +15 -0
  218. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-9-f51467/minimal_patch_plan.md +21 -0
  219. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-9-f51467/patch.diff +9 -0
  220. package/.torusguard/runs/run-20260908-115240-audit/diff_summary.md +221 -0
  221. package/.torusguard/runs/run-20260908-115240-audit/findings.json +1553 -0
  222. package/.torusguard/runs/run-20260908-115240-audit/findings.md +572 -0
  223. package/.torusguard/runs/run-20260908-115240-audit/manifest.json +14 -0
  224. package/.torusguard/runs/run-20260908-115240-audit/recheck.md +91 -0
  225. package/.torusguard/runs/run-20260908-115240-audit/remediation.md +278 -0
  226. package/.torusguard/runs/run-20260908-115240-audit/summary.md +5 -0
  227. package/.torusguard/scripts/__pycache__/audit_runner.cpython-311.pyc +0 -0
  228. package/.torusguard/scripts/__pycache__/finding_scorer.cpython-311.pyc +0 -0
  229. package/.torusguard/scripts/__pycache__/memory_engine.cpython-311.pyc +0 -0
  230. package/.torusguard/scripts/__pycache__/monorepo_detector.cpython-311.pyc +0 -0
  231. package/.torusguard/scripts/__pycache__/run_manager.cpython-311.pyc +0 -0
  232. package/.torusguard/scripts/__pycache__/stack_detect.cpython-311.pyc +0 -0
  233. package/.torusguard/scripts/apply_runner.py +339 -0
  234. package/.torusguard/scripts/audit_runner.py +550 -0
  235. package/.torusguard/scripts/diff_guard.py +52 -4
  236. package/.torusguard/scripts/finding_scorer.py +58 -0
  237. package/.torusguard/scripts/harden_runner.py +375 -0
  238. package/.torusguard/scripts/html_reporter.py +25 -10
  239. package/.torusguard/scripts/manifest_builder.py +2 -0
  240. package/.torusguard/scripts/memory_engine.py +4 -0
  241. package/.torusguard/scripts/recheck_runner.py +221 -0
  242. package/.torusguard/scripts/recipes_runner.py +130 -0
  243. package/.torusguard/scripts/run_manager.py +17 -5
  244. package/.torusguard/skills/torusguard/SKILL.md +42 -42
  245. package/.torusguard/skills/torusguard/bootstrap.py +149 -70
  246. package/.torusguard/snapshots/run-20260908-115240-audit/examples/vulnerable-react-express/client/src/App.jsx.bak +63 -0
  247. package/.torusguard/snapshots/run-20260908-115240-audit/examples/vulnerable-react-express/server/index.js.bak +82 -0
  248. package/.torusguard/snapshots/run-20260908-115240-audit/harness/engine/fixture_manager.py.bak +245 -0
  249. package/.torusguard/snapshots/run-20260908-115240-audit/harness/master_validation.py.bak +698 -0
  250. package/.torusguard/snapshots/run-20260908-115240-audit/harness/runner.py.bak +551 -0
  251. package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_e2e.py.bak +498 -0
  252. package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_qa_v0_6_0.py.bak +572 -0
  253. package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v0_6_1_scale.py.bak +371 -0
  254. package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v0_6_2_modern_stacks.py.bak +462 -0
  255. package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v0_6_3_hardening.py.bak +444 -0
  256. package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v1_0_0_memory.py.bak +302 -0
  257. package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v1_1_0_advanced_memory.py.bak +342 -0
  258. package/.torusguard/snapshots/run-20260908-115240-audit/skills/torusguard/payload/scripts/harden_runner.py.bak +353 -0
  259. package/.torusguard/snapshots/run-20260908-115240-audit/tests/test_v0_6_0_governed_remediation.py.bak +353 -0
  260. package/README.md +70 -33
  261. package/bin/torusguard.js +92 -22
  262. package/package.json +1 -1
  263. package/skills/torusguard/SKILL.md +42 -42
  264. package/skills/torusguard/bootstrap.py +147 -68
  265. package/skills/torusguard/payload/.manifest.json +113 -9
  266. package/skills/torusguard/payload/rules/README.md +93 -62
  267. package/skills/torusguard/payload/rules/TG-AUTH-001-weak-password-storage.md +103 -0
  268. package/skills/torusguard/payload/rules/TG-AUTH-002-client-only-authorization.md +85 -0
  269. package/skills/torusguard/payload/rules/TG-AUTH-003-missing-object-authorization.md +85 -0
  270. package/skills/torusguard/payload/rules/TG-AUTH-004-insecure-session-cookie.md +96 -0
  271. package/skills/torusguard/payload/rules/TG-AUTH-005-unsafe-password-reset.md +104 -0
  272. package/skills/torusguard/payload/rules/TG-CLIENT-001-public-production-source-maps.md +102 -0
  273. package/skills/torusguard/payload/rules/TG-CLIENT-002-sensitive-client-bundle-content.md +102 -0
  274. package/skills/torusguard/payload/rules/TG-DB-001-frontend-database-query.md +83 -0
  275. package/skills/torusguard/payload/rules/TG-DB-002-privileged-database-credential.md +86 -0
  276. package/skills/torusguard/payload/rules/TG-DB-003-frontend-admin-sdk.md +91 -0
  277. package/skills/torusguard/payload/rules/TG-DB-004-missing-tenant-query-isolation.md +103 -0
  278. package/skills/torusguard/payload/rules/TG-INPUT-001-missing-server-validation.md +98 -0
  279. package/skills/torusguard/payload/rules/TG-INPUT-002-raw-sql-concatenation.md +94 -0
  280. package/skills/torusguard/payload/rules/TG-INPUT-003-unsafe-html-or-code-execution.md +102 -0
  281. package/skills/torusguard/payload/rules/TG-INPUT-004-unrestricted-file-upload.md +92 -0
  282. package/skills/torusguard/payload/rules/TG-INPUT-005-unsafe-template-rendering-and-escaping.md +102 -0
  283. package/skills/torusguard/payload/rules/TG-INPUT-006-unsafe-file-path-traversal.md +131 -0
  284. package/skills/torusguard/payload/rules/TG-PLATFORM-001-wildcard-cors-with-credentials.md +101 -0
  285. package/skills/torusguard/payload/rules/TG-PLATFORM-002-missing-security-headers.md +95 -0
  286. package/skills/torusguard/payload/rules/TG-PLATFORM-003-production-stack-trace-exposure.md +94 -0
  287. package/skills/torusguard/payload/rules/TG-PLATFORM-004-missing-request-size-limits.md +102 -0
  288. package/skills/torusguard/payload/rules/TG-RATE-001-unlimited-auth-endpoint.md +112 -0
  289. package/skills/torusguard/payload/rules/TG-RATE-002-unlimited-public-write-endpoint.md +109 -0
  290. package/skills/torusguard/payload/rules/TG-RATE-003-unbounded-resource-consumption.md +105 -0
  291. package/skills/torusguard/payload/rules/TG-SEC-001-hardcoded-secrets.md +83 -0
  292. package/skills/torusguard/payload/rules/TG-SEC-002-public-environment-secrets.md +83 -0
  293. package/skills/torusguard/payload/rules/TG-SEC-003-tracked-env-file.md +79 -0
  294. package/skills/torusguard/payload/rules/TG-SEC-004-sensitive-logging.md +83 -0
  295. package/skills/torusguard/payload/rules/active/TG-AUTH-001-weak-password-storage.md +103 -0
  296. package/skills/torusguard/payload/rules/active/TG-AUTH-002-client-only-authorization.md +85 -0
  297. package/skills/torusguard/payload/rules/active/TG-AUTH-003-missing-object-authorization.md +85 -0
  298. package/skills/torusguard/payload/rules/active/TG-AUTH-004-insecure-session-cookie.md +96 -0
  299. package/skills/torusguard/payload/rules/active/TG-AUTH-005-unsafe-password-reset.md +104 -0
  300. package/skills/torusguard/payload/rules/active/TG-CLIENT-001-public-production-source-maps.md +102 -0
  301. package/skills/torusguard/payload/rules/active/TG-CLIENT-002-sensitive-client-bundle-content.md +102 -0
  302. package/skills/torusguard/payload/rules/active/TG-DB-001-frontend-database-query.md +83 -0
  303. package/skills/torusguard/payload/rules/active/TG-DB-002-privileged-database-credential.md +86 -0
  304. package/skills/torusguard/payload/rules/active/TG-DB-003-frontend-admin-sdk.md +91 -0
  305. package/skills/torusguard/payload/rules/active/TG-DB-004-missing-tenant-query-isolation.md +103 -0
  306. package/skills/torusguard/payload/rules/active/TG-INPUT-001-missing-server-validation.md +98 -0
  307. package/skills/torusguard/payload/rules/active/TG-INPUT-002-raw-sql-concatenation.md +94 -0
  308. package/skills/torusguard/payload/rules/active/TG-INPUT-003-unsafe-html-or-code-execution.md +102 -0
  309. package/skills/torusguard/payload/rules/active/TG-INPUT-004-unrestricted-file-upload.md +92 -0
  310. package/skills/torusguard/payload/rules/active/TG-INPUT-005-unsafe-template-rendering-and-escaping.md +102 -0
  311. package/skills/torusguard/payload/rules/active/TG-INPUT-006-unsafe-file-path-traversal.md +131 -0
  312. package/skills/torusguard/payload/rules/active/TG-PLATFORM-001-wildcard-cors-with-credentials.md +101 -0
  313. package/skills/torusguard/payload/rules/active/TG-PLATFORM-002-missing-security-headers.md +95 -0
  314. package/skills/torusguard/payload/rules/active/TG-PLATFORM-003-production-stack-trace-exposure.md +94 -0
  315. package/skills/torusguard/payload/rules/active/TG-PLATFORM-004-missing-request-size-limits.md +102 -0
  316. package/skills/torusguard/payload/rules/active/TG-RATE-001-unlimited-auth-endpoint.md +112 -0
  317. package/skills/torusguard/payload/rules/active/TG-RATE-002-unlimited-public-write-endpoint.md +109 -0
  318. package/skills/torusguard/payload/rules/active/TG-RATE-003-unbounded-resource-consumption.md +105 -0
  319. package/skills/torusguard/payload/rules/active/TG-SEC-001-hardcoded-secrets.md +83 -0
  320. package/skills/torusguard/payload/rules/active/TG-SEC-002-public-environment-secrets.md +83 -0
  321. package/skills/torusguard/payload/rules/active/TG-SEC-003-tracked-env-file.md +79 -0
  322. package/skills/torusguard/payload/rules/active/TG-SEC-004-sensitive-logging.md +83 -0
  323. package/skills/torusguard/payload/rules/agent/TG-AGENT-001-prompt-injection-system-context.md +56 -0
  324. package/skills/torusguard/payload/rules/agent/TG-AGENT-002-unsafe-tool-dispatch-unsandboxed-execution.md +68 -0
  325. package/skills/torusguard/payload/rules/agent/TG-AGENT-003-broad-mcp-tool-scoping.md +53 -0
  326. package/skills/torusguard/payload/rules/agent/TG-AGENT-004-persistent-memory-cross-session-leakage.md +67 -0
  327. package/skills/torusguard/payload/rules/authorization/TG-AUTH-006-mass-assignment.md +70 -0
  328. package/skills/torusguard/payload/rules/authorization/TG-AUTH-007-missing-property-level-authorization.md +71 -0
  329. package/skills/torusguard/payload/rules/authorization/TG-AUTH-008-untrusted-role-header-injection.md +112 -0
  330. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-001-client-controlled-sensitive-business-value.md +37 -0
  331. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-002-replayable-one-time-operation.md +37 -0
  332. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-003-missing-workflow-state-validation.md +37 -0
  333. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-004-unrestricted-sensitive-business-flow.md +37 -0
  334. package/skills/torusguard/payload/rules/cache/TG-CACHE-001-sensitive-response-publicly-cacheable.md +37 -0
  335. package/skills/torusguard/payload/rules/cache/TG-CACHE-002-missing-user-cache-isolation.md +37 -0
  336. package/skills/torusguard/payload/rules/cache/TG-CACHE-003-sensitive-data-in-url.md +37 -0
  337. package/skills/torusguard/payload/rules/csrf/TG-CSRF-001-missing-csrf-protection.md +37 -0
  338. package/skills/torusguard/payload/rules/csrf/TG-CSRF-002-unsafe-credentialed-cross-origin-request.md +37 -0
  339. package/skills/torusguard/payload/rules/edge/TG-EDGE-001-serverless-global-state-leak.md +83 -0
  340. package/skills/torusguard/payload/rules/edge/TG-EDGE-003-aws-lambda-ephemeral-cold-start.md +76 -0
  341. package/skills/torusguard/payload/rules/graphql/TG-GQL-001-missing-query-depth-or-complexity-limits.md +64 -0
  342. package/skills/torusguard/payload/rules/graphql/TG-GQL-002-resolver-missing-authorization.md +37 -0
  343. package/skills/torusguard/payload/rules/graphql/TG-GQL-003-unbounded-graphql-pagination-or-batching.md +37 -0
  344. package/skills/torusguard/payload/rules/graphql/TG-GQL-004-unnecessary-production-introspection.md +37 -0
  345. package/skills/torusguard/payload/rules/secrets/TG-SEC-005-secret-in-git-history.md +37 -0
  346. package/skills/torusguard/payload/rules/secrets/TG-SEC-006-secret-in-build-artifact.md +37 -0
  347. package/skills/torusguard/payload/rules/secrets/TG-SEC-007-secret-in-test-or-example-fixture.md +37 -0
  348. package/skills/torusguard/payload/rules/ssrf/TG-SSRF-001-user-controlled-server-side-url-fetch.md +68 -0
  349. package/skills/torusguard/payload/rules/ssrf/TG-SSRF-002-missing-internal-network-protection.md +37 -0
  350. package/skills/torusguard/payload/rules/ssrf/TG-SSRF-003-unsafe-redirect-following.md +37 -0
  351. package/skills/torusguard/payload/rules/ssrf/TG-SSRF-004-unbounded-outbound-request.md +37 -0
  352. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-001-missing-or-ignored-dependency-lockfile.md +37 -0
  353. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-002-vulnerable-dependency-review-missing.md +94 -0
  354. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-003-unsafe-ci-cd-secret-exposure.md +37 -0
  355. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-004-unpinned-ci-action.md +37 -0
  356. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-005-unsafe-dependency-install-script.md +37 -0
  357. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-006-container-build-secret-persistence.md +61 -0
  358. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-001-missing-webhook-signature-verification.md +37 -0
  359. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-002-replayable-webhook.md +37 -0
  360. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-003-missing-webhook-idempotency.md +37 -0
  361. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-004-unvalidated-webhook-event-type.md +37 -0
  362. package/skills/torusguard/payload/rules/websocket/TG-WS-001-unauthenticated-websocket-handshake.md +82 -0
  363. package/skills/torusguard/payload/rules/websocket/TG-WS-002-missing-channel-level-authorization.md +37 -0
  364. package/skills/torusguard/payload/rules/websocket/TG-WS-003-unvalidated-websocket-message.md +37 -0
  365. package/skills/torusguard/payload/rules/websocket/TG-WS-004-unbounded-websocket-connections.md +37 -0
  366. package/skills/torusguard/payload/scripts/apply_runner.py +339 -0
  367. package/skills/torusguard/payload/scripts/audit_runner.py +550 -0
  368. package/skills/torusguard/payload/scripts/diff_guard.py +52 -4
  369. package/skills/torusguard/payload/scripts/finding_scorer.py +58 -0
  370. package/skills/torusguard/payload/scripts/harden_runner.py +375 -0
  371. package/skills/torusguard/payload/scripts/html_reporter.py +25 -10
  372. package/skills/torusguard/payload/scripts/manifest_builder.py +2 -0
  373. package/skills/torusguard/payload/scripts/memory_engine.py +4 -0
  374. package/skills/torusguard/payload/scripts/recheck_runner.py +221 -0
  375. package/skills/torusguard/payload/scripts/recipes_runner.py +130 -0
  376. package/skills/torusguard/payload/scripts/run_manager.py +17 -5
  377. package/skills/torusguard/payload/skills/torusguard/SKILL.md +42 -42
  378. package/skills/torusguard/payload/skills/torusguard/bootstrap.py +147 -68
@@ -0,0 +1,353 @@
1
+ """
2
+ TorusGuard v0.6.0 Governed Remediation Test Suite
3
+ Tests:
4
+ 1. Run Folder System & Manifest Generation
5
+ 2. Stable Finding Identity Across Line Shifts
6
+ 3. Root-Cause Clustering across Django, FastAPI, Flask, SQLAlchemy
7
+ 4. Structured Remediation Bundle Generation
8
+ 5. Minimal Patch Governance (Line churn, file count, high-risk escalation)
9
+ 6. Targeted Recheck Status Transitions (Confirmed Fixed, Partially Fixed, Regressed, Needs Manual Review)
10
+ 7. SARIF v2.1.0 JSON Structured Export
11
+ 8. End-to-End v0.6.0 Governed Remediation Workflow Execution
12
+ """
13
+
14
+ import unittest
15
+ import tempfile
16
+ import shutil
17
+ import json
18
+ import sys
19
+ from pathlib import Path
20
+
21
+ # Add project root to sys.path
22
+ sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
23
+
24
+ from core.identity import IdentityEngine, FindingFingerprint
25
+ from core.clustering import ClusteringEngine, RootCauseCluster
26
+ from core.bundle import BundleManager, RemediationBundle
27
+ from core.governance import PatchGovernor, PatchPolicyDecision
28
+ from core.rechecker import TargetedRechecker, TargetedRecheckResult, RecheckOutcome
29
+ from core.run_manager import RunManager
30
+ from core.sarif import SarifExporter
31
+ from core.v6_workflow import V6Workflow
32
+
33
+
34
+ class TestTorusGuardV060(unittest.TestCase):
35
+
36
+ def setUp(self):
37
+ self.test_dir = Path(tempfile.mkdtemp(prefix="torusguard-v0-6-test-"))
38
+
39
+ def tearDown(self):
40
+ shutil.rmtree(self.test_dir, ignore_errors=True)
41
+
42
+ def test_run_folder_creation_and_manifest(self):
43
+ """Verify RunManager initializes isolated run folder with all standard artifacts."""
44
+ run_mgr = RunManager(
45
+ base_dir=self.test_dir,
46
+ target_name="django-core",
47
+ command="audit",
48
+ run_id="run-20260831-test-01"
49
+ )
50
+ self.assertTrue(run_mgr.run_path.exists())
51
+ self.assertTrue(run_mgr.logs_dir.exists())
52
+ self.assertTrue(run_mgr.patches_dir.exists())
53
+ self.assertTrue(run_mgr.bundles_dir.exists())
54
+
55
+ # Write manifest and verify
56
+ run_mgr.write_manifest(
57
+ status_counts={
58
+ "total_findings": 2,
59
+ "confirmed": 1,
60
+ "high_confidence": 1,
61
+ "needs_review": 0,
62
+ "remediated": 0,
63
+ "verified_fixed": 0,
64
+ "regressed": 0,
65
+ }
66
+ )
67
+ self.assertTrue(run_mgr.manifest_file.exists())
68
+ with open(run_mgr.manifest_file, "r", encoding="utf-8") as f:
69
+ data = json.load(f)
70
+ self.assertEqual(data["version"], "v0.6.3")
71
+ self.assertEqual(data["run_id"], "run-20260831-test-01")
72
+ self.assertEqual(data["status_counts"]["total_findings"], 2)
73
+
74
+ def test_stable_finding_identity_across_line_shifts(self):
75
+ """Verify Finding Fingerprint remains stable when comments or surrounding lines shift."""
76
+ code_v1 = """
77
+ def get_invoice(request, invoice_id):
78
+ # Fetch invoice directly without tenant filter
79
+ invoice = Invoice.objects.get(id=invoice_id)
80
+ return JsonResponse({"id": invoice.id})
81
+ """
82
+ code_v2_shifted = """
83
+ # Added extra docstring at the top of file
84
+ # Lines shifted down by 10 lines
85
+ def get_invoice(request, invoice_id):
86
+ invoice = Invoice.objects.get(id=invoice_id)
87
+ return JsonResponse({"id": invoice.id})
88
+ """
89
+
90
+ fp1 = IdentityEngine.generate_identity(
91
+ rule_id="TG-DB-004",
92
+ file_path="invoices/views.py",
93
+ code_snippet=code_v1,
94
+ sink_signature="Invoice.objects.get",
95
+ framework_marker="django",
96
+ )
97
+ fp2 = IdentityEngine.generate_identity(
98
+ rule_id="TG-DB-004",
99
+ file_path="invoices/views.py",
100
+ code_snippet=code_v2_shifted,
101
+ sink_signature="Invoice.objects.get",
102
+ framework_marker="django",
103
+ )
104
+
105
+ self.assertEqual(fp1.fingerprint_id, fp2.fingerprint_id)
106
+ self.assertEqual(fp1.region_hash, fp2.region_hash)
107
+ self.assertTrue(fp1.fingerprint_id.startswith("TG-DB-"))
108
+
109
+ def test_root_cause_clustering(self):
110
+ """Verify grouping of disparate findings into systemic root-cause clusters."""
111
+ findings = [
112
+ {
113
+ "finding_id": "fnd-01",
114
+ "rule_id": "TG-DB-004",
115
+ "title": "Missing Tenant Filter",
116
+ "severity": "High",
117
+ "target": {"file_path": "backend/api/users.py", "line_start": 20, "line_end": 25},
118
+ },
119
+ {
120
+ "finding_id": "fnd-02",
121
+ "rule_id": "TG-DB-004",
122
+ "title": "Missing Tenant Filter on Invoices",
123
+ "severity": "Critical",
124
+ "target": {"file_path": "backend/api/invoices.py", "line_start": 45, "line_end": 50},
125
+ },
126
+ {
127
+ "finding_id": "fnd-03",
128
+ "rule_id": "TG-INPUT-006",
129
+ "title": "Unsafe Upload Path",
130
+ "severity": "High",
131
+ "target": {"file_path": "backend/services/uploader.py", "line_start": 12, "line_end": 18},
132
+ }
133
+ ]
134
+
135
+ clusters = ClusteringEngine.cluster_findings(findings)
136
+ self.assertEqual(len(clusters), 2)
137
+
138
+ cluster_map = {c.cluster_id: c for c in clusters}
139
+ self.assertIn("cluster-tenant-isolation", cluster_map)
140
+ self.assertIn("cluster-path-traversal", cluster_map)
141
+
142
+ tenant_cluster = cluster_map["cluster-tenant-isolation"]
143
+ self.assertEqual(len(tenant_cluster.finding_ids), 2)
144
+ self.assertEqual(len(tenant_cluster.affected_files), 2)
145
+ self.assertEqual(tenant_cluster.risk_severity, "Critical")
146
+
147
+ def test_remediation_bundle_generation(self):
148
+ """Verify structured remediation bundle creates all 5 expected artifacts."""
149
+ finding = {
150
+ "finding_id": "TG-AUTH-008-abc123",
151
+ "rule_id": "TG-AUTH-008",
152
+ "title": "Untrusted Role Header Injection",
153
+ "severity": "High",
154
+ "target": {"file_path": "middleware/auth.py"},
155
+ "what_is_wrong": "Role is read directly from unauthenticated header X-Role.",
156
+ "why_it_matters": "Allows unprivileged users to escalate to Admin role.",
157
+ "what_should_change": "Derive role from verified JWT session payload.",
158
+ "proposed_diff": "--- a/middleware/auth.py\n+++ b/middleware/auth.py\n@@ -1,2 +1,2 @@\n-role = req.headers.get('X-Role')\n+role = req.user.role\n",
159
+ "verification_steps": "Send X-Role header and assert 403 Forbidden.",
160
+ }
161
+
162
+ bundle = BundleManager.create_bundle(finding, cluster_id="cluster-header-trust")
163
+ bundle_dir = bundle.write_to_directory(self.test_dir)
164
+
165
+ self.assertTrue((bundle_dir / "finding.md").exists())
166
+ self.assertTrue((bundle_dir / "remediation.md").exists())
167
+ self.assertTrue((bundle_dir / "minimal_patch_plan.md").exists())
168
+ self.assertTrue((bundle_dir / "verify-after-change.md").exists())
169
+ self.assertTrue((bundle_dir / "metadata.json").exists())
170
+
171
+ with open(bundle_dir / "metadata.json", "r", encoding="utf-8") as f:
172
+ meta = json.load(f)
173
+ self.assertEqual(meta["bundle_id"], "bundle-TG-AUTH-008-abc123")
174
+ self.assertEqual(meta["cluster_id"], "cluster-header-trust")
175
+
176
+ def test_minimal_patch_governance(self):
177
+ """Verify governance policy checks on line churn, file limits, and high-risk escalation."""
178
+ governor = PatchGovernor(max_additions_per_file=15, max_deletions_per_file=10)
179
+
180
+ # 1. Clean minimal patch
181
+ clean_diff = """--- a/services/helper.py
182
+ +++ b/services/helper.py
183
+ @@ -10,3 +10,3 @@
184
+ -val = raw_input
185
+ +val = sanitize(raw_input)
186
+ """
187
+ decision_clean = governor.evaluate_diff(clean_diff, "services/helper.py")
188
+ self.assertTrue(decision_clean.allowed_auto_apply)
189
+ self.assertFalse(decision_clean.escalation_required)
190
+ self.assertEqual(decision_clean.line_additions, 1)
191
+
192
+ # 2. Oversized patch (exceeds line additions)
193
+ oversized_lines = ["--- a/services/helper.py", "+++ b/services/helper.py"]
194
+ for i in range(25):
195
+ oversized_lines.append(f"+line_{i} = True")
196
+ oversized_diff = "\n".join(oversized_lines)
197
+
198
+ decision_oversized = governor.evaluate_diff(oversized_diff, "services/helper.py")
199
+ self.assertFalse(decision_oversized.allowed_auto_apply)
200
+ self.assertTrue(any("exceed threshold" in r for r in decision_oversized.rejection_reasons))
201
+
202
+ # 3. High-risk context (touching auth file with non-trivial churn)
203
+ high_risk_lines = ["--- a/backend/auth/login.py", "+++ b/backend/auth/login.py"]
204
+ for i in range(12):
205
+ high_risk_lines.append(f"+auth_check_{i}()")
206
+ high_risk_diff = "\n".join(high_risk_lines)
207
+
208
+ decision_high_risk = governor.evaluate_diff(high_risk_diff, "backend/auth/login.py")
209
+ self.assertTrue(decision_high_risk.escalation_required)
210
+ self.assertFalse(decision_high_risk.allowed_auto_apply)
211
+
212
+ def test_targeted_recheck_outcomes(self):
213
+ """Verify recheck transitions: Confirmed Fixed, Regressed, Needs Manual Review."""
214
+ # 1. Confirmed Fixed
215
+ res_fixed = TargetedRechecker.verify_finding(
216
+ finding_id="fnd-01",
217
+ rule_id="TG-DB-004",
218
+ target_file="models/query.py",
219
+ original_code_snippet="return Model.objects.all()",
220
+ post_fix_code_snippet="return Model.objects.filter(tenant=request.tenant)",
221
+ is_safe_pattern_present=True,
222
+ is_unsafe_pattern_present=False,
223
+ )
224
+ self.assertEqual(res_fixed.outcome, RecheckOutcome.CONFIRMED_FIXED)
225
+ self.assertEqual(len(res_fixed.regressions_detected), 0)
226
+
227
+ # 2. Regressed (introduced new vulnerability)
228
+ res_regressed = TargetedRechecker.verify_finding(
229
+ finding_id="fnd-02",
230
+ rule_id="TG-INPUT-006",
231
+ target_file="views/upload.py",
232
+ original_code_snippet="file.save(filename)",
233
+ post_fix_code_snippet="os.system(f'cp {filename} /tmp')",
234
+ is_safe_pattern_present=False,
235
+ is_unsafe_pattern_present=True,
236
+ introduced_new_flaws=["TG-CMD-001: Command Injection in upload handler"],
237
+ )
238
+ self.assertEqual(res_regressed.outcome, RecheckOutcome.REGRESSED)
239
+ self.assertIn("Command Injection", res_regressed.regressions_detected[0])
240
+
241
+ # 3. Needs Manual Review
242
+ res_manual = TargetedRechecker.verify_finding(
243
+ finding_id="fnd-03",
244
+ rule_id="TG-WEBHOOK-001",
245
+ target_file="webhooks/receiver.py",
246
+ original_code_snippet="verify_sig()",
247
+ post_fix_code_snippet="verify_sig()",
248
+ requires_manual_context=True,
249
+ )
250
+ self.assertEqual(res_manual.outcome, RecheckOutcome.NEEDS_MANUAL_REVIEW)
251
+
252
+ def test_sarif_v210_export(self):
253
+ """Verify valid SARIF v2.1.0 output structure and stable fingerprints."""
254
+ findings = [
255
+ {
256
+ "finding_id": "TG-DB-123456",
257
+ "fingerprint_id": "TG-DB-123456",
258
+ "rule_id": "TG-DB-004",
259
+ "title": "Missing Tenant Query Isolation",
260
+ "severity": "High",
261
+ "confidence_score": 95,
262
+ "confidence_band": "Confirmed",
263
+ "cluster_id": "cluster-tenant-isolation",
264
+ "target": {"file_path": "backend/models.py", "line_start": 40, "line_end": 45},
265
+ "evidence": {"code_snippet": "return self.query()"},
266
+ }
267
+ ]
268
+
269
+ sarif_obj = SarifExporter.generate_sarif(findings, tool_version="6.0.0")
270
+ self.assertEqual(sarif_obj["version"], "2.1.0")
271
+ self.assertEqual(len(sarif_obj["runs"]), 1)
272
+
273
+ driver = sarif_obj["runs"][0]["tool"]["driver"]
274
+ self.assertEqual(driver["name"], "TorusGuard")
275
+ self.assertEqual(driver["semanticVersion"], "6.0.0")
276
+
277
+ result = sarif_obj["runs"][0]["results"][0]
278
+ self.assertEqual(result["ruleId"], "TG-DB-004")
279
+ self.assertEqual(result["level"], "error")
280
+ self.assertEqual(result["fingerprints"]["torusguard/v6/stable_identity"], "TG-DB-123456")
281
+
282
+ def test_end_to_end_v6_workflow(self):
283
+ """Verify full end-to-end v6 workflow: audit -> harden -> apply -> recheck."""
284
+ workflow = V6Workflow(
285
+ target_root=self.test_dir,
286
+ output_base=self.test_dir / "runs",
287
+ )
288
+
289
+ raw_findings = [
290
+ {
291
+ "rule_id": "TG-INPUT-006",
292
+ "title": "Unsafe File Path Traversal",
293
+ "severity": "High",
294
+ "confidence_score": 92,
295
+ "confidence_band": "Confirmed",
296
+ "target": {"file_path": "uploader.py", "line_start": 10, "line_end": 15},
297
+ "evidence": {"code_snippet": "open(os.path.join(DIR, filename), 'wb')"},
298
+ "what_is_wrong": "Filename from client is not sanitized with secure_filename().",
299
+ "what_should_change": "Sanitize with werkzeug secure_filename.",
300
+ "proposed_diff": "--- a/uploader.py\n+++ b/uploader.py\n@@ -1,2 +1,2 @@\n-path = os.path.join(DIR, filename)\n+path = os.path.join(DIR, secure_filename(filename))\n",
301
+ "verification_steps": "Send ../etc/passwd in filename parameter.",
302
+ }
303
+ ]
304
+
305
+ # 1. Audit Phase
306
+ run_mgr = workflow.execute_audit(
307
+ raw_findings=raw_findings,
308
+ target_name="flask-uploader",
309
+ run_id="run-e2e-01",
310
+ export_sarif=True,
311
+ )
312
+ self.assertTrue(run_mgr.manifest_file.exists())
313
+ self.assertTrue(run_mgr.summary_file.exists())
314
+ self.assertTrue(run_mgr.findings_file.exists())
315
+ self.assertTrue(run_mgr.sarif_file.exists())
316
+
317
+ # 2. Harden Phase
318
+ with open(run_mgr.manifest_file, "r", encoding="utf-8") as f:
319
+ manifest_data = json.load(f)
320
+ self.assertEqual(manifest_data["status_counts"]["total_findings"], 1)
321
+
322
+ bundles = workflow.execute_harden(run_mgr, raw_findings)
323
+ self.assertEqual(len(bundles), 1)
324
+ self.assertTrue(run_mgr.remediation_file.exists())
325
+
326
+ # 3. Apply Phase
327
+ decisions = workflow.execute_apply(run_mgr, bundles)
328
+ self.assertEqual(len(decisions), 1)
329
+ self.assertTrue(decisions[0][1].allowed_auto_apply)
330
+ self.assertTrue(run_mgr.apply_plan_file.exists())
331
+ self.assertTrue(run_mgr.diff_summary_file.exists())
332
+ self.assertTrue(run_mgr.changed_files_file.exists())
333
+
334
+ # 4. Recheck Phase
335
+ recheck_scenarios = [
336
+ {
337
+ "finding_id": bundles[0].finding_id,
338
+ "rule_id": "TG-INPUT-006",
339
+ "target_file": "uploader.py",
340
+ "orig_snippet": "path = os.path.join(DIR, filename)",
341
+ "post_snippet": "path = os.path.join(DIR, secure_filename(filename))",
342
+ "is_safe": True,
343
+ "is_unsafe": False,
344
+ }
345
+ ]
346
+ recheck_results = workflow.execute_recheck(run_mgr, recheck_scenarios)
347
+ self.assertEqual(len(recheck_results), 1)
348
+ self.assertEqual(recheck_results[0].outcome, RecheckOutcome.CONFIRMED_FIXED)
349
+ self.assertTrue(run_mgr.recheck_file.exists())
350
+
351
+
352
+ if __name__ == "__main__":
353
+ unittest.main()
package/README.md CHANGED
@@ -5,14 +5,14 @@
5
5
 
6
6
  **Autonomous Security Guardrails, Governed Remediation, and Authorized Runtime Validation for AI-Built Web Applications.**
7
7
 
8
- [![npm version](https://img.shields.io/npm/v/torusguard.svg?style=flat-square&color=cb3837&logo=npm)](https://www.npmjs.com/package/torusguard)
9
- [![GitHub Packages](https://img.shields.io/badge/GitHub%20Packages-v1.3.0-181717.svg?style=flat-square&logo=github)](https://github.com/githubmofo/TorusGuard/pkgs/npm/torusguard)
10
- [![Release](https://img.shields.io/badge/Release-v1.3.0-blue.svg?style=flat-square)](https://github.com/githubmofo/TorusGuard/releases/latest)
8
+ [![npm version](https://img.shields.io/badge/npm-v1.3.2-cb3837.svg?style=flat-square&logo=npm)](https://www.npmjs.com/package/torusguard)
9
+ [![GitHub Packages](https://img.shields.io/badge/GitHub%20Packages-v1.3.2-181717.svg?style=flat-square&logo=github)](https://github.com/githubmofo/TorusGuard/pkgs/npm/torusguard)
10
+ [![Release](https://img.shields.io/badge/Release-v1.3.2-blue.svg?style=flat-square)](https://github.com/githubmofo/TorusGuard/releases/latest)
11
11
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg?style=flat-square)](LICENSE)
12
12
  [![Python 3.10+](https://img.shields.io/badge/Python-3.10%2B-blue.svg?style=flat-square&logo=python&logoColor=white)](https://python.org)
13
13
  [![Node.js 18+](https://img.shields.io/badge/Node.js-18%2B-339933.svg?style=flat-square&logo=node.js&logoColor=white)](https://nodejs.org)
14
14
  [![SARIF: v2.1.0](https://img.shields.io/badge/SARIF-v2.1.0%20OASIS-purple.svg?style=flat-square)](.torusguard/schemas/)
15
- [![Integrity: SHA--256](https://img.shields.io/badge/Integrity-SHA--256%20(112%20Files)-teal.svg?style=flat-square)](.torusguard/.manifest.json)
15
+ [![Integrity: SHA--256](https://img.shields.io/badge/Integrity-SHA--256%20(216%20Files)-teal.svg?style=flat-square)](.torusguard/.manifest.json)
16
16
  [![OWASP: Top 10](https://img.shields.io/badge/OWASP-Top%2010%20Aligned-orange.svg?style=flat-square)](docs/architecture/SECURITY_ARCHITECTURE.md)
17
17
  </div>
18
18
 
@@ -100,20 +100,20 @@ flowchart TD
100
100
 
101
101
  ---
102
102
 
103
- ### 2. The 7-Stage Finding Lifecycle
104
- Every finding follows a strict closed-loop state machine with an unskippable **Human Gate** and rollback backup before disk modifications:
103
+ ### 2. The 7-Stage Finding Lifecycle (Dual-Strategy Governance)
104
+ Every finding follows a strict closed-loop state machine supported equally via **Terminal CLI** (`npx torusguard ...`) and **AI Chat Workflows** (`/torusguard-...`) with an unskippable **Human Gate** and automatic `.bak` snapshots before disk modification:
105
105
 
106
106
  ```mermaid
107
107
  flowchart LR
108
- Detect["1. DETECT<br/>Static AST Signal"] --> Classify["2. CLASSIFY<br/>0–100 Confidence"]
109
- Classify --> Verify["3. VERIFY<br/>Authorized Probe"]
110
- Verify --> Remediate["4. REMEDIATE<br/>Ponytail Patch Plan"]
111
- Remediate --> Gate{"👤 Human Gate<br/>Approved?"}
112
- Gate -- Yes --> Apply["5. APPLY<br/>Backup &amp; Surgical Patch"]
108
+ Detect["1. DETECT<br/>Static AST Signal<br/><code>audit · /audit</code>"] --> Classify["2. CLASSIFY<br/>0–100 Confidence"]
109
+ Classify --> Verify["3. VERIFY<br/>Authorized Probe<br/><code>verify · /verify</code>"]
110
+ Verify --> Remediate["4. REMEDIATE<br/>Ponytail Patch Plan<br/><code>harden · /harden</code>"]
111
+ Remediate --> Gate{"👤 Human Gate<br/>Approved? [y/N]"}
112
+ Gate -- Yes --> Apply["5. APPLY<br/>Backup &amp; Surgical Patch<br/><code>apply · /apply</code>"]
113
113
  Gate -- No --> Reject["❌ Discarded"]
114
- Apply --> Recheck["6. RE-CHECK<br/>Differential AST Audit"]
115
- Recheck -- Fixed --> Archive["7. ARCHIVE<br/>Golden Recipe Distilled"]
116
- Recheck -- Regressed --> Rollback["⏪ Instant Rollback<br/>(pre_apply/*.bak)"]
114
+ Apply --> Recheck["6. RE-CHECK<br/>Differential AST Audit<br/><code>recheck · /recheck</code>"]
115
+ Recheck -- Fixed --> Archive["7. ARCHIVE<br/>Golden Recipe Distilled<br/><code>recipes</code>"]
116
+ Recheck -- Regressed --> Rollback["⏪ Instant Rollback<br/><code>rollback (.bak)</code>"]
117
117
  ```
118
118
 
119
119
  ---
@@ -198,27 +198,44 @@ flowchart TD
198
198
 
199
199
  ---
200
200
 
201
- ## 🚀 60-Second Quickstart
201
+ ## 🚀 60-Second Quickstart (Dual-Strategy: CLI & Chat)
202
202
 
203
- ### Method A: Via Node.js / NPX (Zero Setup)
203
+ TorusGuard works natively in both standard terminal environments (Cursor, VS Code, CI/CD runners) and AI chat workflows:
204
+
205
+ ### Method A: Via Node.js / NPX (Full 7-Stage Governance Lifecycle)
204
206
  ```bash
205
- # 1. Initialize TorusGuard in your workspace
207
+ # 1. Initialize TorusGuard in your workspace (or /torusguard init)
206
208
  npx torusguard init
207
209
 
208
- # 2. Run static security audit
210
+ # 2. Run static security audit (or /torusguard audit)
209
211
  npx torusguard audit
210
212
 
211
- # 3. Generate visual dark-mode HTML dashboard
213
+ # 3. Formulate minimal Ponytail candidate patches (or /torusguard harden)
214
+ npx torusguard harden
215
+
216
+ # 4. Review interactive Human Gate & apply with pre-apply rollback snapshots (.bak) (or /torusguard apply)
217
+ npx torusguard apply
218
+
219
+ # 5. Targeted differential re-scan verifying fix closure (or /torusguard recheck)
220
+ npx torusguard recheck
221
+
222
+ # 6. Explore distilled Golden Fix Recipes
223
+ npx torusguard recipes
224
+
225
+ # 7. Generate visual dark-mode HTML posture report (or /torusguard report)
212
226
  npx torusguard report --html
213
227
 
214
- # 4. Install Git Pre-Commit Diff Guard Hook (blocks dangerous commits)
228
+ # 8. (Optional) Revert to pre-apply snapshot at any time
229
+ npx torusguard rollback
230
+
231
+ # 9. Install Git Pre-Commit Diff Guard Hook (blocks dangerous commits)
215
232
  npx torusguard diff-guard --install-hook
216
233
 
217
- # 5. Synchronize prompt guardrails across AI editors (<= 300 tokens)
234
+ # 10. Synchronize prompt guardrails across AI editors (<= 300 tokens)
218
235
  npx torusguard rules sync
219
236
  ```
220
237
 
221
- ### Method B: Via Pure Python 3.10+ (Standard Library)
238
+ ### Method B: Via Pure Python 3.10+ (Zero-Dependency Standard Library)
222
239
  ```bash
223
240
  # 1. Initialize workspace
224
241
  python .torusguard/scripts/bootstrap.py --workspace .
@@ -226,10 +243,28 @@ python .torusguard/scripts/bootstrap.py --workspace .
226
243
  # 2. Run static audit
227
244
  python .torusguard/scripts/finding_scorer.py --dir .
228
245
 
229
- # 3. Install Pre-Commit Diff Guard
246
+ # 3. Formulate candidate patch plans (Ponytail Protocol <= 35 add, <= 25 del)
247
+ python .torusguard/scripts/harden_runner.py
248
+
249
+ # 4. Interactive Human Gate patch applier with pre-apply byte snapshots
250
+ python .torusguard/scripts/apply_runner.py
251
+
252
+ # 5. Targeted differential recheck
253
+ python .torusguard/scripts/recheck_runner.py
254
+
255
+ # 6. Explore distilled Golden Fix Recipes
256
+ python .torusguard/scripts/recipes_runner.py
257
+
258
+ # 7. Generate single-file visual HTML posture report
259
+ python .torusguard/scripts/html_reporter.py
260
+
261
+ # 8. Rollback pre-apply snapshots
262
+ python .torusguard/scripts/apply_runner.py --rollback
263
+
264
+ # 9. Install Pre-Commit Diff Guard
230
265
  python .torusguard/scripts/diff_guard.py --install-hook
231
266
 
232
- # 4. Sync AI IDE rules
267
+ # 10. Sync AI IDE rules
233
268
  python .torusguard/scripts/rules_sync.py --workspace . --format all
234
269
  ```
235
270
 
@@ -239,15 +274,17 @@ python .torusguard/scripts/rules_sync.py --workspace . --format all
239
274
 
240
275
  | Command | Subcommands & Flags | Description |
241
276
  |---|---|---|
242
- | `torusguard init` | `[--stack <name>] [--profile <type>]` | Scaffolds `.torusguard/` with active security rules and workflows. |
243
- | `torusguard audit` | `[--scope <path>] [--format md\|json]` | Audits source code against active rules and emits run folder. |
277
+ | `torusguard init` | `[--stack <name>] [--profile <type>]` | Scaffolds `.torusguard/` with active security rules, schemas, and workflows. |
278
+ | `torusguard audit` | `[--scope <path>] [--format md\|json]` | Audits source code against active rules, scores confidence, and emits run folder. |
244
279
  | `torusguard verify` | `[--id <finding_id>]` | Probes authorized endpoints with automated credential masking. |
245
- | `torusguard harden` | `[--id <finding_id>]` | Generates 4-artifact Ponytail patch plans ($\le 35$ additions, $\le 25$ deletions). |
246
- | `torusguard apply` | `[--id <finding_id>] [--dry-run]` | Saves pre-apply `.bak` snapshots and applies surgical patch to disk. |
247
- | `torusguard recheck`| `[--id <finding_id>]` | Differentially re-evaluates AST sinks over modified scopes. |
248
- | `torusguard report` | `[--sarif] [--html] [--out <path>]` | Exports OASIS SARIF v2.1.0 or single-file visual HTML posture report. |
280
+ | `torusguard harden` | `[--scope <path>] [--format md\|json]` | Formulates surgical candidate patch bundles adhering to Ponytail bounds ($\le 35$ additions, $\le 25$ deletions). |
281
+ | `torusguard apply` | `[--bundle <id>] [--yes \| -y]` | Interactive terminal Human Gate (`[y/N/all/quit]`) with syntax diffs, creates `.bak` snapshots, applies patches, and distills Golden Recipes. |
282
+ | `torusguard rollback` | `[--run <run_id>]` | Restores all files from `.torusguard/snapshots/<run_id>/` back to disk instantly. |
283
+ | `torusguard recheck`| `[--scope <path>]` | Differentially re-evaluates AST sinks over modified scopes (`Confirmed Fixed` vs `Regressed`). |
284
+ | `torusguard recipes`| `[--rule <id>] [--json]` | Interactive explorer for distilled, verified Golden Fix Recipes stored in persistent memory. |
285
+ | `torusguard report` | `[--sarif] [--html] [--out <path>]` | Exports OASIS SARIF v2.1.0 or single-file visual HTML posture dashboard. |
249
286
  | `torusguard status` | `[--json]` | Displays stack detection, active rule count, memory metrics, and run history. |
250
- | `torusguard diff-guard`| `[--install-hook] [--diff <file>]` | Scans git diff for bypasses (`TG-DIFF-001..004`) or installs pre-commit hook. |
287
+ | `torusguard diff-guard`| `[--install-hook] [--uninstall-hook] [--diff <file>]` | Scans git diff for bypasses (`TG-DIFF-001..004`) or installs pre-commit hook. |
251
288
  | `torusguard rules sync`| `[--format all\|cursor\|claude\|agent\|windsurf]` | Compiles project rules into AI IDE configs within $\le 300$ prompt tokens. |
252
289
  | `torusguard memory` | `status \| context \| export \| learn` | Inspects adaptive memory, generates proximity cards, or exports team packs. |
253
290
 
@@ -280,8 +317,8 @@ AI coding models often destroy working applications by attempting full-file rewr
280
317
 
281
318
  - **Strict Churn Limits:** Every fix is capped at $\le 35$ additions and $\le 25$ deletions.
282
319
  - **Full-File Rewrite Ban:** Large destructive edits are rejected by the patch engine.
283
- - **Rollback Snapshot Guarantee:** Before any file is modified, a byte-for-byte snapshot is saved to `pre_apply/<file>.bak`.
284
- - **Instant Rollback:** Restoring an original file takes 1 command (`cp pre_apply/<file>.bak <file>`).
320
+ - **Rollback Snapshot Guarantee:** Before any file is modified, a byte-for-byte snapshot is saved to `.torusguard/snapshots/<run_id>/<path>.bak`.
321
+ - **Instant Rollback:** Restoring original files takes 1 command (`npx torusguard rollback`).
285
322
 
286
323
  ---
287
324