* api: drop the MessagePack hub protocol
* sync: fetch items in size-bounded chunks and send them as stored
* sync: label fetch failures by reason and log rejected connections at info
* sync: count rejected connections and cover fetch failure reasons and mid-fetch resets
Rejections are logged at Information, which production filters out, so a
counter by stage is what shows them. Also drops a catch around the no-op
Hub.OnDisconnectedAsync.
Identity already ran on driver 3.x through AspNetCore.Identity.Mongo 10.1.0 and Streetwriters.IdentityServer4.Contrib.MongoDB 5.0.0, while Streetwriters.Data and Streetwriters.Common were built against 2.30, so shared code could hit APIs removed in 3.0 at runtime in Identity only. Every project now uses 3.12.
- MongoDB.Driver.Core is part of MongoDB.Driver in 3.x
- AspNetCore.Identity.Mongo 10.1.0 in Common, matching Identity, which needs Microsoft.Extensions.DependencyInjection 9.0.2
- AspNetCore.HealthChecks.MongoDb 9.0.0, built against driver 3.x
- tests use EphemeralMongo 3.2, as EphemeralMongo8 2.0 is built against driver 2.x; it no longer stops mongod on exit, so the Identity tests now dispose their runner like the API tests do
Identity publishes ClearCache to a service's WAMP address, which reaches only one replica, so a revoked token stayed valid on the others for up to 30 minutes. With CACHE_REDIS_CONNECTION_STRING set, the replica that receives it publishes the keys on Redis and every replica removes them from its in-memory cache. The cache itself stays in memory so a Redis outage doesn't affect authentication; without Redis, only the receiving instance is cleared, as before.
MinioFixture starts a MinIO-compatible server in Docker with Testcontainers (Silo, since MinIO no longer publishes images) and points S3Clients at it. S3ServiceTests cover signed uploads and object sizes, deleting an object and a user's directory, and multipart uploads within and past the storage limit. The interface stub moves out of ApiErrorResponseTests so both can use it. Running the tests now needs Docker.
Controllers no longer catch everything and return ex.Message as a 400, which leaked internal messages and made outages look like client errors. User-facing errors are now ClientExceptions; everything else is a generic 500 or a 503. S3 failover throws S3StorageUnavailableException when every endpoint fails transiently.
Deleting an account checks the password first, since Identity's "Wrong password." only arrived as a WAMP runtime error. Inbox API key checks no longer turn database errors into 401s. Monograph sanitization fails closed instead of storing unsanitized content, and an unreachable WebRisk counts as safe, like an error response already did.