trace-sec 2.1.7 → 2.1.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trace-sec",
3
- "version": "2.1.7",
3
+ "version": "2.1.9",
4
4
  "description": "Threat Reconnaissance & Attack-path Correlation Engine — Security Verification Layer for Coding Agents with Fine-Tuned SecureBERT 2.0 & Laya AI",
5
5
  "type": "module",
6
6
  "main": "bin/trace.js",
@@ -69,14 +69,10 @@ console = Console()
69
69
 
70
70
  @app.callback()
71
71
  def main(ctx: typer.Context):
72
- """If no command is provided, launch interactive story mode (or show banner if non-interactive)."""
72
+ """If no command is provided, launch the interactive TRACE security terminal."""
73
73
  if ctx.invoked_subcommand is None:
74
- if sys.stdin.isatty():
75
- from trace_engine.interactive import run_interactive_story
76
- run_interactive_story()
77
- else:
78
- print_banner()
79
- print_security_notes()
74
+ from trace_engine.interactive import run_interactive_story
75
+ run_interactive_story()
80
76
 
81
77
 
82
78
  @app.command(name="interactive")
@@ -87,11 +87,15 @@ def render_big_logo() -> Text:
87
87
 
88
88
  def render_big_banner(animated: bool = False) -> None:
89
89
  """Renders the sleek minimalist TRACE banner in Mint Green and Crisp White."""
90
+ from trace_engine.intelligence.downloader import is_environment_ready
91
+ models_ready = is_environment_ready()
92
+
90
93
  console.print()
91
94
  console.print(render_big_logo())
92
- console.print(f" [{BOLD_WHITE}]Threat Reconnaissance & Attack-path Correlation Engine[/{BOLD_WHITE}] [{GREEN}]v2.1.0[/{GREEN}]")
95
+ console.print(f" [{BOLD_WHITE}]Threat Reconnaissance & Attack-path Correlation Engine[/{BOLD_WHITE}] [{GREEN}]v2.1.8[/{GREEN}]")
93
96
  console.print(f" [{DIM_WHITE}]Autonomous Neuro-Symbolic Security Intelligence & Live Verification[/{DIM_WHITE}]")
94
- console.print(f" [{GREEN}]● 100% Offline[/{GREEN}] [{WHITE}]•[/{WHITE}] [{GREEN}]● Zero External Telemetry[/{GREEN}] [{WHITE}]•[/{WHITE}] [{GREEN}]● SecureBERT & Laya AI Active[/{GREEN}]")
97
+ ai_status = f"[{GREEN}]● SecureBERT & Laya AI Active[/{GREEN}]" if models_ready else f"[{ORANGE}]● Neural Weights: Optional (AST Semantic Engine Active)[/{ORANGE}]"
98
+ console.print(f" [{GREEN}]● 100% Offline[/{GREEN}] [{WHITE}]•[/{WHITE}] [{GREEN}]● Zero External Telemetry[/{GREEN}] [{WHITE}]•[/{WHITE}] {ai_status}")
95
99
  console.print(f" [{DIM_GREEN}]{'─' * 76}[/{DIM_GREEN}]\n")
96
100
  if animated:
97
101
  time.sleep(0.08)
@@ -123,12 +127,19 @@ def ask_input(
123
127
  "QUIT",
124
128
  "Q",
125
129
  ]
126
- val = Prompt.ask(
127
- prompt_str,
128
- choices=allowed_choices,
129
- default=default,
130
- show_default=show_default,
131
- )
130
+ try:
131
+ val = Prompt.ask(
132
+ prompt_str,
133
+ choices=allowed_choices,
134
+ default=default,
135
+ show_default=show_default,
136
+ )
137
+ except (EOFError, KeyboardInterrupt):
138
+ if default is not None:
139
+ return default
140
+ console.print(f"\n [{GREEN}]✓ TRACE session closed. Happy hacking![/{GREEN}]\n")
141
+ sys.exit(0)
142
+
132
143
  if str(val).strip().lower() in ("exit", "quit", "q", ":q"):
133
144
  console.print(
134
145
  f"\n [{GREEN}]✓ TRACE session closed. Happy hacking![/{GREEN}]\n"
@@ -278,9 +289,8 @@ def run_interactive_story() -> None:
278
289
  """Executes the complete interactive, step-by-step security audit story."""
279
290
  render_big_banner(animated=True)
280
291
 
281
- from trace_engine.intelligence.downloader import prompt_and_bootstrap_models
282
- if not prompt_and_bootstrap_models(interactive=True):
283
- return
292
+ from trace_engine.intelligence.downloader import is_environment_ready, ensure_all_models
293
+ models_ready = is_environment_ready()
284
294
 
285
295
  console.print(f" [{WHITE}]Welcome, Security Operator. TRACE stands ready to audit, verify, and heal codebases.[/{WHITE}]")
286
296
  console.print(f" [{DIM_WHITE}]Navigate using the options below (type 'exit' or 'q' at any prompt to quit).[/{DIM_WHITE}]\n")
@@ -289,25 +299,42 @@ def run_interactive_story() -> None:
289
299
  # STEP 1: Mission Selection
290
300
  # =========================================================================
291
301
  console.print(f" [{BOLD_WHITE}]Select Audit Mission:[/{BOLD_WHITE}]")
292
- console.print(f" [{ORANGE}][1][/{ORANGE}] [{BOLD_WHITE}]Full Security Audit[/{BOLD_WHITE}] [{GREEN}]★ RECOMMENDED[/{GREEN}] [{DIM_WHITE}]─ Multi-language AST, APM graph, & Neural AI[/{DIM_WHITE}]")
302
+ console.print(f" [{ORANGE}][1][/{ORANGE}] [{BOLD_WHITE}]Full Security Audit[/{BOLD_WHITE}] [{GREEN}]★ RECOMMENDED[/{GREEN}] [{DIM_WHITE}]─ Multi-language AST, APM graph, & Security Hypotheses[/{DIM_WHITE}]")
293
303
  console.print(f" [{ORANGE}][2][/{ORANGE}] [{BOLD_WHITE}]Targeted Vulnerability Probes[/{BOLD_WHITE}] [{DIM_WHITE}]─ Select specific testpacks (BOLA, SQLi, SSRF, BFLA)[/{DIM_WHITE}]")
294
304
  console.print(f" [{ORANGE}][3][/{ORANGE}] [{BOLD_WHITE}]Autonomous AST Self-Healing[/{BOLD_WHITE}] [{DIM_WHITE}]─ Surgical refactoring with live rollback verification[/{DIM_WHITE}]")
295
305
  console.print(f" [{ORANGE}][4][/{ORANGE}] [{BOLD_WHITE}]Start Claude Code Local MCP Server[/{BOLD_WHITE}] [{GREEN}]★ LOCAL MCP[/{GREEN}] [{DIM_WHITE}]─ Run HTTP/SSE bridge for Claude Code chat[/{DIM_WHITE}]")
296
- console.print(f" [{ORANGE}][5][/{ORANGE}] [{BOLD_WHITE}]How TRACE Works & Architecture Guide[/{BOLD_WHITE}] [{DIM_WHITE}]─ Interactive architectural diagram & neural models[/{DIM_WHITE}]")
306
+ console.print(f" [{ORANGE}][5][/{ORANGE}] [{BOLD_WHITE}]How TRACE Works & Architecture Guide[/{BOLD_WHITE}] [{DIM_WHITE}]─ Interactive architectural diagram & operational FAQ[/{DIM_WHITE}]")
297
307
  console.print(f" [{ORANGE}][6][/{ORANGE}] [{BOLD_WHITE}]Environment Diagnostics (Doctor)[/{BOLD_WHITE}] [{DIM_WHITE}]─ Inspect local security tools and dependencies[/{DIM_WHITE}]")
298
- console.print(f" [{ORANGE}][7][/{ORANGE}] [{BOLD_WHITE}]Exit[/{BOLD_WHITE}]\n")
308
+ if not models_ready:
309
+ console.print(f" [{ORANGE}][7][/{ORANGE}] [{BOLD_WHITE}]Download Neural Weights[/{BOLD_WHITE}] [{DIM_WHITE}]─ Provision ~1 GB SecureBERT 2.0 & Laya AI into ~/.trace/models[/{DIM_WHITE}]")
310
+ console.print(f" [{ORANGE}][8][/{ORANGE}] [{BOLD_WHITE}]Exit[/{BOLD_WHITE}]\n")
311
+ valid_choices = ["1", "2", "3", "4", "5", "6", "7", "8"]
312
+ else:
313
+ console.print(f" [{ORANGE}][7][/{ORANGE}] [{BOLD_WHITE}]Exit[/{BOLD_WHITE}]\n")
314
+ valid_choices = ["1", "2", "3", "4", "5", "6", "7"]
299
315
 
300
316
  choice = ask_input(
301
317
  f" [{ORANGE}]›[/{ORANGE}] [{BOLD_WHITE}]Choose option[/{BOLD_WHITE}]",
302
- choices=["1", "2", "3", "4", "5", "6", "7"],
318
+ choices=valid_choices,
303
319
  default="1",
304
320
  show_default=True,
305
321
  )
306
322
 
307
- if choice == "7":
323
+ if (not models_ready and choice == "8") or (models_ready and choice == "7"):
308
324
  console.print(f"\n [{GREEN}]✓ TRACE session closed. Happy hacking![/{GREEN}]\n")
309
325
  return
310
326
 
327
+ if not models_ready and choice == "7":
328
+ display_story_header(2, 2, "Neural Model Provisioning", "Downloading fine-tuned SecureBERT 2.0 & Laya AI from GitHub LFS Hub")
329
+ console.print(f" [{WHITE}]Downloading fine-tuned neural models into ~/.trace/models/...[/{WHITE}]")
330
+ try:
331
+ ensure_all_models()
332
+ console.print(f"\n [{GREEN}]✓ Neural models provisioned successfully. SecureBERT & Laya are now online![/{GREEN}]\n")
333
+ except Exception as e:
334
+ console.print(f"\n [{ORANGE}][!] Download could not complete:[/{ORANGE}] [{WHITE}]{e}[/{WHITE}]")
335
+ console.print(f" [{DIM_WHITE}]You can continue using TRACE with the built-in deterministic AST & semantic engine.[/{DIM_WHITE}]\n")
336
+ return
337
+
311
338
  if choice == "4":
312
339
  from trace_engine.mcp.server import TraceMCPServer
313
340
  mcp_obj = TraceMCPServer()
@@ -484,7 +511,8 @@ def run_interactive_story() -> None:
484
511
 
485
512
  # Phase 3: Neuro-Symbolic Bayesian Hypotheses with Real Models
486
513
  model_metrics: Dict[str, Any] = {}
487
- with console.status(f" [{GREEN}]Act III:[/{GREEN}] [{WHITE}]Evaluating SecureBERT 2.0 & Laya System 1 Neural Models on GPU...[/{WHITE}]", spinner="dots"):
514
+ act3_status = "Evaluating SecureBERT 2.0 & Laya System 1 Neural Models..." if models_ready else "Evaluating Security Hypotheses with AST Semantic Engine..."
515
+ with console.status(f" [{GREEN}]Act III:[/{GREEN}] [{WHITE}]{act3_status}[/{WHITE}]", spinner="dots"):
488
516
  engine = HypothesisEngine()
489
517
  all_hypotheses = engine.derive_hypotheses(graph_model, discovered_endpoints)
490
518
 
@@ -518,8 +546,9 @@ def run_interactive_story() -> None:
518
546
  "laya": {"inferences": len(discovered_endpoints), "avg_latency_ms": 0.5, "breakdown": "Evaluated across P0/P1/P2/P3", "available": True},
519
547
  }
520
548
 
549
+ engine_label = "via SecureBERT & Laya" if models_ready else "via AST Semantic Engine"
521
550
  console.print(
522
- f" [{GREEN}]✓ Act III (Neural AI & Hypotheses):[/{GREEN}] [{BOLD_WHITE}]Derived {len(hypotheses)} threat hypotheses[/{BOLD_WHITE}] [{DIM_WHITE}]via SecureBERT & Laya[/{DIM_WHITE}]"
551
+ f" [{GREEN}]✓ Act III (Security Hypotheses):[/{GREEN}] [{BOLD_WHITE}]Derived {len(hypotheses)} threat hypotheses[/{BOLD_WHITE}] [{DIM_WHITE}]{engine_label}[/{DIM_WHITE}]"
523
552
  )
524
553
 
525
554
  # Phase 4: Dynamic Exploit Probes