raxe 0.4.6__py3-none-any.whl

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 (668) hide show
  1. raxe/__init__.py +101 -0
  2. raxe/application/__init__.py +48 -0
  3. raxe/application/ab_testing.py +170 -0
  4. raxe/application/analytics/__init__.py +30 -0
  5. raxe/application/analytics/achievement_service.py +444 -0
  6. raxe/application/analytics/repositories.py +172 -0
  7. raxe/application/analytics/retention_service.py +267 -0
  8. raxe/application/analytics/statistics_service.py +419 -0
  9. raxe/application/analytics/streak_service.py +283 -0
  10. raxe/application/apply_policy.py +291 -0
  11. raxe/application/eager_l2.py +503 -0
  12. raxe/application/preloader.py +353 -0
  13. raxe/application/scan_merger.py +321 -0
  14. raxe/application/scan_pipeline.py +1059 -0
  15. raxe/application/scan_pipeline_async.py +403 -0
  16. raxe/application/session_tracker.py +458 -0
  17. raxe/application/telemetry_manager.py +357 -0
  18. raxe/application/telemetry_orchestrator.py +1210 -0
  19. raxe/async_sdk/__init__.py +34 -0
  20. raxe/async_sdk/cache.py +286 -0
  21. raxe/async_sdk/client.py +556 -0
  22. raxe/async_sdk/wrappers/__init__.py +23 -0
  23. raxe/async_sdk/wrappers/openai.py +238 -0
  24. raxe/cli/__init__.py +21 -0
  25. raxe/cli/auth.py +1047 -0
  26. raxe/cli/branding.py +235 -0
  27. raxe/cli/config.py +334 -0
  28. raxe/cli/custom_rules.py +458 -0
  29. raxe/cli/doctor.py +686 -0
  30. raxe/cli/error_handler.py +665 -0
  31. raxe/cli/event.py +648 -0
  32. raxe/cli/exit_codes.py +57 -0
  33. raxe/cli/expiry_warning.py +302 -0
  34. raxe/cli/export.py +183 -0
  35. raxe/cli/history.py +247 -0
  36. raxe/cli/l2_formatter.py +872 -0
  37. raxe/cli/main.py +1137 -0
  38. raxe/cli/models.py +590 -0
  39. raxe/cli/output.py +403 -0
  40. raxe/cli/privacy.py +84 -0
  41. raxe/cli/profiler.py +262 -0
  42. raxe/cli/progress.py +379 -0
  43. raxe/cli/progress_context.py +101 -0
  44. raxe/cli/repl.py +394 -0
  45. raxe/cli/rules.py +542 -0
  46. raxe/cli/setup_wizard.py +721 -0
  47. raxe/cli/stats.py +292 -0
  48. raxe/cli/suppress.py +501 -0
  49. raxe/cli/telemetry.py +1384 -0
  50. raxe/cli/test.py +130 -0
  51. raxe/cli/tune.py +315 -0
  52. raxe/cli/validate.py +218 -0
  53. raxe/domain/__init__.py +30 -0
  54. raxe/domain/analytics/__init__.py +97 -0
  55. raxe/domain/analytics/achievements.py +306 -0
  56. raxe/domain/analytics/models.py +120 -0
  57. raxe/domain/analytics/retention.py +168 -0
  58. raxe/domain/analytics/statistics.py +207 -0
  59. raxe/domain/analytics/streaks.py +173 -0
  60. raxe/domain/engine/__init__.py +15 -0
  61. raxe/domain/engine/executor.py +396 -0
  62. raxe/domain/engine/matcher.py +212 -0
  63. raxe/domain/inline_suppression.py +176 -0
  64. raxe/domain/ml/__init__.py +133 -0
  65. raxe/domain/ml/embedding_cache.py +309 -0
  66. raxe/domain/ml/gemma_detector.py +921 -0
  67. raxe/domain/ml/gemma_models.py +346 -0
  68. raxe/domain/ml/l2_config.py +428 -0
  69. raxe/domain/ml/l2_output_schema.py +443 -0
  70. raxe/domain/ml/manifest_loader.py +309 -0
  71. raxe/domain/ml/manifest_schema.py +345 -0
  72. raxe/domain/ml/model_metadata.py +263 -0
  73. raxe/domain/ml/model_registry.py +786 -0
  74. raxe/domain/ml/protocol.py +282 -0
  75. raxe/domain/ml/scoring_models.py +419 -0
  76. raxe/domain/ml/stub_detector.py +397 -0
  77. raxe/domain/ml/threat_scorer.py +757 -0
  78. raxe/domain/ml/tokenizer_registry.py +372 -0
  79. raxe/domain/ml/voting/__init__.py +89 -0
  80. raxe/domain/ml/voting/config.py +595 -0
  81. raxe/domain/ml/voting/engine.py +465 -0
  82. raxe/domain/ml/voting/head_voters.py +378 -0
  83. raxe/domain/ml/voting/models.py +222 -0
  84. raxe/domain/models.py +82 -0
  85. raxe/domain/packs/__init__.py +17 -0
  86. raxe/domain/packs/models.py +304 -0
  87. raxe/domain/policies/__init__.py +20 -0
  88. raxe/domain/policies/evaluator.py +212 -0
  89. raxe/domain/policies/models.py +223 -0
  90. raxe/domain/rules/__init__.py +32 -0
  91. raxe/domain/rules/custom.py +286 -0
  92. raxe/domain/rules/models.py +273 -0
  93. raxe/domain/rules/schema.py +166 -0
  94. raxe/domain/rules/validator.py +556 -0
  95. raxe/domain/suppression.py +801 -0
  96. raxe/domain/suppression_factory.py +174 -0
  97. raxe/domain/telemetry/__init__.py +116 -0
  98. raxe/domain/telemetry/backpressure.py +424 -0
  99. raxe/domain/telemetry/event_creator.py +362 -0
  100. raxe/domain/telemetry/events.py +1282 -0
  101. raxe/domain/telemetry/priority.py +263 -0
  102. raxe/domain/telemetry/scan_telemetry_builder.py +670 -0
  103. raxe/infrastructure/__init__.py +25 -0
  104. raxe/infrastructure/analytics/__init__.py +18 -0
  105. raxe/infrastructure/analytics/aggregator.py +484 -0
  106. raxe/infrastructure/analytics/aggregator_optimized.py +184 -0
  107. raxe/infrastructure/analytics/engine.py +748 -0
  108. raxe/infrastructure/analytics/repository.py +409 -0
  109. raxe/infrastructure/analytics/streaks.py +467 -0
  110. raxe/infrastructure/analytics/views.py +178 -0
  111. raxe/infrastructure/cloud/__init__.py +9 -0
  112. raxe/infrastructure/config/__init__.py +56 -0
  113. raxe/infrastructure/config/endpoints.py +641 -0
  114. raxe/infrastructure/config/scan_config.py +352 -0
  115. raxe/infrastructure/config/yaml_config.py +459 -0
  116. raxe/infrastructure/database/__init__.py +10 -0
  117. raxe/infrastructure/database/connection.py +200 -0
  118. raxe/infrastructure/database/models.py +325 -0
  119. raxe/infrastructure/database/scan_history.py +764 -0
  120. raxe/infrastructure/ml/__init__.py +0 -0
  121. raxe/infrastructure/ml/download_progress.py +438 -0
  122. raxe/infrastructure/ml/model_downloader.py +457 -0
  123. raxe/infrastructure/models/__init__.py +16 -0
  124. raxe/infrastructure/models/discovery.py +461 -0
  125. raxe/infrastructure/packs/__init__.py +13 -0
  126. raxe/infrastructure/packs/loader.py +407 -0
  127. raxe/infrastructure/packs/registry.py +381 -0
  128. raxe/infrastructure/policies/__init__.py +16 -0
  129. raxe/infrastructure/policies/api_client.py +256 -0
  130. raxe/infrastructure/policies/validator.py +227 -0
  131. raxe/infrastructure/policies/yaml_loader.py +250 -0
  132. raxe/infrastructure/rules/__init__.py +18 -0
  133. raxe/infrastructure/rules/custom_loader.py +224 -0
  134. raxe/infrastructure/rules/versioning.py +222 -0
  135. raxe/infrastructure/rules/yaml_loader.py +286 -0
  136. raxe/infrastructure/security/__init__.py +31 -0
  137. raxe/infrastructure/security/auth.py +145 -0
  138. raxe/infrastructure/security/policy_validator.py +124 -0
  139. raxe/infrastructure/security/signatures.py +171 -0
  140. raxe/infrastructure/suppression/__init__.py +36 -0
  141. raxe/infrastructure/suppression/composite_repository.py +154 -0
  142. raxe/infrastructure/suppression/sqlite_repository.py +231 -0
  143. raxe/infrastructure/suppression/yaml_composite_repository.py +156 -0
  144. raxe/infrastructure/suppression/yaml_repository.py +510 -0
  145. raxe/infrastructure/telemetry/__init__.py +79 -0
  146. raxe/infrastructure/telemetry/acquisition.py +179 -0
  147. raxe/infrastructure/telemetry/config.py +254 -0
  148. raxe/infrastructure/telemetry/credential_store.py +947 -0
  149. raxe/infrastructure/telemetry/dual_queue.py +1123 -0
  150. raxe/infrastructure/telemetry/flush_helper.py +343 -0
  151. raxe/infrastructure/telemetry/flush_scheduler.py +776 -0
  152. raxe/infrastructure/telemetry/health_client.py +394 -0
  153. raxe/infrastructure/telemetry/hook.py +347 -0
  154. raxe/infrastructure/telemetry/queue.py +520 -0
  155. raxe/infrastructure/telemetry/sender.py +476 -0
  156. raxe/infrastructure/tracking/__init__.py +13 -0
  157. raxe/infrastructure/tracking/usage.py +389 -0
  158. raxe/integrations/__init__.py +55 -0
  159. raxe/integrations/availability.py +143 -0
  160. raxe/integrations/registry.py +122 -0
  161. raxe/integrations/utils.py +135 -0
  162. raxe/mcp/__init__.py +62 -0
  163. raxe/mcp/cli.py +97 -0
  164. raxe/mcp/server.py +409 -0
  165. raxe/monitoring/__init__.py +51 -0
  166. raxe/monitoring/metrics.py +372 -0
  167. raxe/monitoring/profiler.py +388 -0
  168. raxe/monitoring/server.py +136 -0
  169. raxe/packs/core/v1.0.0/pack.yaml +1394 -0
  170. raxe/packs/core/v1.0.0/rules/PI/pi-001@1.0.0.yaml +49 -0
  171. raxe/packs/core/v1.0.0/rules/PI/pi-006@1.0.0.yaml +48 -0
  172. raxe/packs/core/v1.0.0/rules/PI/pi-014@1.0.0.yaml +54 -0
  173. raxe/packs/core/v1.0.0/rules/PI/pi-017@1.0.0.yaml +52 -0
  174. raxe/packs/core/v1.0.0/rules/PI/pi-022@1.0.0.yaml +67 -0
  175. raxe/packs/core/v1.0.0/rules/PI/pi-023@1.0.0.yaml +91 -0
  176. raxe/packs/core/v1.0.0/rules/PI/pi-024@1.0.0.yaml +80 -0
  177. raxe/packs/core/v1.0.0/rules/PI/pi-025@1.0.0.yaml +81 -0
  178. raxe/packs/core/v1.0.0/rules/PI/pi-026@1.0.0.yaml +50 -0
  179. raxe/packs/core/v1.0.0/rules/PI/pi-027@1.0.0.yaml +77 -0
  180. raxe/packs/core/v1.0.0/rules/PI/pi-028@1.0.0.yaml +52 -0
  181. raxe/packs/core/v1.0.0/rules/PI/pi-029@1.0.0.yaml +51 -0
  182. raxe/packs/core/v1.0.0/rules/PI/pi-030@1.0.0.yaml +55 -0
  183. raxe/packs/core/v1.0.0/rules/PI/pi-033@1.0.0.yaml +50 -0
  184. raxe/packs/core/v1.0.0/rules/PI/pi-034@1.0.0.yaml +50 -0
  185. raxe/packs/core/v1.0.0/rules/PI/pi-035@1.0.0.yaml +50 -0
  186. raxe/packs/core/v1.0.0/rules/PI/pi-046@1.0.0.yaml +50 -0
  187. raxe/packs/core/v1.0.0/rules/PI/pi-047@1.0.0.yaml +50 -0
  188. raxe/packs/core/v1.0.0/rules/PI/pi-048@1.0.0.yaml +50 -0
  189. raxe/packs/core/v1.0.0/rules/PI/pi-049@1.0.0.yaml +50 -0
  190. raxe/packs/core/v1.0.0/rules/PI/pi-050@1.0.0.yaml +50 -0
  191. raxe/packs/core/v1.0.0/rules/PI/pi-068@1.0.0.yaml +50 -0
  192. raxe/packs/core/v1.0.0/rules/PI/pi-078@1.0.0.yaml +50 -0
  193. raxe/packs/core/v1.0.0/rules/PI/pi-2001@1.0.0.yaml +35 -0
  194. raxe/packs/core/v1.0.0/rules/PI/pi-2004@1.0.0.yaml +39 -0
  195. raxe/packs/core/v1.0.0/rules/PI/pi-201@1.0.0.yaml +43 -0
  196. raxe/packs/core/v1.0.0/rules/PI/pi-202@1.0.0.yaml +47 -0
  197. raxe/packs/core/v1.0.0/rules/PI/pi-203@1.0.0.yaml +46 -0
  198. raxe/packs/core/v1.0.0/rules/PI/pi-3007@1.0.0.yaml +44 -0
  199. raxe/packs/core/v1.0.0/rules/PI/pi-3016@1.0.0.yaml +44 -0
  200. raxe/packs/core/v1.0.0/rules/PI/pi-3026@1.0.0.yaml +39 -0
  201. raxe/packs/core/v1.0.0/rules/PI/pi-3027@1.0.0.yaml +64 -0
  202. raxe/packs/core/v1.0.0/rules/PI/pi-3028@1.0.0.yaml +51 -0
  203. raxe/packs/core/v1.0.0/rules/PI/pi-3029@1.0.0.yaml +53 -0
  204. raxe/packs/core/v1.0.0/rules/PI/pi-3030@1.0.0.yaml +50 -0
  205. raxe/packs/core/v1.0.0/rules/PI/pi-3031@1.0.0.yaml +50 -0
  206. raxe/packs/core/v1.0.0/rules/PI/pi-3032@1.0.0.yaml +50 -0
  207. raxe/packs/core/v1.0.0/rules/PI/pi-3033@1.0.0.yaml +56 -0
  208. raxe/packs/core/v1.0.0/rules/PI/pi-3034@1.0.0.yaml +50 -0
  209. raxe/packs/core/v1.0.0/rules/PI/pi-79@1.0.0.yaml +38 -0
  210. raxe/packs/core/v1.0.0/rules/PI/pi-80@1.0.0.yaml +38 -0
  211. raxe/packs/core/v1.0.0/rules/PI/pi-81@1.0.0.yaml +38 -0
  212. raxe/packs/core/v1.0.0/rules/PI/pi-82@1.0.0.yaml +38 -0
  213. raxe/packs/core/v1.0.0/rules/PI/pi-83@1.0.0.yaml +38 -0
  214. raxe/packs/core/v1.0.0/rules/PI/pi-84@1.0.0.yaml +38 -0
  215. raxe/packs/core/v1.0.0/rules/PI/pi-85@1.0.0.yaml +38 -0
  216. raxe/packs/core/v1.0.0/rules/PI/pi-86@1.0.0.yaml +38 -0
  217. raxe/packs/core/v1.0.0/rules/PI/pi-87@1.0.0.yaml +38 -0
  218. raxe/packs/core/v1.0.0/rules/PI/pi-88@1.0.0.yaml +38 -0
  219. raxe/packs/core/v1.0.0/rules/PI/pi-89@1.0.0.yaml +38 -0
  220. raxe/packs/core/v1.0.0/rules/PI/pi-90@1.0.0.yaml +38 -0
  221. raxe/packs/core/v1.0.0/rules/PI/pi-91@1.0.0.yaml +38 -0
  222. raxe/packs/core/v1.0.0/rules/PI/pi-92@1.0.0.yaml +38 -0
  223. raxe/packs/core/v1.0.0/rules/PI/pi-93@1.0.0.yaml +38 -0
  224. raxe/packs/core/v1.0.0/rules/PI/pi-94@1.0.0.yaml +38 -0
  225. raxe/packs/core/v1.0.0/rules/PI/pi-95@1.0.0.yaml +38 -0
  226. raxe/packs/core/v1.0.0/rules/PI/pi-96@1.0.0.yaml +38 -0
  227. raxe/packs/core/v1.0.0/rules/PI/pi-97@1.0.0.yaml +38 -0
  228. raxe/packs/core/v1.0.0/rules/PI/pi-98@1.0.0.yaml +38 -0
  229. raxe/packs/core/v1.0.0/rules/cmd/cmd-001@1.0.0.yaml +48 -0
  230. raxe/packs/core/v1.0.0/rules/cmd/cmd-007@1.0.0.yaml +48 -0
  231. raxe/packs/core/v1.0.0/rules/cmd/cmd-015@1.0.0.yaml +56 -0
  232. raxe/packs/core/v1.0.0/rules/cmd/cmd-016@1.0.0.yaml +46 -0
  233. raxe/packs/core/v1.0.0/rules/cmd/cmd-017@1.0.0.yaml +57 -0
  234. raxe/packs/core/v1.0.0/rules/cmd/cmd-021@1.0.0.yaml +46 -0
  235. raxe/packs/core/v1.0.0/rules/cmd/cmd-022@1.0.0.yaml +46 -0
  236. raxe/packs/core/v1.0.0/rules/cmd/cmd-023@1.0.0.yaml +78 -0
  237. raxe/packs/core/v1.0.0/rules/cmd/cmd-024@1.0.0.yaml +46 -0
  238. raxe/packs/core/v1.0.0/rules/cmd/cmd-025@1.0.0.yaml +93 -0
  239. raxe/packs/core/v1.0.0/rules/cmd/cmd-026@1.0.0.yaml +81 -0
  240. raxe/packs/core/v1.0.0/rules/cmd/cmd-027@1.0.0.yaml +82 -0
  241. raxe/packs/core/v1.0.0/rules/cmd/cmd-028@1.0.0.yaml +46 -0
  242. raxe/packs/core/v1.0.0/rules/cmd/cmd-033@1.0.0.yaml +48 -0
  243. raxe/packs/core/v1.0.0/rules/cmd/cmd-036@1.0.0.yaml +47 -0
  244. raxe/packs/core/v1.0.0/rules/cmd/cmd-037@1.0.0.yaml +44 -0
  245. raxe/packs/core/v1.0.0/rules/cmd/cmd-052@1.0.0.yaml +43 -0
  246. raxe/packs/core/v1.0.0/rules/cmd/cmd-054@1.0.0.yaml +44 -0
  247. raxe/packs/core/v1.0.0/rules/cmd/cmd-056@1.0.0.yaml +43 -0
  248. raxe/packs/core/v1.0.0/rules/cmd/cmd-065@1.0.0.yaml +46 -0
  249. raxe/packs/core/v1.0.0/rules/cmd/cmd-075@1.0.0.yaml +45 -0
  250. raxe/packs/core/v1.0.0/rules/cmd/cmd-079@1.0.0.yaml +44 -0
  251. raxe/packs/core/v1.0.0/rules/cmd/cmd-1080@1.0.0.yaml +41 -0
  252. raxe/packs/core/v1.0.0/rules/cmd/cmd-1090@1.0.0.yaml +41 -0
  253. raxe/packs/core/v1.0.0/rules/cmd/cmd-1104@1.0.0.yaml +44 -0
  254. raxe/packs/core/v1.0.0/rules/cmd/cmd-1105@1.0.0.yaml +41 -0
  255. raxe/packs/core/v1.0.0/rules/cmd/cmd-1112@1.0.0.yaml +44 -0
  256. raxe/packs/core/v1.0.0/rules/cmd/cmd-201@1.0.0.yaml +47 -0
  257. raxe/packs/core/v1.0.0/rules/cmd/cmd-202@1.0.0.yaml +42 -0
  258. raxe/packs/core/v1.0.0/rules/cmd/cmd-203@1.0.0.yaml +43 -0
  259. raxe/packs/core/v1.0.0/rules/cmd/cmd-204@1.0.0.yaml +47 -0
  260. raxe/packs/core/v1.0.0/rules/cmd/cmd-205@1.0.0.yaml +44 -0
  261. raxe/packs/core/v1.0.0/rules/cmd/cmd-206@1.0.0.yaml +47 -0
  262. raxe/packs/core/v1.0.0/rules/cmd/cmd-207@1.0.0.yaml +46 -0
  263. raxe/packs/core/v1.0.0/rules/cmd/cmd-208@1.0.0.yaml +42 -0
  264. raxe/packs/core/v1.0.0/rules/cmd/cmd-209@1.0.0.yaml +38 -0
  265. raxe/packs/core/v1.0.0/rules/cmd/cmd-210@1.0.0.yaml +38 -0
  266. raxe/packs/core/v1.0.0/rules/cmd/cmd-211@1.0.0.yaml +38 -0
  267. raxe/packs/core/v1.0.0/rules/cmd/cmd-212@1.0.0.yaml +38 -0
  268. raxe/packs/core/v1.0.0/rules/cmd/cmd-213@1.0.0.yaml +38 -0
  269. raxe/packs/core/v1.0.0/rules/cmd/cmd-214@1.0.0.yaml +38 -0
  270. raxe/packs/core/v1.0.0/rules/cmd/cmd-215@1.0.0.yaml +38 -0
  271. raxe/packs/core/v1.0.0/rules/cmd/cmd-216@1.0.0.yaml +38 -0
  272. raxe/packs/core/v1.0.0/rules/cmd/cmd-217@1.0.0.yaml +38 -0
  273. raxe/packs/core/v1.0.0/rules/cmd/cmd-218@1.0.0.yaml +38 -0
  274. raxe/packs/core/v1.0.0/rules/cmd/cmd-219@1.0.0.yaml +38 -0
  275. raxe/packs/core/v1.0.0/rules/cmd/cmd-220@1.0.0.yaml +38 -0
  276. raxe/packs/core/v1.0.0/rules/cmd/cmd-221@1.0.0.yaml +38 -0
  277. raxe/packs/core/v1.0.0/rules/cmd/cmd-222@1.0.0.yaml +38 -0
  278. raxe/packs/core/v1.0.0/rules/cmd/cmd-223@1.0.0.yaml +38 -0
  279. raxe/packs/core/v1.0.0/rules/cmd/cmd-224@1.0.0.yaml +38 -0
  280. raxe/packs/core/v1.0.0/rules/cmd/cmd-225@1.0.0.yaml +38 -0
  281. raxe/packs/core/v1.0.0/rules/cmd/cmd-226@1.0.0.yaml +38 -0
  282. raxe/packs/core/v1.0.0/rules/cmd/cmd-227@1.0.0.yaml +38 -0
  283. raxe/packs/core/v1.0.0/rules/cmd/cmd-228@1.0.0.yaml +38 -0
  284. raxe/packs/core/v1.0.0/rules/cmd/cmd-229@1.0.0.yaml +38 -0
  285. raxe/packs/core/v1.0.0/rules/cmd/cmd-230@1.0.0.yaml +38 -0
  286. raxe/packs/core/v1.0.0/rules/cmd/cmd-231@1.0.0.yaml +38 -0
  287. raxe/packs/core/v1.0.0/rules/cmd/cmd-232@1.0.0.yaml +38 -0
  288. raxe/packs/core/v1.0.0/rules/cmd/cmd-233@1.0.0.yaml +38 -0
  289. raxe/packs/core/v1.0.0/rules/cmd/cmd-234@1.0.0.yaml +38 -0
  290. raxe/packs/core/v1.0.0/rules/cmd/cmd-235@1.0.0.yaml +38 -0
  291. raxe/packs/core/v1.0.0/rules/cmd/cmd-236@1.0.0.yaml +38 -0
  292. raxe/packs/core/v1.0.0/rules/cmd/cmd-237@1.0.0.yaml +38 -0
  293. raxe/packs/core/v1.0.0/rules/cmd/cmd-238@1.0.0.yaml +38 -0
  294. raxe/packs/core/v1.0.0/rules/enc/enc-001@1.0.0.yaml +48 -0
  295. raxe/packs/core/v1.0.0/rules/enc/enc-013@1.0.0.yaml +46 -0
  296. raxe/packs/core/v1.0.0/rules/enc/enc-019@1.0.0.yaml +43 -0
  297. raxe/packs/core/v1.0.0/rules/enc/enc-020@1.0.0.yaml +47 -0
  298. raxe/packs/core/v1.0.0/rules/enc/enc-024@1.0.0.yaml +46 -0
  299. raxe/packs/core/v1.0.0/rules/enc/enc-029@1.0.0.yaml +44 -0
  300. raxe/packs/core/v1.0.0/rules/enc/enc-038@1.0.0.yaml +44 -0
  301. raxe/packs/core/v1.0.0/rules/enc/enc-044@1.0.0.yaml +46 -0
  302. raxe/packs/core/v1.0.0/rules/enc/enc-067@1.0.0.yaml +42 -0
  303. raxe/packs/core/v1.0.0/rules/enc/enc-069@1.0.0.yaml +42 -0
  304. raxe/packs/core/v1.0.0/rules/enc/enc-100@1.0.0.yaml +38 -0
  305. raxe/packs/core/v1.0.0/rules/enc/enc-101@1.0.0.yaml +38 -0
  306. raxe/packs/core/v1.0.0/rules/enc/enc-102@1.0.0.yaml +38 -0
  307. raxe/packs/core/v1.0.0/rules/enc/enc-103@1.0.0.yaml +38 -0
  308. raxe/packs/core/v1.0.0/rules/enc/enc-104@1.0.0.yaml +38 -0
  309. raxe/packs/core/v1.0.0/rules/enc/enc-105@1.0.0.yaml +38 -0
  310. raxe/packs/core/v1.0.0/rules/enc/enc-106@1.0.0.yaml +38 -0
  311. raxe/packs/core/v1.0.0/rules/enc/enc-107@1.0.0.yaml +38 -0
  312. raxe/packs/core/v1.0.0/rules/enc/enc-108@1.0.0.yaml +38 -0
  313. raxe/packs/core/v1.0.0/rules/enc/enc-109@1.0.0.yaml +38 -0
  314. raxe/packs/core/v1.0.0/rules/enc/enc-110@1.0.0.yaml +38 -0
  315. raxe/packs/core/v1.0.0/rules/enc/enc-111@1.0.0.yaml +38 -0
  316. raxe/packs/core/v1.0.0/rules/enc/enc-112@1.0.0.yaml +38 -0
  317. raxe/packs/core/v1.0.0/rules/enc/enc-113@1.0.0.yaml +38 -0
  318. raxe/packs/core/v1.0.0/rules/enc/enc-114@1.0.0.yaml +38 -0
  319. raxe/packs/core/v1.0.0/rules/enc/enc-115@1.0.0.yaml +38 -0
  320. raxe/packs/core/v1.0.0/rules/enc/enc-116@1.0.0.yaml +38 -0
  321. raxe/packs/core/v1.0.0/rules/enc/enc-117@1.0.0.yaml +38 -0
  322. raxe/packs/core/v1.0.0/rules/enc/enc-118@1.0.0.yaml +38 -0
  323. raxe/packs/core/v1.0.0/rules/enc/enc-119@1.0.0.yaml +38 -0
  324. raxe/packs/core/v1.0.0/rules/enc/enc-120@1.0.0.yaml +38 -0
  325. raxe/packs/core/v1.0.0/rules/enc/enc-201@1.0.0.yaml +37 -0
  326. raxe/packs/core/v1.0.0/rules/enc/enc-202@1.0.0.yaml +41 -0
  327. raxe/packs/core/v1.0.0/rules/enc/enc-203@1.0.0.yaml +41 -0
  328. raxe/packs/core/v1.0.0/rules/enc/enc-3004@1.0.0.yaml +40 -0
  329. raxe/packs/core/v1.0.0/rules/enc/enc-3006@1.0.0.yaml +40 -0
  330. raxe/packs/core/v1.0.0/rules/enc/enc-3011@1.0.0.yaml +40 -0
  331. raxe/packs/core/v1.0.0/rules/enc/enc-5016@1.0.0.yaml +46 -0
  332. raxe/packs/core/v1.0.0/rules/enc/enc-6001@1.0.0.yaml +53 -0
  333. raxe/packs/core/v1.0.0/rules/enc/enc-6002@1.0.0.yaml +41 -0
  334. raxe/packs/core/v1.0.0/rules/enc/enc-70@1.0.0.yaml +38 -0
  335. raxe/packs/core/v1.0.0/rules/enc/enc-71@1.0.0.yaml +38 -0
  336. raxe/packs/core/v1.0.0/rules/enc/enc-72@1.0.0.yaml +38 -0
  337. raxe/packs/core/v1.0.0/rules/enc/enc-73@1.0.0.yaml +38 -0
  338. raxe/packs/core/v1.0.0/rules/enc/enc-74@1.0.0.yaml +38 -0
  339. raxe/packs/core/v1.0.0/rules/enc/enc-75@1.0.0.yaml +38 -0
  340. raxe/packs/core/v1.0.0/rules/enc/enc-76@1.0.0.yaml +38 -0
  341. raxe/packs/core/v1.0.0/rules/enc/enc-77@1.0.0.yaml +38 -0
  342. raxe/packs/core/v1.0.0/rules/enc/enc-78@1.0.0.yaml +38 -0
  343. raxe/packs/core/v1.0.0/rules/enc/enc-79@1.0.0.yaml +38 -0
  344. raxe/packs/core/v1.0.0/rules/enc/enc-80@1.0.0.yaml +38 -0
  345. raxe/packs/core/v1.0.0/rules/enc/enc-81@1.0.0.yaml +38 -0
  346. raxe/packs/core/v1.0.0/rules/enc/enc-82@1.0.0.yaml +38 -0
  347. raxe/packs/core/v1.0.0/rules/enc/enc-83@1.0.0.yaml +38 -0
  348. raxe/packs/core/v1.0.0/rules/enc/enc-84@1.0.0.yaml +38 -0
  349. raxe/packs/core/v1.0.0/rules/enc/enc-85@1.0.0.yaml +38 -0
  350. raxe/packs/core/v1.0.0/rules/enc/enc-86@1.0.0.yaml +38 -0
  351. raxe/packs/core/v1.0.0/rules/enc/enc-87@1.0.0.yaml +38 -0
  352. raxe/packs/core/v1.0.0/rules/enc/enc-88@1.0.0.yaml +38 -0
  353. raxe/packs/core/v1.0.0/rules/enc/enc-89@1.0.0.yaml +38 -0
  354. raxe/packs/core/v1.0.0/rules/enc/enc-90@1.0.0.yaml +38 -0
  355. raxe/packs/core/v1.0.0/rules/enc/enc-91@1.0.0.yaml +38 -0
  356. raxe/packs/core/v1.0.0/rules/enc/enc-92@1.0.0.yaml +38 -0
  357. raxe/packs/core/v1.0.0/rules/enc/enc-93@1.0.0.yaml +38 -0
  358. raxe/packs/core/v1.0.0/rules/enc/enc-94@1.0.0.yaml +38 -0
  359. raxe/packs/core/v1.0.0/rules/enc/enc-95@1.0.0.yaml +38 -0
  360. raxe/packs/core/v1.0.0/rules/enc/enc-96@1.0.0.yaml +38 -0
  361. raxe/packs/core/v1.0.0/rules/enc/enc-97@1.0.0.yaml +38 -0
  362. raxe/packs/core/v1.0.0/rules/enc/enc-98@1.0.0.yaml +38 -0
  363. raxe/packs/core/v1.0.0/rules/enc/enc-99@1.0.0.yaml +38 -0
  364. raxe/packs/core/v1.0.0/rules/hc/hc-001@1.0.0.yaml +73 -0
  365. raxe/packs/core/v1.0.0/rules/hc/hc-002@1.0.0.yaml +71 -0
  366. raxe/packs/core/v1.0.0/rules/hc/hc-003@1.0.0.yaml +65 -0
  367. raxe/packs/core/v1.0.0/rules/hc/hc-004@1.0.0.yaml +73 -0
  368. raxe/packs/core/v1.0.0/rules/hc/hc-101@1.0.0.yaml +47 -0
  369. raxe/packs/core/v1.0.0/rules/hc/hc-102@1.0.0.yaml +47 -0
  370. raxe/packs/core/v1.0.0/rules/hc/hc-103@1.0.0.yaml +47 -0
  371. raxe/packs/core/v1.0.0/rules/hc/hc-104@1.0.0.yaml +47 -0
  372. raxe/packs/core/v1.0.0/rules/hc/hc-105@1.0.0.yaml +48 -0
  373. raxe/packs/core/v1.0.0/rules/hc/hc-106@1.0.0.yaml +40 -0
  374. raxe/packs/core/v1.0.0/rules/hc/hc-107@1.0.0.yaml +47 -0
  375. raxe/packs/core/v1.0.0/rules/hc/hc-108@1.0.0.yaml +47 -0
  376. raxe/packs/core/v1.0.0/rules/hc/hc-109@1.0.0.yaml +50 -0
  377. raxe/packs/core/v1.0.0/rules/hc/hc-110@1.0.0.yaml +56 -0
  378. raxe/packs/core/v1.0.0/rules/hc/hc-111@1.0.0.yaml +49 -0
  379. raxe/packs/core/v1.0.0/rules/hc/hc-112@1.0.0.yaml +53 -0
  380. raxe/packs/core/v1.0.0/rules/hc/hc-113@1.0.0.yaml +52 -0
  381. raxe/packs/core/v1.0.0/rules/hc/hc-114@1.0.0.yaml +52 -0
  382. raxe/packs/core/v1.0.0/rules/hc/hc-115@1.0.0.yaml +52 -0
  383. raxe/packs/core/v1.0.0/rules/hc/hc-116@1.0.0.yaml +53 -0
  384. raxe/packs/core/v1.0.0/rules/hc/hc-117@1.0.0.yaml +54 -0
  385. raxe/packs/core/v1.0.0/rules/hc/hc-118@1.0.0.yaml +52 -0
  386. raxe/packs/core/v1.0.0/rules/hc/hc-119@1.0.0.yaml +51 -0
  387. raxe/packs/core/v1.0.0/rules/hc/hc-120@1.0.0.yaml +52 -0
  388. raxe/packs/core/v1.0.0/rules/hc/hc-121@1.0.0.yaml +51 -0
  389. raxe/packs/core/v1.0.0/rules/hc/hc-122@1.0.0.yaml +51 -0
  390. raxe/packs/core/v1.0.0/rules/hc/hc-123@1.0.0.yaml +52 -0
  391. raxe/packs/core/v1.0.0/rules/hc/hc-124@1.0.0.yaml +53 -0
  392. raxe/packs/core/v1.0.0/rules/hc/hc-125@1.0.0.yaml +53 -0
  393. raxe/packs/core/v1.0.0/rules/hc/hc-126@1.0.0.yaml +53 -0
  394. raxe/packs/core/v1.0.0/rules/hc/hc-127@1.0.0.yaml +53 -0
  395. raxe/packs/core/v1.0.0/rules/hc/hc-128@1.0.0.yaml +53 -0
  396. raxe/packs/core/v1.0.0/rules/hc/hc-129@1.0.0.yaml +51 -0
  397. raxe/packs/core/v1.0.0/rules/hc/hc-130@1.0.0.yaml +51 -0
  398. raxe/packs/core/v1.0.0/rules/hc/hc-131@1.0.0.yaml +51 -0
  399. raxe/packs/core/v1.0.0/rules/hc/hc-132@1.0.0.yaml +51 -0
  400. raxe/packs/core/v1.0.0/rules/hc/hc-133@1.0.0.yaml +53 -0
  401. raxe/packs/core/v1.0.0/rules/hc/hc-134@1.0.0.yaml +51 -0
  402. raxe/packs/core/v1.0.0/rules/hc/hc-135@1.0.0.yaml +51 -0
  403. raxe/packs/core/v1.0.0/rules/hc/hc-136@1.0.0.yaml +51 -0
  404. raxe/packs/core/v1.0.0/rules/hc/hc-137@1.0.0.yaml +51 -0
  405. raxe/packs/core/v1.0.0/rules/hc/hc-138@1.0.0.yaml +51 -0
  406. raxe/packs/core/v1.0.0/rules/hc/hc-139@1.0.0.yaml +51 -0
  407. raxe/packs/core/v1.0.0/rules/hc/hc-140@1.0.0.yaml +51 -0
  408. raxe/packs/core/v1.0.0/rules/hc/hc-141@1.0.0.yaml +41 -0
  409. raxe/packs/core/v1.0.0/rules/hc/hc-142@1.0.0.yaml +37 -0
  410. raxe/packs/core/v1.0.0/rules/hc/hc-143@1.0.0.yaml +37 -0
  411. raxe/packs/core/v1.0.0/rules/hc/hc-144@1.0.0.yaml +37 -0
  412. raxe/packs/core/v1.0.0/rules/hc/hc-145@1.0.0.yaml +37 -0
  413. raxe/packs/core/v1.0.0/rules/hc/hc-146@1.0.0.yaml +37 -0
  414. raxe/packs/core/v1.0.0/rules/hc/hc-147@1.0.0.yaml +37 -0
  415. raxe/packs/core/v1.0.0/rules/hc/hc-148@1.0.0.yaml +37 -0
  416. raxe/packs/core/v1.0.0/rules/hc/hc-149@1.0.0.yaml +37 -0
  417. raxe/packs/core/v1.0.0/rules/hc/hc-150@1.0.0.yaml +37 -0
  418. raxe/packs/core/v1.0.0/rules/hc/hc-151@1.0.0.yaml +37 -0
  419. raxe/packs/core/v1.0.0/rules/hc/hc-152@1.0.0.yaml +37 -0
  420. raxe/packs/core/v1.0.0/rules/hc/hc-153@1.0.0.yaml +37 -0
  421. raxe/packs/core/v1.0.0/rules/hc/hc-154@1.0.0.yaml +37 -0
  422. raxe/packs/core/v1.0.0/rules/hc/hc-155@1.0.0.yaml +37 -0
  423. raxe/packs/core/v1.0.0/rules/hc/hc-156@1.0.0.yaml +37 -0
  424. raxe/packs/core/v1.0.0/rules/hc/hc-157@1.0.0.yaml +37 -0
  425. raxe/packs/core/v1.0.0/rules/hc/hc-158@1.0.0.yaml +37 -0
  426. raxe/packs/core/v1.0.0/rules/hc/hc-159@1.0.0.yaml +37 -0
  427. raxe/packs/core/v1.0.0/rules/hc/hc-160@1.0.0.yaml +37 -0
  428. raxe/packs/core/v1.0.0/rules/hc/hc-161@1.0.0.yaml +37 -0
  429. raxe/packs/core/v1.0.0/rules/jb/jb-001@1.0.0.yaml +47 -0
  430. raxe/packs/core/v1.0.0/rules/jb/jb-009@1.0.0.yaml +47 -0
  431. raxe/packs/core/v1.0.0/rules/jb/jb-020@1.0.0.yaml +47 -0
  432. raxe/packs/core/v1.0.0/rules/jb/jb-021@1.0.0.yaml +46 -0
  433. raxe/packs/core/v1.0.0/rules/jb/jb-022@1.0.0.yaml +47 -0
  434. raxe/packs/core/v1.0.0/rules/jb/jb-028@1.0.0.yaml +43 -0
  435. raxe/packs/core/v1.0.0/rules/jb/jb-033@1.0.0.yaml +46 -0
  436. raxe/packs/core/v1.0.0/rules/jb/jb-034@1.0.0.yaml +46 -0
  437. raxe/packs/core/v1.0.0/rules/jb/jb-036@1.0.0.yaml +41 -0
  438. raxe/packs/core/v1.0.0/rules/jb/jb-039@1.0.0.yaml +41 -0
  439. raxe/packs/core/v1.0.0/rules/jb/jb-056@1.0.0.yaml +38 -0
  440. raxe/packs/core/v1.0.0/rules/jb/jb-066@1.0.0.yaml +37 -0
  441. raxe/packs/core/v1.0.0/rules/jb/jb-076@1.0.0.yaml +37 -0
  442. raxe/packs/core/v1.0.0/rules/jb/jb-098@1.0.0.yaml +46 -0
  443. raxe/packs/core/v1.0.0/rules/jb/jb-103@1.0.0.yaml +47 -0
  444. raxe/packs/core/v1.0.0/rules/jb/jb-104@1.0.0.yaml +52 -0
  445. raxe/packs/core/v1.0.0/rules/jb/jb-105@1.0.0.yaml +56 -0
  446. raxe/packs/core/v1.0.0/rules/jb/jb-110@1.0.0.yaml +56 -0
  447. raxe/packs/core/v1.0.0/rules/jb/jb-111@1.0.0.yaml +57 -0
  448. raxe/packs/core/v1.0.0/rules/jb/jb-112@1.0.0.yaml +38 -0
  449. raxe/packs/core/v1.0.0/rules/jb/jb-113@1.0.0.yaml +38 -0
  450. raxe/packs/core/v1.0.0/rules/jb/jb-114@1.0.0.yaml +38 -0
  451. raxe/packs/core/v1.0.0/rules/jb/jb-115@1.0.0.yaml +38 -0
  452. raxe/packs/core/v1.0.0/rules/jb/jb-116@1.0.0.yaml +38 -0
  453. raxe/packs/core/v1.0.0/rules/jb/jb-117@1.0.0.yaml +38 -0
  454. raxe/packs/core/v1.0.0/rules/jb/jb-118@1.0.0.yaml +38 -0
  455. raxe/packs/core/v1.0.0/rules/jb/jb-119@1.0.0.yaml +38 -0
  456. raxe/packs/core/v1.0.0/rules/jb/jb-120@1.0.0.yaml +38 -0
  457. raxe/packs/core/v1.0.0/rules/jb/jb-121@1.0.0.yaml +38 -0
  458. raxe/packs/core/v1.0.0/rules/jb/jb-122@1.0.0.yaml +38 -0
  459. raxe/packs/core/v1.0.0/rules/jb/jb-123@1.0.0.yaml +38 -0
  460. raxe/packs/core/v1.0.0/rules/jb/jb-124@1.0.0.yaml +38 -0
  461. raxe/packs/core/v1.0.0/rules/jb/jb-125@1.0.0.yaml +38 -0
  462. raxe/packs/core/v1.0.0/rules/jb/jb-126@1.0.0.yaml +38 -0
  463. raxe/packs/core/v1.0.0/rules/jb/jb-127@1.0.0.yaml +38 -0
  464. raxe/packs/core/v1.0.0/rules/jb/jb-128@1.0.0.yaml +38 -0
  465. raxe/packs/core/v1.0.0/rules/jb/jb-129@1.0.0.yaml +38 -0
  466. raxe/packs/core/v1.0.0/rules/jb/jb-130@1.0.0.yaml +38 -0
  467. raxe/packs/core/v1.0.0/rules/jb/jb-131@1.0.0.yaml +38 -0
  468. raxe/packs/core/v1.0.0/rules/jb/jb-132@1.0.0.yaml +38 -0
  469. raxe/packs/core/v1.0.0/rules/jb/jb-133@1.0.0.yaml +38 -0
  470. raxe/packs/core/v1.0.0/rules/jb/jb-134@1.0.0.yaml +38 -0
  471. raxe/packs/core/v1.0.0/rules/jb/jb-135@1.0.0.yaml +38 -0
  472. raxe/packs/core/v1.0.0/rules/jb/jb-136@1.0.0.yaml +38 -0
  473. raxe/packs/core/v1.0.0/rules/jb/jb-137@1.0.0.yaml +38 -0
  474. raxe/packs/core/v1.0.0/rules/jb/jb-138@1.0.0.yaml +38 -0
  475. raxe/packs/core/v1.0.0/rules/jb/jb-139@1.0.0.yaml +38 -0
  476. raxe/packs/core/v1.0.0/rules/jb/jb-140@1.0.0.yaml +38 -0
  477. raxe/packs/core/v1.0.0/rules/jb/jb-141@1.0.0.yaml +38 -0
  478. raxe/packs/core/v1.0.0/rules/jb/jb-142@1.0.0.yaml +38 -0
  479. raxe/packs/core/v1.0.0/rules/jb/jb-143@1.0.0.yaml +38 -0
  480. raxe/packs/core/v1.0.0/rules/jb/jb-144@1.0.0.yaml +38 -0
  481. raxe/packs/core/v1.0.0/rules/jb/jb-145@1.0.0.yaml +38 -0
  482. raxe/packs/core/v1.0.0/rules/jb/jb-146@1.0.0.yaml +38 -0
  483. raxe/packs/core/v1.0.0/rules/jb/jb-147@1.0.0.yaml +38 -0
  484. raxe/packs/core/v1.0.0/rules/jb/jb-148@1.0.0.yaml +38 -0
  485. raxe/packs/core/v1.0.0/rules/jb/jb-149@1.0.0.yaml +38 -0
  486. raxe/packs/core/v1.0.0/rules/jb/jb-150@1.0.0.yaml +38 -0
  487. raxe/packs/core/v1.0.0/rules/jb/jb-151@1.0.0.yaml +38 -0
  488. raxe/packs/core/v1.0.0/rules/jb/jb-152@1.0.0.yaml +38 -0
  489. raxe/packs/core/v1.0.0/rules/jb/jb-153@1.0.0.yaml +38 -0
  490. raxe/packs/core/v1.0.0/rules/jb/jb-154@1.0.0.yaml +38 -0
  491. raxe/packs/core/v1.0.0/rules/jb/jb-155@1.0.0.yaml +38 -0
  492. raxe/packs/core/v1.0.0/rules/jb/jb-156@1.0.0.yaml +38 -0
  493. raxe/packs/core/v1.0.0/rules/jb/jb-157@1.0.0.yaml +38 -0
  494. raxe/packs/core/v1.0.0/rules/jb/jb-158@1.0.0.yaml +38 -0
  495. raxe/packs/core/v1.0.0/rules/jb/jb-159@1.0.0.yaml +38 -0
  496. raxe/packs/core/v1.0.0/rules/jb/jb-160@1.0.0.yaml +38 -0
  497. raxe/packs/core/v1.0.0/rules/jb/jb-161@1.0.0.yaml +38 -0
  498. raxe/packs/core/v1.0.0/rules/jb/jb-162@1.0.0.yaml +38 -0
  499. raxe/packs/core/v1.0.0/rules/jb/jb-201@1.0.0.yaml +40 -0
  500. raxe/packs/core/v1.0.0/rules/jb/jb-202@1.0.0.yaml +41 -0
  501. raxe/packs/core/v1.0.0/rules/jb/jb-203@1.0.0.yaml +51 -0
  502. raxe/packs/core/v1.0.0/rules/jb/jb-204@1.0.0.yaml +50 -0
  503. raxe/packs/core/v1.0.0/rules/jb/jb-205@1.0.0.yaml +50 -0
  504. raxe/packs/core/v1.0.0/rules/jb/jb-206@1.0.0.yaml +50 -0
  505. raxe/packs/core/v1.0.0/rules/jb/jb-207@1.0.0.yaml +49 -0
  506. raxe/packs/core/v1.0.0/rules/pii/pii-001@1.0.0.yaml +48 -0
  507. raxe/packs/core/v1.0.0/rules/pii/pii-009@1.0.0.yaml +48 -0
  508. raxe/packs/core/v1.0.0/rules/pii/pii-012@1.0.0.yaml +48 -0
  509. raxe/packs/core/v1.0.0/rules/pii/pii-017@1.0.0.yaml +48 -0
  510. raxe/packs/core/v1.0.0/rules/pii/pii-022@1.0.0.yaml +47 -0
  511. raxe/packs/core/v1.0.0/rules/pii/pii-025@1.0.0.yaml +47 -0
  512. raxe/packs/core/v1.0.0/rules/pii/pii-027@1.0.0.yaml +47 -0
  513. raxe/packs/core/v1.0.0/rules/pii/pii-028@1.0.0.yaml +47 -0
  514. raxe/packs/core/v1.0.0/rules/pii/pii-034@1.0.0.yaml +47 -0
  515. raxe/packs/core/v1.0.0/rules/pii/pii-037@1.0.0.yaml +47 -0
  516. raxe/packs/core/v1.0.0/rules/pii/pii-040@1.0.0.yaml +47 -0
  517. raxe/packs/core/v1.0.0/rules/pii/pii-041@1.0.0.yaml +47 -0
  518. raxe/packs/core/v1.0.0/rules/pii/pii-044@1.0.0.yaml +47 -0
  519. raxe/packs/core/v1.0.0/rules/pii/pii-050@1.0.0.yaml +57 -0
  520. raxe/packs/core/v1.0.0/rules/pii/pii-051@1.0.0.yaml +53 -0
  521. raxe/packs/core/v1.0.0/rules/pii/pii-052@1.0.0.yaml +52 -0
  522. raxe/packs/core/v1.0.0/rules/pii/pii-053@1.0.0.yaml +56 -0
  523. raxe/packs/core/v1.0.0/rules/pii/pii-054@1.0.0.yaml +53 -0
  524. raxe/packs/core/v1.0.0/rules/pii/pii-055@1.0.0.yaml +51 -0
  525. raxe/packs/core/v1.0.0/rules/pii/pii-056@1.0.0.yaml +51 -0
  526. raxe/packs/core/v1.0.0/rules/pii/pii-058@1.0.0.yaml +47 -0
  527. raxe/packs/core/v1.0.0/rules/pii/pii-2015@1.0.0.yaml +41 -0
  528. raxe/packs/core/v1.0.0/rules/pii/pii-2025@1.0.0.yaml +35 -0
  529. raxe/packs/core/v1.0.0/rules/pii/pii-2026@1.0.0.yaml +39 -0
  530. raxe/packs/core/v1.0.0/rules/pii/pii-2035@1.0.0.yaml +39 -0
  531. raxe/packs/core/v1.0.0/rules/pii/pii-2037@1.0.0.yaml +39 -0
  532. raxe/packs/core/v1.0.0/rules/pii/pii-2042@1.0.0.yaml +39 -0
  533. raxe/packs/core/v1.0.0/rules/pii/pii-3001@1.0.0.yaml +39 -0
  534. raxe/packs/core/v1.0.0/rules/pii/pii-3002@1.0.0.yaml +41 -0
  535. raxe/packs/core/v1.0.0/rules/pii/pii-3003@1.0.0.yaml +36 -0
  536. raxe/packs/core/v1.0.0/rules/pii/pii-3004@1.0.0.yaml +41 -0
  537. raxe/packs/core/v1.0.0/rules/pii/pii-3005@1.0.0.yaml +39 -0
  538. raxe/packs/core/v1.0.0/rules/pii/pii-3006@1.0.0.yaml +35 -0
  539. raxe/packs/core/v1.0.0/rules/pii/pii-3007@1.0.0.yaml +37 -0
  540. raxe/packs/core/v1.0.0/rules/pii/pii-3008@1.0.0.yaml +35 -0
  541. raxe/packs/core/v1.0.0/rules/pii/pii-3009@1.0.0.yaml +42 -0
  542. raxe/packs/core/v1.0.0/rules/pii/pii-3010@1.0.0.yaml +39 -0
  543. raxe/packs/core/v1.0.0/rules/pii/pii-3011@1.0.0.yaml +35 -0
  544. raxe/packs/core/v1.0.0/rules/pii/pii-3012@1.0.0.yaml +35 -0
  545. raxe/packs/core/v1.0.0/rules/pii/pii-3013@1.0.0.yaml +36 -0
  546. raxe/packs/core/v1.0.0/rules/pii/pii-3014@1.0.0.yaml +36 -0
  547. raxe/packs/core/v1.0.0/rules/pii/pii-3015@1.0.0.yaml +42 -0
  548. raxe/packs/core/v1.0.0/rules/pii/pii-3016@1.0.0.yaml +42 -0
  549. raxe/packs/core/v1.0.0/rules/pii/pii-3017@1.0.0.yaml +40 -0
  550. raxe/packs/core/v1.0.0/rules/pii/pii-3018@1.0.0.yaml +38 -0
  551. raxe/packs/core/v1.0.0/rules/pii/pii-3019@1.0.0.yaml +40 -0
  552. raxe/packs/core/v1.0.0/rules/pii/pii-3020@1.0.0.yaml +40 -0
  553. raxe/packs/core/v1.0.0/rules/pii/pii-3021@1.0.0.yaml +39 -0
  554. raxe/packs/core/v1.0.0/rules/pii/pii-3022@1.0.0.yaml +36 -0
  555. raxe/packs/core/v1.0.0/rules/pii/pii-3023@1.0.0.yaml +41 -0
  556. raxe/packs/core/v1.0.0/rules/pii/pii-3024@1.0.0.yaml +37 -0
  557. raxe/packs/core/v1.0.0/rules/pii/pii-3025@1.0.0.yaml +38 -0
  558. raxe/packs/core/v1.0.0/rules/pii/pii-3026@1.0.0.yaml +42 -0
  559. raxe/packs/core/v1.0.0/rules/pii/pii-3027@1.0.0.yaml +38 -0
  560. raxe/packs/core/v1.0.0/rules/pii/pii-3028@1.0.0.yaml +42 -0
  561. raxe/packs/core/v1.0.0/rules/pii/pii-3029@1.0.0.yaml +36 -0
  562. raxe/packs/core/v1.0.0/rules/pii/pii-3030@1.0.0.yaml +42 -0
  563. raxe/packs/core/v1.0.0/rules/pii/pii-3031@1.0.0.yaml +37 -0
  564. raxe/packs/core/v1.0.0/rules/pii/pii-3032@1.0.0.yaml +42 -0
  565. raxe/packs/core/v1.0.0/rules/pii/pii-3033@1.0.0.yaml +39 -0
  566. raxe/packs/core/v1.0.0/rules/pii/pii-3034@1.0.0.yaml +40 -0
  567. raxe/packs/core/v1.0.0/rules/pii/pii-3035@1.0.0.yaml +43 -0
  568. raxe/packs/core/v1.0.0/rules/pii/pii-3036@1.0.0.yaml +41 -0
  569. raxe/packs/core/v1.0.0/rules/pii/pii-3037@1.0.0.yaml +35 -0
  570. raxe/packs/core/v1.0.0/rules/pii/pii-3038@1.0.0.yaml +35 -0
  571. raxe/packs/core/v1.0.0/rules/pii/pii-3039@1.0.0.yaml +35 -0
  572. raxe/packs/core/v1.0.0/rules/pii/pii-3040@1.0.0.yaml +41 -0
  573. raxe/packs/core/v1.0.0/rules/pii/pii-3041@1.0.0.yaml +39 -0
  574. raxe/packs/core/v1.0.0/rules/pii/pii-3042@1.0.0.yaml +36 -0
  575. raxe/packs/core/v1.0.0/rules/pii/pii-3043@1.0.0.yaml +35 -0
  576. raxe/packs/core/v1.0.0/rules/pii/pii-3044@1.0.0.yaml +43 -0
  577. raxe/packs/core/v1.0.0/rules/pii/pii-3045@1.0.0.yaml +36 -0
  578. raxe/packs/core/v1.0.0/rules/pii/pii-3046@1.0.0.yaml +37 -0
  579. raxe/packs/core/v1.0.0/rules/pii/pii-3047@1.0.0.yaml +36 -0
  580. raxe/packs/core/v1.0.0/rules/pii/pii-3048@1.0.0.yaml +36 -0
  581. raxe/packs/core/v1.0.0/rules/pii/pii-3049@1.0.0.yaml +38 -0
  582. raxe/packs/core/v1.0.0/rules/pii/pii-3050@1.0.0.yaml +44 -0
  583. raxe/packs/core/v1.0.0/rules/pii/pii-3051@1.0.0.yaml +35 -0
  584. raxe/packs/core/v1.0.0/rules/pii/pii-3052@1.0.0.yaml +36 -0
  585. raxe/packs/core/v1.0.0/rules/pii/pii-3053@1.0.0.yaml +35 -0
  586. raxe/packs/core/v1.0.0/rules/pii/pii-3054@1.0.0.yaml +35 -0
  587. raxe/packs/core/v1.0.0/rules/pii/pii-3055@1.0.0.yaml +40 -0
  588. raxe/packs/core/v1.0.0/rules/pii/pii-3056@1.0.0.yaml +38 -0
  589. raxe/packs/core/v1.0.0/rules/pii/pii-3057@1.0.0.yaml +40 -0
  590. raxe/packs/core/v1.0.0/rules/pii/pii-3058@1.0.0.yaml +43 -0
  591. raxe/packs/core/v1.0.0/rules/pii/pii-3059@1.0.0.yaml +42 -0
  592. raxe/packs/core/v1.0.0/rules/pii/pii-3060@1.0.0.yaml +42 -0
  593. raxe/packs/core/v1.0.0/rules/pii/pii-3061@1.0.0.yaml +50 -0
  594. raxe/packs/core/v1.0.0/rules/pii/pii-3062@1.0.0.yaml +50 -0
  595. raxe/packs/core/v1.0.0/rules/pii/pii-3063@1.0.0.yaml +54 -0
  596. raxe/packs/core/v1.0.0/rules/pii/pii-3064@1.0.0.yaml +78 -0
  597. raxe/packs/core/v1.0.0/rules/pii/pii-3065@1.0.0.yaml +84 -0
  598. raxe/packs/core/v1.0.0/rules/pii/pii-3066@1.0.0.yaml +84 -0
  599. raxe/packs/core/v1.0.0/rules/pii/pii-3067@1.0.0.yaml +88 -0
  600. raxe/packs/core/v1.0.0/rules/pii/pii-3068@1.0.0.yaml +94 -0
  601. raxe/packs/core/v1.0.0/rules/pii/pii-3069@1.0.0.yaml +90 -0
  602. raxe/packs/core/v1.0.0/rules/pii/pii-3070@1.0.0.yaml +99 -0
  603. raxe/packs/core/v1.0.0/rules/pii/pii-3071@1.0.0.yaml +91 -0
  604. raxe/packs/core/v1.0.0/rules/pii/pii-3072@1.0.0.yaml +38 -0
  605. raxe/packs/core/v1.0.0/rules/pii/pii-3073@1.0.0.yaml +38 -0
  606. raxe/packs/core/v1.0.0/rules/pii/pii-3074@1.0.0.yaml +38 -0
  607. raxe/packs/core/v1.0.0/rules/pii/pii-3075@1.0.0.yaml +38 -0
  608. raxe/packs/core/v1.0.0/rules/pii/pii-3076@1.0.0.yaml +38 -0
  609. raxe/packs/core/v1.0.0/rules/pii/pii-3077@1.0.0.yaml +38 -0
  610. raxe/packs/core/v1.0.0/rules/pii/pii-3078@1.0.0.yaml +38 -0
  611. raxe/packs/core/v1.0.0/rules/pii/pii-3079@1.0.0.yaml +38 -0
  612. raxe/packs/core/v1.0.0/rules/pii/pii-3080@1.0.0.yaml +38 -0
  613. raxe/packs/core/v1.0.0/rules/pii/pii-3081@1.0.0.yaml +38 -0
  614. raxe/packs/core/v1.0.0/rules/pii/pii-3082@1.0.0.yaml +38 -0
  615. raxe/packs/core/v1.0.0/rules/pii/pii-3083@1.0.0.yaml +38 -0
  616. raxe/packs/core/v1.0.0/rules/pii/pii-3084@1.0.0.yaml +38 -0
  617. raxe/packs/core/v1.0.0/rules/pii/pii-3085@1.0.0.yaml +38 -0
  618. raxe/packs/core/v1.0.0/rules/rag/rag-016@1.0.0.yaml +47 -0
  619. raxe/packs/core/v1.0.0/rules/rag/rag-028@1.0.0.yaml +47 -0
  620. raxe/packs/core/v1.0.0/rules/rag/rag-042@1.0.0.yaml +47 -0
  621. raxe/packs/core/v1.0.0/rules/rag/rag-044@1.0.0.yaml +47 -0
  622. raxe/packs/core/v1.0.0/rules/rag/rag-045@1.0.0.yaml +47 -0
  623. raxe/packs/core/v1.0.0/rules/rag/rag-050@1.0.0.yaml +47 -0
  624. raxe/packs/core/v1.0.0/rules/rag/rag-201@1.0.0.yaml +41 -0
  625. raxe/packs/core/v1.0.0/rules/rag/rag-202@1.0.0.yaml +41 -0
  626. raxe/packs/core/v1.0.0/rules/rag/rag-3001@1.0.0.yaml +41 -0
  627. raxe/packs/core/v1.0.0/rules/rag/rag-3006@1.0.0.yaml +41 -0
  628. raxe/packs/core/v1.0.0/rules/rag/rag-3009@1.0.0.yaml +41 -0
  629. raxe/packs/core/v1.0.0/rules/rag/rag-3012@1.0.0.yaml +41 -0
  630. raxe/plugins/__init__.py +98 -0
  631. raxe/plugins/custom_rules.py +380 -0
  632. raxe/plugins/loader.py +389 -0
  633. raxe/plugins/manager.py +538 -0
  634. raxe/plugins/protocol.py +428 -0
  635. raxe/py.typed +0 -0
  636. raxe/sdk/__init__.py +77 -0
  637. raxe/sdk/agent_scanner.py +1918 -0
  638. raxe/sdk/client.py +1603 -0
  639. raxe/sdk/decorator.py +175 -0
  640. raxe/sdk/exceptions.py +859 -0
  641. raxe/sdk/integrations/__init__.py +277 -0
  642. raxe/sdk/integrations/agent_scanner.py +71 -0
  643. raxe/sdk/integrations/autogen.py +872 -0
  644. raxe/sdk/integrations/crewai.py +1368 -0
  645. raxe/sdk/integrations/dspy.py +845 -0
  646. raxe/sdk/integrations/extractors.py +363 -0
  647. raxe/sdk/integrations/huggingface.py +395 -0
  648. raxe/sdk/integrations/langchain.py +948 -0
  649. raxe/sdk/integrations/litellm.py +484 -0
  650. raxe/sdk/integrations/llamaindex.py +1049 -0
  651. raxe/sdk/integrations/portkey.py +831 -0
  652. raxe/sdk/suppression_context.py +215 -0
  653. raxe/sdk/wrappers/__init__.py +163 -0
  654. raxe/sdk/wrappers/anthropic.py +310 -0
  655. raxe/sdk/wrappers/openai.py +221 -0
  656. raxe/sdk/wrappers/vertexai.py +484 -0
  657. raxe/utils/__init__.py +12 -0
  658. raxe/utils/error_sanitizer.py +135 -0
  659. raxe/utils/logging.py +241 -0
  660. raxe/utils/performance.py +414 -0
  661. raxe/utils/profiler.py +339 -0
  662. raxe/utils/validators.py +170 -0
  663. raxe-0.4.6.dist-info/METADATA +471 -0
  664. raxe-0.4.6.dist-info/RECORD +668 -0
  665. raxe-0.4.6.dist-info/WHEEL +5 -0
  666. raxe-0.4.6.dist-info/entry_points.txt +2 -0
  667. raxe-0.4.6.dist-info/licenses/LICENSE +56 -0
  668. raxe-0.4.6.dist-info/top_level.txt +1 -0
raxe/cli/main.py ADDED
@@ -0,0 +1,1137 @@
1
+ """
2
+ RAXE CLI - Command-line interface.
3
+
4
+ Uses the unified Raxe client internally - no duplicate logic.
5
+ """
6
+ import json
7
+ import sys
8
+ from pathlib import Path
9
+
10
+ import click
11
+
12
+ from raxe import __version__
13
+ from raxe.cli.auth import auth, auth_link
14
+ from raxe.cli.config import config
15
+ from raxe.cli.doctor import doctor
16
+ from raxe.cli.event import event
17
+ from raxe.cli.error_handler import handle_cli_error
18
+ from raxe.cli.exit_codes import (
19
+ EXIT_CONFIG_ERROR,
20
+ EXIT_INVALID_INPUT,
21
+ EXIT_SCAN_ERROR,
22
+ EXIT_THREAT_DETECTED,
23
+ )
24
+ from raxe.cli.expiry_warning import check_and_display_expiry_warning
25
+ from raxe.cli.export import export
26
+ from raxe.cli.history import history
27
+ from raxe.cli.models import models
28
+ from raxe.cli.output import console, display_error, display_scan_result, display_success
29
+ from raxe.cli.privacy import privacy_command
30
+ from raxe.cli.profiler import profile_command
31
+ from raxe.cli.repl import repl
32
+ from raxe.cli.rules import rules
33
+ from raxe.cli.stats import stats
34
+ from raxe.cli.suppress import suppress
35
+ from raxe.cli.telemetry import telemetry
36
+ from raxe.cli.test import test
37
+ from raxe.cli.tune import tune
38
+ from raxe.cli.validate import validate_rule_command
39
+ from raxe.sdk.client import Raxe
40
+
41
+
42
+ # Note: Telemetry flush is now handled by the unified helper:
43
+ # from raxe.infrastructure.telemetry.flush_helper import ensure_telemetry_flushed
44
+
45
+
46
+ @click.group(invoke_without_command=True)
47
+ @click.version_option(version=__version__, prog_name="RAXE CLI", message="%(prog)s %(version)s")
48
+ @click.option(
49
+ "--no-color",
50
+ is_flag=True,
51
+ help="Disable colored output",
52
+ envvar="RAXE_NO_COLOR",
53
+ )
54
+ @click.option(
55
+ "--verbose",
56
+ is_flag=True,
57
+ help="Show detailed logs (enables console logging)",
58
+ envvar="RAXE_VERBOSE",
59
+ )
60
+ @click.option(
61
+ "--quiet",
62
+ is_flag=True,
63
+ help="Suppress all visual output (for CI/CD)",
64
+ envvar="RAXE_QUIET",
65
+ )
66
+ @click.pass_context
67
+ def cli(ctx, no_color: bool, verbose: bool, quiet: bool):
68
+ """RAXE - AI Security for LLMs • Privacy-First Threat Detection"""
69
+ # Flush any stale telemetry from previous sessions (non-blocking background thread)
70
+ # This recovers events that were queued but not flushed due to crashes or improper exit
71
+ try:
72
+ from raxe.infrastructure.telemetry.flush_helper import flush_stale_telemetry_async
73
+ flush_stale_telemetry_async()
74
+ except Exception:
75
+ pass # Never block CLI startup
76
+
77
+ # Ensure ctx.obj exists for sub-commands
78
+ ctx.ensure_object(dict)
79
+ ctx.obj["no_color"] = no_color or quiet # Quiet implies no color
80
+ ctx.obj["verbose"] = verbose and not quiet # Quiet overrides verbose
81
+ ctx.obj["quiet"] = quiet
82
+
83
+ # Show welcome banner if no command provided (unless quiet)
84
+ if ctx.invoked_subcommand is None:
85
+ if not quiet:
86
+ # Check if this is a first run
87
+ from raxe.cli.setup_wizard import check_first_run, display_first_run_message
88
+
89
+ if check_first_run():
90
+ display_first_run_message(console)
91
+ else:
92
+ from raxe.cli.branding import print_help_menu
93
+ print_help_menu(console)
94
+ ctx.exit()
95
+
96
+ # Track command usage (record the invoked command name)
97
+ if ctx.invoked_subcommand:
98
+ try:
99
+ from raxe.infrastructure.tracking.usage import UsageTracker
100
+ tracker = UsageTracker()
101
+ tracker.record_command(ctx.invoked_subcommand)
102
+ except Exception:
103
+ # Don't fail if tracking fails
104
+ pass
105
+
106
+ # Enable console logging if verbose flag set
107
+ if verbose:
108
+ import os
109
+ os.environ["RAXE_ENABLE_CONSOLE_LOGGING"] = "true"
110
+
111
+ # Reconfigure logging to enable console output
112
+ from raxe.utils.logging import setup_logging
113
+ setup_logging(enable_console_logging=True)
114
+
115
+
116
+ @cli.command()
117
+ @click.option(
118
+ "--api-key",
119
+ help="RAXE API key (optional, for cloud features)",
120
+ envvar="RAXE_API_KEY",
121
+ )
122
+ @click.option(
123
+ "--telemetry/--no-telemetry",
124
+ default=True,
125
+ help="Enable privacy-preserving telemetry (default: enabled)",
126
+ )
127
+ @click.option(
128
+ "--force",
129
+ is_flag=True,
130
+ help="Overwrite existing configuration",
131
+ )
132
+ @handle_cli_error
133
+ def init(api_key: str | None, telemetry: bool, force: bool):
134
+ """Initialize RAXE configuration with interactive setup."""
135
+ from rich.panel import Panel
136
+ from rich.text import Text
137
+
138
+ from raxe.cli.branding import print_info, print_logo, print_success
139
+
140
+ config_dir = Path.home() / ".raxe"
141
+ config_file = config_dir / "config.yaml"
142
+
143
+ # Show compact logo
144
+ print_logo(console, compact=True)
145
+ console.print()
146
+ console.print("🔧 [bold cyan]RAXE Initialization[/bold cyan]")
147
+ console.print()
148
+
149
+ # Check if already initialized
150
+ if config_file.exists() and not force:
151
+ print_success(console, f"RAXE already initialized at {config_file}")
152
+ print_info(console, "Use --force to overwrite existing configuration")
153
+ return
154
+
155
+ # Create config directory
156
+ config_dir.mkdir(parents=True, exist_ok=True)
157
+
158
+ # Show configuration summary
159
+ summary = Text()
160
+ summary.append("Configuration Summary:\n\n", style="bold cyan")
161
+ summary.append(" 📂 Location: ", style="white")
162
+ summary.append(f"{config_file}\n", style="cyan")
163
+ summary.append(" 🔑 API Key: ", style="white")
164
+ summary.append(f"{api_key if api_key else 'Not configured (optional)'}\n", style="yellow" if not api_key else "green")
165
+ summary.append(" 📊 Telemetry: ", style="white")
166
+ summary.append(f"{'Enabled' if telemetry else 'Disabled'}\n", style="green" if telemetry else "yellow")
167
+ summary.append(" ⚡ Performance: ", style="white")
168
+ summary.append("Balanced mode with L2 detection\n", style="cyan")
169
+
170
+ console.print(Panel(summary, border_style="cyan", padding=(1, 2)))
171
+ console.print()
172
+
173
+ # Generate config
174
+ config_content = f"""# RAXE Configuration
175
+ version: 1.0.0
176
+
177
+ # API Key (optional - for cloud features)
178
+ {"api_key: " + api_key if api_key else "# api_key: raxe_test_customer123_abc456"}
179
+
180
+ # Telemetry (privacy-preserving, only hashes sent)
181
+ telemetry:
182
+ enabled: {str(telemetry).lower()}
183
+ endpoint: https://api.beta.raxe.ai/v1/telemetry
184
+
185
+ # Performance
186
+ performance:
187
+ mode: balanced # fast, balanced, accurate
188
+ l2_enabled: true
189
+ max_latency_ms: 10
190
+
191
+ # Pack precedence (custom > community > core)
192
+ packs:
193
+ precedence:
194
+ - custom
195
+ - community
196
+ - core
197
+
198
+ # Policy source
199
+ policies:
200
+ source: local_file # local_file, api, inline
201
+ path: .raxe/policies.yaml
202
+ """
203
+
204
+ config_file.write_text(config_content)
205
+
206
+ print_success(console, "RAXE initialized successfully!")
207
+ console.print()
208
+
209
+ # Next steps panel
210
+ next_steps = Text()
211
+ next_steps.append("Quick Start:\n\n", style="bold cyan")
212
+ next_steps.append(" 1️⃣ ", style="white")
213
+ next_steps.append('raxe scan "your text here"\n', style="cyan")
214
+ next_steps.append(" Scan text for security threats\n\n", style="dim")
215
+ next_steps.append(" 2️⃣ ", style="white")
216
+ next_steps.append('raxe test\n', style="cyan")
217
+ next_steps.append(" Test your configuration\n\n", style="dim")
218
+ next_steps.append(" 3️⃣ ", style="white")
219
+ next_steps.append('raxe stats\n', style="cyan")
220
+ next_steps.append(" View statistics & achievements\n\n", style="dim")
221
+ next_steps.append(" 📚 ", style="white")
222
+ next_steps.append('https://docs.raxe.ai\n', style="cyan underline")
223
+ next_steps.append(" Read the documentation", style="dim")
224
+
225
+ console.print(Panel(next_steps, title="[bold cyan]Next Steps[/bold cyan]", border_style="cyan", padding=(1, 2)))
226
+ console.print()
227
+
228
+
229
+ @cli.command()
230
+ @handle_cli_error
231
+ def setup():
232
+ """Interactive setup wizard for first-time users.
233
+
234
+ Provides a friendly, guided setup experience that walks you through:
235
+ - API key configuration (or temp key auto-generation)
236
+ - Detection settings (L2 ML detection, telemetry)
237
+ - Shell completion installation
238
+ - Configuration file creation
239
+ - Test scan verification
240
+
241
+ \b
242
+ Examples:
243
+ raxe setup
244
+ """
245
+ from raxe.cli.setup_wizard import run_setup_wizard
246
+
247
+ success = run_setup_wizard(console)
248
+
249
+ if not success:
250
+ sys.exit(1)
251
+
252
+
253
+ def parse_suppress_pattern(pattern: str) -> tuple[str, str]:
254
+ """Parse suppress pattern with optional action override.
255
+
256
+ Formats:
257
+ pi-001 -> (pi-001, SUPPRESS)
258
+ pi-001:FLAG -> (pi-001, FLAG)
259
+ pi-001:LOG -> (pi-001, LOG)
260
+ jb-* -> (jb-*, SUPPRESS)
261
+ jb-*:FLAG -> (jb-*, FLAG)
262
+
263
+ Args:
264
+ pattern: Pattern string, optionally with :ACTION suffix
265
+
266
+ Returns:
267
+ Tuple of (rule_pattern, action)
268
+
269
+ Raises:
270
+ click.BadParameter: If action is invalid
271
+ """
272
+ if ":" in pattern:
273
+ parts = pattern.rsplit(":", 1)
274
+ rule_pattern = parts[0]
275
+ action = parts[1].upper()
276
+ if action not in ("SUPPRESS", "FLAG", "LOG"):
277
+ raise click.BadParameter(
278
+ f"Invalid action '{action}'. Valid actions: SUPPRESS, FLAG, LOG"
279
+ )
280
+ return rule_pattern, action
281
+ return pattern, "SUPPRESS"
282
+
283
+
284
+ @cli.command()
285
+ @click.argument("text", required=False)
286
+ @click.option(
287
+ "--stdin",
288
+ is_flag=True,
289
+ help="Read text from stdin instead of argument",
290
+ )
291
+ @click.option(
292
+ "--format",
293
+ type=click.Choice(["text", "json", "yaml", "table"]),
294
+ default="text",
295
+ help="Output format (default: text)",
296
+ )
297
+ @click.option(
298
+ "--ci",
299
+ is_flag=True,
300
+ help="CI/CD mode: JSON output, no banner, exit code 1 on threats",
301
+ envvar="RAXE_CI",
302
+ )
303
+ @click.option(
304
+ "--profile",
305
+ is_flag=True,
306
+ help="Enable performance profiling",
307
+ )
308
+ @click.option(
309
+ "--l1-only",
310
+ is_flag=True,
311
+ help="Use L1 (regex) detection only",
312
+ )
313
+ @click.option(
314
+ "--l2-only",
315
+ is_flag=True,
316
+ help="Use L2 (ML) detection only",
317
+ )
318
+ @click.option(
319
+ "--mode",
320
+ type=click.Choice(["fast", "balanced", "thorough"]),
321
+ default="balanced",
322
+ help="Performance mode (default: balanced)",
323
+ )
324
+ @click.option(
325
+ "--confidence",
326
+ type=float,
327
+ help="Minimum confidence threshold (0.0-1.0)",
328
+ )
329
+ @click.option(
330
+ "--explain",
331
+ is_flag=True,
332
+ help="Show detailed explanation of detections",
333
+ )
334
+ @click.option(
335
+ "--dry-run",
336
+ is_flag=True,
337
+ help="Test scan without saving to database",
338
+ )
339
+ @click.option(
340
+ "--suppress",
341
+ "suppress_patterns",
342
+ multiple=True,
343
+ help="Suppress rule(s) for this scan. Supports wildcards and action override (e.g., pi-001, jb-*, pi-001:FLAG)",
344
+ )
345
+ @click.pass_context
346
+ def scan(
347
+ ctx,
348
+ text: str | None,
349
+ stdin: bool,
350
+ format: str,
351
+ ci: bool,
352
+ profile: bool,
353
+ l1_only: bool,
354
+ l2_only: bool,
355
+ mode: str,
356
+ confidence: float | None,
357
+ explain: bool,
358
+ dry_run: bool,
359
+ suppress_patterns: tuple[str, ...],
360
+ ):
361
+ """
362
+ Scan text for security threats.
363
+
364
+ \b
365
+ Examples:
366
+ raxe scan "Ignore all previous instructions"
367
+ echo "test" | raxe scan --stdin
368
+ raxe scan "prompt" --format json
369
+ raxe scan "text" --l1-only --mode fast
370
+ raxe scan "text" --confidence 0.8 --explain
371
+ raxe scan "text" --ci # CI/CD mode (JSON, exit 1 on threats)
372
+ raxe --quiet scan "text" # Same as --ci
373
+
374
+ \b
375
+ Suppression Examples:
376
+ raxe scan "text" --suppress pi-001 # Suppress single rule
377
+ raxe scan "text" --suppress pi-001 --suppress jb-* # Multiple suppressions
378
+ raxe scan "text" --suppress "pi-001:FLAG" # Flag instead of suppress
379
+
380
+ \b
381
+ Exit Codes (for CI/CD integration):
382
+ 0 Success - scan completed, no threats detected
383
+ 1 Threat detected (with --ci or --quiet mode)
384
+ 2 Invalid input - no text provided or bad arguments
385
+ 3 Configuration error - RAXE not initialized
386
+ 4 Scan error - execution failed
387
+ """
388
+ # Check if CI or quiet mode is enabled
389
+ # --ci flag is an explicit alias for CI/CD mode (same as --quiet)
390
+ quiet = ctx.obj.get("quiet", False) or ci
391
+ verbose = ctx.obj.get("verbose", False) and not ci # CI mode overrides verbose
392
+ no_color = ctx.obj.get("no_color", False) or ci # CI mode implies no color
393
+
394
+ # Auto-enable quiet mode for JSON/YAML formats to prevent progress contamination
395
+ if format in ("json", "yaml"):
396
+ quiet = True
397
+
398
+ # Override format to JSON if quiet mode
399
+ if quiet and format == "text":
400
+ format = "json"
401
+
402
+ # Show compact logo (for visual consistency)
403
+ from raxe.cli.branding import print_logo
404
+ if format == "text" and not quiet: # Only show for text output when not quiet
405
+ print_logo(console, compact=True)
406
+ console.print()
407
+ # Check and display API key expiry warning if applicable
408
+ check_and_display_expiry_warning(console)
409
+
410
+ # Get text from argument or stdin
411
+ if stdin:
412
+ text = sys.stdin.read()
413
+ elif not text:
414
+ display_error("No text provided", "Provide text as argument or use --stdin")
415
+ sys.exit(EXIT_INVALID_INPUT)
416
+
417
+ # Setup progress indicator
418
+ from raxe.cli.progress import create_progress_indicator
419
+ from raxe.cli.progress_context import detect_progress_mode
420
+
421
+ progress_mode = detect_progress_mode(
422
+ quiet=quiet,
423
+ verbose=verbose,
424
+ no_color=no_color
425
+ )
426
+
427
+ progress = create_progress_indicator(progress_mode)
428
+
429
+ # Create Raxe client (uses config if available)
430
+ try:
431
+ raxe = Raxe(progress_callback=progress)
432
+ except Exception as e:
433
+ display_error("Failed to initialize RAXE", str(e))
434
+ console.print("Try running: [cyan]raxe init[/cyan]")
435
+ sys.exit(EXIT_CONFIG_ERROR)
436
+
437
+ # Add CLI-specified suppressions (temporary, for this scan only)
438
+ cli_suppressions: list[tuple[str, str]] = [] # (pattern, action) tuples
439
+ if suppress_patterns:
440
+ from raxe.domain.suppression import Suppression, SuppressionAction, SuppressionValidationError
441
+
442
+ for pattern_str in suppress_patterns:
443
+ try:
444
+ rule_pattern, action_str = parse_suppress_pattern(pattern_str)
445
+ action = SuppressionAction(action_str)
446
+
447
+ # Add to suppression manager (temporary, runtime only)
448
+ raxe.suppression_manager.add_suppression(
449
+ pattern=rule_pattern,
450
+ reason="CLI --suppress flag",
451
+ action=action,
452
+ created_by="cli",
453
+ log_to_audit=False, # Don't log temporary suppressions
454
+ )
455
+ cli_suppressions.append((rule_pattern, action_str))
456
+ except SuppressionValidationError as e:
457
+ display_error(
458
+ f"Invalid suppression pattern: {pattern_str}",
459
+ f"{e}\n\nValid pattern examples:\n"
460
+ " pi-001 - Suppress specific rule\n"
461
+ " pi-* - Suppress all prompt injection rules\n"
462
+ " jb-*:FLAG - Flag jailbreak rules for review\n"
463
+ )
464
+ sys.exit(EXIT_INVALID_INPUT)
465
+ except click.BadParameter as e:
466
+ display_error(f"Invalid suppression pattern: {pattern_str}", str(e))
467
+ sys.exit(EXIT_INVALID_INPUT)
468
+
469
+ # Scan using unified client
470
+ # Wire all CLI flags to scan parameters
471
+ try:
472
+ if profile:
473
+ # Import profiler here to avoid circular dependency
474
+ try:
475
+ from raxe.monitoring.profiler import PerformanceProfiler
476
+
477
+ profiler = PerformanceProfiler()
478
+ prof_result = profiler.profile_scan(text, iterations=1)
479
+ result = raxe.scan(
480
+ text,
481
+ l1_enabled=not l2_only,
482
+ l2_enabled=not l1_only,
483
+ mode=mode,
484
+ confidence_threshold=confidence if confidence else 0.5,
485
+ explain=explain,
486
+ dry_run=dry_run,
487
+ entry_point="cli",
488
+ )
489
+
490
+ # Show scan result first
491
+ if format == "text":
492
+ no_color = ctx.obj.get("no_color", False)
493
+ display_scan_result(result, no_color=no_color, explain=explain)
494
+
495
+ # Then show profile
496
+ click.echo()
497
+ click.secho("=" * 60, fg="cyan")
498
+ click.secho("Performance Profile", fg="cyan", bold=True)
499
+ click.secho("=" * 60, fg="cyan")
500
+ click.echo(prof_result.stats_report)
501
+ else:
502
+ # For JSON/YAML, just show result (profile would clutter output)
503
+ result = raxe.scan(
504
+ text,
505
+ l1_enabled=not l2_only,
506
+ l2_enabled=not l1_only,
507
+ mode=mode,
508
+ confidence_threshold=confidence if confidence else 0.5,
509
+ explain=explain,
510
+ dry_run=dry_run,
511
+ entry_point="cli",
512
+ )
513
+ except ImportError:
514
+ console.print("[yellow]Warning: Profiling not available[/yellow]")
515
+ result = raxe.scan(
516
+ text,
517
+ l1_enabled=not l2_only,
518
+ l2_enabled=not l1_only,
519
+ mode=mode,
520
+ confidence_threshold=confidence if confidence else 0.5,
521
+ explain=explain,
522
+ dry_run=dry_run,
523
+ entry_point="cli",
524
+ )
525
+ else:
526
+ result = raxe.scan(
527
+ text,
528
+ l1_enabled=not l2_only,
529
+ l2_enabled=not l1_only,
530
+ mode=mode,
531
+ confidence_threshold=confidence if confidence else 0.5,
532
+ explain=explain,
533
+ dry_run=dry_run,
534
+ entry_point="cli",
535
+ )
536
+ except Exception as e:
537
+ display_error("Scan execution failed", str(e))
538
+ sys.exit(EXIT_SCAN_ERROR)
539
+
540
+ # Output based on format
541
+ if format == "json" and not profile:
542
+ # Collect L1 detections
543
+ l1_detections = []
544
+ for d in result.scan_result.l1_result.detections:
545
+ detection_dict = {
546
+ "rule_id": d.rule_id,
547
+ "severity": d.severity.value,
548
+ "confidence": d.confidence,
549
+ "layer": "L1",
550
+ "message": getattr(d, "message", ""),
551
+ }
552
+ # Include flag status if flagged
553
+ if getattr(d, "is_flagged", False):
554
+ detection_dict["is_flagged"] = True
555
+ if getattr(d, "suppression_reason", None):
556
+ detection_dict["flag_reason"] = d.suppression_reason
557
+ l1_detections.append(detection_dict)
558
+
559
+ # Collect L2 predictions
560
+ l2_detections = []
561
+ if result.scan_result.l2_result and result.scan_result.l2_result.has_predictions:
562
+ for p in result.scan_result.l2_result.predictions:
563
+ # Map confidence to severity
564
+ if p.confidence >= 0.8:
565
+ severity = "high"
566
+ elif p.confidence >= 0.6:
567
+ severity = "medium"
568
+ else:
569
+ severity = "low"
570
+
571
+ # Extract family/subfamily from bundle metadata if available
572
+ family = p.metadata.get("family")
573
+ sub_family = p.metadata.get("sub_family")
574
+ scores = p.metadata.get("scores", {})
575
+ why_it_hit = p.metadata.get("why_it_hit", [])
576
+ recommended_action = p.metadata.get("recommended_action", [])
577
+
578
+ detection = {
579
+ "rule_id": f"L2-{p.threat_type.value}",
580
+ "severity": severity,
581
+ "confidence": p.confidence,
582
+ "layer": "L2",
583
+ "message": p.explanation or f"{p.threat_type.value} detected",
584
+ }
585
+
586
+ # Add ML model metadata fields if available
587
+ if family:
588
+ detection["family"] = family
589
+ if sub_family:
590
+ detection["sub_family"] = sub_family
591
+ if scores:
592
+ detection["scores"] = scores
593
+ if why_it_hit:
594
+ detection["why_it_hit"] = why_it_hit
595
+ if recommended_action:
596
+ detection["recommended_action"] = recommended_action
597
+
598
+ l2_detections.append(detection)
599
+
600
+ output = {
601
+ "has_detections": result.scan_result.has_threats,
602
+ "detections": l1_detections + l2_detections,
603
+ "duration_ms": result.duration_ms,
604
+ "l1_count": len(l1_detections),
605
+ "l2_count": len(l2_detections),
606
+ }
607
+ click.echo(json.dumps(output, indent=2))
608
+
609
+ elif format == "yaml" and not profile:
610
+ try:
611
+ import yaml
612
+
613
+ # Collect L1 detections
614
+ l1_detections = []
615
+ for d in result.scan_result.l1_result.detections:
616
+ detection_dict = {
617
+ "rule_id": d.rule_id,
618
+ "severity": d.severity.value,
619
+ "confidence": d.confidence,
620
+ "layer": "L1",
621
+ "message": getattr(d, "message", ""),
622
+ }
623
+ # Include flag status if flagged
624
+ if getattr(d, "is_flagged", False):
625
+ detection_dict["is_flagged"] = True
626
+ if getattr(d, "suppression_reason", None):
627
+ detection_dict["flag_reason"] = d.suppression_reason
628
+ l1_detections.append(detection_dict)
629
+
630
+ # Collect L2 predictions
631
+ l2_detections = []
632
+ if result.scan_result.l2_result and result.scan_result.l2_result.has_predictions:
633
+ for p in result.scan_result.l2_result.predictions:
634
+ # Map confidence to severity
635
+ if p.confidence >= 0.8:
636
+ severity = "high"
637
+ elif p.confidence >= 0.6:
638
+ severity = "medium"
639
+ else:
640
+ severity = "low"
641
+
642
+ l2_detections.append({
643
+ "rule_id": f"L2-{p.threat_type.value}",
644
+ "severity": severity,
645
+ "confidence": p.confidence,
646
+ "layer": "L2",
647
+ "message": p.explanation or f"{p.threat_type.value} detected",
648
+ })
649
+
650
+ output = {
651
+ "has_detections": result.scan_result.has_threats,
652
+ "detections": l1_detections + l2_detections,
653
+ "duration_ms": result.duration_ms,
654
+ "l1_count": len(l1_detections),
655
+ "l2_count": len(l2_detections),
656
+ }
657
+ click.echo(yaml.dump(output))
658
+ except ImportError:
659
+ display_error("PyYAML not installed", "Use --format json instead")
660
+ sys.exit(EXIT_CONFIG_ERROR)
661
+
662
+ elif format == "text" and not profile:
663
+ # Use rich output
664
+ no_color = ctx.obj.get("no_color", False)
665
+ display_scan_result(result, no_color=no_color, explain=explain)
666
+
667
+ # Show dry-run feedback after displaying result (unless quiet)
668
+ if dry_run and not quiet:
669
+ console.print()
670
+ console.print("[yellow] Dry run mode: Results not saved to database[/yellow]")
671
+ console.print()
672
+
673
+ # Auto-flush telemetry at end of scan using unified helper
674
+ # This ends the session and flushes all queued events
675
+ try:
676
+ from raxe.infrastructure.telemetry.flush_helper import ensure_telemetry_flushed
677
+
678
+ ensure_telemetry_flushed(timeout_seconds=2.0, end_session=True)
679
+ except Exception:
680
+ pass # Never let telemetry affect scan completion
681
+
682
+ # Exit with appropriate code for CI/CD (quiet mode)
683
+ if quiet and result.scan_result.has_threats:
684
+ sys.exit(EXIT_THREAT_DETECTED)
685
+
686
+
687
+ @cli.command("batch")
688
+ @click.argument("file", type=click.Path(exists=True))
689
+ @click.option(
690
+ "--format", "output_format",
691
+ type=click.Choice(["text", "json", "csv"]),
692
+ default="text",
693
+ help="Output format (default: text)",
694
+ )
695
+ @click.option(
696
+ "--output",
697
+ type=click.Path(),
698
+ help="Output file for results (default: stdout)",
699
+ )
700
+ @click.option(
701
+ "--fail-fast",
702
+ is_flag=True,
703
+ help="Stop on first critical threat",
704
+ )
705
+ @handle_cli_error
706
+ def batch_scan(file: str, output_format: str, output: str | None, fail_fast: bool) -> None:
707
+ """
708
+ Batch scan prompts from a file.
709
+
710
+ Reads prompts from a file (one per line) and scans each.
711
+
712
+ \b
713
+ Examples:
714
+ raxe batch prompts.txt
715
+ raxe batch prompts.txt --format json --output results.json
716
+ raxe batch prompts.txt --fail-fast
717
+ """
718
+ import csv as csv_module
719
+ from pathlib import Path
720
+
721
+ from raxe.cli.branding import print_logo
722
+
723
+ # Show compact logo for text output
724
+ if output_format == "text":
725
+ print_logo(console, compact=True)
726
+ console.print()
727
+ # Check and display API key expiry warning if applicable
728
+ check_and_display_expiry_warning(console)
729
+
730
+ try:
731
+ raxe = Raxe()
732
+ except Exception as e:
733
+ display_error("Failed to initialize RAXE", str(e))
734
+ console.print("Try running: [cyan]raxe init[/cyan]")
735
+ sys.exit(EXIT_CONFIG_ERROR)
736
+
737
+ # Read prompts from file
738
+ # Supports both plain text (one prompt per line) and JSON format
739
+ # JSON format: {"id": "...", "prompt": "...", ...} - extracts "prompt" field
740
+ import json as json_module
741
+
742
+ def extract_prompt(line: str) -> str:
743
+ """Extract prompt from line, handling JSON if present."""
744
+ line = line.strip()
745
+ if not line:
746
+ return ""
747
+ # Try to parse as JSON and extract "prompt" field
748
+ if line.startswith("{"):
749
+ try:
750
+ data = json_module.loads(line)
751
+ if isinstance(data, dict) and "prompt" in data:
752
+ return str(data["prompt"])
753
+ except json_module.JSONDecodeError:
754
+ pass # Not valid JSON, use line as-is
755
+ return line
756
+
757
+ try:
758
+ with open(file) as f:
759
+ prompts = [extract_prompt(line) for line in f]
760
+ prompts = [p for p in prompts if p] # Filter empty
761
+ except Exception as e:
762
+ display_error("Failed to read input file", str(e))
763
+ sys.exit(EXIT_INVALID_INPUT)
764
+
765
+ if not prompts:
766
+ console.print("[yellow]No prompts found in file[/yellow]")
767
+ return
768
+
769
+ console.print(f"[cyan]Batch scanning {len(prompts)} prompts...[/cyan]")
770
+ console.print()
771
+
772
+ # Scan all prompts
773
+ results = []
774
+ threats_found = 0
775
+ critical_found = False
776
+
777
+ from raxe.cli.output import create_progress_bar
778
+
779
+ with create_progress_bar("Scanning...") as progress:
780
+ task = progress.add_task("Processing...", total=len(prompts))
781
+
782
+ for i, prompt in enumerate(prompts):
783
+ try:
784
+ result = raxe.scan(prompt)
785
+ results.append({
786
+ "line": i + 1,
787
+ "prompt": prompt[:50] + "..." if len(prompt) > 50 else prompt,
788
+ "has_threats": result.scan_result.has_threats,
789
+ "detection_count": len(result.scan_result.l1_result.detections),
790
+ "highest_severity": result.scan_result.combined_severity.value if result.scan_result.has_threats else "none",
791
+ "duration_ms": result.duration_ms,
792
+ "detections": [
793
+ {
794
+ "rule_id": d.rule_id,
795
+ "severity": d.severity.value,
796
+ "confidence": d.confidence,
797
+ }
798
+ for d in result.scan_result.l1_result.detections
799
+ ],
800
+ })
801
+
802
+ if result.scan_result.has_threats:
803
+ threats_found += 1
804
+ if result.scan_result.combined_severity.value == "critical":
805
+ critical_found = True
806
+ if fail_fast:
807
+ console.print()
808
+ console.print(f"[red bold]Critical threat found at line {i+1}. Stopping.[/red bold]")
809
+ break
810
+
811
+ progress.update(task, completed=i + 1)
812
+
813
+ except Exception as e:
814
+ console.print()
815
+ display_error(f"Error scanning line {i+1}", str(e))
816
+ if fail_fast:
817
+ break
818
+
819
+ console.print()
820
+
821
+ # Output results
822
+ if output_format == "json":
823
+ import json
824
+ output_data = {
825
+ "total_scanned": len(results),
826
+ "threats_found": threats_found,
827
+ "results": results,
828
+ }
829
+
830
+ if output:
831
+ Path(output).write_text(json.dumps(output_data, indent=2))
832
+ display_success(f"Results written to {output}")
833
+ else:
834
+ console.print(json.dumps(output_data, indent=2))
835
+
836
+ elif output_format == "csv":
837
+ if not output:
838
+ display_error("CSV format requires --output option", "Specify output file with --output")
839
+ sys.exit(EXIT_INVALID_INPUT)
840
+
841
+ with open(output, "w", newline="") as f:
842
+ writer = csv_module.DictWriter(
843
+ f,
844
+ fieldnames=["line", "prompt", "has_threats", "detection_count", "highest_severity", "duration_ms"]
845
+ )
846
+ writer.writeheader()
847
+ for result in results:
848
+ writer.writerow({
849
+ "line": result["line"],
850
+ "prompt": result["prompt"],
851
+ "has_threats": result["has_threats"],
852
+ "detection_count": result["detection_count"],
853
+ "highest_severity": result["highest_severity"],
854
+ "duration_ms": result["duration_ms"],
855
+ })
856
+
857
+ display_success(f"Results written to {output}")
858
+
859
+ else: # text format
860
+ # Display summary
861
+ from rich.table import Table
862
+
863
+ table = Table(title="Batch Scan Results", show_header=True, header_style="bold cyan")
864
+ table.add_column("Line", justify="right", style="cyan", no_wrap=True)
865
+ table.add_column("Prompt", style="white")
866
+ table.add_column("Status", style="bold", no_wrap=True)
867
+ table.add_column("Detections", justify="right", no_wrap=True)
868
+ table.add_column("Time", justify="right", no_wrap=True)
869
+
870
+ for result in results:
871
+ if result["has_threats"]:
872
+ status = "[red]THREAT[/red]"
873
+ else:
874
+ status = "[green]SAFE[/green]"
875
+
876
+ table.add_row(
877
+ str(result["line"]),
878
+ result["prompt"],
879
+ status,
880
+ str(result["detection_count"]),
881
+ f"{result['duration_ms']:.1f}ms",
882
+ )
883
+
884
+ console.print(table)
885
+ console.print()
886
+
887
+ # Summary
888
+ console.print("[bold]Summary[/bold]")
889
+ console.print(f" Total scanned: {len(results)}")
890
+ console.print(f" Threats found: {threats_found}")
891
+ console.print(f" Clean scans: {len(results) - threats_found}")
892
+
893
+ if critical_found:
894
+ console.print(" [red bold]Critical threats detected![/red bold]")
895
+
896
+ console.print()
897
+
898
+ # Auto-flush telemetry at end of batch scan
899
+ # Use generous timeout and batches for batch operations (many events)
900
+ # Each HTTP batch takes ~0.5-1s, so 1000 prompts needs ~40s+ for full flush
901
+ try:
902
+ from raxe.infrastructure.telemetry.flush_helper import ensure_telemetry_flushed
903
+
904
+ # Calculate appropriate timeout based on number of prompts
905
+ # ~0.05s per prompt accounts for HTTP latency, capped at 120s
906
+ timeout = min(5.0 + len(prompts) * 0.05, 120.0)
907
+ # Allow 2x batches to handle both critical and standard queues
908
+ # Each queue might have up to len(prompts) events
909
+ max_batches = max(20, (len(prompts) // 50 + 1) * 2)
910
+
911
+ ensure_telemetry_flushed(
912
+ timeout_seconds=timeout,
913
+ max_batches=max_batches,
914
+ end_session=True,
915
+ )
916
+ except Exception:
917
+ pass # Never let telemetry affect batch completion
918
+
919
+
920
+ @cli.group()
921
+ def pack():
922
+ """Manage rule packs."""
923
+ pass
924
+
925
+
926
+ @pack.command("list")
927
+ def pack_list():
928
+ """List installed rule packs."""
929
+ raxe = Raxe()
930
+
931
+ click.echo("Installed packs:")
932
+ click.echo()
933
+
934
+ # Get packs from registry
935
+ stats = raxe.stats
936
+ click.echo(f" Rules loaded: {stats['rules_loaded']}")
937
+ click.echo(f" Packs loaded: {stats['packs_loaded']}")
938
+ click.echo()
939
+ click.echo("Use 'raxe pack info <pack-id>' for details")
940
+
941
+
942
+ @pack.command("info")
943
+ @click.argument("pack_id")
944
+ def pack_info(pack_id: str):
945
+ """Show information about a specific pack."""
946
+ click.echo(f"Pack: {pack_id}")
947
+ click.echo(" (Full pack info coming in next sprint)")
948
+
949
+
950
+ @cli.command()
951
+ @handle_cli_error
952
+ def plugins():
953
+ """List installed plugins.
954
+
955
+ Shows all discovered plugins with their status (loaded or failed).
956
+ """
957
+ from raxe.plugins import PluginLoader
958
+
959
+ loader = PluginLoader()
960
+ discovered = loader.discover_plugins()
961
+
962
+ if not discovered:
963
+ console.print("[yellow]No plugins found[/yellow]")
964
+ console.print()
965
+ console.print(f"Install plugins to: {loader.plugin_paths}")
966
+ console.print("See: https://docs.raxe.ai/plugins for more info")
967
+ return
968
+
969
+ # Create table
970
+ from rich.table import Table
971
+
972
+ table = Table(title="Installed Plugins")
973
+ table.add_column("Name", style="cyan", no_wrap=True)
974
+ table.add_column("Path", style="blue")
975
+ table.add_column("Status", style="green")
976
+
977
+ for plugin_info in discovered:
978
+ # Determine status
979
+ if plugin_info.name in loader.loaded_plugins:
980
+ status = "[green]✓ Loaded[/green]"
981
+ elif plugin_info.name in loader.failed_plugins:
982
+ error = loader.failed_plugins[plugin_info.name]
983
+ status = f"[red]✗ Failed: {error}[/red]"
984
+ else:
985
+ status = "[yellow]○ Not Enabled[/yellow]"
986
+
987
+ table.add_row(
988
+ plugin_info.name,
989
+ str(plugin_info.path),
990
+ status
991
+ )
992
+
993
+ console.print(table)
994
+ console.print()
995
+ console.print(f"Total: {len(discovered)} plugins discovered")
996
+ console.print(f"Loaded: {len(loader.loaded_plugins)}")
997
+ console.print(f"Failed: {len(loader.failed_plugins)}")
998
+ console.print()
999
+ console.print("Enable plugins in ~/.raxe/config.yaml under plugins.enabled")
1000
+
1001
+
1002
+ # Note: profile_cmd removed - use 'raxe profile' command instead
1003
+ # Note: metrics_server removed - functionality consolidated into monitoring module
1004
+
1005
+
1006
+ @cli.command("completion")
1007
+ @click.argument(
1008
+ "shell",
1009
+ type=click.Choice(["bash", "zsh", "fish", "powershell"]),
1010
+ )
1011
+ def completion(shell: str):
1012
+ """
1013
+ Generate shell completion script.
1014
+
1015
+ \b
1016
+ Installation:
1017
+ # Bash
1018
+ raxe completion bash > /etc/bash_completion.d/raxe
1019
+
1020
+ # Zsh
1021
+ raxe completion zsh > ~/.zsh/completions/_raxe
1022
+
1023
+ # Fish
1024
+ raxe completion fish > ~/.config/fish/completions/raxe.fish
1025
+
1026
+ # PowerShell
1027
+ raxe completion powershell >> $PROFILE
1028
+ """
1029
+ if shell == "bash":
1030
+ script = """
1031
+ # RAXE bash completion
1032
+ _raxe_completion() {
1033
+ local cur prev opts
1034
+ COMPREPLY=()
1035
+ cur="${COMP_WORDS[COMP_CWORD]}"
1036
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
1037
+ opts="init setup scan batch test stats export repl rules doctor pack plugins privacy profile suppress telemetry tune validate-rule auth completion --help --version"
1038
+
1039
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
1040
+ return 0
1041
+ }
1042
+ complete -F _raxe_completion raxe
1043
+ """
1044
+ elif shell == "zsh":
1045
+ script = """
1046
+ #compdef raxe
1047
+ _raxe() {
1048
+ local -a commands
1049
+ commands=(
1050
+ 'init:Initialize RAXE configuration'
1051
+ 'setup:Interactive setup wizard'
1052
+ 'scan:Scan text for threats'
1053
+ 'batch:Batch scan prompts from file'
1054
+ 'test:Test configuration and connectivity'
1055
+ 'stats:Show local statistics'
1056
+ 'export:Export scan history'
1057
+ 'repl:Interactive shell'
1058
+ 'rules:Manage and inspect detection rules'
1059
+ 'doctor:Run system health checks'
1060
+ 'pack:Manage rule packs'
1061
+ 'plugins:List installed plugins'
1062
+ 'privacy:Show privacy guarantees'
1063
+ 'profile:Profile scan performance'
1064
+ 'suppress:Manage false positive suppressions'
1065
+ 'telemetry:Manage telemetry settings'
1066
+ 'tune:Tune detection parameters'
1067
+ 'validate-rule:Validate a rule file'
1068
+ 'auth:Manage authentication and API keys'
1069
+ 'completion:Generate shell completion'
1070
+ )
1071
+ _describe 'command' commands
1072
+ }
1073
+ _raxe
1074
+ """
1075
+ elif shell == "fish":
1076
+ script = """
1077
+ # RAXE fish completion
1078
+ complete -c raxe -f -a "init setup scan batch test stats export repl rules doctor pack plugins privacy profile suppress telemetry tune validate-rule auth completion"
1079
+ complete -c raxe -f -a "init" -d "Initialize RAXE configuration"
1080
+ complete -c raxe -f -a "setup" -d "Interactive setup wizard"
1081
+ complete -c raxe -f -a "scan" -d "Scan text for threats"
1082
+ complete -c raxe -f -a "batch" -d "Batch scan prompts from file"
1083
+ complete -c raxe -f -a "test" -d "Test configuration"
1084
+ complete -c raxe -f -a "stats" -d "Show statistics"
1085
+ complete -c raxe -f -a "export" -d "Export scan history"
1086
+ complete -c raxe -f -a "repl" -d "Interactive shell"
1087
+ complete -c raxe -f -a "rules" -d "Manage detection rules"
1088
+ complete -c raxe -f -a "doctor" -d "Run health checks"
1089
+ complete -c raxe -f -a "pack" -d "Manage rule packs"
1090
+ complete -c raxe -f -a "plugins" -d "List installed plugins"
1091
+ complete -c raxe -f -a "privacy" -d "Show privacy guarantees"
1092
+ complete -c raxe -f -a "profile" -d "Profile scan performance"
1093
+ complete -c raxe -f -a "suppress" -d "Manage suppressions"
1094
+ complete -c raxe -f -a "telemetry" -d "Manage telemetry settings"
1095
+ complete -c raxe -f -a "tune" -d "Tune detection parameters"
1096
+ complete -c raxe -f -a "validate-rule" -d "Validate a rule file"
1097
+ complete -c raxe -f -a "auth" -d "Manage authentication and API keys"
1098
+ """
1099
+ elif shell == "powershell":
1100
+ script = """
1101
+ # RAXE PowerShell completion
1102
+ Register-ArgumentCompleter -Native -CommandName raxe -ScriptBlock {
1103
+ param($wordToComplete, $commandAst, $cursorPosition)
1104
+ $commands = @('init', 'setup', 'scan', 'batch', 'test', 'stats', 'export', 'repl', 'rules', 'doctor', 'pack', 'plugins', 'privacy', 'profile', 'suppress', 'telemetry', 'tune', 'validate-rule', 'auth', 'completion')
1105
+ $commands | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
1106
+ [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
1107
+ }
1108
+ }
1109
+ """
1110
+ click.echo(script)
1111
+
1112
+
1113
+ # Register new commands
1114
+ cli.add_command(auth)
1115
+ cli.add_command(test)
1116
+ cli.add_command(stats)
1117
+ cli.add_command(export)
1118
+ cli.add_command(repl)
1119
+ cli.add_command(rules)
1120
+ cli.add_command(doctor)
1121
+ cli.add_command(models)
1122
+ cli.add_command(profile_command)
1123
+ cli.add_command(privacy_command)
1124
+ cli.add_command(suppress)
1125
+ cli.add_command(tune)
1126
+ cli.add_command(validate_rule_command)
1127
+ cli.add_command(config)
1128
+ cli.add_command(event)
1129
+ cli.add_command(history)
1130
+ cli.add_command(telemetry)
1131
+
1132
+ # Top-level alias for 'raxe link ABC123' (same as 'raxe auth link ABC123')
1133
+ cli.add_command(auth_link, name="link")
1134
+
1135
+
1136
+ if __name__ == "__main__":
1137
+ cli()