Source code for cadrumo.adapters.outbound.aeat.auth.clave_movil_metadata

"""Cl@ve Móvil persisted-session metadata records.

:class:`adapters.outbound.aeat.auth.clave_movil.ClaveMovilAuthProvider` stores
:class:`ClaveMovilSessionMetadata` inside the encrypted
:class:`adapters.outbound.aeat.auth.session_store.PersistedBrowserSession`
metadata mapping. The record binds the Playwright storage state to the
operator identity, post-auth landing URL, verification code, and resume
deadline observed during the human-in-the-loop login flow.

Application callers later narrow this provider-owned shape to the common
:class:`application.auth.sessions.PersistedAuthSession` reuse contract.
"""

from __future__ import annotations

from datetime import datetime
from typing import Final

from pydantic import BaseModel, Field

from .....core.auth_provider import AuthProviderKind
from .....core.identity.digest import ContentDigest
from .....core.models import STRICT_FROZEN_CONFIG

AEAT_CLAVE_MOVIL_METADATA_SCHEMA_VERSION: Final[int] = 2
"""Schema version for Cl@ve Móvil :class:`ClaveMovilSessionMetadata` records."""


[docs] class ClaveMovilSessionMetadata(BaseModel): """Provider-owned metadata stored with encrypted Cl@ve Móvil storage state. ``provider_kind`` keeps the encrypted object distinguishable from certificate-auth metadata. ``storage_state_sha256`` lets resume paths reject stale or mismatched browser state, while ``landing_url`` lets live probes verify an already-authenticated page without re-entering AEAT's Cl@ve selector. The same operational fields are projected into :class:`~application.auth.session_types.ClaveMovilSessionDetail` when a session is rebuilt. """ model_config = STRICT_FROZEN_CONFIG schema_version: int = Field(default=AEAT_CLAVE_MOVIL_METADATA_SCHEMA_VERSION, ge=2) provider_kind: AuthProviderKind = AuthProviderKind.CLAVE_MOVIL identity_nif: str = Field(min_length=1) authenticated_at: datetime idle_deadline: datetime storage_state_sha256: ContentDigest used_non_qr_fallback: bool = False verification_code: str | None = None landing_url: str | None = Field( default=None, description=( "Concrete URL Playwright observed after AEAT dispatched the " "successful login. " "Used as the probe target by auth-session readiness checks because AEAT's " "Cl@ve selector page is a static dispatch page that always returns 200 " "regardless of auth state." ), )
__all__ = [ "AEAT_CLAVE_MOVIL_METADATA_SCHEMA_VERSION", "ClaveMovilSessionMetadata", ]