Release v21.9.0
Summary
Cratis.Chronicle, Cratis.Chronicle.AspNetCore and Cratis.Chronicle.Testing are updated from 16.20.0 to 16.26.0, picking up 16.21.0, 16.22.0, 16.22.1, 16.22.2, 16.22.3, 16.22.4, 16.23.0, 16.24.0, 16.24.1, 16.25.0 and 16.26.0.
Added
- Chronicle 16.21.0: Allow reactors to return ordered cross-stream events with exact concurrency scopes in one atomic append. (Cratis/Chronicle#3651)
- Chronicle 16.22.0:
Compliance:Encryption:MigrateFromDefaultStoragesupports read-through migration from default compliance key storage to Vault or Azure Key Vault. (Cratis/Chronicle#3639) - Chronicle 16.23.0: A diagnostic reports
[EventSourceType]and[EventStreamType]declared on an event type, where they have no effect (Cratis/Chronicle#3642) - Chronicle 16.25.0:
WithTlsCertificateandWithEncryptionCertificateon the Aspire builder, which mount a certificate into the Chronicle container read-only and point the configuration at it (Cratis/Chronicle#3607) - Chronicle 16.26.0: Add
IUnitOfWork.AddEventsfor ordered cross-source events and independently labelled exact concurrency scopes in the existing transaction (Cratis/Chronicle#3683)
Changed
Cratis.Chronicle,Cratis.Chronicle.AspNetCoreandCratis.Chronicle.Testingare updated to16.26.0- Chronicle 16.24.0:
IReadModels.GetInstanceByIdresolves a materialized reducer-backed read model from the materialized store instead of replaying its events, with PII released server-side (Cratis/Chronicle#3605) - Chronicle 16.24.0:
IReadModels.GetInstancesreturns the stored instances for a materialized read model instead of replaying the event log; passing an explicit event count still replays (Cratis/Chronicle#3605) - Chronicle 16.24.0: A reducer-backed read model no longer needs a connected reducer client to be read by key (Cratis/Chronicle#3605)
- Chronicle 16.24.0: Read model instance reads are eventually consistent unless the read model is marked
[Passive]— mark it passive where a read must reflect an append that just happened (Cratis/Chronicle#3605) - Chronicle 16.24.1: Geospatial documentation now describes the JSON schema Chronicle emits — a leaf carrying only its format, with GeoJSON on the wire — and records that marking a geospatial value
[PII]is not supported, since an erased subject cannot be materialized back into one (Cratis/Chronicle#3673) - Chronicle 16.25.0: An Aspire AppHost configured for production must now supply a TLS certificate, and an encryption certificate when the internal OAuth authority is enabled — without them the production image does not start (Cratis/Chronicle#3607)
- Chronicle 16.26.0: Materialize and validate ordered events and scope inputs before staging while preserving pure legacy
AddEventbehavior (Cratis/Chronicle#3683)
Fixed
- Chronicle 16.21.0: Prevent CHR0043 from hanging or losing AutoMap state across helper-returned and member-held projection builders. (Cratis/Chronicle#3614)
- Chronicle 16.21.0: Resolve integration fixture services from scenario-owned scopes and always complete database cleanup. (Cratis/Chronicle#3649)
- Chronicle 16.21.0: Prevent Orleans MongoDB services from capturing Arc scoped clients regardless of registration order. (Cratis/Chronicle#3650)
- Chronicle 16.22.0: Rejected seed batches no longer disconnect clients or trigger reconnect loops; they remain unseeded for correction. (Cratis/Chronicle#3662)
- Chronicle 16.22.0:
ReviseEventresolvesIEventSerializerin the current event-store scope. (Cratis/Chronicle#3663) - Chronicle 16.22.0: Compliance-key erasure attempts every configured store and reports incomplete erasure. (Cratis/Chronicle#3664)
- Chronicle 16.22.0: An unavailable compliance key store is reported as unavailable, not as a missing key. (Cratis/Chronicle#3665)
- Chronicle 16.22.0: Refused or unconvertible join writes are logged as warnings without exposing key values. (Cratis/Chronicle#3656)
- Chronicle 16.22.1: The compliance key cache no longer restores a key that was deleted or evicted while a read of it was in flight. The cache releases its lock to call the backing store and takes it again to record the answer; an erasure landing in that window was overwritten by the older answer, so a shredded key came back and was served again
- Chronicle 16.22.1: An erasure no longer leaves the key cacheable for the length of the durable delete. The cache was cleared before that call, so a read starting afterwards could still find the key in the store and cache it, and cached keys have no time-to-live. Erasing one revision no longer evicts the others
- Chronicle 16.22.1: A partially failed erasure still clears the cache rather than keeping a key that may already be destroyed, and still evicts from every silo. A composite key store attempts every store and then reports the failure, so the key can be gone and the call still throw
- Chronicle 16.22.1: Saving a key no longer loses to a read that began before it. After a rotation the cache could serve the superseded key, so values encrypted under the new revision failed to decrypt until something evicted the entry
- Chronicle 16.22.2: Registering projection definitions that are identical to the ones already registered no longer repeats the registration fan-out - the kernel only processes definitions that are new or changed, so restarting or reconnecting clients of the same version register near-instantly and queued duplicate registrations collapse instead of piling up
- Chronicle 16.22.2: The .NET client no longer stacks registration retries:
RegisterAllruns as a single flight per event store - a call arriving while a registration is in flight joins that run instead of sending a duplicate - and a run that follows a failure waits an exponentially growing, jittered backoff before hitting the kernel again - Chronicle 16.22.2: An interrupted registration is retried in full on the next attempt instead of being skipped as already registered
- Chronicle 16.23.0: The duplicate context-mapping diagnostic now reports two
[SetFromContext<T>]for one event type split across a positional record's parameter and its generated property (Cratis/Chronicle#3626) - Chronicle 16.23.0:
[EventSourceType]and[EventStreamType]no longer document a placement on an event type that nothing reads (Cratis/Chronicle#3642) - Chronicle 16.24.0: PII is now released on the non-generic
IReadModels.GetInstanceById(Type, ...)for reducer-backed read models, which is how reactors resolve read model parameters — it previously returned encrypted values (Cratis/Chronicle#3605) - Chronicle 16.24.0: A read model instance request for a reducer-backed read model is made against the event sequence that reducer reduces from, rather than always the event log (Cratis/Chronicle#3605)
- Chronicle 16.24.1: Applying or releasing compliance no longer fails with
CompliancePropertyNotFoundInSchemawhen a read model or event carries a[PII]value alongside a geospatialPoint,LineStringorPolygon; the geospatial value is left in the clear (Cratis/Chronicle#3673) - Chronicle 16.25.0: An Aspire AppHost that configures Chronicle for production now runs the production image, instead of the development image that ships development credentials and an anonymous state-reset endpoint (Cratis/Chronicle#3607)
- Chronicle 16.25.0: A TLS certificate without a password now loads, instead of failing the server's startup with a cryptographic error
- Chronicle 16.25.0: A certificate path that does not exist now fails the AppHost immediately, instead of producing a container that reports itself running while its process has died (Cratis/Chronicle#3607)
- Chronicle 16.25.0: Configuring either certificate twice now replaces the earlier call, instead of producing a container Docker refuses to start (Cratis/Chronicle#3607)
Security
- Chronicle 16.22.0: Rejected seed diagnostics omit event-source IDs and constraint messages that may contain compliance subjects. (Cratis/Chronicle#3662)
- Chronicle 16.25.0: An Aspire AppHost configured for production no longer runs a development-compiled Chronicle, which seeds a documented default administrator password and a fixed OAuth client secret, and exposes an unauthenticated endpoint that erases the event store (Cratis/Chronicle#3607)
Arc command transaction addition
- Add a convention-discovered command response handler for Chronicle
EventsWithConcurrencyScopes. - Preserve returned cross-source event order and command metadata while enrolling the batch exactly once in the active command unit of work.
- Preserve exact independently labelled concurrency scopes captured by the command decision.
- Use one atomic
AppendManyonly for the established no-active-transaction fallback. - Convert constraint and concurrency rejection into an ordinary failed
CommandResultwith no partial event residue. - Keep every existing returned-event handler and automatic optimistic-concurrency strategy unchanged.
Verification
- Chronicle command specs: 632/632 in Debug and 632/632 in Release.
- Whole
Arc.slnxRelease build: 0 warnings and 0 errors. - Exact feature matrix: 44/44.
- Reversing the ordered batch produced 8 intended red positional facts.
- Dropping the exact scopes produced 7 intended reds, including the real timing discriminator accepting the command and leaving both target streams dirty.
- Markdown lint: 264/264; documentation links: 322/322.
- Fresh code and security reviews approved the final implementation.
Closes #2475.