howler-api 4.0.0.dev1281__tar.gz → 4.0.0.dev1291__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/PKG-INFO +1 -1
  2. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v2/ingest.py +2 -2
  3. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/common/loader.py +1 -0
  4. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/config.py +1 -0
  5. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/datastore/collection.py +2 -2
  6. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/correlation_service.py +3 -2
  7. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/fuzzy_service.py +4 -4
  8. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/search_service.py +4 -47
  9. howler_api-4.0.0.dev1291/howler/utils/indexes.py +56 -0
  10. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/pyproject.toml +1 -1
  11. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/README.md +0 -0
  12. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/__init__.py +0 -0
  13. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/actions/__init__.py +0 -0
  14. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/actions/add_label.py +0 -0
  15. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/actions/add_to_bundle.py +0 -0
  16. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/actions/add_to_case.py +0 -0
  17. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/actions/change_field.py +0 -0
  18. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/actions/demote.py +0 -0
  19. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/actions/example_plugin.py +0 -0
  20. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/actions/prioritization.py +0 -0
  21. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/actions/promote.py +0 -0
  22. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/actions/remove_from_bundle.py +0 -0
  23. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/actions/remove_label.py +0 -0
  24. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/actions/transition.py +0 -0
  25. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/__init__.py +0 -0
  26. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/base.py +0 -0
  27. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/socket.py +0 -0
  28. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v1/__init__.py +0 -0
  29. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v1/action.py +0 -0
  30. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v1/analytic.py +0 -0
  31. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v1/auth.py +0 -0
  32. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v1/clue.py +0 -0
  33. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v1/configs.py +0 -0
  34. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v1/dossier.py +0 -0
  35. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v1/help.py +0 -0
  36. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v1/hit.py +0 -0
  37. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v1/notebook.py +0 -0
  38. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v1/overview.py +0 -0
  39. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v1/search.py +0 -0
  40. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v1/template.py +0 -0
  41. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v1/tool.py +0 -0
  42. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v1/user.py +0 -0
  43. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v1/utils/__init__.py +0 -0
  44. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v1/utils/etag.py +0 -0
  45. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v1/utils/params.py +0 -0
  46. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v1/view.py +0 -0
  47. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v2/__init__.py +0 -0
  48. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v2/case.py +0 -0
  49. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v2/fuzzy.py +0 -0
  50. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/api/v2/search.py +0 -0
  51. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/app.py +0 -0
  52. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/common/README.md +0 -0
  53. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/common/__init__.py +0 -0
  54. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/common/classification.py +0 -0
  55. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/common/classification.yml +0 -0
  56. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/common/exceptions.py +0 -0
  57. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/common/logging/__init__.py +0 -0
  58. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/common/logging/audit.py +0 -0
  59. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/common/logging/format.py +0 -0
  60. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/common/net.py +0 -0
  61. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/common/net_static.py +0 -0
  62. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/common/random_user.py +0 -0
  63. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/common/swagger.py +0 -0
  64. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/cronjobs/__init__.py +0 -0
  65. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/cronjobs/action_queue_worker.py +0 -0
  66. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/cronjobs/correlation.py +0 -0
  67. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/cronjobs/retention.py +0 -0
  68. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/cronjobs/view_cleanup.py +0 -0
  69. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/datastore/README.md +0 -0
  70. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/datastore/__init__.py +0 -0
  71. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/datastore/bulk.py +0 -0
  72. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/datastore/constants.py +0 -0
  73. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/datastore/exceptions.py +0 -0
  74. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/datastore/howler_store.py +0 -0
  75. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/datastore/migrations/fix_process.py +0 -0
  76. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/datastore/operations.py +0 -0
  77. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/datastore/schemas.py +0 -0
  78. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/datastore/store.py +0 -0
  79. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/datastore/support/__init__.py +0 -0
  80. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/datastore/support/build.py +0 -0
  81. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/datastore/support/schemas.py +0 -0
  82. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/datastore/types.py +0 -0
  83. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/error.py +0 -0
  84. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/external/README.md +0 -0
  85. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/external/__init__.py +0 -0
  86. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/external/generate_mitre.py +0 -0
  87. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/external/generate_sigma_rules.py +0 -0
  88. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/external/generate_tlds.py +0 -0
  89. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/external/reindex_data.py +0 -0
  90. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/external/wipe_databases.py +0 -0
  91. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/gunicorn_config.py +0 -0
  92. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/healthz.py +0 -0
  93. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/helper/__init__.py +0 -0
  94. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/helper/azure.py +0 -0
  95. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/helper/discover.py +0 -0
  96. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/helper/hit.py +0 -0
  97. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/helper/oauth.py +0 -0
  98. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/helper/search.py +0 -0
  99. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/helper/workflow.py +0 -0
  100. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/helper/ws.py +0 -0
  101. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/README.md +0 -0
  102. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/__init__.py +0 -0
  103. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/base.py +0 -0
  104. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/charter.txt +0 -0
  105. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/constants.py +0 -0
  106. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/helper.py +0 -0
  107. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/howler_enum.py +0 -0
  108. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/mixins.py +0 -0
  109. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/__init__.py +0 -0
  110. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/action.py +0 -0
  111. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/analytic.py +0 -0
  112. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/assemblyline.py +0 -0
  113. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/aws.py +0 -0
  114. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/azure.py +0 -0
  115. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/case.py +0 -0
  116. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/cbs.py +0 -0
  117. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/clue.py +0 -0
  118. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/config.py +0 -0
  119. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/dossier.py +0 -0
  120. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/__init__.py +0 -0
  121. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/agent.py +0 -0
  122. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/autonomous_system.py +0 -0
  123. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/client.py +0 -0
  124. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/cloud.py +0 -0
  125. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/code_signature.py +0 -0
  126. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/container.py +0 -0
  127. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/dns.py +0 -0
  128. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/egress.py +0 -0
  129. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/elf.py +0 -0
  130. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/email.py +0 -0
  131. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/error.py +0 -0
  132. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/event.py +0 -0
  133. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/faas.py +0 -0
  134. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/file.py +0 -0
  135. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/geo.py +0 -0
  136. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/group.py +0 -0
  137. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/hash.py +0 -0
  138. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/host.py +0 -0
  139. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/http.py +0 -0
  140. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/ingress.py +0 -0
  141. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/interface.py +0 -0
  142. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/network.py +0 -0
  143. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/observer.py +0 -0
  144. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/organization.py +0 -0
  145. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/os.py +0 -0
  146. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/pe.py +0 -0
  147. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/process.py +0 -0
  148. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/registry.py +0 -0
  149. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/related.py +0 -0
  150. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/rule.py +0 -0
  151. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/server.py +0 -0
  152. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/threat.py +0 -0
  153. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/tls.py +0 -0
  154. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/url.py +0 -0
  155. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/user.py +0 -0
  156. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/user_agent.py +0 -0
  157. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/ecs/vulnerability.py +0 -0
  158. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/event.py +0 -0
  159. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/gcp.py +0 -0
  160. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/hit.py +0 -0
  161. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/howler_data.py +0 -0
  162. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/lead.py +0 -0
  163. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/localized_label.py +0 -0
  164. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/overview.py +0 -0
  165. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/pivot.py +0 -0
  166. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/record.py +0 -0
  167. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/template.py +0 -0
  168. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/user.py +0 -0
  169. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/models/view.py +0 -0
  170. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/random_data.py +0 -0
  171. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/odm/randomizer.py +0 -0
  172. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/patched.py +0 -0
  173. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/plugins/__init__.py +0 -0
  174. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/plugins/config.py +0 -0
  175. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/remote/__init__.py +0 -0
  176. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/remote/datatypes/README.md +0 -0
  177. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/remote/datatypes/__init__.py +0 -0
  178. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/remote/datatypes/counters.py +0 -0
  179. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/remote/datatypes/events.py +0 -0
  180. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/remote/datatypes/hash.py +0 -0
  181. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/remote/datatypes/lock.py +0 -0
  182. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/remote/datatypes/queues/__init__.py +0 -0
  183. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/remote/datatypes/queues/comms.py +0 -0
  184. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/remote/datatypes/queues/multi.py +0 -0
  185. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/remote/datatypes/queues/named.py +0 -0
  186. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/remote/datatypes/queues/priority.py +0 -0
  187. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/remote/datatypes/set.py +0 -0
  188. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/remote/datatypes/user_quota_tracker.py +0 -0
  189. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/security/__init__.py +0 -0
  190. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/security/socket.py +0 -0
  191. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/security/utils.py +0 -0
  192. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/__init__.py +0 -0
  193. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/action_service.py +0 -0
  194. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/analytic_service.py +0 -0
  195. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/auth_service.py +0 -0
  196. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/bundle_compat_service.py +0 -0
  197. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/case_service.py +0 -0
  198. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/comms_service.py +0 -0
  199. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/config_service.py +0 -0
  200. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/docs_service.py +0 -0
  201. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/dossier_service.py +0 -0
  202. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/event_service.py +0 -0
  203. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/hit_service.py +0 -0
  204. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/jwt_service.py +0 -0
  205. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/lucene_service.py +0 -0
  206. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/notebook_service.py +0 -0
  207. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/overview_service.py +0 -0
  208. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/template_service.py +0 -0
  209. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/user_service.py +0 -0
  210. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/services/viewer_service.py +0 -0
  211. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/telemetry.py +0 -0
  212. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/utils/__init__.py +0 -0
  213. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/utils/annotations.py +0 -0
  214. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/utils/chunk.py +0 -0
  215. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/utils/compat.py +0 -0
  216. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/utils/constants.py +0 -0
  217. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/utils/dict_utils.py +0 -0
  218. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/utils/isotime.py +0 -0
  219. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/utils/list_utils.py +0 -0
  220. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/utils/lucene.py +0 -0
  221. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/utils/net_utils.py +0 -0
  222. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/utils/path.py +0 -0
  223. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/utils/socket_utils.py +0 -0
  224. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/utils/str_utils.py +0 -0
  225. {howler_api-4.0.0.dev1281 → howler_api-4.0.0.dev1291}/howler/utils/uid.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: howler-api
3
- Version: 4.0.0.dev1281
3
+ Version: 4.0.0.dev1291
4
4
  Summary: Howler - API server
5
5
  License: MIT
6
6
  Keywords: howler,alerting,gc,canada,cse-cst,cse,cst,cyber,cccs
@@ -11,7 +11,7 @@ from howler.common.exceptions import HowlerException, HowlerValueError
11
11
  from howler.common.loader import datastore
12
12
  from howler.common.logging import get_logger
13
13
  from howler.common.swagger import generate_swagger_docs
14
- from howler.config import config
14
+ from howler.config import CORRELATION_QUEUE_NAME, config
15
15
  from howler.datastore.collection import ESCollection
16
16
  from howler.datastore.exceptions import DataStoreException
17
17
  from howler.datastore.howler_store import INDEXES
@@ -46,7 +46,7 @@ def _get_ingestion_queue() -> NamedQueue[str]:
46
46
 
47
47
  if _ingestion_queue is None:
48
48
  _ingestion_queue = NamedQueue(
49
- "howler.ingestion_queue",
49
+ CORRELATION_QUEUE_NAME,
50
50
  host=config.core.redis.persistent.host,
51
51
  port=config.core.redis.persistent.port,
52
52
  private=False,
@@ -14,6 +14,7 @@ if TYPE_CHECKING:
14
14
 
15
15
 
16
16
  APP_NAME = os.environ.get("APP_NAME", "howler")
17
+ DATASTORE_INDEX_PREFIX = os.environ.get("HWL_DATASTORE_INDEX_PREFIX", APP_NAME)
17
18
  APP_PREFIX = os.environ.get("APP_PREFIX", "hwl")
18
19
  USER_TYPES = {"admin", "user", "automation_basic", "automation_advanced", "actionrunner_basic", "actionrunner_advanced"}
19
20
 
@@ -24,6 +24,7 @@ HWL_USE_WEBSOCKET_API = os.environ.get("HWL_USE_WEBSOCKET_API", "false").lower()
24
24
  HWL_USE_JOB_SYSTEM = os.environ.get("HWL_USE_JOB_SYSTEM", "false").lower() == "true"
25
25
  HWL_ENABLE_COVERAGE = os.environ.get("HWL_ENABLE_COVERAGE", "false").lower() == "true"
26
26
  HWL_PLUGIN_DIRECTORY = os.environ.get("HWL_PLUGIN_DIRECTORY", "/etc/howler/plugins")
27
+ CORRELATION_QUEUE_NAME = os.environ.get("HWL_CORRELATION_QUEUE_NAME", "howler.ingestion_queue")
27
28
 
28
29
 
29
30
  def get_version() -> str:
@@ -20,7 +20,7 @@ from opentelemetry import trace
20
20
 
21
21
  from howler import odm
22
22
  from howler.common.exceptions import HowlerRuntimeError, HowlerValueError, NonRecoverableError
23
- from howler.common.loader import APP_NAME
23
+ from howler.common.loader import DATASTORE_INDEX_PREFIX
24
24
  from howler.common.logging.format import HWL_DATE_FORMAT, HWL_LOG_FORMAT
25
25
  from howler.datastore.constants import BACK_MAPPING, TYPE_MAPPING
26
26
  from howler.datastore.exceptions import (
@@ -229,7 +229,7 @@ class ESCollection(Generic[ModelType]):
229
229
  self._index_list: list[str] = []
230
230
 
231
231
  self.datastore = datastore
232
- self.name = f"{APP_NAME}-{name}"
232
+ self.name = f"{DATASTORE_INDEX_PREFIX}-{name}"
233
233
  self.ilm_config = ilm_config
234
234
  self.index_name = f"{self.name}_hot"
235
235
  self.model_class = model_class
@@ -16,6 +16,7 @@ from opentelemetry import trace
16
16
  from howler.common.exceptions import InvalidDataException, NotFoundException
17
17
  from howler.common.loader import datastore
18
18
  from howler.common.logging import get_logger
19
+ from howler.config import CORRELATION_QUEUE_NAME
19
20
  from howler.odm.models.case import CaseRule, RuleIndexTypes
20
21
  from howler.odm.models.config import config
21
22
  from howler.remote.datatypes.queues.named import NamedQueue
@@ -181,7 +182,7 @@ def process_batch(record_ids: list[str]) -> int: # noqa: C901
181
182
  def _build_queue() -> NamedQueue[str]:
182
183
  """Create the NamedQueue backed by persistent Redis."""
183
184
  return NamedQueue(
184
- "howler.ingestion_queue",
185
+ CORRELATION_QUEUE_NAME,
185
186
  host=config.core.redis.persistent.host,
186
187
  port=config.core.redis.persistent.port,
187
188
  private=False,
@@ -210,7 +211,7 @@ def run_worker() -> None: # pragma: no cover – long-running loop, tested via
210
211
  logger.debug("Processing correlation batch of %d hit(s)", len(batch))
211
212
  try:
212
213
  added = process_batch(batch)
213
- logger.info("Correlation batch complete: %d/%d hit(s) added", added, len(batch))
214
+ logger.info("Correlation batch complete: %d case item(s) added for %d record(s)", added, len(batch))
214
215
  except Exception:
215
216
  logger.exception("Error processing correlation batch")
216
217
  finally:
@@ -8,7 +8,7 @@ import elasticsearch
8
8
  from elasticsearch import Elasticsearch
9
9
 
10
10
  from howler import odm
11
- from howler.common.loader import APP_NAME, datastore
11
+ from howler.common.loader import datastore
12
12
  from howler.common.logging import get_logger
13
13
  from howler.datastore.exceptions import SearchException, SearchRetryException
14
14
  from howler.datastore.types import SearchResult
@@ -25,7 +25,7 @@ from howler.odm.base import (
25
25
  Text,
26
26
  _Field,
27
27
  )
28
- from howler.services.search_service import _normalize_indexes
28
+ from howler.utils.indexes import get_logical_index_name, normalize_indexes
29
29
  from howler.utils.str_utils import sanitize_lucene_query
30
30
 
31
31
  DEFAULT_OFFSET = 0
@@ -369,7 +369,7 @@ def fuzzy_search(
369
369
  raise SearchException(f"Invalid index for fuzzy search: {idx}")
370
370
 
371
371
  client: Elasticsearch = datastore().ds.client
372
- parsed_indexes = _normalize_indexes(indexes)
372
+ parsed_indexes = normalize_indexes(indexes)
373
373
 
374
374
  query_body = build_fuzzy_query(query, indexes, filters, access_control)
375
375
 
@@ -420,7 +420,7 @@ def _format_items_with_score(hits: list[dict[str, Any]]) -> list[dict[str, Any]]
420
420
  if source:
421
421
  raw_index = hit.get("_index", None)
422
422
  if raw_index:
423
- source["__index"] = raw_index.replace(f"{APP_NAME}-", "").replace("_hot", "")
423
+ source["__index"] = get_logical_index_name(raw_index)
424
424
  source["_score"] = hit.get("_score", 0)
425
425
  items.append(source)
426
426
  return items
@@ -5,7 +5,7 @@ from typing import Any
5
5
  import elasticsearch
6
6
  from elasticsearch import Elasticsearch
7
7
 
8
- from howler.common.loader import APP_NAME, datastore
8
+ from howler.common.loader import datastore
9
9
  from howler.common.logging import get_logger
10
10
  from howler.datastore.collection import parse_sort
11
11
  from howler.datastore.exceptions import SearchException, SearchRetryException
@@ -13,6 +13,7 @@ from howler.datastore.types import SearchResult
13
13
  from howler.helper.search import get_collection, has_access_control
14
14
  from howler.odm.models.user import User
15
15
  from howler.services import case_service
16
+ from howler.utils.indexes import get_logical_index_name, normalize_indexes
16
17
 
17
18
  DEFAULT_OFFSET = 0
18
19
  DEFAULT_ROW_SIZE = 25
@@ -23,50 +24,6 @@ SCROLL_TIMEOUT = "5m"
23
24
  logger = get_logger(__file__)
24
25
 
25
26
 
26
- def _normalize_indexes(indexes: str | list[str]) -> str:
27
- """Normalizes Elasticsearch index names into a comma-separated string.
28
-
29
- Parses the input indexes and applies naming conventions. Special patterns like
30
- wildcards, exclusions, and explicitly formatted indexes are preserved as-is.
31
- Regular indexes are formatted with the APP_NAME prefix and '_hot' suffix.
32
-
33
- Args:
34
- indexes: A comma-separated string or list of index names to normalize.
35
-
36
- Returns:
37
- A comma-separated string of normalized index names ready for Elasticsearch queries.
38
-
39
- Raises:
40
- SearchException: If no valid indexes are provided after parsing and stripping whitespace.
41
-
42
- Examples:
43
- >>> _normalize_indexes("logs,metrics")
44
- "howler-logs_hot,howler-metrics_hot"
45
-
46
- >>> _normalize_indexes(["*", "custom-index"])
47
- "*,custom-index"
48
-
49
- >>> _normalize_indexes("alerts, events")
50
- "howler-alerts_hot,howler-events_hot"
51
- """
52
- if isinstance(indexes, str):
53
- parsed_indexes = [item.strip() for item in indexes.split(",") if item.strip()]
54
- else:
55
- parsed_indexes = [item.strip() for item in indexes if item.strip()]
56
-
57
- if not parsed_indexes:
58
- raise SearchException("No indexes were provided.")
59
-
60
- normalized_indexes: list[str] = []
61
- for index in parsed_indexes:
62
- if index in {"*", "_all"} or "-" in index or "*" in index:
63
- normalized_indexes.append(index)
64
- else:
65
- normalized_indexes.append(f"{APP_NAME}-{index}")
66
-
67
- return ",".join(normalized_indexes)
68
-
69
-
70
27
  def _format_items(hits: list[dict[str, Any]], user_classification: str | None) -> list[dict[str, Any]]:
71
28
  """Formats Elasticsearch search hits into a standardized item format.
72
29
 
@@ -86,7 +43,7 @@ def _format_items(hits: list[dict[str, Any]], user_classification: str | None) -
86
43
  raw_index = hit.get("_index", None)
87
44
 
88
45
  if raw_index:
89
- source["__index"] = raw_index.replace(f"{APP_NAME}-", "").replace("_hot", "")
46
+ source["__index"] = get_logical_index_name(raw_index)
90
47
 
91
48
  if source.get("__index") == "case" and user_classification:
92
49
  case_service.filter_case_items_by_classification(source, user_classification)
@@ -137,7 +94,7 @@ def search( # noqa: C901
137
94
  del metadata
138
95
 
139
96
  client: Elasticsearch = datastore().ds.client
140
- parsed_indexes = _normalize_indexes(indexes)
97
+ parsed_indexes = normalize_indexes(indexes)
141
98
 
142
99
  if filters is None:
143
100
  parsed_filters: list[str] = []
@@ -0,0 +1,56 @@
1
+ from howler.common.loader import APP_NAME, DATASTORE_INDEX_PREFIX
2
+ from howler.datastore.exceptions import SearchException
3
+
4
+
5
+ def normalize_indexes(indexes: str | list[str]) -> str:
6
+ """Normalizes Elasticsearch index names into a comma-separated string.
7
+
8
+ Parses the input indexes and applies naming conventions. Special patterns like
9
+ wildcards, exclusions, and explicitly formatted indexes are preserved as-is.
10
+ Regular indexes are formatted with the datastore index prefix and '_hot' suffix.
11
+
12
+ Args:
13
+ indexes: A comma-separated string or list of index names to normalize.
14
+
15
+ Returns:
16
+ A comma-separated string of normalized index names ready for Elasticsearch queries.
17
+
18
+ Raises:
19
+ SearchException: If no valid indexes are provided after parsing and stripping whitespace.
20
+
21
+ Examples:
22
+ >>> normalize_indexes("logs,metrics")
23
+ "howler-logs_hot,howler-metrics_hot"
24
+
25
+ >>> normalize_indexes(["*", "custom-index"])
26
+ "*,custom-index"
27
+
28
+ >>> normalize_indexes("alerts, events")
29
+ "howler-alerts_hot,howler-events_hot"
30
+ """
31
+ if isinstance(indexes, str):
32
+ parsed_indexes = [item.strip() for item in indexes.split(",") if item.strip()]
33
+ else:
34
+ parsed_indexes = [item.strip() for item in indexes if item.strip()]
35
+
36
+ if not parsed_indexes:
37
+ raise SearchException("No indexes were provided.")
38
+
39
+ normalized_indexes: list[str] = []
40
+ for index in parsed_indexes:
41
+ if index in {"*", "_all"} or "-" in index or "*" in index:
42
+ normalized_indexes.append(index)
43
+ else:
44
+ normalized_indexes.append(f"{DATASTORE_INDEX_PREFIX}-{index}")
45
+
46
+ return ",".join(normalized_indexes)
47
+
48
+
49
+ def get_logical_index_name(raw_index: str) -> str:
50
+ """Strip the physical datastore prefix and hot-index suffix from an index name."""
51
+ for index_prefix in sorted({DATASTORE_INDEX_PREFIX, APP_NAME}, key=len, reverse=True):
52
+ if raw_index.startswith(f"{index_prefix}-"):
53
+ raw_index = raw_index.removeprefix(f"{index_prefix}-")
54
+ break
55
+
56
+ return raw_index.removesuffix("_hot")
@@ -152,7 +152,7 @@ suppress-none-returning = true
152
152
  [tool.poetry]
153
153
  package-mode = true
154
154
  name = "howler-api"
155
- version = "4.0.0.dev1281"
155
+ version = "4.0.0.dev1291"
156
156
  description = "Howler - API server"
157
157
  authors = [
158
158
  "Canadian Centre for Cyber Security <howler@cyber.gc.ca>",