using System.Text.Json.Nodes; namespace backend.Realtime; public interface IRealtimeUpstream : IAsyncDisposable { Task SendJsonAsync(JsonObject envelope, CancellationToken ct); Task ReceiveJsonAsync(CancellationToken ct); // Once a receive returns null because the WebSocket transitioned out of // the Open state, these surface why. Both stay null until that happens. bool IsClosed { get; } string? CloseReason { get; } }