Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ jobs:
# A development kernel (MongoDB included) that the kernel-backed specifications (*.integration.spec.ts) run against.
services:
chronicle:
image: cratis/chronicle:19.22.1-development
image: cratis/chronicle:19.26.2-development
ports:
- 35000:35000

Expand Down
2 changes: 1 addition & 1 deletion Documentation/connecting.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ The TypeScript client and the Chronicle kernel have separate version numbers, an

Instead, the client sends its contract descriptor to the kernel on every new connection, and the kernel reports whether it can serve it. When the kernel reports an incompatibility, or does not implement the check, the client throws `IncompatibleChronicleServer`, does not retry, and rejects every later call. Deploy a compatible kernel and create a new client. Unlike the .NET client, the TypeScript client has no option to skip this check.

There is no published compatibility matrix. The examples in these guides were run against the `cratis/chronicle:19.4.8-development` image. Before you upgrade in production, test the client against the kernel version you run. [Preserve existing append routes](./migrate-append-routing.md) describes the upgrade that needs a kernel supporting kernel-owned append routing.
There is no published compatibility matrix. The kernel-backed specifications use the `cratis/chronicle:19.26.2-development` image. Before you upgrade in production, test the client against the kernel version you run. [Preserve existing append routes](./migrate-append-routing.md) describes the upgrade that needs a kernel supporting kernel-owned append routing.

## Shut down

Expand Down
2 changes: 1 addition & 1 deletion Documentation/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ Rejecting non-ASCII keys under `ignoreCasing` is a deliberate, permanent default
| Atomic batches | A remover earlier in the batch releases the cycle for later events in the batch; a second covered event after an in-batch claim is blocked. A rejected batch commits nothing, including its releases. The raw kernel violation reports the durable holder's sequence number (the first covered event after the source's latest committed remover), or `18446744073709551615` when only an earlier event in the batch holds the cycle. |
| Still rejected | One covered type with removers, several covered types without removers, any other count or overlap of covered and removal types, a cycle definition next to any other definition, fieldless event-type removers and scopes. Use a kernel-backed test. |

The committed `Source/testing/fixtures/*.json` snapshots run through the real in-process kernel via the pinned `Cratis.Chronicle.Testing` 19.8.1 oracle. `yarn oracle:check` verifies them alongside projection fixtures. The fixture tests also compare the TypeScript client’s serialized content, context fields, hash, result shape and essential reads. The boundary fixture covers an empty string, the supported printable ASCII range, a mixed-case property name and exclusion of a different event type on the same source. The source-tail fixture distinguishes the last event for A from the global tail. `batches.json` checks kernel-stored resolved per-entry metadata, the tag merge (including duplicate removal), correlation ID, ordering, hashes, batch causation, read filters and empty-batch rejection. Its .NET client-path oracle resolves per-entry versus shared route, subject and occurrence options **before** sending each event and supplies explicit route defaults; it does not independently prove those precedence rules. Those rules come from production `prepareBatchAppend` shared with the scenario. The separate `batch-omitted-routes.json` fixture bypasses the .NET convenience type and sends genuinely omitted and empty routes through the pinned kernel's batch service, verifying `Default`/`All`/`Default` resolution without claiming client-path notifications. Empty route and subject metadata are outside the scenario's supported domain. `builders.json` proves .NET's sequential setup/action semantics; `batch-rollback.json` proves rejected unique-constraint batches are atomic and leave no sequence gap. `constraints.json` proves string key ownership across event types and sources, ordinal casing and significant spaces, decorated and fluent unique-event-type rejection, raw wire violation fields, default property messages for in-batch conflicts and post-reclaim cross-source conflicts, successful same-source same-key batches with both sequences committed and a subsequent cross-source conflict reporting the last sequence, multiple failures on different events in one batch, and atomic rollback. It does not prove the violation order when one event violates multiple definitions; scenarios reject that overlap. These cases exercise the packaged kernel; the TypeScript spec compares every result and committed-history snapshot to the fixture. `constraints-isolation.json` selects only its declared text definition, and `constraints-key-domain.json` installs a shared string/boolean definition with explicit schemas. Both capture raw kernel violations, mapped results, routes, content, hashes and accepted history after each single or batch operation; failed appends assert unchanged history and sequence. The oracle checks effective installed definitions against fixture order, property names, scope, removal and casing and pins both the sequence and constraint contract descriptors. `constraints-property-lifecycle.json` and `constraints-property-covered-removal.json` separately capture replacement, removal, and batch non-release from pinned kernel storage: raw and mapped violations, every stored hash and history snapshot, and atomic rollback. The removal fixture checks three alternative removers, including a fieldless event; the covered-removal fixture shows validation before release. `constraints-event-type-siblings.json` and `constraints-event-type-cycles.json` each install one unique-event-type definition and capture cycle claims, releases by each remover, other-source removers, repeated removers, a covered remover, in-batch release and reclaim, blocked batches and their rollback, with raw and mapped violations and every stored hash. Composite keys are not inferred from these fixtures; `constraints-composite.json` separately installs a two-property definition shared across three event types (including a reversed declared order and a single key) and a three-property definition, and captures declared-order joining, delimiter collisions, empty components, per-property violations and messages, reclaim, replacement, removal and batch collisions. `constraints-ignore-casing.json` installs a case-insensitive single key with a remover and a case-insensitive composite, and captures ASCII case pairs, punctuation/digit/space significance, case-only same-source reclaim, original-cased details, replacement, removal, batch collisions and folding across component boundaries. Blank or whitespace-padded source filters are rejected until their normalization is fixture-backed. They do not establish production storage, concurrency, compliance or scheduler fidelity; use a kernel-backed test for those behaviors.
The committed `Source/testing/fixtures/*.json` snapshots run through the real in-process kernel via the pinned `Cratis.Chronicle.Testing` 19.26.2 oracle. `yarn oracle:check` verifies them alongside projection fixtures. The fixture tests also compare the TypeScript client’s serialized content, context fields, hash, result shape and essential reads. The boundary fixture covers an empty string, the supported printable ASCII range, a mixed-case property name and exclusion of a different event type on the same source. The source-tail fixture distinguishes the last event for A from the global tail. `batches.json` checks kernel-stored resolved per-entry metadata, the tag merge (including duplicate removal), correlation ID, ordering, hashes, batch causation, read filters and empty-batch rejection. Its .NET client-path oracle resolves per-entry versus shared route, subject and occurrence options **before** sending each event and supplies explicit route defaults; it does not independently prove those precedence rules. Those rules come from production `prepareBatchAppend` shared with the scenario. The separate `batch-omitted-routes.json` fixture bypasses the .NET convenience type and sends genuinely omitted and empty routes through the pinned kernel's batch service, verifying `Default`/`All`/`Default` resolution without claiming client-path notifications. Empty route and subject metadata are outside the scenario's supported domain. `builders.json` proves .NET's sequential setup/action semantics; `batch-rollback.json` proves rejected unique-constraint batches are atomic and leave no sequence gap. `constraints.json` proves string key ownership across event types and sources, ordinal casing and significant spaces, decorated and fluent unique-event-type rejection, raw wire violation fields, default property messages for in-batch conflicts and post-reclaim cross-source conflicts, successful same-source same-key batches with both sequences committed and a subsequent cross-source conflict reporting the last sequence, multiple failures on different events in one batch, and atomic rollback. It does not prove the violation order when one event violates multiple definitions; scenarios reject that overlap. These cases exercise the packaged kernel; the TypeScript spec compares every result and committed-history snapshot to the fixture. `constraints-isolation.json` selects only its declared text definition, and `constraints-key-domain.json` installs a shared string/boolean definition with explicit schemas. Both capture raw kernel violations, mapped results, routes, content, hashes and accepted history after each single or batch operation; failed appends assert unchanged history and sequence. The oracle checks effective installed definitions against fixture order, property names, scope, removal and casing and pins both the sequence and constraint contract descriptors. `constraints-property-lifecycle.json` and `constraints-property-covered-removal.json` separately capture replacement, removal, and batch non-release from pinned kernel storage: raw and mapped violations, every stored hash and history snapshot, and atomic rollback. The removal fixture checks three alternative removers, including a fieldless event; the covered-removal fixture shows validation before release. `constraints-event-type-siblings.json` and `constraints-event-type-cycles.json` each install one unique-event-type definition and capture cycle claims, releases by each remover, other-source removers, repeated removers, a covered remover, in-batch release and reclaim, blocked batches and their rollback, with raw and mapped violations and every stored hash. Composite keys are not inferred from these fixtures; `constraints-composite.json` separately installs a two-property definition shared across three event types (including a reversed declared order and a single key) and a three-property definition, and captures declared-order joining, delimiter collisions, empty components, per-property violations and messages, reclaim, replacement, removal and batch collisions. `constraints-ignore-casing.json` installs a case-insensitive single key with a remover and a case-insensitive composite, and captures ASCII case pairs, punctuation/digit/space significance, case-only same-source reclaim, original-cased details, replacement, removal, batch collisions and folding across component boundaries. Blank or whitespace-padded source filters are rejected until their normalization is fixture-backed. They do not establish production storage, concurrency, compliance or scheduler fidelity; use a kernel-backed test for those behaviors.

## ReactorScenario: live event deliveries and recorded effects

Expand Down
6 changes: 3 additions & 3 deletions Source/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@
},
"dependencies": {
"@bufbuild/protobuf": "^2.16.0",
"@cratis/chronicle.contracts": "19.26.0",
"@cratis/chronicle.contracts": "19.26.2",
"@grpc/grpc-js": "^1.14.5",
"@opentelemetry/api": "^1.9.1",
"glob": "^13.0.6",
Expand All @@ -183,7 +183,7 @@
"undici": "^8.11.2"
},
"devDependencies": {
"@cratis/fundamentals": "7.19.8",
"@cratis/fundamentals": "7.20.0",
"@types/node": "^26.6.3",
"@typescript/native": "npm:typescript@^7.0.2",
"esbuild": "^0.28.2",
Expand All @@ -192,6 +192,6 @@
"vitest": "^5.0.3"
},
"peerDependencies": {
"@cratis/fundamentals": "^7.19.8"
"@cratis/fundamentals": "^7.20.0"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ const artifacts: IClientArtifactsProvider = {
globalForHandlers: []
};

async function eventually(accept: () => boolean, timeoutMs = 30_000): Promise<void> {
// 30s was occasionally too tight for this reactor's initial catch-up under concurrent
// kernel load in CI (observed timing out at 31.2s on a run that passed cleanly on retry
// with no code change); 45s keeps the polling assertion honest while tolerating that jitter.
async function eventually(accept: () => boolean, timeoutMs = 45_000): Promise<void> {
const deadline = Date.now() + timeoutMs;
while (!accept()) {
if (Date.now() > deadline) throw new Error('Timed out waiting for the kernel');
Expand Down
8 changes: 4 additions & 4 deletions Source/testing/fixtures/alternate.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
"oracle": "eventScenario",
"license": "Copyright (c) Cratis. MIT; see LICENSE.",
"chronicle": {
"version": "19.8.1",
"commit": "8fe5d30"
"version": "19.26.2",
"commit": "1f8d832"
},
"tsContracts": {
"version": "19.8.1",
"descriptorSha256": "aee2206b2c79b36a34be7c0cf59eab1dfd9e35d9c0dff03c03de7eb659c12a2c"
"version": "19.26.2",
"descriptorSha256": "4b867c47b2e4d125306bb3cb062b106fa19d7a500accb5650fc1ac709e97596f"
},
"actions": [
{
Expand Down
8 changes: 4 additions & 4 deletions Source/testing/fixtures/batch-omitted-routes.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
"oracle": "eventScenario",
"license": "Copyright (c) Cratis. MIT; see LICENSE.",
"chronicle": {
"version": "19.8.1",
"commit": "8fe5d30"
"version": "19.26.2",
"commit": "1f8d832"
},
"tsContracts": {
"version": "19.8.1",
"descriptorSha256": "aee2206b2c79b36a34be7c0cf59eab1dfd9e35d9c0dff03c03de7eb659c12a2c"
"version": "19.26.2",
"descriptorSha256": "4b867c47b2e4d125306bb3cb062b106fa19d7a500accb5650fc1ac709e97596f"
},
"routeCases": [
{ "source": "A", "name": "omitted", "active": true },
Expand Down
8 changes: 4 additions & 4 deletions Source/testing/fixtures/batch-rollback.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
"oracle": "eventScenario",
"license": "Copyright (c) Cratis. MIT; see LICENSE.",
"chronicle": {
"version": "19.8.1",
"commit": "8fe5d30"
"version": "19.26.2",
"commit": "1f8d832"
},
"tsContracts": {
"version": "19.8.1",
"descriptorSha256": "aee2206b2c79b36a34be7c0cf59eab1dfd9e35d9c0dff03c03de7eb659c12a2c"
"version": "19.26.2",
"descriptorSha256": "4b867c47b2e4d125306bb3cb062b106fa19d7a500accb5650fc1ac709e97596f"
},
"operations": [
{
Expand Down
8 changes: 4 additions & 4 deletions Source/testing/fixtures/batches.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
"oracle": "eventScenario",
"license": "Copyright (c) Cratis. MIT; see LICENSE.",
"chronicle": {
"version": "19.8.1",
"commit": "8fe5d30"
"version": "19.26.2",
"commit": "1f8d832"
},
"tsContracts": {
"version": "19.8.1",
"descriptorSha256": "aee2206b2c79b36a34be7c0cf59eab1dfd9e35d9c0dff03c03de7eb659c12a2c"
"version": "19.26.2",
"descriptorSha256": "4b867c47b2e4d125306bb3cb062b106fa19d7a500accb5650fc1ac709e97596f"
},
"operations": [
{
Expand Down
8 changes: 4 additions & 4 deletions Source/testing/fixtures/boundary.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
"oracle": "eventScenario",
"license": "Copyright (c) Cratis. MIT; see LICENSE.",
"chronicle": {
"version": "19.8.1",
"commit": "8fe5d30"
"version": "19.26.2",
"commit": "1f8d832"
},
"tsContracts": {
"version": "19.8.1",
"descriptorSha256": "aee2206b2c79b36a34be7c0cf59eab1dfd9e35d9c0dff03c03de7eb659c12a2c"
"version": "19.26.2",
"descriptorSha256": "4b867c47b2e4d125306bb3cb062b106fa19d7a500accb5650fc1ac709e97596f"
},
"actions": [
{
Expand Down
8 changes: 4 additions & 4 deletions Source/testing/fixtures/builders.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
"oracle": "eventScenario",
"license": "Copyright (c) Cratis. MIT; see LICENSE.",
"chronicle": {
"version": "19.8.1",
"commit": "8fe5d30"
"version": "19.26.2",
"commit": "1f8d832"
},
"tsContracts": {
"version": "19.8.1",
"descriptorSha256": "aee2206b2c79b36a34be7c0cf59eab1dfd9e35d9c0dff03c03de7eb659c12a2c"
"version": "19.26.2",
"descriptorSha256": "4b867c47b2e4d125306bb3cb062b106fa19d7a500accb5650fc1ac709e97596f"
},
"operations": [
{
Expand Down
8 changes: 4 additions & 4 deletions Source/testing/fixtures/client-causation.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
"oracle": "eventScenario",
"license": "Copyright (c) Cratis. MIT; see LICENSE.",
"chronicle": {
"version": "19.8.1",
"commit": "8fe5d30"
"version": "19.26.2",
"commit": "1f8d832"
},
"tsContracts": {
"version": "19.8.1",
"descriptorSha256": "aee2206b2c79b36a34be7c0cf59eab1dfd9e35d9c0dff03c03de7eb659c12a2c"
"version": "19.26.2",
"descriptorSha256": "4b867c47b2e4d125306bb3cb062b106fa19d7a500accb5650fc1ac709e97596f"
},
"actions": [
{
Expand Down
10 changes: 5 additions & 5 deletions Source/testing/fixtures/constraints-composite.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
"oracle": "eventScenario",
"license": "Copyright (c) Cratis. MIT; see LICENSE.",
"chronicle": {
"version": "19.8.1",
"commit": "8fe5d30"
"version": "19.26.2",
"commit": "1f8d832"
},
"tsContracts": {
"version": "19.8.1",
"descriptorSha256": "aee2206b2c79b36a34be7c0cf59eab1dfd9e35d9c0dff03c03de7eb659c12a2c"
"version": "19.26.2",
"descriptorSha256": "4b867c47b2e4d125306bb3cb062b106fa19d7a500accb5650fc1ac709e97596f"
},
"constraintDescriptorSha256": "8de18d804165220f6c491cfed59ca31bf55c84eb6eb7a94a2a83b092b12bbf84",
"constraintDescriptorSha256": "6c5ec2367fdfbe95fd9f09c05fcf40645dd43db5c98a3d616443845828d3e253",
"eventSchemas": {
"string": {
"eventTypeId": "OracleDomainText",
Expand Down
10 changes: 5 additions & 5 deletions Source/testing/fixtures/constraints-event-type-cycles.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
"oracle": "eventScenario",
"license": "Copyright (c) Cratis. MIT; see LICENSE.",
"chronicle": {
"version": "19.8.1",
"commit": "8fe5d30"
"version": "19.26.2",
"commit": "1f8d832"
},
"tsContracts": {
"version": "19.8.1",
"descriptorSha256": "aee2206b2c79b36a34be7c0cf59eab1dfd9e35d9c0dff03c03de7eb659c12a2c"
"version": "19.26.2",
"descriptorSha256": "4b867c47b2e4d125306bb3cb062b106fa19d7a500accb5650fc1ac709e97596f"
},
"constraintDescriptorSha256": "8de18d804165220f6c491cfed59ca31bf55c84eb6eb7a94a2a83b092b12bbf84",
"constraintDescriptorSha256": "6c5ec2367fdfbe95fd9f09c05fcf40645dd43db5c98a3d616443845828d3e253",
"eventSchemas": {
"first": {
"eventTypeId": "OracleCycleFirst",
Expand Down
10 changes: 5 additions & 5 deletions Source/testing/fixtures/constraints-event-type-siblings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
"oracle": "eventScenario",
"license": "Copyright (c) Cratis. MIT; see LICENSE.",
"chronicle": {
"version": "19.8.1",
"commit": "8fe5d30"
"version": "19.26.2",
"commit": "1f8d832"
},
"tsContracts": {
"version": "19.8.1",
"descriptorSha256": "aee2206b2c79b36a34be7c0cf59eab1dfd9e35d9c0dff03c03de7eb659c12a2c"
"version": "19.26.2",
"descriptorSha256": "4b867c47b2e4d125306bb3cb062b106fa19d7a500accb5650fc1ac709e97596f"
},
"constraintDescriptorSha256": "8de18d804165220f6c491cfed59ca31bf55c84eb6eb7a94a2a83b092b12bbf84",
"constraintDescriptorSha256": "6c5ec2367fdfbe95fd9f09c05fcf40645dd43db5c98a3d616443845828d3e253",
"eventSchemas": {
"first": {
"eventTypeId": "OracleCycleFirst",
Expand Down
10 changes: 5 additions & 5 deletions Source/testing/fixtures/constraints-ignore-casing.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
"oracle": "eventScenario",
"license": "Copyright (c) Cratis. MIT; see LICENSE.",
"chronicle": {
"version": "19.8.1",
"commit": "8fe5d30"
"version": "19.26.2",
"commit": "1f8d832"
},
"tsContracts": {
"version": "19.8.1",
"descriptorSha256": "aee2206b2c79b36a34be7c0cf59eab1dfd9e35d9c0dff03c03de7eb659c12a2c"
"version": "19.26.2",
"descriptorSha256": "4b867c47b2e4d125306bb3cb062b106fa19d7a500accb5650fc1ac709e97596f"
},
"constraintDescriptorSha256": "8de18d804165220f6c491cfed59ca31bf55c84eb6eb7a94a2a83b092b12bbf84",
"constraintDescriptorSha256": "6c5ec2367fdfbe95fd9f09c05fcf40645dd43db5c98a3d616443845828d3e253",
"eventSchemas": {
"string": {
"eventTypeId": "OracleDomainText",
Expand Down
Loading
Loading