Skip to content

fix(api): ensure hit statuses are not mismatched on ingest#487

Open
cccs-mdr wants to merge 4 commits into
developfrom
validate-hit-status-fields
Open

fix(api): ensure hit statuses are not mismatched on ingest#487
cccs-mdr wants to merge 4 commits into
developfrom
validate-hit-status-fields

Conversation

@cccs-mdr

Copy link
Copy Markdown
Collaborator

No description provided.

Copilot AI review requested due to automatic review settings July 13, 2026 18:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR tightens API ingest validation for hits by normalizing inconsistent state combinations at ingest time (so assessment/escalation and escalation/status don’t drift), and aligns ODM model annotations with explicit str/| None typing for better static clarity.

Changes:

  • Add ingest-time normalization in convert_hit() to enforce assessment→escalation mapping and ensure certain escalation values imply resolved status.
  • Emit warnings when incoming hits are auto-corrected to meet the expected state constraints.
  • Update HowlerData/related ODM model field type annotations to use str | None and explicit str for enum-backed fields.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
api/howler/services/hit_service.py Adds ingest-time state normalization and warning messages for mismatched assessment/escalation and escalation/status.
api/howler/odm/models/howler_data.py Refines ODM model type annotations (PEP 604 unions and explicit str types for enum fields).

Comment thread api/howler/services/hit_service.py Outdated
Comment thread api/howler/services/hit_service.py Outdated
Comment thread api/howler/odm/models/howler_data.py Outdated
@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Static Badge

Howler API - Coverage Results

Static Badge Static Badge

Diff Coverage

Diff: origin/main...HEAD, staged and unstaged changes

  • api/howler/services/hit_service.py (100%)

Summary

  • Total: 7 lines
  • Missing: 0 lines
  • Coverage: 100%

Full Coverage Report

Expand
Name                                            Stmts   Miss Branch BrPart  Cover
---------------------------------------------------------------------------------
howler/__init__.py                                  0      0      0      0   100%
howler/actions/__init__.py                         83      2     36      3    96%
howler/actions/add_label.py                        30      4      6      2    83%
howler/actions/add_to_bundle.py                    50      6     14      3    83%
howler/actions/change_field.py                     18      9      2      0    45%
howler/actions/demote.py                           35     18      8      0    40%
howler/actions/example_plugin.py                   13      8      2      0    33%
howler/actions/prioritization.py                   24     12      2      0    46%
howler/actions/promote.py                          35     18      8      0    40%
howler/actions/remove_from_bundle.py               47      6     14      5    79%
howler/actions/remove_label.py                     30      4      6      2    83%
howler/actions/transition.py                       66      4     24      4    91%
howler/api/__init__.py                            121     48     26      2    56%
howler/api/base.py                                 36      0     12      0   100%
howler/api/socket.py                               69      9     16      6    82%
howler/api/v1/__init__.py                          38      3     14      2    90%
howler/api/v1/action.py                           132     31     32      8    71%
howler/api/v1/analytic.py                         307     87     98     33    66%
howler/api/v1/auth.py                             164     25     56     16    80%
howler/api/v1/clue.py                              47     14     12      0    66%
howler/api/v1/configs.py                           14      0      0      0   100%
howler/api/v1/dossier.py                           96     27     10      4    69%
howler/api/v1/help.py                              13      0      0      0   100%
howler/api/v1/hit.py                              482     69    160     42    82%
howler/api/v1/notebook.py                          33      5      6      1    85%
howler/api/v1/overview.py                          84     10     18      6    84%
howler/api/v1/search.py                           303     80     90     17    71%
howler/api/v1/template.py                          93     12     26      8    83%
howler/api/v1/tool.py                             112      9     48      5    90%
howler/api/v1/user.py                             182     55     58     22    63%
howler/api/v1/utils/__init__.py                     0      0      0      0   100%
howler/api/v1/utils/etag.py                        23      0      8      1    97%
howler/api/v1/utils/params.py                      30      3     10      1    85%
howler/api/v1/view.py                             134     26     36     12    78%
howler/app.py                                     129     15     36     12    82%
howler/common/__init__.py                           0      0      0      0   100%
howler/common/classification.py                   597     78    342     73    83%
howler/common/exceptions.py                        74      8      2      0    89%
howler/common/loader.py                            87     24     40     11    66%
howler/common/logging/__init__.py                 141     83     64      7    36%
howler/common/logging/audit.py                     44      5      8      4    83%
howler/common/logging/format.py                    14      2      0      0    86%
howler/common/net.py                               55      2     28      2    95%
howler/common/net_static.py                         1      0      0      0   100%
howler/common/random_user.py                       10      0      2      0   100%
howler/common/swagger.py                           69     10     28      5    82%
howler/config.py                                   28      0      0      0   100%
howler/cronjobs/__init__.py                        19      2      4      0    91%
howler/cronjobs/action_queue_worker.py             22      2      6      1    89%
howler/cronjobs/retention.py                       48     15     12      2    68%
howler/cronjobs/rules.py                          116      9     36      5    89%
howler/cronjobs/view_cleanup.py                    47      6     22      4    83%
howler/datastore/__init__.py                        0      0      0      0   100%
howler/datastore/bulk.py                           53     53     26      0     0%
howler/datastore/collection.py                   1283    245    572    113    78%
howler/datastore/constants.py                       7      0      0      0   100%
howler/datastore/exceptions.py                     23      1      0      0    96%
howler/datastore/howler_store.py                   74      8     14      2    89%
howler/datastore/operations.py                     45      5     16      5    84%
howler/datastore/schemas.py                         4      4      0      0     0%
howler/datastore/store.py                         155     35     36      8    73%
howler/datastore/support/__init__.py                0      0      0      0   100%
howler/datastore/support/build.py                 101     26     68     10    70%
howler/datastore/support/schemas.py                 4      0      0      0   100%
howler/datastore/types.py                          13      0      0      0   100%
howler/error.py                                    52     31     12      0    33%
howler/healthz.py                                  47     31     12      0    27%
howler/helper/__init__.py                           0      0      0      0   100%
howler/helper/azure.py                             20      0      8      0   100%
howler/helper/discover.py                          32     10     12      4    64%
howler/helper/hit.py                               66     17     32     12    68%
howler/helper/oauth.py                            155     68    100     19    52%
howler/helper/search.py                            20      1      2      1    91%
howler/helper/workflow.py                          47      3     22      3    91%
howler/odm/__init__.py                              1      0      0      0   100%
howler/odm/base.py                                902    165    408     44    78%
howler/odm/helper.py                              171     22     68      6    82%
howler/odm/howler_enum.py                          13      0      0      0   100%
howler/odm/randomizer.py                          219     44    120     18    79%
howler/plugins/__init__.py                         17      0      4      0   100%
howler/plugins/config.py                           78      0     40      0   100%
howler/remote/__init__.py                           0      0      0      0   100%
howler/remote/datatypes/__init__.py               104      2     40      2    97%
howler/remote/datatypes/counters.py                47      5     16      0    92%
howler/remote/datatypes/events.py                  35      1      6      3    90%
howler/remote/datatypes/hash.py                   114     17     22      7    82%
howler/remote/datatypes/lock.py                    19      0      2      0   100%
howler/remote/datatypes/queues/__init__.py          0      0      0      0   100%
howler/remote/datatypes/queues/comms.py            46     10     14      3    75%
howler/remote/datatypes/queues/multi.py            22      3      8      3    80%
howler/remote/datatypes/queues/named.py            66      6     24      6    87%
howler/remote/datatypes/queues/priority.py        107     20     38     12    75%
howler/remote/datatypes/set.py                     74     12      8      2    80%
howler/remote/datatypes/user_quota_tracker.py      28     10      4      0    56%
howler/security/__init__.py                       128     21     40     10    82%
howler/security/socket.py                          53     10     12      5    74%
howler/security/utils.py                           81     37     36      2    48%
howler/services/__init__.py                         0      0      0      0   100%
howler/services/action_service.py                 101      4     52      5    94%
howler/services/analytic_service.py                78      9     32      2    90%
howler/services/auth_service.py                   140     13     52     10    88%
howler/services/config_service.py                  50      8      8      2    83%
howler/services/dossier_service.py                 79      7     40      2    89%
howler/services/event_service.py                   43     13     18      3    64%
howler/services/hit_service.py                    265     12    112      8    94%
howler/services/jwt_service.py                     71     20     18      3    74%
howler/services/lucene_service.py                 157     12     48      8    90%
howler/services/notebook_service.py                58      3     18      3    92%
howler/services/overview_service.py                21      5      6      2    74%
howler/services/template_service.py                22      5      6      2    75%
howler/services/user_service.py                   150     32     66     17    72%
howler/telemetry.py                                33     28      6      0    13%
howler/utils/__init__.py                            0      0      0      0   100%
howler/utils/annotations.py                         0      0      0      0   100%
howler/utils/chunk.py                               8      0      2      0   100%
howler/utils/compat.py                             11      6      2      1    46%
howler/utils/constants.py                           3      0      0      0   100%
howler/utils/dict_utils.py                        123     12     86     11    87%
howler/utils/isotime.py                             8      1      2      1    80%
howler/utils/list_utils.py                          7      0      4      0   100%
howler/utils/lucene.py                             52      1     18      1    97%
howler/utils/path.py                               16     16      2      0     0%
howler/utils/socket_utils.py                       22      0     14      3    92%
howler/utils/str_utils.py                         115     21     38      4    80%
howler/utils/uid.py                                20      2      4      2    83%
---------------------------------------------------------------------------------
TOTAL                                           10624   2018   3984    721    78%

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@cccs-mdr cccs-mdr changed the title fix(api): ensure hit statuses can't be mismatched on ingest fix(api): ensure hit statuses are not mismatched on ingest Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants