"""ЕМИАС sign-in mock for the patient web app (SPEC §9 `esia_mock`: registration by the doctor's code). Real ЕМИАС / ЕСИА OAuth needs a registered information system, so the prototype accepts the one-time connect code the doctor hands out after the visit (323-FZ art. 36.2): code → patient token + attending doctor. The class implements `IdentityProvider`, so the real OAuth client replaces it without touching the web channel. It is deliberately NOT installed into `integrations.identity`: the Telegram channel verifies a code twice (on `/start` and in the core flow), which a one-time redeeming provider would break. Lane B wires the production provider for all channels (#14). This module may use the identity DB: it is the registration boundary (guardrail #5). """ from app.core import clock from app.db import identity_repo from app.db.identity import ConnectCode from app.db.session import get_identity_session from app.integrations.base import VerifiedPerson CODE_MAX_LEN = 32 class EmiasMock: async def verify(self, auth_code: str) -> VerifiedPerson | None: code = auth_code.strip().upper() if not code or len(code) > CODE_MAX_LEN: return None async with get_identity_session() as s: row = await s.get(ConnectCode, code) if row is None: return None token = await identity_repo.redeem_connect_code(s, code=code, now=clock.now()) if token is None: return None return VerifiedPerson(token=token, doctor_id=row.doctor_id)