Source code for cadrumo.application.auth.protocols
"""Protocol definitions for the application-layer auth session boundary.These protocols declare the interface the application layer depends on forpersisted auth session management. Concrete implementations live in theadapter layer (adapters/outbound/aeat/auth/session_store.py) and satisfythese protocols structurally.:class:`SessionStoreProtocol` returns :class:`PersistedSessionDataProtocol`records to the persisted-session service."""from__future__importannotationsfromcollections.abcimportGenerator,MappingfromcontextlibimportcontextmanagerfromcontextvarsimportContextVarfrompathlibimportPathfromtypingimportTYPE_CHECKING,Protocol,TypedDict,runtime_checkablefrom...core.errors.hierarchyimportInternalInvariantErrorifTYPE_CHECKING:from...core.configimportSettings
[docs]@runtime_checkableclassBrowserResponsePort(Protocol):"""Minimal response surface needed to classify an authentication probe."""@propertydefok(self)->bool:"""Whether the browser classified the response as successful."""...@propertydefstatus(self)->int:"""HTTP status observed by the browser."""...
[docs]@runtime_checkableclassBrowserPagePort(Protocol):"""Minimal page surface consumed by authentication providers."""@propertydefurl(self)->str:"""Final page URL after redirects."""...
[docs]asyncdefgoto(self,url:str,*,timeout:float|None=None,)->BrowserResponsePort|None:"""Navigate to ``url`` and return its response, if any."""...
[docs]asyncdefclick(self,selector:str)->None:"""Click one selector while driving an authentication flow."""...
[docs]asyncdefclose(self)->None:"""Close the page after the authentication probe completes."""...
[docs]classBrowserContextKwargs(TypedDict,total=False):"""Subset of Playwright ``Browser.new_context()`` keyword arguments. Only the kwargs that AEAT auth provisioners currently supply are declared here. ``total=False`` makes every key optional so callers can return a partial mapping. """client_certificates:list[dict[str,str|bytes]]
[docs]@runtime_checkableclassBrowserContextProvisioner(Protocol):"""Hook that decorates browser-context creation for auth providers. Concrete outbound auth provisioners implement this protocol to add Playwright ``new_context()`` kwargs. """
[docs]defbuild_context_kwargs(self)->BrowserContextKwargs:"""Return the provider-owned browser context arguments."""...
[docs]@runtime_checkableclassBrowserContextPort(Protocol):"""Minimal browser context used by authentication providers."""
[docs]asyncdefnew_page(self)->BrowserPagePort:"""Create a page for a live verification flow."""...
[docs]asyncdefstorage_state(self)->Mapping[str,object]:"""Return the in-memory browser storage state."""...
[docs]asyncdefclose(self)->None:"""Close the context during provider teardown."""...
[docs]@runtime_checkableclassBrowserSessionPort(Protocol):"""Browser lifecycle required by concrete authentication providers."""
[docs]asyncdefcreate_context(self,*,provisioner:BrowserContextProvisioner|None=None,storage_state:Mapping[str,object]|None=None,)->BrowserContextPort:"""Create a context with optional provider or persisted state."""...
[docs]asyncdefclose(self)->None:"""Close the owned browser process."""...
[docs]classBrowserSessionFactoryPort(Protocol):"""Async browser-session constructor accepted by auth composition."""asyncdef__call__(self,settings:Settings)->BrowserSessionPort:"""Create the concrete outbound browser session for ``settings``."""...
[docs]@runtime_checkableclassPersistedSessionDataProtocol(Protocol):"""Minimal surface the application layer reads from a persisted session record."""@propertydefstorage_state(self)->Mapping[str,object]:"""Playwright browser storage state for the persisted session."""...@propertydefmetadata(self)->Mapping[str,object]:"""Provider-specific session metadata."""...
[docs]@runtime_checkableclassSessionStoreProtocol(Protocol):"""Structural interface for the persisted browser session store. The application layer depends on this protocol rather than the concrete adapter module so that application/auth/sessions.py does not carry a direct import from adapters/outbound/aeat/auth/session_store.py. """
[docs]defexists(self,path:Path)->bool:"""Return whether a session is persisted at logical ``path``."""...
[docs]defload(self,path:Path)->PersistedSessionDataProtocol|None:"""Load persisted session data for ``path``. Returns a :class:`PersistedSessionDataProtocol`, or ``None`` when absent. """...
[docs]defdelete(self,path:Path)->bool:"""Delete persisted session data at ``path``, returning True when removed."""...
[docs]@contextmanagerdefbind_session_store(store:SessionStoreProtocol)->Generator[SessionStoreProtocol]:"""Bind the encrypted outbound session store for one runtime scope."""token=_BOUND_SESSION_STORE.set(store)try:yieldstorefinally:_BOUND_SESSION_STORE.reset(token)
[docs]defsession_store()->SessionStoreProtocol:"""Return the session store installed by outward composition."""try:return_BOUND_SESSION_STORE.get()exceptLookupErrorasexc:raiseInternalInvariantError("AEAT authentication session-store composition is not bound")fromexc