"""Torch-free application services shared between the model-heavy dependency layer and the lightweight routers. Importing this module never pulls torch or the biometric models, so the notification/OOB router (and its API tests) stay torch-free. The `notifications` singleton IS the instance the full app uses (ModelState.notify references it), so production and tests share one service + state. Persistence and audit are optional hooks the full app wires at startup; they no-op when unwired (e.g. in the light CI test app), matching the demo store's behavior.""" from __future__ import annotations from typing import Callable, Optional from amanpay.notifications.service import NotificationService # Single shared notification/OOB service (referenced by ModelState.notify). notifications = NotificationService() _persist: Optional[Callable[[], None]] = None _audit: Optional[Callable[[str, str, dict], None]] = None def wire(persist: Optional[Callable[[], None]] = None, audit: Optional[Callable[[str, str, dict], None]] = None) -> None: """Wire durable-persistence and audit callbacks from the full app (torch side).""" global _persist, _audit _persist = persist _audit = audit def persist_prefs() -> None: if _persist is not None: _persist() def audit_event(user_id: str, action: str, detail: dict) -> None: if _audit is not None: _audit(user_id, action, detail)