Changelog
All notable changes to SignalARRR will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[4.3.2]
Security
- MessagePack downgraded from 3.1.4 to 2.5.301 to patch CVE-2026-48109 / GHSA-hv8m-jj95-wg3x (high-severity LZ4 decompression out-of-bounds read / DoS), which was failing the build via NuGet audit. 2.5.x is the MessagePack line that
Microsoft.AspNetCore.SignalR.Protocols.MessagePackruns on (through .NET 10), so consumers using the SignalR MessagePack hub protocol are no longer forced onto a cross-major MessagePack version. No functional change — only basic serialization APIs are used.
[4.3.1]
Fixed
- Fire-and-forget
sendserver methods silently did nothing (e.g. group joins):HARRR.SendMessageran the target method in a detachedTask.Runafter SignalR had already disposed theHub, so any access to the hub-injectedContext/Clients/Groups(such asGroups.AddToGroupAsync) silently failed and the method body never took effect. The method is now awaited within the hub invocation, keeping theHubalive for its duration. Affects every client — the typed proxy routes anyvoid/Task-returning server method through thissendpath, so this was hit without explicitly choosingsend. - (Swift) Negotiate/WebSocket URL broke when the hub URL carried a query string: both the negotiate URL and the WebSocket transport URL were built by string concatenation, producing a broken URL like
.../hub/sync?user=x?id=...(HTTP 400 on negotiate). Rebuilt withURLComponentsso existing query parameters are preserved and/negotiateis inserted into the path. - (Swift) Connection hung ~30s against
localhost/IPv6: whenlocalhostresolved to IPv6 (::1) against an IPv4-only server there was no Happy-Eyeballs fallback for the WebSocket upgrade. Negotiate now fast-fails on a configurable timeout instead of waiting on the OS connect timeout, and the127.0.0.1workaround is documented.
Changed
- (Swift) Undispatched server→client calls now log instead of failing silently: mirrors the .NET client. When a server→client call arrives for which no handler is registered, the client logs a warning pointing to
onServerMethod(...)— the most common cause is registering a SignalARRR contract withon(...)(which only handles raw SignalR events). Theon(...)vsonServerMethod(...)distinction is now documented on both APIs.
Added
- Regression tests: a .NET integration test proving a
send-routed server method joins a group against a liveHub(fails on the old fire-and-forget behaviour), and Swift unit tests covering query-string-safe transport URL construction.
[4.3.0]
Added
- Redis-compatible cluster backplane: multi-node SignalARRR deployments can now route typed server-to-client traffic through Redis-compatible infrastructure such as Redis, Valkey, or Garnet.
- Distributed query support: cluster-wide broadcast, user targeting, attribute targeting, remote group management, and cross-node
InvokeAllAsync/InvokeOneAsync. - Cluster presence snapshots:
ClientManagercan now report cluster-wide connections, groups, attributes, and online users. - Crash cleanup + hardening tests: added active stale-node cleanup and new multi-node tests for reconnect, remote group leave, ordered cross-node push delivery, and crash recovery.
Documentation
- Added backplane and cluster semantics documentation for server deployments.
[4.2.2]
Fixed
- Server-to-Client push crash with null arguments:
nullarguments for reference type parameters (e.g.,string?) crashed the client's message dispatcher silently — the root cause of server-to-client push failures when using typed proxies. - Silent error swallowing in client message handler: Replaced
catch { // ignored }withILogger.LogError()so developers can diagnose failed server-to-client pushes.
Added
- 4 new server-to-client push integration tests: Cross-assembly tests covering fire-and-forget push, invoke with return value, null parameter handling, and multi-client broadcast.
[4.2.1]
Fixed
- Source Generator not included in NuGet packages: The generator DLL was never bundled in NuGet packages — it only worked with local project references. Fixed by shipping it in the Server and Client packages.
- Source Generator now ships in Server and Client packages: Consumer projects get proxy generation automatically by referencing Server or Client — no extra package reference needed.
Contractsremains attribute-only (no generator).
[4.2.0]
Added
- Transport-Level Authentication: Support for client certificates (mTLS), cookies, and Windows/Negotiate authentication alongside existing token-based auth. The server auto-detects the authentication mode per client and re-validates transport credentials server-side when the auth cache expires — no challenge round-trip needed.
AuthenticationModeenum:None,MessageLevel,TransportLevel— exposed onClientContext.AuthModefor per-client auth mode inspectionClientContext.ClientCertificate: Stores the client certificate from the TLS handshake for server-side re-validationITransportAuthRevalidationService: Pluggable interface for custom transport-auth re-validation logic (e.g., custom CRL endpoints, OCSP stapling, session store checks)DefaultTransportAuthRevalidationService: Built-in implementation with certificate expiry checks, X509 chain validation (CRL/OCSP), and custom validator callback support- Certificate validation options:
WithCertificateRevocationCheck(bool),WithCertificateRevocationMode(X509RevocationMode),WithCustomCertificateValidator(Func<X509Certificate2, bool>)onSignalARRRServerOptionsBuilder - Mixed-mode authentication: A single hub can serve both token-based and certificate-based clients simultaneously
- Certificate refresh on reconnect:
ClientContextupdates transport credentials (cert + principal) when a client reconnects with a new certificate - 9 new integration tests for transport-level auth: cert auth, auto-detection, cache expiry with server-side re-validation, expired cert rejection, AllowAnonymous bypass, and mixed-mode scenarios
Fixed
- Source Generator cross-assembly discovery: The Source Generator now discovers
[SignalARRRContract]interfaces in referenced assemblies (not just in the current compilation's source code). This fixes the common scenario where contract interfaces are defined in a shared library and referenced by server/client projects. The generator only scans assemblies that referenceCocoar.SignalARRR.Contracts, avoiding unnecessary work.
[4.1.0]
Added
- Multi-targeting: All library packages now support
net8.0,net9.0, andnet10.0 Cocoar.SignalARRR.Client.FullFramework: New client package targetingnetstandard2.0for .NET Framework 4.6.2+ — typed proxies viaDispatchProxy, streaming (via polyfills), server-to-client RPC, cancellation, file transfer, and optional MessagePack- Framework-conditional package versions: ASP.NET Core packages resolve to the correct version per target framework, preventing transitive version conflicts
- CI matrix testing: PR validation now tests on .NET 8, 9, and 10 across all platforms
- Typed broadcasts:
WithHub<T>().WithGroup().SendAsync<T>()— chainable LINQ-style API for typed fire-and-forget sends to groups, filtered clients, and all clients. Groups tracked inClientContext.Groupsand synced with SignalR. - Typed multi-client invoke:
InvokeAllAsync<T, TResult>()(parallel, all results) andInvokeOneAsync<T, TResult>()(first responder wins) onIEnumerable<ClientContext>
Changed
- MessagePack is now optional: Install
Microsoft.AspNetCore.SignalR.Protocols.MessagePackseparately and call.AddMessagePackProtocol()when needed Cocoar.SignalARRR.Commonnow also targetsnetstandard2.0
Fixed
- SignalR 10.0.5 compatibility:
InvokeServerMessagehandler now properly awaits async operations npm versionin CI: Added--allow-same-versionflag
[4.0.0]
Breaking Changes
- Target framework changed from
netstandard2.0tonet10.0 ImpromptuInterfaceremoved — replaced by source-generated proxies and opt-inDispatchProxyfallback- Proxy creation now requires
[SignalARRRContract]attribute on interfaces (or referenceCocoar.SignalARRR.DynamicProxyfor runtime fallback) - Custom
IAuthenticatorinterface removed — use ASP.NET Core authentication handlers and[Authorize]policies instead - HTTP Proxy pass-through feature removed (deferred to Phase 2)
netstandard2.0target dropped — all packages now targetnet10.0(except SourceGenerator which targetsnetstandard2.0per Roslyn requirements)- Hub-level
[Authorize]inheritance restored: if the Hub class has[Authorize], ServerMethods classes inherit it automatically (behavior change from v2.x where this was disabled)
Added
- Source Generator: Compile-time proxy generation from
[SignalARRRContract]interfaces — zero reflection, AOT-friendly Cocoar.SignalARRR.Contracts: Single-reference meta-package for shared interface projects (attribute + generator + ProxyGenerator)Cocoar.SignalARRR.DynamicProxy: Opt-inDispatchProxy-based runtime fallback for plugin/dynamic scenarios- CancellationToken server-to-client propagation: Server can pass
CancellationTokento client methods and cancel remotely ServerProxyCreatorHelper.StreamAsync<T>: Server can requestIAsyncEnumerable<T>streams from client methodsServerStreamManager: Channel-based stream correlation for server-initiated client streamsStreamItemToServer/StreamCompleteToServerhub methods for client-to-server stream item deliveryClientManagertyped extensions:GetTypedMethods<T>(connectionId)for server-to-client RPC from outside hub context- Authorization integration tests: Tests for authenticated calls, unauthenticated rejection, and hub-level auth inheritance
TreatWarningsAsErrors: Enabled globally viaDirectory.Build.props
Removed
ImpromptuInterfacedependencynetstandard2.0target / polyfill packages (Microsoft.Bcl.AsyncInterfaces,System.Threading.Channels, etc.)SignalARRRDynamicProxy.csandStreamingType.csfrom ProxyGenerator (replaced by DispatchProxy package)- Non-generic
Invoke(Type returnType, ...)overloads fromClientProxyCreatorHelperandServerProxyCreatorHelper - Old
RegisterMethodsclient-side registration API (replaced byRegisterInterface) - Custom
IAuthenticatorinterface andTryAuthenticate/SetAuthDataonClientContext
[2.1.2] - Previous Release
Features
- Split hub methods across multiple classes via
ServerMethods<T> - Method-level authorization with
[Authorize]attribute - Continuous token validation with automatic challenge/refresh
- Server-to-client RPC with response awaiting
- Support for
IObservable<T>,IAsyncEnumerable<T>, andChannelReader<T>streaming - Type-safe client proxies from interfaces
- Multi-platform support (Server, .NET Client, TypeScript Client)