* sync: keep pushed ciphers as UTF-8 from the hub to MongoDB
Pushed ciphers were parsed into strings, then encoded back to UTF-8 by
the driver into a new buffer for each large one: the two largest
sources of large object heap allocations on prod.
PushItems now reads each cipher straight into a pooled UTF-8 buffer and
UpsertMany writes the item's BSON itself, from that buffer, into another
pooled one. The stored documents are unchanged. Validation moves to
SyncItemValidator, and the base64 check is vectorized.
* sync: hand back pushed buffers when a push is rejected
The hub disposed the pushed items only after its own checks, and the
authorization filter rejects a call after SignalR has bound it, so those
rejections left their pooled buffers to the GC. A push with null items
also made the cleanup throw over the real error.
Registering a device inserted a new document every time, so concurrent registrations (two first fetches at once) left duplicate devices, and one stuck with IsSyncReset=true full-synced on every fetch. Registration is now an upsert on UserId + DeviceId; registering an existing device resets it to a full sync.
Signup ignores a duplicate-key error when inserting user settings: until Identity's users are unique, a double-submitted signup can resolve to the same user twice.