Commit f817d9a8 authored by George Papathanail's avatar George Papathanail
Browse files

feat: thread subject_id toward Location Retrieval's device derivation

CallerContext.subject_id now flows through to
LocationRetrievalService.retrieve_location, which falls back to a new
_device_from_subject hook when the request omits . Left as an
explicit no-op for now: a three-legged token's  is a Keycloak user
id, not a network identifier CAMARA's Device schema can hold, and there's
no claim yet that carries one -- guessing wrong here means locating the
wrong person, so omitting  still 422s until that claim exists.
parent cefbe873
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -81,5 +81,6 @@ async def retrieve_location(
    return await service.retrieve_location(
        request=request,
        app_provider_id=caller.app_provider_id,
        subject_id=caller.subject_id,
        x_correlator=caller.x_correlator,
    )
+20 −3
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ from uuid import UUID, uuid4
import structlog

from open_exposure_gateway.api.camara.location_retrieval.v0_5_0.schemas import (
    Device,
    Location,
    RetrievalLocationRequest,
)
@@ -37,9 +38,11 @@ class LocationRetrievalService:
        self,
        request: RetrievalLocationRequest,
        app_provider_id: str,
        subject_id: Optional[str] = None,
        x_correlator: Optional[str] = None,
    ) -> Location:
        if request.device is None:
        device = request.device or self._device_from_subject(subject_id)
        if device is None:
            raise UnprocessableEntityException(
                error_code=ErrorCode.MISSING_IDENTIFIER,
                message="The device cannot be identified.",
@@ -48,7 +51,7 @@ class LocationRetrievalService:
        correlation_id = x_correlator or str(uuid4())
        query = build_location_query(
            request=request,
            device=request.device,
            device=device,
            correlation_id=correlation_id,
            app_provider_id=app_provider_id,
            service_specification_id=self._service_specification_id,
@@ -60,7 +63,7 @@ class LocationRetrievalService:
        )

        try:
            return build_location(result, request.device)
            return build_location(result, device)
        except ValueError as exc:
            logger.error(
                "srm_location_result_malformed",
@@ -71,3 +74,17 @@ class LocationRetrievalService:
                message="SRM returned an unusable location",
                details=str(exc),
            ) from exc

    def _device_from_subject(self, subject_id: Optional[str]) -> Optional[Device]:
        """Derives `device` from a three-legged token's subject when the caller
        omits it, per CAMARA's own optionality rule for this field (closes
        architecture.md F4). Deliberately a no-op for now: `subject_id` is
        currently the token's raw `sub` -- a Keycloak user id -- not a network
        identifier CAMARA's Device schema can hold (phone number, IP, etc.).
        There is no such claim on a three-legged token yet. Wire this up once
        the subscriber-consent flow defines a real claim to derive a Device
        from; until then, omitting `device` correctly still 422s instead of
        silently guessing -- and guessing wrong here means locating the wrong
        person, so this must stay a hard no until that claim exists.
        """
        return None