howler-api 4.0.0.dev1308__tar.gz → 4.0.0.dev1311__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.dev1308 → howler_api-4.0.0.dev1311}/PKG-INFO +1 -1
  2. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/datastore/collection.py +92 -22
  3. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/external/reindex_data.py +1 -0
  4. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/random_data.py +5 -1
  5. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/pyproject.toml +1 -1
  6. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/README.md +0 -0
  7. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/__init__.py +0 -0
  8. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/actions/__init__.py +0 -0
  9. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/actions/add_label.py +0 -0
  10. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/actions/add_to_bundle.py +0 -0
  11. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/actions/add_to_case.py +0 -0
  12. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/actions/change_field.py +0 -0
  13. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/actions/demote.py +0 -0
  14. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/actions/example_plugin.py +0 -0
  15. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/actions/prioritization.py +0 -0
  16. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/actions/promote.py +0 -0
  17. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/actions/remove_from_bundle.py +0 -0
  18. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/actions/remove_label.py +0 -0
  19. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/actions/transition.py +0 -0
  20. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/__init__.py +0 -0
  21. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/base.py +0 -0
  22. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/socket.py +0 -0
  23. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v1/__init__.py +0 -0
  24. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v1/action.py +0 -0
  25. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v1/analytic.py +0 -0
  26. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v1/auth.py +0 -0
  27. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v1/clue.py +0 -0
  28. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v1/configs.py +0 -0
  29. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v1/dossier.py +0 -0
  30. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v1/help.py +0 -0
  31. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v1/hit.py +0 -0
  32. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v1/notebook.py +0 -0
  33. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v1/overview.py +0 -0
  34. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v1/search.py +0 -0
  35. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v1/template.py +0 -0
  36. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v1/tool.py +0 -0
  37. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v1/user.py +0 -0
  38. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v1/utils/__init__.py +0 -0
  39. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v1/utils/etag.py +0 -0
  40. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v1/utils/params.py +0 -0
  41. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v1/view.py +0 -0
  42. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v2/__init__.py +0 -0
  43. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v2/case.py +0 -0
  44. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v2/fuzzy.py +0 -0
  45. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v2/ingest.py +0 -0
  46. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/api/v2/search.py +0 -0
  47. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/app.py +0 -0
  48. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/common/README.md +0 -0
  49. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/common/__init__.py +0 -0
  50. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/common/classification.py +0 -0
  51. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/common/classification.yml +0 -0
  52. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/common/exceptions.py +0 -0
  53. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/common/loader.py +0 -0
  54. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/common/logging/__init__.py +0 -0
  55. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/common/logging/audit.py +0 -0
  56. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/common/logging/format.py +0 -0
  57. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/common/net.py +0 -0
  58. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/common/net_static.py +0 -0
  59. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/common/random_user.py +0 -0
  60. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/common/swagger.py +0 -0
  61. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/config.py +0 -0
  62. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/cronjobs/__init__.py +0 -0
  63. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/cronjobs/action_queue_worker.py +0 -0
  64. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/cronjobs/correlation.py +0 -0
  65. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/cronjobs/retention.py +0 -0
  66. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/cronjobs/view_cleanup.py +0 -0
  67. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/datastore/README.md +0 -0
  68. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/datastore/__init__.py +0 -0
  69. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/datastore/bulk.py +0 -0
  70. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/datastore/constants.py +0 -0
  71. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/datastore/exceptions.py +0 -0
  72. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/datastore/howler_store.py +0 -0
  73. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/datastore/migrations/fix_process.py +0 -0
  74. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/datastore/operations.py +0 -0
  75. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/datastore/schemas.py +0 -0
  76. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/datastore/store.py +0 -0
  77. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/datastore/support/__init__.py +0 -0
  78. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/datastore/support/build.py +0 -0
  79. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/datastore/support/schemas.py +0 -0
  80. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/datastore/types.py +0 -0
  81. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/error.py +0 -0
  82. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/external/README.md +0 -0
  83. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/external/__init__.py +0 -0
  84. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/external/generate_mitre.py +0 -0
  85. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/external/generate_sigma_rules.py +0 -0
  86. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/external/generate_tlds.py +0 -0
  87. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/external/wipe_databases.py +0 -0
  88. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/gunicorn_config.py +0 -0
  89. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/healthz.py +0 -0
  90. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/helper/__init__.py +0 -0
  91. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/helper/azure.py +0 -0
  92. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/helper/discover.py +0 -0
  93. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/helper/hit.py +0 -0
  94. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/helper/oauth.py +0 -0
  95. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/helper/search.py +0 -0
  96. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/helper/workflow.py +0 -0
  97. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/helper/ws.py +0 -0
  98. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/README.md +0 -0
  99. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/__init__.py +0 -0
  100. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/base.py +0 -0
  101. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/charter.txt +0 -0
  102. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/constants.py +0 -0
  103. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/helper.py +0 -0
  104. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/howler_enum.py +0 -0
  105. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/mixins.py +0 -0
  106. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/__init__.py +0 -0
  107. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/action.py +0 -0
  108. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/analytic.py +0 -0
  109. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/assemblyline.py +0 -0
  110. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/aws.py +0 -0
  111. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/azure.py +0 -0
  112. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/case.py +0 -0
  113. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/cbs.py +0 -0
  114. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/clue.py +0 -0
  115. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/config.py +0 -0
  116. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/dossier.py +0 -0
  117. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/__init__.py +0 -0
  118. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/agent.py +0 -0
  119. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/autonomous_system.py +0 -0
  120. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/client.py +0 -0
  121. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/cloud.py +0 -0
  122. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/code_signature.py +0 -0
  123. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/container.py +0 -0
  124. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/dns.py +0 -0
  125. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/egress.py +0 -0
  126. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/elf.py +0 -0
  127. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/email.py +0 -0
  128. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/error.py +0 -0
  129. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/event.py +0 -0
  130. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/faas.py +0 -0
  131. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/file.py +0 -0
  132. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/geo.py +0 -0
  133. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/group.py +0 -0
  134. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/hash.py +0 -0
  135. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/host.py +0 -0
  136. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/http.py +0 -0
  137. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/ingress.py +0 -0
  138. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/interface.py +0 -0
  139. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/network.py +0 -0
  140. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/observer.py +0 -0
  141. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/organization.py +0 -0
  142. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/os.py +0 -0
  143. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/pe.py +0 -0
  144. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/process.py +0 -0
  145. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/registry.py +0 -0
  146. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/related.py +0 -0
  147. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/rule.py +0 -0
  148. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/server.py +0 -0
  149. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/threat.py +0 -0
  150. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/tls.py +0 -0
  151. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/url.py +0 -0
  152. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/user.py +0 -0
  153. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/user_agent.py +0 -0
  154. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/ecs/vulnerability.py +0 -0
  155. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/event.py +0 -0
  156. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/gcp.py +0 -0
  157. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/hit.py +0 -0
  158. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/howler_data.py +0 -0
  159. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/lead.py +0 -0
  160. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/localized_label.py +0 -0
  161. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/overview.py +0 -0
  162. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/pivot.py +0 -0
  163. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/record.py +0 -0
  164. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/template.py +0 -0
  165. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/user.py +0 -0
  166. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/models/view.py +0 -0
  167. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/odm/randomizer.py +0 -0
  168. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/patched.py +0 -0
  169. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/plugins/__init__.py +0 -0
  170. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/plugins/config.py +0 -0
  171. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/remote/__init__.py +0 -0
  172. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/remote/datatypes/README.md +0 -0
  173. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/remote/datatypes/__init__.py +0 -0
  174. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/remote/datatypes/counters.py +0 -0
  175. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/remote/datatypes/events.py +0 -0
  176. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/remote/datatypes/hash.py +0 -0
  177. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/remote/datatypes/lock.py +0 -0
  178. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/remote/datatypes/queues/__init__.py +0 -0
  179. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/remote/datatypes/queues/comms.py +0 -0
  180. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/remote/datatypes/queues/multi.py +0 -0
  181. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/remote/datatypes/queues/named.py +0 -0
  182. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/remote/datatypes/queues/priority.py +0 -0
  183. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/remote/datatypes/set.py +0 -0
  184. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/remote/datatypes/user_quota_tracker.py +0 -0
  185. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/security/__init__.py +0 -0
  186. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/security/socket.py +0 -0
  187. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/security/utils.py +0 -0
  188. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/__init__.py +0 -0
  189. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/action_service.py +0 -0
  190. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/analytic_service.py +0 -0
  191. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/auth_service.py +0 -0
  192. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/bundle_compat_service.py +0 -0
  193. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/case_service.py +0 -0
  194. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/comms_service.py +0 -0
  195. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/config_service.py +0 -0
  196. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/correlation_service.py +0 -0
  197. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/docs_service.py +0 -0
  198. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/dossier_service.py +0 -0
  199. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/event_service.py +0 -0
  200. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/fuzzy_service.py +0 -0
  201. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/hit_service.py +0 -0
  202. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/jwt_service.py +0 -0
  203. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/lucene_service.py +0 -0
  204. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/notebook_service.py +0 -0
  205. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/overview_service.py +0 -0
  206. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/search_service.py +0 -0
  207. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/template_service.py +0 -0
  208. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/user_service.py +0 -0
  209. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/services/viewer_service.py +0 -0
  210. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/telemetry.py +0 -0
  211. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/utils/__init__.py +0 -0
  212. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/utils/annotations.py +0 -0
  213. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/utils/chunk.py +0 -0
  214. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/utils/compat.py +0 -0
  215. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/utils/constants.py +0 -0
  216. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/utils/dict_utils.py +0 -0
  217. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/utils/indexes.py +0 -0
  218. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/utils/isotime.py +0 -0
  219. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/utils/list_utils.py +0 -0
  220. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/utils/lucene.py +0 -0
  221. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/utils/net_utils.py +0 -0
  222. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/utils/path.py +0 -0
  223. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/utils/socket_utils.py +0 -0
  224. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/howler/utils/str_utils.py +0 -0
  225. {howler_api-4.0.0.dev1308 → howler_api-4.0.0.dev1311}/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.dev1308
3
+ Version: 4.0.0.dev1311
4
4
  Summary: Howler - API server
5
5
  License: MIT
6
6
  Keywords: howler,alerting,gc,canada,cse-cst,cse,cst,cyber,cccs
@@ -252,19 +252,50 @@ class ESCollection(Generic[ModelType]):
252
252
 
253
253
  @property
254
254
  def index_list_full(self):
255
+ """Return every physical index for this collection, newest ILM index first.
256
+
257
+ Maintenance operations that must visit historical rollover indexes should use this
258
+ property. The active index is included even when no ILM rollover index exists.
259
+ """
255
260
  if not self._index_list:
256
- self._index_list = list(self.with_retries(self.datastore.client.indices.get, index=f"{self.name}-*").keys())
261
+ self._index_list = self._get_ilm_index_names()
257
262
 
258
- return [self.index_name] + sorted(self._index_list, reverse=True)
263
+ return list(dict.fromkeys([self.index_name, *sorted(self._index_list, reverse=True)]))
259
264
 
260
265
  @property
261
266
  def index_list(self):
262
- """This property contains the list of valid indexes for the current collection.
267
+ """Return the active physical write index for this collection.
263
268
 
264
- :return: list of valid indexes for this collection
269
+ Historical ILM rollover indexes are intentionally excluded. Bulk plans use this
270
+ list for default write, update, and delete targets, and widening it would fan those
271
+ operations out across historical indexes.
265
272
  """
266
273
  return [self.index_name]
267
274
 
275
+ def _get_ilm_index_names(self) -> list[str]:
276
+ """Return physical ILM rollover indexes, excluding temporary maintenance indexes."""
277
+ try:
278
+ indices = self.datastore.client.indices.get(
279
+ index=f"{self.name}-0*",
280
+ ignore_unavailable=True,
281
+ )
282
+ except elasticsearch.exceptions.NotFoundError:
283
+ return []
284
+
285
+ index_pattern = re.compile(rf"^{re.escape(self.name)}-\d{{6}}$")
286
+ return sorted(index for index in indices if index_pattern.fullmatch(index))
287
+
288
+ def _refresh_ilm_index_name(self):
289
+ """Set ``index_name`` to the latest existing ILM index, when one exists."""
290
+ if not self.ilm_config:
291
+ return
292
+
293
+ ilm_indices = self._get_ilm_index_names()
294
+
295
+ if ilm_indices:
296
+ self._index_list = ilm_indices
297
+ self.index_name = ilm_indices[-1]
298
+
268
299
  def scan_with_retry(
269
300
  self,
270
301
  query,
@@ -730,7 +761,7 @@ class ESCollection(Generic[ModelType]):
730
761
  def reindex(self, allow_failures: bool = False, request_timeout: int = 60):
731
762
  """Reindex all the data of the collection into a freshly mapped index.
732
763
 
733
- For every index in ``self.index_list`` the data is copied into a temporary
764
+ For every physical index in ``self.index_list_full`` the data is copied into a temporary
734
765
  ``__reindex`` index that uses the current mappings/settings. Writes to the source
735
766
  index are blocked while the copy runs so the reindex result and document counts can
736
767
  be validated before the original index is deleted. The temporary index is only
@@ -750,7 +781,8 @@ class ESCollection(Generic[ModelType]):
750
781
  operation can be recovered with :meth:`reindex_cleanup`.
751
782
  """
752
783
  logger.warning("Beginning Reindex")
753
- for index in self.index_list:
784
+ self._refresh_ilm_index_name()
785
+ for index in self.index_list_full:
754
786
  new_name = f"{index}__reindex"
755
787
  index_data = None
756
788
  source_count = None
@@ -798,7 +830,7 @@ class ESCollection(Generic[ModelType]):
798
830
  self.datastore.client.indices.create,
799
831
  index=new_name,
800
832
  mappings=self._get_index_mappings(),
801
- settings=self._get_index_settings(),
833
+ settings=self._get_reindex_settings(index_data),
802
834
  )
803
835
 
804
836
  # Reindex data into target
@@ -847,12 +879,10 @@ class ESCollection(Generic[ModelType]):
847
879
  )
848
880
 
849
881
  alias_actions = []
850
- aliases = index_data.get("aliases", {}) or {self.name: {"is_write_index": True}}
882
+ aliases = index_data.get("aliases", {})
851
883
  for alias, alias_data in aliases.items():
852
884
  alias_action = {"index": index, "alias": alias}
853
885
  alias_action.update(alias_data)
854
- if alias == self.name or alias_data.get("is_write_index", False):
855
- alias_action["is_write_index"] = True
856
886
  alias_actions.append({"add": alias_action})
857
887
  alias_actions.append({"remove_index": {"index": new_name}})
858
888
  self.with_retries(self.datastore.client.indices.update_aliases, actions=alias_actions)
@@ -880,6 +910,14 @@ class ESCollection(Generic[ModelType]):
880
910
 
881
911
  return True
882
912
 
913
+ def _get_reindex_settings(self, index_data: dict) -> dict:
914
+ """Build settings for a reindex target without dropping ILM lifecycle metadata."""
915
+ settings = self._get_index_settings()
916
+ lifecycle = index_data.get("settings", {}).get("index", {}).get("lifecycle")
917
+ if lifecycle:
918
+ settings["index"]["lifecycle"] = deepcopy(lifecycle)
919
+ return settings
920
+
883
921
  def _validate_reindex_result(self, index, new_name, reindex_result, allow_failures):
884
922
  """Validate the result of an Elasticsearch reindex task.
885
923
 
@@ -956,17 +994,18 @@ class ESCollection(Generic[ModelType]):
956
994
  def reindex_cleanup(self):
957
995
  """Recover from a failed or interrupted :meth:`reindex` run.
958
996
 
959
- For every index that still has a leftover ``__reindex`` index, restore the source
960
- index as the writable target and delete the orphaned ``__reindex`` index. If the
961
- source index is missing, raise an error instead of deleting ``__reindex`` because
962
- it may be the only remaining copy of the data.
997
+ For every physical index that still has a leftover ``__reindex`` index, restore the source
998
+ index's original aliases and delete the orphaned ``__reindex`` index. If the source
999
+ index is missing, raise an error instead of deleting ``__reindex`` because it may
1000
+ be the only remaining copy of the data.
963
1001
 
964
1002
  Write blocks set during reindexing are cleared so the collection is usable again.
965
1003
 
966
1004
  :return: ``True`` when cleanup completed on all indexes
967
1005
  """
968
1006
  logger.warning("Beginning reindex cleanup")
969
- for index in self.index_list:
1007
+ self._refresh_ilm_index_name()
1008
+ for index in self.index_list_full:
970
1009
  new_name = f"{index}__reindex"
971
1010
 
972
1011
  if not self.with_retries(self.datastore.client.indices.exists, index=new_name):
@@ -987,17 +1026,13 @@ class ESCollection(Generic[ModelType]):
987
1026
  reindex_aliases = new_index_data.get("aliases", {})
988
1027
 
989
1028
  alias_actions = []
990
- for alias in sorted(set(source_aliases) | set(reindex_aliases) | {self.name}):
1029
+ for alias in sorted(set(source_aliases) | set(reindex_aliases)):
991
1030
  source_alias_data = source_aliases.get(alias, {})
992
1031
  reindex_alias_data = reindex_aliases.get(alias, {})
993
1032
 
994
1033
  add_alias_data = {"index": index, "alias": alias}
995
1034
  add_alias_data.update(source_alias_data)
996
- if (
997
- alias == self.name
998
- or source_alias_data.get("is_write_index", False)
999
- or reindex_alias_data.get("is_write_index", False)
1000
- ):
1035
+ if source_alias_data.get("is_write_index", False) or reindex_alias_data.get("is_write_index", False):
1001
1036
  add_alias_data["is_write_index"] = True
1002
1037
 
1003
1038
  alias_actions.append({"add": add_alias_data})
@@ -2905,7 +2940,42 @@ class ESCollection(Generic[ModelType]):
2905
2940
  if existing_ilm_indices:
2906
2941
  # ILM already bootstrapped — ensure the alias exists
2907
2942
  latest = sorted(existing_ilm_indices)[-1]
2908
- if not self.with_retries(self.datastore.client.indices.exists_alias, name=self.name):
2943
+ legacy_hot_index = f"{self.name}_hot"
2944
+ if self.with_retries(self.datastore.client.indices.exists_alias, name=self.name):
2945
+ alias_indices = self.with_retries(self.datastore.client.indices.get_alias, name=self.name)
2946
+ alias_actions = []
2947
+ for alias_index, alias_index_data in alias_indices.items():
2948
+ alias_data = alias_index_data.get("aliases", {}).get(self.name, {})
2949
+ if alias_index == legacy_hot_index:
2950
+ alias_actions.append({"remove": {"index": alias_index, "alias": self.name}})
2951
+ elif alias_index != latest and alias_data.get("is_write_index", False):
2952
+ alias_actions.append(
2953
+ {
2954
+ "add": {
2955
+ "index": alias_index,
2956
+ "alias": self.name,
2957
+ **alias_data,
2958
+ "is_write_index": False,
2959
+ }
2960
+ }
2961
+ )
2962
+
2963
+ latest_alias_data = alias_indices.get(latest, {}).get("aliases", {}).get(self.name, {})
2964
+ if not latest_alias_data.get("is_write_index", False):
2965
+ alias_actions.append(
2966
+ {
2967
+ "add": {
2968
+ "index": latest,
2969
+ "alias": self.name,
2970
+ **latest_alias_data,
2971
+ "is_write_index": True,
2972
+ }
2973
+ }
2974
+ )
2975
+
2976
+ if alias_actions:
2977
+ self.with_retries(self.datastore.client.indices.update_aliases, actions=alias_actions)
2978
+ else:
2909
2979
  # Find the latest index to set as write index
2910
2980
  self.with_retries(
2911
2981
  self.datastore.client.indices.put_alias,
@@ -99,6 +99,7 @@ if __name__ == "__main__":
99
99
 
100
100
  for index_name in selected:
101
101
  collection: ESCollection = getattr(ds, index_name)
102
+ collection._refresh_ilm_index_name()
102
103
 
103
104
  if args.verbose:
104
105
  print(f"Index schema for '{index_name}':")
@@ -867,8 +867,12 @@ def wipe_actions(ds: HowlerDatastore):
867
867
  def create_dossiers(ds: HowlerDatastore, num_dossiers: int = 5):
868
868
  "Create random dossiers"
869
869
  users = ds.user.search("*:*")["items"]
870
- for _ in range(num_dossiers):
870
+ for index in range(num_dossiers):
871
871
  dossier = generate_useful_dossier(users)
872
+ if index == 0:
873
+ dossier.type = "personal"
874
+ elif index == 1:
875
+ dossier.type = "global"
872
876
  ds.dossier.save(dossier.dossier_id, dossier)
873
877
 
874
878
  ds.dossier.commit()
@@ -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.dev1308"
155
+ version = "4.0.0.dev1311"
156
156
  description = "Howler - API server"
157
157
  authors = [
158
158
  "Canadian Centre for Cyber Security <howler@cyber.gc.ca>",