Compliance wave 4: the portable-today suites (2.38.1) - #620
Merged
Conversation
Four new shared suites, 40 tests, taking the library from 65 to 105. Every entry point they exercise was already declared on the shared JasperFx surfaces, so none of them needed a new fixture member: - FetchForWritingCompliance (13) - FetchForWriting / FetchForExclusiveWriting / WriteToAggregate / AppendOptimistic / AppendExclusive and version-checked Append, plus the concurrency failures. EventStreamUnexpectedMaxEventIdException derives from JasperFx's own ConcurrencyException and both products throw it, so there is no exception shape to abstract over. - StreamReadCompliance (11) - FetchStreamAsync with version, fromVersion and timestamp bounds, FetchStreamStateAsync, single-event LoadAsync. - EventMetadataCompliance (9) - the IEvent envelope: per-stream Version, store-global Sequence, server Timestamp, type naming via the registry, tenant, and headers. - LiveAggregationCompliance (7) - AggregateStreamAsync and AggregateStreamToLastKnownAsync, including walking back past a fold that deletes the aggregate. Verified green on both stores against working copies: Marten 105/105 and Polecat 105/105, zero capability gates. Two smaller changes come with them: ComplianceStoreConfig.EnableHeaders, following the EnableCorrelationTracking precedent - the flag is spelled differently in each product (Marten's Events.MetadataConfig.HeadersEnabled, Polecat's Events.EnableHeaders) so the fixture resolves it. Stamping headers needs nothing new, since IEvent.SetHeader is already shared. A doc correction on IEventStream<T>.StartingVersion, which claimed a fetch of a missing stream reports null. Both products report 0. The suite caught it, which is the first time a compliance test has corrected an upstream contract doc. The README gains a coverage inventory, the out-of-scope boundary, and the ComplianceSourceDir dev loop both consumers already support. Refs JasperFx/marten#5137, #5139, #5141, #5143, #5118 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VpDCvJcBDZerieJB4JEHde
This was referenced Aug 4, 2026
Closed
Closed
This was referenced Aug 4, 2026
jeremydmiller
added a commit
to JasperFx/marten
that referenced
this pull request
Aug 4, 2026
Bumps JasperFx, JasperFx.Events, JasperFx.Events.ComplianceTests and both source generators 2.38.0 -> 2.39.1, and enrolls the four new shared suites that shipped in it (JasperFx/jasperfx#620): - fetch_for_writing_compliance (13) - stream_read_compliance (11) - event_metadata_compliance (9) - live_aggregation_compliance (7) Marten's compliance coverage goes from 65 to 105 tests with zero capability gates. MartenComplianceFixture resolves the new ComplianceStoreConfig.EnableHeaders flag onto Events.MetadataConfig.HeadersEnabled, the same way it already resolves EnableCorrelationTracking. EventSourcingTests.csproj gains the ComplianceSourceDir switch Polecat.Tests already had: passing it swaps the published suites for a jasperfx working copy, so a wave can be validated against Marten before the JasperFx release. Without it nothing changes. The bump also carries #618, which stops ShardName discarding the tenant slot for HighWaterMark names -- a store-global high-water shard still collapses to "HighWaterMark", but a tenant-scoped one now composes to "HighWaterMark:{tenant}". That is the grammar Marten already persisted through HighWaterShardIdentity, so the runtime needed no change; the upstream fix brought ShardName into line with Marten rather than the other way round. Bug_4785's assertion encoded the old "tenant slot is always discarded" behaviour and is updated to pin both halves of the new grammar, and the HighWaterShardIdentity doc comment that described the superseded behaviour is corrected. Verified on net9.0 against the published packages: 105/105 compliance, 1667/0/7 EventSourcingTests, 280/280 DaemonTests. Closes #5137 Closes #5139 Closes #5141 Closes #5143 Refs #5118 Claude-Session: https://claude.ai/code/session_01VpDCvJcBDZerieJB4JEHde Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
jeremydmiller
added a commit
to JasperFx/polecat
that referenced
this pull request
Aug 4, 2026
Bumps JasperFx, JasperFx.Events, JasperFx.Events.ComplianceTests and both source generators 2.38.0 -> 2.39.1, and enrolls the four new shared suites that shipped in it (JasperFx/jasperfx#620): - fetch_for_writing_compliance (13) - stream_read_compliance (11) - event_metadata_compliance (9) - live_aggregation_compliance (7) Polecat's compliance coverage goes from 65 to 105 tests with zero capability gates. PolecatComplianceFixture resolves the new ComplianceStoreConfig.EnableHeaders flag onto Events.EnableHeaders, alongside the existing correlation wiring. The flag exists because the two products spell it differently -- stamping the headers themselves needed nothing new, since IEvent.SetHeader is already shared. Verified on net9.0: 105/105 compliance and 1703/0/3 for the full Polecat.Tests suite against the published 2.39.1 packages. Claude-Session: https://claude.ai/code/session_01VpDCvJcBDZerieJB4JEHde Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Compliance wave 4 — the whole "portable today" group from the wave backlog (marten#5118). Four suites, 40 tests, library 65 → 105, and not one of them needed a new fixture member: every entry point was already declared on the shared JasperFx surfaces.
FetchForWritingComplianceFetchForWriting/FetchForExclusiveWriting/WriteToAggregate/WriteExclusivelyToAggregate/AppendOptimistic/AppendExclusive/ version-checkedAppend, and the concurrency failuresStreamReadComplianceFetchStreamAsyncwith version,fromVersionand timestamp bounds;FetchStreamStateAsync; single-eventLoadAsyncEventMetadataComplianceIEventenvelope — per-streamVersion, store-globalSequence, serverTimestamp, type naming via the registry, tenant, headersLiveAggregationComplianceAggregateStreamAsyncandAggregateStreamToLastKnownAsync, including walking back past a fold that deletes the aggregateVerified on both stores before opening this
Not "should port cleanly" — actually run, against working copies wired through the
ComplianceSourceDirdev loop:Zero capability gates on either store.
Two things worth reading closely
No exception abstraction was needed for concurrency.
EventStreamUnexpectedMaxEventIdExceptionderives from JasperFx's ownConcurrencyException, and both products throw it — this was the one thing that looked like it would need a seam member and did not. The suite asserts the shared base rather than the exact derived type, and wraps the whole fetch-append-save sequence rather than a single call, because whether a store detects the conflict eagerly at fetch or late at commit is an implementation choice. Pinning it would encode one product's timing as the standard.A compliance test corrected an upstream contract doc, which is a first.
IEventStream<T>.StartingVersionwas documented as null when the stream does not exist. Both products report0. The doc is what was wrong, so it is fixed here, with a pointer to the test that establishes it.Also included
ComplianceStoreConfig.EnableHeaders, following theEnableCorrelationTrackingprecedent — the flag is spelled differently in each product (MartenEvents.MetadataConfig.HeadersEnabled, PolecatEvents.EnableHeaders) so the fixture resolves it. Stamping the headers needs nothing new:IEvent.SetHeaderis already shared.ComplianceSourceDirdev loop both consumers already support. That is part of what marten#5155 asks for.JasperFxVersion2.38.0 → 2.38.1, in this PR, per the--skip-duplicatepublish trap.Notes on the time-based tests
Two tests need a real timestamp gap. Both derive the cut-off from the stored event timestamps rather than the test host's clock (the two are different machines in CI, and stores stamp server-side), and both pick a point strictly between two commits so the suite does not accidentally pin whether a store's timestamp filter is inclusive or exclusive.
After this merges
Consumers adopt on 2.38.1 — Marten enrollments plus the
EnableHeadersfixture wiring are ready on a branch and gated only on the publish; Polecat's are the same shape.🤖 Generated with Claude Code
https://claude.ai/code/session_01VpDCvJcBDZerieJB4JEHde