torusguard 1.3.6 → 2.0.0-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/.torusguard/.manifest.json +9 -8
  2. package/.torusguard/auth.json +5 -0
  3. package/.torusguard/rules_catalog.json +242 -518
  4. package/.torusguard/runs/report-latest.html +3529 -364
  5. package/.torusguard/runs/run-20260918-105940-audit/manifest.json +2 -1
  6. package/.torusguard/runs/run-20260918-105940-audit/remediation.md +7 -0
  7. package/.torusguard/runs/run-20260919-145701-audit/findings.json +1 -0
  8. package/.torusguard/runs/run-20260919-145701-audit/findings.md +8 -0
  9. package/.torusguard/runs/run-20260919-145701-audit/manifest.json +12 -0
  10. package/.torusguard/runs/run-20260919-145701-audit/summary.md +5 -0
  11. package/.torusguard/runs/run-20260919-151729-audit/findings.json +1 -0
  12. package/.torusguard/runs/run-20260919-151729-audit/findings.md +8 -0
  13. package/.torusguard/runs/run-20260919-151729-audit/manifest.json +13 -0
  14. package/.torusguard/runs/run-20260919-151729-audit/remediation.md +7 -0
  15. package/.torusguard/runs/run-20260919-151729-audit/summary.md +5 -0
  16. package/.torusguard/runs/run-20260919-152340-audit/findings.json +1 -0
  17. package/.torusguard/runs/run-20260919-152340-audit/findings.md +8 -0
  18. package/.torusguard/runs/run-20260919-152340-audit/manifest.json +12 -0
  19. package/.torusguard/runs/run-20260919-152340-audit/summary.md +5 -0
  20. package/.torusguard/runs/run-20260919-152345-audit/findings.json +1 -0
  21. package/.torusguard/runs/run-20260919-152345-audit/findings.md +8 -0
  22. package/.torusguard/runs/run-20260919-152345-audit/manifest.json +12 -0
  23. package/.torusguard/runs/run-20260919-152345-audit/summary.md +5 -0
  24. package/.torusguard/runs/run-20260919-153500-audit/findings.json +1 -0
  25. package/.torusguard/runs/run-20260919-153500-audit/findings.md +8 -0
  26. package/.torusguard/runs/run-20260919-153500-audit/manifest.json +12 -0
  27. package/.torusguard/runs/run-20260919-153500-audit/summary.md +5 -0
  28. package/.torusguard/scripts/__pycache__/apply_runner.cpython-314.pyc +0 -0
  29. package/.torusguard/scripts/__pycache__/audit_runner.cpython-314.pyc +0 -0
  30. package/.torusguard/scripts/__pycache__/harden_runner.cpython-314.pyc +0 -0
  31. package/.torusguard/scripts/__pycache__/html_reporter.cpython-314.pyc +0 -0
  32. package/.torusguard/scripts/__pycache__/manifest_builder.cpython-314.pyc +0 -0
  33. package/.torusguard/scripts/__pycache__/recipes_runner.cpython-314.pyc +0 -0
  34. package/.torusguard/scripts/__pycache__/report_sync.cpython-314.pyc +0 -0
  35. package/.torusguard/scripts/apply_runner.py +101 -8
  36. package/.torusguard/scripts/audit_runner.py +116 -11
  37. package/.torusguard/scripts/harden_runner.py +122 -68
  38. package/.torusguard/scripts/html_reporter.py +1170 -253
  39. package/.torusguard/scripts/manifest_builder.py +2 -0
  40. package/.torusguard/scripts/recheck_runner.py +2 -1
  41. package/.torusguard/scripts/recipes_runner.py +91 -8
  42. package/.torusguard/scripts/report_sync.py +134 -7
  43. package/.torusguard/scripts/status_runner.py +267 -0
  44. package/.torusguard/snapshots/20260921-182638/go.mod.bak +11 -0
  45. package/.torusguard/snapshots/20260921-185213/file.go.bak +5 -0
  46. package/README.md +314 -364
  47. package/bin/torusguard.js +190 -20
  48. package/package.json +6 -2
  49. package/skills/torusguard/__pycache__/bootstrap.cpython-314.pyc +0 -0
  50. package/skills/torusguard/bootstrap.py +45 -6
  51. package/skills/torusguard/payload/.manifest.json +29 -14
  52. package/skills/torusguard/payload/TORUSGUARD.md +145 -145
  53. package/skills/torusguard/payload/agents/auditor.md +41 -41
  54. package/skills/torusguard/payload/agents/profiler.md +49 -49
  55. package/skills/torusguard/payload/agents/remediator.md +41 -41
  56. package/skills/torusguard/payload/agents/reviewer.md +39 -39
  57. package/skills/torusguard/payload/agents/validator.md +46 -46
  58. package/skills/torusguard/payload/config/scope.json +24 -24
  59. package/skills/torusguard/payload/references/csharp-security.md +41 -41
  60. package/skills/torusguard/payload/references/go-security.md +41 -41
  61. package/skills/torusguard/payload/references/java-security.md +40 -40
  62. package/skills/torusguard/payload/references/polyglot-security-matrix.md +25 -25
  63. package/skills/torusguard/payload/references/rust-security.md +40 -40
  64. package/skills/torusguard/payload/rules/custom/.gitkeep +1 -1
  65. package/skills/torusguard/payload/rules/custom/README.md +30 -30
  66. package/skills/torusguard/payload/scripts/__pycache__/audit_runner.cpython-314.pyc +0 -0
  67. package/skills/torusguard/payload/scripts/__pycache__/html_reporter.cpython-314.pyc +0 -0
  68. package/skills/torusguard/payload/scripts/__pycache__/report_sync.cpython-314.pyc +0 -0
  69. package/skills/torusguard/payload/scripts/__pycache__/sarif_exporter.cpython-314.pyc +0 -0
  70. package/skills/torusguard/payload/scripts/__pycache__/term_ui.cpython-314.pyc +0 -0
  71. package/skills/torusguard/payload/scripts/apply_runner.py +101 -8
  72. package/skills/torusguard/payload/scripts/audit_runner.py +116 -11
  73. package/skills/torusguard/payload/scripts/harden_runner.py +122 -68
  74. package/skills/torusguard/payload/scripts/html_reporter.py +1170 -253
  75. package/skills/torusguard/payload/scripts/manifest_builder.py +2 -0
  76. package/skills/torusguard/payload/scripts/recheck_runner.py +2 -1
  77. package/skills/torusguard/payload/scripts/recipes_runner.py +91 -8
  78. package/skills/torusguard/payload/scripts/report_sync.py +134 -7
  79. package/skills/torusguard/payload/scripts/rules_sync.py +321 -321
  80. package/skills/torusguard/payload/scripts/safety_gate.py +64 -64
  81. package/skills/torusguard/payload/scripts/status_runner.py +267 -0
  82. package/skills/torusguard/payload/skills/torusguard/references/csharp-security.md +41 -41
  83. package/skills/torusguard/payload/skills/torusguard/references/go-security.md +41 -41
  84. package/skills/torusguard/payload/skills/torusguard/references/java-security.md +40 -40
  85. package/skills/torusguard/payload/skills/torusguard/references/polyglot-security-matrix.md +25 -25
  86. package/skills/torusguard/payload/skills/torusguard/references/rust-security.md +40 -40
  87. package/skills/torusguard/payload/templates/audit-report.template.md +54 -54
  88. package/skills/torusguard/payload/templates/authorization.template.md +34 -34
  89. package/skills/torusguard/payload/templates/finding-card.template.md +32 -32
  90. package/skills/torusguard/payload/templates/remediation-bundle.template.md +35 -35
  91. package/skills/torusguard/payload/workflows/apply.md +9 -1
  92. package/skills/torusguard/payload/workflows/audit.md +8 -2
  93. package/skills/torusguard/payload/workflows/harden.md +6 -1
  94. package/skills/torusguard/payload/workflows/init.md +7 -1
  95. package/skills/torusguard/payload/workflows/recipes.md +55 -0
  96. package/skills/torusguard/payload/workflows/report.md +59 -55
  97. package/skills/torusguard/payload/workflows/status.md +4 -1
  98. package/skills/torusguard/payload/workflows/torusguard-apply.md +110 -0
  99. package/skills/torusguard/payload/workflows/torusguard-audit.md +105 -0
  100. package/skills/torusguard/payload/workflows/torusguard-authorize.md +96 -0
  101. package/skills/torusguard/payload/workflows/torusguard-exploit-check.md +98 -0
  102. package/skills/torusguard/payload/workflows/torusguard-harden.md +104 -0
  103. package/skills/torusguard/payload/workflows/torusguard-init.md +106 -0
  104. package/skills/torusguard/payload/workflows/torusguard-recheck.md +101 -0
  105. package/skills/torusguard/payload/workflows/torusguard-recipes.md +55 -0
  106. package/skills/torusguard/payload/workflows/torusguard-report.md +105 -0
  107. package/skills/torusguard/payload/workflows/torusguard-status.md +103 -0
  108. package/skills/torusguard/payload/workflows/torusguard-verify.md +100 -0
  109. package/skills/torusguard/payload/workflows/torusguard-web-validate.md +96 -0
  110. package/skills/torusguard/payload/workflows/torusguard.md +19 -0
@@ -1,64 +1,64 @@
1
- #!/usr/bin/env python3
2
- """
3
- TorusGuard Runtime Safety Gate Evaluator
4
- Evaluates prospective HTTP/browser validation probes against non-destruction policies.
5
- """
6
-
7
- import sys
8
- import json
9
- import argparse
10
- from typing import Dict, Any, Tuple
11
-
12
- def evaluate_safety_gate(method: str, path: str, body: str = "") -> Tuple[str, str]:
13
- """
14
- Returns (decision, rationale)
15
- Decisions:
16
- - Auto-Allowed
17
- - Approval Required
18
- - Manual Only (Blocked)
19
- """
20
- method_upper = method.upper()
21
-
22
- # Block destructive verbs
23
- if method_upper in ("DELETE", "DROP"):
24
- return "Manual Only", f"Method '{method_upper}' is destructive and strictly blocked from automated runtime validation."
25
-
26
- # Block sensitive administrative paths
27
- destructive_keywords = ["/admin/delete", "/shutdown", "/drop-database", "/purge", "/reset-system"]
28
- for kw in destructive_keywords:
29
- if kw in path.lower():
30
- return "Manual Only", f"Path '{path}' targets destructive administrative endpoint '{kw}'."
31
-
32
- # Safe read methods
33
- if method_upper in ("GET", "HEAD", "OPTIONS"):
34
- return "Auto-Allowed", f"Read-only method '{method_upper}' with non-destructive path."
35
-
36
- # State-changing methods (POST, PUT, PATCH)
37
- if method_upper in ("POST", "PUT", "PATCH"):
38
- # Check if safe canary marker exists
39
- if "tg-canary" in body.lower() or "torusguard" in body.lower():
40
- return "Approval Required", f"State-changing method '{method_upper}' contains benign TorusGuard test marker; requires user approval."
41
- else:
42
- return "Approval Required", f"State-changing method '{method_upper}' requires operator approval before execution."
43
-
44
- return "Approval Required", f"Unknown probe profile for {method_upper} {path}."
45
-
46
-
47
- def main():
48
- parser = argparse.ArgumentParser(description="TorusGuard Safety Gate Evaluator")
49
- parser.add_argument("--method", "-m", default="GET", help="HTTP Method")
50
- parser.add_argument("--path", "-p", default="/api/test", help="Endpoint path")
51
- parser.add_argument("--body", "-b", default="", help="Request payload body")
52
- parser.add_argument("--json", action="store_true", help="Output JSON")
53
- args = parser.parse_args()
54
-
55
- decision, rationale = evaluate_safety_gate(args.method, args.path, args.body)
56
-
57
- if args.json:
58
- print(json.dumps({"decision": decision, "rationale": rationale}, indent=2))
59
- else:
60
- print(f"Safety Decision: {decision}")
61
- print(f"Rationale: {rationale}")
62
-
63
- if __name__ == "__main__":
64
- main()
1
+ #!/usr/bin/env python3
2
+ """
3
+ TorusGuard Runtime Safety Gate Evaluator
4
+ Evaluates prospective HTTP/browser validation probes against non-destruction policies.
5
+ """
6
+
7
+ import sys
8
+ import json
9
+ import argparse
10
+ from typing import Dict, Any, Tuple
11
+
12
+ def evaluate_safety_gate(method: str, path: str, body: str = "") -> Tuple[str, str]:
13
+ """
14
+ Returns (decision, rationale)
15
+ Decisions:
16
+ - Auto-Allowed
17
+ - Approval Required
18
+ - Manual Only (Blocked)
19
+ """
20
+ method_upper = method.upper()
21
+
22
+ # Block destructive verbs
23
+ if method_upper in ("DELETE", "DROP"):
24
+ return "Manual Only", f"Method '{method_upper}' is destructive and strictly blocked from automated runtime validation."
25
+
26
+ # Block sensitive administrative paths
27
+ destructive_keywords = ["/admin/delete", "/shutdown", "/drop-database", "/purge", "/reset-system"]
28
+ for kw in destructive_keywords:
29
+ if kw in path.lower():
30
+ return "Manual Only", f"Path '{path}' targets destructive administrative endpoint '{kw}'."
31
+
32
+ # Safe read methods
33
+ if method_upper in ("GET", "HEAD", "OPTIONS"):
34
+ return "Auto-Allowed", f"Read-only method '{method_upper}' with non-destructive path."
35
+
36
+ # State-changing methods (POST, PUT, PATCH)
37
+ if method_upper in ("POST", "PUT", "PATCH"):
38
+ # Check if safe canary marker exists
39
+ if "tg-canary" in body.lower() or "torusguard" in body.lower():
40
+ return "Approval Required", f"State-changing method '{method_upper}' contains benign TorusGuard test marker; requires user approval."
41
+ else:
42
+ return "Approval Required", f"State-changing method '{method_upper}' requires operator approval before execution."
43
+
44
+ return "Approval Required", f"Unknown probe profile for {method_upper} {path}."
45
+
46
+
47
+ def main():
48
+ parser = argparse.ArgumentParser(description="TorusGuard Safety Gate Evaluator")
49
+ parser.add_argument("--method", "-m", default="GET", help="HTTP Method")
50
+ parser.add_argument("--path", "-p", default="/api/test", help="Endpoint path")
51
+ parser.add_argument("--body", "-b", default="", help="Request payload body")
52
+ parser.add_argument("--json", action="store_true", help="Output JSON")
53
+ args = parser.parse_args()
54
+
55
+ decision, rationale = evaluate_safety_gate(args.method, args.path, args.body)
56
+
57
+ if args.json:
58
+ print(json.dumps({"decision": decision, "rationale": rationale}, indent=2))
59
+ else:
60
+ print(f"Safety Decision: {decision}")
61
+ print(f"Rationale: {rationale}")
62
+
63
+ if __name__ == "__main__":
64
+ main()
@@ -0,0 +1,267 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ TorusGuard Diagnostic Status Engine (v1.4.0)
4
+ Displays workspace security posture, detected stack, active rules, historical runs,
5
+ golden recipes, and runtime scope validity in mathematically aligned 75-column cards.
6
+ Adheres to Python Pro & Python Patterns standards.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import sys
12
+ import json
13
+ import argparse
14
+ from pathlib import Path
15
+ from dataclasses import dataclass, asdict
16
+ from typing import Any
17
+
18
+ # Import term_ui for 75-column card formatting
19
+ try:
20
+ from term_ui import (
21
+ BOLD, DIM, RESET, CYAN, GREEN, YELLOW, WHITE, GRAY, RED,
22
+ card_header, card_border_top, card_border_bottom, card_divider, format_box_line
23
+ )
24
+ except ImportError:
25
+ scripts_dir = Path(__file__).resolve().parent
26
+ if str(scripts_dir) not in sys.path:
27
+ sys.path.insert(0, str(scripts_dir))
28
+ from term_ui import (
29
+ BOLD, DIM, RESET, CYAN, GREEN, YELLOW, WHITE, GRAY, RED,
30
+ card_header, card_border_top, card_border_bottom, card_divider, format_box_line
31
+ )
32
+
33
+
34
+ @dataclass
35
+ class WorkspaceStatus:
36
+ version: str
37
+ target_path: str
38
+ is_initialized: bool
39
+ stack_detected: str
40
+ active_rules_count: int
41
+ total_runs_count: int
42
+ latest_run_id: str | None
43
+ latest_run_time: str | None
44
+ latest_findings: int
45
+ golden_recipes_count: int
46
+ scope_status: str
47
+ health_score: int
48
+ posture_status: str
49
+
50
+ def to_dict(self) -> dict[str, Any]:
51
+ return asdict(self)
52
+
53
+
54
+ def collect_status(target_dir: Path) -> WorkspaceStatus:
55
+ """Inspect workspace configuration and filesystem records to construct status snapshot."""
56
+ target_dir = target_dir.resolve()
57
+ tg_dir = target_dir / ".torusguard"
58
+ is_init = tg_dir.is_dir()
59
+
60
+ # 1. Read config
61
+ version = "1.4.0"
62
+ stack_name = "Undetected"
63
+ cfg_file = tg_dir / "config" / "torusguard.json"
64
+ if cfg_file.is_file():
65
+ try:
66
+ with open(cfg_file, "r", encoding="utf-8") as f:
67
+ cfg = json.load(f)
68
+ version = cfg.get("version", version)
69
+ stack_name = cfg.get("stack", stack_name)
70
+ except (json.JSONDecodeError, OSError):
71
+ pass
72
+
73
+ if stack_name in ("Undetected", "Unknown", "None", ""):
74
+ try:
75
+ from stack_detect import detect_stack
76
+ p = detect_stack(target_dir)
77
+ parts = []
78
+ if p.get("language") and p["language"] != "Unknown":
79
+ parts.append(p["language"])
80
+ if p.get("framework") and p["framework"] != "None":
81
+ parts.append(p["framework"])
82
+ if parts:
83
+ stack_name = " / ".join(parts)
84
+ except Exception:
85
+ pass
86
+
87
+ # 2. Count active rules
88
+ active_rules_count = 0
89
+ active_rules_dir = tg_dir / "rules" / "active"
90
+ if active_rules_dir.is_dir():
91
+ active_rules_count = sum(1 for f in active_rules_dir.glob("*.md"))
92
+ if active_rules_count == 0:
93
+ rules_root = tg_dir / "rules"
94
+ if rules_root.is_dir():
95
+ active_rules_count = sum(1 for f in rules_root.rglob("TG-*.md"))
96
+ if active_rules_count == 0:
97
+ active_rules_count = 74 # Canonical rule catalog default
98
+
99
+ # 3. Read run history
100
+ total_runs = 0
101
+ latest_run_id: str | None = None
102
+ latest_run_time: str | None = None
103
+ latest_findings = 0
104
+ runs_dir = tg_dir / "runs"
105
+ if runs_dir.is_dir():
106
+ run_folders = [d for d in runs_dir.iterdir() if d.is_dir() and d.name.startswith("run-")]
107
+ run_folders.sort(key=lambda d: d.name, reverse=True)
108
+ total_runs = len(run_folders)
109
+ if run_folders:
110
+ latest = run_folders[0]
111
+ latest_run_id = latest.name
112
+ manifest_file = latest / "manifest.json"
113
+ if manifest_file.is_file():
114
+ try:
115
+ with open(manifest_file, "r", encoding="utf-8") as f:
116
+ m = json.load(f)
117
+ latest_run_time = m.get("created_at", latest.name)
118
+ latest_findings = m.get("findings_count", 0)
119
+ except (json.JSONDecodeError, OSError):
120
+ pass
121
+
122
+ # 4. Golden recipes in persistent memory
123
+ golden_recipes_count = 0
124
+ patterns_file = tg_dir / "memory" / "patterns.json"
125
+ if patterns_file.is_file():
126
+ try:
127
+ with open(patterns_file, "r", encoding="utf-8") as f:
128
+ p_data = json.load(f)
129
+ if isinstance(p_data, list):
130
+ golden_recipes_count = sum(
131
+ 1 for p in p_data
132
+ if isinstance(p, dict) and (
133
+ p.get("pattern_type") == "golden_fix_recipe" or "recipe_data" in p or "recipe_id" in p
134
+ )
135
+ )
136
+ elif isinstance(p_data, dict):
137
+ golden_recipes_count = len(p_data.get("golden_recipes", []))
138
+ except (json.JSONDecodeError, OSError):
139
+ pass
140
+
141
+ # 5. Scope authorization
142
+ scope_status = "Unconfigured"
143
+ scope_file = tg_dir / "config" / "scope.json"
144
+ if scope_file.is_file():
145
+ try:
146
+ with open(scope_file, "r", encoding="utf-8") as f:
147
+ s_data = json.load(f)
148
+ expires_at = s_data.get("expires_at")
149
+ if expires_at:
150
+ scope_status = "Authorized (TTL Active)"
151
+ else:
152
+ scope_status = "Authorized (Static)"
153
+ except (json.JSONDecodeError, OSError):
154
+ scope_status = "Error reading scope"
155
+
156
+ # 6. Posture health from security_report.md
157
+ health_score = 100
158
+ posture = "CLEAN & SECURE"
159
+ report_file = target_dir / "security_report.md"
160
+ if report_file.is_file():
161
+ try:
162
+ content = report_file.read_text(encoding="utf-8")
163
+ import re
164
+ m = re.search(r"Posture Score:\s*`(\d+)/100`", content)
165
+ if m:
166
+ health_score = int(m.group(1))
167
+ m_stat = re.search(r"Posture Status:\s*`([^`]+)`", content)
168
+ if m_stat:
169
+ posture = m_stat.group(1)
170
+ except OSError:
171
+ pass
172
+
173
+ if health_score < 70:
174
+ posture = "ACTION NEEDED"
175
+ elif health_score < 90:
176
+ posture = "ELEVATED RISK"
177
+ elif health_score == 100:
178
+ posture = "CLEAN & SECURE"
179
+
180
+ return WorkspaceStatus(
181
+ version=version,
182
+ target_path=str(target_dir),
183
+ is_initialized=is_init,
184
+ stack_detected=stack_name,
185
+ active_rules_count=active_rules_count,
186
+ total_runs_count=total_runs,
187
+ latest_run_id=latest_run_id,
188
+ latest_run_time=latest_run_time,
189
+ latest_findings=latest_findings,
190
+ golden_recipes_count=golden_recipes_count,
191
+ scope_status=scope_status,
192
+ health_score=health_score,
193
+ posture_status=posture,
194
+ )
195
+
196
+
197
+ def print_status_card(status: WorkspaceStatus) -> None:
198
+ """Render standardized 75-column diagnostic status cards."""
199
+ print()
200
+ print(card_header(
201
+ "🛡️ T O R U S G U A R D S T A T U S",
202
+ "Workspace Diagnostic Overview & Posture Snapshot",
203
+ f"v{status.version}"
204
+ ))
205
+ print()
206
+
207
+ # Card 1: Workspace & Stack
208
+ print(card_border_top("Workspace Environment", CYAN))
209
+ init_str = f"{GREEN}Initialized (.torusguard/ active){RESET}" if status.is_initialized else f"{RED}Uninitialized (Run: npx torusguard init){RESET}"
210
+ print(format_box_line(f"Workspace: {WHITE}{status.target_path}{RESET}", 67))
211
+ print(format_box_line(f"Status: {init_str}", 67))
212
+ print(format_box_line(f"Stack: {BOLD}{WHITE}{status.stack_detected}{RESET}", 67))
213
+ print(format_box_line(f"Active Rules: {GREEN}{status.active_rules_count}{RESET} canonical rules enabled across 18 families", 67))
214
+ print(card_border_bottom(CYAN))
215
+ print()
216
+
217
+ # Card 2: Run History & Memory
218
+ print(card_border_top("Run History & Memory Engine", YELLOW))
219
+ print(format_box_line(f"Total Runs: {WHITE}{status.total_runs_count}{RESET} historical audit runs", 67, border_color=YELLOW))
220
+ if status.latest_run_id:
221
+ print(format_box_line(f"Latest Run: {CYAN}{status.latest_run_id}{RESET}", 67, border_color=YELLOW))
222
+ print(format_box_line(f"Run Timestamp: {DIM}{status.latest_run_time or 'N/A'}{RESET}", 67, border_color=YELLOW))
223
+ print(format_box_line(f"Run Findings: {WHITE}{status.latest_findings}{RESET} vulnerabilities discovered", 67, border_color=YELLOW))
224
+ else:
225
+ print(format_box_line(f"Latest Run: {DIM}No runs recorded yet (Run: npx torusguard audit){RESET}", 67, border_color=YELLOW))
226
+ print(format_box_line(f"Golden Recipes: {GREEN}{status.golden_recipes_count}{RESET} verified fix patterns distilled in memory", 67, border_color=YELLOW))
227
+ print(format_box_line(f"Runtime Scope: {WHITE}{status.scope_status}{RESET}", 67, border_color=YELLOW))
228
+ print(card_border_bottom(YELLOW))
229
+ print()
230
+
231
+ # Card 3: Security Posture
232
+ posture_color = GREEN if status.health_score >= 90 else (YELLOW if status.health_score >= 70 else RED)
233
+ print(card_border_top("Security Health Posture", posture_color, double=True))
234
+ print(format_box_line(f"Health Score: {posture_color}{BOLD}{status.health_score}/100{RESET}", 67, border="║", border_color=posture_color))
235
+ print(format_box_line(f"Posture State: {posture_color}{BOLD}{status.posture_status}{RESET}", 67, border="║", border_color=posture_color))
236
+ print(format_box_line(f"Living Ledger: {CYAN}security_report.md (Synchronized){RESET}", 67, border="║", border_color=posture_color))
237
+ print(card_border_bottom(posture_color, double=True))
238
+ print()
239
+
240
+ # Quick Next Actions
241
+ print(card_border_top("Available Lifecycle Actions", GRAY))
242
+ print(format_box_line(f"Audit Codebase: {GREEN}npx torusguard audit{RESET}", 67, border_color=GRAY))
243
+ print(format_box_line(f"Harden Patches: {GREEN}npx torusguard harden{RESET}", 67, border_color=GRAY))
244
+ print(format_box_line(f"View Recipes: {GREEN}npx torusguard recipes{RESET}", 67, border_color=GRAY))
245
+ print(format_box_line(f"HTML Dashboard: {GREEN}npx torusguard report --html{RESET}", 67, border_color=GRAY))
246
+ print(card_border_bottom(GRAY))
247
+ print()
248
+
249
+
250
+ def main() -> None:
251
+ parser = argparse.ArgumentParser(description="TorusGuard Workspace Diagnostic Status Engine")
252
+ parser.add_argument("path", nargs="?", default=".", help="Target project root directory")
253
+ parser.add_argument("--target", "-t", help="Target project root directory (alias for path)")
254
+ parser.add_argument("--json", action="store_true", help="Output raw JSON snapshot")
255
+ args = parser.parse_args()
256
+
257
+ target = Path(args.target or args.path).resolve()
258
+ status = collect_status(target)
259
+
260
+ if args.json:
261
+ print(json.dumps(status.to_dict(), indent=2))
262
+ else:
263
+ print_status_card(status)
264
+
265
+
266
+ if __name__ == "__main__":
267
+ main()
@@ -1,41 +1,41 @@
1
- # TorusGuard Skill Reference: C# & ASP.NET Core Security
2
-
3
- > **Loaded When:** A project is identified as a C# / .NET application (`*.csproj`, `*.sln`, ASP.NET Core detected).
4
-
5
- ---
6
-
7
- ## 🛡️ Key Inspection Areas & Rules
8
-
9
- ### 1. Authentication & Authorization
10
- * `TG-AUTH-001`: Ensure controllers and endpoints have `[Authorize]` attributes.
11
- * Prohibit unvetted `[AllowAnonymous]` on sensitive business logic or user data endpoints.
12
-
13
- ### 2. Entity Framework Core & SQL Injection
14
- * `TG-INPUT-002`: Use LINQ expressions or `FromSqlInterpolated` with interpolated string syntax (EF Core converts parameters automatically).
15
- * Prohibit raw `FromSqlRaw` with un-parameterized string concatenations.
16
- * `TG-DB-004`: Configure Global Query Filters (`HasQueryFilter(e => e.TenantId == _currentTenant)`) for multi-tenant safety.
17
-
18
- ### 3. Anti-Forgery & TLS
19
- * `TG-CSRF-001`: Ensure `[ValidateAntiForgeryToken]` or `[AutoValidateAntiforgeryToken]` is applied to POST/PUT/DELETE actions.
20
- * Prohibit `DangerousAcceptAnyServerCertificateValidator`.
21
-
22
- ---
23
-
24
- ## 🛠️ Safe Patterns Summary
25
-
26
- ```csharp
27
- // Safe Entity Framework Parameterized Query
28
- var user = await context.Users
29
- .Where(u => u.Id == userId && u.TenantId == currentTenantId)
30
- .FirstOrDefaultAsync();
31
-
32
- // Safe Global Query Filter in DbContext
33
- modelBuilder.Entity<Invoice>()
34
- .HasQueryFilter(i => i.TenantId == _tenantProvider.GetTenantId());
35
-
36
- // Safe Controller Security
37
- [Authorize]
38
- [ApiController]
39
- [Route("api/[controller]")]
40
- public class InvoicesController : ControllerBase { ... }
41
- ```
1
+ # TorusGuard Skill Reference: C# & ASP.NET Core Security
2
+
3
+ > **Loaded When:** A project is identified as a C# / .NET application (`*.csproj`, `*.sln`, ASP.NET Core detected).
4
+
5
+ ---
6
+
7
+ ## 🛡️ Key Inspection Areas & Rules
8
+
9
+ ### 1. Authentication & Authorization
10
+ * `TG-AUTH-001`: Ensure controllers and endpoints have `[Authorize]` attributes.
11
+ * Prohibit unvetted `[AllowAnonymous]` on sensitive business logic or user data endpoints.
12
+
13
+ ### 2. Entity Framework Core & SQL Injection
14
+ * `TG-INPUT-002`: Use LINQ expressions or `FromSqlInterpolated` with interpolated string syntax (EF Core converts parameters automatically).
15
+ * Prohibit raw `FromSqlRaw` with un-parameterized string concatenations.
16
+ * `TG-DB-004`: Configure Global Query Filters (`HasQueryFilter(e => e.TenantId == _currentTenant)`) for multi-tenant safety.
17
+
18
+ ### 3. Anti-Forgery & TLS
19
+ * `TG-CSRF-001`: Ensure `[ValidateAntiForgeryToken]` or `[AutoValidateAntiforgeryToken]` is applied to POST/PUT/DELETE actions.
20
+ * Prohibit `DangerousAcceptAnyServerCertificateValidator`.
21
+
22
+ ---
23
+
24
+ ## 🛠️ Safe Patterns Summary
25
+
26
+ ```csharp
27
+ // Safe Entity Framework Parameterized Query
28
+ var user = await context.Users
29
+ .Where(u => u.Id == userId && u.TenantId == currentTenantId)
30
+ .FirstOrDefaultAsync();
31
+
32
+ // Safe Global Query Filter in DbContext
33
+ modelBuilder.Entity<Invoice>()
34
+ .HasQueryFilter(i => i.TenantId == _tenantProvider.GetTenantId());
35
+
36
+ // Safe Controller Security
37
+ [Authorize]
38
+ [ApiController]
39
+ [Route("api/[controller]")]
40
+ public class InvoicesController : ControllerBase { ... }
41
+ ```
@@ -1,41 +1,41 @@
1
- # TorusGuard Skill Reference: Go Security
2
-
3
- > **Loaded When:** A project is identified as a Go application (`go.mod`, `go.sum`, or Go source files detected).
4
-
5
- ---
6
-
7
- ## 🛡️ Key Inspection Areas & Rules
8
-
9
- ### 1. Database & SQL Injection
10
- * `TG-INPUT-002`: Ensure raw queries use parameterized placeholders (`?`, `$1`), never `fmt.Sprintf` or string concatenation.
11
- * `TG-DB-004`: Enforce tenant isolation in GORM queries (`db.Where("tenant_id = ?", tenantID)`).
12
-
13
- ### 2. TLS & Network Security
14
- * `TG-DIFF-001`: Prohibit `InsecureSkipVerify: true` in `tls.Config`. Always use valid root CA pools.
15
- * `TG-SSRF-001`: Validate outbound URLs before issuing `http.Get` or `http.Post`.
16
-
17
- ### 3. Concurrency & Goroutine Safety
18
- * `TG-BIZ-001`: Ensure context cancellation propagation (`ctx.Done()`) to prevent goroutine leaks.
19
- * Use mutexes or channels to prevent data races on shared state.
20
-
21
- ### 4. Input Validation & Path Traversal
22
- * `TG-INPUT-006`: Sanitize file paths with `filepath.Clean` and check `strings.HasPrefix(cleanPath, baseDir)`.
23
-
24
- ---
25
-
26
- ## 🛠️ Safe Patterns Summary
27
-
28
- ```go
29
- // Safe Parameterized Query
30
- row := db.QueryRowContext(ctx, "SELECT id, email FROM users WHERE id = ? AND tenant_id = ?", userID, tenantID)
31
-
32
- // Safe GORM Scoping
33
- var invoice Invoice
34
- result := db.Where("id = ? AND tenant_id = ?", invoiceID, currentTenantID).First(&invoice)
35
-
36
- // Safe TLS Client
37
- tlsConfig := &tls.Config{
38
- MinVersion: tls.VersionTLS13,
39
- }
40
- client := &http.Client{Transport: &http.Transport{TLSClientConfig: tlsConfig}}
41
- ```
1
+ # TorusGuard Skill Reference: Go Security
2
+
3
+ > **Loaded When:** A project is identified as a Go application (`go.mod`, `go.sum`, or Go source files detected).
4
+
5
+ ---
6
+
7
+ ## 🛡️ Key Inspection Areas & Rules
8
+
9
+ ### 1. Database & SQL Injection
10
+ * `TG-INPUT-002`: Ensure raw queries use parameterized placeholders (`?`, `$1`), never `fmt.Sprintf` or string concatenation.
11
+ * `TG-DB-004`: Enforce tenant isolation in GORM queries (`db.Where("tenant_id = ?", tenantID)`).
12
+
13
+ ### 2. TLS & Network Security
14
+ * `TG-DIFF-001`: Prohibit `InsecureSkipVerify: true` in `tls.Config`. Always use valid root CA pools.
15
+ * `TG-SSRF-001`: Validate outbound URLs before issuing `http.Get` or `http.Post`.
16
+
17
+ ### 3. Concurrency & Goroutine Safety
18
+ * `TG-BIZ-001`: Ensure context cancellation propagation (`ctx.Done()`) to prevent goroutine leaks.
19
+ * Use mutexes or channels to prevent data races on shared state.
20
+
21
+ ### 4. Input Validation & Path Traversal
22
+ * `TG-INPUT-006`: Sanitize file paths with `filepath.Clean` and check `strings.HasPrefix(cleanPath, baseDir)`.
23
+
24
+ ---
25
+
26
+ ## 🛠️ Safe Patterns Summary
27
+
28
+ ```go
29
+ // Safe Parameterized Query
30
+ row := db.QueryRowContext(ctx, "SELECT id, email FROM users WHERE id = ? AND tenant_id = ?", userID, tenantID)
31
+
32
+ // Safe GORM Scoping
33
+ var invoice Invoice
34
+ result := db.Where("id = ? AND tenant_id = ?", invoiceID, currentTenantID).First(&invoice)
35
+
36
+ // Safe TLS Client
37
+ tlsConfig := &tls.Config{
38
+ MinVersion: tls.VersionTLS13,
39
+ }
40
+ client := &http.Client{Transport: &http.Transport{TLSClientConfig: tlsConfig}}
41
+ ```
@@ -1,40 +1,40 @@
1
- # TorusGuard Skill Reference: Java & Spring Security
2
-
3
- > **Loaded When:** A project is identified as a Java/Kotlin application (`pom.xml`, `build.gradle`, Spring Boot detected).
4
-
5
- ---
6
-
7
- ## 🛡️ Key Inspection Areas & Rules
8
-
9
- ### 1. Spring Security & CSRF
10
- * `TG-CSRF-001`: Prohibit `.csrf().disable()` or `AbstractHttpConfigurer::disable` on state-changing browser routes.
11
- * `TG-PLATFORM-001`: Avoid `@CrossOrigin(origins = "*")` with `allowCredentials = "true"`.
12
-
13
- ### 2. JPA & Hibernate SQL Injection
14
- * `TG-INPUT-002`: Use named parameters (`:param`) or `CriteriaBuilder`. Never concatenate strings into JPQL queries.
15
- * `TG-DB-004`: Enforce tenant isolation via `@Filter` or explicit where clauses.
16
-
17
- ### 3. Insecure Deserialization & XML
18
- * Prohibit `ObjectInputStream.readObject()` on untrusted input without look-ahead verification.
19
- * Disable external entity resolution (`setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)`).
20
-
21
- ---
22
-
23
- ## 🛠️ Safe Patterns Summary
24
-
25
- ```java
26
- // Safe JPA Query
27
- @Query("SELECT u FROM User u WHERE u.id = :id AND u.tenantId = :tenantId")
28
- Optional<User> findByIdAndTenantId(@Param("id") Long id, @Param("tenantId") String tenantId);
29
-
30
- // Safe Spring Security Configuration
31
- @Bean
32
- public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
33
- http
34
- .authorizeHttpRequests(auth -> auth
35
- .requestMatchers("/public/**").permitAll()
36
- .anyRequest().authenticated()
37
- );
38
- return http.build();
39
- }
40
- ```
1
+ # TorusGuard Skill Reference: Java & Spring Security
2
+
3
+ > **Loaded When:** A project is identified as a Java/Kotlin application (`pom.xml`, `build.gradle`, Spring Boot detected).
4
+
5
+ ---
6
+
7
+ ## 🛡️ Key Inspection Areas & Rules
8
+
9
+ ### 1. Spring Security & CSRF
10
+ * `TG-CSRF-001`: Prohibit `.csrf().disable()` or `AbstractHttpConfigurer::disable` on state-changing browser routes.
11
+ * `TG-PLATFORM-001`: Avoid `@CrossOrigin(origins = "*")` with `allowCredentials = "true"`.
12
+
13
+ ### 2. JPA & Hibernate SQL Injection
14
+ * `TG-INPUT-002`: Use named parameters (`:param`) or `CriteriaBuilder`. Never concatenate strings into JPQL queries.
15
+ * `TG-DB-004`: Enforce tenant isolation via `@Filter` or explicit where clauses.
16
+
17
+ ### 3. Insecure Deserialization & XML
18
+ * Prohibit `ObjectInputStream.readObject()` on untrusted input without look-ahead verification.
19
+ * Disable external entity resolution (`setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)`).
20
+
21
+ ---
22
+
23
+ ## 🛠️ Safe Patterns Summary
24
+
25
+ ```java
26
+ // Safe JPA Query
27
+ @Query("SELECT u FROM User u WHERE u.id = :id AND u.tenantId = :tenantId")
28
+ Optional<User> findByIdAndTenantId(@Param("id") Long id, @Param("tenantId") String tenantId);
29
+
30
+ // Safe Spring Security Configuration
31
+ @Bean
32
+ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
33
+ http
34
+ .authorizeHttpRequests(auth -> auth
35
+ .requestMatchers("/public/**").permitAll()
36
+ .anyRequest().authenticated()
37
+ );
38
+ return http.build();
39
+ }
40
+ ```