From e01eab61cf81c4d51acbdbfaced5ed6bb6dd3d1c Mon Sep 17 00:00:00 2001 From: Benjamin Pelletier Date: Wed, 19 Aug 2026 19:34:38 +0000 Subject: [PATCH 1/5] Fix zero-value overconstraint in SCD --- .../astm/utm/dss/fragments/sub/crud/create.md | 2 -- .../utm/dss/fragments/sub/validate/zero_index.md | 15 --------------- .../utm/dss/validators/subscription_validator.py | 15 --------------- 3 files changed, 32 deletions(-) delete mode 100644 monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/sub/validate/zero_index.md diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/sub/crud/create.md b/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/sub/crud/create.md index f88c86c0bb..5196c3fef9 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/sub/crud/create.md +++ b/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/sub/crud/create.md @@ -17,5 +17,3 @@ A successful subscription creation query is expected to return a well-defined bo If the content of the response does not correspond to the requested content, the DSS is failing to implement **[astm.f3548.v21.DSS0005,5](../../../../../../../requirements/astm/f3548/v21.md)**. ## [Validate subscription fields](../validate/correctness.md) - -## [Validate notification index](../validate/zero_index.md) diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/sub/validate/zero_index.md b/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/sub/validate/zero_index.md deleted file mode 100644 index c00218f519..0000000000 --- a/monitoring/uss_qualifier/scenarios/astm/utm/dss/fragments/sub/validate/zero_index.md +++ /dev/null @@ -1,15 +0,0 @@ -# Validate subscription notification index is equal to 0 test step fragment - -This test step fragment attempts to validate a single subscription's notification index returned by the DSS after the creation -of a subscription. - -The index may change for reasons outside of `uss_qualifier`'s control or awareness, therefore the only thing we can reliably verify with regard to the notification index is that: - - it should be there - - on creation of the entity it should be 0 - - after creation, it should be 0 or greater - -The code for these checks lives in the [subscription_validator.py](../../../validators/subscription_validator.py) class. - -## ⚠️ New subscription has a notification index of 0 check - -The notification index of a newly created subscription must be 0, otherwise the DSS is in violation of **[astm.f3548.v21.DSS0005,5](../../../../../../../requirements/astm/f3548/v21.md)**. diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/dss/validators/subscription_validator.py b/monitoring/uss_qualifier/scenarios/astm/utm/dss/validators/subscription_validator.py index 2cbe166bbf..8be52e7f4f 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/dss/validators/subscription_validator.py +++ b/monitoring/uss_qualifier/scenarios/astm/utm/dss/validators/subscription_validator.py @@ -317,21 +317,6 @@ def validate_created_subscription( expected_version=None, ) - # Check that the notification index is 0 for a newly created subscription. - # Should the notification field be missing, we assume it will have defaulted to 0 on the DSS's side. - with self._scenario.check( - "New subscription has a notification index of 0", self._pid - ) as check: - notif_index = new_sub.subscription.notification_index - if notif_index != 0: - self._fail_sub_check( - check, - summary=f"Returned notification index was {notif_index} instead of 0", - details="A subscription is expected to have a notification index of 0 when it is created" - f"Parameters used: {self._sub_params}", - t_dss=t_dss, - ) - def _check_notif_index_equal_or_above_0( self, notif_index: int, t_dss: datetime ) -> None: From 133dee3e083133d96042cb108846760bb3b04f7f Mon Sep 17 00:00:00 2001 From: Benjamin Pelletier Date: Wed, 19 Aug 2026 20:19:11 +0000 Subject: [PATCH 2/5] Remove zero-value overconstraint in RID --- .../dss/isa_subscription_interactions.py | 22 ------------------- .../netrid/common/dss/subscription_simple.py | 15 ------------- .../v19/dss/isa_subscription_interactions.md | 10 --------- .../netrid/v19/dss/subscription_simple.md | 5 ----- .../v22a/dss/isa_subscription_interactions.md | 10 --------- .../netrid/v22a/dss/subscription_simple.md | 4 ---- 6 files changed, 66 deletions(-) diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/isa_subscription_interactions.py b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/isa_subscription_interactions.py index 4aed362da0..0f07987b3c 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/isa_subscription_interactions.py +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/isa_subscription_interactions.py @@ -144,17 +144,6 @@ def _new_subscription_in_isa_step(self): ], ) - with self.check( - "Newly created subscription has a notification_index of 0", - [self._dss.participant_id], - ) as check: - if created_subscription.subscription.notification_index != 0: - check.record_failed( - summary="Subscription notification_index is not 0", - details=f"The subscription created for the area {self._isa_area} is expected to have a notification_index of 0. The returned subscription has a notification_index of {created_subscription.subscription.notification_index}.", - query_timestamps=[created_subscription.query.request.timestamp], - ) - # Modify the ISA with self.check( "Mutate the ISA", @@ -365,17 +354,6 @@ def _mutate_subscription_towards_isa_boundary_step(self): ], ) - with self.check( - "Mutated subscription has a notification_index of 0", - [self._dss.participant_id], - ) as check: - if created_subscription.subscription.notification_index != 0: - check.record_failed( - summary="Subscription notification_index is not 0", - details=f"The subscription created for the area {self._isa_area} is expected to have a notification_index of 0. The returned subscription has a notification_index of {created_subscription.subscription.notification_index}.", - query_timestamps=[created_subscription.query.request.timestamp], - ) - # Modify the ISA with self.check( "Mutate the ISA", diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/subscription_simple.py b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/subscription_simple.py index b8760cabdc..475bcc16a2 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/subscription_simple.py +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss/subscription_simple.py @@ -227,21 +227,6 @@ def _create_sub_with_params(self, creation_params: dict[str, Any]): creation_params["sub_id"], newly_created, creation_params, False ) - # Check that the notification index is 0 for a newly created subscription. - # Should the notification field be missing, we assume it will have defaulted to 0 on the DSS's side. - with self.check( - "Returned notification index is 0 if present", - [self._dss_wrapper.participant_id], - ) as check: - notif_index = newly_created.subscription.notification_index - if notif_index is not None and notif_index != 0: - check.record_failed( - f"Returned notification index was {notif_index} instead of 0", - details="A subscription is expected to have a notification index of 0 when it is created" - f"Parameters used: {creation_params}", - query_timestamps=[newly_created.query.request.timestamp], - ) - # Store the version of the subscription self._current_subscriptions[creation_params["sub_id"]] = ( newly_created.subscription diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_subscription_interactions.md b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_subscription_interactions.md index ba90ffb4d9..eb5eefe695 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_subscription_interactions.md +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/isa_subscription_interactions.md @@ -60,11 +60,6 @@ The DSS should allow the creation of a subscription within the ISA footprint, ot A subscription that is created for a volume that intersects with the previously created ISA should mention the previously created ISA. If not, the serving DSS is in violation of **[astm.f3411.v19.DSS0030,c](../../../../../requirements/astm/f3411/v19.md)**. -#### ⚠️ Newly created subscription has a notification_index of 0 check - -A newly created subscription is expected to have a notification index of 0, otherwise the DSS implementation under -test does not comply with **[astm.f3411.v19.DSS0030,c](../../../../../requirements/astm/f3411/v19.md)** - #### 🛑 Mutate the ISA check If the ISA cannot be mutated, **[astm.f3411.v19.DSS0030,a](../../../../../requirements/astm/f3411/v19.md)** is likely not implemented correctly. @@ -127,11 +122,6 @@ The DSS should allow a valid mutation of a subscription's area, otherwise it is A subscription that is created for a volume that intersects with the previously created ISA should mention the previously created ISA. If not, the serving DSS is in violation of **[astm.f3411.v19.DSS0030,c](../../../../../requirements/astm/f3411/v19.md)**. -#### ⚠️ Mutated subscription has a notification_index of 0 check - -A newly created subscription is expected to have a notification index of 0, otherwise the DSS implementation under -test does not comply with **[astm.f3411.v19.DSS0030,c](../../../../../requirements/astm/f3411/v19.md)** - #### 🛑 Mutate the ISA check If the ISA cannot be mutated, **[astm.f3411.v19.DSS0030,a](../../../../../requirements/astm/f3411/v19.md)** is likely not implemented correctly. diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/subscription_simple.md b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/subscription_simple.md index 89fbe5c2b1..718b556534 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/subscription_simple.md +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v19/dss/subscription_simple.md @@ -69,11 +69,6 @@ If the returned subscription has no owner set, **[astm.f3411.v19.DSS0030,c](../. If the returned subscription's owner does not correspond to the uss_qualifier, **[astm.f3411.v19.DSS0030,c](../../../../../requirements/astm/f3411/v19.md)** is not respected. - -#### 🛑 Returned notification index is 0 if present check - -The notification index of a newly created subscription must be 0, otherwise the DSS is in violation of **[astm.f3411.v19.DSS0030,c](../../../../../requirements/astm/f3411/v19.md)**. - #### 🛑 Returned subscription has an ISA URL check If the returned subscription has no ISA URL defined, **[astm.f3411.v19.DSS0030,c](../../../../../requirements/astm/f3411/v19.md)** is not respected. diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_subscription_interactions.md b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_subscription_interactions.md index eb74e569d2..6a25e5904e 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_subscription_interactions.md +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/isa_subscription_interactions.md @@ -60,11 +60,6 @@ The DSS should allow the creation of a subscription within the ISA footprint, ot A subscription that is created for a volume that intersects with the previously created ISA should mention the previously created ISA. If not, the serving DSS is in violation of **[astm.f3411.v22a.DSS0030,c](../../../../../requirements/astm/f3411/v22a.md)**. -#### ⚠️ Newly created subscription has a notification_index of 0 check - -A newly created subscription is expected to have a notification index of 0, otherwise the DSS implementation under -test does not comply with **[astm.f3411.v22a.DSS0030,c](../../../../../requirements/astm/f3411/v22a.md)** - #### 🛑 Mutate the ISA check If the ISA cannot be mutated, **[astm.f3411.v22a.DSS0030,a](../../../../../requirements/astm/f3411/v22a.md)** is likely not implemented correctly. @@ -127,11 +122,6 @@ The DSS should allow a valid mutation of a subscription's area, otherwise it is A subscription that is created for a volume that intersects with the previously created ISA should mention the previously created ISA. If not, the serving DSS is in violation of **[astm.f3411.v22a.DSS0030,c](../../../../../requirements/astm/f3411/v22a.md)**. -#### ⚠️ Mutated subscription has a notification_index of 0 check - -A newly created subscription is expected to have a notification index of 0, otherwise the DSS implementation under -test does not comply with **[astm.f3411.v22a.DSS0030,c](../../../../../requirements/astm/f3411/v22a.md)** - #### 🛑 Mutate the ISA check If the ISA cannot be mutated, **[astm.f3411.v22a.DSS0030,a](../../../../../requirements/astm/f3411/v22a.md)** is likely not implemented correctly. diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/subscription_simple.md b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/subscription_simple.md index b45f79a6ef..a0a84ef936 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/subscription_simple.md +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/v22a/dss/subscription_simple.md @@ -69,10 +69,6 @@ If the returned subscription has no owner set, **[astm.f3411.v22a.DSS0030,c](../ If the returned subscription's owner does not correspond to the uss_qualifier, **[astm.f3411.v22a.DSS0030,c](../../../../../requirements/astm/f3411/v22a.md)** is not respected. -#### 🛑 Returned notification index is 0 if present check - -The notification index of a newly created subscription must be 0, otherwise the DSS is in violation of **[astm.f3411.v22a.DSS0030,c](../../../../../requirements/astm/f3411/v22a.md)**. - #### 🛑 Returned subscription has an ISA URL check If the returned subscription has no ISA URL defined, **[astm.f3411.v22a.DSS0030,c](../../../../../requirements/astm/f3411/v22a.md)** is not respected. From 2ac3eb1c36ad0ad5829c5da261423b08e58304dd Mon Sep 17 00:00:00 2001 From: Benjamin Pelletier Date: Wed, 19 Aug 2026 21:09:49 +0000 Subject: [PATCH 3/5] `make format` --- .basedpyright/baseline.json | 48 ------------------------------------- 1 file changed, 48 deletions(-) diff --git a/.basedpyright/baseline.json b/.basedpyright/baseline.json index 5ab6c07abc..a1ea37ecff 100644 --- a/.basedpyright/baseline.json +++ b/.basedpyright/baseline.json @@ -5797,22 +5797,6 @@ "lineCount": 1 } }, - { - "code": "reportOptionalMemberAccess", - "range": { - "startColumn": 49, - "endColumn": 67, - "lineCount": 1 - } - }, - { - "code": "reportOptionalMemberAccess", - "range": { - "startColumn": 221, - "endColumn": 239, - "lineCount": 1 - } - }, { "code": "reportOperatorIssue", "range": { @@ -6125,22 +6109,6 @@ "lineCount": 1 } }, - { - "code": "reportOptionalMemberAccess", - "range": { - "startColumn": 49, - "endColumn": 67, - "lineCount": 1 - } - }, - { - "code": "reportOptionalMemberAccess", - "range": { - "startColumn": 221, - "endColumn": 239, - "lineCount": 1 - } - }, { "code": "reportOperatorIssue", "range": { @@ -6363,14 +6331,6 @@ "lineCount": 1 } }, - { - "code": "reportOptionalMemberAccess", - "range": { - "startColumn": 53, - "endColumn": 71, - "lineCount": 1 - } - }, { "code": "reportArgumentType", "range": { @@ -16965,14 +16925,6 @@ "lineCount": 1 } }, - { - "code": "reportOptionalMemberAccess", - "range": { - "startColumn": 47, - "endColumn": 65, - "lineCount": 1 - } - }, { "code": "reportArgumentType", "range": { From d8e4aab2614ae6b55ef78a2ca48bdca04e632e21 Mon Sep 17 00:00:00 2001 From: Benjamin Pelletier Date: Wed, 19 Aug 2026 20:58:03 +0000 Subject: [PATCH 4/5] Switch DSS test target to 0.23.0-rc4 with time-based notification index --- monitoring/uss_qualifier/scripts/test_docker_fully_mocked.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/monitoring/uss_qualifier/scripts/test_docker_fully_mocked.sh b/monitoring/uss_qualifier/scripts/test_docker_fully_mocked.sh index 228fd64ad8..2dd6aab9d7 100755 --- a/monitoring/uss_qualifier/scripts/test_docker_fully_mocked.sh +++ b/monitoring/uss_qualifier/scripts/test_docker_fully_mocked.sh @@ -47,6 +47,8 @@ trap on_sigint SIGINT echo "Start mock system" echo "=============" +export DSS_IMAGE="${DSS_IMAGE:-interuss/dss:v0.23.0-rc4}" +export CORE_SERVICE_EXTRA_FLAGS="${CORE_SERVICE_EXTRA_FLAGS:---enable_time_based_notification_index}" make start-locally make start-uss-mocks From 56c9f3d51071ae0b3288cf3c4947418e6fd889ff Mon Sep 17 00:00:00 2001 From: Benjamin Pelletier Date: Thu, 20 Aug 2026 06:16:19 +0000 Subject: [PATCH 5/5] Fix F3411 notification index sync check --- .basedpyright/baseline.json | 56 ------------------- .../uss_qualifier/resources/astm/dss.py | 9 +++ .../uss_qualifier/resources/astm/f3411/dss.py | 17 +++++- .../resources/astm/f3548/v21/dss.py | 6 ++ .../netrid/common/dss_interoperability.py | 36 +++++++++--- .../scenarios/astm/netrid/dss_wrapper.py | 5 ++ .../f3411/dss/DSSInstanceSpecification.json | 11 ++++ .../v21/dss/DSSInstanceSpecification.json | 11 ++++ 8 files changed, 86 insertions(+), 65 deletions(-) create mode 100644 monitoring/uss_qualifier/resources/astm/dss.py diff --git a/.basedpyright/baseline.json b/.basedpyright/baseline.json index a1ea37ecff..a24acf5878 100644 --- a/.basedpyright/baseline.json +++ b/.basedpyright/baseline.json @@ -7059,46 +7059,6 @@ "lineCount": 1 } }, - { - "code": "reportOptionalMemberAccess", - "range": { - "startColumn": 45, - "endColumn": 48, - "lineCount": 1 - } - }, - { - "code": "reportOptionalMemberAccess", - "range": { - "startColumn": 46, - "endColumn": 49, - "lineCount": 1 - } - }, - { - "code": "reportArgumentType", - "range": { - "startColumn": 28, - "endColumn": 75, - "lineCount": 1 - } - }, - { - "code": "reportOptionalMemberAccess", - "range": { - "startColumn": 53, - "endColumn": 56, - "lineCount": 1 - } - }, - { - "code": "reportOptionalMemberAccess", - "range": { - "startColumn": 51, - "endColumn": 54, - "lineCount": 1 - } - }, { "code": "reportOptionalMemberAccess", "range": { @@ -7115,14 +7075,6 @@ "lineCount": 1 } }, - { - "code": "reportArgumentType", - "range": { - "startColumn": 28, - "endColumn": 63, - "lineCount": 1 - } - }, { "code": "reportOptionalMemberAccess", "range": { @@ -7155,14 +7107,6 @@ "lineCount": 1 } }, - { - "code": "reportArgumentType", - "range": { - "startColumn": 28, - "endColumn": 61, - "lineCount": 1 - } - }, { "code": "reportOptionalMemberAccess", "range": { diff --git a/monitoring/uss_qualifier/resources/astm/dss.py b/monitoring/uss_qualifier/resources/astm/dss.py new file mode 100644 index 0000000000..617964824c --- /dev/null +++ b/monitoring/uss_qualifier/resources/astm/dss.py @@ -0,0 +1,9 @@ +from enum import StrEnum + + +class NotificationIndexImplementation(StrEnum): + ZeroBasedIncrementPerDispatch = "ZeroBasedIncrementPerDispatch" + """Notification index starts at 0 and is incremented by 1 each time a notification is requested/sent due to the associated subscription.""" + + TimedBased = "TimeBased" + """Notification index is populated based on the clock of the DSS instance serving the request.""" diff --git a/monitoring/uss_qualifier/resources/astm/f3411/dss.py b/monitoring/uss_qualifier/resources/astm/f3411/dss.py index 37fd428f5c..3767561446 100644 --- a/monitoring/uss_qualifier/resources/astm/f3411/dss.py +++ b/monitoring/uss_qualifier/resources/astm/f3411/dss.py @@ -2,12 +2,13 @@ from urllib.parse import urlparse -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.monitorlib import infrastructure from monitoring.monitorlib.infrastructure import UTMClientSession from monitoring.monitorlib.rid import RIDVersion from monitoring.uss_qualifier.reports.report import ParticipantID +from monitoring.uss_qualifier.resources.astm.dss import NotificationIndexImplementation from monitoring.uss_qualifier.resources.communications import AuthAdapterResource from monitoring.uss_qualifier.resources.resource import Resource @@ -22,6 +23,11 @@ class DSSInstanceSpecification(ImplicitDict): base_url: str """Base URL for the DSS instance according to the ASTM F3411 API appropriate to the specified rid_version""" + notification_index_implementation: Optional[NotificationIndexImplementation] + """Style of implementation this instance uses for notification index. + + If not specified, TimeBased is assumed.""" + def __init__(self, *args, **kwargs): super().__init__(**kwargs) try: @@ -35,6 +41,7 @@ class DSSInstance: rid_version: RIDVersion base_url: str client: infrastructure.UTMClientSession + notification_index_implementation: NotificationIndexImplementation def __init__( self, @@ -42,17 +49,21 @@ def __init__( base_url: str, rid_version: RIDVersion, client: UTMClientSession, + notification_index_implementation: NotificationIndexImplementation, ): self.participant_id = participant_id self.base_url = base_url self.rid_version = rid_version self.client = client + self.notification_index_implementation = notification_index_implementation def is_same_as(self, other: DSSInstance) -> bool: return ( self.participant_id == other.participant_id and self.rid_version == other.rid_version and self.base_url == other.base_url + and self.notification_index_implementation + == other.notification_index_implementation ) @@ -85,6 +96,10 @@ def __init__( infrastructure.utm_client_session_factory.get_session( specification.base_url, auth_adapter.adapter ), + specification.notification_index_implementation + if "notification_index_implementation" in specification + and specification.notification_index_implementation + else NotificationIndexImplementation.TimedBased, ) @classmethod diff --git a/monitoring/uss_qualifier/resources/astm/f3548/v21/dss.py b/monitoring/uss_qualifier/resources/astm/f3548/v21/dss.py index a8feb9b8c3..484d198fed 100644 --- a/monitoring/uss_qualifier/resources/astm/f3548/v21/dss.py +++ b/monitoring/uss_qualifier/resources/astm/f3548/v21/dss.py @@ -51,6 +51,7 @@ from monitoring.monitorlib.inspection import calling_function_name, fullname from monitoring.monitorlib.mutate import scd as mutate from monitoring.monitorlib.mutate.scd import MutatedSubscription +from monitoring.uss_qualifier.resources.astm.dss import NotificationIndexImplementation from monitoring.uss_qualifier.resources.communications import AuthAdapterResource from monitoring.uss_qualifier.resources.resource import Resource @@ -71,6 +72,11 @@ class DSSInstanceSpecification(ImplicitDict): timeout_seconds: Optional[float] """If specified, number of seconds to allow before timing out requests to this DSS instance.""" + notification_index_implementation: Optional[NotificationIndexImplementation] + """Style of implementation this instance uses for notification index. + + If not specified, TimeBased is assumed.""" + def __init__(self, *args, **kwargs): super().__init__(**kwargs) try: diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss_interoperability.py b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss_interoperability.py index c5793f39c9..6ba53cbf2a 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss_interoperability.py +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/common/dss_interoperability.py @@ -11,6 +11,7 @@ from monitoring.monitorlib.fetch.rid import ISA from monitoring.monitorlib.geo import get_latlngrect_vertices, make_latlng_rect from monitoring.uss_qualifier.resources import PlanningAreaResource +from monitoring.uss_qualifier.resources.astm.dss import NotificationIndexImplementation from monitoring.uss_qualifier.resources.astm.f3411.dss import ( DSSInstanceResource, DSSInstancesResource, @@ -308,7 +309,7 @@ def step3(self): # check data synchronization def get_fail_params( field_name: str, - primary_sub_field_value: str, + primary_sub_field_value: object, other_sub_field_value: object, ) -> dict: return dict( @@ -371,16 +372,35 @@ def get_fail_params( [dss.participant_id], ) as check: if ( - primary_sub.subscription.raw.notification_index - != other_sub.subscription.raw.notification_index + dss.notification_index_implementation + != self._dss_primary.notification_index_implementation ): check.record_failed( - **get_fail_params( - "notification_index", - primary_sub.subscription.raw.notification_index, - other_sub.subscription.raw.notification_index, - ) + summary="Incompatible notification index implementations", + details=f"All DSS instances in a pool must use the same notification index implementation to achieve synchronized notification count behavior, but DSS for {dss.participant_id} uses {dss.notification_index_implementation.value} while DSS for {self._dss_primary.participant_id} uses {self._dss_primary.notification_index_implementation.value}", + ) + elif ( + dss.notification_index_implementation + == NotificationIndexImplementation.ZeroBasedIncrementPerDispatch + ): + primary_index = ( + primary_sub.subscription.raw.notification_index + if primary_sub.subscription + and primary_sub.subscription.raw.notification_index + else 0 ) + other_index = ( + other_sub.subscription.raw.notification_index + if other_sub.subscription + and other_sub.subscription.raw.notification_index + else 0 + ) + if primary_index != other_index: + check.record_failed( + **get_fail_params( + "notification_index", primary_index, other_index + ) + ) with self.check( "Subscription[P] start/end times are properly synchronized with all DSS", diff --git a/monitoring/uss_qualifier/scenarios/astm/netrid/dss_wrapper.py b/monitoring/uss_qualifier/scenarios/astm/netrid/dss_wrapper.py index d1f64dd9d3..7a1ab1018a 100644 --- a/monitoring/uss_qualifier/scenarios/astm/netrid/dss_wrapper.py +++ b/monitoring/uss_qualifier/scenarios/astm/netrid/dss_wrapper.py @@ -22,6 +22,7 @@ from monitoring.monitorlib.mutate import rid as mutate from monitoring.monitorlib.mutate.rid import ChangedSubscription, ISAChange from monitoring.monitorlib.rid import RIDVersion +from monitoring.uss_qualifier.resources.astm.dss import NotificationIndexImplementation from monitoring.uss_qualifier.resources.astm.f3411.dss import DSSInstance from monitoring.uss_qualifier.scenarios.astm.netrid.common.dss.isa_validator import ( ISAValidator, @@ -55,6 +56,10 @@ def participant_id(self) -> str: def base_url(self) -> str: return self._dss.base_url + @property + def notification_index_implementation(self) -> NotificationIndexImplementation: + return self._dss.notification_index_implementation + # TODO: QueryError is not actually raised for RID functions, this function and its uses should be removed def _handle_query_error( self, diff --git a/schemas/monitoring/uss_qualifier/resources/astm/f3411/dss/DSSInstanceSpecification.json b/schemas/monitoring/uss_qualifier/resources/astm/f3411/dss/DSSInstanceSpecification.json index 61ca3a0186..9a7903d048 100644 --- a/schemas/monitoring/uss_qualifier/resources/astm/f3411/dss/DSSInstanceSpecification.json +++ b/schemas/monitoring/uss_qualifier/resources/astm/f3411/dss/DSSInstanceSpecification.json @@ -11,6 +11,17 @@ "description": "Base URL for the DSS instance according to the ASTM F3411 API appropriate to the specified rid_version", "type": "string" }, + "notification_index_implementation": { + "description": "Style of implementation this instance uses for notification index.\n\nIf not specified, TimeBased is assumed.", + "enum": [ + "ZeroBasedIncrementPerDispatch", + "TimeBased" + ], + "type": [ + "string", + "null" + ] + }, "participant_id": { "description": "ID of the USS responsible for this DSS instance", "type": "string" diff --git a/schemas/monitoring/uss_qualifier/resources/astm/f3548/v21/dss/DSSInstanceSpecification.json b/schemas/monitoring/uss_qualifier/resources/astm/f3548/v21/dss/DSSInstanceSpecification.json index 6712a3a77c..456c52a7ab 100644 --- a/schemas/monitoring/uss_qualifier/resources/astm/f3548/v21/dss/DSSInstanceSpecification.json +++ b/schemas/monitoring/uss_qualifier/resources/astm/f3548/v21/dss/DSSInstanceSpecification.json @@ -11,6 +11,17 @@ "description": "Base URL for the DSS instance according to the ASTM F3548-21 API", "type": "string" }, + "notification_index_implementation": { + "description": "Style of implementation this instance uses for notification index.\n\nIf not specified, TimeBased is assumed.", + "enum": [ + "ZeroBasedIncrementPerDispatch", + "TimeBased" + ], + "type": [ + "string", + "null" + ] + }, "participant_id": { "description": "ID of the USS responsible for this DSS instance", "type": "string"