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,444 @@
|
|
|
1
|
+
"""Achievement tracking and evaluation service.
|
|
2
|
+
|
|
3
|
+
Manages all achievement types and tracks user progress.
|
|
4
|
+
|
|
5
|
+
CRITICAL: This is application layer - orchestrates but doesn't calculate.
|
|
6
|
+
All calculations delegated to domain layer, all I/O to repository.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
from datetime import datetime, timezone
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from raxe.domain.analytics import (
|
|
14
|
+
ACHIEVEMENTS,
|
|
15
|
+
Achievement,
|
|
16
|
+
calculate_user_achievements,
|
|
17
|
+
check_achievement_unlocked,
|
|
18
|
+
find_next_achievements,
|
|
19
|
+
get_achievement_by_id,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
from .repositories import AnalyticsRepository
|
|
23
|
+
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class AchievementService:
|
|
28
|
+
"""Service for comprehensive achievement tracking.
|
|
29
|
+
|
|
30
|
+
This service orchestrates:
|
|
31
|
+
1. Data loading from repository (infrastructure)
|
|
32
|
+
2. Achievement evaluation (domain pure functions)
|
|
33
|
+
3. Achievement saving and notification
|
|
34
|
+
|
|
35
|
+
CRITICAL: This service does NOT perform calculations itself.
|
|
36
|
+
All business logic is delegated to domain layer functions.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(self, repository: AnalyticsRepository):
|
|
40
|
+
"""Initialize achievement service.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
repository: Repository for data access (dependency injection)
|
|
44
|
+
"""
|
|
45
|
+
self.repository = repository
|
|
46
|
+
self._streak_service = None # Can be set externally to avoid circular import
|
|
47
|
+
|
|
48
|
+
def set_streak_service(self, streak_service):
|
|
49
|
+
"""Set the streak service for streak-based achievements.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
streak_service: StreakService instance
|
|
53
|
+
"""
|
|
54
|
+
self._streak_service = streak_service
|
|
55
|
+
|
|
56
|
+
def evaluate_user_achievements(
|
|
57
|
+
self,
|
|
58
|
+
installation_id: str
|
|
59
|
+
) -> list[Achievement]:
|
|
60
|
+
"""Evaluate all potential achievements for a user.
|
|
61
|
+
|
|
62
|
+
This checks which achievements the user has earned and saves any
|
|
63
|
+
new achievements to the repository.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
installation_id: User's installation identifier
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
List of newly earned achievements
|
|
70
|
+
|
|
71
|
+
Example:
|
|
72
|
+
>>> service = AchievementService(repo)
|
|
73
|
+
>>> new_achievements = service.evaluate_user_achievements("abc123")
|
|
74
|
+
>>> for ach in new_achievements:
|
|
75
|
+
... print(f"Unlocked: {ach.name} (+{ach.points} points)")
|
|
76
|
+
"""
|
|
77
|
+
try:
|
|
78
|
+
# Step 1: Gather user activity data (I/O)
|
|
79
|
+
activity = self.repository.get_user_activity(installation_id)
|
|
80
|
+
|
|
81
|
+
if not activity:
|
|
82
|
+
logger.info(
|
|
83
|
+
f"No activity for achievement evaluation: {installation_id}"
|
|
84
|
+
)
|
|
85
|
+
return []
|
|
86
|
+
|
|
87
|
+
# Step 2: Get streak info if streak service available
|
|
88
|
+
from datetime import date
|
|
89
|
+
|
|
90
|
+
from raxe.domain.analytics import StreakMetrics
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
if self._streak_service:
|
|
94
|
+
streak_metrics = self._streak_service.get_user_streak(installation_id)
|
|
95
|
+
else:
|
|
96
|
+
# Fallback to zero streaks if service not available
|
|
97
|
+
streak_metrics = StreakMetrics(
|
|
98
|
+
installation_id=installation_id,
|
|
99
|
+
current_streak=0,
|
|
100
|
+
longest_streak=0,
|
|
101
|
+
total_scan_days=len(activity.scan_dates),
|
|
102
|
+
last_scan_date=date.today()
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Step 3: Calculate all unlocked achievements using domain (pure logic)
|
|
106
|
+
user_achievements = calculate_user_achievements(
|
|
107
|
+
installation_id=installation_id,
|
|
108
|
+
scan_count=activity.total_scans,
|
|
109
|
+
streak_metrics=streak_metrics
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# Step 4: Get existing achievements from repository (I/O)
|
|
113
|
+
existing = self.repository.get_achievements(installation_id)
|
|
114
|
+
existing_ids = {a['achievement_id'] for a in existing}
|
|
115
|
+
|
|
116
|
+
# Step 5: Filter to only new achievements
|
|
117
|
+
new_achievement_ids = [
|
|
118
|
+
ach_id for ach_id in user_achievements.unlocked_achievements
|
|
119
|
+
if ach_id not in existing_ids
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
new_achievements = []
|
|
123
|
+
for ach_id in new_achievement_ids:
|
|
124
|
+
achievement = get_achievement_by_id(ach_id)
|
|
125
|
+
if achievement:
|
|
126
|
+
new_achievements.append(achievement)
|
|
127
|
+
|
|
128
|
+
# Step 6: Save new achievements to repository (I/O)
|
|
129
|
+
for achievement in new_achievements:
|
|
130
|
+
self.repository.save_achievement(
|
|
131
|
+
installation_id=installation_id,
|
|
132
|
+
achievement_id=achievement.id,
|
|
133
|
+
earned_at=datetime.now(timezone.utc),
|
|
134
|
+
metadata={
|
|
135
|
+
'name': achievement.name,
|
|
136
|
+
'description': achievement.description,
|
|
137
|
+
'points': achievement.points,
|
|
138
|
+
'unlock_condition': achievement.unlock_condition,
|
|
139
|
+
'scan_count': activity.total_scans,
|
|
140
|
+
'streak_count': streak_metrics.longest_streak
|
|
141
|
+
}
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
logger.info(
|
|
145
|
+
f"Achievement unlocked: {installation_id} -> "
|
|
146
|
+
f"{achievement.name} (+{achievement.points} points)"
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
return new_achievements
|
|
150
|
+
|
|
151
|
+
except Exception as e:
|
|
152
|
+
logger.error(
|
|
153
|
+
f"Failed to evaluate achievements for {installation_id}: {e}"
|
|
154
|
+
)
|
|
155
|
+
raise
|
|
156
|
+
|
|
157
|
+
def get_user_achievement_summary(
|
|
158
|
+
self,
|
|
159
|
+
installation_id: str
|
|
160
|
+
) -> dict[str, Any]:
|
|
161
|
+
"""Get complete achievement summary for a user.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
installation_id: User's installation identifier
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
Dictionary with unlocked achievements, points, and next goals
|
|
168
|
+
|
|
169
|
+
Example:
|
|
170
|
+
>>> service = AchievementService(repo)
|
|
171
|
+
>>> summary = service.get_user_achievement_summary("abc123")
|
|
172
|
+
>>> print(f"Total points: {summary['total_points']}")
|
|
173
|
+
>>> print(f"Unlocked: {summary['unlocked_count']}/{summary['total_count']}")
|
|
174
|
+
"""
|
|
175
|
+
try:
|
|
176
|
+
# Step 1: Get user activity and calculate current state
|
|
177
|
+
activity = self.repository.get_user_activity(installation_id)
|
|
178
|
+
|
|
179
|
+
if not activity:
|
|
180
|
+
return {
|
|
181
|
+
"installation_id": installation_id,
|
|
182
|
+
"total_points": 0,
|
|
183
|
+
"unlocked_count": 0,
|
|
184
|
+
"total_count": len(ACHIEVEMENTS),
|
|
185
|
+
"unlocked_achievements": [],
|
|
186
|
+
"next_achievements": []
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
# Step 2: Get streak metrics
|
|
190
|
+
from datetime import date
|
|
191
|
+
|
|
192
|
+
from raxe.domain.analytics import StreakMetrics
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
if self._streak_service:
|
|
196
|
+
streak_metrics = self._streak_service.get_user_streak(installation_id)
|
|
197
|
+
else:
|
|
198
|
+
streak_metrics = StreakMetrics(
|
|
199
|
+
installation_id=installation_id,
|
|
200
|
+
current_streak=0,
|
|
201
|
+
longest_streak=0,
|
|
202
|
+
total_scan_days=len(activity.scan_dates),
|
|
203
|
+
last_scan_date=date.today()
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
# Step 3: Calculate user achievements using domain (pure logic)
|
|
207
|
+
user_achievements = calculate_user_achievements(
|
|
208
|
+
installation_id=installation_id,
|
|
209
|
+
scan_count=activity.total_scans,
|
|
210
|
+
streak_metrics=streak_metrics
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
# Step 4: Find next achievements to unlock (pure logic)
|
|
214
|
+
next_achievements = find_next_achievements(
|
|
215
|
+
user_achievements,
|
|
216
|
+
max_results=3
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
# Step 5: Build response
|
|
220
|
+
result = {
|
|
221
|
+
"installation_id": installation_id,
|
|
222
|
+
"total_points": user_achievements.total_points,
|
|
223
|
+
"unlocked_count": len(user_achievements.unlocked_achievements),
|
|
224
|
+
"total_count": len(ACHIEVEMENTS),
|
|
225
|
+
"unlocked_achievements": [
|
|
226
|
+
{
|
|
227
|
+
"id": ach_id,
|
|
228
|
+
"name": get_achievement_by_id(ach_id).name,
|
|
229
|
+
"points": get_achievement_by_id(ach_id).points
|
|
230
|
+
}
|
|
231
|
+
for ach_id in user_achievements.unlocked_achievements
|
|
232
|
+
if get_achievement_by_id(ach_id)
|
|
233
|
+
],
|
|
234
|
+
"next_achievements": [
|
|
235
|
+
{
|
|
236
|
+
"id": ach.id,
|
|
237
|
+
"name": ach.name,
|
|
238
|
+
"description": ach.description,
|
|
239
|
+
"points": ach.points,
|
|
240
|
+
"progress_needed": progress
|
|
241
|
+
}
|
|
242
|
+
for ach, progress in next_achievements
|
|
243
|
+
]
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
logger.info(
|
|
247
|
+
f"Achievement summary for {installation_id}: "
|
|
248
|
+
f"{result['unlocked_count']}/{result['total_count']} unlocked, "
|
|
249
|
+
f"{result['total_points']} points"
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
return result
|
|
253
|
+
|
|
254
|
+
except Exception as e:
|
|
255
|
+
logger.error(
|
|
256
|
+
f"Failed to get achievement summary for {installation_id}: {e}"
|
|
257
|
+
)
|
|
258
|
+
raise
|
|
259
|
+
|
|
260
|
+
def get_recent_unlocks(
|
|
261
|
+
self
|
|
262
|
+
) -> list[dict[str, Any]]:
|
|
263
|
+
"""Get recently unlocked achievements across all users.
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
List of recent achievement unlocks with user and timestamp
|
|
267
|
+
|
|
268
|
+
Example:
|
|
269
|
+
>>> service = AchievementService(repo)
|
|
270
|
+
>>> recent = service.get_recent_unlocks()
|
|
271
|
+
>>> for unlock in recent[:5]:
|
|
272
|
+
... print(f"{unlock['achievement_name']} - {unlock['earned_at']}")
|
|
273
|
+
"""
|
|
274
|
+
try:
|
|
275
|
+
# Note: This is a simplified implementation.
|
|
276
|
+
# For production, we'd want a dedicated query method in repository
|
|
277
|
+
# that can efficiently get recent unlocks across all users.
|
|
278
|
+
|
|
279
|
+
# For now, we'll return an empty list as this would require
|
|
280
|
+
# iterating through all users which is inefficient.
|
|
281
|
+
# This should be implemented as a repository method with proper indexing.
|
|
282
|
+
|
|
283
|
+
logger.warning(
|
|
284
|
+
"get_recent_unlocks is not yet implemented - "
|
|
285
|
+
"requires repository method with proper indexing"
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
return []
|
|
289
|
+
|
|
290
|
+
except Exception as e:
|
|
291
|
+
logger.error(f"Failed to get recent unlocks: {e}")
|
|
292
|
+
raise
|
|
293
|
+
|
|
294
|
+
def get_achievement_leaderboard(
|
|
295
|
+
self
|
|
296
|
+
) -> list[dict[str, Any]]:
|
|
297
|
+
"""Get top users by achievement points.
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
List of top users sorted by achievement points
|
|
301
|
+
|
|
302
|
+
Example:
|
|
303
|
+
>>> service = AchievementService(repo)
|
|
304
|
+
>>> leaderboard = service.get_achievement_leaderboard()
|
|
305
|
+
>>> for rank, user in enumerate(leaderboard, 1):
|
|
306
|
+
... print(f"{rank}. {user['installation_id']}: {user['points']} pts")
|
|
307
|
+
"""
|
|
308
|
+
try:
|
|
309
|
+
# Note: This is a simplified implementation.
|
|
310
|
+
# For production with millions of users, we'd want to cache
|
|
311
|
+
# achievement points or use materialized views.
|
|
312
|
+
|
|
313
|
+
# For now, we'll return an empty list as this would require
|
|
314
|
+
# calculating achievements for all users which is inefficient.
|
|
315
|
+
# This should be implemented with proper caching/indexing.
|
|
316
|
+
|
|
317
|
+
logger.warning(
|
|
318
|
+
"get_achievement_leaderboard is not yet implemented - "
|
|
319
|
+
"requires caching or materialized views for efficiency"
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
return []
|
|
323
|
+
|
|
324
|
+
except Exception as e:
|
|
325
|
+
logger.error(f"Failed to get achievement leaderboard: {e}")
|
|
326
|
+
raise
|
|
327
|
+
|
|
328
|
+
def get_achievement_progress(
|
|
329
|
+
self,
|
|
330
|
+
installation_id: str,
|
|
331
|
+
achievement_id: str
|
|
332
|
+
) -> dict[str, Any]:
|
|
333
|
+
"""Get user's progress toward a specific achievement.
|
|
334
|
+
|
|
335
|
+
Args:
|
|
336
|
+
installation_id: User's installation identifier
|
|
337
|
+
achievement_id: Achievement to check progress for
|
|
338
|
+
|
|
339
|
+
Returns:
|
|
340
|
+
Dictionary with achievement details and progress
|
|
341
|
+
|
|
342
|
+
Raises:
|
|
343
|
+
ValueError: If achievement_id is invalid
|
|
344
|
+
|
|
345
|
+
Example:
|
|
346
|
+
>>> service = AchievementService(repo)
|
|
347
|
+
>>> progress = service.get_achievement_progress("abc123", "power_user")
|
|
348
|
+
>>> print(f"Progress: {progress['current']}/{progress['required']}")
|
|
349
|
+
>>> print(f"Unlocked: {progress['unlocked']}")
|
|
350
|
+
"""
|
|
351
|
+
try:
|
|
352
|
+
# Step 1: Validate achievement exists
|
|
353
|
+
achievement = get_achievement_by_id(achievement_id)
|
|
354
|
+
if not achievement:
|
|
355
|
+
raise ValueError(f"Invalid achievement_id: {achievement_id}")
|
|
356
|
+
|
|
357
|
+
# Step 2: Get user activity
|
|
358
|
+
activity = self.repository.get_user_activity(installation_id)
|
|
359
|
+
|
|
360
|
+
if not activity:
|
|
361
|
+
return {
|
|
362
|
+
"achievement_id": achievement_id,
|
|
363
|
+
"achievement_name": achievement.name,
|
|
364
|
+
"unlocked": False,
|
|
365
|
+
"current": 0,
|
|
366
|
+
"required": self._extract_threshold(achievement.unlock_condition),
|
|
367
|
+
"progress_percentage": 0.0
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
# Step 3: Get streak metrics
|
|
371
|
+
from datetime import date
|
|
372
|
+
|
|
373
|
+
from raxe.domain.analytics import StreakMetrics
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
if self._streak_service:
|
|
377
|
+
streak_metrics = self._streak_service.get_user_streak(installation_id)
|
|
378
|
+
else:
|
|
379
|
+
streak_metrics = StreakMetrics(
|
|
380
|
+
installation_id=installation_id,
|
|
381
|
+
current_streak=0,
|
|
382
|
+
longest_streak=0,
|
|
383
|
+
total_scan_days=len(activity.scan_dates),
|
|
384
|
+
last_scan_date=date.today()
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
# Step 4: Check if achievement is unlocked (pure logic)
|
|
388
|
+
is_unlocked = check_achievement_unlocked(
|
|
389
|
+
achievement,
|
|
390
|
+
scan_count=activity.total_scans,
|
|
391
|
+
streak_count=streak_metrics.longest_streak
|
|
392
|
+
)
|
|
393
|
+
|
|
394
|
+
# Step 5: Calculate progress
|
|
395
|
+
required = self._extract_threshold(achievement.unlock_condition)
|
|
396
|
+
|
|
397
|
+
if "scan_count" in achievement.unlock_condition:
|
|
398
|
+
current = activity.total_scans
|
|
399
|
+
elif "streak_count" in achievement.unlock_condition:
|
|
400
|
+
current = streak_metrics.longest_streak
|
|
401
|
+
else:
|
|
402
|
+
current = 0
|
|
403
|
+
|
|
404
|
+
progress_percentage = min((current / required * 100), 100.0) if required > 0 else 0.0
|
|
405
|
+
|
|
406
|
+
result = {
|
|
407
|
+
"achievement_id": achievement_id,
|
|
408
|
+
"achievement_name": achievement.name,
|
|
409
|
+
"description": achievement.description,
|
|
410
|
+
"points": achievement.points,
|
|
411
|
+
"unlocked": is_unlocked,
|
|
412
|
+
"current": current,
|
|
413
|
+
"required": required,
|
|
414
|
+
"progress_percentage": round(progress_percentage, 1)
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
logger.info(
|
|
418
|
+
f"Achievement progress for {installation_id}/{achievement_id}: "
|
|
419
|
+
f"{current}/{required} ({progress_percentage:.1f}%)"
|
|
420
|
+
)
|
|
421
|
+
|
|
422
|
+
return result
|
|
423
|
+
|
|
424
|
+
except Exception as e:
|
|
425
|
+
logger.error(
|
|
426
|
+
f"Failed to get achievement progress for {installation_id}/{achievement_id}: {e}"
|
|
427
|
+
)
|
|
428
|
+
raise
|
|
429
|
+
|
|
430
|
+
def _extract_threshold(self, unlock_condition: str) -> int:
|
|
431
|
+
"""Extract numeric threshold from unlock condition string.
|
|
432
|
+
|
|
433
|
+
Args:
|
|
434
|
+
unlock_condition: Condition string (e.g., "scan_count >= 100")
|
|
435
|
+
|
|
436
|
+
Returns:
|
|
437
|
+
Numeric threshold value
|
|
438
|
+
"""
|
|
439
|
+
try:
|
|
440
|
+
if ">=" in unlock_condition:
|
|
441
|
+
return int(unlock_condition.split(">=")[1].strip())
|
|
442
|
+
return 0
|
|
443
|
+
except (ValueError, IndexError):
|
|
444
|
+
return 0
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"""Repository interfaces for analytics data access.
|
|
2
|
+
|
|
3
|
+
These are abstract interfaces that define contracts for data access.
|
|
4
|
+
Concrete implementations live in infrastructure layer.
|
|
5
|
+
|
|
6
|
+
CRITICAL: This defines the boundary between application and infrastructure.
|
|
7
|
+
Domain layer never imports this - only application layer uses repositories.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from abc import ABC, abstractmethod
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
from datetime import date, datetime
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class ScanEvent:
|
|
18
|
+
"""Scan event data for analytics.
|
|
19
|
+
|
|
20
|
+
This is a data transfer object (DTO) that represents a scan event
|
|
21
|
+
without coupling to infrastructure database models.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
installation_id: User's installation identifier
|
|
25
|
+
timestamp: When the scan occurred
|
|
26
|
+
event_type: Type of event (e.g., "scan_completed")
|
|
27
|
+
has_threats: Whether threats were detected
|
|
28
|
+
severity: Highest severity level detected (optional)
|
|
29
|
+
scan_duration_ms: Duration of scan in milliseconds (optional)
|
|
30
|
+
"""
|
|
31
|
+
installation_id: str
|
|
32
|
+
timestamp: datetime
|
|
33
|
+
event_type: str
|
|
34
|
+
has_threats: bool
|
|
35
|
+
severity: str | None = None
|
|
36
|
+
scan_duration_ms: float | None = None
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class UserActivity:
|
|
41
|
+
"""User activity data for analytics.
|
|
42
|
+
|
|
43
|
+
Aggregated user activity information needed for analytics calculations.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
installation_id: User's installation identifier
|
|
47
|
+
first_seen: First scan timestamp
|
|
48
|
+
last_seen: Most recent scan timestamp
|
|
49
|
+
total_scans: Total number of scans performed
|
|
50
|
+
total_threats: Total number of threats detected
|
|
51
|
+
scan_dates: List of unique dates with scan activity
|
|
52
|
+
"""
|
|
53
|
+
installation_id: str
|
|
54
|
+
first_seen: datetime
|
|
55
|
+
last_seen: datetime
|
|
56
|
+
total_scans: int
|
|
57
|
+
total_threats: int
|
|
58
|
+
scan_dates: list[date]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class AnalyticsRepository(ABC):
|
|
62
|
+
"""Abstract repository for analytics data access.
|
|
63
|
+
|
|
64
|
+
This interface defines the contract for all analytics data operations.
|
|
65
|
+
Concrete implementations (SQLite, Postgres, etc.) must implement all methods.
|
|
66
|
+
|
|
67
|
+
CRITICAL: This is the application/infrastructure boundary.
|
|
68
|
+
All I/O operations must go through repository implementations.
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
@abstractmethod
|
|
72
|
+
def get_scan_events(
|
|
73
|
+
self,
|
|
74
|
+
start_date: date,
|
|
75
|
+
end_date: date,
|
|
76
|
+
installation_id: str | None = None
|
|
77
|
+
) -> list[ScanEvent]:
|
|
78
|
+
"""Get scan events within date range.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
start_date: Start of date range (inclusive)
|
|
82
|
+
end_date: End of date range (inclusive)
|
|
83
|
+
installation_id: Optional filter for specific user
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
List of ScanEvent objects matching criteria
|
|
87
|
+
"""
|
|
88
|
+
pass
|
|
89
|
+
|
|
90
|
+
@abstractmethod
|
|
91
|
+
def get_user_activity(
|
|
92
|
+
self,
|
|
93
|
+
installation_id: str,
|
|
94
|
+
start_date: date | None = None,
|
|
95
|
+
end_date: date | None = None
|
|
96
|
+
) -> UserActivity | None:
|
|
97
|
+
"""Get user activity summary.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
installation_id: User's installation identifier
|
|
101
|
+
start_date: Optional start date filter
|
|
102
|
+
end_date: Optional end date filter
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
UserActivity object or None if user not found
|
|
106
|
+
"""
|
|
107
|
+
pass
|
|
108
|
+
|
|
109
|
+
@abstractmethod
|
|
110
|
+
def get_cohort_users(
|
|
111
|
+
self,
|
|
112
|
+
cohort_date: date
|
|
113
|
+
) -> list[str]:
|
|
114
|
+
"""Get list of users who joined on specific date.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
cohort_date: Date to find new installations
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
List of installation IDs who first appeared on cohort_date
|
|
121
|
+
"""
|
|
122
|
+
pass
|
|
123
|
+
|
|
124
|
+
@abstractmethod
|
|
125
|
+
def get_active_users(
|
|
126
|
+
self,
|
|
127
|
+
target_date: date,
|
|
128
|
+
window_days: int = 1
|
|
129
|
+
) -> list[str]:
|
|
130
|
+
"""Get active users within window of target date.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
target_date: Reference date for activity check
|
|
134
|
+
window_days: Number of days before target_date to include
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
List of installation IDs active in the window
|
|
138
|
+
"""
|
|
139
|
+
pass
|
|
140
|
+
|
|
141
|
+
@abstractmethod
|
|
142
|
+
def save_achievement(
|
|
143
|
+
self,
|
|
144
|
+
installation_id: str,
|
|
145
|
+
achievement_id: str,
|
|
146
|
+
earned_at: datetime,
|
|
147
|
+
metadata: dict[str, Any]
|
|
148
|
+
) -> None:
|
|
149
|
+
"""Save achievement earned by user.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
installation_id: User who earned the achievement
|
|
153
|
+
achievement_id: Unique achievement identifier
|
|
154
|
+
earned_at: Timestamp when achievement was earned
|
|
155
|
+
metadata: Additional achievement data (name, points, etc.)
|
|
156
|
+
"""
|
|
157
|
+
pass
|
|
158
|
+
|
|
159
|
+
@abstractmethod
|
|
160
|
+
def get_achievements(
|
|
161
|
+
self,
|
|
162
|
+
installation_id: str
|
|
163
|
+
) -> list[dict[str, Any]]:
|
|
164
|
+
"""Get all achievements for user.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
installation_id: User to query
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
List of achievement dictionaries with metadata
|
|
171
|
+
"""
|
|
172
|
+
pass
|