torusguard 0.9.4 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.torusguard/.manifest.json +2 -2
- package/.torusguard/config/torusguard.json +1 -1
- package/.torusguard/skills/torusguard/SKILL.md +11 -7
- package/README.md +3 -2
- package/bin/torusguard.js +79 -43
- package/package.json +1 -1
- package/skills/torusguard/SKILL.md +2 -2
- package/skills/torusguard/__pycache__/bootstrap.cpython-311.pyc +0 -0
- package/skills/torusguard/bootstrap.py +180 -80
- package/skills/torusguard/payload/.manifest.json +2 -2
- package/skills/torusguard/payload/config/torusguard.json +1 -1
- package/skills/torusguard/payload/scripts/__pycache__/diff_guard.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/scripts/__pycache__/monorepo_detector.cpython-311.pyc +0 -0
- package/skills/torusguard/payload/skills/torusguard/SKILL.md +11 -7
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"agents/validator.md": "79fc4431de5c5507f8730aee6c5c3e61fd238cbf8cf8c7c6aac462eee9761ed6",
|
|
9
9
|
"config/scope.json": "b198a86186b4c6d5e1af516bf4e3a6afa8878e622ca1d57a5bf72d294f8c6f25",
|
|
10
10
|
"config/slash-commands.json": "5390f0d26f8117a62e56c58147d3a0d2deab1a20956302b212703281d13fa84e",
|
|
11
|
-
"config/torusguard.json": "
|
|
11
|
+
"config/torusguard.json": "077bc6a948f9420aded8dba248577ff3ebf054cab64cf538a7a6d05223fe27bc",
|
|
12
12
|
"references/django-security.md": "a15b7eb11b51dd1970d3d65544cf79ebea91fb99dc0e085e58a56532a718dce7",
|
|
13
13
|
"references/drf-security.md": "c7a7af3acaef895bf4798590acc88b3a2e9831a49eb2d23b4d8f31540ab264cc",
|
|
14
14
|
"references/express-security.md": "dff1db15e614d29d8c272f9da345b418077e62dc883fe210c7a50c552c76493f",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"scripts/safety_gate.py": "3379b7534b2590cf563717a448983ad8ed7e8f174f0ad65683d33e8a10f51558",
|
|
41
41
|
"scripts/sarif_exporter.py": "35c66637413afc4b72d5bd426638447c77231d2a8594dce5addceffd4803a20d",
|
|
42
42
|
"scripts/stack_detect.py": "99b7bdf9829d58ff5b8c59afd6e8b6429bbb11d830ac73dec491101cbbc41574",
|
|
43
|
-
"skills/torusguard/SKILL.md": "
|
|
43
|
+
"skills/torusguard/SKILL.md": "31a115886ffb115f2b975c4d0670e780e11ea68201559b24b20d0d0ef456058f",
|
|
44
44
|
"skills/torusguard/bootstrap.py": "7e348065a622089ab1d51e9bf4864e5b0022aaee1ccb2ecbf7057c14e792e2c7",
|
|
45
45
|
"skills/torusguard/references/auth-and-sessions.md": "34c2843f8c0dbe3574e54f00a39a92a1f431527ec5f69b2d64c84240d424a39e",
|
|
46
46
|
"skills/torusguard/references/business-logic-and-abuse.md": "0d6088936bc1a01023070332fccef0f2e0734358a5119379055f3d2895c22567",
|
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: torusguard
|
|
3
|
-
description:
|
|
4
|
-
version: 0.9.
|
|
3
|
+
description: "Autonomous security engine: 71 rules across 11 families, governed remediation (Ponytail Protocol), SARIF v2.1.0 exports, and 5-agent authority separation for Python & TypeScript web applications."
|
|
4
|
+
version: 0.9.5
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# TorusGuard Master Router
|
|
7
|
+
# TorusGuard Master Security Router
|
|
8
8
|
|
|
9
|
-
**Principle:** If the browser receives it, users can inspect it. Keep secrets,
|
|
9
|
+
**Principle:** If the browser receives it, users can inspect it. Keep secrets, database queries, and authorization strictly on trusted server-side code.
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
## ⚡ Workspace Bootstrap Check
|
|
14
|
-
1. **If `.torusguard/` exists:**
|
|
15
|
-
2. **If `.torusguard/` is
|
|
14
|
+
1. **If `.torusguard/` exists on disk:** Full governance active. Route slash commands to local specialist workflows below.
|
|
15
|
+
2. **If `.torusguard/` is absent (Autonomous AI Mode):** Operates standalone in any AI agent (Kimi, Antigravity, VS Code, Cursor). Apply in-memory security invariants:
|
|
16
|
+
- Server-side auth & tenant scoping (`.filter(tenant=...)`).
|
|
17
|
+
- Zero client-side secrets (`SUPABASE_SERVICE_ROLE_KEY`, live API keys).
|
|
18
|
+
- Ponytail Protocol patch limits ($\le 35$ additions, $\le 25$ deletions).
|
|
19
|
+
- *Upgrade:* Run `npx torusguard init` to unlock local `.torusguard/` run tracking & individual commands.
|
|
16
20
|
|
|
17
21
|
---
|
|
18
22
|
|
|
19
23
|
## Specialist Skill Routing (Lazy Loading)
|
|
20
|
-
Load **only** the designated sub-skill
|
|
24
|
+
Load **only** the designated sub-skill on demand to preserve the 1,000–1,500 token budget:
|
|
21
25
|
|
|
22
26
|
| Command | Specialist Skill | Agent |
|
|
23
27
|
| :--- | :--- | :--- |
|
package/README.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img src="TorusGuard.png" alt="TorusGuard Security Banner" width="480" style="max-width: 100%; height: auto; border-radius: 8px;">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/githubmofo/TorusGuard/main/TorusGuard.png" alt="TorusGuard Security Banner" width="480" style="max-width: 100%; height: auto; border-radius: 8px;">
|
|
3
3
|
|
|
4
4
|
# TorusGuard
|
|
5
5
|
|
|
6
6
|
**Autonomous Security Guardrails, Governed Remediation, and Authorized Runtime Validation for AI-Built Web Applications.**
|
|
7
7
|
|
|
8
8
|
[](https://www.npmjs.com/package/torusguard)
|
|
9
|
-
[](https://github.com/githubmofo/TorusGuard/pkgs/npm/torusguard)
|
|
10
|
+
[](https://github.com/githubmofo/TorusGuard/releases/latest)
|
|
10
11
|
[](LICENSE)
|
|
11
12
|
[](https://python.org)
|
|
12
13
|
[](https://nodejs.org)
|
package/bin/torusguard.js
CHANGED
|
@@ -15,14 +15,16 @@ const command = args[0] || 'init';
|
|
|
15
15
|
const rootDir = path.resolve(__dirname, '..');
|
|
16
16
|
const cwd = process.cwd();
|
|
17
17
|
|
|
18
|
-
// ANSI Color Helpers
|
|
18
|
+
// ─── ANSI Color Helpers ───────────────────────────────────────────────────────
|
|
19
19
|
const BOLD = '\x1b[1m';
|
|
20
|
+
const DIM = '\x1b[2m';
|
|
20
21
|
const RESET = '\x1b[0m';
|
|
21
22
|
const CYAN = '\x1b[36m';
|
|
22
23
|
const GREEN = '\x1b[32m';
|
|
23
24
|
const YELLOW = '\x1b[33m';
|
|
25
|
+
const WHITE = '\x1b[97m';
|
|
24
26
|
const GRAY = '\x1b[90m';
|
|
25
|
-
const
|
|
27
|
+
const RED = '\x1b[31m';
|
|
26
28
|
|
|
27
29
|
// Detect available Python binary (python or python3)
|
|
28
30
|
let pythonCmd = 'python';
|
|
@@ -45,24 +47,41 @@ try {
|
|
|
45
47
|
|
|
46
48
|
function printHelp() {
|
|
47
49
|
console.log(`
|
|
48
|
-
${CYAN}
|
|
49
|
-
${CYAN}│${RESET}
|
|
50
|
-
${CYAN}│${RESET}
|
|
51
|
-
${CYAN}
|
|
52
|
-
|
|
53
|
-
${
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
${
|
|
64
|
-
|
|
65
|
-
|
|
50
|
+
${CYAN}╭─────────────────────────────────────────────────────────────────────────╮${RESET}
|
|
51
|
+
${CYAN}│${RESET} ${CYAN}│${RESET}
|
|
52
|
+
${CYAN}│${RESET} ${BOLD}${WHITE}🛡️ T O R U S G U A R D C L I${RESET} ${GRAY}v0.9.5${RESET} ${CYAN}│${RESET}
|
|
53
|
+
${CYAN}│${RESET} ${DIM}Autonomous Security Engine for AI-Built Applications${RESET} ${CYAN}│${RESET}
|
|
54
|
+
${CYAN}│${RESET} ${CYAN}│${RESET}
|
|
55
|
+
${CYAN}╰─────────────────────────────────────────────────────────────────────────╯${RESET}
|
|
56
|
+
|
|
57
|
+
${BOLD}Usage:${RESET} ${GREEN}npx torusguard${RESET} ${WHITE}[command]${RESET} ${GRAY}[options]${RESET}
|
|
58
|
+
|
|
59
|
+
${CYAN}┌─────────────────────────────────────────────────────────────────────────┐${RESET}
|
|
60
|
+
${CYAN}│${RESET} ${BOLD}Commands${RESET} ${CYAN}│${RESET}
|
|
61
|
+
${CYAN}├─────────────────────────────────────────────────────────────────────────┤${RESET}
|
|
62
|
+
${CYAN}│${RESET} ${GREEN}init${RESET} Scaffold ${BOLD}.torusguard/${RESET} workspace + unlock 11 slash commands ${CYAN}│${RESET}
|
|
63
|
+
${CYAN}│${RESET} ${GREEN}status${RESET} Display active security posture, rules, and stack info ${CYAN}│${RESET}
|
|
64
|
+
${CYAN}│${RESET} ${GREEN}audit${RESET} Run static AST security scan on the target project ${CYAN}│${RESET}
|
|
65
|
+
${CYAN}│${RESET} ${GREEN}report${RESET} Export OASIS SARIF v2.1.0 structured telemetry ${CYAN}│${RESET}
|
|
66
|
+
${CYAN}│${RESET} ${GREEN}help${RESET} Show this interactive command guide ${CYAN}│${RESET}
|
|
67
|
+
${CYAN}├─────────────────────────────────────────────────────────────────────────┤${RESET}
|
|
68
|
+
${CYAN}│${RESET} ${BOLD}Options${RESET} ${CYAN}│${RESET}
|
|
69
|
+
${CYAN}├─────────────────────────────────────────────────────────────────────────┤${RESET}
|
|
70
|
+
${CYAN}│${RESET} ${GRAY}--target <dir>${RESET} Target directory to analyze or scaffold ${DIM}(default: .)${RESET} ${CYAN}│${RESET}
|
|
71
|
+
${CYAN}│${RESET} ${GRAY}--force${RESET} Overwrite existing workspace and re-scaffold ${CYAN}│${RESET}
|
|
72
|
+
${CYAN}└─────────────────────────────────────────────────────────────────────────┘${RESET}
|
|
73
|
+
|
|
74
|
+
${BOLD}AI Chat Commands:${RESET}
|
|
75
|
+
${DIM}In your AI IDE chat, use any of these slash commands:${RESET}
|
|
76
|
+
${CYAN}/torusguard${RESET} Main orchestrator (status, audit, harden, etc.)
|
|
77
|
+
${CYAN}/torusguard-audit${RESET} Static AST security scan
|
|
78
|
+
${CYAN}/torusguard-harden${RESET} Generate governed fix patches
|
|
79
|
+
${CYAN}/torusguard-apply${RESET} Apply patches with rollback snapshots
|
|
80
|
+
${CYAN}/torusguard-report${RESET} Executive security posture report
|
|
81
|
+
${CYAN}/torusguard-status${RESET} Read-only workspace diagnostic
|
|
82
|
+
|
|
83
|
+
${DIM}Documentation:${RESET} ${CYAN}https://github.com/githubmofo/TorusGuard${RESET}
|
|
84
|
+
${DIM}NPM Package:${RESET} ${CYAN}https://npmjs.com/package/torusguard${RESET}
|
|
66
85
|
`);
|
|
67
86
|
}
|
|
68
87
|
|
|
@@ -76,28 +95,45 @@ if (command === 'status') {
|
|
|
76
95
|
if (fs.existsSync(cfgPath)) {
|
|
77
96
|
try {
|
|
78
97
|
const cfg = JSON.parse(fs.readFileSync(cfgPath, 'utf-8'));
|
|
98
|
+
const stackLang = cfg.detected_stack?.language || 'Not yet detected';
|
|
99
|
+
const stackFw = cfg.detected_stack?.framework || 'Not yet detected';
|
|
100
|
+
const stackDb = cfg.detected_stack?.data_layer || 'Not yet detected';
|
|
101
|
+
const stackStatus = cfg.detected_stack ? `${GREEN}Detected${RESET}` : `${YELLOW}Pending first audit${RESET}`;
|
|
102
|
+
|
|
79
103
|
console.log(`
|
|
80
|
-
${CYAN}
|
|
81
|
-
${CYAN}│${RESET}
|
|
82
|
-
${CYAN}
|
|
83
|
-
|
|
84
|
-
${
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
${BOLD}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
${
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
${CYAN}
|
|
99
|
-
${CYAN}│${RESET}
|
|
100
|
-
${CYAN}
|
|
104
|
+
${CYAN}╭─────────────────────────────────────────────────────────────────────────╮${RESET}
|
|
105
|
+
${CYAN}│${RESET} ${CYAN}│${RESET}
|
|
106
|
+
${CYAN}│${RESET} ${BOLD}${WHITE}🛡️ TORUSGUARD SECURITY POSTURE${RESET} ${GRAY}v0.9.5${RESET} ${CYAN}│${RESET}
|
|
107
|
+
${CYAN}│${RESET} ${CYAN}│${RESET}
|
|
108
|
+
${CYAN}╰─────────────────────────────────────────────────────────────────────────╯${RESET}
|
|
109
|
+
|
|
110
|
+
${BOLD}▸ Workspace:${RESET} ${GREEN}${cwd}${RESET}
|
|
111
|
+
${BOLD}▸ Governance:${RESET} ${GREEN}Full Local Governance (.torusguard/)${RESET}
|
|
112
|
+
|
|
113
|
+
${CYAN}┌── Environment & Stack ──────────────────────────────────────────────────┐${RESET}
|
|
114
|
+
${CYAN}│${RESET} Language: ${BOLD}${stackLang}${RESET}
|
|
115
|
+
${CYAN}│${RESET} Framework: ${BOLD}${stackFw}${RESET}
|
|
116
|
+
${CYAN}│${RESET} Data Layer: ${BOLD}${stackDb}${RESET}
|
|
117
|
+
${CYAN}│${RESET} Stack Detection: ${stackStatus}
|
|
118
|
+
${CYAN}└─────────────────────────────────────────────────────────────────────────┘${RESET}
|
|
119
|
+
|
|
120
|
+
${CYAN}┌── Governance Telemetry ─────────────────────────────────────────────────┐${RESET}
|
|
121
|
+
${CYAN}│${RESET} Rules Catalog: ${GREEN}71 Canonical Security Rules${RESET} (11 families)
|
|
122
|
+
${CYAN}│${RESET} Severity Floor: ${YELLOW}${cfg.severity_threshold || 'medium'}${RESET}
|
|
123
|
+
${CYAN}│${RESET} Runs Directory: ${DIM}${cfg.runs_dir || '.torusguard/runs'}${RESET}
|
|
124
|
+
${CYAN}│${RESET} Ponytail Bounds: ${GREEN}<= 35 additions, <= 25 deletions${RESET}
|
|
125
|
+
${CYAN}└─────────────────────────────────────────────────────────────────────────┘${RESET}
|
|
126
|
+
|
|
127
|
+
${CYAN}┌── Rule Families ────────────────────────────────────────────────────────┐${RESET}
|
|
128
|
+
${CYAN}│${RESET} ${YELLOW}TG-SEC${RESET} Secrets & Credentials ${YELLOW}TG-DB${RESET} Database Safety
|
|
129
|
+
${CYAN}│${RESET} ${YELLOW}TG-INPUT${RESET} Input Validation ${YELLOW}TG-AUTH${RESET} Authentication
|
|
130
|
+
${CYAN}│${RESET} ${YELLOW}TG-CLIENT${RESET} Client Bundle Leaks ${YELLOW}TG-DIFF${RESET} Diff Inspection
|
|
131
|
+
${CYAN}│${RESET} ${YELLOW}TG-AGENT${RESET} AI Agent Security ${YELLOW}TG-EDGE${RESET} Serverless
|
|
132
|
+
${CYAN}│${RESET} ${YELLOW}TG-SUPPLY${RESET} Supply Chain & CI/CD ${YELLOW}TG-SSRF${RESET} Outbound Net
|
|
133
|
+
${CYAN}│${RESET} ${YELLOW}TG-BIZ${RESET} Business Logic
|
|
134
|
+
${CYAN}└─────────────────────────────────────────────────────────────────────────┘${RESET}
|
|
135
|
+
|
|
136
|
+
${DIM}Quick Action:${RESET} In your AI chat, run ${CYAN}/torusguard-audit${RESET} to scan.
|
|
101
137
|
`);
|
|
102
138
|
process.exit(0);
|
|
103
139
|
} catch (e) {
|
|
@@ -105,8 +141,8 @@ if (command === 'status') {
|
|
|
105
141
|
}
|
|
106
142
|
} else {
|
|
107
143
|
console.log(`
|
|
108
|
-
${YELLOW}
|
|
109
|
-
|
|
144
|
+
${YELLOW}⚠${RESET} No .torusguard workspace found in current directory.
|
|
145
|
+
Run ${GREEN}npx torusguard init${RESET} to scaffold full workspace governance.
|
|
110
146
|
`);
|
|
111
147
|
process.exit(0);
|
|
112
148
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: torusguard
|
|
3
|
-
description:
|
|
4
|
-
version: 0.9.
|
|
3
|
+
description: "Autonomous security engine: 71 rules across 11 families, governed remediation (Ponytail Protocol), SARIF v2.1.0 exports, and 5-agent authority separation for Python & TypeScript web applications."
|
|
4
|
+
version: 0.9.5
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# TorusGuard Master Security Router
|
|
Binary file
|
|
@@ -10,7 +10,6 @@ import sys
|
|
|
10
10
|
import shutil
|
|
11
11
|
import json
|
|
12
12
|
import argparse
|
|
13
|
-
import subprocess
|
|
14
13
|
from pathlib import Path
|
|
15
14
|
|
|
16
15
|
# Ensure UTF-8 stdout/stderr on Windows consoles
|
|
@@ -25,6 +24,19 @@ if sys.stderr and hasattr(sys.stderr, "reconfigure"):
|
|
|
25
24
|
except Exception:
|
|
26
25
|
pass
|
|
27
26
|
|
|
27
|
+
# ─── ANSI Color Helpers ───────────────────────────────────────────────────────
|
|
28
|
+
BOLD = "\033[1m"
|
|
29
|
+
DIM = "\033[2m"
|
|
30
|
+
RESET = "\033[0m"
|
|
31
|
+
CYAN = "\033[36m"
|
|
32
|
+
GREEN = "\033[32m"
|
|
33
|
+
YELLOW = "\033[33m"
|
|
34
|
+
WHITE = "\033[97m"
|
|
35
|
+
GRAY = "\033[90m"
|
|
36
|
+
RED = "\033[31m"
|
|
37
|
+
BG_GREEN = "\033[42m"
|
|
38
|
+
BG_CYAN = "\033[46m"
|
|
39
|
+
|
|
28
40
|
|
|
29
41
|
def find_project_root(start_dir=None):
|
|
30
42
|
"""Detect project root directory by searching for standard repo root markers."""
|
|
@@ -45,6 +57,114 @@ def find_project_root(start_dir=None):
|
|
|
45
57
|
return current
|
|
46
58
|
|
|
47
59
|
|
|
60
|
+
def print_header():
|
|
61
|
+
"""Print the branded TorusGuard header card."""
|
|
62
|
+
print(f"""
|
|
63
|
+
{CYAN}╭─────────────────────────────────────────────────────────────────────────╮{RESET}
|
|
64
|
+
{CYAN}│{RESET} {CYAN}│{RESET}
|
|
65
|
+
{CYAN}│{RESET} {BOLD}{WHITE}🛡️ T O R U S G U A R D{RESET} {GRAY}v0.9.5{RESET} {CYAN}│{RESET}
|
|
66
|
+
{CYAN}│{RESET} {DIM}Autonomous Security Engine for AI-Built Applications{RESET} {CYAN}│{RESET}
|
|
67
|
+
{CYAN}│{RESET} {CYAN}│{RESET}
|
|
68
|
+
{CYAN}╰─────────────────────────────────────────────────────────────────────────╯{RESET}
|
|
69
|
+
""")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def print_step_1_assets(file_count):
|
|
73
|
+
"""Print the enhanced Step 1 asset unpacking card."""
|
|
74
|
+
print(f""" {CYAN}┌─ {BOLD}Step 1/3{RESET} {CYAN}──────────────────────── {WHITE}Unpacking Governance Assets{RESET} {CYAN}──────┐{RESET}
|
|
75
|
+
{CYAN}│{RESET} {CYAN}│{RESET}
|
|
76
|
+
{CYAN}│{RESET} {GREEN}✔{RESET} Canonical security rules {DIM}71 rules across 11 families{RESET} {CYAN}│{RESET}
|
|
77
|
+
{CYAN}│{RESET} {GREEN}✔{RESET} JSON validation schemas {DIM}8 formal schemas{RESET} {CYAN}│{RESET}
|
|
78
|
+
{CYAN}│{RESET} {GREEN}✔{RESET} Specialist agent specifications {DIM}5 isolated agents{RESET} {CYAN}│{RESET}
|
|
79
|
+
{CYAN}│{RESET} {GREEN}✔{RESET} Workflow templates {DIM}11 slash commands{RESET} {CYAN}│{RESET}
|
|
80
|
+
{CYAN}│{RESET} {GREEN}✔{RESET} Framework reference guides {DIM}10 security guides{RESET} {CYAN}│{RESET}
|
|
81
|
+
{CYAN}│{RESET} {CYAN}│{RESET}
|
|
82
|
+
{CYAN}│{RESET} {BOLD}{WHITE}{file_count} files unpacked{RESET} {CYAN}│{RESET}
|
|
83
|
+
{CYAN}└───────────────────────────────────────────────────────────────────────┘{RESET}
|
|
84
|
+
""")
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def print_step_2_profile(detected_stack=None):
|
|
88
|
+
"""Print the security profile & coverage card (in-process stack alignment)."""
|
|
89
|
+
if detected_stack and detected_stack.get("framework") and detected_stack.get("framework") != "None":
|
|
90
|
+
fw = str(detected_stack.get("framework"))
|
|
91
|
+
lang = str(detected_stack.get("language", ""))
|
|
92
|
+
label = f"Auto-aligned stack: {fw} ({lang})"
|
|
93
|
+
pad = " " * max(0, 66 - len(label))
|
|
94
|
+
status_line = f" {CYAN}│{RESET} {GREEN}✔{RESET} {BOLD}Auto-aligned stack:{RESET} {WHITE}{fw}{RESET} {DIM}({lang}){RESET}{pad}{CYAN}│{RESET}"
|
|
95
|
+
else:
|
|
96
|
+
status_line = f" {CYAN}│{RESET} {DIM}ℹ Stack auto-detected on first /torusguard-audit run{RESET} {CYAN}│{RESET}"
|
|
97
|
+
|
|
98
|
+
print(f""" {CYAN}┌─ {BOLD}Step 2/3{RESET} {CYAN}──────────────────── {WHITE}Security Profile & Coverage{RESET} {CYAN}────────┐{RESET}
|
|
99
|
+
{CYAN}│{RESET} {CYAN}│{RESET}
|
|
100
|
+
{CYAN}│{RESET} {BOLD}Rule Families:{RESET} {CYAN}│{RESET}
|
|
101
|
+
{CYAN}│{RESET} {YELLOW}TG-SEC{RESET} Secrets & Credentials {YELLOW}TG-DB{RESET} Database Safety {CYAN}│{RESET}
|
|
102
|
+
{CYAN}│{RESET} {YELLOW}TG-INPUT{RESET} Input Validation {YELLOW}TG-AUTH{RESET} Authentication {CYAN}│{RESET}
|
|
103
|
+
{CYAN}│{RESET} {YELLOW}TG-CLIENT{RESET} Client Bundle Leaks {YELLOW}TG-DIFF{RESET} Diff Inspection {CYAN}│{RESET}
|
|
104
|
+
{CYAN}│{RESET} {YELLOW}TG-AGENT{RESET} AI Agent Security {YELLOW}TG-EDGE{RESET} Serverless {CYAN}│{RESET}
|
|
105
|
+
{CYAN}│{RESET} {YELLOW}TG-SUPPLY{RESET} Supply Chain & CI/CD {YELLOW}TG-SSRF{RESET} Outbound Net {CYAN}│{RESET}
|
|
106
|
+
{CYAN}│{RESET} {YELLOW}TG-BIZ{RESET} Business Logic {CYAN}│{RESET}
|
|
107
|
+
{CYAN}│{RESET} {CYAN}│{RESET}
|
|
108
|
+
{CYAN}│{RESET} {BOLD}Supported Stacks:{RESET} {CYAN}│{RESET}
|
|
109
|
+
{CYAN}│{RESET} {GREEN}Python{RESET} Django {DIM}·{RESET} FastAPI {DIM}·{RESET} Flask {DIM}·{RESET} DRF {DIM}·{RESET} SQLAlchemy {CYAN}│{RESET}
|
|
110
|
+
{CYAN}│{RESET} {GREEN}Node.js{RESET} Next.js {DIM}·{RESET} Express {DIM}·{RESET} React {DIM}·{RESET} Supabase {DIM}·{RESET} Firebase {CYAN}│{RESET}
|
|
111
|
+
{CYAN}│{RESET} {CYAN}│{RESET}
|
|
112
|
+
{status_line}
|
|
113
|
+
{CYAN}└───────────────────────────────────────────────────────────────────────┘{RESET}
|
|
114
|
+
""")
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def print_step_3_bridges(registered_ides):
|
|
118
|
+
"""Print the IDE command registration card."""
|
|
119
|
+
lines = ""
|
|
120
|
+
for r in registered_ides:
|
|
121
|
+
lines += f" {CYAN}│{RESET} {GREEN}✔{RESET} {r:<67} {CYAN}│{RESET}\n"
|
|
122
|
+
|
|
123
|
+
print(f""" {CYAN}┌─ {BOLD}Step 3/3{RESET} {CYAN}─────────────────── {WHITE}AI IDE Command Registration{RESET} {CYAN}─────────┐{RESET}
|
|
124
|
+
{CYAN}│{RESET} {CYAN}│{RESET}
|
|
125
|
+
{lines} {CYAN}│{RESET} {CYAN}│{RESET}
|
|
126
|
+
{CYAN}└───────────────────────────────────────────────────────────────────────┘{RESET}
|
|
127
|
+
""")
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def print_success_card():
|
|
131
|
+
"""Print the final success card with next steps."""
|
|
132
|
+
print(f""" {GREEN}╔═══════════════════════════════════════════════════════════════════════╗{RESET}
|
|
133
|
+
{GREEN}║{RESET} {GREEN}║{RESET}
|
|
134
|
+
{GREEN}║{RESET} {GREEN}{BOLD}✅ WORKSPACE INITIALIZED SUCCESSFULLY{RESET} {GREEN}║{RESET}
|
|
135
|
+
{GREEN}║{RESET} {GREEN}║{RESET}
|
|
136
|
+
{GREEN}╠═══════════════════════════════════════════════════════════════════════╣{RESET}
|
|
137
|
+
{GREEN}║{RESET} {GREEN}║{RESET}
|
|
138
|
+
{GREEN}║{RESET} {BOLD}Next Steps:{RESET} {GREEN}║{RESET}
|
|
139
|
+
{GREEN}║{RESET} {GREEN}║{RESET}
|
|
140
|
+
{GREEN}║{RESET} {CYAN}1.{RESET} In AI Chat {WHITE}/torusguard-audit{RESET} or {WHITE}/torusguard{RESET} {GREEN}║{RESET}
|
|
141
|
+
{GREEN}║{RESET} {CYAN}2.{RESET} In Terminal {WHITE}npx torusguard status{RESET} {GREEN}║{RESET}
|
|
142
|
+
{GREEN}║{RESET} {CYAN}3.{RESET} In CI/CD {WHITE}npx torusguard audit{RESET} {GREEN}║{RESET}
|
|
143
|
+
{GREEN}║{RESET} {GREEN}║{RESET}
|
|
144
|
+
{GREEN}║{RESET} {DIM}Docs{RESET} {CYAN}https://github.com/githubmofo/TorusGuard{RESET} {GREEN}║{RESET}
|
|
145
|
+
{GREEN}║{RESET} {DIM}NPM{RESET} {CYAN}https://npmjs.com/package/torusguard{RESET} {GREEN}║{RESET}
|
|
146
|
+
{GREEN}║{RESET} {GREEN}║{RESET}
|
|
147
|
+
{GREEN}╚═══════════════════════════════════════════════════════════════════════╝{RESET}
|
|
148
|
+
""")
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def print_already_initialized(target_root, cfg):
|
|
152
|
+
"""Print the already-initialized status card."""
|
|
153
|
+
print(f"""
|
|
154
|
+
{CYAN}╭─────────────────────────────────────────────────────────────────────────╮{RESET}
|
|
155
|
+
{CYAN}│{RESET} {BOLD}{WHITE}🛡️ TORUSGUARD WORKSPACE{RESET} {GREEN}[Active]{RESET} {CYAN}│{RESET}
|
|
156
|
+
{CYAN}╰─────────────────────────────────────────────────────────────────────────╯{RESET}
|
|
157
|
+
|
|
158
|
+
{BOLD}▸ Project Root:{RESET} {GREEN}{target_root}{RESET}
|
|
159
|
+
{BOLD}▸ Workspace:{RESET} {GREEN}.torusguard/{RESET} {DIM}(Already Initialized){RESET}
|
|
160
|
+
{BOLD}▸ Version:{RESET} {CYAN}{cfg.get('version', '0.9.5')}{RESET}
|
|
161
|
+
{BOLD}▸ Severity Floor:{RESET} {YELLOW}{cfg.get('severity_threshold', 'medium')}{RESET}
|
|
162
|
+
|
|
163
|
+
{DIM}To refresh templates or re-scaffold, run:{RESET}
|
|
164
|
+
{CYAN}npx torusguard init --force{RESET}
|
|
165
|
+
""")
|
|
166
|
+
|
|
167
|
+
|
|
48
168
|
def scaffold_workspace(target_root=None, force=False, full_commands=False):
|
|
49
169
|
"""Scaffold the .torusguard workspace into the target project root."""
|
|
50
170
|
target_root = Path(target_root or find_project_root()).resolve()
|
|
@@ -53,40 +173,25 @@ def scaffold_workspace(target_root=None, force=False, full_commands=False):
|
|
|
53
173
|
payload_dir = script_dir / "payload"
|
|
54
174
|
|
|
55
175
|
if torusguard_target.exists() and not force:
|
|
56
|
-
print("""
|
|
57
|
-
╭──────────────────────────────────────────────────────────────────────────╮
|
|
58
|
-
│ 🛡️ TORUSGUARD WORKSPACE STATUS [Active] │
|
|
59
|
-
╰──────────────────────────────────────────────────────────────────────────╯
|
|
60
|
-
""")
|
|
61
|
-
print(f" ▸ Project Root: {target_root}")
|
|
62
|
-
print(f" ▸ Workspace: .torusguard/ (Already Initialized)")
|
|
63
176
|
config_file = torusguard_target / "config" / "torusguard.json"
|
|
177
|
+
cfg = {}
|
|
64
178
|
if config_file.exists():
|
|
65
179
|
try:
|
|
66
180
|
with open(config_file, "r", encoding="utf-8") as f:
|
|
67
181
|
cfg = json.load(f)
|
|
68
|
-
print(f" ▸ Version: {cfg.get('version', '0.9.3')}")
|
|
69
|
-
print(f" ▸ Severity Floor: {cfg.get('severity_threshold', 'medium')}")
|
|
70
182
|
except Exception:
|
|
71
183
|
pass
|
|
72
|
-
|
|
73
|
-
💡 Workspace already exists. To refresh templates or re-scaffold, run:
|
|
74
|
-
npx torusguard init --force
|
|
75
|
-
""")
|
|
184
|
+
print_already_initialized(target_root, cfg)
|
|
76
185
|
return True
|
|
77
186
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
╰──────────────────────────────────────────────────────────────────────────╯
|
|
83
|
-
""")
|
|
84
|
-
print(f" ▸ Target Project: {target_root}")
|
|
85
|
-
print(f" ▸ Destination: {torusguard_target}")
|
|
187
|
+
# ── Header ──────────────────────────────────────────────────────────────
|
|
188
|
+
print_header()
|
|
189
|
+
print(f" {BOLD}▸ Target Project:{RESET} {WHITE}{target_root}{RESET}")
|
|
190
|
+
print(f" {BOLD}▸ Destination:{RESET} {WHITE}{torusguard_target}{RESET}")
|
|
86
191
|
|
|
87
|
-
# 1
|
|
192
|
+
# ── Step 1: Unpack Payload ──────────────────────────────────────────────
|
|
193
|
+
file_count = 93
|
|
88
194
|
if payload_dir.is_dir():
|
|
89
|
-
print("\n ▸ Step 1/3: Unpacking Offline Governance Assets...")
|
|
90
195
|
try:
|
|
91
196
|
if torusguard_target.exists() and force:
|
|
92
197
|
shutil.rmtree(torusguard_target)
|
|
@@ -95,22 +200,25 @@ def scaffold_workspace(target_root=None, force=False, full_commands=False):
|
|
|
95
200
|
torusguard_target,
|
|
96
201
|
ignore=shutil.ignore_patterns("runs", "*.pyc", "__pycache__", ".git*")
|
|
97
202
|
)
|
|
98
|
-
|
|
203
|
+
# Count actual files
|
|
204
|
+
file_count = sum(1 for _ in torusguard_target.rglob("*") if _.is_file())
|
|
99
205
|
except Exception as e:
|
|
100
|
-
print(f"
|
|
206
|
+
print(f"\n {RED}✖ Failed to unpack payload: {e}{RESET}")
|
|
101
207
|
return False
|
|
102
208
|
else:
|
|
103
209
|
# Fallback: create base structure
|
|
104
|
-
print("\n1. Bundled payload not found. Creating core skeleton...")
|
|
105
210
|
subdirs = [
|
|
106
211
|
"config", "agents", "workflows", "scripts", "templates",
|
|
107
212
|
"schemas", "references", "rules/active", "runs"
|
|
108
213
|
]
|
|
109
214
|
for s in subdirs:
|
|
110
215
|
(torusguard_target / s).mkdir(parents=True, exist_ok=True)
|
|
111
|
-
|
|
216
|
+
file_count = 0
|
|
112
217
|
|
|
113
|
-
|
|
218
|
+
print()
|
|
219
|
+
print_step_1_assets(file_count)
|
|
220
|
+
|
|
221
|
+
# ── Ensure runs and rules/active directories exist ──────────────────────
|
|
114
222
|
runs_dir = torusguard_target / "runs"
|
|
115
223
|
runs_dir.mkdir(parents=True, exist_ok=True)
|
|
116
224
|
gitkeep_runs = runs_dir / ".gitkeep"
|
|
@@ -123,50 +231,51 @@ def scaffold_workspace(target_root=None, force=False, full_commands=False):
|
|
|
123
231
|
if not gitkeep_rules.exists():
|
|
124
232
|
gitkeep_rules.write_text("", encoding="utf-8")
|
|
125
233
|
|
|
126
|
-
#
|
|
127
|
-
|
|
234
|
+
# ── Step 2: Security Profile & Coverage (In-Process, Zero Subprocess) ──
|
|
235
|
+
# Execute stack detection in-process without spawning child processes (Socket.dev safe)
|
|
236
|
+
detected_stack = None
|
|
128
237
|
stack_detect_script = torusguard_target / "scripts" / "stack_detect.py"
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if stack_detect_script.exists():
|
|
238
|
+
if stack_detect_script.is_file():
|
|
132
239
|
try:
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
print(f" ⎿ Framework: {detected_stack.get('framework')}")
|
|
143
|
-
print(f" ⎿ Data Layer: {detected_stack.get('data_layer')}")
|
|
144
|
-
except Exception as e:
|
|
145
|
-
print(f" ⚠ Stack detection warning: {e}")
|
|
240
|
+
import importlib.util
|
|
241
|
+
spec = importlib.util.spec_from_file_location("stack_detect", str(stack_detect_script))
|
|
242
|
+
if spec and spec.loader:
|
|
243
|
+
sd_mod = importlib.util.module_from_spec(spec)
|
|
244
|
+
spec.loader.exec_module(sd_mod)
|
|
245
|
+
if hasattr(sd_mod, "detect_stack"):
|
|
246
|
+
detected_stack = sd_mod.detect_stack(target_root)
|
|
247
|
+
except Exception:
|
|
248
|
+
detected_stack = None
|
|
146
249
|
|
|
147
|
-
# 4. Update torusguard.json configuration
|
|
148
250
|
config_file = torusguard_target / "config" / "torusguard.json"
|
|
149
251
|
if config_file.exists():
|
|
150
252
|
try:
|
|
151
253
|
with open(config_file, "r", encoding="utf-8") as f:
|
|
152
254
|
cfg = json.load(f)
|
|
153
|
-
|
|
154
|
-
"
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
255
|
+
if detected_stack and detected_stack.get("framework") != "None":
|
|
256
|
+
cfg["detected_stack"] = {
|
|
257
|
+
"language": detected_stack.get("language"),
|
|
258
|
+
"framework": detected_stack.get("framework"),
|
|
259
|
+
"data_layer": detected_stack.get("data_layer")
|
|
260
|
+
}
|
|
261
|
+
else:
|
|
262
|
+
cfg["detected_stack"] = {
|
|
263
|
+
"language": "Unknown",
|
|
264
|
+
"framework": "None",
|
|
265
|
+
"data_layer": "None"
|
|
266
|
+
}
|
|
158
267
|
with open(config_file, "w", encoding="utf-8") as f:
|
|
159
268
|
json.dump(cfg, f, indent=2)
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
print(f" ⚠ Config update error: {e}")
|
|
269
|
+
except Exception:
|
|
270
|
+
pass
|
|
163
271
|
|
|
164
|
-
|
|
165
|
-
|
|
272
|
+
print_step_2_profile(detected_stack)
|
|
273
|
+
|
|
274
|
+
# ── Step 3: Register Slash Commands for AI IDEs ─────────────────────────
|
|
166
275
|
registered_ides = []
|
|
167
276
|
tg_workflow_content = """---
|
|
168
277
|
description: TorusGuard Autonomous Security Command Engine — run static security audits, authorized runtime web validation, governed remediation, and SARIF exports.
|
|
169
|
-
version: 0.9.
|
|
278
|
+
version: 0.9.5
|
|
170
279
|
tools: Read, Grep, Glob, Bash, Edit, Write
|
|
171
280
|
agent: auditor
|
|
172
281
|
---
|
|
@@ -192,16 +301,16 @@ Parse the requested action from `$ARGUMENTS` (e.g. `audit`, `verify`, `web-valid
|
|
|
192
301
|
agents_wf.mkdir(parents=True, exist_ok=True)
|
|
193
302
|
(agents_wf / "torusguard.md").write_text(tg_workflow_content, encoding="utf-8")
|
|
194
303
|
dest_workflow_dirs.append(agents_wf)
|
|
195
|
-
registered_ides.append("Antigravity / Gemini
|
|
304
|
+
registered_ides.append("Antigravity / Gemini .agents/workflows/torusguard.md")
|
|
196
305
|
|
|
197
306
|
agent_wf = target_root / ".agent" / "workflows"
|
|
198
307
|
agent_wf.mkdir(parents=True, exist_ok=True)
|
|
199
308
|
(agent_wf / "torusguard.md").write_text(tg_workflow_content, encoding="utf-8")
|
|
200
309
|
dest_workflow_dirs.append(agent_wf)
|
|
201
|
-
registered_ides.append("
|
|
310
|
+
registered_ides.append("Tribunal Agent Kit .agent/workflows/torusguard.md")
|
|
202
311
|
|
|
203
312
|
# When full_commands is requested (e.g. via NPM package npx torusguard init),
|
|
204
|
-
# unlock and register all 11 individual slash commands
|
|
313
|
+
# unlock and register all 11 individual slash commands
|
|
205
314
|
if full_commands:
|
|
206
315
|
src_wf = torusguard_target / "workflows"
|
|
207
316
|
if src_wf.is_dir():
|
|
@@ -213,7 +322,7 @@ Parse the requested action from `$ARGUMENTS` (e.g. `audit`, `verify`, `web-valid
|
|
|
213
322
|
for d in dest_workflow_dirs:
|
|
214
323
|
shutil.copy2(wf_file, d / cmd_filename)
|
|
215
324
|
count += 1
|
|
216
|
-
registered_ides.append(f"
|
|
325
|
+
registered_ides.append(f"{count} Slash Commands /torusguard-audit, -harden, -apply, ...")
|
|
217
326
|
|
|
218
327
|
# Claude Code (.claude/commands)
|
|
219
328
|
claude_dir = target_root / ".claude"
|
|
@@ -221,7 +330,7 @@ Parse the requested action from `$ARGUMENTS` (e.g. `audit`, `verify`, `web-valid
|
|
|
221
330
|
claude_commands = claude_dir / "commands"
|
|
222
331
|
claude_commands.mkdir(parents=True, exist_ok=True)
|
|
223
332
|
(claude_commands / "torusguard.md").write_text(tg_workflow_content, encoding="utf-8")
|
|
224
|
-
registered_ides.append("Claude Code
|
|
333
|
+
registered_ides.append("Claude Code .claude/commands/torusguard.md")
|
|
225
334
|
|
|
226
335
|
# Cursor (.cursor/rules)
|
|
227
336
|
cursor_dir = target_root / ".cursor"
|
|
@@ -229,7 +338,7 @@ Parse the requested action from `$ARGUMENTS` (e.g. `audit`, `verify`, `web-valid
|
|
|
229
338
|
cursor_rules = cursor_dir / "rules"
|
|
230
339
|
cursor_rules.mkdir(parents=True, exist_ok=True)
|
|
231
340
|
(cursor_rules / "torusguard.mdc").write_text(tg_workflow_content, encoding="utf-8")
|
|
232
|
-
registered_ides.append("Cursor
|
|
341
|
+
registered_ides.append("Cursor .cursor/rules/torusguard.mdc")
|
|
233
342
|
|
|
234
343
|
# Windsurf (.windsurfrules)
|
|
235
344
|
if (target_root / ".windsurfrules").exists() or (target_root / ".windsurf").exists():
|
|
@@ -237,7 +346,7 @@ Parse the requested action from `$ARGUMENTS` (e.g. `audit`, `verify`, `web-valid
|
|
|
237
346
|
current_content = windsurf_rules.read_text(encoding="utf-8") if windsurf_rules.exists() else ""
|
|
238
347
|
if "TorusGuard" not in current_content:
|
|
239
348
|
windsurf_rules.write_text(current_content + "\n\n" + tg_workflow_content, encoding="utf-8")
|
|
240
|
-
registered_ides.append("Windsurf
|
|
349
|
+
registered_ides.append("Windsurf .windsurfrules")
|
|
241
350
|
|
|
242
351
|
# VS Code / GitHub Copilot (.github/copilot-instructions.md)
|
|
243
352
|
github_dir = target_root / ".github"
|
|
@@ -246,28 +355,19 @@ Parse the requested action from `$ARGUMENTS` (e.g. `audit`, `verify`, `web-valid
|
|
|
246
355
|
current_content = copilot_file.read_text(encoding="utf-8") if copilot_file.exists() else ""
|
|
247
356
|
if "TorusGuard" not in current_content:
|
|
248
357
|
copilot_file.write_text(current_content + "\n\n# TorusGuard Security Instructions\n" + tg_workflow_content, encoding="utf-8")
|
|
249
|
-
registered_ides.append("VS Code / Copilot
|
|
358
|
+
registered_ides.append("VS Code / Copilot .github/copilot-instructions.md")
|
|
250
359
|
|
|
251
360
|
# Universal AGENTS.md (Kimi, Codex, Open Agent Standard)
|
|
252
361
|
agents_md = target_root / "AGENTS.md"
|
|
253
362
|
current_agents = agents_md.read_text(encoding="utf-8") if agents_md.exists() else ""
|
|
254
363
|
if "TorusGuard" not in current_agents:
|
|
255
364
|
agents_md.write_text(current_agents + ("\n\n" if current_agents else "") + "# TorusGuard Security Guardrails\n\nRun `/torusguard audit` to scan the codebase or refer to `.torusguard/` for security guidelines.\n", encoding="utf-8")
|
|
256
|
-
registered_ides.append("Universal
|
|
365
|
+
registered_ides.append("Universal AGENTS.md Kimi / Open Agent Standard")
|
|
257
366
|
|
|
258
|
-
|
|
259
|
-
print(f" ✔ {r}")
|
|
367
|
+
print_step_3_bridges(registered_ides)
|
|
260
368
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
│ ✨ TorusGuard Workspace Initialized Successfully! │
|
|
264
|
-
│ │
|
|
265
|
-
│ 🚀 Next Steps: │
|
|
266
|
-
│ 1. In AI Chat: Type `/torusguard-audit` or `/torusguard` to scan │
|
|
267
|
-
│ 2. In Terminal: Run `npx torusguard status` for security posture │
|
|
268
|
-
│ 3. In CI/CD: Run `npx torusguard audit` to generate SARIF data │
|
|
269
|
-
╰──────────────────────────────────────────────────────────────────────────╯
|
|
270
|
-
""")
|
|
369
|
+
# ── Success Card ────────────────────────────────────────────────────────
|
|
370
|
+
print_success_card()
|
|
271
371
|
return True
|
|
272
372
|
|
|
273
373
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"agents/validator.md": "79fc4431de5c5507f8730aee6c5c3e61fd238cbf8cf8c7c6aac462eee9761ed6",
|
|
9
9
|
"config/scope.json": "b198a86186b4c6d5e1af516bf4e3a6afa8878e622ca1d57a5bf72d294f8c6f25",
|
|
10
10
|
"config/slash-commands.json": "5390f0d26f8117a62e56c58147d3a0d2deab1a20956302b212703281d13fa84e",
|
|
11
|
-
"config/torusguard.json": "
|
|
11
|
+
"config/torusguard.json": "077bc6a948f9420aded8dba248577ff3ebf054cab64cf538a7a6d05223fe27bc",
|
|
12
12
|
"references/django-security.md": "a15b7eb11b51dd1970d3d65544cf79ebea91fb99dc0e085e58a56532a718dce7",
|
|
13
13
|
"references/drf-security.md": "c7a7af3acaef895bf4798590acc88b3a2e9831a49eb2d23b4d8f31540ab264cc",
|
|
14
14
|
"references/express-security.md": "dff1db15e614d29d8c272f9da345b418077e62dc883fe210c7a50c552c76493f",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"scripts/safety_gate.py": "3379b7534b2590cf563717a448983ad8ed7e8f174f0ad65683d33e8a10f51558",
|
|
41
41
|
"scripts/sarif_exporter.py": "35c66637413afc4b72d5bd426638447c77231d2a8594dce5addceffd4803a20d",
|
|
42
42
|
"scripts/stack_detect.py": "99b7bdf9829d58ff5b8c59afd6e8b6429bbb11d830ac73dec491101cbbc41574",
|
|
43
|
-
"skills/torusguard/SKILL.md": "
|
|
43
|
+
"skills/torusguard/SKILL.md": "31a115886ffb115f2b975c4d0670e780e11ea68201559b24b20d0d0ef456058f",
|
|
44
44
|
"skills/torusguard/bootstrap.py": "7e348065a622089ab1d51e9bf4864e5b0022aaee1ccb2ecbf7057c14e792e2c7",
|
|
45
45
|
"skills/torusguard/references/auth-and-sessions.md": "34c2843f8c0dbe3574e54f00a39a92a1f431527ec5f69b2d64c84240d424a39e",
|
|
46
46
|
"skills/torusguard/references/business-logic-and-abuse.md": "0d6088936bc1a01023070332fccef0f2e0734358a5119379055f3d2895c22567",
|
|
Binary file
|
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: torusguard
|
|
3
|
-
description:
|
|
4
|
-
version: 0.9.
|
|
3
|
+
description: "Autonomous security engine: 71 rules across 11 families, governed remediation (Ponytail Protocol), SARIF v2.1.0 exports, and 5-agent authority separation for Python & TypeScript web applications."
|
|
4
|
+
version: 0.9.5
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# TorusGuard Master Router
|
|
7
|
+
# TorusGuard Master Security Router
|
|
8
8
|
|
|
9
|
-
**Principle:** If the browser receives it, users can inspect it. Keep secrets,
|
|
9
|
+
**Principle:** If the browser receives it, users can inspect it. Keep secrets, database queries, and authorization strictly on trusted server-side code.
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
## ⚡ Workspace Bootstrap Check
|
|
14
|
-
1. **If `.torusguard/` exists:**
|
|
15
|
-
2. **If `.torusguard/` is
|
|
14
|
+
1. **If `.torusguard/` exists on disk:** Full governance active. Route slash commands to local specialist workflows below.
|
|
15
|
+
2. **If `.torusguard/` is absent (Autonomous AI Mode):** Operates standalone in any AI agent (Kimi, Antigravity, VS Code, Cursor). Apply in-memory security invariants:
|
|
16
|
+
- Server-side auth & tenant scoping (`.filter(tenant=...)`).
|
|
17
|
+
- Zero client-side secrets (`SUPABASE_SERVICE_ROLE_KEY`, live API keys).
|
|
18
|
+
- Ponytail Protocol patch limits ($\le 35$ additions, $\le 25$ deletions).
|
|
19
|
+
- *Upgrade:* Run `npx torusguard init` to unlock local `.torusguard/` run tracking & individual commands.
|
|
16
20
|
|
|
17
21
|
---
|
|
18
22
|
|
|
19
23
|
## Specialist Skill Routing (Lazy Loading)
|
|
20
|
-
Load **only** the designated sub-skill
|
|
24
|
+
Load **only** the designated sub-skill on demand to preserve the 1,000–1,500 token budget:
|
|
21
25
|
|
|
22
26
|
| Command | Specialist Skill | Agent |
|
|
23
27
|
| :--- | :--- | :--- |
|