namespace DeepDrftPublic.Client.Services; /// /// Supplies the client-minted anonymous listener id (Phase 16 §3, wave 16.3, D5 Option A) to the /// fire-and-forget telemetry sinks. The id is a random first-party localStorage GUID — opaque, no /// PII, no fingerprinting, clearable. Split into an async warm () and a /// synchronous read () so the existing sync emit paths (the beacon sink, the share /// tracker) need no async signature change: a caller warms the cache when it goes interactive, and the /// emit then reads the cached value with no JS round-trip on the close/unload path. /// /// /// Degrades to null when localStorage is unavailable (private mode / blocked / partitioned /// third-party iframe) — the sink then omits the id and sends an anonId-less event. Over-counting is the /// accepted direction of error (§3); a missing id never throws. /// /// public interface IAnonIdProvider { /// /// The cached anon id, or null if not yet warmed or if storage is unavailable. Synchronous and safe /// to read from the player close path and the page-unload handler, neither of which can await. /// string? Current { get; } /// /// Warm the cache from localStorage via JS interop (minting on first visit). Idempotent — only /// the first successful read populates the cache; later calls are no-ops. Best-effort: a JS failure /// (interop unavailable during prerender, storage blocked) leaves null and never /// throws. /// ValueTask EnsureLoadedAsync(); }