Commit 05365df9 authored by Dimitrios Gogos's avatar Dimitrios Gogos
Browse files

feat: refactor service specification ID handling for QoD and Location Retrieval

parent a84df597
Loading
Loading
Loading
Loading
+21 −13
Original line number Diff line number Diff line
from functools import lru_cache
from uuid import UUID
from uuid import UUID, uuid5

from pydantic import BaseModel, HttpUrl
from pydantic_settings import BaseSettings, SettingsConfigDict

# The platform seeds one QoD service specification at deployment (ADR-0035); every
# activate carries its id. There is no CAMARA registration step to resolve it from,
# so the id cannot be derived per request -- minting one would reference no catalog
# row and SRM would answer failed_before_start. This is the well-known id used when
# nobody sets one at deploy time; SRM's topology bootstrap must seed the same value.
# QoD and Location Retrieval have no CAMARA registration step to resolve a
# service_specification_id from, so each uses one platform-seeded specification at a
# well-known id (ADR-0035). Both sides derive that id from the recipe in SRM Interface
# Contract §E.2 rather than pasting a constant, so neither can go stale if the recipe
# changes; SRM's bootstrap seeds the same value.

DEFAULT_QOD_SERVICE_SPECIFICATION_ID = UUID("7608e902-b927-559f-b448-e7e9061dfa5c")
_SPECIFICATION_VERSION = "1"
_NAMESPACE_URL = UUID("6ba7b811-9dad-11d1-80b4-00c04fd430c8")

# Location Retrieval has no registration step either, so it resolves its
# service_specification_id the same way (ADR-0035's pattern applied to a second family).
# It persists nothing -- a sync query writes no service_order or capability_instance --
# but the internal query body still requires the field, and SRM uses it to resolve the
# control path for the location_context capability.
DEFAULT_LOCATION_RETRIEVAL_SERVICE_SPECIFICATION_ID = UUID("0129e7ce-8e02-5dfd-bae1-0303bcc7676e")

def well_known_service_specification_id(ref: str) -> UUID:
    return uuid5(
        _NAMESPACE_URL,
        f"https://etsi.org/sdg/oop/service-specification/{ref}/{_SPECIFICATION_VERSION}",
    )


DEFAULT_QOD_SERVICE_SPECIFICATION_ID = well_known_service_specification_id("qod-session")

DEFAULT_LOCATION_RETRIEVAL_SERVICE_SPECIFICATION_ID = well_known_service_specification_id(
    "location-context"
)


class SRMSettings(BaseModel):
+13 −15
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ from open_exposure_gateway.core.config import (
    DEFAULT_QOD_SERVICE_SPECIFICATION_ID,
    Settings,
    get_settings,
    well_known_service_specification_id,
)


@@ -93,23 +94,20 @@ class TestDefaults:
        assert settings.location_retrieval_settings.uses_default_service_specification_id is True


class TestWellKnownQodServiceSpecificationId:
    def test_constant_matches_its_documented_derivation(self) -> None:
        """The default is a cross-component contract: SRM's bootstrap must seed this
        exact id. Both sides derive it from the same URL rather than copying a literal,
        so this pins the recipe -- changing the constant without changing the URL (or
        the reverse) is a silent break that only shows up as failed_before_start."""
        assert DEFAULT_QOD_SERVICE_SPECIFICATION_ID == uuid5(
            NAMESPACE_URL, "https://etsi.org/sdg/oop/service-specification/qod-session/1"
        )
class TestWellKnownServiceSpecificationIds:
    """The ids are derived, so the literals live here rather than in src"""

    def test_qod_matches_the_published_id(self) -> None:
        assert DEFAULT_QOD_SERVICE_SPECIFICATION_ID == UUID("7608e902-b927-559f-b448-e7e9061dfa5c")

class TestWellKnownLocationRetrievalServiceSpecificationId:
    def test_constant_matches_its_documented_derivation(self) -> None:
        """Same cross-component contract as the QoD id, same recipe -- only the `ref`
        differs. Pinning it here is what stops the two sides drifting apart silently."""
        assert DEFAULT_LOCATION_RETRIEVAL_SERVICE_SPECIFICATION_ID == uuid5(
            NAMESPACE_URL, "https://etsi.org/sdg/oop/service-specification/location-context/1"
    def test_location_retrieval_matches_the_published_id(self) -> None:
        assert DEFAULT_LOCATION_RETRIEVAL_SERVICE_SPECIFICATION_ID == UUID(
            "0129e7ce-8e02-5dfd-bae1-0303bcc7676e"
        )

    def test_the_recipe_is_the_documented_url(self) -> None:
        assert well_known_service_specification_id("qod-session") == uuid5(
            NAMESPACE_URL, "https://etsi.org/sdg/oop/service-specification/qod-session/1"
        )