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
|
@@ -0,0 +1,776 @@
|
|
|
1
|
+
"""Timer-based flush scheduler for dual queues.
|
|
2
|
+
|
|
3
|
+
This module implements a timer-based scheduler for flushing telemetry events
|
|
4
|
+
from dual priority queues. It manages two independent timers:
|
|
5
|
+
- Critical queue timer (5s default) for high-priority threat events
|
|
6
|
+
- Standard queue timer (5m default) for batched clean scan events
|
|
7
|
+
|
|
8
|
+
The scheduler supports:
|
|
9
|
+
- Graceful shutdown with timeout
|
|
10
|
+
- Thread-safe operations
|
|
11
|
+
- Comprehensive statistics tracking
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import atexit
|
|
17
|
+
import signal
|
|
18
|
+
import threading
|
|
19
|
+
import time
|
|
20
|
+
from dataclasses import dataclass
|
|
21
|
+
from datetime import datetime, timezone
|
|
22
|
+
from typing import Any, Protocol
|
|
23
|
+
|
|
24
|
+
from raxe.utils.logging import get_logger
|
|
25
|
+
|
|
26
|
+
logger = get_logger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class DualQueueProtocol(Protocol):
|
|
30
|
+
"""Protocol for dual queue implementations.
|
|
31
|
+
|
|
32
|
+
This protocol defines the interface that queue implementations must provide
|
|
33
|
+
to work with the FlushScheduler.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def dequeue_critical_batch(self, batch_size: int) -> list[dict[str, Any]]:
|
|
37
|
+
"""Dequeue a batch of critical (threat) events.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
batch_size: Maximum number of events to dequeue
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
List of event payloads
|
|
44
|
+
"""
|
|
45
|
+
...
|
|
46
|
+
|
|
47
|
+
def dequeue_standard_batch(self, batch_size: int) -> list[dict[str, Any]]:
|
|
48
|
+
"""Dequeue a batch of standard (clean) events.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
batch_size: Maximum number of events to dequeue
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
List of event payloads
|
|
55
|
+
"""
|
|
56
|
+
...
|
|
57
|
+
|
|
58
|
+
def get_critical_count(self) -> int:
|
|
59
|
+
"""Get count of events in critical queue."""
|
|
60
|
+
...
|
|
61
|
+
|
|
62
|
+
def get_standard_count(self) -> int:
|
|
63
|
+
"""Get count of events in standard queue."""
|
|
64
|
+
...
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class TelemetryShipperProtocol(Protocol):
|
|
68
|
+
"""Protocol for telemetry shipper implementations.
|
|
69
|
+
|
|
70
|
+
This defines the interface for sending batches of events to the
|
|
71
|
+
telemetry backend.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
def ship_batch(self, events: list[dict[str, Any]]) -> dict[str, Any]:
|
|
75
|
+
"""Ship a batch of events to the telemetry backend.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
events: List of event payloads to ship
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
Response dictionary with status and metadata
|
|
82
|
+
"""
|
|
83
|
+
...
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@dataclass
|
|
87
|
+
class FlushConfig:
|
|
88
|
+
"""Flush scheduler configuration.
|
|
89
|
+
|
|
90
|
+
Attributes:
|
|
91
|
+
critical_interval_seconds: Interval between critical queue flushes
|
|
92
|
+
standard_interval_seconds: Interval between standard queue flushes
|
|
93
|
+
max_batch_size: Maximum events per batch
|
|
94
|
+
shutdown_timeout_seconds: Timeout for graceful shutdown
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
critical_interval_seconds: float = 5.0
|
|
98
|
+
standard_interval_seconds: float = 300.0 # 5 minutes
|
|
99
|
+
max_batch_size: int = 100
|
|
100
|
+
shutdown_timeout_seconds: float = 10.0
|
|
101
|
+
|
|
102
|
+
@classmethod
|
|
103
|
+
def for_production(cls) -> FlushConfig:
|
|
104
|
+
"""Production mode with standard intervals.
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
FlushConfig configured for production
|
|
108
|
+
"""
|
|
109
|
+
return cls(
|
|
110
|
+
critical_interval_seconds=5.0,
|
|
111
|
+
standard_interval_seconds=300.0,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class SQLiteDualQueueAdapter:
|
|
116
|
+
"""Adapter to make DualQueue (SQLite-based) work with FlushScheduler.
|
|
117
|
+
|
|
118
|
+
This adapter wraps the SQLite-based DualQueue to provide the
|
|
119
|
+
DualQueueProtocol interface expected by FlushScheduler.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
def __init__(self, queue: Any) -> None:
|
|
123
|
+
"""Initialize the adapter.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
queue: The DualQueue instance to wrap
|
|
127
|
+
"""
|
|
128
|
+
self._queue = queue
|
|
129
|
+
self._pending_event_ids: list[str] = []
|
|
130
|
+
|
|
131
|
+
def dequeue_critical_batch(self, batch_size: int) -> list[dict[str, Any]]:
|
|
132
|
+
"""Dequeue a batch of critical (threat) events.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
batch_size: Maximum number of events to dequeue
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
List of event payloads
|
|
139
|
+
"""
|
|
140
|
+
events = self._queue.dequeue_critical(batch_size)
|
|
141
|
+
# Store event IDs for marking as sent later
|
|
142
|
+
self._pending_event_ids = [e["event_id"] for e in events]
|
|
143
|
+
return events
|
|
144
|
+
|
|
145
|
+
def dequeue_standard_batch(self, batch_size: int) -> list[dict[str, Any]]:
|
|
146
|
+
"""Dequeue a batch of standard (clean) events.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
batch_size: Maximum number of events to dequeue
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
List of event payloads
|
|
153
|
+
"""
|
|
154
|
+
events = self._queue.dequeue_standard(batch_size)
|
|
155
|
+
# Store event IDs for marking as sent later
|
|
156
|
+
self._pending_event_ids = [e["event_id"] for e in events]
|
|
157
|
+
return events
|
|
158
|
+
|
|
159
|
+
def get_critical_count(self) -> int:
|
|
160
|
+
"""Get count of events in critical queue."""
|
|
161
|
+
stats = self._queue.get_stats()
|
|
162
|
+
return stats.get("critical_count", 0)
|
|
163
|
+
|
|
164
|
+
def get_standard_count(self) -> int:
|
|
165
|
+
"""Get count of events in standard queue."""
|
|
166
|
+
stats = self._queue.get_stats()
|
|
167
|
+
return stats.get("standard_count", 0)
|
|
168
|
+
|
|
169
|
+
def mark_sent(self) -> None:
|
|
170
|
+
"""Mark pending events as successfully sent."""
|
|
171
|
+
if self._pending_event_ids:
|
|
172
|
+
self._queue.mark_batch_sent(self._pending_event_ids)
|
|
173
|
+
self._pending_event_ids = []
|
|
174
|
+
|
|
175
|
+
def mark_failed(self, error: str, retry_delay_seconds: int = 60) -> None:
|
|
176
|
+
"""Mark pending events as failed."""
|
|
177
|
+
if self._pending_event_ids:
|
|
178
|
+
self._queue.mark_batch_failed(
|
|
179
|
+
self._pending_event_ids, error, retry_delay_seconds
|
|
180
|
+
)
|
|
181
|
+
self._pending_event_ids = []
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class HttpShipper:
|
|
185
|
+
"""HTTP shipper that uses BatchSender for telemetry transmission.
|
|
186
|
+
|
|
187
|
+
This implements TelemetryShipperProtocol and wraps BatchSender to
|
|
188
|
+
provide actual HTTP shipping capability for FlushScheduler.
|
|
189
|
+
"""
|
|
190
|
+
|
|
191
|
+
def __init__(
|
|
192
|
+
self,
|
|
193
|
+
endpoint: str,
|
|
194
|
+
api_key: str | None = None,
|
|
195
|
+
installation_id: str | None = None,
|
|
196
|
+
queue_adapter: SQLiteDualQueueAdapter | None = None,
|
|
197
|
+
api_key_id: str | None = None,
|
|
198
|
+
) -> None:
|
|
199
|
+
"""Initialize the HTTP shipper.
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
endpoint: Telemetry endpoint URL
|
|
203
|
+
api_key: API key for authentication
|
|
204
|
+
installation_id: Installation ID for batch envelope
|
|
205
|
+
queue_adapter: Optional queue adapter for marking events sent/failed
|
|
206
|
+
api_key_id: Pre-computed key ID for batch envelope (optional).
|
|
207
|
+
If not provided, will be computed from api_key when sending.
|
|
208
|
+
"""
|
|
209
|
+
from raxe.infrastructure.telemetry.sender import BatchSender, CircuitBreaker
|
|
210
|
+
|
|
211
|
+
self._endpoint = endpoint
|
|
212
|
+
self._api_key = api_key
|
|
213
|
+
self._installation_id = installation_id or "inst_unknown"
|
|
214
|
+
self._queue_adapter = queue_adapter
|
|
215
|
+
self._api_key_id = api_key_id
|
|
216
|
+
|
|
217
|
+
self._sender = BatchSender(
|
|
218
|
+
endpoint=endpoint,
|
|
219
|
+
api_key=api_key,
|
|
220
|
+
installation_id=installation_id,
|
|
221
|
+
circuit_breaker=CircuitBreaker(),
|
|
222
|
+
api_key_id=api_key_id,
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
self._stats = {
|
|
226
|
+
"batches_sent": 0,
|
|
227
|
+
"events_sent": 0,
|
|
228
|
+
"errors": 0,
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
def ship_batch(self, events: list[dict[str, Any]], no_retry: bool = False) -> dict[str, Any]:
|
|
232
|
+
"""Ship a batch of events to the telemetry backend.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
events: List of event payloads to ship
|
|
236
|
+
no_retry: If True, skip retries (useful for shutdown scenarios)
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
Response dictionary with status and metadata
|
|
240
|
+
"""
|
|
241
|
+
if not events:
|
|
242
|
+
return {"success": True, "events_accepted": 0}
|
|
243
|
+
|
|
244
|
+
try:
|
|
245
|
+
response = self._sender.send_batch(events, no_retry=no_retry)
|
|
246
|
+
|
|
247
|
+
self._stats["batches_sent"] += 1
|
|
248
|
+
self._stats["events_sent"] += len(events)
|
|
249
|
+
|
|
250
|
+
# Mark events as sent in the queue
|
|
251
|
+
if self._queue_adapter:
|
|
252
|
+
self._queue_adapter.mark_sent()
|
|
253
|
+
|
|
254
|
+
logger.info(
|
|
255
|
+
"http_shipper_batch_sent",
|
|
256
|
+
event_count=len(events),
|
|
257
|
+
total_sent=self._stats["events_sent"],
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
return {
|
|
261
|
+
"success": True,
|
|
262
|
+
"events_accepted": len(events),
|
|
263
|
+
"response": response,
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
except Exception as e:
|
|
267
|
+
self._stats["errors"] += 1
|
|
268
|
+
|
|
269
|
+
# Mark events as failed in the queue
|
|
270
|
+
if self._queue_adapter:
|
|
271
|
+
self._queue_adapter.mark_failed(str(e))
|
|
272
|
+
|
|
273
|
+
logger.error(
|
|
274
|
+
"http_shipper_batch_failed",
|
|
275
|
+
event_count=len(events),
|
|
276
|
+
error=str(e),
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
return {
|
|
280
|
+
"success": False,
|
|
281
|
+
"events_accepted": 0,
|
|
282
|
+
"error": str(e),
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
def update_credentials(
|
|
286
|
+
self,
|
|
287
|
+
api_key: str | None = None,
|
|
288
|
+
installation_id: str | None = None,
|
|
289
|
+
api_key_id: str | None = None,
|
|
290
|
+
) -> None:
|
|
291
|
+
"""Update API key, installation_id, and api_key_id (for credential rotation).
|
|
292
|
+
|
|
293
|
+
Args:
|
|
294
|
+
api_key: New API key
|
|
295
|
+
installation_id: New installation ID
|
|
296
|
+
api_key_id: New pre-computed key ID
|
|
297
|
+
"""
|
|
298
|
+
if api_key is not None:
|
|
299
|
+
self._api_key = api_key
|
|
300
|
+
self._sender.api_key = api_key
|
|
301
|
+
if installation_id is not None:
|
|
302
|
+
self._installation_id = installation_id
|
|
303
|
+
self._sender.installation_id = installation_id
|
|
304
|
+
if api_key_id is not None:
|
|
305
|
+
self._api_key_id = api_key_id
|
|
306
|
+
self._sender.api_key_id = api_key_id
|
|
307
|
+
|
|
308
|
+
def get_stats(self) -> dict[str, Any]:
|
|
309
|
+
"""Get shipper statistics.
|
|
310
|
+
|
|
311
|
+
Returns:
|
|
312
|
+
Dictionary with shipping statistics
|
|
313
|
+
"""
|
|
314
|
+
return {
|
|
315
|
+
**self._stats,
|
|
316
|
+
"circuit_state": self._sender.get_circuit_state(),
|
|
317
|
+
"endpoint": self._endpoint,
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
@dataclass
|
|
322
|
+
class FlushStats:
|
|
323
|
+
"""Statistics for flush operations.
|
|
324
|
+
|
|
325
|
+
Attributes:
|
|
326
|
+
critical_flushes: Number of critical queue flush operations
|
|
327
|
+
standard_flushes: Number of standard queue flush operations
|
|
328
|
+
events_shipped: Total events shipped across all flushes
|
|
329
|
+
errors: Number of errors encountered
|
|
330
|
+
last_critical_flush: Timestamp of last critical flush
|
|
331
|
+
last_standard_flush: Timestamp of last standard flush
|
|
332
|
+
"""
|
|
333
|
+
|
|
334
|
+
critical_flushes: int = 0
|
|
335
|
+
standard_flushes: int = 0
|
|
336
|
+
events_shipped: int = 0
|
|
337
|
+
errors: int = 0
|
|
338
|
+
last_critical_flush: datetime | None = None
|
|
339
|
+
last_standard_flush: datetime | None = None
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
class FlushScheduler:
|
|
343
|
+
"""Timer-based flush scheduler for dual queues.
|
|
344
|
+
|
|
345
|
+
Runs two independent timers:
|
|
346
|
+
- Critical queue timer (5s default) for high-priority threat events
|
|
347
|
+
- Standard queue timer (5m default) for batched clean scan events
|
|
348
|
+
|
|
349
|
+
The scheduler supports graceful shutdown and comprehensive statistics tracking.
|
|
350
|
+
|
|
351
|
+
Example:
|
|
352
|
+
>>> from raxe.infrastructure.telemetry.flush_scheduler import (
|
|
353
|
+
... FlushScheduler, FlushConfig, HttpShipper
|
|
354
|
+
... )
|
|
355
|
+
>>> config = FlushConfig.for_production()
|
|
356
|
+
>>> shipper = HttpShipper(endpoint="https://...", api_key="...")
|
|
357
|
+
>>> scheduler = FlushScheduler(queue=my_queue, shipper=shipper, config=config)
|
|
358
|
+
>>> scheduler.start()
|
|
359
|
+
>>> # ... events are flushed automatically ...
|
|
360
|
+
>>> scheduler.stop(graceful=True)
|
|
361
|
+
"""
|
|
362
|
+
|
|
363
|
+
def __init__(
|
|
364
|
+
self,
|
|
365
|
+
queue: DualQueueProtocol,
|
|
366
|
+
shipper: TelemetryShipperProtocol,
|
|
367
|
+
config: FlushConfig | None = None,
|
|
368
|
+
) -> None:
|
|
369
|
+
"""Initialize the flush scheduler.
|
|
370
|
+
|
|
371
|
+
Args:
|
|
372
|
+
queue: Dual queue implementation (must implement DualQueueProtocol)
|
|
373
|
+
shipper: Telemetry shipper (must implement TelemetryShipperProtocol)
|
|
374
|
+
config: Flush configuration (uses defaults if None)
|
|
375
|
+
"""
|
|
376
|
+
self._config = config or FlushConfig()
|
|
377
|
+
self._queue = queue
|
|
378
|
+
self._shipper = shipper
|
|
379
|
+
|
|
380
|
+
# State management
|
|
381
|
+
self._running = False
|
|
382
|
+
self._lock = threading.RLock()
|
|
383
|
+
self._stop_event = threading.Event()
|
|
384
|
+
|
|
385
|
+
# Timers
|
|
386
|
+
self._critical_timer: threading.Timer | None = None
|
|
387
|
+
self._standard_timer: threading.Timer | None = None
|
|
388
|
+
|
|
389
|
+
# Statistics
|
|
390
|
+
self._stats = FlushStats()
|
|
391
|
+
|
|
392
|
+
# Session tracking (for session_end events)
|
|
393
|
+
self._session_start: datetime | None = None
|
|
394
|
+
self._session_id: str | None = None
|
|
395
|
+
|
|
396
|
+
# Register shutdown handlers
|
|
397
|
+
self._register_shutdown_handlers()
|
|
398
|
+
|
|
399
|
+
def _register_shutdown_handlers(self) -> None:
|
|
400
|
+
"""Register atexit and signal handlers for graceful shutdown."""
|
|
401
|
+
# atexit handler for normal program termination
|
|
402
|
+
atexit.register(self._atexit_handler)
|
|
403
|
+
|
|
404
|
+
# Signal handlers for SIGTERM/SIGINT (if running in main thread)
|
|
405
|
+
try:
|
|
406
|
+
if threading.current_thread() is threading.main_thread():
|
|
407
|
+
# Store original handlers to chain
|
|
408
|
+
self._original_sigterm = signal.signal(
|
|
409
|
+
signal.SIGTERM, self._signal_handler
|
|
410
|
+
)
|
|
411
|
+
self._original_sigint = signal.signal(
|
|
412
|
+
signal.SIGINT, self._signal_handler
|
|
413
|
+
)
|
|
414
|
+
except ValueError:
|
|
415
|
+
# Can't set signal handlers in non-main thread
|
|
416
|
+
logger.debug("flush_scheduler_signal_handlers_skipped", reason="not_main_thread")
|
|
417
|
+
|
|
418
|
+
def _atexit_handler(self) -> None:
|
|
419
|
+
"""Handler called on program exit."""
|
|
420
|
+
if self._running:
|
|
421
|
+
logger.info("flush_scheduler_atexit_triggered")
|
|
422
|
+
self.stop(graceful=True)
|
|
423
|
+
|
|
424
|
+
def _signal_handler(self, signum: int, frame: Any) -> None:
|
|
425
|
+
"""Handler for SIGTERM/SIGINT signals.
|
|
426
|
+
|
|
427
|
+
Args:
|
|
428
|
+
signum: Signal number
|
|
429
|
+
frame: Current stack frame
|
|
430
|
+
"""
|
|
431
|
+
logger.info(
|
|
432
|
+
"flush_scheduler_signal_received",
|
|
433
|
+
signal=signal.Signals(signum).name,
|
|
434
|
+
)
|
|
435
|
+
self.stop(graceful=True)
|
|
436
|
+
|
|
437
|
+
# Chain to original handler
|
|
438
|
+
handler_attr = "_original_sigterm" if signum == signal.SIGTERM else "_original_sigint"
|
|
439
|
+
original_handler = getattr(self, handler_attr, None)
|
|
440
|
+
if original_handler and callable(original_handler):
|
|
441
|
+
original_handler(signum, frame)
|
|
442
|
+
|
|
443
|
+
def start(self) -> None:
|
|
444
|
+
"""Start background flush timers.
|
|
445
|
+
|
|
446
|
+
Starts two independent timer threads for critical and standard queues.
|
|
447
|
+
Safe to call multiple times - subsequent calls are no-ops if already running.
|
|
448
|
+
"""
|
|
449
|
+
with self._lock:
|
|
450
|
+
if self._running:
|
|
451
|
+
logger.warning("flush_scheduler_already_running")
|
|
452
|
+
return
|
|
453
|
+
|
|
454
|
+
self._running = True
|
|
455
|
+
self._stop_event.clear()
|
|
456
|
+
self._session_start = datetime.now(timezone.utc)
|
|
457
|
+
|
|
458
|
+
# Start timers
|
|
459
|
+
self._schedule_critical_flush()
|
|
460
|
+
self._schedule_standard_flush()
|
|
461
|
+
|
|
462
|
+
logger.info(
|
|
463
|
+
"flush_scheduler_started",
|
|
464
|
+
critical_interval=self._config.critical_interval_seconds,
|
|
465
|
+
standard_interval=self._config.standard_interval_seconds,
|
|
466
|
+
max_batch_size=self._config.max_batch_size,
|
|
467
|
+
)
|
|
468
|
+
|
|
469
|
+
def stop(self, graceful: bool = True) -> None:
|
|
470
|
+
"""Stop scheduler.
|
|
471
|
+
|
|
472
|
+
Args:
|
|
473
|
+
graceful: If True, flush pending events before stopping
|
|
474
|
+
"""
|
|
475
|
+
with self._lock:
|
|
476
|
+
if not self._running:
|
|
477
|
+
return
|
|
478
|
+
|
|
479
|
+
logger.info(
|
|
480
|
+
"flush_scheduler_stopping",
|
|
481
|
+
graceful=graceful,
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
self._running = False
|
|
485
|
+
self._stop_event.set()
|
|
486
|
+
|
|
487
|
+
# Cancel timers
|
|
488
|
+
if self._critical_timer:
|
|
489
|
+
self._critical_timer.cancel()
|
|
490
|
+
self._critical_timer = None
|
|
491
|
+
if self._standard_timer:
|
|
492
|
+
self._standard_timer.cancel()
|
|
493
|
+
self._standard_timer = None
|
|
494
|
+
|
|
495
|
+
# Flush remaining events if graceful shutdown
|
|
496
|
+
if graceful:
|
|
497
|
+
self._graceful_shutdown()
|
|
498
|
+
|
|
499
|
+
logger.info(
|
|
500
|
+
"flush_scheduler_stopped",
|
|
501
|
+
critical_flushes=self._stats.critical_flushes,
|
|
502
|
+
standard_flushes=self._stats.standard_flushes,
|
|
503
|
+
events_shipped=self._stats.events_shipped,
|
|
504
|
+
errors=self._stats.errors,
|
|
505
|
+
)
|
|
506
|
+
|
|
507
|
+
def _graceful_shutdown(self) -> None:
|
|
508
|
+
"""Perform graceful shutdown - NON-BLOCKING.
|
|
509
|
+
|
|
510
|
+
Events remain in SQLite queue for delivery on next CLI run.
|
|
511
|
+
This ensures the CLI never hangs waiting for network operations.
|
|
512
|
+
"""
|
|
513
|
+
# Check remaining events in queues
|
|
514
|
+
try:
|
|
515
|
+
critical_remaining = self._queue.get_critical_count()
|
|
516
|
+
standard_remaining = self._queue.get_standard_count()
|
|
517
|
+
|
|
518
|
+
if critical_remaining > 0 or standard_remaining > 0:
|
|
519
|
+
logger.debug(
|
|
520
|
+
"flush_scheduler_shutdown_events_pending",
|
|
521
|
+
critical_remaining=critical_remaining,
|
|
522
|
+
standard_remaining=standard_remaining,
|
|
523
|
+
message="Events will be delivered on next CLI run",
|
|
524
|
+
)
|
|
525
|
+
else:
|
|
526
|
+
logger.debug("flush_scheduler_shutdown_queues_empty")
|
|
527
|
+
|
|
528
|
+
except Exception as e:
|
|
529
|
+
logger.debug(
|
|
530
|
+
"flush_scheduler_shutdown_check_error",
|
|
531
|
+
error=str(e),
|
|
532
|
+
)
|
|
533
|
+
|
|
534
|
+
def _schedule_critical_flush(self) -> None:
|
|
535
|
+
"""Schedule the next critical queue flush."""
|
|
536
|
+
if not self._running or self._stop_event.is_set():
|
|
537
|
+
return
|
|
538
|
+
|
|
539
|
+
self._critical_timer = threading.Timer(
|
|
540
|
+
self._config.critical_interval_seconds,
|
|
541
|
+
self._critical_flush_callback,
|
|
542
|
+
)
|
|
543
|
+
self._critical_timer.daemon = True
|
|
544
|
+
self._critical_timer.name = "FlushScheduler-Critical"
|
|
545
|
+
self._critical_timer.start()
|
|
546
|
+
|
|
547
|
+
def _schedule_standard_flush(self) -> None:
|
|
548
|
+
"""Schedule the next standard queue flush."""
|
|
549
|
+
if not self._running or self._stop_event.is_set():
|
|
550
|
+
return
|
|
551
|
+
|
|
552
|
+
self._standard_timer = threading.Timer(
|
|
553
|
+
self._config.standard_interval_seconds,
|
|
554
|
+
self._standard_flush_callback,
|
|
555
|
+
)
|
|
556
|
+
self._standard_timer.daemon = True
|
|
557
|
+
self._standard_timer.name = "FlushScheduler-Standard"
|
|
558
|
+
self._standard_timer.start()
|
|
559
|
+
|
|
560
|
+
def _critical_flush_callback(self) -> None:
|
|
561
|
+
"""Timer callback for critical queue flush."""
|
|
562
|
+
if not self._running:
|
|
563
|
+
return
|
|
564
|
+
|
|
565
|
+
try:
|
|
566
|
+
self.flush_critical()
|
|
567
|
+
except Exception as e:
|
|
568
|
+
logger.error(
|
|
569
|
+
"flush_scheduler_critical_callback_error",
|
|
570
|
+
error=str(e),
|
|
571
|
+
)
|
|
572
|
+
self._stats.errors += 1
|
|
573
|
+
finally:
|
|
574
|
+
# Reschedule
|
|
575
|
+
self._schedule_critical_flush()
|
|
576
|
+
|
|
577
|
+
def _standard_flush_callback(self) -> None:
|
|
578
|
+
"""Timer callback for standard queue flush."""
|
|
579
|
+
if not self._running:
|
|
580
|
+
return
|
|
581
|
+
|
|
582
|
+
try:
|
|
583
|
+
self.flush_standard()
|
|
584
|
+
except Exception as e:
|
|
585
|
+
logger.error(
|
|
586
|
+
"flush_scheduler_standard_callback_error",
|
|
587
|
+
error=str(e),
|
|
588
|
+
)
|
|
589
|
+
self._stats.errors += 1
|
|
590
|
+
finally:
|
|
591
|
+
# Reschedule
|
|
592
|
+
self._schedule_standard_flush()
|
|
593
|
+
|
|
594
|
+
def flush_critical(self, no_retry: bool = False) -> int:
|
|
595
|
+
"""Flush critical queue immediately.
|
|
596
|
+
|
|
597
|
+
Args:
|
|
598
|
+
no_retry: If True, skip retries (useful for shutdown scenarios)
|
|
599
|
+
|
|
600
|
+
Returns:
|
|
601
|
+
Number of events sent
|
|
602
|
+
"""
|
|
603
|
+
events = self._queue.dequeue_critical_batch(self._config.max_batch_size)
|
|
604
|
+
if not events:
|
|
605
|
+
return 0
|
|
606
|
+
|
|
607
|
+
events_sent = self._ship_batch(events, queue_type="critical", no_retry=no_retry)
|
|
608
|
+
|
|
609
|
+
with self._lock:
|
|
610
|
+
self._stats.critical_flushes += 1
|
|
611
|
+
self._stats.events_shipped += events_sent
|
|
612
|
+
self._stats.last_critical_flush = datetime.now(timezone.utc)
|
|
613
|
+
|
|
614
|
+
logger.info(
|
|
615
|
+
"flush_scheduler_critical_flushed",
|
|
616
|
+
events_sent=events_sent,
|
|
617
|
+
total_critical_flushes=self._stats.critical_flushes,
|
|
618
|
+
)
|
|
619
|
+
|
|
620
|
+
return events_sent
|
|
621
|
+
|
|
622
|
+
def flush_standard(self, no_retry: bool = False) -> int:
|
|
623
|
+
"""Flush standard queue immediately.
|
|
624
|
+
|
|
625
|
+
Args:
|
|
626
|
+
no_retry: If True, skip retries (useful for shutdown scenarios)
|
|
627
|
+
|
|
628
|
+
Returns:
|
|
629
|
+
Number of events sent
|
|
630
|
+
"""
|
|
631
|
+
events = self._queue.dequeue_standard_batch(self._config.max_batch_size)
|
|
632
|
+
if not events:
|
|
633
|
+
return 0
|
|
634
|
+
|
|
635
|
+
events_sent = self._ship_batch(events, queue_type="standard", no_retry=no_retry)
|
|
636
|
+
|
|
637
|
+
with self._lock:
|
|
638
|
+
self._stats.standard_flushes += 1
|
|
639
|
+
self._stats.events_shipped += events_sent
|
|
640
|
+
self._stats.last_standard_flush = datetime.now(timezone.utc)
|
|
641
|
+
|
|
642
|
+
logger.info(
|
|
643
|
+
"flush_scheduler_standard_flushed",
|
|
644
|
+
events_sent=events_sent,
|
|
645
|
+
total_standard_flushes=self._stats.standard_flushes,
|
|
646
|
+
)
|
|
647
|
+
|
|
648
|
+
return events_sent
|
|
649
|
+
|
|
650
|
+
def flush_all(self) -> int:
|
|
651
|
+
"""Flush both queues.
|
|
652
|
+
|
|
653
|
+
Returns:
|
|
654
|
+
Total events sent across both queues
|
|
655
|
+
"""
|
|
656
|
+
critical_count = self.flush_critical()
|
|
657
|
+
standard_count = self.flush_standard()
|
|
658
|
+
return critical_count + standard_count
|
|
659
|
+
|
|
660
|
+
def _ship_batch(self, events: list[dict[str, Any]], queue_type: str, no_retry: bool = False) -> int:
|
|
661
|
+
"""Ship a batch of events.
|
|
662
|
+
|
|
663
|
+
Args:
|
|
664
|
+
events: List of event payloads to ship
|
|
665
|
+
queue_type: Type of queue (critical/standard) for logging
|
|
666
|
+
no_retry: If True, skip retries (useful for shutdown scenarios)
|
|
667
|
+
|
|
668
|
+
Returns:
|
|
669
|
+
Number of events successfully shipped
|
|
670
|
+
"""
|
|
671
|
+
if not events:
|
|
672
|
+
return 0
|
|
673
|
+
|
|
674
|
+
try:
|
|
675
|
+
response = self._shipper.ship_batch(events, no_retry=no_retry)
|
|
676
|
+
|
|
677
|
+
# Check for success
|
|
678
|
+
if response.get("success", False):
|
|
679
|
+
events_accepted = response.get("events_accepted", len(events))
|
|
680
|
+
return int(events_accepted) if events_accepted is not None else len(events)
|
|
681
|
+
else:
|
|
682
|
+
logger.warning(
|
|
683
|
+
"flush_scheduler_ship_failed",
|
|
684
|
+
queue_type=queue_type,
|
|
685
|
+
event_count=len(events),
|
|
686
|
+
response=response,
|
|
687
|
+
)
|
|
688
|
+
self._stats.errors += 1
|
|
689
|
+
return 0
|
|
690
|
+
|
|
691
|
+
except Exception as e:
|
|
692
|
+
logger.error(
|
|
693
|
+
"flush_scheduler_ship_error",
|
|
694
|
+
queue_type=queue_type,
|
|
695
|
+
event_count=len(events),
|
|
696
|
+
error=str(e),
|
|
697
|
+
)
|
|
698
|
+
self._stats.errors += 1
|
|
699
|
+
return 0
|
|
700
|
+
|
|
701
|
+
def is_running(self) -> bool:
|
|
702
|
+
"""Check if scheduler is running.
|
|
703
|
+
|
|
704
|
+
Returns:
|
|
705
|
+
True if scheduler is running, False otherwise
|
|
706
|
+
"""
|
|
707
|
+
return self._running
|
|
708
|
+
|
|
709
|
+
def get_stats(self) -> dict[str, Any]:
|
|
710
|
+
"""Get flush statistics.
|
|
711
|
+
|
|
712
|
+
Returns:
|
|
713
|
+
Dictionary with scheduler statistics including:
|
|
714
|
+
- is_running: Whether scheduler is currently running
|
|
715
|
+
- critical_flushes: Count of critical queue flushes
|
|
716
|
+
- standard_flushes: Count of standard queue flushes
|
|
717
|
+
- events_shipped: Total events shipped
|
|
718
|
+
- errors: Error count
|
|
719
|
+
- last_critical_flush: Timestamp of last critical flush
|
|
720
|
+
- last_standard_flush: Timestamp of last standard flush
|
|
721
|
+
- queue_depths: Current queue depths
|
|
722
|
+
"""
|
|
723
|
+
with self._lock:
|
|
724
|
+
stats = {
|
|
725
|
+
"is_running": self._running,
|
|
726
|
+
"critical_flushes": self._stats.critical_flushes,
|
|
727
|
+
"standard_flushes": self._stats.standard_flushes,
|
|
728
|
+
"events_shipped": self._stats.events_shipped,
|
|
729
|
+
"errors": self._stats.errors,
|
|
730
|
+
"last_critical_flush": (
|
|
731
|
+
self._stats.last_critical_flush.isoformat()
|
|
732
|
+
if self._stats.last_critical_flush
|
|
733
|
+
else None
|
|
734
|
+
),
|
|
735
|
+
"last_standard_flush": (
|
|
736
|
+
self._stats.last_standard_flush.isoformat()
|
|
737
|
+
if self._stats.last_standard_flush
|
|
738
|
+
else None
|
|
739
|
+
),
|
|
740
|
+
"config": {
|
|
741
|
+
"critical_interval_seconds": self._config.critical_interval_seconds,
|
|
742
|
+
"standard_interval_seconds": self._config.standard_interval_seconds,
|
|
743
|
+
"max_batch_size": self._config.max_batch_size,
|
|
744
|
+
"shutdown_timeout_seconds": self._config.shutdown_timeout_seconds,
|
|
745
|
+
},
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
# Add queue depths if available
|
|
749
|
+
try:
|
|
750
|
+
stats["queue_depths"] = {
|
|
751
|
+
"critical": self._queue.get_critical_count(),
|
|
752
|
+
"standard": self._queue.get_standard_count(),
|
|
753
|
+
}
|
|
754
|
+
except Exception:
|
|
755
|
+
stats["queue_depths"] = {"critical": -1, "standard": -1}
|
|
756
|
+
|
|
757
|
+
return stats
|
|
758
|
+
|
|
759
|
+
def get_shipper(self) -> TelemetryShipperProtocol:
|
|
760
|
+
"""Get the shipper instance.
|
|
761
|
+
|
|
762
|
+
Returns:
|
|
763
|
+
The telemetry shipper instance
|
|
764
|
+
"""
|
|
765
|
+
return self._shipper
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
__all__ = [
|
|
769
|
+
"DualQueueProtocol",
|
|
770
|
+
"FlushConfig",
|
|
771
|
+
"FlushScheduler",
|
|
772
|
+
"FlushStats",
|
|
773
|
+
"HttpShipper",
|
|
774
|
+
"SQLiteDualQueueAdapter",
|
|
775
|
+
"TelemetryShipperProtocol",
|
|
776
|
+
]
|