Skip to content

Compliance wave 4: the portable-today suites (2.38.1) - #620

Merged
jeremydmiller merged 1 commit into
mainfrom
compliance/wave-4-portable
Aug 4, 2026
Merged

Compliance wave 4: the portable-today suites (2.38.1)#620
jeremydmiller merged 1 commit into
mainfrom
compliance/wave-4-portable

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

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.

Suite Tests Covers marten issue
FetchForWritingCompliance 13 FetchForWriting / FetchForExclusiveWriting / WriteToAggregate / WriteExclusivelyToAggregate / AppendOptimistic / AppendExclusive / version-checked Append, and the concurrency failures marten#5137
StreamReadCompliance 11 FetchStreamAsync with version, fromVersion and timestamp bounds; FetchStreamStateAsync; single-event LoadAsync marten#5139
EventMetadataCompliance 9 the IEvent envelope — per-stream Version, store-global Sequence, server Timestamp, type naming via the registry, tenant, headers marten#5143
LiveAggregationCompliance 7 AggregateStreamAsync and AggregateStreamToLastKnownAsync, including walking back past a fold that deletes the aggregate marten#5141

Verified on both stores before opening this

Not "should port cleanly" — actually run, against working copies wired through the ComplianceSourceDir dev loop:

  • Marten 105/105 compliance, and 1667/0/7 for the whole EventSourcingTests suite
  • Polecat 105/105 compliance

Zero capability gates on either store.

Two things worth reading closely

No exception abstraction was needed for concurrency. EventStreamUnexpectedMaxEventIdException derives from JasperFx's own ConcurrencyException, 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>.StartingVersion was documented as null when the stream does not exist. Both products report 0. 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 the EnableCorrelationTracking precedent — the flag is spelled differently in each product (Marten Events.MetadataConfig.HeadersEnabled, Polecat Events.EnableHeaders) so the fixture resolves it. Stamping the headers needs nothing new: IEvent.SetHeader is already shared.
  • README gains a coverage inventory, an explicit out-of-scope boundary, and the ComplianceSourceDir dev loop both consumers already support. That is part of what marten#5155 asks for.
  • JasperFxVersion 2.38.0 → 2.38.1, in this PR, per the --skip-duplicate publish 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 EnableHeaders fixture 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

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
@jeremydmiller
jeremydmiller merged commit a6a5299 into main Aug 4, 2026
1 check passed
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant