@shirudo/ddd-kit 3.0.0-rc.8 → 3.0.0-rc.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"testing.js","names":[],"sources":["../src/testing/contract-assertions.ts","../src/testing/command-outbox-contract.ts","../src/testing/deadline-store-contract.ts","../src/testing/es-repository-contract.ts","../src/testing/event-bus-contract.ts","../src/testing/event-store-contract.ts","../src/testing/idempotency-store-contract.ts","../src/testing/outbox-contract.ts","../src/testing/projection-checkpoint-contract.ts","../src/testing/repository-contract.ts","../src/testing/snapshot-store-contract.ts"],"sourcesContent":["/**\n * Assertion, error-matching, and suite-runner helpers shared by the\n * repository contract suites (state-stored and event-sourced). Internal\n * to the testing entry: not re-exported from `@shirudo/ddd-kit/testing`.\n */\nimport { isRecordedDomainEvent } from \"../domain/event/domain-event\";\nimport { runBoundedExecution } from \"../internal/async/execution\";\n\n/**\n * One entry of a contract test suite. Every suite (repository,\n * event-sourced repository, outbox, idempotency store) returns a list\n * of these; bind them with\n * `(test.skipped ? it.skip : it)(test.name, test.run)`.\n */\nexport interface ContractTest {\n\tname: string;\n\trun: () => Promise<void>;\n\t/** Present when the harness lacks the capability this test needs. */\n\tskipped?: { capability: string };\n}\n\n/**\n * Runs one contract-test body against a fresh environment and tears it\n * down in a finally-like discipline with one subtle, load-bearing rule:\n * a teardown failure (dropping a schema on an aborted pool) must never\n * REPLACE the contract-violation diagnostic that is the suite's entire\n * value. It only surfaces when the body itself succeeded.\n */\nexport async function runInContractEnvironment<\n\tEnv extends { teardown?(): Promise<void> },\n>(\n\tcreateEnvironment: () => Promise<Env>,\n\tbody: (env: Env) => Promise<void>,\n): Promise<void> {\n\tconst env = await createEnvironment();\n\tlet bodyFailed = false;\n\tlet bodyError: unknown;\n\ttry {\n\t\tawait body(env);\n\t} catch (error) {\n\t\tbodyFailed = true;\n\t\tbodyError = error;\n\t}\n\ttry {\n\t\tawait env.teardown?.();\n\t} catch (teardownError) {\n\t\tif (!bodyFailed) {\n\t\t\tthrow teardownError;\n\t\t}\n\t}\n\tif (bodyFailed) {\n\t\tthrow bodyError;\n\t}\n}\n\n/**\n * Binds a harness's environment factory into the per-test wrapper the\n * suites build their entries from: `inEnv(body)` yields a test `run`\n * that creates a fresh environment, runs the body, and tears down via\n * {@link runInContractEnvironment}.\n */\nexport function bindContractEnvironment<\n\tEnv extends { teardown?(): Promise<void> },\n>(\n\tcreateEnvironment: () => Promise<Env>,\n): (body: (env: Env) => Promise<void>) => () => Promise<void> {\n\treturn (body) => () => runInContractEnvironment(createEnvironment, body);\n}\n\n/** Resolves to the rejection reason, or `undefined` when the promise resolved. */\nexport function captureRejection(promise: Promise<unknown>): Promise<unknown> {\n\treturn promise.then(\n\t\t() => undefined,\n\t\t(error: unknown) => error,\n\t);\n}\n\n/**\n * Default bound for the overlapping `run` calls of the contract suites, in\n * milliseconds. On an environment that gives each `run` call its own\n * connection, the second call completes in milliseconds. The failure path\n * takes up to twice the bound: the bound itself, then the wait for the\n * released calls to settle. Twice the bound plus environment creation and\n * teardown stays below the default test timeout of common runners\n * (5000 ms). So the named failure reaches the report before the runner's\n * own timeout replaces it.\n */\nexport const OVERLAPPING_CALLS_BOUND_MS = 1_000;\n\nconst overlappingCallsViolation = (boundMs: number): string =>\n\t`run must permit overlapping calls: a second run call did not complete within ${boundMs} ms while the first call stayed open. ` +\n\t\"Either run serializes its calls, the first call holds a lock that blocks the second one, or the second call needs more time than the bound. \" +\n\t\"Give each call its own transaction and connection, load without row locks, or raise overlappingCallsBoundMs on the harness\";\n\nfunction settle<T>(promise: Promise<T>): Promise<PromiseSettledResult<T>> {\n\treturn promise.then(\n\t\t(value) => ({ status: \"fulfilled\", value }),\n\t\t(reason: unknown) => ({ status: \"rejected\", reason }),\n\t);\n}\n\n/** Outcomes of every promise, or `undefined` when one is still open after `boundMs`. */\nfunction settledWithin(\n\tpromises: ReadonlyArray<Promise<unknown>>,\n\tboundMs: number,\n): Promise<PromiseSettledResult<unknown>[] | undefined> {\n\treturn runBoundedExecution(\n\t\t\"release of the overlapping calls\",\n\t\t{ timeoutMs: boundMs },\n\t\t() => Promise.allSettled(promises),\n\t).catch(() => undefined);\n}\n\n/** A `run` call that stays open until the proof releases it. */\nexport interface ParkedRunCall<T> {\n\treadonly call: Promise<T>;\n\treadonly release: () => void;\n}\n\n/**\n * Starts a `run` call and holds it open. `start` receives `hold`. The work\n * of the call awaits `hold()` at the point where it must stay open, for\n * example after its load. The result resolves once the work holds and the\n * call is still open. A call that rejects before that propagates its\n * rejection. A call that resolves while its work holds fails: `run` did not\n * await its work.\n */\nexport async function parkRunCall<T>(\n\tstart: (hold: () => Promise<void>) => Promise<T>,\n): Promise<ParkedRunCall<T>> {\n\tlet release!: () => void;\n\tconst mayContinue = new Promise<void>((resolve) => {\n\t\trelease = resolve;\n\t});\n\tlet markHolding!: () => void;\n\tconst holding = new Promise<\"holding\">((resolve) => {\n\t\tmarkHolding = () => resolve(\"holding\");\n\t});\n\tconst call = start(() => {\n\t\tmarkHolding();\n\t\treturn mayContinue;\n\t});\n\tconst settled = settle(call).then((outcome) => outcome.status);\n\n\tlet state = await Promise.race([holding, settled]);\n\tif (state === \"holding\") {\n\t\tstate = await Promise.race([settled, Promise.resolve(\"holding\" as const)]);\n\t}\n\tif (state === \"rejected\") await call;\n\tassert(\n\t\tstate === \"holding\",\n\t\t\"run must await its work: the call resolved while its work still holds\",\n\t);\n\treturn { call, release };\n}\n\n/**\n * Starts a `run` call through `startCall` and awaits it. The call must\n * complete while `parked` stays open. On an environment that serializes\n * `run`, it never completes. So this bounds the wait. After `boundMs` it\n * releases the parked call and waits up to `boundMs` for both calls to\n * settle. Then it fails with the requirement. A rejection of the call, or a\n * synchronous throw of `startCall`, releases the parked call the same way\n * and then propagates. On success the parked call stays parked; the proof\n * releases it when it is ready.\n */\nexport async function awaitOverlappingCall<T>(\n\tstartCall: () => Promise<T>,\n\tparked: ParkedRunCall<unknown>,\n\tboundMs: number,\n): Promise<T> {\n\tlet call: Promise<T>;\n\ttry {\n\t\tcall = startCall();\n\t} catch (error) {\n\t\tparked.release();\n\t\tawait settledWithin([parked.call], boundMs);\n\t\tthrow error;\n\t}\n\tconst outcome = await runBoundedExecution(\n\t\t\"overlapping run call\",\n\t\t{ timeoutMs: boundMs },\n\t\t() => settle(call),\n\t).catch(() => undefined);\n\tif (outcome?.status === \"fulfilled\") return outcome.value;\n\n\tparked.release();\n\tawait settledWithin([parked.call, call], boundMs);\n\tassert(outcome !== undefined, overlappingCallsViolation(boundMs));\n\tthrow outcome.reason;\n}\n\n/**\n * Proves that the environment lets two `run` calls stay open at once.\n *\n * The stale-writer proofs hold one transaction open while a second one\n * commits. An environment that serializes `run` (one connection, a mutex)\n * blocks the second call behind the first. The suite then hangs at the test\n * timeout with no cause. This proof turns that hang into a named failure\n * within `boundMs`. It releases the first call before it returns and waits\n * up to `boundMs` for both calls to complete. A second call that is still\n * blocked after that stays in flight, observed, while the failure reports.\n */\nexport async function assertRunPermitsOverlappingCalls(\n\trun: (work: () => Promise<void>) => Promise<unknown>,\n\tboundMs: number,\n): Promise<void> {\n\tconst first = await parkRunCall((hold) => run(hold));\n\n\tawait awaitOverlappingCall(() => run(async () => {}), first, boundMs);\n\n\tfirst.release();\n\tconst firstOutcome = (await settledWithin([first.call], boundMs))?.[0];\n\tassert(\n\t\tfirstOutcome !== undefined,\n\t\t`the first run call did not complete within ${boundMs} ms after the proof released it`,\n\t);\n\tif (firstOutcome.status === \"rejected\") throw firstOutcome.reason;\n}\n\n/** The part of a contract environment that the preflight needs. */\ninterface OverlappingRunEnvironment<TId> {\n\trun<R>(\n\t\twork: (context: {\n\t\t\trepository: { findById(id: TId): Promise<unknown> };\n\t\t}) => Promise<R>,\n\t): Promise<R>;\n}\n\n/**\n * The preflight entry both repository suites put first: it names a\n * serializing environment before the stale-writer proofs can hang on it.\n * Each `run` call of the proof reads `freshId()` before it holds. So an\n * adapter that reserves its connection on the first statement holds the\n * connection while the call stays open.\n */\nexport function overlappingCallsPreflight<\n\tEnv extends OverlappingRunEnvironment<TId>,\n\tTId,\n>(\n\tinEnvironment: (body: (env: Env) => Promise<void>) => () => Promise<void>,\n\tfreshId: () => TId,\n\tboundMs: number,\n): ContractTest {\n\treturn {\n\t\tname: \"environment preflight: a second run call completes while the first call stays open\",\n\t\trun: inEnvironment((env) =>\n\t\t\tassertRunPermitsOverlappingCalls(\n\t\t\t\t(work) =>\n\t\t\t\t\tenv.run(async ({ repository }) => {\n\t\t\t\t\t\tawait repository.findById(freshId());\n\t\t\t\t\t\tawait work();\n\t\t\t\t\t}),\n\t\t\t\tboundMs,\n\t\t\t),\n\t\t),\n\t};\n}\n\n/**\n * Load with a contract diagnostic instead of a bare TypeError downstream.\n * `suspectHint` names the suite-specific likely cause (broken hydration\n * vs broken replay read).\n */\nexport async function loadAggregateOrFail<TAgg, TId>(\n\trepository: { findById(id: TId): Promise<TAgg | null | undefined> },\n\tid: TId,\n\tsuspectHint: string,\n): Promise<TAgg> {\n\tconst loaded = await repository.findById(id);\n\tassert(\n\t\tloaded !== null && loaded !== undefined,\n\t\t`findById(${String(id)}) returned no aggregate for an identity that must exist: ${suspectHint}`,\n\t);\n\treturn loaded;\n}\n\n/**\n * A capability-gated test entry whose `run()` rejects loudly, so a naive\n * binding that ignores `skipped` fails instead of green-no-op'ing.\n * Structurally assignable to both suites' test-entry types.\n */\nexport function skippedContractTest(\n\tname: string,\n\tcapability: string,\n): ContractTest & { skipped: { capability: string } } {\n\treturn {\n\t\tname,\n\t\tskipped: { capability },\n\t\trun: async () => {\n\t\t\tthrow new Error(\n\t\t\t\t`Contract test skipped: harness capability '${capability}' is not provided. ` +\n\t\t\t\t\t`Bind skipped tests with it.skip ((test.skipped ? it.skip : it)(test.name, test.run)) ` +\n\t\t\t\t\t`or provide the capability; each skipped capability is an unproven guarantee.`,\n\t\t\t);\n\t\t},\n\t};\n}\n\n/**\n * Capability gate that keeps a test's NAME single-sourced: a harness\n * that satisfies the gate gets the real test, everyone else gets the\n * loud skipped entry under the same name (see\n * {@link skippedContractTest}). Nests for tests behind several gates;\n * the outermost failing gate's capability wins the skip report.\n */\nexport function gatedContractTest(\n\tgate: { capability: string; satisfiedBy: boolean },\n\ttest: ContractTest,\n): ContractTest {\n\treturn gate.satisfiedBy\n\t\t? test\n\t\t: skippedContractTest(test.name, gate.capability);\n}\n\n/**\n * Identities of an in-memory pending batch, with the shared precondition\n * that every event carries the recorded brand. The `requirement` names\n * the suite-specific rule the harness violated when an event is not\n * recorded.\n */\nexport function recordedPendingEventIds(\n\tevents: ReadonlyArray<unknown>,\n\trequirement: string,\n): string[] {\n\treturn events.map((event) => {\n\t\tassert(\n\t\t\ttypeof event === \"object\" &&\n\t\t\t\tevent !== null &&\n\t\t\t\tisRecordedDomainEvent(event),\n\t\t\trequirement,\n\t\t);\n\t\treturn (event as { readonly eventId: string }).eventId;\n\t});\n}\n\n/**\n * Sorted identities of committed outbox envelopes. Shared by both\n * repository suites so the projection cannot drift between them.\n */\nexport function sortedCommittedEventIds(\n\tcommitted: ReadonlyArray<{ readonly event: { readonly eventId: string } }>,\n): string[] {\n\treturn committed.map(({ event }) => event.eventId).sort();\n}\n\nexport function assert(condition: boolean, message: string): asserts condition {\n\tif (!condition) {\n\t\tthrow new Error(`Contract violated: ${message}`);\n\t}\n}\n\nexport function assertEqual(\n\tactual: unknown,\n\texpected: unknown,\n\tmessage: string,\n): void {\n\tif (actual !== expected) {\n\t\tthrow new Error(\n\t\t\t`Contract violated: ${message} (expected ${String(expected)}, got ${String(actual)})`,\n\t\t);\n\t}\n}\n\n/**\n * Walks the standard `cause` chain (cycle-safe, hostile-getter-safe)\n * looking for an Error that matches the given name. Matching is\n * deliberately by NAME, not `instanceof`: the suite ships in its own\n * bundle entry, and the adapter's errors come from the main entry's\n * copy of the kit (or even a second installed kit version) -\n * cross-copy `instanceof` is always false, name identity is the stable\n * contract. Since v3 the kit's errors are StructuredErrors whose\n * runtime `name` IS their SCREAMING_SNAKE code, minification-stable by\n * construction and inherited by subclasses (a `PgConflictError extends\n * ConcurrencyConflictError` keeps the code as its name). The suites\n * match ONLY the v3 codes. Failure diagnostics render the rejection's\n * cause-chain names ({@link describeError}), so an unexpected error,\n * including one from a different kit copy in the dependency graph, is\n * identifiable from the message without version-specific knowledge in\n * the suite.\n */\nexport function chainContainsErrorNamed(error: unknown, name: string): boolean {\n\tlet found = false;\n\twalkCauseChain(error, (node) => {\n\t\tfound = errorMatchesName(node, name);\n\t\treturn found;\n\t});\n\treturn found;\n}\n\n/**\n * The one cause-chain walk every chain-inspecting helper in this file\n * is expressed through (cycle-safe, hostile-cause-getter-safe): visits\n * each object node until `visit` asks to stop by returning `true`, the\n * chain ends, repeats, or advancing turns hostile. Single-sourced on\n * purpose: a hardening fix (a depth cap, a new hostile shape) must land\n * in ALL walkers at once, or the suites judge the same adapter\n * rejection inconsistently. Per-node property reads stay the visitor's\n * responsibility; only the `cause` advance is guarded here.\n */\nfunction walkCauseChain(\n\terror: unknown,\n\tvisit: (node: object) => boolean,\n): void {\n\tconst seen = new Set<unknown>();\n\tlet current: unknown = error;\n\twhile (\n\t\tcurrent !== null &&\n\t\tcurrent !== undefined &&\n\t\ttypeof current === \"object\" &&\n\t\t!seen.has(current)\n\t) {\n\t\tseen.add(current);\n\t\tif (visit(current)) return;\n\t\ttry {\n\t\t\tcurrent = (current as { cause?: unknown }).cause;\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t}\n}\n\n/**\n * Asserts that the cause chain carries a kit error with one of the given\n * codes (since v3, `error.name === error.code`; the codes are the ONLY\n * accepted identity). Failure messages built with {@link describeError}\n * render the rejection's cause-chain names, so an unexpected error, e.g.\n * one from a different `@shirudo/ddd-kit` copy in the dependency graph,\n * is identifiable from the diagnostic without the suite carrying any\n * version-specific knowledge.\n */\nexport function assertChainContainsKitError(\n\trejection: unknown,\n\tcodes: readonly string[],\n\tmessage: string,\n): void {\n\tif (codes.some((code) => chainContainsErrorNamed(rejection, code))) {\n\t\treturn;\n\t}\n\tthrow new Error(`Contract violated: ${message}`);\n}\n\n/**\n * Walks the `cause` chain (cycle-safe, hostile-getter-safe) looking for\n * `retryable === true`: the same loose, property-based contract the\n * kit's retry classifier (`someChainRetryable`) applies. Suites assert\n * retryability with this instead of reading the top-level rejection, so\n * an adapter that wraps a kit error in its own error chain, which\n * {@link assertChainContainsKitError} deliberately tolerates, is judged\n * exactly the way a consumer's retry loop will judge it.\n *\n * Deliberately NOT a call to `someChainRetryable` itself: that\n * classifier throws on a circular cause chain (its callers handle\n * that), while a hardened suite must survive whatever error shape an\n * adapter rejects with and answer with a contract diagnostic, never a\n * helper crash. Same hardening discipline as\n * {@link chainContainsErrorNamed}.\n */\nexport function chainContainsRetryable(error: unknown): boolean {\n\tlet found = false;\n\twalkCauseChain(error, (node) => {\n\t\ttry {\n\t\t\tfound = (node as { retryable?: unknown }).retryable === true;\n\t\t} catch {\n\t\t\t// Hostile `retryable` getter: stop the walk, keep found=false.\n\t\t\treturn true;\n\t\t}\n\t\treturn found;\n\t});\n\treturn found;\n}\n\nfunction errorMatchesName(candidate: object, name: string): boolean {\n\ttry {\n\t\tif ((candidate as { name?: unknown }).name === name) {\n\t\t\treturn true;\n\t\t}\n\t} catch {\n\t\t// Hostile `name` getter: treat as non-matching, keep walking.\n\t}\n\t// Fallback for errors whose own `name` was overridden (a subclass\n\t// that re-assigns `this.name` after super): the prototype chain\n\t// still carries the base class's constructor name.\n\ttry {\n\t\tlet proto: object | null = Object.getPrototypeOf(candidate);\n\t\tfor (let depth = 0; proto !== null && depth < 20; depth++) {\n\t\t\tif (\n\t\t\t\t(proto.constructor as { name?: unknown } | undefined)?.name === name\n\t\t\t) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tproto = Object.getPrototypeOf(proto);\n\t\t}\n\t} catch {\n\t\t// Hostile `constructor` getter on a prototype: non-matching.\n\t}\n\treturn false;\n}\n\nexport function describeError(error: unknown): string {\n\tif (error instanceof Error) {\n\t\tconst chain = causeChainNames(error);\n\t\tconst suffix =\n\t\t\tchain.length > 1 ? ` (cause chain: ${chain.join(\" -> \")})` : \"\";\n\t\treturn `${error.name}: ${error.message}${suffix}`;\n\t}\n\treturn String(error);\n}\n\n/**\n * Names along the `cause` chain (cycle-safe, hostile-getter-safe), for\n * failure diagnostics: a wrapped rejection shows WHAT it wraps, so an\n * unexpected error deep in the chain (a raw driver error, or an error\n * from a different kit copy) is identifiable from the message alone.\n */\nfunction causeChainNames(error: Error): string[] {\n\tconst names: string[] = [];\n\twalkCauseChain(error, (node) => {\n\t\ttry {\n\t\t\tconst { name } = node as { name?: unknown };\n\t\t\tnames.push(typeof name === \"string\" ? name : \"(unnamed)\");\n\t\t} catch {\n\t\t\t// Hostile `name` getter: stop with the partial chain collected.\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t});\n\treturn names;\n}\n","import type { PublishedCommand } from \"../application/cqrs/command/command\";\nimport type {\n\tCommandOutboxCommitCandidate,\n\tCommandOutboxWriter,\n\tDurableCommandMessage,\n} from \"../application/cqrs/command/command-outbox\";\nimport { deepEqual } from \"../internal/structural/deep-equal\";\nimport {\n\tassert,\n\tassertEqual,\n\tbindContractEnvironment,\n\ttype ContractTest,\n\tcaptureRejection,\n\tgatedContractTest,\n} from \"./contract-assertions\";\n\nexport interface CommandOutboxContractEnvironment<C extends PublishedCommand> {\n\treadonly outbox: CommandOutboxWriter<C>;\n\treadonly addCommitted: (\n\t\tcommits: ReadonlyArray<CommandOutboxCommitCandidate<C>>,\n\t) => Promise<void>;\n\treadonly addRolledBack?: (\n\t\tcommits: ReadonlyArray<CommandOutboxCommitCandidate<C>>,\n\t) => Promise<void>;\n\treadonly readAll: () => Promise<\n\t\tReadonlyArray<CommandOutboxCommitCandidate<C>>\n\t>;\n\treadonly teardown?: () => Promise<void>;\n}\n\nexport interface CommandOutboxContractHarness<C extends PublishedCommand> {\n\treadonly createEnvironment: () => Promise<\n\t\tCommandOutboxContractEnvironment<C>\n\t>;\n\t/**\n\t * Builds one command for the given seed. The suite derives conflicting\n\t * commits from different seeds, so `createCommand` MUST return distinct\n\t * command content per seed (put the seed in the payload). A constant\n\t * command makes a manufactured conflict deep-equal to its original, and\n\t * the conflict tests then fail a compliant adapter that deduplicates\n\t * the exact retry.\n\t */\n\treadonly createCommand: (seed: number) => C;\n\treadonly providesRolledBackAdds?: boolean;\n}\n\nexport type CommandOutboxContractTest = ContractTest;\n\nexport function createCommandOutboxContractTests<C extends PublishedCommand>(\n\tharness: CommandOutboxContractHarness<C>,\n): ReadonlyArray<CommandOutboxContractTest> {\n\tconst inEnv = bindContractEnvironment(harness.createEnvironment);\n\tconst commit = (\n\t\tseed: number,\n\t\tcommandSeeds: ReadonlyArray<number> = [seed],\n\t): CommandOutboxCommitCandidate<C> => ({\n\t\torigin: {\n\t\t\teventId: `process-event-${seed}`,\n\t\t\tsource: {\n\t\t\t\taggregateType: \"CheckoutProcess\",\n\t\t\t\taggregateId: \"order-1\",\n\t\t\t},\n\t\t\tposition: {\n\t\t\t\taggregateVersion: seed,\n\t\t\t\tcommitSequence: 0,\n\t\t\t\tcommitSize: 1,\n\t\t\t},\n\t\t},\n\t\tmessages: commandSeeds.map((commandSeed, index) =>\n\t\t\tmessage(seed, index, harness.createCommand(commandSeed)),\n\t\t),\n\t});\n\tconst tests: CommandOutboxContractTest[] = [\n\t\t{\n\t\t\tname: \"deduplicates an exact retry by origin event id\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst original = commit(1);\n\t\t\t\tawait env.addCommitted([original]);\n\t\t\t\tawait env.addCommitted([original]);\n\t\t\t\tconst stored = await env.readAll();\n\t\t\t\tassertEqual(\n\t\t\t\t\tstored.length,\n\t\t\t\t\t1,\n\t\t\t\t\t\"an exact retry must retain one receipt, not append a duplicate\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(stored[0], original),\n\t\t\t\t\t\"an exact retry must preserve the original receipt and commands\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"rejects conflicting reuse of an origin event id\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst original = commit(1);\n\t\t\t\tawait env.addCommitted([original]);\n\t\t\t\tconst conflict = {\n\t\t\t\t\t...commit(1, [99]),\n\t\t\t\t\torigin: {\n\t\t\t\t\t\t...commit(1, [99]).origin,\n\t\t\t\t\t\teventId: original.origin.eventId,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tassert(\n\t\t\t\t\t!deepEqual(conflict.messages, original.messages),\n\t\t\t\t\t\"harness contract: createCommand must return distinct content \" +\n\t\t\t\t\t\t\"per seed, or the manufactured conflict is an exact retry\",\n\t\t\t\t);\n\t\t\t\tconst rejection = await captureRejection(env.addCommitted([conflict]));\n\t\t\t\tassert(\n\t\t\t\t\trejection !== undefined,\n\t\t\t\t\t\"a reused origin event id with different messages must reject\",\n\t\t\t\t);\n\t\t\t\tconst stored = await env.readAll();\n\t\t\t\tassertEqual(\n\t\t\t\t\tstored.length,\n\t\t\t\t\t1,\n\t\t\t\t\t\"a conflicting retry must not append another receipt\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(stored[0], original),\n\t\t\t\t\t\"a conflicting retry must not replace the original receipt\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"rejects an origin event id reused with a different source\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst original = commit(1);\n\t\t\t\tawait env.addCommitted([original]);\n\t\t\t\tconst conflicts: ReadonlyArray<{\n\t\t\t\t\treadonly fact: \"aggregateId\" | \"aggregateType\";\n\t\t\t\t\treadonly candidate: CommandOutboxCommitCandidate<C>;\n\t\t\t\t}> = [\n\t\t\t\t\t{\n\t\t\t\t\t\tfact: \"aggregateId\",\n\t\t\t\t\t\tcandidate: {\n\t\t\t\t\t\t\t...original,\n\t\t\t\t\t\t\torigin: {\n\t\t\t\t\t\t\t\t...original.origin,\n\t\t\t\t\t\t\t\tsource: {\n\t\t\t\t\t\t\t\t\t...original.origin.source,\n\t\t\t\t\t\t\t\t\taggregateId: \"order-2\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfact: \"aggregateType\",\n\t\t\t\t\t\tcandidate: {\n\t\t\t\t\t\t\t...original,\n\t\t\t\t\t\t\torigin: {\n\t\t\t\t\t\t\t\t...original.origin,\n\t\t\t\t\t\t\t\tsource: {\n\t\t\t\t\t\t\t\t\t...original.origin.source,\n\t\t\t\t\t\t\t\t\taggregateType: \"Order\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t\tfor (const { fact, candidate } of conflicts) {\n\t\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\t\tenv.addCommitted([candidate]),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\trejection !== undefined,\n\t\t\t\t\t\t`a reused origin event id with a different source.${fact} must reject`,\n\t\t\t\t\t);\n\t\t\t\t\tconst stored = await env.readAll();\n\t\t\t\t\tassert(\n\t\t\t\t\t\tdeepEqual(stored, [original]),\n\t\t\t\t\t\t`a source.${fact} conflict must leave the original receipt unchanged`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"rejects an origin event id reused with a different position\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst original = commit(1);\n\t\t\t\tawait env.addCommitted([original]);\n\t\t\t\tconst positions = [\n\t\t\t\t\t{ fact: \"aggregateVersion\", change: { aggregateVersion: 2 } },\n\t\t\t\t\t{ fact: \"commitSequence\", change: { commitSequence: 1 } },\n\t\t\t\t\t{ fact: \"commitSize\", change: { commitSize: 2 } },\n\t\t\t\t] as const;\n\t\t\t\tfor (const { fact, change } of positions) {\n\t\t\t\t\tconst conflict: CommandOutboxCommitCandidate<C> = {\n\t\t\t\t\t\t...original,\n\t\t\t\t\t\torigin: {\n\t\t\t\t\t\t\t...original.origin,\n\t\t\t\t\t\t\tposition: {\n\t\t\t\t\t\t\t\t...original.origin.position,\n\t\t\t\t\t\t\t\t...change,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\t\tenv.addCommitted([conflict]),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\trejection !== undefined,\n\t\t\t\t\t\t`a reused origin event id with a different position.${fact} must reject`,\n\t\t\t\t\t);\n\t\t\t\t\tconst stored = await env.readAll();\n\t\t\t\t\tassert(\n\t\t\t\t\t\tdeepEqual(stored, [original]),\n\t\t\t\t\t\t`a position.${fact} conflict must leave the original receipt unchanged`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"rejects a conflicting batch atomically\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst original = commit(1);\n\t\t\t\tawait env.addCommitted([original]);\n\t\t\t\tconst newCommit = commit(2);\n\t\t\t\tconst conflictingOriginal = {\n\t\t\t\t\t...commit(1, [77]),\n\t\t\t\t\torigin: {\n\t\t\t\t\t\t...commit(1, [77]).origin,\n\t\t\t\t\t\teventId: original.origin.eventId,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tassert(\n\t\t\t\t\t!deepEqual(conflictingOriginal.messages, original.messages),\n\t\t\t\t\t\"harness contract: createCommand must return distinct content \" +\n\t\t\t\t\t\t\"per seed, or the manufactured conflict is an exact retry\",\n\t\t\t\t);\n\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\tenv.addCommitted([newCommit, conflictingOriginal]),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\trejection !== undefined,\n\t\t\t\t\t\"a batch containing a conflicting origin must reject\",\n\t\t\t\t);\n\t\t\t\tconst stored = await env.readAll();\n\t\t\t\tassertEqual(\n\t\t\t\t\tstored.length,\n\t\t\t\t\t1,\n\t\t\t\t\t\"a rejected batch must not leave its earlier new receipt behind\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(stored[0], original),\n\t\t\t\t\t\"a rejected batch must preserve the pre-existing receipt\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"retains command and commit input order\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst first = commit(1, [10, 11]);\n\t\t\t\tconst second = commit(2, [20, 21]);\n\t\t\t\tawait env.addCommitted([first, second]);\n\t\t\t\tconst stored = await env.readAll();\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\tstored.map(({ origin }) => origin.eventId),\n\t\t\t\t\t\t[first.origin.eventId, second.origin.eventId],\n\t\t\t\t\t),\n\t\t\t\t\t\"commit receipts must retain input order\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\tstored.map(({ messages }) =>\n\t\t\t\t\t\t\tmessages.map(({ command }) => command),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\tfirst.messages.map(({ command }) => command),\n\t\t\t\t\t\t\tsecond.messages.map(({ command }) => command),\n\t\t\t\t\t\t],\n\t\t\t\t\t),\n\t\t\t\t\t\"commands inside each receipt must retain mapper order\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"retains every position in a multi-event aggregate commit\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst first = commit(10);\n\t\t\t\tconst second = commit(11);\n\t\t\t\tconst commitSize = 2;\n\t\t\t\tconst aggregateVersion = 7;\n\t\t\t\tconst multiEventCommit: ReadonlyArray<CommandOutboxCommitCandidate<C>> =\n\t\t\t\t\t[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t...first,\n\t\t\t\t\t\t\torigin: {\n\t\t\t\t\t\t\t\t...first.origin,\n\t\t\t\t\t\t\t\tposition: {\n\t\t\t\t\t\t\t\t\taggregateVersion,\n\t\t\t\t\t\t\t\t\tcommitSequence: 0,\n\t\t\t\t\t\t\t\t\tcommitSize,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t...second,\n\t\t\t\t\t\t\torigin: {\n\t\t\t\t\t\t\t\t...second.origin,\n\t\t\t\t\t\t\t\tposition: {\n\t\t\t\t\t\t\t\t\taggregateVersion,\n\t\t\t\t\t\t\t\t\tcommitSequence: 1,\n\t\t\t\t\t\t\t\t\tcommitSize,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\tawait env.addCommitted(multiEventCommit);\n\t\t\t\tconst stored = await env.readAll();\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(stored, multiEventCommit),\n\t\t\t\t\t\"a multi-event commit must retain its shared version, sequence, and size for every receipt\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"retains an empty command receipt and advances the source cursor\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst empty = commit(1, []);\n\t\t\t\tconst next = commit(2);\n\t\t\t\tawait env.addCommitted([empty]);\n\t\t\t\tawait env.addCommitted([next]);\n\t\t\t\tconst stored = await env.readAll();\n\t\t\t\tassertEqual(\n\t\t\t\t\tstored.length,\n\t\t\t\t\t2,\n\t\t\t\t\t\"an empty command batch must retain its source receipt\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tstored[0]?.messages.length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"the retained empty receipt must contain no invented command\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\tstored.map(({ origin }) => origin.position.aggregateVersion),\n\t\t\t\t\t\t[1, 2],\n\t\t\t\t\t),\n\t\t\t\t\t\"the source cursor must advance through the empty receipt\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t];\n\ttests.push(\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"providesRolledBackAdds\",\n\t\t\t\tsatisfiedBy: harness.providesRolledBackAdds === true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"a rolled-back add leaves no receipt or command behind\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tif (!env.addRolledBack) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Contract violated: harness declared providesRolledBackAdds but the environment lacks addRolledBack\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait env.addRolledBack([commit(1)]);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\t(await env.readAll()).length,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t\"a rolled-back transaction must persist no command receipt\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t);\n\treturn tests;\n}\n\nfunction message<C extends PublishedCommand>(\n\tcommitSeed: number,\n\tindex: number,\n\tcommand: C,\n): DurableCommandMessage<C> {\n\treturn {\n\t\tmessageId: `process-event-${commitSeed}:command:${index}`,\n\t\trecordedAt: \"2027-04-05T06:07:08.000Z\",\n\t\tdestination: \"participant.commands\",\n\t\tcommand,\n\t\tconversationId: \"checkout-order-1\",\n\t\tcausationId: `process-event-${commitSeed}`,\n\t};\n}\n","import type {\n\tDeadLetterDeadline,\n\tDeadlineStore,\n} from \"../application/deadlines/deadline-store\";\nimport { deepEqual } from \"../internal/structural/deep-equal\";\nimport {\n\tassert,\n\tassertEqual,\n\tbindContractEnvironment,\n\ttype ContractTest,\n\tgatedContractTest,\n} from \"./contract-assertions\";\n\n/** One contract test; bind with `(test.skipped ? it.skip : it)(test.name, test.run)`. */\nexport type DeadlineStoreContractTest = ContractTest;\n\n/** The plain-data payload shape the suite round-trips. */\ninterface SuitePayload {\n\tkind: string;\n\tstep?: number;\n}\n\n/**\n * One isolated test environment: a fresh deadline store. The suite\n * creates one per test and tears it down afterwards.\n */\nexport interface DeadlineStoreContractEnvironment {\n\t/** The adapter under test. */\n\tstore: DeadlineStore<SuitePayload>;\n\n\t/**\n\t * Runs `work` (schedule/cancel calls) the way production does:\n\t * inside a transaction that COMMITS. For a non-transactional store\n\t * this simply invokes `work`.\n\t */\n\trun<R>(work: () => Promise<R>): Promise<R>;\n\n\t/**\n\t * Optional capability: runs `work` inside a transaction that ROLLS\n\t * BACK. Enables the rollback tests: a rolled-back schedule must not\n\t * leave a deadline behind (a ghost input for a state change that\n\t * never happened), and a rolled-back cancel must not have removed\n\t * one. Transactional adapters should always provide this.\n\t */\n\trunRolledBack?<R>(work: () => Promise<R>): Promise<R>;\n\n\t/** Release connections, drop schemas, etc. Called in a finally. */\n\tteardown?(): Promise<void>;\n}\n\n/**\n * What an adapter supplies to run the deadline-store contract suite.\n * For SQL adapters, run against a real database (testcontainers or\n * equivalent): the rollback tests prove YOUR transaction wiring, and\n * schedule/cancel joining the write transaction is the port's central\n * correctness rule.\n */\nexport interface DeadlineStoreContractHarness {\n\tcreateEnvironment(): Promise<DeadlineStoreContractEnvironment>;\n\n\t/**\n\t * The adapter's attempt ceiling: how many `markFailed` reports move\n\t * a deadline to the dead-letter set. Must be at least 2 so the\n\t * attempts-surfacing test can observe a survivor.\n\t */\n\tfailuresToDeadLetter: number;\n\n\t/**\n\t * Declare `true` when environments provide {@link\n\t * DeadlineStoreContractEnvironment.runRolledBack}. Without it, the\n\t * rollback tests are marked skipped: the honest state of an\n\t * in-memory fake, and a loud gap for a transactional adapter.\n\t */\n\tprovidesRolledBackRuns?: boolean;\n\n\t/**\n\t * Declare `true` when the adapter's `due` CLAIMS the returned\n\t * records for competing pollers (lease, visibility timeout), as the\n\t * port sanctions. Tests that re-poll records an earlier poll\n\t * returned without resolving them (attempts surfacing, neighbor\n\t * flow after a dead-letter, successor visibility during a\n\t * reschedule race) assume a non-claiming read and are marked\n\t * skipped for claiming adapters; prove your claim/expiry semantics\n\t * in your own suite.\n\t */\n\tclaimsOnDue?: boolean;\n}\n\nconst at = (iso: string): Date => new Date(iso);\nconst T0 = \"2026-03-01T10:00:00.000Z\";\nconst T1 = \"2026-03-01T10:05:00.000Z\";\nconst T2 = \"2026-03-01T10:10:00.000Z\";\n\n/**\n * The deadline-store contract test suite: the proof that an adapter\n * delivers the schedule/cancel/due/acknowledge semantics the port\n * documents. Store semantics are an **adapter contract, not a kit\n * guarantee**; this suite is how an adapter demonstrates them.\n *\n * Framework-agnostic: bind with\n * `(test.skipped ? it.skip : it)(test.name, test.run)`.\n */\nexport function createDeadlineStoreContractTests(\n\tharness: DeadlineStoreContractHarness,\n): DeadlineStoreContractTest[] {\n\tconst inEnv = bindContractEnvironment(() => harness.createEnvironment());\n\tconst ceiling = harness.failuresToDeadLetter;\n\tif (!Number.isInteger(ceiling) || ceiling < 2) {\n\t\tthrow new Error(\n\t\t\t\"Contract violated: failuresToDeadLetter must be an integer >= 2; observing attempts on a pending deadline needs one that survives a failure\",\n\t\t);\n\t}\n\n\treturn [\n\t\t{\n\t\t\tname: \"a deadline is invisible before its due time and delivered from it onward\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(() =>\n\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\tscope: \"checkout-saga\",\n\t\t\t\t\t\tkey: \"order-1\",\n\t\t\t\t\t\tdueAt: at(T1),\n\t\t\t\t\t\tpayload: { kind: \"payment-timeout\" },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await env.store.due(at(T0), 10)).length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"a deadline must not fire early\",\n\t\t\t\t);\n\t\t\t\tconst dueExactly = await env.store.due(at(T1), 10);\n\t\t\t\tassertEqual(\n\t\t\t\t\tdueExactly.length,\n\t\t\t\t\t1,\n\t\t\t\t\t\"a deadline is due AT its due time (dueAt <= now)\",\n\t\t\t\t);\n\t\t\t\tconst record = dueExactly[0];\n\t\t\t\tassert(record !== undefined, \"expected the due deadline\");\n\t\t\t\tassertEqual(record.scope, \"checkout-saga\", \"scope must round-trip\");\n\t\t\t\tassertEqual(record.key, \"order-1\", \"key must round-trip\");\n\t\t\t\tassertEqual(\n\t\t\t\t\trecord.dueAt.getTime(),\n\t\t\t\t\tat(T1).getTime(),\n\t\t\t\t\t\"dueAt must round-trip with millisecond fidelity\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(record.payload, { kind: \"payment-timeout\" }),\n\t\t\t\t\t\"the payload must round-trip as plain data\",\n\t\t\t\t);\n\t\t\t\tassertEqual(record.attempts, 0, \"a fresh deadline has no attempts\");\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"due returns earliest first and respects the limit\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(async () => {\n\t\t\t\t\tawait env.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"late\",\n\t\t\t\t\t\tdueAt: at(T2),\n\t\t\t\t\t\tpayload: { kind: \"late\" },\n\t\t\t\t\t});\n\t\t\t\t\tawait env.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"early\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"early\" },\n\t\t\t\t\t});\n\t\t\t\t\tawait env.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"middle\",\n\t\t\t\t\t\tdueAt: at(T1),\n\t\t\t\t\t\tpayload: { kind: \"middle\" },\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\tconst firstPage = await env.store.due(at(T2), 2);\n\t\t\t\tassert(\n\t\t\t\t\tfirstPage.length >= 1 && firstPage.length <= 2,\n\t\t\t\t\t\"limit must bound the page: up to limit records, at least one while deadlines are due\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tfirstPage[0]?.key,\n\t\t\t\t\t\"early\",\n\t\t\t\t\t\"the earliest due deadline comes first\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"markDelivered consumes the deadline and is idempotent on unknown and repeated ids\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(() =>\n\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"k\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"x\" },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst [record] = await env.store.due(at(T1), 10);\n\t\t\t\tassert(record !== undefined, \"expected a due deadline\");\n\t\t\t\tawait env.store.markDelivered([record.deliveryId]);\n\t\t\t\tawait env.store.markDelivered([record.deliveryId]);\n\t\t\t\tawait env.store.markDelivered([\"no-such-delivery-id\"]);\n\t\t\t\tassert(\n\t\t\t\t\t!(await env.store.due(at(T2), 10)).some(\n\t\t\t\t\t\t(d) => d.deliveryId === record.deliveryId,\n\t\t\t\t\t),\n\t\t\t\t\t\"a delivered deadline must never come back\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"cancel removes exactly the addressed deadline and tolerates unknown addresses\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(async () => {\n\t\t\t\t\tawait env.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"keep\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"keep\" },\n\t\t\t\t\t});\n\t\t\t\t\tawait env.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"drop\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"drop\" },\n\t\t\t\t\t});\n\t\t\t\t\tawait env.store.cancel(\"s\", \"drop\");\n\t\t\t\t\tawait env.store.cancel(\"s\", \"never-scheduled\");\n\t\t\t\t});\n\t\t\t\tconst due = await env.store.due(at(T1), 10);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\tdue.map((d) => d.key),\n\t\t\t\t\t\t[\"keep\"],\n\t\t\t\t\t),\n\t\t\t\t\t\"cancel must remove the addressed deadline and nothing else\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"addresses are isolated per scope\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(async () => {\n\t\t\t\t\tawait env.store.schedule({\n\t\t\t\t\t\tscope: \"reservation-hold\",\n\t\t\t\t\t\tkey: \"id-1\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"hold\" },\n\t\t\t\t\t});\n\t\t\t\t\tawait env.store.schedule({\n\t\t\t\t\t\tscope: \"checkout-saga\",\n\t\t\t\t\t\tkey: \"id-1\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"timeout\" },\n\t\t\t\t\t});\n\t\t\t\t\tawait env.store.cancel(\"reservation-hold\", \"id-1\");\n\t\t\t\t});\n\t\t\t\tconst due = await env.store.due(at(T1), 10);\n\t\t\t\tassert(\n\t\t\t\t\tdue.length === 1 && due[0]?.scope === \"checkout-saga\",\n\t\t\t\t\t\"the same key under another scope is a different deadline\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t// The successor-visibility half of the race needs a re-poll while the\n\t\t// replaced incarnation is un-acked; an adapter claiming at address\n\t\t// granularity legitimately holds the address until the claim resolves.\n\t\tgatedContractTest(\n\t\t\t{ capability: \"non-claiming due\", satisfiedBy: !harness.claimsOnDue },\n\t\t\t{\n\t\t\t\tname: \"schedule on an occupied address replaces it, and a stale ack cannot consume the successor\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tawait env.run(() =>\n\t\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\t\tkey: \"k\",\n\t\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\t\tpayload: { kind: \"first\", step: 1 },\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tconst [first] = await env.store.due(at(T1), 10);\n\t\t\t\t\tassert(first !== undefined, \"expected the first incarnation\");\n\n\t\t\t\t\t// Reschedule while the first incarnation is in flight.\n\t\t\t\t\tawait env.run(() =>\n\t\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\t\tkey: \"k\",\n\t\t\t\t\t\t\tdueAt: at(T1),\n\t\t\t\t\t\t\tpayload: { kind: \"second\", step: 2 },\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\t// The late ack of the replaced incarnation must be a no-op.\n\t\t\t\t\tawait env.store.markDelivered([first.deliveryId]);\n\n\t\t\t\t\tconst due = await env.store.due(at(T2), 10);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tdue.length,\n\t\t\t\t\t\t1,\n\t\t\t\t\t\t\"exactly one pending deadline exists per address\",\n\t\t\t\t\t);\n\t\t\t\t\tconst successor = due[0];\n\t\t\t\t\tassert(successor !== undefined, \"expected the successor\");\n\t\t\t\t\tassert(\n\t\t\t\t\t\tdeepEqual(successor.payload, { kind: \"second\", step: 2 }),\n\t\t\t\t\t\t\"the successor carries the rescheduled payload\",\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tsuccessor.deliveryId !== first.deliveryId,\n\t\t\t\t\t\t\"a reschedule is a fresh incarnation with a fresh deliveryId\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\t{\n\t\t\tname: \"after delivery the address is free again for a fresh schedule\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(() =>\n\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"k\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"first\" },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst [first] = await env.store.due(at(T1), 10);\n\t\t\t\tassert(first !== undefined, \"expected a due deadline\");\n\t\t\t\tawait env.store.markDelivered([first.deliveryId]);\n\t\t\t\tawait env.run(() =>\n\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"k\",\n\t\t\t\t\t\tdueAt: at(T1),\n\t\t\t\t\t\tpayload: { kind: \"again\" },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst due = await env.store.due(at(T2), 10);\n\t\t\t\tassert(\n\t\t\t\t\tdue.length === 1 && deepEqual(due[0]?.payload, { kind: \"again\" }),\n\t\t\t\t\t\"a consumed address must accept a new deadline\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"the attempt ceiling dead-letters the deadline, visible in deadLetters with its attempt count\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(() =>\n\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"poison\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"poison\" },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst [poison] = await env.store.due(at(T1), 1);\n\t\t\t\tassert(poison !== undefined, \"expected the due deadline\");\n\t\t\t\tlet transition: DeadLetterDeadline<SuitePayload> | undefined;\n\t\t\t\tfor (let i = 0; i < ceiling; i++) {\n\t\t\t\t\tconst current = await env.store.markFailed(\n\t\t\t\t\t\tpoison.deliveryId,\n\t\t\t\t\t\tnew Error(\"boom\"),\n\t\t\t\t\t);\n\t\t\t\t\tif (i < ceiling - 1) {\n\t\t\t\t\t\tassertEqual(\n\t\t\t\t\t\t\tcurrent,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\"markFailed must not report a dead-letter transition below the ceiling\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\ttransition = current;\n\t\t\t\t}\n\t\t\t\tassertEqual(\n\t\t\t\t\ttransition?.deliveryId,\n\t\t\t\t\tpoison.deliveryId,\n\t\t\t\t\t\"the ceiling-crossing markFailed call must return the exact dead-letter transition\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\ttransition?.attempts,\n\t\t\t\t\tceiling,\n\t\t\t\t\t\"the returned transition must carry the final attempt count\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait env.store.markFailed(poison.deliveryId, new Error(\"late\")),\n\t\t\t\t\tundefined,\n\t\t\t\t\t\"a late failure report must not repeat the dead-letter transition\",\n\t\t\t\t);\n\t\t\t\t// Membership, not count: dead-lettered is terminal for every\n\t\t\t\t// adapter, claiming or not.\n\t\t\t\tassert(\n\t\t\t\t\t!(await env.store.due(at(T2), 10)).some(\n\t\t\t\t\t\t(d) => d.deliveryId === poison.deliveryId,\n\t\t\t\t\t),\n\t\t\t\t\t\"a dead-lettered deadline must stop coming back\",\n\t\t\t\t);\n\t\t\t\tconst dead = await env.store.deadLetters();\n\t\t\t\tassert(\n\t\t\t\t\tdead.length === 1 && dead[0]?.attempts === ceiling,\n\t\t\t\t\t\"the dead-lettered deadline must appear in deadLetters() with its attempt count\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t// Observing attempts on a pending record, and a neighbor's continued\n\t\t// flow, both need re-polls of records an earlier poll returned\n\t\t// without resolving them; claiming adapters legitimately hold those\n\t\t// back until the claim expires.\n\t\tgatedContractTest(\n\t\t\t{ capability: \"non-claiming due\", satisfiedBy: !harness.claimsOnDue },\n\t\t\t{\n\t\t\t\tname: \"attempts surface on redelivery, and a poison deadline does not block its neighbors\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tawait env.run(async () => {\n\t\t\t\t\t\tawait env.store.schedule({\n\t\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\t\tkey: \"poison\",\n\t\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\t\tpayload: { kind: \"poison\" },\n\t\t\t\t\t\t});\n\t\t\t\t\t\tawait env.store.schedule({\n\t\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\t\tkey: \"healthy\",\n\t\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\t\tpayload: { kind: \"healthy\" },\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t\tconst [poison] = await env.store.due(at(T1), 1);\n\t\t\t\t\tassert(poison !== undefined, \"expected the earliest due deadline\");\n\t\t\t\t\tawait env.store.markFailed(poison.deliveryId, new Error(\"boom\"));\n\t\t\t\t\tconst afterOne = await env.store.due(at(T1), 10);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tafterOne.find((d) => d.deliveryId === poison.deliveryId)?.attempts,\n\t\t\t\t\t\t1,\n\t\t\t\t\t\t\"attempts must be surfaced on the record after markFailed\",\n\t\t\t\t\t);\n\t\t\t\t\tfor (let i = 1; i < ceiling; i++) {\n\t\t\t\t\t\tawait env.store.markFailed(poison.deliveryId, new Error(\"boom\"));\n\t\t\t\t\t}\n\t\t\t\t\tassert(\n\t\t\t\t\t\t(await env.store.due(at(T1), 10)).some((d) => d.key === \"healthy\"),\n\t\t\t\t\t\t\"deadlines carry no cross-address ordering; a dead-lettered neighbor must not block delivery\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\t{\n\t\t\tname: \"two dead-lettered incarnations of one address are both kept and individually clearable\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(() =>\n\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"k\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"first\" },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst [first] = await env.store.due(at(T1), 10);\n\t\t\t\tassert(first !== undefined, \"expected the first incarnation\");\n\t\t\t\tfor (let i = 0; i < ceiling; i++) {\n\t\t\t\t\tawait env.store.markFailed(first.deliveryId, new Error(\"boom\"));\n\t\t\t\t}\n\t\t\t\t// The dead letter freed the address; the process schedules a\n\t\t\t\t// fresh incarnation, and it dead-letters too.\n\t\t\t\tawait env.run(() =>\n\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"k\",\n\t\t\t\t\t\tdueAt: at(T1),\n\t\t\t\t\t\tpayload: { kind: \"second\" },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst [second] = await env.store.due(at(T2), 10);\n\t\t\t\tassert(second !== undefined, \"expected the second incarnation\");\n\t\t\t\tfor (let i = 0; i < ceiling; i++) {\n\t\t\t\t\tawait env.store.markFailed(second.deliveryId, new Error(\"boom\"));\n\t\t\t\t}\n\t\t\t\tconst dead = await env.store.deadLetters();\n\t\t\t\tassert(\n\t\t\t\t\tdead.length === 2 &&\n\t\t\t\t\t\tdead.some((d) => d.deliveryId === first.deliveryId) &&\n\t\t\t\t\t\tdead.some((d) => d.deliveryId === second.deliveryId),\n\t\t\t\t\t\"dead letters are kept per incarnation; a later dead letter of the same address must not overwrite an earlier un-acked one\",\n\t\t\t\t);\n\t\t\t\tawait env.store.markDelivered([first.deliveryId]);\n\t\t\t\tconst remaining = await env.store.deadLetters();\n\t\t\t\tassert(\n\t\t\t\t\tremaining.length === 1 &&\n\t\t\t\t\t\tremaining[0]?.deliveryId === second.deliveryId,\n\t\t\t\t\t\"acknowledging one dead-lettered incarnation must not clear its sibling\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"late failure reports never resurrect or advance anything, and acking a dead letter clears it\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(() =>\n\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"k\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"x\" },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst [record] = await env.store.due(at(T1), 10);\n\t\t\t\tassert(record !== undefined, \"expected a due deadline\");\n\t\t\t\tfor (let i = 0; i < ceiling; i++) {\n\t\t\t\t\tawait env.store.markFailed(record.deliveryId, new Error(\"boom\"));\n\t\t\t\t}\n\t\t\t\t// Late reports against a dead-lettered incarnation: no-ops.\n\t\t\t\tawait env.store.markFailed(record.deliveryId, new Error(\"late\"));\n\t\t\t\tawait env.store.markFailed(\"no-such-id\", new Error(\"unknown\"));\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await env.store.deadLetters()).length,\n\t\t\t\t\t1,\n\t\t\t\t\t\"late or unknown failure reports must not change the dead-letter set\",\n\t\t\t\t);\n\t\t\t\t// Manual redelivery, then ack: the dead letter clears.\n\t\t\t\tawait env.store.markDelivered([record.deliveryId]);\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await env.store.deadLetters()).length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"acking a dead-lettered deadline must clear it\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"providesRolledBackRuns\",\n\t\t\t\tsatisfiedBy: harness.providesRolledBackRuns === true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"a rolled-back schedule leaves no deadline behind\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tif (!env.runRolledBack) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Contract violated: harness declared providesRolledBackRuns but the environment lacks runRolledBack\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait env\n\t\t\t\t\t\t.runRolledBack(() =>\n\t\t\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\t\t\tkey: \"ghost\",\n\t\t\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\t\t\tpayload: { kind: \"ghost\" },\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\t\t// The rollback mechanism may surface as a rejection; the\n\t\t\t\t\t\t\t// contract under test is the store state afterwards.\n\t\t\t\t\t\t});\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\t(await env.store.due(at(T2), 10)).length,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t\"a deadline from a rolled-back transaction is a ghost input and must not exist\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"providesRolledBackRuns\",\n\t\t\t\tsatisfiedBy: harness.providesRolledBackRuns === true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"a rolled-back cancel leaves the deadline in place\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tif (!env.runRolledBack) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Contract violated: harness declared providesRolledBackRuns but the environment lacks runRolledBack\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait env.run(() =>\n\t\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\t\tkey: \"k\",\n\t\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\t\tpayload: { kind: \"x\" },\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tawait env\n\t\t\t\t\t\t.runRolledBack(() => env.store.cancel(\"s\", \"k\"))\n\t\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\t\t// See above: only the state afterwards is the contract.\n\t\t\t\t\t\t});\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\t(await env.store.due(at(T1), 10)).length,\n\t\t\t\t\t\t1,\n\t\t\t\t\t\t\"a cancel from a rolled-back transaction must not have removed the deadline\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t];\n}\n","import type { Aggregate } from \"../domain/aggregate/aggregate\";\nimport type { AggregateAddress } from \"../domain/aggregate/aggregate-address\";\nimport type {\n\tAnyDomainEvent,\n\tPendingDomainEvent,\n} from \"../domain/event/domain-event\";\nimport type { Id } from \"../domain/identity/id\";\nimport { deepEqual } from \"../internal/structural/deep-equal\";\nimport type { CommittedDomainEvent } from \"../messaging/committed-event\";\nimport type {\n\tReadStreamOptions,\n\tStreamReadResult,\n} from \"../persistence/event-store/event-store\";\nimport {\n\tassert,\n\tassertChainContainsKitError,\n\tassertEqual,\n\tawaitOverlappingCall,\n\tbindContractEnvironment,\n\ttype ContractTest,\n\tcaptureRejection,\n\tdescribeError,\n\tgatedContractTest,\n\tloadAggregateOrFail,\n\tOVERLAPPING_CALLS_BOUND_MS,\n\toverlappingCallsPreflight,\n\tparkRunCall,\n\trecordedPendingEventIds,\n\tsortedCommittedEventIds,\n} from \"./contract-assertions\";\n\n/** Event-sourced repositories normally expose no physical removal. */\nexport interface EsContractRepository<\n\tTAggregate extends Aggregate<Id<string>, AnyDomainEvent>,\n> {\n\tfindById(id: TAggregate[\"id\"]): Promise<TAggregate | undefined>;\n\tadd(aggregate: TAggregate): void;\n\tupdate(aggregate: TAggregate): void;\n}\n\nexport interface EsRepositoryContractEnvironment<\n\tTAggregate extends Aggregate<Id<string>, TEvent>,\n\tTEvent extends AnyDomainEvent = AnyDomainEvent,\n> {\n\trun<R>(\n\t\twork: (context: {\n\t\t\trepository: EsContractRepository<TAggregate>;\n\t\t}) => Promise<R>,\n\t): Promise<R>;\n\tcommittedOutboxEvents(): Promise<ReadonlyArray<CommittedDomainEvent<TEvent>>>;\n\tfailNextOutboxWrite(error: Error): void;\n\tcommittedStreamEvents(\n\t\tstream: AggregateAddress<TAggregate[\"id\"]>,\n\t\toptions: ReadStreamOptions,\n\t): Promise<StreamReadResult<TEvent>>;\n\tteardown?(): Promise<void>;\n}\n\nexport interface EsRepositoryContractHarness<\n\tTAggregate extends Aggregate<Id<string>, TEvent>,\n\tTEvent extends AnyDomainEvent = AnyDomainEvent,\n> {\n\tcreateEnvironment(): Promise<\n\t\tEsRepositoryContractEnvironment<TAggregate, TEvent>\n\t>;\n\t/** Fresh aggregate with exactly one recorded creation event. */\n\tcreateAggregate(): TAggregate;\n\tcreateAggregateWithId?(id: TAggregate[\"id\"]): TAggregate;\n\tstreamKeyFor(id: TAggregate[\"id\"]): AggregateAddress<TAggregate[\"id\"]>;\n\t/** Applies exactly one event and advances the aggregate version by one. */\n\tmutate(aggregate: TAggregate): void;\n\tsnapshotState?(aggregate: TAggregate): unknown;\n\t/**\n\t * Persists a snapshot of the aggregate at its current version in the\n\t * environment's snapshot store, so the next load there starts from it.\n\t * Enables the snapshot catch-up proof.\n\t */\n\tcaptureSnapshot?(\n\t\taggregate: TAggregate,\n\t\tenvironment: EsRepositoryContractEnvironment<TAggregate, TEvent>,\n\t): Promise<void>;\n\t/**\n\t * Bound for the overlapping `run` calls, in milliseconds: the second call\n\t * of the environment preflight, and the committing call of each\n\t * stale-writer proof. Raise it only for a second connection that needs\n\t * more time to open, or for a slow commit. Keep twice the bound, plus\n\t * environment creation and teardown, below the test timeout of the runner.\n\t */\n\toverlappingCallsBoundMs?: number;\n}\n\nexport type EsRepositoryContractTest = ContractTest;\n\n/**\n * Contract suite for event-stream adapters using v3 Unit-of-Work receipts.\n *\n * `add` and `update` register intent only. At commit, the adapter appends the\n * receipt's exact event batch with the Unit of Work's expected version, in the\n * same transaction as the outbox. `run` must support overlapping calls so the\n * mandatory stale-writer proof exercises a real stream OCC predicate.\n */\nexport function createEsRepositoryContractTests<\n\tTAggregate extends Aggregate<Id<string>, TEvent>,\n\tTEvent extends AnyDomainEvent = AnyDomainEvent,\n>(\n\tharness: EsRepositoryContractHarness<TAggregate, TEvent>,\n): EsRepositoryContractTest[] {\n\ttype Environment = EsRepositoryContractEnvironment<TAggregate, TEvent>;\n\tconst inEnvironment = bindContractEnvironment(() =>\n\t\tharness.createEnvironment(),\n\t);\n\tconst readAll = { limit: 100 } as const;\n\tconst createAggregateWithId = harness.createAggregateWithId;\n\tconst snapshotState = harness.snapshotState;\n\tconst captureSnapshot = harness.captureSnapshot;\n\tconst overlappingCallsBoundMs =\n\t\tharness.overlappingCallsBoundMs ?? OVERLAPPING_CALLS_BOUND_MS;\n\n\tconst load = (\n\t\trepository: EsContractRepository<TAggregate>,\n\t\tid: TAggregate[\"id\"],\n\t): Promise<TAggregate> =>\n\t\tloadAggregateOrFail(\n\t\t\trepository,\n\t\t\tid,\n\t\t\t\"the stream was not appended or replayed correctly\",\n\t\t);\n\tconst streamFor = (id: TAggregate[\"id\"]) => harness.streamKeyFor(id);\n\t// Pre-flush identities: the in-memory batch must be recorded before\n\t// the adapter may flush it.\n\tconst recordedIds = (\n\t\tevents: ReadonlyArray<PendingDomainEvent<TEvent>>,\n\t): string[] =>\n\t\trecordedPendingEventIds(\n\t\t\tevents,\n\t\t\t\"pending events must be recorded before flush\",\n\t\t);\n\t// Read-back identities: adapters may serialize committed events to rows\n\t// and decode them on read. A decoded event does not carry the in-memory\n\t// recorded brand, and no contract demands a re-mint on read, so only\n\t// the persisted identity is asserted here.\n\tconst ids = (events: ReadonlyArray<TEvent>): string[] =>\n\t\tevents.map((event) => {\n\t\t\tassert(\n\t\t\t\ttypeof event.eventId === \"string\" && event.eventId.length > 0,\n\t\t\t\t\"committed events must carry their persisted eventId\",\n\t\t\t);\n\t\t\treturn event.eventId;\n\t\t});\n\tconst outboxIds = (\n\t\tevents: ReadonlyArray<CommittedDomainEvent<TEvent>>,\n\t): string[] => sortedCommittedEventIds(events);\n\n\tasync function seed(environment: Environment): Promise<TAggregate> {\n\t\tconst aggregate = harness.createAggregate();\n\t\tawait environment.run(async ({ repository }) => {\n\t\t\trepository.add(aggregate);\n\t\t});\n\t\treturn aggregate;\n\t}\n\n\tconst tests: EsRepositoryContractTest[] = [\n\t\toverlappingCallsPreflight<Environment, TAggregate[\"id\"]>(\n\t\t\tinEnvironment,\n\t\t\t() => harness.createAggregate().id,\n\t\t\toverlappingCallsBoundMs,\n\t\t),\n\t\t{\n\t\t\tname: \"add appends the exact creation batch to stream and outbox\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tconst expectedIds = recordedIds(aggregate.pendingEvents);\n\t\t\t\tassertEqual(\n\t\t\t\t\texpectedIds.length,\n\t\t\t\t\t1,\n\t\t\t\t\t\"createAggregate must record exactly one creation event\",\n\t\t\t\t);\n\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t});\n\t\t\t\tconst stream = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(aggregate.id),\n\t\t\t\t\treadAll,\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tstream.exists && deepEqual(ids(stream.events), expectedIds),\n\t\t\t\t\t\"the stream must contain exactly the registered creation batch\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\toutboxIds(await environment.committedOutboxEvents()),\n\t\t\t\t\t\t[...expectedIds].sort(),\n\t\t\t\t\t),\n\t\t\t\t\t\"the outbox must contain the same exact creation batch\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\taggregate.pendingEvents.length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"successful commit must acknowledge the creation batch\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"MANDATORY stale append: writer B conflicts after writer A commits and appends no prefix\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\tconst writerB = await parkRunCall((hold) =>\n\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\tconst stale = await load(repository, seeded.id);\n\t\t\t\t\t\tawait hold();\n\t\t\t\t\t\tharness.mutate(stale);\n\t\t\t\t\t\tharness.mutate(stale);\n\t\t\t\t\t\trepository.update(stale);\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\tconst winner = await awaitOverlappingCall(\n\t\t\t\t\t() =>\n\t\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\t\tconst current = await load(repository, seeded.id);\n\t\t\t\t\t\t\tharness.mutate(current);\n\t\t\t\t\t\t\trepository.update(current);\n\t\t\t\t\t\t\treturn current;\n\t\t\t\t\t\t}),\n\t\t\t\t\twriterB,\n\t\t\t\t\toverlappingCallsBoundMs,\n\t\t\t\t);\n\t\t\t\tconst streamAfterWinner = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(seeded.id),\n\t\t\t\t\treadAll,\n\t\t\t\t);\n\t\t\t\twriterB.release();\n\t\t\t\tconst rejection = await captureRejection(writerB.call);\n\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\trejection,\n\t\t\t\t\t[\"CONCURRENCY_CONFLICT\"],\n\t\t\t\t\t`stale append must reject with ConcurrencyConflictError; got ${describeError(rejection)}`,\n\t\t\t\t);\n\t\t\t\tconst finalStream = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(seeded.id),\n\t\t\t\t\treadAll,\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tfinalStream.exists &&\n\t\t\t\t\t\tdeepEqual(ids(finalStream.events), ids(streamAfterWinner.events)),\n\t\t\t\t\t\"a rejected multi-event append must leave no prefix in the stream\",\n\t\t\t\t);\n\t\t\t\tconst reloaded = await environment.run(({ repository }) =>\n\t\t\t\t\tload(repository, seeded.id),\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\treloaded.version,\n\t\t\t\t\twinner.version,\n\t\t\t\t\t\"replay must end at the winning stream version\",\n\t\t\t\t);\n\t\t\t\tif (snapshotState) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\t\tsnapshotState.call(harness, reloaded),\n\t\t\t\t\t\t\tsnapshotState.call(harness, winner),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t\"replay must fold to writer A's state\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"replay preserves emission order and returns no pending events\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tconst expectedIds = recordedIds(aggregate.pendingEvents);\n\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t});\n\t\t\t\tconst reloaded = await environment.run(({ repository }) =>\n\t\t\t\t\tload(repository, aggregate.id),\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\treloaded.version,\n\t\t\t\t\texpectedIds.length,\n\t\t\t\t\t\"event-sourced version must equal the folded event count\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\treloaded.pendingEvents.length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"replay must not re-record historical events\",\n\t\t\t\t);\n\t\t\t\tif (snapshotState) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\t\tsnapshotState.call(harness, reloaded),\n\t\t\t\t\t\t\tsnapshotState.call(harness, aggregate),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t\"replay must fold to the same state in emission order\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst stream = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(aggregate.id),\n\t\t\t\t\treadAll,\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tstream.exists && deepEqual(ids(stream.events), expectedIds),\n\t\t\t\t\t\"the committed stream must preserve emission order\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"rollback leaves stream and outbox absent and acknowledges nothing\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tconst pending = [...aggregate.pendingEvents];\n\t\t\t\tawait captureRejection(\n\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t\t\tthrow new Error(\"rollback probe\");\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst stream = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(aggregate.id),\n\t\t\t\t\treadAll,\n\t\t\t\t);\n\t\t\t\tassert(!stream.exists, \"rollback must leave the stream absent\");\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await environment.committedOutboxEvents()).length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"rollback must leave the outbox empty\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(aggregate.pendingEvents, pending),\n\t\t\t\t\t\"rollback must retain the exact pending batch\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"retrying the same never-persisted instance after rollback creates the full stream\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tconst expectedIds = recordedIds(aggregate.pendingEvents);\n\t\t\t\tawait captureRejection(\n\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t\t\tthrow new Error(\"rollback probe\");\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\t// The documented retry carve-out: a never-persisted instance has\n\t\t\t\t// no row or stream to reload, so the caller re-adds the SAME\n\t\t\t\t// instance with its retained pending batch.\n\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t});\n\t\t\t\tconst stream = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(aggregate.id),\n\t\t\t\t\treadAll,\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tstream.exists && deepEqual(ids(stream.events), expectedIds),\n\t\t\t\t\t\"the retried add must create the stream with the full pending history\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\taggregate.pendingEvents.length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"the successful retry must acknowledge the whole batch\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"outbox failure rolls the already-appended stream batch back\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tconst pending = [...aggregate.pendingEvents];\n\t\t\t\tenvironment.failNextOutboxWrite(new Error(\"outbox failure probe\"));\n\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tassert(rejection !== undefined, \"the outbox failure must reject\");\n\t\t\t\tconst stream = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(aggregate.id),\n\t\t\t\t\treadAll,\n\t\t\t\t);\n\t\t\t\tassert(!stream.exists, \"stream append must roll back with the outbox\");\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await environment.committedOutboxEvents()).length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"failed outbox write must commit no envelope\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(aggregate.pendingEvents, pending),\n\t\t\t\t\t\"failed commit must acknowledge none of the event batch\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"read windows preserve absence, actual head, and point-in-time bounds\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst missingAggregate = harness.createAggregate();\n\t\t\t\tconst missing = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(missingAggregate.id),\n\t\t\t\t\treadAll,\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\t!missing.exists && missing.lastVersion === 0,\n\t\t\t\t\t\"a missing stream must report exists=false and head 0\",\n\t\t\t\t);\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t});\n\t\t\t\tconst afterOne = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(aggregate.id),\n\t\t\t\t\t{ limit: 100, fromVersion: 1 },\n\t\t\t\t);\n\t\t\t\tconst asOfTwo = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(aggregate.id),\n\t\t\t\t\t{ limit: 100, toVersion: 2 },\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tafterOne.exists &&\n\t\t\t\t\t\tafterOne.lastVersion === 3 &&\n\t\t\t\t\t\tafterOne.events.length === 2,\n\t\t\t\t\t\"fromVersion is exclusive and preserves the actual stream head\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tasOfTwo.exists &&\n\t\t\t\t\t\tasOfTwo.lastVersion === 3 &&\n\t\t\t\t\t\tasOfTwo.events.length === 2,\n\t\t\t\t\t\"toVersion is inclusive and preserves the actual stream head\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"identity map returns one replayed instance per Unit of Work\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\tconst first = await repository.findById(seeded.id);\n\t\t\t\t\tconst second = await repository.findById(seeded.id);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tfirst !== undefined && first === second,\n\t\t\t\t\t\t\"repeated stream loads must return the same tracked instance\",\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t}),\n\t\t},\n\t];\n\n\ttests.push(\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"createAggregateWithId\",\n\t\t\t\tsatisfiedBy: Boolean(createAggregateWithId),\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"duplicate add conflicts and leaves the existing stream untouched\",\n\t\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\t\tassert(createAggregateWithId !== undefined, \"capability gate\");\n\t\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\t\tconst before = await environment.committedStreamEvents(\n\t\t\t\t\t\tstreamFor(seeded.id),\n\t\t\t\t\t\treadAll,\n\t\t\t\t\t);\n\t\t\t\t\tconst duplicate = createAggregateWithId.call(harness, seeded.id);\n\t\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\t\trepository.add(duplicate);\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\t\trejection,\n\t\t\t\t\t\t[\"CONCURRENCY_CONFLICT\", \"DUPLICATE_AGGREGATE\"],\n\t\t\t\t\t\t`duplicate stream creation must reject with a mapped kit error; got ${describeError(rejection)}`,\n\t\t\t\t\t);\n\t\t\t\t\tconst after = await environment.committedStreamEvents(\n\t\t\t\t\t\tstreamFor(seeded.id),\n\t\t\t\t\t\treadAll,\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tdeepEqual(ids(after.events), ids(before.events)),\n\t\t\t\t\t\t\"duplicate add must not modify the existing stream\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t);\n\n\ttests.push(\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"captureSnapshot\",\n\t\t\t\tsatisfiedBy: Boolean(captureSnapshot),\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"snapshot catch-up ends at the stream head and folds only the tail\",\n\t\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\t\tassert(captureSnapshot !== undefined, \"capability gate\");\n\t\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\t\tconst loaded = await load(repository, seeded.id);\n\t\t\t\t\t\tharness.mutate(loaded);\n\t\t\t\t\t\trepository.update(loaded);\n\t\t\t\t\t});\n\t\t\t\t\tconst snapshotted = await environment.run(({ repository }) =>\n\t\t\t\t\t\tload(repository, seeded.id),\n\t\t\t\t\t);\n\t\t\t\t\tawait captureSnapshot.call(harness, snapshotted, environment);\n\n\t\t\t\t\tconst atHead = await environment.run(({ repository }) =>\n\t\t\t\t\t\tload(repository, seeded.id),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tatHead.version === snapshotted.version,\n\t\t\t\t\t\t`a snapshot at the head must load at the head ${snapshotted.version}, not beyond it; got ${atHead.version}`,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst winner = await environment.run(async ({ repository }) => {\n\t\t\t\t\t\tconst loaded = await load(repository, seeded.id);\n\t\t\t\t\t\tharness.mutate(loaded);\n\t\t\t\t\t\tharness.mutate(loaded);\n\t\t\t\t\t\trepository.update(loaded);\n\t\t\t\t\t\treturn loaded;\n\t\t\t\t\t});\n\t\t\t\t\tconst caughtUp = await environment.run(({ repository }) =>\n\t\t\t\t\t\tload(repository, seeded.id),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tcaughtUp.version === winner.version,\n\t\t\t\t\t\t`snapshot catch-up must end at the stream head ${winner.version}; got ${caughtUp.version}`,\n\t\t\t\t\t);\n\t\t\t\t\tif (snapshotState) {\n\t\t\t\t\t\tassert(\n\t\t\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\t\t\tsnapshotState.call(harness, caughtUp),\n\t\t\t\t\t\t\t\tsnapshotState.call(harness, winner),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\"snapshot catch-up must fold only the tail after the snapshot\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t);\n\n\treturn tests;\n}\n","import type { AnyDomainEvent } from \"../domain/event/domain-event\";\nimport type { EventBus } from \"../messaging/event-bus/ports\";\nimport {\n\tassert,\n\tassertEqual,\n\tbindContractEnvironment,\n\ttype ContractTest,\n\tcaptureRejection,\n} from \"./contract-assertions\";\n\n/** One entry of the event-bus contract suite. */\nexport type EventBusContractTest = ContractTest;\n\n/**\n * What the suite runs against. The harness creates one per test and tears\n * it down afterwards. No transaction wrapper: the port is in-process and\n * transaction-free by design.\n */\nexport interface EventBusContractEnvironment<Evt extends AnyDomainEvent> {\n\t/** The implementation under test. */\n\treadonly bus: EventBus<Evt>;\n\n\t/** Release connections, drop schemas, etc. Called in a finally. */\n\tteardown?(): Promise<void>;\n}\n\n/**\n * What an implementation supplies to run the event-bus contract suite.\n *\n * The suite mints no events, so it stays free of any event union. The two\n * factories must produce DIFFERENT `type` values: the suite subscribes to\n * both to prove that ordering holds across types and that a catch-all\n * subscription sees every type.\n */\nexport interface EventBusContractHarness<Evt extends AnyDomainEvent> {\n\tcreateEnvironment(): Promise<EventBusContractEnvironment<Evt>>;\n\t/** An event of the first type. Called repeatedly; each call may differ. */\n\tcreateFirstEvent(): Evt;\n\t/** An event of the second type, whose `type` differs from the first. */\n\tcreateSecondEvent(): Evt;\n}\n\n/** Resolves after enough turns for a parallel batch to have started. */\nfunction turn(): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, 0));\n}\n\n/**\n * The event-bus contract test suite: the proof that an implementation\n * delivers the guarantees the `EventBus` port documents. Ordering,\n * parallelism within one event, and error collection after the batch are\n * a **port contract, not a kit guarantee**; this suite is how an\n * implementation demonstrates them.\n *\n * The suite covers the port and nothing else. Construction options of the\n * kit's own adapter, such as a publish-depth bound or an observer bundle,\n * are not port behavior and are not pinned here.\n *\n * Framework-agnostic: bind with\n * `(test.skipped ? it.skip : it)(test.name, test.run)`.\n */\nexport function createEventBusContractTests<Evt extends AnyDomainEvent>(\n\tharness: EventBusContractHarness<Evt>,\n): EventBusContractTest[] {\n\ttype Env = EventBusContractEnvironment<Evt>;\n\tconst inEnv = bindContractEnvironment(() => harness.createEnvironment());\n\n\tconst first = () => harness.createFirstEvent();\n\tconst second = () => harness.createSecondEvent();\n\t// Called inside a test, never while the suite is built. A harness whose\n\t// factories need their environment would otherwise throw before a single\n\t// test has a name.\n\tconst types = () => {\n\t\tconst firstType = first().type as Evt[\"type\"];\n\t\tconst secondType = second().type as Evt[\"type\"];\n\t\tassert(\n\t\t\tfirstType !== secondType,\n\t\t\t\"the harness must supply two event factories with different types\",\n\t\t);\n\t\treturn { firstType, secondType };\n\t};\n\n\treturn [\n\t\t{\n\t\t\tname: \"dispatches the events of one batch in input order\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType, secondType } = types();\n\t\t\t\tconst seen: string[] = [];\n\t\t\t\t// The first type is the slower one. Input order must hold\n\t\t\t\t// whatever the handlers cost, so a dispatch that runs the batch\n\t\t\t\t// concurrently reorders here and fails.\n\t\t\t\tbus.subscribe(firstType, async (event) => {\n\t\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, 20));\n\t\t\t\t\tseen.push(event.type);\n\t\t\t\t});\n\t\t\t\tbus.subscribe(secondType, async (event) => {\n\t\t\t\t\tseen.push(event.type);\n\t\t\t\t});\n\n\t\t\t\tawait bus.publish([first(), second(), first()]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tseen.join(\",\"),\n\t\t\t\t\t[firstType, secondType, firstType].join(\",\"),\n\t\t\t\t\t\"a batch dispatches its events in input order\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"starts the handlers of an event only after the previous event finished\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType, secondType } = types();\n\t\t\t\tconst trace: string[] = [];\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\ttrace.push(\"first:start\");\n\t\t\t\t\tawait turn();\n\t\t\t\t\ttrace.push(\"first:end\");\n\t\t\t\t});\n\t\t\t\tbus.subscribe(secondType, async () => {\n\t\t\t\t\ttrace.push(\"second:start\");\n\t\t\t\t});\n\n\t\t\t\tawait bus.publish([first(), second()]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\ttrace.join(\",\"),\n\t\t\t\t\t\"first:start,first:end,second:start\",\n\t\t\t\t\t\"an event dispatches only after the previous one finished\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"runs the handlers of one event in parallel\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst trace: string[] = [];\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\ttrace.push(\"a:start\");\n\t\t\t\t\tawait turn();\n\t\t\t\t\ttrace.push(\"a:end\");\n\t\t\t\t});\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\ttrace.push(\"b:start\");\n\t\t\t\t\tawait turn();\n\t\t\t\t\ttrace.push(\"b:end\");\n\t\t\t\t});\n\n\t\t\t\tawait bus.publish([first()]);\n\n\t\t\t\t// Sequential dispatch would read a:start, a:end, b:start, b:end.\n\t\t\t\tassertEqual(\n\t\t\t\t\ttrace.join(\",\"),\n\t\t\t\t\t\"a:start,b:start,a:end,b:end\",\n\t\t\t\t\t\"the handlers of one event run in parallel\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"runs every handler of an event when a peer fails\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst seen: string[] = [];\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tthrow new Error(\"first handler failed\");\n\t\t\t\t});\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tseen.push(\"peer\");\n\t\t\t\t});\n\n\t\t\t\tawait captureRejection(bus.publish([first()]));\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tseen.join(\",\"),\n\t\t\t\t\t\"peer\",\n\t\t\t\t\t\"a peer of a failing handler still runs\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"reaches the caller with a single failure directly\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst failure = new Error(\"the only handler failed\");\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tthrow failure;\n\t\t\t\t});\n\n\t\t\t\tconst thrown = await captureRejection(bus.publish([first()]));\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tthrown,\n\t\t\t\t\tfailure,\n\t\t\t\t\t\"a single failure reaches the caller unchanged\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"collects two or more failures into an AggregateError\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst one = new Error(\"handler one failed\");\n\t\t\t\tconst two = new Error(\"handler two failed\");\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tthrow one;\n\t\t\t\t});\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tthrow two;\n\t\t\t\t});\n\n\t\t\t\tconst thrown = await captureRejection(bus.publish([first()]));\n\n\t\t\t\tassert(\n\t\t\t\t\tthrown instanceof AggregateError,\n\t\t\t\t\t\"two failures must reach the caller as an AggregateError\",\n\t\t\t\t);\n\t\t\t\t// The port promises that every failure is carried, not the order\n\t\t\t\t// they are carried in. Ordering is an implementation choice.\n\t\t\t\tassertEqual(\n\t\t\t\t\tthrown.errors.length,\n\t\t\t\t\t2,\n\t\t\t\t\t\"the AggregateError carries every failure\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tthrown.errors.includes(one) && thrown.errors.includes(two),\n\t\t\t\t\t\"the AggregateError carries both failures\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"publishes the remaining events of a batch after a failure\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType, secondType } = types();\n\t\t\t\tconst seen: string[] = [];\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tthrow new Error(\"first handler failed\");\n\t\t\t\t});\n\t\t\t\tbus.subscribe(secondType, async (event) => {\n\t\t\t\t\tseen.push(event.type);\n\t\t\t\t});\n\n\t\t\t\tawait captureRejection(bus.publish([first(), second()]));\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tseen.join(\",\"),\n\t\t\t\t\tsecondType,\n\t\t\t\t\t\"a failure does not stop the remaining events of the batch\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"treats a handler that throws synchronously as a rejection\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst seen: string[] = [];\n\t\t\t\tbus.subscribe(firstType, () => {\n\t\t\t\t\tthrow new Error(\"thrown synchronously\");\n\t\t\t\t});\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tseen.push(\"peer\");\n\t\t\t\t});\n\n\t\t\t\tconst thrown = await captureRejection(bus.publish([first()]));\n\n\t\t\t\tassert(thrown instanceof Error, \"the throw must reach the caller\");\n\t\t\t\tassertEqual(\n\t\t\t\t\tseen.join(\",\"),\n\t\t\t\t\t\"peer\",\n\t\t\t\t\t\"a synchronous throw does not skip the peers\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"hands every subscriber the same event object\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst received: unknown[] = [];\n\t\t\t\tbus.subscribe(firstType, (event) => {\n\t\t\t\t\treceived.push(event);\n\t\t\t\t});\n\t\t\t\tbus.subscribeAll((event) => {\n\t\t\t\t\treceived.push(event);\n\t\t\t\t});\n\n\t\t\t\tconst published = first();\n\t\t\t\tawait bus.publish([published]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\treceived.length,\n\t\t\t\t\t2,\n\t\t\t\t\t\"both subscriptions must receive the event\",\n\t\t\t\t);\n\t\t\t\tfor (const one of received) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tone === published,\n\t\t\t\t\t\t\"every subscriber receives the published event itself, so its metadata cannot differ between them\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"delivers every type of a subscribed set to one handler\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType, secondType } = types();\n\t\t\t\tconst seen: string[] = [];\n\t\t\t\tbus.subscribeMany([firstType, secondType], (event) => {\n\t\t\t\t\tseen.push(event.type);\n\t\t\t\t});\n\n\t\t\t\tawait bus.publish([first(), second()]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tseen.join(\",\"),\n\t\t\t\t\t[firstType, secondType].join(\",\"),\n\t\t\t\t\t\"a set subscription receives every type in the set\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"releases every subscription of a set with one call\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType, secondType } = types();\n\t\t\t\tconst seen: string[] = [];\n\t\t\t\tconst release = bus.subscribeMany([firstType, secondType], (event) => {\n\t\t\t\t\tseen.push(event.type);\n\t\t\t\t});\n\n\t\t\t\trelease();\n\t\t\t\tawait bus.publish([first(), second()]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tseen.length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"one release must remove every subscription the set made\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"subscribes a repeated type of a set once\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tlet calls = 0;\n\t\t\t\tbus.subscribeMany([firstType, firstType], () => {\n\t\t\t\t\tcalls++;\n\t\t\t\t});\n\n\t\t\t\tawait bus.publish([first()]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tcalls,\n\t\t\t\t\t1,\n\t\t\t\t\t\"the argument is a set, so a repeated type subscribes once\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"delivers every event type to a catch-all subscription\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType, secondType } = types();\n\t\t\t\tconst seen: string[] = [];\n\t\t\t\tbus.subscribeAll(async (event) => {\n\t\t\t\t\tseen.push(event.type);\n\t\t\t\t});\n\n\t\t\t\tawait bus.publish([first(), second()]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tseen.join(\",\"),\n\t\t\t\t\t[firstType, secondType].join(\",\"),\n\t\t\t\t\t\"a catch-all subscription receives every event type\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"runs a catch-all handler in the same batch as the typed handlers\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst seen: string[] = [];\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tthrow new Error(\"typed handler failed\");\n\t\t\t\t});\n\t\t\t\tbus.subscribeAll(async () => {\n\t\t\t\t\tseen.push(\"catch-all\");\n\t\t\t\t});\n\n\t\t\t\tawait captureRejection(bus.publish([first()]));\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tseen.join(\",\"),\n\t\t\t\t\t\"catch-all\",\n\t\t\t\t\t\"a catch-all handler runs in the same batch as the typed ones\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"removes exactly one subscription when the same handler subscribed twice\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tlet calls = 0;\n\t\t\t\tconst handler = async () => {\n\t\t\t\t\tcalls++;\n\t\t\t\t};\n\t\t\t\tconst release = bus.subscribe(firstType, handler);\n\t\t\t\tbus.subscribe(firstType, handler);\n\n\t\t\t\trelease();\n\t\t\t\tawait bus.publish([first()]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tcalls,\n\t\t\t\t\t1,\n\t\t\t\t\t\"unsubscribe removes exactly one of two identical subscriptions\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"ignores a second call of the unsubscribe function\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tlet calls = 0;\n\t\t\t\tconst release = bus.subscribe(firstType, async () => {\n\t\t\t\t\tcalls++;\n\t\t\t\t});\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tcalls++;\n\t\t\t\t});\n\n\t\t\t\trelease();\n\t\t\t\trelease();\n\t\t\t\tawait bus.publish([first()]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tcalls,\n\t\t\t\t\t1,\n\t\t\t\t\t\"a second unsubscribe removes no further subscription\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"resolves once() with the next event of its type and stops after it\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tlet deliveries = 0;\n\t\t\t\tbus.subscribeAll(async () => {\n\t\t\t\t\tdeliveries++;\n\t\t\t\t});\n\t\t\t\tconst waiting = bus.once(firstType);\n\n\t\t\t\tconst announced = first();\n\t\t\t\tawait bus.publish([announced]);\n\t\t\t\tconst received = await waiting;\n\t\t\t\tawait bus.publish([first()]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\treceived.eventId,\n\t\t\t\t\tannounced.eventId,\n\t\t\t\t\t\"once() resolves with the first event of that type\",\n\t\t\t\t);\n\t\t\t\t// The catch-all proves the second publication happened, so the\n\t\t\t\t// subscription of once() is gone rather than never reached.\n\t\t\t\tassertEqual(\n\t\t\t\t\tdeliveries,\n\t\t\t\t\t2,\n\t\t\t\t\t\"the second publication must still reach the bus\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"rejects once() when its timeout expires\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst thrown = await captureRejection(\n\t\t\t\t\tbus.once(firstType, { timeoutMs: 5 }),\n\t\t\t\t);\n\n\t\t\t\tassert(thrown !== undefined, \"once() must reject after its timeout\");\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"rejects once() with the reason of an aborted signal\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst controller = new AbortController();\n\t\t\t\tconst reason = new Error(\"the caller stopped waiting\");\n\t\t\t\tconst waiting = captureRejection(\n\t\t\t\t\tbus.once(firstType, { signal: controller.signal }),\n\t\t\t\t);\n\n\t\t\t\tcontroller.abort(reason);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait waiting,\n\t\t\t\t\treason,\n\t\t\t\t\t\"once() rejects with the reason of the signal\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"rejects a publication whose signal is already aborted\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst controller = new AbortController();\n\t\t\t\tcontroller.abort(new Error(\"stopped before publish\"));\n\t\t\t\tlet called = false;\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tcalled = true;\n\t\t\t\t});\n\n\t\t\t\tconst thrown = await captureRejection(\n\t\t\t\t\tbus.publish([first()], { signal: controller.signal }),\n\t\t\t\t);\n\n\t\t\t\tassert(thrown !== undefined, \"an aborted publication must reject\");\n\t\t\t\tassertEqual(\n\t\t\t\t\tcalled,\n\t\t\t\t\tfalse,\n\t\t\t\t\t\"an aborted publication dispatches no handler\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"refuses every operation after close\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tbus.close();\n\n\t\t\t\tlet subscribeThrew = false;\n\t\t\t\ttry {\n\t\t\t\t\tbus.subscribe(firstType, () => {});\n\t\t\t\t} catch {\n\t\t\t\t\tsubscribeThrew = true;\n\t\t\t\t}\n\t\t\t\tlet subscribeAllThrew = false;\n\t\t\t\ttry {\n\t\t\t\t\tbus.subscribeAll(() => {});\n\t\t\t\t} catch {\n\t\t\t\t\tsubscribeAllThrew = true;\n\t\t\t\t}\n\n\t\t\t\tassert(subscribeThrew, \"subscribe must refuse a closed bus\");\n\t\t\t\tassert(subscribeAllThrew, \"subscribeAll must refuse a closed bus\");\n\t\t\t\tassert(\n\t\t\t\t\t(await captureRejection(bus.publish([first()]))) !== undefined,\n\t\t\t\t\t\"publish must refuse a closed bus\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\t(await captureRejection(bus.once(firstType))) !== undefined,\n\t\t\t\t\t\"once must refuse a closed bus\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"settles a pending once() when the bus closes\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\t// Without a timeout and without a signal this waiter has no\n\t\t\t\t// other way to end.\n\t\t\t\tconst waiting = captureRejection(bus.once(firstType));\n\n\t\t\t\tbus.close();\n\n\t\t\t\tassert(\n\t\t\t\t\t(await waiting) !== undefined,\n\t\t\t\t\t\"closing must settle a pending once()\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"does nothing when close is called again\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tbus.close();\n\n\t\t\t\tlet threw = false;\n\t\t\t\ttry {\n\t\t\t\t\tbus.close();\n\t\t\t\t} catch {\n\t\t\t\t\tthrew = true;\n\t\t\t\t}\n\n\t\t\t\tassert(threw === false, \"a second close must do nothing\");\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"bounds the wait, not the handler, when the timeout expires\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tlet running = true;\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, 200));\n\t\t\t\t\trunning = false;\n\t\t\t\t});\n\n\t\t\t\tconst thrown = await captureRejection(\n\t\t\t\t\tbus.publish([first()], { timeoutMs: 10 }),\n\t\t\t\t);\n\n\t\t\t\tassert(thrown !== undefined, \"the publication must reject\");\n\t\t\t\tassertEqual(\n\t\t\t\t\trunning,\n\t\t\t\t\ttrue,\n\t\t\t\t\t\"the timeout bounds the wait, so the handler keeps running\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t];\n}\n","import type { AggregateAddress } from \"../domain/aggregate/aggregate-address\";\nimport type { AnyDomainEvent } from \"../domain/event/domain-event\";\nimport type { EventStore } from \"../persistence/event-store/event-store\";\nimport {\n\tassert,\n\tassertChainContainsKitError,\n\tbindContractEnvironment,\n\ttype ContractTest,\n\tcaptureRejection,\n} from \"./contract-assertions\";\n\n/** One named contract test for an EventStore adapter. */\nexport type EventStoreContractTest = ContractTest;\n\n/** One isolated adapter instance. The suite creates one per test. */\nexport interface EventStoreContractEnvironment<Evt extends AnyDomainEvent> {\n\treadonly store: EventStore<Evt>;\n\tteardown?(): Promise<void>;\n}\n\n/**\n * Inputs needed to prove the EventStore's observable port contract.\n *\n * `createCollidingStreamKeys` must return two valid stream keys with the same\n * raw aggregate id and different aggregate types. `createEvent` must return an\n * event addressed to the supplied key; different sequence values must produce\n * different event ids.\n */\nexport interface EventStoreContractHarness<Evt extends AnyDomainEvent> {\n\tcreateEnvironment(): Promise<EventStoreContractEnvironment<Evt>>;\n\tcreateCollidingStreamKeys(): readonly [AggregateAddress, AggregateAddress];\n\tcreateEvent(stream: AggregateAddress, sequence: number): Evt;\n}\n\n/**\n * Reusable proof of an EventStore adapter's portable semantics: qualified\n * value identity, ordered reads and slicing, OCC error mapping and atomicity,\n * no-op empty appends, and detached return arrays. Physical-position\n * corruption needs adapter-specific fixture support and is tested there.\n */\nexport function createEventStoreContractTests<Evt extends AnyDomainEvent>(\n\tharness: EventStoreContractHarness<Evt>,\n): EventStoreContractTest[] {\n\tconst inEnv = bindContractEnvironment(() => harness.createEnvironment());\n\tconst fixtureRead = { limit: 100 } as const;\n\tconst hasSameEventIds = (\n\t\tactual: ReadonlyArray<Evt>,\n\t\texpected: ReadonlyArray<Evt>,\n\t): boolean =>\n\t\tactual.length === expected.length &&\n\t\tactual.every((event, index) => event.eventId === expected[index]?.eventId);\n\n\treturn [\n\t\t{\n\t\t\tname: \"unknown stream: read reports explicit absence at version zero\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst missing = await store.readStream({ ...firstKey }, fixtureRead);\n\t\t\t\tassert(\n\t\t\t\t\t!missing.exists &&\n\t\t\t\t\t\tmissing.lastVersion === 0 &&\n\t\t\t\t\t\tmissing.events.length === 0,\n\t\t\t\t\t\"an unknown qualified stream must return the explicit missing state\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"empty append: no version check and no stream creation\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tawait store.append(firstKey, [], { expectedVersion: 999 });\n\t\t\t\tconst event = harness.createEvent(firstKey, 1);\n\t\t\t\tawait store.append({ ...firstKey }, [event], { expectedVersion: 0 });\n\t\t\t\tconst stored = await store.readStream(firstKey, fixtureRead);\n\t\t\t\tassert(\n\t\t\t\t\tstored.exists &&\n\t\t\t\t\t\tstored.lastVersion === 1 &&\n\t\t\t\t\t\tstored.events.length === 1 &&\n\t\t\t\t\t\tstored.events[0]?.eventId === event.eventId,\n\t\t\t\t\t\"an empty append must not check OCC or create an empty stream\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"qualified stream key: equal aggregate ids remain isolated by aggregate type\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey, secondKey] = harness.createCollidingStreamKeys();\n\t\t\t\tassert(\n\t\t\t\t\tfirstKey.aggregateId === secondKey.aggregateId,\n\t\t\t\t\t\"createCollidingStreamKeys must return equal raw aggregate ids\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tfirstKey.aggregateType !== secondKey.aggregateType,\n\t\t\t\t\t\"createCollidingStreamKeys must return different aggregate types\",\n\t\t\t\t);\n\n\t\t\t\tconst firstEvent = harness.createEvent(firstKey, 1);\n\t\t\t\tconst secondEvent = harness.createEvent(secondKey, 2);\n\t\t\t\tassert(\n\t\t\t\t\tfirstEvent.eventId !== secondEvent.eventId,\n\t\t\t\t\t\"createEvent must produce different event ids for different sequence values\",\n\t\t\t\t);\n\n\t\t\t\tawait store.append(firstKey, [firstEvent], { expectedVersion: 0 });\n\t\t\t\tawait store.append(secondKey, [secondEvent], { expectedVersion: 0 });\n\n\t\t\t\tconst firstStream = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\tfixtureRead,\n\t\t\t\t);\n\t\t\t\tconst secondStream = await store.readStream(\n\t\t\t\t\t{ ...secondKey },\n\t\t\t\t\tfixtureRead,\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tfirstStream.exists &&\n\t\t\t\t\t\tfirstStream.events.length === 1 &&\n\t\t\t\t\t\tfirstStream.events[0]?.eventId === firstEvent.eventId,\n\t\t\t\t\t\"the first aggregate type must retain only its own event; key objects are value addresses, not identity tokens\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tsecondStream.exists &&\n\t\t\t\t\t\tsecondStream.events.length === 1 &&\n\t\t\t\t\t\tsecondStream.events[0]?.eventId === secondEvent.eventId,\n\t\t\t\t\t\"the second aggregate type must retain only its own event when the raw id collides\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"append/read: event order and fromVersion slicing are preserved\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst events = [1, 2, 3].map((sequence) =>\n\t\t\t\t\tharness.createEvent(firstKey, sequence),\n\t\t\t\t);\n\t\t\t\tawait store.append(firstKey, events, { expectedVersion: 0 });\n\t\t\t\tconst whole = await store.readStream({ ...firstKey }, fixtureRead);\n\t\t\t\tconst afterTwo = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{\n\t\t\t\t\t\t...fixtureRead,\n\t\t\t\t\t\tfromVersion: 2,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\twhole.exists &&\n\t\t\t\t\t\twhole.lastVersion === 3 &&\n\t\t\t\t\t\thasSameEventIds(whole.events, events),\n\t\t\t\t\t\"reads must preserve append order\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tafterTwo.exists &&\n\t\t\t\t\t\tafterTwo.lastVersion === 3 &&\n\t\t\t\t\t\tafterTwo.events.length === 1 &&\n\t\t\t\t\t\tafterTwo.events[0]?.eventId === events[2]?.eventId,\n\t\t\t\t\t\"fromVersion 2 must return exactly the events after the first two positions\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"paged read: limit bounds every page and fromVersion continues without gaps or duplicates\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst events = [1, 2, 3, 4, 5].map((sequence) =>\n\t\t\t\t\tharness.createEvent(firstKey, sequence),\n\t\t\t\t);\n\t\t\t\tawait store.append(firstKey, events, { expectedVersion: 0 });\n\n\t\t\t\tconst collected: Evt[] = [];\n\t\t\t\tlet cursor = 0;\n\t\t\t\tlet targetHead: number | undefined;\n\t\t\t\tfor (let attempt = 0; attempt < events.length; attempt += 1) {\n\t\t\t\t\tconst page = await store.readStream(\n\t\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfromVersion: cursor,\n\t\t\t\t\t\t\tlimit: 2,\n\t\t\t\t\t\t\t...(targetHead === undefined ? {} : { toVersion: targetHead }),\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tpage.exists,\n\t\t\t\t\t\t\"a paged read of an existing stream must retain existence\",\n\t\t\t\t\t);\n\t\t\t\t\ttargetHead ??= page.lastVersion;\n\t\t\t\t\tassert(\n\t\t\t\t\t\tpage.lastVersion >= targetHead,\n\t\t\t\t\t\t\"lastVersion must keep reporting at least the head pinned by the first page\",\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tpage.events.length > 0 && page.events.length <= 2,\n\t\t\t\t\t\t\"an unread page must make progress without exceeding the requested limit\",\n\t\t\t\t\t);\n\t\t\t\t\tcollected.push(...page.events);\n\t\t\t\t\tcursor += page.events.length;\n\t\t\t\t\tif (cursor >= targetHead) break;\n\t\t\t\t}\n\n\t\t\t\tassert(\n\t\t\t\t\ttargetHead === events.length && cursor === targetHead,\n\t\t\t\t\t\"following fromVersion by each actual page length must reach the pinned head\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\thasSameEventIds(collected, events),\n\t\t\t\t\t\"paged continuation must reproduce append order without gaps or duplicates\",\n\t\t\t\t);\n\t\t\t\tconst atEnd = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{ fromVersion: cursor, toVersion: targetHead, limit: 2 },\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tatEnd.exists && atEnd.events.length === 0,\n\t\t\t\t\t\"continuing at the pinned head must return an existing empty page\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"read options: invalid limits and stream positions fail loudly\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst invalidOptions: unknown[] = [\n\t\t\t\t\t{},\n\t\t\t\t\t{ limit: 0 },\n\t\t\t\t\t{ limit: 1.5 },\n\t\t\t\t\t{ limit: Number.MAX_SAFE_INTEGER + 1 },\n\t\t\t\t\t{ limit: 1, fromVersion: -1 },\n\t\t\t\t\t{ limit: 1, fromVersion: 1.5 },\n\t\t\t\t\t{ limit: 1, fromVersion: Number.MAX_SAFE_INTEGER + 1 },\n\t\t\t\t\t{ limit: 1, toVersion: -1 },\n\t\t\t\t\t{ limit: 1, toVersion: 1.5 },\n\t\t\t\t\t{ limit: 1, toVersion: Number.MAX_SAFE_INTEGER + 1 },\n\t\t\t\t];\n\n\t\t\t\tfor (const options of invalidOptions) {\n\t\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\t\tstore.readStream(firstKey, options as never),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\trejection instanceof RangeError,\n\t\t\t\t\t\t\"invalid read bounds must reject with RangeError before querying the stream\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"bounded read: toVersion is inclusive while lastVersion remains the actual head\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst events = [1, 2, 3, 4].map((sequence) =>\n\t\t\t\t\tharness.createEvent(firstKey, sequence),\n\t\t\t\t);\n\t\t\t\tawait store.append(firstKey, events, { expectedVersion: 0 });\n\n\t\t\t\tconst bounded = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{ ...fixtureRead, fromVersion: 1, toVersion: 3 },\n\t\t\t\t);\n\n\t\t\t\tassert(\n\t\t\t\t\tbounded.exists &&\n\t\t\t\t\t\tbounded.lastVersion === 4 &&\n\t\t\t\t\t\thasSameEventIds(bounded.events, events.slice(1, 3)),\n\t\t\t\t\t\"(fromVersion, toVersion] must include positions 2 and 3 while lastVersion reports the actual head at 4\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"bounded read edges: zero, beyond-head, and inverted ranges are empty or clamped\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst events = [1, 2, 3].map((sequence) =>\n\t\t\t\t\tharness.createEvent(firstKey, sequence),\n\t\t\t\t);\n\t\t\t\tawait store.append(firstKey, events, { expectedVersion: 0 });\n\n\t\t\t\tconst atZero = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{ ...fixtureRead, toVersion: 0 },\n\t\t\t\t);\n\t\t\t\tconst beyondHead = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{ ...fixtureRead, toVersion: 99 },\n\t\t\t\t);\n\t\t\t\tconst inverted = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{ ...fixtureRead, fromVersion: 2, toVersion: 1 },\n\t\t\t\t);\n\t\t\t\tconst equalBounds = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{ ...fixtureRead, fromVersion: 2, toVersion: 2 },\n\t\t\t\t);\n\n\t\t\t\tassert(\n\t\t\t\t\tatZero.exists &&\n\t\t\t\t\t\tatZero.lastVersion === 3 &&\n\t\t\t\t\t\tatZero.events.length === 0,\n\t\t\t\t\t\"toVersion=0 must return an existing empty window with the actual head\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tbeyondHead.exists &&\n\t\t\t\t\t\tbeyondHead.lastVersion === 3 &&\n\t\t\t\t\t\thasSameEventIds(beyondHead.events, events),\n\t\t\t\t\t\"toVersion beyond the head must clamp to the actual stream head\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tinverted.exists &&\n\t\t\t\t\t\tinverted.lastVersion === 3 &&\n\t\t\t\t\t\tinverted.events.length === 0 &&\n\t\t\t\t\t\tequalBounds.exists &&\n\t\t\t\t\t\tequalBounds.lastVersion === 3 &&\n\t\t\t\t\t\tequalBounds.events.length === 0,\n\t\t\t\t\t\"fromVersion >= toVersion describes an empty interval and must not throw\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"read state: empty and beyond-head windows retain existence and the actual stream head\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tawait store.append(\n\t\t\t\t\tfirstKey,\n\t\t\t\t\t[harness.createEvent(firstKey, 4), harness.createEvent(firstKey, 5)],\n\t\t\t\t\t{ expectedVersion: 0 },\n\t\t\t\t);\n\n\t\t\t\tconst atHead = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{\n\t\t\t\t\t\t...fixtureRead,\n\t\t\t\t\t\tfromVersion: 2,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tconst beyondHead = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{\n\t\t\t\t\t\t...fixtureRead,\n\t\t\t\t\t\tfromVersion: 99,\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tfor (const result of [atHead, beyondHead]) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tresult.exists &&\n\t\t\t\t\t\t\tresult.lastVersion === 2 &&\n\t\t\t\t\t\t\tresult.events.length === 0,\n\t\t\t\t\t\t\"an empty read window must retain stream existence and report the actual head, even when fromVersion is beyond it\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"qualified fromVersion: slicing one type cannot observe a colliding raw id\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey, secondKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst firstEvents = [10, 11, 12].map((sequence) =>\n\t\t\t\t\tharness.createEvent(firstKey, sequence),\n\t\t\t\t);\n\t\t\t\tconst secondEvents = [20, 21].map((sequence) =>\n\t\t\t\t\tharness.createEvent(secondKey, sequence),\n\t\t\t\t);\n\t\t\t\tawait store.append(firstKey, firstEvents, { expectedVersion: 0 });\n\t\t\t\tawait store.append(secondKey, secondEvents, { expectedVersion: 0 });\n\t\t\t\tconst firstTail = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{\n\t\t\t\t\t\t...fixtureRead,\n\t\t\t\t\t\tfromVersion: 1,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tconst secondTail = await store.readStream(\n\t\t\t\t\t{ ...secondKey },\n\t\t\t\t\t{\n\t\t\t\t\t\t...fixtureRead,\n\t\t\t\t\t\tfromVersion: 1,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tfirstTail.exists &&\n\t\t\t\t\t\tfirstTail.lastVersion === 3 &&\n\t\t\t\t\t\tfirstTail.events.length === 2 &&\n\t\t\t\t\t\tfirstTail.events[0]?.eventId === firstEvents[1]?.eventId &&\n\t\t\t\t\t\tfirstTail.events[1]?.eventId === firstEvents[2]?.eventId,\n\t\t\t\t\t\"fromVersion must slice only the requested aggregate type's stream\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tsecondTail.exists &&\n\t\t\t\t\t\tsecondTail.lastVersion === 2 &&\n\t\t\t\t\t\tsecondTail.events.length === 1 &&\n\t\t\t\t\t\tsecondTail.events[0]?.eventId === secondEvents[1]?.eventId,\n\t\t\t\t\t\"a colliding raw id under another type must retain its independent version window\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"OCC: a rejected multi-event append is atomic and maps to ConcurrencyConflictError\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst seeded = [\n\t\t\t\t\tharness.createEvent(firstKey, 30),\n\t\t\t\t\tharness.createEvent(firstKey, 31),\n\t\t\t\t];\n\t\t\t\tawait store.append(firstKey, seeded, { expectedVersion: 0 });\n\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\tstore.append(\n\t\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\tharness.createEvent(firstKey, 32),\n\t\t\t\t\t\t\tharness.createEvent(firstKey, 33),\n\t\t\t\t\t\t],\n\t\t\t\t\t\t{ expectedVersion: 1 },\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\trejection,\n\t\t\t\t\t[\"CONCURRENCY_CONFLICT\"],\n\t\t\t\t\t\"a stale append must map the adapter conflict to ConcurrencyConflictError\",\n\t\t\t\t);\n\t\t\t\tconst stored = await store.readStream(firstKey, fixtureRead);\n\t\t\t\tassert(\n\t\t\t\t\tstored.exists &&\n\t\t\t\t\t\tstored.lastVersion === 2 &&\n\t\t\t\t\t\tstored.events.length === 2 &&\n\t\t\t\t\t\tstored.events[0]?.eventId === seeded[0]?.eventId &&\n\t\t\t\t\t\tstored.events[1]?.eventId === seeded[1]?.eventId,\n\t\t\t\t\t\"a rejected multi-event append must leave the stream untouched\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"OCC: duplicate create is rejected atomically with a sanctioned kit error\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst seeded = harness.createEvent(firstKey, 50);\n\t\t\t\tawait store.append(firstKey, [seeded], { expectedVersion: 0 });\n\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\tstore.append(\n\t\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\tharness.createEvent(firstKey, 51),\n\t\t\t\t\t\t\tharness.createEvent(firstKey, 52),\n\t\t\t\t\t\t],\n\t\t\t\t\t\t{ expectedVersion: 0 },\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\trejection,\n\t\t\t\t\t[\"CONCURRENCY_CONFLICT\", \"DUPLICATE_AGGREGATE\"],\n\t\t\t\t\t\"a duplicate create must map to ConcurrencyConflictError or the sanctioned DuplicateAggregateError\",\n\t\t\t\t);\n\t\t\t\tconst stored = await store.readStream(firstKey, fixtureRead);\n\t\t\t\tassert(\n\t\t\t\t\tstored.exists &&\n\t\t\t\t\t\tstored.lastVersion === 1 &&\n\t\t\t\t\t\tstored.events.length === 1 &&\n\t\t\t\t\t\tstored.events[0]?.eventId === seeded.eventId,\n\t\t\t\t\t\"a rejected duplicate-create batch must leave the existing stream untouched\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"OCC: an expectedVersion ahead of an unknown stream conflicts without creating it\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\tstore.append(firstKey, [harness.createEvent(firstKey, 60)], {\n\t\t\t\t\t\texpectedVersion: 3,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\trejection,\n\t\t\t\t\t[\"CONCURRENCY_CONFLICT\"],\n\t\t\t\t\t\"an expectedVersion ahead of the stream must map to ConcurrencyConflictError\",\n\t\t\t\t);\n\t\t\t\tconst first = harness.createEvent(firstKey, 61);\n\t\t\t\tawait store.append({ ...firstKey }, [first], { expectedVersion: 0 });\n\t\t\t\tconst stored = await store.readStream(firstKey, fixtureRead);\n\t\t\t\tassert(\n\t\t\t\t\tstored.exists &&\n\t\t\t\t\t\tstored.lastVersion === 1 &&\n\t\t\t\t\t\tstored.events.length === 1 &&\n\t\t\t\t\t\tstored.events[0]?.eventId === first.eventId,\n\t\t\t\t\t\"the rejected append must not leave an empty stream or partial events behind\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"read ownership: a mutation attempt cannot mutate the stream\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst seeded = harness.createEvent(firstKey, 40);\n\t\t\t\tawait store.append(firstKey, [seeded], { expectedVersion: 0 });\n\t\t\t\tconst callerOwned = (await store.readStream(firstKey, fixtureRead))\n\t\t\t\t\t.events as Evt[];\n\t\t\t\ttry {\n\t\t\t\t\tcallerOwned.push(harness.createEvent(firstKey, 41));\n\t\t\t\t} catch {\n\t\t\t\t\t// A detached frozen array is also valid: the contract forbids exposing\n\t\t\t\t\t// mutable live state, not defensive immutability.\n\t\t\t\t}\n\t\t\t\tconst stored = await store.readStream({ ...firstKey }, fixtureRead);\n\t\t\t\tassert(\n\t\t\t\t\tstored.exists &&\n\t\t\t\t\t\tstored.events.length === 1 &&\n\t\t\t\t\t\tstored.events[0]?.eventId === seeded.eventId,\n\t\t\t\t\t\"readStream must return an owned array, never live internal state\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t];\n}\n","import type {\n\tIdempotencyClaim,\n\tIdempotencyClaimHandle,\n\tIdempotencyStore,\n} from \"../application/idempotency/idempotency\";\nimport { deepEqual } from \"../internal/structural/deep-equal\";\nimport {\n\tassert,\n\tassertChainContainsKitError,\n\tassertEqual,\n\tbindContractEnvironment,\n\ttype ContractTest,\n\tcaptureRejection,\n\tchainContainsRetryable,\n\tgatedContractTest,\n} from \"./contract-assertions\";\n\n/** One contract test; bind with `(test.skipped ? it.skip : it)(test.name, test.run)`. */\nexport type IdempotencyStoreContractTest = ContractTest;\n\n/**\n * One isolated test environment: a fresh idempotency store. The suite\n * creates one per test and tears it down afterwards.\n */\nexport interface IdempotencyStoreContractEnvironment<TCtx> {\n\t/** The adapter under test. */\n\tstore: IdempotencyStore<TCtx>;\n\n\t/**\n\t * Runs `work` inside a transaction that COMMITS, handing it the\n\t * transaction context the store methods expect, the way\n\t * `withIdempotentCommit` calls them in production. For a\n\t * non-transactional store this simply invokes `work` with a dummy\n\t * context.\n\t */\n\trun<R>(work: (ctx: TCtx) => Promise<R>): Promise<R>;\n\n\t/**\n\t * For the `\"transactional\"` family: runs `work` inside a transaction\n\t * that ROLLS BACK. Required there; the rollback-releases-the-claim\n\t * test is that family's core proof. Irrelevant for the\n\t * `\"non-transactional\"` family.\n\t */\n\trunRolledBack?<R>(work: (ctx: TCtx) => Promise<R>): Promise<R>;\n\n\t/**\n\t * For the `\"non-transactional\"` family: advances or edits adapter test\n\t * state so this exact claim's CURRENT lease is expired. Required there;\n\t * a fake clock or test-only row update keeps the suite deterministic.\n\t */\n\texpireLease?(claim: IdempotencyClaimHandle): Promise<void>;\n\n\t/**\n\t * Moves the adapter's test clock to an exact instant. Required by the\n\t * non-transactional family so renewal is proved without wall-clock sleeps.\n\t */\n\tadvanceTimeTo?(instant: Date): Promise<void>;\n\n\t/** Release connections, drop schemas, etc. Called in a finally. */\n\tteardown?(): Promise<void>;\n}\n\n/**\n * What an adapter supplies to run the idempotency-store contract suite.\n *\n * The port (`IdempotencyStore`) deliberately supports two adapter\n * families with different lifecycle semantics, and the suite follows\n * the declared family instead of forcing one onto the other:\n *\n * - `\"transactional\"` (the single-transaction pattern): the record\n * lives in the same database as the aggregates; a committed\n * `complete` is final and replayable, a rollback releases everything,\n * and `renew`/`confirm`/`abandon`/`reconcile` are no-ops. The family's core proof is the\n * rollback test, so environments MUST provide `runRolledBack`, and\n * run against a real database for SQL adapters.\n * - `\"non-transactional\"` (the leased two-phase pattern, e.g. the\n * in-memory reference): the store cannot see commits, so `complete` only\n * STAGES the outcome, `confirm` finalizes it post-commit, `abandon`\n * compensates failed attempts, and expired staged records require\n * reconciliation. Environments MUST provide deterministic `expireLease` and\n * `advanceTimeTo` controls. The rollback test is skipped.\n */\nexport interface IdempotencyStoreContractHarness<TCtx> {\n\tcreateEnvironment(): Promise<IdempotencyStoreContractEnvironment<TCtx>>;\n\n\t/** Which lifecycle family the adapter implements; see above. */\n\tfamily: \"transactional\" | \"non-transactional\";\n}\n\nfunction claimedHandle(\n\tclaim: IdempotencyClaim,\n\tmessage: string,\n): IdempotencyClaimHandle {\n\tassert(claim.status === \"claimed\", message);\n\treturn claim.claim;\n}\n\nasync function expireLease<TCtx>(\n\tenv: IdempotencyStoreContractEnvironment<TCtx>,\n\tclaim: IdempotencyClaimHandle,\n): Promise<void> {\n\tif (!env.expireLease) {\n\t\tthrow new Error(\n\t\t\t\"Contract violated: the non-transactional family requires expireLease on the environment\",\n\t\t);\n\t}\n\tawait env.expireLease(claim);\n}\n\nasync function advanceTimeTo<TCtx>(\n\tenv: IdempotencyStoreContractEnvironment<TCtx>,\n\tinstant: Date,\n): Promise<void> {\n\tif (!env.advanceTimeTo) {\n\t\tthrow new Error(\n\t\t\t\"Contract violated: the non-transactional family requires advanceTimeTo on the environment\",\n\t\t);\n\t}\n\tawait env.advanceTimeTo(instant);\n}\n\n/**\n * The idempotency-store contract test suite: the proof that an adapter\n * delivers the claim/renew/complete/confirm/abandon/reconcile lifecycle\n * `withIdempotentCommit` documents, for its declared family. Store\n * semantics are an **adapter contract, not a kit guarantee**; this\n * suite is how an adapter demonstrates them.\n *\n * Framework-agnostic: bind with\n * `(test.skipped ? it.skip : it)(test.name, test.run)`.\n */\nexport function createIdempotencyStoreContractTests<TCtx>(\n\tharness: IdempotencyStoreContractHarness<TCtx>,\n): IdempotencyStoreContractTest[] {\n\tconst inEnv = bindContractEnvironment(() => harness.createEnvironment());\n\n\t// Shared tests: hold for BOTH families (confirm/abandon are no-ops in\n\t// the transactional family, which these tests tolerate by design).\n\tconst tests: IdempotencyStoreContractTest[] = [\n\t\t{\n\t\t\tname: \"a fresh key is claimed; the full lifecycle replays the outcome\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\tawait env.run((ctx) => env.store.claim(ctx, \"key-1\", \"fp-1\")),\n\t\t\t\t\t\"a fresh key must be claimed by this execution\",\n\t\t\t\t);\n\t\t\t\tawait env.run((ctx) => env.store.complete(ctx, claim, { total: 42 }));\n\t\t\t\tawait env.store.confirm(claim);\n\t\t\t\tconst replay = await env.run((ctx) =>\n\t\t\t\t\tenv.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\treplay.status === \"completed\",\n\t\t\t\t\t\"a completed and confirmed key must replay as completed\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(replay.outcome, { total: 42 }),\n\t\t\t\t\t\"the replayed outcome must round-trip the stored value\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"the same key with a different fingerprint throws IdempotencyKeyReuseError\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\t// Built on a COMPLETED record: the one same-key/other-command\n\t\t\t\t// state both families can actually reach in production (a\n\t\t\t\t// transactional store never commits a bare pending claim).\n\t\t\t\tconst first = await env.run(async (ctx) => {\n\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\tawait env.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.complete(ctx, claim, \"done\");\n\t\t\t\t\treturn claim;\n\t\t\t\t});\n\t\t\t\tawait env.store.confirm(first);\n\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\tenv.run((ctx) => env.store.claim(ctx, \"key-1\", \"fp-OTHER\")),\n\t\t\t\t);\n\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\trejection,\n\t\t\t\t\t[\"IDEMPOTENCY_KEY_REUSE\"],\n\t\t\t\t\t\"a different fingerprint must throw IdempotencyKeyReuseError, never replay another command's outcome\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"abandon never destroys a completed, confirmed outcome\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst first = await env.run(async (ctx) => {\n\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\tawait env.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.complete(ctx, claim, \"done\");\n\t\t\t\t\treturn claim;\n\t\t\t\t});\n\t\t\t\tawait env.store.confirm(first);\n\t\t\t\tawait env.store.abandon(first);\n\t\t\t\tconst claim = await env.run((ctx) =>\n\t\t\t\t\tenv.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tclaim.status === \"completed\",\n\t\t\t\t\t\"abandon must not release a completed, confirmed record\",\n\t\t\t\t);\n\t\t\t\tassertEqual(claim.outcome, \"done\", \"the outcome survives\");\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"confirm is idempotent, and confirming a missing key is a no-op\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst first = await env.run(async (ctx) => {\n\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\tawait env.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.complete(ctx, claim, \"done\");\n\t\t\t\t\treturn claim;\n\t\t\t\t});\n\t\t\t\tawait env.store.confirm(first);\n\t\t\t\tawait env.store.confirm(first);\n\t\t\t\tawait env.store.confirm({ key: \"never-claimed\", token: \"missing\" });\n\t\t\t\tconst claim = await env.run((ctx) =>\n\t\t\t\t\tenv.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tclaim.status === \"completed\" && claim.outcome === \"done\",\n\t\t\t\t\t\"re-confirms and unknown-key confirms must change nothing\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"complete without a pending claim throws the wiring error\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\tenv.run((ctx) =>\n\t\t\t\t\t\tenv.store.complete(ctx, { key: \"key-1\", token: \"missing\" }, \"x\"),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\trejection,\n\t\t\t\t\t[\"IDEMPOTENCY_COMPLETED_WITHOUT_CLAIM\"],\n\t\t\t\t\t\"complete() without claim() must throw IdempotencyCompletionWithoutClaimError\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t];\n\n\tconst nonTransactional = harness.family === \"non-transactional\";\n\n\t// The commit-is-the-finalize proof only EXISTS for the transactional\n\t// family; a two-phase store must do the OPPOSITE (an unconfirmed\n\t// staged outcome stays in-flight), so there is no skip twin for it.\n\tif (!nonTransactional) {\n\t\ttests.push({\n\t\t\tname: \"a committed complete replays even without confirm (commit is the finalize)\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(async (ctx) => {\n\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\tawait env.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.complete(ctx, claim, \"done\");\n\t\t\t\t});\n\t\t\t\t// No confirm: for a transactional store the commit already\n\t\t\t\t// finalized the record.\n\t\t\t\tconst claim = await env.run((ctx) =>\n\t\t\t\t\tenv.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tclaim.status === \"completed\" && claim.outcome === \"done\",\n\t\t\t\t\t\"a committed complete must replay without a confirm call\",\n\t\t\t\t);\n\t\t\t}),\n\t\t});\n\t}\n\n\ttests.push(\n\t\t// A committed-yet-pending claim is a state only the two-phase family\n\t\t// can reach (its claims commit immediately). In the\n\t\t// single-transaction pattern, concurrent claimers collide on the row\n\t\t// lock of an UNCOMMITTED insert, which a sequential suite cannot\n\t\t// portably provoke, and a committed bare claim is legitimately\n\t\t// treated as a stale crash leftover an adapter may reclaim.\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"family: non-transactional\",\n\t\t\t\tsatisfiedBy: nonTransactional,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"a pending claim is in-flight for concurrent claimers, and the error is retryable\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tawait env.run((ctx) => env.store.claim(ctx, \"key-1\", \"fp-1\"));\n\t\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\t\tenv.run((ctx) => env.store.claim(ctx, \"key-1\", \"fp-1\")),\n\t\t\t\t\t);\n\t\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\t\trejection,\n\t\t\t\t\t\t[\"IDEMPOTENCY_IN_FLIGHT\"],\n\t\t\t\t\t\t\"claiming a pending key must throw IdempotencyInFlightError\",\n\t\t\t\t\t);\n\t\t\t\t\t// Chain-walked like the kit's retry classifier: an adapter may\n\t\t\t\t\t// wrap the kit error, exactly as the code-based check above\n\t\t\t\t\t// tolerates, and a consumer's retry loop still sees retryable.\n\t\t\t\t\tassert(\n\t\t\t\t\t\tchainContainsRetryable(rejection),\n\t\t\t\t\t\t\"the in-flight error must be retryable (on the rejection or its cause chain)\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"family: non-transactional\",\n\t\t\t\tsatisfiedBy: nonTransactional,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"renew extends ownership beyond the original lease expiry\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\tawait env.run((ctx) => env.store.claim(ctx, \"key-renew\", \"fp\")),\n\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tclaim.lease !== undefined,\n\t\t\t\t\t\t\"a non-transactional claim must carry lease timing\",\n\t\t\t\t\t);\n\t\t\t\t\tconst originalExpiry = new Date(claim.lease.expiresAt).getTime();\n\t\t\t\t\tassert(\n\t\t\t\t\t\tNumber.isFinite(originalExpiry) &&\n\t\t\t\t\t\t\tnew Date(originalExpiry).toISOString() ===\n\t\t\t\t\t\t\t\tclaim.lease.expiresAt &&\n\t\t\t\t\t\t\tNumber.isSafeInteger(claim.lease.renewAfterMs) &&\n\t\t\t\t\t\t\tclaim.lease.renewAfterMs > 0,\n\t\t\t\t\t\t\"lease timing must carry a valid expiry and positive safe renewal delay\",\n\t\t\t\t\t);\n\t\t\t\t\tawait advanceTimeTo(env, new Date(originalExpiry - 1));\n\t\t\t\t\tconst renewed = await env.store.renew(claim);\n\t\t\t\t\tassert(\n\t\t\t\t\t\trenewed !== undefined &&\n\t\t\t\t\t\t\tnew Date(renewed.expiresAt).getTime() > originalExpiry,\n\t\t\t\t\t\t\"renew must extend the lease beyond its previous expiry\",\n\t\t\t\t\t);\n\t\t\t\t\tawait advanceTimeTo(env, new Date(originalExpiry + 1));\n\t\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\t\tenv.run((ctx) => env.store.claim(ctx, \"key-renew\", \"fp\")),\n\t\t\t\t\t);\n\t\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\t\trejection,\n\t\t\t\t\t\t[\"IDEMPOTENCY_IN_FLIGHT\"],\n\t\t\t\t\t\t\"the renewed owner must still hold the key after the original expiry\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"family: non-transactional\",\n\t\t\t\tsatisfiedBy: nonTransactional,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"an expired pending lease is reclaimed under a new token and fences its stale owner\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tconst first = claimedHandle(\n\t\t\t\t\t\tawait env.run((ctx) => env.store.claim(ctx, \"key-1\", \"fp-1\")),\n\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tfirst.lease !== undefined,\n\t\t\t\t\t\t\"a non-transactional claim must carry lease timing\",\n\t\t\t\t\t);\n\t\t\t\t\tawait expireLease(env, first);\n\t\t\t\t\tconst successor = claimedHandle(\n\t\t\t\t\t\tawait env.run((ctx) => env.store.claim(ctx, \"key-1\", \"fp-1\")),\n\t\t\t\t\t\t\"an expired pending claim must be reclaimed\",\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tsuccessor.token !== first.token,\n\t\t\t\t\t\t\"each ownership generation must have a different token\",\n\t\t\t\t\t);\n\t\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\t\tenv.run((ctx) => env.store.complete(ctx, first, \"stale\")),\n\t\t\t\t\t);\n\t\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\t\trejection,\n\t\t\t\t\t\t[\"IDEMPOTENCY_CLAIM_LOST\"],\n\t\t\t\t\t\t\"a stale owner must fail before it can complete after takeover\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"family: non-transactional\",\n\t\t\t\tsatisfiedBy: nonTransactional,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"an expired staged outcome requires reconciliation and never auto-replays\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tconst first = await env.run(async (ctx) => {\n\t\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\t\tawait env.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait env.store.complete(ctx, claim, \"uncertain\");\n\t\t\t\t\t\treturn claim;\n\t\t\t\t\t});\n\t\t\t\t\tawait expireLease(env, first);\n\t\t\t\t\tconst claim = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tclaim.status === \"reconciliation-required\",\n\t\t\t\t\t\t\"an expired staged outcome must require authoritative reconciliation\",\n\t\t\t\t\t);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tclaim.reconciliation.token,\n\t\t\t\t\t\tfirst.token,\n\t\t\t\t\t\t\"the reconciliation receipt identifies the staged owner\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"family: non-transactional\",\n\t\t\t\tsatisfiedBy: nonTransactional,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"reconciliation confirms committed work or releases proven rollback\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tconst committedHandle = await env.run(async (ctx) => {\n\t\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\t\tawait env.store.claim(ctx, \"committed\", \"fp\"),\n\t\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait env.store.complete(ctx, claim, \"winner\");\n\t\t\t\t\t\treturn claim;\n\t\t\t\t\t});\n\t\t\t\t\tawait expireLease(env, committedHandle);\n\t\t\t\t\tconst committed = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.claim(ctx, \"committed\", \"fp\"),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tcommitted.status === \"reconciliation-required\",\n\t\t\t\t\t\t\"the staged outcome must expose its reconciliation receipt\",\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.reconcile(committed.reconciliation, \"committed\");\n\t\t\t\t\tconst replay = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.claim(ctx, \"committed\", \"fp\"),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\treplay.status === \"completed\" && replay.outcome === \"winner\",\n\t\t\t\t\t\t\"committed evidence must make the staged outcome replayable\",\n\t\t\t\t\t);\n\n\t\t\t\t\tconst rolledBackHandle = await env.run(async (ctx) => {\n\t\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\t\tawait env.store.claim(ctx, \"rolled-back\", \"fp\"),\n\t\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait env.store.complete(ctx, claim, \"must disappear\");\n\t\t\t\t\t\treturn claim;\n\t\t\t\t\t});\n\t\t\t\t\tawait expireLease(env, rolledBackHandle);\n\t\t\t\t\tconst rolledBack = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.claim(ctx, \"rolled-back\", \"fp\"),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\trolledBack.status === \"reconciliation-required\",\n\t\t\t\t\t\t\"the staged outcome must expose its reconciliation receipt\",\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.reconcile(rolledBack.reconciliation, \"not-committed\");\n\t\t\t\t\tconst fresh = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.claim(ctx, \"rolled-back\", \"fp\"),\n\t\t\t\t\t);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tfresh.status,\n\t\t\t\t\t\t\"claimed\",\n\t\t\t\t\t\t\"not-committed evidence must release the staged outcome\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\t// Two-phase-hooks family: staged semantics and real abandon are the\n\t\t// core proofs; the transactional family's hooks are no-ops instead.\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"family: non-transactional\",\n\t\t\t\tsatisfiedBy: nonTransactional,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"a staged, unconfirmed outcome is in-flight, never replayed\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tawait env.run(async (ctx) => {\n\t\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\t\tawait env.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait env.store.complete(ctx, claim, \"uncommitted\");\n\t\t\t\t\t});\n\t\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\t\tenv.run((ctx) => env.store.claim(ctx, \"key-1\", \"fp-1\")),\n\t\t\t\t\t);\n\t\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\t\trejection,\n\t\t\t\t\t\t[\"IDEMPOTENCY_IN_FLIGHT\"],\n\t\t\t\t\t\t\"a staged outcome must never replay; it is in-flight until confirmed\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"family: non-transactional\",\n\t\t\t\tsatisfiedBy: nonTransactional,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"abandon releases a pending claim so the next attempt claims fresh\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tconst first = claimedHandle(\n\t\t\t\t\t\tawait env.run((ctx) => env.store.claim(ctx, \"key-1\", \"fp-1\")),\n\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.abandon(first);\n\t\t\t\t\tconst claim = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tclaim.status,\n\t\t\t\t\t\t\"claimed\",\n\t\t\t\t\t\t\"an abandoned pending claim must be claimable again\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"family: non-transactional\",\n\t\t\t\tsatisfiedBy: nonTransactional,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"abandon releases a staged outcome so the next attempt claims fresh\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tconst first = await env.run(async (ctx) => {\n\t\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\t\tawait env.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait env.store.complete(ctx, claim, \"uncommitted\");\n\t\t\t\t\t\treturn claim;\n\t\t\t\t\t});\n\t\t\t\t\tawait env.store.abandon(first);\n\t\t\t\t\tconst claim = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tclaim.status,\n\t\t\t\t\t\t\"claimed\",\n\t\t\t\t\t\t\"an abandoned staged outcome must be claimable again\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\t// Single-transaction family: committed state is final, hooks are\n\t\t// no-ops, and the rollback proof is mandatory.\n\t\tgatedContractTest(\n\t\t\t{ capability: \"family: transactional\", satisfiedBy: !nonTransactional },\n\t\t\t{\n\t\t\t\tname: \"a rolled-back transaction releases the claim (single-transaction pattern)\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tif (!env.runRolledBack) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Contract violated: the transactional family requires runRolledBack on the environment\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait env\n\t\t\t\t\t\t.runRolledBack(async (ctx) => {\n\t\t\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\t\t\tawait env.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tawait env.store.complete(ctx, claim, \"rolled back\");\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\t\t// The rollback mechanism may surface as a rejection; the\n\t\t\t\t\t\t\t// contract under test is the store state afterwards.\n\t\t\t\t\t\t});\n\t\t\t\t\tconst claim = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tclaim.status,\n\t\t\t\t\t\t\"claimed\",\n\t\t\t\t\t\t\"a rolled-back claim/complete must leave the key claimable\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t);\n\n\treturn tests;\n}\n","import type { AggregateAddress } from \"../domain/aggregate/aggregate-address\";\nimport type { AnyDomainEvent } from \"../domain/event/domain-event\";\nimport { deepEqual } from \"../internal/structural/deep-equal\";\nimport type { EventCommitCandidate } from \"../messaging/committed-event\";\nimport type {\n\tDeadLetterRecord,\n\tDispatchTrackingOutbox,\n\tOutbox,\n\tOutboxRecord,\n} from \"../messaging/outbox/ports\";\nimport { isDispatchTrackingOutbox } from \"../messaging/outbox/ports\";\nimport {\n\tassert,\n\tassertEqual,\n\tbindContractEnvironment,\n\ttype ContractTest,\n\tcaptureRejection,\n\tdescribeError,\n\tgatedContractTest,\n} from \"./contract-assertions\";\n\n/** One contract test; bind with `(test.skipped ? it.skip : it)(test.name, test.run)`. */\nexport type OutboxContractTest = ContractTest;\n\n/**\n * One isolated test environment: a fresh outbox store. The suite\n * creates one per test and tears it down afterwards.\n */\nexport interface OutboxContractEnvironment<Evt extends AnyDomainEvent> {\n\t/** The adapter under test. */\n\toutbox: Outbox<Evt> | DispatchTrackingOutbox<Evt>;\n\n\t/**\n\t * Runs `outbox.add(candidates)` inside a transaction that COMMITS, the\n\t * way `withCommit` calls it in production. The suite supplies complete\n\t * candidates with explicit source, aggregate version, zero-based commit\n\t * sequence, and commit size. For a non-transactional store this is simply\n\t * `outbox.add(candidates)`.\n\t */\n\taddCommitted(events: ReadonlyArray<EventCommitCandidate<Evt>>): Promise<void>;\n\n\t/**\n\t * Optional capability: runs `outbox.add(candidates)` inside a\n\t * transaction that ROLLS BACK. Enables the rollback-purity test: a\n\t * rolled-back add must leave nothing behind. Transactional adapters\n\t * should always provide this; it is the half of the outbox promise\n\t * that in-memory fakes cannot keep.\n\t */\n\taddRolledBack?(\n\t\tevents: ReadonlyArray<EventCommitCandidate<Evt>>,\n\t): Promise<void>;\n\n\t/** Release connections, drop schemas, etc. Called in a finally. */\n\tteardown?(): Promise<void>;\n}\n\n/**\n * What an adapter supplies to run the outbox contract suite.\n *\n * For SQL adapters, run against a real database (testcontainers or\n * equivalent): the commit-order and rollback tests prove YOUR schema\n * and transaction wiring, not the kit's.\n *\n * Note on claiming: multi-instance safety (`getPending` claiming via\n * `FOR UPDATE SKIP LOCKED` or equivalent) is part of the port contract\n * for competing dispatchers but is not covered here; concurrency\n * cannot be proven portably by a generic suite. Test it in your\n * adapter's own suite if you run more than one dispatcher.\n */\nexport interface OutboxContractHarness<Evt extends AnyDomainEvent> {\n\tcreateEnvironment(): Promise<OutboxContractEnvironment<Evt>>;\n\n\t/**\n\t * Deterministic event factory: the same `seed` yields an event with\n\t * the SAME `eventId` (the suite uses this for the dedupe test), and\n\t * different seeds yield distinct `eventId`s.\n\t */\n\tcreateEvent(seed: number): Evt;\n\n\t/**\n\t * For a `DispatchTrackingOutbox` adapter: how many `markFailed`\n\t * reports move a record to the dead-letter set (the adapter's\n\t * configured attempt ceiling). Omit for plain `Outbox` adapters;\n\t * the dispatch-tracking tests are then marked skipped. With a\n\t * ceiling of 1 the attempts-surfacing test is marked skipped too:\n\t * observing attempts on a PENDING record needs a record that\n\t * survives one failure.\n\t */\n\tfailuresToDeadLetter?: number;\n\n\t/**\n\t * Declare `true` when environments provide {@link\n\t * OutboxContractEnvironment.addRolledBack}. Without it, the\n\t * rollback-purity test is marked skipped: the honest state of an\n\t * in-memory fake, and a loud gap for a transactional adapter.\n\t */\n\tprovidesRolledBackAdds?: boolean;\n\n\t/**\n\t * Declare `true` when the adapter's `getPending` CLAIMS the returned\n\t * records for competing dispatchers (lease, visibility timeout,\n\t * `FOR UPDATE SKIP LOCKED`), as the port sanctions. Every test that\n\t * re-polls records a previous poll returned without resolving them\n\t * (head stability, re-ack non-disturbance, attempts surfacing)\n\t * assumes a non-claiming read and is marked skipped for claiming\n\t * adapters; prove your claim/expiry semantics in your own suite.\n\t */\n\tclaimsOnGetPending?: boolean;\n\n\t/**\n\t * Declare `true` when `add()` dedupes on `eventId` (the unique-key\n\t * constraint the port RECOMMENDS). The dedupe test is gated on this:\n\t * an adapter without the constraint satisfies the port's normative\n\t * requirements and must not fail the suite, but the skip stays\n\t * visible as the unproven recommendation it is.\n\t */\n\tdedupesOnEventId?: boolean;\n}\n\n/**\n * The outbox contract test suite: the proof that an adapter delivers\n * the guarantees `withCommit` and `OutboxDispatcher` document. The kit\n * is store-agnostic, so commit-order reads, qualified source-position\n * identity, eventful-predecessor linkage, idempotent acks, and rollback\n * purity are an **adapter contract, not a kit guarantee**; this suite is how\n * an adapter demonstrates them. Its source-law tests also prove that colliding\n * raw ids stay isolated by aggregate type and aggregate id.\n *\n * Framework-agnostic: bind with\n * `(test.skipped ? it.skip : it)(test.name, test.run)`.\n */\nexport function createOutboxContractTests<Evt extends AnyDomainEvent>(\n\tharness: OutboxContractHarness<Evt>,\n): OutboxContractTest[] {\n\ttype Env = OutboxContractEnvironment<Evt>;\n\tconst inEnv = bindContractEnvironment(() => harness.createEnvironment());\n\tconst defaultSource: AggregateAddress = {\n\t\taggregateType: \"ContractAggregate\",\n\t\taggregateId: \"contract-aggregate\",\n\t};\n\tconst commit = (\n\t\tevents: ReadonlyArray<Evt>,\n\t\taggregateVersion = 1,\n\t\tsource: AggregateAddress = defaultSource,\n\t): ReadonlyArray<EventCommitCandidate<Evt>> =>\n\t\tevents.map((event, commitSequence) => ({\n\t\t\tevent,\n\t\t\tsource,\n\t\t\tposition: {\n\t\t\t\taggregateVersion,\n\t\t\t\tcommitSequence,\n\t\t\t\tcommitSize: events.length,\n\t\t\t},\n\t\t}));\n\tconst takeAndAck = async (\n\t\tenv: Env,\n\t\tcount: number,\n\t): Promise<ReadonlyArray<OutboxRecord<Evt>>> => {\n\t\tconst records: Array<OutboxRecord<Evt>> = [];\n\t\tfor (let index = 0; index < count; index += 1) {\n\t\t\tconst [record] = await env.outbox.getPending(1);\n\t\t\tassert(\n\t\t\t\trecord !== undefined,\n\t\t\t\t`expected committed outbox record ${index + 1} of ${count}`,\n\t\t\t);\n\t\t\trecords.push(record);\n\t\t\tawait env.outbox.markDispatched([record.dispatchId]);\n\t\t}\n\t\treturn records;\n\t};\n\n\tconst tests: OutboxContractTest[] = [\n\t\t{\n\t\t\tname: \"finalizes complete commit receipts and links the next eventful commit\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.addCommitted(\n\t\t\t\t\tcommit([harness.createEvent(1), harness.createEvent(2)], 1),\n\t\t\t\t);\n\t\t\t\t// Version 2 may have been a state-only commit; the event-source\n\t\t\t\t// predecessor is still the previous EVENTFUL version 1.\n\t\t\t\tawait env.addCommitted(commit([harness.createEvent(3)], 3));\n\t\t\t\tconst records = await takeAndAck(env, 3);\n\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\trecords.map(({ position }) => position),\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\taggregateVersion: 1,\n\t\t\t\t\t\t\t\tcommitSequence: 0,\n\t\t\t\t\t\t\t\tcommitSize: 2,\n\t\t\t\t\t\t\t\tpreviousEventfulAggregateVersion: null,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\taggregateVersion: 1,\n\t\t\t\t\t\t\t\tcommitSequence: 1,\n\t\t\t\t\t\t\t\tcommitSize: 2,\n\t\t\t\t\t\t\t\tpreviousEventfulAggregateVersion: null,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\taggregateVersion: 3,\n\t\t\t\t\t\t\t\tcommitSequence: 0,\n\t\t\t\t\t\t\t\tcommitSize: 1,\n\t\t\t\t\t\t\t\tpreviousEventfulAggregateVersion: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t),\n\t\t\t\t\t\"the source must preserve zero-based commit completeness and link the next eventful commit to version 1\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"rejects different event identities at one qualified source position\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst original = commit([harness.createEvent(1)], 1);\n\t\t\t\tconst collision = commit([harness.createEvent(2)], 1);\n\t\t\t\tawait env.addCommitted(original);\n\t\t\t\tconst rejection = await captureRejection(env.addCommitted(collision));\n\t\t\t\tassert(\n\t\t\t\t\trejection !== undefined,\n\t\t\t\t\t\"a different eventId at one qualified source position must reject\",\n\t\t\t\t);\n\n\t\t\t\tconst [record] = await takeAndAck(env, 1);\n\t\t\t\tassertEqual(\n\t\t\t\t\trecord?.event.eventId,\n\t\t\t\t\toriginal[0]?.event.eventId,\n\t\t\t\t\t\"the rejected collision must not replace the original record\",\n\t\t\t\t);\n\t\t\t\tawait env.addCommitted(commit([harness.createEvent(3)], 2));\n\t\t\t\tconst [next] = await takeAndAck(env, 1);\n\t\t\t\tassertEqual(\n\t\t\t\t\tnext?.position.previousEventfulAggregateVersion,\n\t\t\t\t\t1,\n\t\t\t\t\t\"the rejected collision must not change the source head\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"keeps event-source heads isolated by aggregate type and id\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst sources: ReadonlyArray<AggregateAddress> = [\n\t\t\t\t\t{ aggregateType: \"Order\", aggregateId: \"1\" },\n\t\t\t\t\t{ aggregateType: \"Payment\", aggregateId: \"1\" },\n\t\t\t\t\t{ aggregateType: \"Order\", aggregateId: \"2\" },\n\t\t\t\t];\n\t\t\t\tfor (const [index, source] of sources.entries()) {\n\t\t\t\t\tawait env.addCommitted(\n\t\t\t\t\t\tcommit([harness.createEvent(index + 1)], 1, source),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst records = await takeAndAck(env, sources.length);\n\t\t\t\tassert(\n\t\t\t\t\trecords.every(\n\t\t\t\t\t\t(record, index) =>\n\t\t\t\t\t\t\trecord.source.aggregateType === sources[index]?.aggregateType &&\n\t\t\t\t\t\t\trecord.source.aggregateId === sources[index]?.aggregateId &&\n\t\t\t\t\t\t\trecord.position.previousEventfulAggregateVersion === null,\n\t\t\t\t\t),\n\t\t\t\t\t\"colliding raw ids or aggregate types must each retain an independent genesis head\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"getPending returns records in commit order, across separate committed adds\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.addCommitted(\n\t\t\t\t\tcommit([harness.createEvent(1), harness.createEvent(2)], 1),\n\t\t\t\t);\n\t\t\t\tawait env.addCommitted(commit([harness.createEvent(3)], 2));\n\t\t\t\t// Explicit limit: the port leaves the no-argument page size to\n\t\t\t\t// the implementation, so the suite never relies on it.\n\t\t\t\tconst pending = await env.outbox.getPending(10);\n\t\t\t\t// \"Up to limit\": short pages are port-legal, so the assertion\n\t\t\t\t// is a non-empty PREFIX of commit order, not the full page.\n\t\t\t\tconst expectedIds = [1, 2, 3].map(\n\t\t\t\t\t(seed) => harness.createEvent(seed).eventId,\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tpending.length >= 1,\n\t\t\t\t\t\"a non-empty backlog must surface at least one record\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\tpending.map((record) => record.event.eventId),\n\t\t\t\t\t\texpectedIds.slice(0, pending.length),\n\t\t\t\t\t),\n\t\t\t\t\t\"records must come back in the order add() persisted them\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"getPending respects the limit\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.addCommitted(\n\t\t\t\t\tcommit([1, 2, 3, 4].map((s) => harness.createEvent(s))),\n\t\t\t\t);\n\t\t\t\tconst firstPage = await env.outbox.getPending(2);\n\t\t\t\t// The port promises UP TO `limit` records; a shorter page is\n\t\t\t\t// legal, an empty one against a non-empty backlog is not (the\n\t\t\t\t// dispatcher would spin without progress).\n\t\t\t\tassert(\n\t\t\t\t\tfirstPage.length >= 1 && firstPage.length <= 2,\n\t\t\t\t\t\"limit must bound the page: up to `limit` records, at least one while the backlog is non-empty\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t// Head stability assumes a non-claiming read; the port sanctions\n\t\t// claiming reads (lease, visibility timeout, FOR UPDATE SKIP\n\t\t// LOCKED) for competing dispatchers, and for those an un-acked\n\t\t// head legitimately stays invisible until the claim expires.\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"non-claiming getPending\",\n\t\t\t\tsatisfiedBy: !harness.claimsOnGetPending,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"an un-acked head comes back on the next poll (no silent skipping)\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tawait env.addCommitted(\n\t\t\t\t\t\tcommit([1, 2, 3, 4].map((s) => harness.createEvent(s))),\n\t\t\t\t\t);\n\t\t\t\t\tconst firstPage = await env.outbox.getPending(2);\n\t\t\t\t\tconst again = await env.outbox.getPending(2);\n\t\t\t\t\t// Short pages are port-legal (\"up to limit\"), so compare\n\t\t\t\t\t// the overlapping prefix: what head stability forbids is\n\t\t\t\t\t// silently SKIPPING an un-acked record, not short pages.\n\t\t\t\t\tconst overlap = Math.min(firstPage.length, again.length);\n\t\t\t\t\tassert(\n\t\t\t\t\t\toverlap >= 1,\n\t\t\t\t\t\t\"a non-empty backlog must surface at least one record on every poll\",\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\t\tagain.slice(0, overlap).map((r) => r.dispatchId),\n\t\t\t\t\t\t\tfirstPage.slice(0, overlap).map((r) => r.dispatchId),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t\"an un-acked head must come back on the next poll (no silent skipping)\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\t{\n\t\t\tname: \"markDispatched removes records; re-acks and unknown acks are accepted\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.addCommitted(\n\t\t\t\t\tcommit([harness.createEvent(1), harness.createEvent(2)]),\n\t\t\t\t);\n\t\t\t\tconst [first] = await env.outbox.getPending(1);\n\t\t\t\tassert(first !== undefined, \"expected a pending record\");\n\t\t\t\tawait env.outbox.markDispatched([first.dispatchId]);\n\t\t\t\t// Idempotency: re-acking and acking unknown ids must be no-ops.\n\t\t\t\tawait env.outbox.markDispatched([first.dispatchId]);\n\t\t\t\tawait env.outbox.markDispatched([\"no-such-dispatch-id\"]);\n\t\t\t\t// Membership, not count: claiming adapters may hold back the\n\t\t\t\t// still-pending second record, but a dispatched record must\n\t\t\t\t// never come back for anyone.\n\t\t\t\tconst remaining = await env.outbox.getPending(10);\n\t\t\t\tassert(\n\t\t\t\t\t!remaining.some((r) => r.dispatchId === first.dispatchId),\n\t\t\t\t\t\"a dispatched record must never come back\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t// Observing that OTHER records survive a re-ack needs a re-poll of\n\t\t// records an earlier poll already returned un-acked; claiming\n\t\t// adapters legitimately hold those back until the claim expires.\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"non-claiming getPending\",\n\t\t\t\tsatisfiedBy: !harness.claimsOnGetPending,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"idempotent re-acks do not disturb other pending records\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tawait env.addCommitted(\n\t\t\t\t\t\tcommit([harness.createEvent(1), harness.createEvent(2)]),\n\t\t\t\t\t);\n\t\t\t\t\tconst [first] = await env.outbox.getPending(1);\n\t\t\t\t\tassert(first !== undefined, \"expected a pending record\");\n\t\t\t\t\tawait env.outbox.markDispatched([first.dispatchId]);\n\t\t\t\t\tawait env.outbox.markDispatched([first.dispatchId]);\n\t\t\t\t\tawait env.outbox.markDispatched([\"no-such-dispatch-id\"]);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\t(await env.outbox.getPending(10)).length,\n\t\t\t\t\t\t1,\n\t\t\t\t\t\t\"idempotent re-acks must not disturb other records\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\t// Dedupe on eventId is the port's RECOMMENDATION, not a normative\n\t\t// requirement; only adapters that declare the unique-key constraint\n\t\t// are held to it.\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"dedupesOnEventId\",\n\t\t\t\tsatisfiedBy: harness.dedupesOnEventId === true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"re-adding an event with the same eventId is deduped, not duplicated\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tconst original = commit([harness.createEvent(1)]);\n\t\t\t\t\tawait env.addCommitted(original);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait env.addCommitted(original);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t// A bare UNIQUE(eventId) constraint makes the duplicate\n\t\t\t\t\t\t// INSERT throw; the contract wants an idempotent add.\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Contract violated: add() must swallow a duplicate eventId, not throw. \" +\n\t\t\t\t\t\t\t\t\"Dedupe means an idempotent add (INSERT ... ON CONFLICT DO NOTHING or \" +\n\t\t\t\t\t\t\t\t`equivalent), not a raised unique violation. Got: ${describeError(error)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst pending = await env.outbox.getPending(10);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tpending.length,\n\t\t\t\t\t\t1,\n\t\t\t\t\t\t\"the same eventId must yield one record (unique-key dedupe)\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t];\n\n\t// Rollback purity: capability-gated (in-memory fakes cannot keep it).\n\ttests.push(\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"providesRolledBackAdds\",\n\t\t\t\tsatisfiedBy: harness.providesRolledBackAdds === true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"a rolled-back add leaves nothing behind (transactional participation)\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tif (!env.addRolledBack) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Contract violated: harness declared providesRolledBackAdds but the environment lacks addRolledBack\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait env.addRolledBack(commit([harness.createEvent(1)], 1));\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\t(await env.outbox.getPending(10)).length,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t\"events added in a rolled-back transaction must not appear\",\n\t\t\t\t\t);\n\t\t\t\t\tawait env.addCommitted(commit([harness.createEvent(2)], 2));\n\t\t\t\t\tconst [afterRollback] = await takeAndAck(env, 1);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tafterRollback?.position.previousEventfulAggregateVersion,\n\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\"a rolled-back add must not advance the event-source head\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t);\n\n\t// Dispatch tracking: gated on the harness declaring the ceiling.\n\t// `attemptCeiling` is only ever read inside enabled tests, where the\n\t// gate guarantees the harness declared it.\n\tconst trackingEnabled = harness.failuresToDeadLetter !== undefined;\n\tconst attemptCeiling = harness.failuresToDeadLetter ?? 0;\n\tconst trackingGate = (test: ContractTest): ContractTest =>\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"failuresToDeadLetter (DispatchTrackingOutbox)\",\n\t\t\t\tsatisfiedBy: trackingEnabled,\n\t\t\t},\n\t\t\ttest,\n\t\t);\n\ttests.push(\n\t\ttrackingGate(\n\t\t\t// Observing attempts needs the record back on a re-poll after an\n\t\t\t// un-acked poll (a claiming adapter may hold it until the claim\n\t\t\t// expires) AND a record that survives one failure (with a\n\t\t\t// ceiling of 1, the single markFailed dead-letters it before\n\t\t\t// the re-poll, exactly as the port requires).\n\t\t\tgatedContractTest(\n\t\t\t\t{\n\t\t\t\t\tcapability: \"non-claiming getPending\",\n\t\t\t\t\tsatisfiedBy: !harness.claimsOnGetPending,\n\t\t\t\t},\n\t\t\t\tgatedContractTest(\n\t\t\t\t\t{\n\t\t\t\t\t\tcapability: \"failuresToDeadLetter >= 2\",\n\t\t\t\t\t\tsatisfiedBy: attemptCeiling >= 2,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"markFailed increments attempts surfaced on pending records\",\n\t\t\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\t\t\tconst outbox = env.outbox;\n\t\t\t\t\t\t\tassert(\n\t\t\t\t\t\t\t\tisDispatchTrackingOutbox(outbox),\n\t\t\t\t\t\t\t\t\"harness declared a tracking outbox\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tawait env.addCommitted(commit([harness.createEvent(1)]));\n\t\t\t\t\t\t\tconst [record] = await outbox.getPending(1);\n\t\t\t\t\t\t\tassert(record !== undefined, \"expected a pending record\");\n\t\t\t\t\t\t\tawait outbox.markFailed(record.dispatchId, new Error(\"boom\"));\n\t\t\t\t\t\t\tconst [after] = await outbox.getPending(1);\n\t\t\t\t\t\t\tassertEqual(\n\t\t\t\t\t\t\t\tafter?.attempts,\n\t\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\t\t\"attempts must be surfaced on the record after markFailed\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}),\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t),\n\t\t),\n\t\ttrackingGate({\n\t\t\tname: \"reaching the attempt ceiling dead-letters the record and unblocks getPending\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst outbox = env.outbox;\n\t\t\t\tassert(\n\t\t\t\t\tisDispatchTrackingOutbox(outbox),\n\t\t\t\t\t\"harness declared a tracking outbox\",\n\t\t\t\t);\n\t\t\t\tawait env.addCommitted(\n\t\t\t\t\tcommit([harness.createEvent(1), harness.createEvent(2)]),\n\t\t\t\t);\n\t\t\t\tconst [poison] = await outbox.getPending(1);\n\t\t\t\tassert(poison !== undefined, \"expected a pending record\");\n\t\t\t\tlet transition: DeadLetterRecord<Evt> | undefined;\n\t\t\t\tfor (let i = 0; i < attemptCeiling; i++) {\n\t\t\t\t\tconst current = await outbox.markFailed(\n\t\t\t\t\t\tpoison.dispatchId,\n\t\t\t\t\t\tnew Error(\"poison\"),\n\t\t\t\t\t);\n\t\t\t\t\tif (i < attemptCeiling - 1) {\n\t\t\t\t\t\tassertEqual(\n\t\t\t\t\t\t\tcurrent,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\"markFailed must not report a dead-letter transition below the ceiling\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\ttransition = current;\n\t\t\t\t}\n\t\t\t\tassertEqual(\n\t\t\t\t\ttransition?.dispatchId,\n\t\t\t\t\tpoison.dispatchId,\n\t\t\t\t\t\"the ceiling-crossing markFailed call must return the exact dead-letter transition\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\ttransition?.attempts,\n\t\t\t\t\tattemptCeiling,\n\t\t\t\t\t\"the returned transition must carry the final attempt count\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait outbox.markFailed(poison.dispatchId, new Error(\"late\")),\n\t\t\t\t\tundefined,\n\t\t\t\t\t\"a late failure report must not repeat the dead-letter transition\",\n\t\t\t\t);\n\t\t\t\tconst pending = await outbox.getPending(10);\n\t\t\t\tassertEqual(\n\t\t\t\t\tpending.length,\n\t\t\t\t\t1,\n\t\t\t\t\t\"the dead-lettered record must stop coming back; successors must flow\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tpending[0]?.dispatchId !== poison.dispatchId,\n\t\t\t\t\t\"the surviving record must be the successor, not the poison one\",\n\t\t\t\t);\n\t\t\t\tconst dead = await outbox.deadLetters();\n\t\t\t\tassertEqual(dead.length, 1, \"the record must appear in deadLetters()\");\n\t\t\t\tassertEqual(\n\t\t\t\t\tdead[0]?.attempts,\n\t\t\t\t\tattemptCeiling,\n\t\t\t\t\t\"the dead-letter record must carry its attempt count\",\n\t\t\t\t);\n\t\t\t}),\n\t\t}),\n\t\ttrackingGate({\n\t\t\tname: \"markFailed on unknown or dispatched ids never resurrects a record\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst outbox = env.outbox;\n\t\t\t\tassert(\n\t\t\t\t\tisDispatchTrackingOutbox(outbox),\n\t\t\t\t\t\"harness declared a tracking outbox\",\n\t\t\t\t);\n\t\t\t\tawait env.addCommitted(commit([harness.createEvent(1)]));\n\t\t\t\tconst [record] = await outbox.getPending(1);\n\t\t\t\tassert(record !== undefined, \"expected a pending record\");\n\t\t\t\tawait outbox.markDispatched([record.dispatchId]);\n\t\t\t\tawait outbox.markFailed(record.dispatchId, new Error(\"late report\"));\n\t\t\t\tawait outbox.markFailed(\"no-such-id\", new Error(\"unknown\"));\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await outbox.getPending(10)).length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"late or unknown failure reports must not resurrect records\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await outbox.deadLetters()).length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"late or unknown failure reports must not dead-letter anything\",\n\t\t\t\t);\n\t\t\t}),\n\t\t}),\n\t\ttrackingGate({\n\t\t\tname: \"markDispatched clears a dead-lettered record (manual redelivery then ack)\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst outbox = env.outbox;\n\t\t\t\tassert(\n\t\t\t\t\tisDispatchTrackingOutbox(outbox),\n\t\t\t\t\t\"harness declared a tracking outbox\",\n\t\t\t\t);\n\t\t\t\tawait env.addCommitted(commit([harness.createEvent(1)]));\n\t\t\t\tconst [record] = await outbox.getPending(1);\n\t\t\t\tassert(record !== undefined, \"expected a pending record\");\n\t\t\t\tfor (let i = 0; i < attemptCeiling; i++) {\n\t\t\t\t\tawait outbox.markFailed(record.dispatchId, new Error(\"poison\"));\n\t\t\t\t}\n\t\t\t\tawait outbox.markDispatched([record.dispatchId]);\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await outbox.deadLetters()).length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"acking a dead-lettered record must clear it\",\n\t\t\t\t);\n\t\t\t}),\n\t\t}),\n\t);\n\n\treturn tests;\n}\n","import type {\n\tProjectionCheckpoint,\n\tProjectionCheckpointStore,\n\tProjectionPosition,\n} from \"../application/projections/ports\";\nimport type { AggregateAddress } from \"../domain/aggregate/aggregate-address\";\nimport {\n\tassert,\n\tassertEqual,\n\tbindContractEnvironment,\n\ttype ContractTest,\n\tcaptureRejection,\n\tgatedContractTest,\n} from \"./contract-assertions\";\n\n/** One contract test; bind with `(test.skipped ? it.skip : it)(test.name, test.run)`. */\nexport type ProjectionCheckpointStoreContractTest = ContractTest;\n\n/**\n * One isolated test environment: a fresh checkpoint store. The suite\n * creates one per test and tears it down afterwards.\n */\nexport interface ProjectionCheckpointStoreContractEnvironment<TCtx> {\n\t/** The adapter under test. */\n\tstore: ProjectionCheckpointStore<TCtx>;\n\n\t/**\n\t * Runs `work` inside a transaction that COMMITS, handing it the\n\t * transaction context the store methods expect, the way the\n\t * `Projector` calls them in production. For a non-transactional\n\t * store this simply invokes `work` with a dummy context.\n\t */\n\trun<R>(work: (ctx: TCtx) => Promise<R>): Promise<R>;\n\n\t/**\n\t * Optional capability: starts every supplied transaction independently and\n\t * concurrently. Each callback must receive its own transaction context for\n\t * database adapters (normally a separate pooled connection). Enables the\n\t * missing-key/existing-key exclusion test; implementing this as sequential\n\t * calls would make that proof meaningless.\n\t */\n\trunConcurrently?<R>(\n\t\tworks: ReadonlyArray<(ctx: TCtx) => Promise<R>>,\n\t): Promise<R[]>;\n\n\t/**\n\t * Optional capability: runs `work` inside a transaction that ROLLS\n\t * BACK. Enables the rollback test: a rolled-back save must leave no\n\t * checkpoint behind, the half of the atomic update+checkpoint\n\t * promise the store contributes. Transactional adapters should\n\t * always provide this; in-memory fakes cannot.\n\t */\n\trunRolledBack?<R>(work: (ctx: TCtx) => Promise<R>): Promise<R>;\n\n\t/** Release connections, drop schemas, etc. Called in a finally. */\n\tteardown?(): Promise<void>;\n}\n\n/**\n * What an adapter supplies to run the projection-checkpoint-store\n * contract suite. For SQL adapters, run against a real database\n * (testcontainers or equivalent): concurrent runs prove missing-key locking,\n * the rollback test proves YOUR transaction wiring, and the checkpoint table\n * must live in the same database as the read models it accounts for.\n */\nexport interface ProjectionCheckpointStoreContractHarness<TCtx> {\n\tcreateEnvironment(): Promise<\n\t\tProjectionCheckpointStoreContractEnvironment<TCtx>\n\t>;\n\n\t/**\n\t * Declare `true` when environments provide {@link\n\t * ProjectionCheckpointStoreContractEnvironment.runRolledBack}.\n\t * Without it, the rollback test is marked skipped: the honest state\n\t * of an in-memory fake, and a loud gap for a transactional adapter.\n\t */\n\tprovidesRolledBackRuns?: boolean;\n\n\t/**\n\t * Declare `true` when environments provide {@link\n\t * ProjectionCheckpointStoreContractEnvironment.runConcurrently}. Without\n\t * it, missing-key lock safety is marked skipped and remains an explicitly\n\t * unproven adapter guarantee.\n\t */\n\tprovidesConcurrentRuns?: boolean;\n}\n\nconst pos = (\n\taggregateVersion: number,\n\tcommitSequence: number,\n\tcommitSize = commitSequence + 1,\n\tpreviousEventfulAggregateVersion: number | null = null,\n): ProjectionPosition => ({\n\taggregateVersion,\n\tcommitSequence,\n\tcommitSize,\n\tpreviousEventfulAggregateVersion,\n});\n\nconst order = (aggregateId: string): AggregateAddress => ({\n\taggregateType: \"Order\",\n\taggregateId,\n});\n\nconst checkpoint = (\n\tposition: ProjectionPosition,\n\tlastAppliedEventId = \"evt-at-watermark\",\n): ProjectionCheckpoint => ({ position, lastAppliedEventId });\n\n/**\n * The projection-checkpoint-store contract test suite: the proof that\n * an adapter delivers the watermark semantics the `Projector`\n * documents. Checkpoint semantics are an **adapter contract, not a\n * kit guarantee**; this suite is how an adapter demonstrates them. Enable its\n * concurrent-runs capability to prove genesis-safe exclusion rather than\n * leaving that guarantee visibly skipped.\n *\n * The concurrent test exercises commit visibility, but cannot deterministically\n * hold an adapter between return from `withCheckpointLocks` and its surrounding\n * transaction commit. It can therefore expose an early lock release only when\n * a waiter enters during that window; holding database locks through commit or\n * rollback remains an explicit adapter responsibility, not a complete proof\n * supplied by this suite.\n *\n * Framework-agnostic: bind with\n * `(test.skipped ? it.skip : it)(test.name, test.run)`.\n */\nexport function createProjectionCheckpointStoreContractTests<TCtx>(\n\tharness: ProjectionCheckpointStoreContractHarness<TCtx>,\n): ProjectionCheckpointStoreContractTest[] {\n\tconst inEnv = bindContractEnvironment(() => harness.createEnvironment());\n\n\treturn [\n\t\t{\n\t\t\tname: \"a never-seen (projection, aggregate) pair loads undefined\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst loaded = await env.run((ctx) =>\n\t\t\t\t\tenv.store.load(ctx, \"order-list\", order(\"o-1\")),\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tloaded,\n\t\t\t\t\tundefined,\n\t\t\t\t\t\"a fresh store must report no watermark\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"providesConcurrentRuns\",\n\t\t\t\tsatisfiedBy: harness.providesConcurrentRuns === true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"checkpoint locks serialize competing critical sections for absent and existing rows\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tconst runConcurrently = env.runConcurrently;\n\t\t\t\t\tif (!runConcurrently) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Contract violated: harness declared providesConcurrentRuns but the environment lacks runConcurrently\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst contenders = 8;\n\t\t\t\t\tconst address = order(\"o-locked\");\n\t\t\t\t\tconst advanceOnce = async (\n\t\t\t\t\t\texpectedVersion: number | undefined,\n\t\t\t\t\t\tnextVersion: number,\n\t\t\t\t\t): Promise<number> => {\n\t\t\t\t\t\tconst outcomes = await runConcurrently(\n\t\t\t\t\t\t\tArray.from(\n\t\t\t\t\t\t\t\t{ length: contenders },\n\t\t\t\t\t\t\t\t() => (ctx) =>\n\t\t\t\t\t\t\t\t\tenv.store.withCheckpointLocks(\n\t\t\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\t\t\t\t\t[address],\n\t\t\t\t\t\t\t\t\t\tasync () => {\n\t\t\t\t\t\t\t\t\t\t\tconst stored = await env.store.load(\n\t\t\t\t\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\t\t\t\t\t\t\taddress,\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\t\t\texpectedVersion === undefined\n\t\t\t\t\t\t\t\t\t\t\t\t\t? stored !== undefined\n\t\t\t\t\t\t\t\t\t\t\t\t\t: stored?.position.aggregateVersion !==\n\t\t\t\t\t\t\t\t\t\t\t\t\t\texpectedVersion\n\t\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tawait Promise.resolve();\n\t\t\t\t\t\t\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\t\t\t\t\t\t\taddress,\n\t\t\t\t\t\t\t\t\t\t\t\tcheckpoint(pos(nextVersion, 0), `evt-v${nextVersion}`),\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn outcomes.filter((advanced) => advanced).length;\n\t\t\t\t\t};\n\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tawait advanceOnce(undefined, 1),\n\t\t\t\t\t\t1,\n\t\t\t\t\t\t\"exactly one competing callback may advance a missing checkpoint key; genesis has no row that SELECT FOR UPDATE could lock\",\n\t\t\t\t\t);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tawait advanceOnce(1, 2),\n\t\t\t\t\t\t1,\n\t\t\t\t\t\t\"exactly one competing callback may advance an existing checkpoint key from the observed watermark\",\n\t\t\t\t\t);\n\t\t\t\t\tconst stored = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.load(ctx, \"order-list\", address),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tstored?.position.aggregateVersion === 2,\n\t\t\t\t\t\t\"serialized genesis and existing-row advances must leave the final watermark visible\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\t{\n\t\t\tname: \"checkpoint locks release after a rejected critical section\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst address = order(\"o-rejected-lock\");\n\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\tenv.run((ctx) =>\n\t\t\t\t\t\tenv.store.withCheckpointLocks(\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\t\t[address],\n\t\t\t\t\t\t\tasync () => {\n\t\t\t\t\t\t\t\tthrow new Error(\"projection failed\");\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\trejection !== undefined,\n\t\t\t\t\t\"the store must propagate a rejected critical section\",\n\t\t\t\t);\n\n\t\t\t\tlet retried = false;\n\t\t\t\tawait env.run((ctx) =>\n\t\t\t\t\tenv.store.withCheckpointLocks(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\t[address],\n\t\t\t\t\t\tasync () => {\n\t\t\t\t\t\t\tretried = true;\n\t\t\t\t\t\t},\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tretried,\n\t\t\t\t\t\"a rejected callback must release its key so redelivery can enter\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"save/load round-trips the complete checkpoint receipt\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run((ctx) =>\n\t\t\t\t\tenv.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\tcheckpoint(pos(5, 2, 3, 3), \"evt-o-1-5-2\"),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tconst loaded = await env.run((ctx) =>\n\t\t\t\t\tenv.store.load(ctx, \"order-list\", order(\"o-1\")),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tloaded?.position.aggregateVersion === 5 &&\n\t\t\t\t\t\tloaded.position.commitSequence === 2 &&\n\t\t\t\t\t\tloaded.position.commitSize === 3 &&\n\t\t\t\t\t\tloaded.position.previousEventfulAggregateVersion === 3 &&\n\t\t\t\t\t\tloaded.lastAppliedEventId === \"evt-o-1-5-2\",\n\t\t\t\t\t\"the stored checkpoint must round-trip every cursor field and the watermark event identity\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"save overwrites the previous watermark (last write wins; monotonicity is the projector's job)\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(async (ctx) => {\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\tcheckpoint(pos(5, 0), \"evt-first\"),\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\tcheckpoint(pos(5, 1), \"evt-second\"),\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t\tconst loaded = await env.run((ctx) =>\n\t\t\t\t\tenv.store.load(ctx, \"order-list\", order(\"o-1\")),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tloaded?.position.aggregateVersion === 5 &&\n\t\t\t\t\t\tloaded.position.commitSequence === 1 &&\n\t\t\t\t\t\tloaded.lastAppliedEventId === \"evt-second\",\n\t\t\t\t\t\"a later save must replace the stored watermark verbatim\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"a loaded position is a detached copy; mutating it must not move the watermark\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run((ctx) =>\n\t\t\t\t\tenv.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\tcheckpoint(pos(2, 0)),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tconst loaded = await env.run((ctx) =>\n\t\t\t\t\tenv.store.load(ctx, \"order-list\", order(\"o-1\")),\n\t\t\t\t);\n\t\t\t\tassert(loaded !== undefined, \"expected a stored watermark\");\n\t\t\t\t(loaded.position as { aggregateVersion: number }).aggregateVersion = 99;\n\t\t\t\tconst reloaded = await env.run((ctx) =>\n\t\t\t\t\tenv.store.load(ctx, \"order-list\", order(\"o-1\")),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\treloaded?.position.aggregateVersion === 2,\n\t\t\t\t\t\"the stored watermark must be immune to mutation of a previously loaded copy\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"watermarks are isolated per projection and per aggregate\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(async (ctx) => {\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\tcheckpoint(pos(3, 0)),\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-detail\",\n\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\tcheckpoint(pos(1, 0)),\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\torder(\"o-2\"),\n\t\t\t\t\t\tcheckpoint(pos(7, 0)),\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t\tconst [listO1, detailO1, listO2] = await env.run((ctx) =>\n\t\t\t\t\tPromise.all([\n\t\t\t\t\t\tenv.store.load(ctx, \"order-list\", order(\"o-1\")),\n\t\t\t\t\t\tenv.store.load(ctx, \"order-detail\", order(\"o-1\")),\n\t\t\t\t\t\tenv.store.load(ctx, \"order-list\", order(\"o-2\")),\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tlistO1?.position.aggregateVersion === 3 &&\n\t\t\t\t\t\tdetailO1?.position.aggregateVersion === 1 &&\n\t\t\t\t\t\tlistO2?.position.aggregateVersion === 7,\n\t\t\t\t\t\"the watermark key is the (projection, aggregateType, aggregateId) triple; no part may bleed into another\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"watermarks are isolated per aggregate TYPE: colliding raw ids do not share a checkpoint\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(async (ctx) => {\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\t{ aggregateType: \"Order\", aggregateId: \"1\" },\n\t\t\t\t\t\tcheckpoint(pos(10, 0)),\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\t{ aggregateType: \"Payment\", aggregateId: \"1\" },\n\t\t\t\t\t\tcheckpoint(pos(1, 0)),\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t\tconst [orderMark, paymentMark] = await env.run((ctx) =>\n\t\t\t\t\tPromise.all([\n\t\t\t\t\t\tenv.store.load(ctx, \"order-list\", {\n\t\t\t\t\t\t\taggregateType: \"Order\",\n\t\t\t\t\t\t\taggregateId: \"1\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tenv.store.load(ctx, \"order-list\", {\n\t\t\t\t\t\t\taggregateType: \"Payment\",\n\t\t\t\t\t\t\taggregateId: \"1\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\torderMark?.position.aggregateVersion === 10 &&\n\t\t\t\t\t\tpaymentMark?.position.aggregateVersion === 1,\n\t\t\t\t\t\"identities are type-scoped: Order 1 at version 10 must not make Payment 1 look processed\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"address encoding is collision-free even with separator-like characters in either half\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\t// The two classic composite-key collisions: a separator\n\t\t\t\t// smuggled into the type vs. into the id. Whatever encoding\n\t\t\t\t// the adapter uses (composite column, JSON tuple, nested\n\t\t\t\t// key), these addresses must keep distinct watermarks.\n\t\t\t\tconst inType: AggregateAddress = {\n\t\t\t\t\taggregateType: \"A\\u0000B\",\n\t\t\t\t\taggregateId: \"C\",\n\t\t\t\t};\n\t\t\t\tconst inId: AggregateAddress = {\n\t\t\t\t\taggregateType: \"A\",\n\t\t\t\t\taggregateId: \"B\\u0000C\",\n\t\t\t\t};\n\t\t\t\tawait env.run(async (ctx) => {\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\tinType,\n\t\t\t\t\t\tcheckpoint(pos(10, 0)),\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.save(ctx, \"order-list\", inId, checkpoint(pos(1, 0)));\n\t\t\t\t});\n\t\t\t\tconst [first, second] = await env.run((ctx) =>\n\t\t\t\t\tPromise.all([\n\t\t\t\t\t\tenv.store.load(ctx, \"order-list\", inType),\n\t\t\t\t\t\tenv.store.load(ctx, \"order-list\", inId),\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tfirst?.position.aggregateVersion === 10 &&\n\t\t\t\t\t\tsecond?.position.aggregateVersion === 1,\n\t\t\t\t\t\"two addresses that differ only in where a hostile separator sits must not share a watermark\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"hasReached compares the full pair: unseen is false, behind is false, at and past are true\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run((ctx) =>\n\t\t\t\t\tenv.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\tcheckpoint(pos(5, 0)),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait env.store.hasReached(\"order-list\", order(\"o-2\"), pos(1, 0)),\n\t\t\t\t\tfalse,\n\t\t\t\t\t\"an unseen aggregate has reached nothing\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait env.store.hasReached(\"order-list\", order(\"o-1\"), pos(5, 1)),\n\t\t\t\t\tfalse,\n\t\t\t\t\t\"a later commitSequence of the SAME version is not yet reached; comparing on the version alone would lie mid-commit\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait env.store.hasReached(\"order-list\", order(\"o-1\"), pos(6, 0)),\n\t\t\t\t\tfalse,\n\t\t\t\t\t\"a later version is not yet reached\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait env.store.hasReached(\"order-list\", order(\"o-1\"), pos(5, 0)),\n\t\t\t\t\ttrue,\n\t\t\t\t\t\"the stored position itself is reached\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait env.store.hasReached(\"order-list\", order(\"o-1\"), pos(4, 7)),\n\t\t\t\t\ttrue,\n\t\t\t\t\t\"any earlier version is reached regardless of its commitSequence\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"reset clears only the named projection's checkpoints\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(async (ctx) => {\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\tcheckpoint(pos(3, 0)),\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-detail\",\n\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\tcheckpoint(pos(2, 0)),\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t\tawait env.run((ctx) => env.store.reset(ctx, \"order-list\"));\n\t\t\t\tconst [cleared, untouched] = await env.run((ctx) =>\n\t\t\t\t\tPromise.all([\n\t\t\t\t\t\tenv.store.load(ctx, \"order-list\", order(\"o-1\")),\n\t\t\t\t\t\tenv.store.load(ctx, \"order-detail\", order(\"o-1\")),\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tcleared,\n\t\t\t\t\tundefined,\n\t\t\t\t\t\"the reset projection must start from zero (rebuild entry point)\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tuntouched?.position.aggregateVersion === 2,\n\t\t\t\t\t\"a sibling projection's checkpoints must survive the reset\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait env.store.hasReached(\"order-list\", order(\"o-1\"), pos(1, 0)),\n\t\t\t\t\tfalse,\n\t\t\t\t\t\"hasReached must report false after a reset\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"providesRolledBackRuns\",\n\t\t\t\tsatisfiedBy: harness.providesRolledBackRuns === true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"a rolled-back save leaves no checkpoint behind (atomic update+checkpoint)\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tif (!env.runRolledBack) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Contract violated: harness declared providesRolledBackRuns but the environment lacks runRolledBack\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait env\n\t\t\t\t\t\t.runRolledBack((ctx) =>\n\t\t\t\t\t\t\tenv.store.save(\n\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\t\t\tcheckpoint(pos(1, 0)),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\t\t// The rollback mechanism may surface as a rejection; the\n\t\t\t\t\t\t\t// contract under test is the store state afterwards.\n\t\t\t\t\t\t});\n\t\t\t\t\tconst loaded = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.load(ctx, \"order-list\", order(\"o-1\")),\n\t\t\t\t\t);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tloaded,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\"a checkpoint from a rolled-back transaction must not exist; otherwise events are lost while marked processed\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t];\n}\n","import type { Aggregate } from \"../domain/aggregate/aggregate\";\nimport type {\n\tAnyDomainEvent,\n\tPendingDomainEvent,\n} from \"../domain/event/domain-event\";\nimport type { Id } from \"../domain/identity/id\";\nimport { deepEqual } from \"../internal/structural/deep-equal\";\nimport type { CommittedDomainEvent } from \"../messaging/committed-event\";\nimport {\n\tassert,\n\tassertChainContainsKitError,\n\tassertEqual,\n\tawaitOverlappingCall,\n\tbindContractEnvironment,\n\ttype ContractTest,\n\tcaptureRejection,\n\tdescribeError,\n\tgatedContractTest,\n\tloadAggregateOrFail,\n\tOVERLAPPING_CALLS_BOUND_MS,\n\toverlappingCallsPreflight,\n\tparkRunCall,\n\trecordedPendingEventIds,\n\tsortedCommittedEventIds,\n} from \"./contract-assertions\";\n\n/** Application-facing state-stored repository exercised by the suite. */\nexport interface ContractRepository<\n\tTAggregate extends Aggregate<Id<string>, AnyDomainEvent>,\n> {\n\tfindById(id: TAggregate[\"id\"]): Promise<TAggregate | undefined>;\n\tadd(aggregate: TAggregate): void;\n\tupdate(aggregate: TAggregate): void;\n\t/** Physical removal is an optional persistence capability. */\n\tremove?(aggregate: TAggregate): void;\n}\n\n/** One isolated real-adapter environment. `run` must permit overlapping calls. */\nexport interface RepositoryContractEnvironment<\n\tTAggregate extends Aggregate<Id<string>, TEvent>,\n\tTEvent extends AnyDomainEvent = AnyDomainEvent,\n> {\n\trun<R>(\n\t\twork: (context: {\n\t\t\trepository: ContractRepository<TAggregate>;\n\t\t}) => Promise<R>,\n\t): Promise<R>;\n\tcommittedOutboxEvents(): Promise<ReadonlyArray<CommittedDomainEvent<TEvent>>>;\n\t/** Makes the next transactional outbox write fail for atomicity proof. */\n\tfailNextOutboxWrite(error: Error): void;\n\tteardown?(): Promise<void>;\n}\n\n/** Fixtures and observable projections supplied by an adapter package. */\nexport interface RepositoryContractHarness<\n\tTAggregate extends Aggregate<Id<string>, TEvent>,\n\tTEvent extends AnyDomainEvent = AnyDomainEvent,\n> {\n\tcreateEnvironment(): Promise<\n\t\tRepositoryContractEnvironment<TAggregate, TEvent>\n\t>;\n\t/** A fresh aggregate with a unique id. */\n\tcreateAggregate(): TAggregate;\n\t/** One version-bumping decision that records at least one event. */\n\tmutate(aggregate: TAggregate): void;\n\t/** Required for duplicate-add and same-UoW deletion-finality proofs. */\n\tcreateAggregateWithId?(id: TAggregate[\"id\"]): TAggregate;\n\t/**\n\t * A version-bumping decision with no event whose resulting state is\n\t * deep-equal to the previous state (`setState({ ...state })`). The\n\t * deep-equal requirement is load-bearing: it forces a diff-based\n\t * `PersistenceModel` to derive an EMPTY change set, so the suite proves\n\t * that an adapter persists the bumped version even when\n\t * `changes.empty` is true. Skipping that write desyncs the persisted\n\t * version and produces false concurrency conflicts later.\n\t */\n\tmutateVersionOnly?(aggregate: TAggregate): void;\n\t/** A decision that changes a nested collection. */\n\tmutateChildCollection?(aggregate: TAggregate): void;\n\t/** Round-trip-stable adapter persistence projection. */\n\tsnapshotState?(aggregate: TAggregate): unknown;\n\t/** Opt out only for an intentionally upserting add implementation. */\n\tinsertsAreDuplicateChecked?: boolean;\n\t/** Enables physical-remove behavior and stale-remove OCC tests. */\n\tremovesAreSupported?: boolean;\n\t/** The remove flush predicates on the version captured at load. */\n\tremovesAreVersionChecked?: boolean;\n\t/**\n\t * Bound for the overlapping `run` calls, in milliseconds: the second call\n\t * of the environment preflight, and the committing call of each\n\t * stale-writer proof. Raise it only for a second connection that needs\n\t * more time to open, or for a slow commit. Keep twice the bound, plus\n\t * environment creation and teardown, below the test timeout of the runner.\n\t */\n\toverlappingCallsBoundMs?: number;\n}\n\nexport type RepositoryContractTest = ContractTest;\n\n/**\n * Contract suite for the v3 explicit-intent, commit-time-flush protocol.\n *\n * The harness must use the public `UnitOfWork` with a real adapter. In\n * particular, `run` must create a fresh Unit of Work and transaction for each\n * call and allow two calls to overlap; the mandatory stale-writer proof keeps\n * writer B open while writer A commits. SQL/ORM adapters therefore need a\n * real database and connection pool. An in-memory harness proves only itself.\n *\n * Writes are synchronous registrations. Durable adapter I/O happens after the\n * callback returns, while the transaction is still open. A test that passes\n * because `add` or `update` writes early is not a conforming implementation.\n */\nexport function createRepositoryContractTests<\n\tTAggregate extends Aggregate<Id<string>, TEvent>,\n\tTEvent extends AnyDomainEvent = AnyDomainEvent,\n>(\n\tharness: RepositoryContractHarness<TAggregate, TEvent>,\n): RepositoryContractTest[] {\n\ttype Environment = RepositoryContractEnvironment<TAggregate, TEvent>;\n\tconst inEnvironment = bindContractEnvironment(() =>\n\t\tharness.createEnvironment(),\n\t);\n\tconst snapshotState = harness.snapshotState;\n\tconst createAggregateWithId = harness.createAggregateWithId;\n\tconst mutateVersionOnly = harness.mutateVersionOnly;\n\tconst mutateChildCollection = harness.mutateChildCollection;\n\tconst insertsAreDuplicateChecked =\n\t\tharness.insertsAreDuplicateChecked !== false;\n\tconst removesAreSupported = harness.removesAreSupported === true;\n\tconst removesAreVersionChecked =\n\t\tremovesAreSupported && harness.removesAreVersionChecked === true;\n\tconst overlappingCallsBoundMs =\n\t\tharness.overlappingCallsBoundMs ?? OVERLAPPING_CALLS_BOUND_MS;\n\n\tconst load = (\n\t\trepository: ContractRepository<TAggregate>,\n\t\tid: TAggregate[\"id\"],\n\t): Promise<TAggregate> =>\n\t\tloadAggregateOrFail(\n\t\t\trepository,\n\t\t\tid,\n\t\t\t\"the adapter did not commit or reconstitute the aggregate\",\n\t\t);\n\n\tasync function seed(environment: Environment): Promise<TAggregate> {\n\t\tconst aggregate = harness.createAggregate();\n\t\tharness.mutate(aggregate);\n\t\tawait environment.run(async ({ repository }) => {\n\t\t\trepository.add(aggregate);\n\t\t});\n\t\treturn aggregate;\n\t}\n\n\tconst reload = (environment: Environment, id: TAggregate[\"id\"]) =>\n\t\tenvironment.run(({ repository }) => load(repository, id));\n\n\tconst eventIds = (\n\t\tevents: ReadonlyArray<CommittedDomainEvent<TEvent>>,\n\t): string[] => sortedCommittedEventIds(events);\n\tconst pendingEventIds = (\n\t\tevents: ReadonlyArray<PendingDomainEvent<TEvent>>,\n\t): string[] =>\n\t\trecordedPendingEventIds(\n\t\t\tevents,\n\t\t\t\"the harness must record pending events before persistence\",\n\t\t);\n\n\tconst tests: RepositoryContractTest[] = [\n\t\toverlappingCallsPreflight<Environment, TAggregate[\"id\"]>(\n\t\t\tinEnvironment,\n\t\t\t() => harness.createAggregate().id,\n\t\t\toverlappingCallsBoundMs,\n\t\t),\n\t\t{\n\t\t\tname: \"add flushes a new aggregate and its exact event batch atomically\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tconst registeredEvents = [...aggregate.pendingEvents];\n\n\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t});\n\n\t\t\t\tconst reloaded = await reload(environment, aggregate.id);\n\t\t\t\tassertEqual(\n\t\t\t\t\treloaded.version,\n\t\t\t\t\taggregate.version,\n\t\t\t\t\t\"add must store the version registered by the Unit of Work\",\n\t\t\t\t);\n\t\t\t\tif (snapshotState) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\t\tsnapshotState.call(harness, reloaded),\n\t\t\t\t\t\t\tsnapshotState.call(harness, aggregate),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t\"add must store the adapter's complete persistence projection\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst outbox = await environment.committedOutboxEvents();\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(eventIds(outbox), pendingEventIds(registeredEvents).sort()),\n\t\t\t\t\t\"the outbox must contain exactly the batch registered by add\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\taggregate.pendingEvents.length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"only a committed add acknowledges its registered event batch\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"committed outbox envelopes carry exact position facts\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\t// Position facts must be provable through the repository suite\n\t\t\t\t// alone: OutboxWriter-only adapters (CDC, broker-native) cannot\n\t\t\t\t// run the outbox suite, and idempotent consumers key their\n\t\t\t\t// watermarks on (aggregateVersion, commitSequence).\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tconst batchSize = aggregate.pendingEvents.length;\n\t\t\t\tconst committedVersion = aggregate.version;\n\n\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t});\n\n\t\t\t\tconst positions = (await environment.committedOutboxEvents())\n\t\t\t\t\t.map(({ position }) => position)\n\t\t\t\t\t.sort((a, b) => a.commitSequence - b.commitSequence);\n\t\t\t\tassertEqual(\n\t\t\t\t\tpositions.length,\n\t\t\t\t\tbatchSize,\n\t\t\t\t\t\"every registered event must commit exactly one envelope\",\n\t\t\t\t);\n\t\t\t\tpositions.forEach((position, index) => {\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tposition.aggregateVersion,\n\t\t\t\t\t\tcommittedVersion,\n\t\t\t\t\t\t\"every envelope must carry the version the commit persisted\",\n\t\t\t\t\t);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tposition.commitSequence,\n\t\t\t\t\t\tindex,\n\t\t\t\t\t\t\"commitSequence must be gapless and zero-based over the batch\",\n\t\t\t\t\t);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tposition.commitSize,\n\t\t\t\t\t\tbatchSize,\n\t\t\t\t\t\t\"commitSize must equal the exact batch length\",\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"MANDATORY stale update: writer B conflicts after writer A commits and persists nothing\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\tconst writerB = await parkRunCall((hold) =>\n\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\tconst stale = await load(repository, seeded.id);\n\t\t\t\t\t\tawait hold();\n\t\t\t\t\t\tharness.mutate(stale);\n\t\t\t\t\t\trepository.update(stale);\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\tconst committedA = await awaitOverlappingCall(\n\t\t\t\t\t() =>\n\t\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\t\tconst current = await load(repository, seeded.id);\n\t\t\t\t\t\t\tharness.mutate(current);\n\t\t\t\t\t\t\trepository.update(current);\n\t\t\t\t\t\t\treturn current;\n\t\t\t\t\t\t}),\n\t\t\t\t\twriterB,\n\t\t\t\t\toverlappingCallsBoundMs,\n\t\t\t\t);\n\t\t\t\tconst outboxAfterA = await environment.committedOutboxEvents();\n\t\t\t\twriterB.release();\n\t\t\t\tconst rejection = await captureRejection(writerB.call);\n\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\trejection,\n\t\t\t\t\t[\"CONCURRENCY_CONFLICT\"],\n\t\t\t\t\t`stale update must reject with ConcurrencyConflictError; got ${describeError(rejection)}`,\n\t\t\t\t);\n\n\t\t\t\tconst final = await reload(environment, seeded.id);\n\t\t\t\tassertEqual(\n\t\t\t\t\tfinal.version,\n\t\t\t\t\tcommittedA.version,\n\t\t\t\t\t\"the stale writer must not replace writer A's version\",\n\t\t\t\t);\n\t\t\t\tif (snapshotState) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\t\tsnapshotState.call(harness, final),\n\t\t\t\t\t\t\tsnapshotState.call(harness, committedA),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t\"the stale writer must not replace writer A's state\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\teventIds(await environment.committedOutboxEvents()),\n\t\t\t\t\t\teventIds(outboxAfterA),\n\t\t\t\t\t),\n\t\t\t\t\t\"a rejected stale flush must add no outbox records\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"rollback acknowledges nothing and commits neither state nor outbox\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tconst pending = [...aggregate.pendingEvents];\n\t\t\t\tawait captureRejection(\n\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t\t\tthrow new Error(\"rollback probe\");\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst absent = await environment.run(({ repository }) =>\n\t\t\t\t\trepository.findById(aggregate.id),\n\t\t\t\t);\n\t\t\t\tassert(absent === undefined, \"a rolled-back add must leave no row\");\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await environment.committedOutboxEvents()).length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"a rolled-back add must leave no outbox record\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(aggregate.pendingEvents, pending),\n\t\t\t\t\t\"rollback must acknowledge none of the registered event batch\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"outbox failure rolls the already-flushed aggregate write back\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tconst pending = [...aggregate.pendingEvents];\n\t\t\t\tenvironment.failNextOutboxWrite(new Error(\"outbox failure probe\"));\n\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tassert(rejection !== undefined, \"the outbox failure must reject\");\n\t\t\t\tconst absent = await environment.run(({ repository }) =>\n\t\t\t\t\trepository.findById(aggregate.id),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tabsent === undefined,\n\t\t\t\t\t\"state flush must roll back when the outbox write fails\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await environment.committedOutboxEvents()).length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"failed outbox write must commit no envelope\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(aggregate.pendingEvents, pending),\n\t\t\t\t\t\"failed commit must acknowledge none of the event batch\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"identity map returns one instance for repeated loads in one Unit of Work\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\tconst first = await repository.findById(seeded.id);\n\t\t\t\t\tconst second = await repository.findById(seeded.id);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tfirst !== undefined && first === second,\n\t\t\t\t\t\t\"repeated reads must return the same tracked aggregate instance\",\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"an unchanged explicit update is safe and emits no event\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\tconst before = await environment.committedOutboxEvents();\n\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\tconst aggregate = await load(repository, seeded.id);\n\t\t\t\t\trepository.update(aggregate);\n\t\t\t\t});\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\teventIds(await environment.committedOutboxEvents()),\n\t\t\t\t\t\teventIds(before),\n\t\t\t\t\t),\n\t\t\t\t\t\"an unchanged update must not manufacture an outbox event\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t];\n\n\ttests.push(\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: createAggregateWithId\n\t\t\t\t\t? \"insertsAreDuplicateChecked\"\n\t\t\t\t\t: \"createAggregateWithId\",\n\t\t\t\tsatisfiedBy:\n\t\t\t\t\tBoolean(createAggregateWithId) && insertsAreDuplicateChecked,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"duplicate add rejects and preserves the existing aggregate\",\n\t\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\t\tassert(createAggregateWithId !== undefined, \"capability gate\");\n\t\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\t\t// Mutated twice so its version differs from the seeded\n\t\t\t\t\t// row's: a clobbering insert is then visible in the\n\t\t\t\t\t// version check even without a state snapshot.\n\t\t\t\t\tconst duplicate = createAggregateWithId.call(harness, seeded.id);\n\t\t\t\t\tharness.mutate(duplicate);\n\t\t\t\t\tharness.mutate(duplicate);\n\t\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\t\trepository.add(duplicate);\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\t// Exactly DUPLICATE_AGGREGATE, not a retryable conflict:\n\t\t\t\t\t// the docs instruct mapping uniqueness violations\n\t\t\t\t\t// (Postgres 23505, MySQL 1062, SQLite\n\t\t\t\t\t// SQLITE_CONSTRAINT_UNIQUE) to DuplicateAggregateError,\n\t\t\t\t\t// and a duplicate add is deterministic and must not be\n\t\t\t\t\t// retried unchanged.\n\t\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\t\trejection,\n\t\t\t\t\t\t[\"DUPLICATE_AGGREGATE\"],\n\t\t\t\t\t\t`duplicate add must reject with (or wrap) ` +\n\t\t\t\t\t\t\t`DuplicateAggregateError; map your driver's ` +\n\t\t\t\t\t\t\t`unique-violation signal instead of a retryable ` +\n\t\t\t\t\t\t\t`conflict; got ${describeError(rejection)}`,\n\t\t\t\t\t);\n\t\t\t\t\t// The existing row is untouched by the rejected insert:\n\t\t\t\t\t// version and (capability permitting) state.\n\t\t\t\t\tconst final = await reload(environment, seeded.id);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tfinal.version,\n\t\t\t\t\t\tseeded.version,\n\t\t\t\t\t\t\"the existing row must be untouched by the rejected \" +\n\t\t\t\t\t\t\t\"duplicate add; a duplicate check firing after the \" +\n\t\t\t\t\t\t\t\"write clobbers it\",\n\t\t\t\t\t);\n\t\t\t\t\tif (snapshotState) {\n\t\t\t\t\t\tassert(\n\t\t\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\t\t\tsnapshotState.call(harness, final),\n\t\t\t\t\t\t\t\tsnapshotState.call(harness, seeded),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\"the existing row's state must be untouched by the \" +\n\t\t\t\t\t\t\t\t\"rejected duplicate add\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t);\n\n\ttests.push(\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"mutateVersionOnly\",\n\t\t\t\tsatisfiedBy: Boolean(mutateVersionOnly),\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"version-only change still persists (skip-save must not desync the OCC baseline)\",\n\t\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\t\tassert(mutateVersionOnly !== undefined, \"capability gate\");\n\t\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\t\tconst outboxBefore = await environment.committedOutboxEvents();\n\t\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\t\tconst aggregate = await load(repository, seeded.id);\n\t\t\t\t\t\tmutateVersionOnly.call(harness, aggregate);\n\t\t\t\t\t\trepository.update(aggregate);\n\t\t\t\t\t});\n\t\t\t\t\tconst reloaded = await reload(environment, seeded.id);\n\t\t\t\t\t// The harness contract keeps the projection deep-equal, so a\n\t\t\t\t\t// diff-based model derives an EMPTY change set here: an\n\t\t\t\t\t// adapter that skips empty writes fails this reload.\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\treloaded.version,\n\t\t\t\t\t\tseeded.version + 1,\n\t\t\t\t\t\t\"a version-only change (empty change set, bumped version) \" +\n\t\t\t\t\t\t\t\"must still be persisted; skipping it desyncs the \" +\n\t\t\t\t\t\t\t\"persisted version and produces false concurrency \" +\n\t\t\t\t\t\t\t\"conflicts later\",\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\t\teventIds(await environment.committedOutboxEvents()),\n\t\t\t\t\t\t\teventIds(outboxBefore),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t\"state-only update must not create an outbox event\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t);\n\n\ttests.push(\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"mutateChildCollection\",\n\t\t\t\tsatisfiedBy: Boolean(mutateChildCollection),\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"nested collection changes survive the adapter change-set projection\",\n\t\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\t\tassert(mutateChildCollection !== undefined, \"capability gate\");\n\t\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\t\tconst aggregate = await load(repository, seeded.id);\n\t\t\t\t\t\tmutateChildCollection.call(harness, aggregate);\n\t\t\t\t\t\trepository.update(aggregate);\n\t\t\t\t\t});\n\t\t\t\t\tconst reloaded = await reload(environment, seeded.id);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\treloaded.version,\n\t\t\t\t\t\tseeded.version + 1,\n\t\t\t\t\t\t\"nested collection update must advance the persisted root version\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t);\n\n\ttests.push(\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"removesAreSupported\",\n\t\t\t\tsatisfiedBy: removesAreSupported,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"remove tombstones the identity and physically removes at commit\",\n\t\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\t\tassert(repository.remove !== undefined, \"remove capability gate\");\n\t\t\t\t\t\tconst aggregate = await load(repository, seeded.id);\n\t\t\t\t\t\trepository.remove(aggregate);\n\t\t\t\t\t\tassert(\n\t\t\t\t\t\t\t(await repository.findById(seeded.id)) === undefined,\n\t\t\t\t\t\t\t\"a removed aggregate is immediately absent from the Unit of Work\",\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t\t\tassert(\n\t\t\t\t\t\t(await environment.run(({ repository }) =>\n\t\t\t\t\t\t\trepository.findById(seeded.id),\n\t\t\t\t\t\t)) === undefined,\n\t\t\t\t\t\t\"remove must physically remove the aggregate after commit\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t);\n\n\ttests.push(\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"removesAreVersionChecked\",\n\t\t\t\tsatisfiedBy: removesAreVersionChecked,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"stale remove conflicts and cannot delete a concurrent update\",\n\t\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\t\tconst staleRemove = await parkRunCall((hold) =>\n\t\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\t\tassert(repository.remove !== undefined, \"remove capability gate\");\n\t\t\t\t\t\t\tconst stale = await load(repository, seeded.id);\n\t\t\t\t\t\t\tawait hold();\n\t\t\t\t\t\t\trepository.remove(stale);\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tawait awaitOverlappingCall(\n\t\t\t\t\t\t() =>\n\t\t\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\t\t\tconst current = await load(repository, seeded.id);\n\t\t\t\t\t\t\t\tharness.mutate(current);\n\t\t\t\t\t\t\t\trepository.update(current);\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\tstaleRemove,\n\t\t\t\t\t\toverlappingCallsBoundMs,\n\t\t\t\t\t);\n\t\t\t\t\tstaleRemove.release();\n\t\t\t\t\tconst rejection = await captureRejection(staleRemove.call);\n\t\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\t\trejection,\n\t\t\t\t\t\t[\"CONCURRENCY_CONFLICT\"],\n\t\t\t\t\t\t`stale remove must reject with ConcurrencyConflictError; got ${describeError(rejection)}`,\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\t(await reload(environment, seeded.id)) !== undefined,\n\t\t\t\t\t\t\"stale remove must not delete the concurrent winner\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t);\n\n\treturn tests;\n}\n","import type { AggregateSnapshot, Version } from \"../domain/aggregate/aggregate\";\nimport type { AggregateAddress } from \"../domain/aggregate/aggregate-address\";\nimport type { Id } from \"../domain/identity/id\";\nimport { deepEqual } from \"../internal/structural/deep-equal\";\nimport type { SnapshotStore } from \"../persistence/snapshot-store/snapshot-store\";\nimport {\n\tassert,\n\tassertEqual,\n\tbindContractEnvironment,\n\ttype ContractTest,\n} from \"./contract-assertions\";\n\n/** One contract test; bind with `(test.skipped ? it.skip : it)(test.name, test.run)`. */\nexport type SnapshotStoreContractTest = ContractTest;\n\n/** The plain-data state shape the suite round-trips. */\ninterface SuiteState {\n\ttotal: number;\n\titems: Array<{ sku: string; qty: number }>;\n\tnote?: string;\n}\n\n/**\n * One isolated test environment: a fresh snapshot store. The suite\n * creates one per test and tears it down afterwards. No transaction\n * wrapper: the port is transaction-free by design (snapshots are\n * derived data written after the commit; see `SnapshotStore`).\n */\nexport interface SnapshotStoreContractEnvironment {\n\t/** The adapter under test. */\n\tstore: SnapshotStore<SuiteState>;\n\n\t/** Release connections, drop schemas, etc. Called in a finally. */\n\tteardown?(): Promise<void>;\n}\n\n/**\n * What an adapter supplies to run the snapshot-store contract suite.\n * For SQL adapters, run against a real database (testcontainers or\n * equivalent). Note the fidelity demands the suite enforces:\n * `snapshotAt` must survive with millisecond precision (store it as\n * ISO-8601 text or epoch milliseconds; MySQL `DATETIME` without\n * fractional seconds truncates), and an ABSENT `schemaVersion` must\n * come back absent, not as `0` or `null`-coerced.\n */\nexport interface SnapshotStoreContractHarness {\n\tcreateEnvironment(): Promise<SnapshotStoreContractEnvironment>;\n}\n\nconst AT = new Date(\"2026-01-05T10:20:30.456Z\");\n\nfunction snapshot(\n\tversion: number,\n\tstate: SuiteState,\n\tschemaVersion?: number,\n): AggregateSnapshot<SuiteState> {\n\treturn {\n\t\tstate,\n\t\tversion: version as Version,\n\t\t// A fresh Date per snapshot: an adapter that normalizes the input\n\t\t// Date IN PLACE must not be able to mutate the suite's expected\n\t\t// value into agreeing with it.\n\t\tsnapshotAt: new Date(AT),\n\t\t...(schemaVersion === undefined ? {} : { schemaVersion }),\n\t};\n}\n\nconst id = (value: string): Id<string> => value as Id<string>;\nconst address = (\n\taggregateType: string,\n\taggregateId: string,\n): AggregateAddress<Id<string>> => ({\n\taggregateType,\n\taggregateId: id(aggregateId),\n});\n\n/**\n * The snapshot-store contract test suite: the proof that an adapter\n * delivers the round-trip and isolation semantics the\n * snapshot-plus-recent-events load path relies on. Store semantics are\n * an **adapter contract, not a kit guarantee**; this suite is how an\n * adapter demonstrates them.\n *\n * Framework-agnostic: bind with\n * `(test.skipped ? it.skip : it)(test.name, test.run)`.\n */\nexport function createSnapshotStoreContractTests(\n\tharness: SnapshotStoreContractHarness,\n): SnapshotStoreContractTest[] {\n\tconst inEnv = bindContractEnvironment(() => harness.createEnvironment());\n\n\treturn [\n\t\t{\n\t\t\tname: \"an aggregate without a snapshot loads undefined\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait env.store.load(address(\"Order\", \"o-1\")),\n\t\t\t\t\tundefined,\n\t\t\t\t\t\"a fresh store must report no snapshot; the repository falls back to full replay\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"save/load round-trips state, version, snapshotAt (millisecond fidelity), and schemaVersion\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst stored = snapshot(\n\t\t\t\t\t42,\n\t\t\t\t\t{ total: 7, items: [{ sku: \"a\", qty: 2 }], note: \"hi\" },\n\t\t\t\t\t3,\n\t\t\t\t);\n\t\t\t\tawait env.store.save(address(\"Order\", \"o-1\"), stored);\n\t\t\t\tconst loaded = await env.store.load(address(\"Order\", \"o-1\"));\n\t\t\t\tassert(loaded !== undefined, \"the saved snapshot must load\");\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(loaded.state, stored.state),\n\t\t\t\t\t\"the state must round-trip deep-equal as plain data\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tloaded.version,\n\t\t\t\t\t42,\n\t\t\t\t\t\"the aggregate version must round-trip\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tloaded.snapshotAt instanceof Date,\n\t\t\t\t\t\"snapshotAt must round-trip as a Date; rehydrate your storage format (ISO-8601 text, epoch ms) on load\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tloaded.snapshotAt.getTime(),\n\t\t\t\t\tAT.getTime(),\n\t\t\t\t\t\"snapshotAt must survive with millisecond precision (store ISO-8601 text or epoch ms)\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tloaded.schemaVersion,\n\t\t\t\t\t3,\n\t\t\t\t\t\"schemaVersion must round-trip verbatim; the restore path compares it against the aggregate's declared schema\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"an absent schemaVersion round-trips as absent\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.store.save(\n\t\t\t\t\taddress(\"Order\", \"o-1\"),\n\t\t\t\t\tsnapshot(1, { total: 0, items: [] }),\n\t\t\t\t);\n\t\t\t\tconst loaded = await env.store.load(address(\"Order\", \"o-1\"));\n\t\t\t\tassertEqual(\n\t\t\t\t\tloaded?.schemaVersion,\n\t\t\t\t\tundefined,\n\t\t\t\t\t\"a snapshot stored without schemaVersion must not come back with a fabricated one; restore treats absence as schema 1\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"save replaces the previous snapshot: latest wins, no history\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.store.save(\n\t\t\t\t\taddress(\"Order\", \"o-1\"),\n\t\t\t\t\tsnapshot(10, { total: 1, items: [] }),\n\t\t\t\t);\n\t\t\t\tawait env.store.save(\n\t\t\t\t\taddress(\"Order\", \"o-1\"),\n\t\t\t\t\tsnapshot(20, { total: 2, items: [] }),\n\t\t\t\t);\n\t\t\t\tconst loaded = await env.store.load(address(\"Order\", \"o-1\"));\n\t\t\t\tassert(\n\t\t\t\t\tloaded?.version === 20 && loaded.state.total === 2,\n\t\t\t\t\t\"load must return the latest snapshot only\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"snapshots are isolated per aggregate type AND per aggregate id\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.store.save(\n\t\t\t\t\taddress(\"Order\", \"x-1\"),\n\t\t\t\t\tsnapshot(1, { total: 1, items: [] }),\n\t\t\t\t);\n\t\t\t\tawait env.store.save(\n\t\t\t\t\taddress(\"Invoice\", \"x-1\"),\n\t\t\t\t\tsnapshot(2, { total: 2, items: [] }),\n\t\t\t\t);\n\t\t\t\tawait env.store.save(\n\t\t\t\t\taddress(\"Order\", \"x-2\"),\n\t\t\t\t\tsnapshot(3, { total: 3, items: [] }),\n\t\t\t\t);\n\t\t\t\tconst [orderX1, invoiceX1, orderX2] = await Promise.all([\n\t\t\t\t\tenv.store.load(address(\"Order\", \"x-1\")),\n\t\t\t\t\tenv.store.load(address(\"Invoice\", \"x-1\")),\n\t\t\t\t\tenv.store.load(address(\"Order\", \"x-2\")),\n\t\t\t\t]);\n\t\t\t\tassert(\n\t\t\t\t\torderX1?.version === 1 &&\n\t\t\t\t\t\tinvoiceX1?.version === 2 &&\n\t\t\t\t\t\torderX2?.version === 3,\n\t\t\t\t\t\"the key is the (aggregateType, aggregateId) pair; neither half may bleed into the other\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"delete removes exactly the addressed snapshot and tolerates unknown keys\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.store.save(\n\t\t\t\t\taddress(\"Order\", \"o-1\"),\n\t\t\t\t\tsnapshot(1, { total: 1, items: [] }),\n\t\t\t\t);\n\t\t\t\tawait env.store.save(\n\t\t\t\t\taddress(\"Order\", \"o-2\"),\n\t\t\t\t\tsnapshot(2, { total: 2, items: [] }),\n\t\t\t\t);\n\t\t\t\tawait env.store.delete(address(\"Order\", \"o-1\"));\n\t\t\t\tawait env.store.delete(address(\"Order\", \"never-saved\"));\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait env.store.load(address(\"Order\", \"o-1\")),\n\t\t\t\t\tundefined,\n\t\t\t\t\t\"the deleted snapshot must be gone (schema-migration fallback and erasure both rely on it)\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await env.store.load(address(\"Order\", \"o-2\")))?.version,\n\t\t\t\t\t2,\n\t\t\t\t\t\"a sibling snapshot must survive the delete\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"loads are detached copies and saves capture the input: later mutations touch nothing\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst input = snapshot(5, { total: 5, items: [{ sku: \"a\", qty: 1 }] });\n\t\t\t\tawait env.store.save(address(\"Order\", \"o-1\"), input);\n\t\t\t\t// Mutating the caller's input AFTER save must not reach the store.\n\t\t\t\tinput.state.items.push({ sku: \"hacked\", qty: 99 });\n\n\t\t\t\tconst loaded = await env.store.load(address(\"Order\", \"o-1\"));\n\t\t\t\tassert(loaded !== undefined, \"expected the saved snapshot\");\n\t\t\t\tassertEqual(\n\t\t\t\t\tloaded.state.items.length,\n\t\t\t\t\t1,\n\t\t\t\t\t\"save must capture the snapshot by value, not hold the caller's reference\",\n\t\t\t\t);\n\t\t\t\t// Mutating the loaded copy must not corrupt the stored one.\n\t\t\t\tloaded.state.total = 999;\n\t\t\t\tconst reloaded = await env.store.load(address(\"Order\", \"o-1\"));\n\t\t\t\tassertEqual(\n\t\t\t\t\treloaded?.state.total,\n\t\t\t\t\t5,\n\t\t\t\t\t\"load must hand out a detached copy, never live internal state\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"testing.js","names":[],"sources":["../src/testing/contract-assertions.ts","../src/testing/command-outbox-contract.ts","../src/testing/deadline-store-contract.ts","../src/testing/es-repository-contract.ts","../src/testing/event-bus-contract.ts","../src/testing/event-store-contract.ts","../src/testing/idempotency-store-contract.ts","../src/testing/outbox-contract.ts","../src/testing/projection-checkpoint-contract.ts","../src/testing/repository-contract.ts","../src/testing/snapshot-store-contract.ts"],"sourcesContent":["/**\n * Assertion, error-matching, and suite-runner helpers shared by the\n * repository contract suites (state-stored and event-sourced). Internal\n * to the testing entry: not re-exported from `@shirudo/ddd-kit/testing`.\n */\nimport { isRecordedDomainEvent } from \"../domain/event/domain-event\";\nimport { runBoundedExecution } from \"../internal/async/execution\";\n\n/**\n * One entry of a contract test suite. Every suite (repository,\n * event-sourced repository, outbox, idempotency store) returns a list\n * of these; bind them with\n * `(test.skipped ? it.skip : it)(test.name, test.run)`.\n */\nexport interface ContractTest {\n\tname: string;\n\trun: () => Promise<void>;\n\t/** Present when the harness lacks the capability this test needs. */\n\tskipped?: { capability: string };\n}\n\n/**\n * Runs one contract-test body against a fresh environment and tears it\n * down in a finally-like discipline with one subtle, load-bearing rule:\n * a teardown failure (dropping a schema on an aborted pool) must never\n * REPLACE the contract-violation diagnostic that is the suite's entire\n * value. It only surfaces when the body itself succeeded.\n */\nexport async function runInContractEnvironment<\n\tEnv extends { teardown?(): Promise<void> },\n>(\n\tcreateEnvironment: () => Promise<Env>,\n\tbody: (env: Env) => Promise<void>,\n): Promise<void> {\n\tconst env = await createEnvironment();\n\tlet bodyFailed = false;\n\tlet bodyError: unknown;\n\ttry {\n\t\tawait body(env);\n\t} catch (error) {\n\t\tbodyFailed = true;\n\t\tbodyError = error;\n\t}\n\ttry {\n\t\tawait env.teardown?.();\n\t} catch (teardownError) {\n\t\tif (!bodyFailed) {\n\t\t\tthrow teardownError;\n\t\t}\n\t}\n\tif (bodyFailed) {\n\t\tthrow bodyError;\n\t}\n}\n\n/**\n * Binds a harness's environment factory into the per-test wrapper the\n * suites build their entries from: `inEnv(body)` yields a test `run`\n * that creates a fresh environment, runs the body, and tears down via\n * {@link runInContractEnvironment}.\n */\nexport function bindContractEnvironment<\n\tEnv extends { teardown?(): Promise<void> },\n>(\n\tcreateEnvironment: () => Promise<Env>,\n): (body: (env: Env) => Promise<void>) => () => Promise<void> {\n\treturn (body) => () => runInContractEnvironment(createEnvironment, body);\n}\n\n/** Resolves to the rejection reason, or `undefined` when the promise resolved. */\nexport function captureRejection(promise: Promise<unknown>): Promise<unknown> {\n\treturn promise.then(\n\t\t() => undefined,\n\t\t(error: unknown) => error,\n\t);\n}\n\n/**\n * Default bound for the overlapping `run` calls of the contract suites, in\n * milliseconds. On an environment that gives each `run` call its own\n * connection, the second call completes in milliseconds. The failure path\n * takes up to twice the bound: the bound itself, then the wait for the\n * released calls to settle. Twice the bound plus environment creation and\n * teardown stays below the default test timeout of common runners\n * (5000 ms). So the named failure reaches the report before the runner's\n * own timeout replaces it.\n */\nexport const OVERLAPPING_CALLS_BOUND_MS = 1_000;\n\nconst overlappingCallsViolation = (boundMs: number): string =>\n\t`run must permit overlapping calls: a second run call did not complete within ${boundMs} ms while the first call stayed open. ` +\n\t\"Either run serializes its calls, the first call holds a lock that blocks the second one, or the second call needs more time than the bound. \" +\n\t\"Give each call its own transaction and connection, load without row locks, or raise overlappingCallsBoundMs on the harness\";\n\nfunction settle<T>(promise: Promise<T>): Promise<PromiseSettledResult<T>> {\n\treturn promise.then(\n\t\t(value) => ({ status: \"fulfilled\", value }),\n\t\t(reason: unknown) => ({ status: \"rejected\", reason }),\n\t);\n}\n\n/** Outcomes of every promise, or `undefined` when one is still open after `boundMs`. */\nfunction settledWithin(\n\tpromises: ReadonlyArray<Promise<unknown>>,\n\tboundMs: number,\n): Promise<PromiseSettledResult<unknown>[] | undefined> {\n\treturn runBoundedExecution(\n\t\t\"release of the overlapping calls\",\n\t\t{ timeoutMs: boundMs },\n\t\t() => Promise.allSettled(promises),\n\t).catch(() => undefined);\n}\n\n/** A `run` call that stays open until the proof releases it. */\nexport interface ParkedRunCall<T> {\n\treadonly call: Promise<T>;\n\treadonly release: () => void;\n}\n\n/**\n * Starts a `run` call and holds it open. `start` receives `hold`. The work\n * of the call awaits `hold()` at the point where it must stay open, for\n * example after its load. The result resolves once the work holds and the\n * call is still open. A call that rejects before that propagates its\n * rejection. A call that resolves while its work holds fails: `run` did not\n * await its work.\n */\nexport async function parkRunCall<T>(\n\tstart: (hold: () => Promise<void>) => Promise<T>,\n): Promise<ParkedRunCall<T>> {\n\tlet release!: () => void;\n\tconst mayContinue = new Promise<void>((resolve) => {\n\t\trelease = resolve;\n\t});\n\tlet markHolding!: () => void;\n\tconst holding = new Promise<\"holding\">((resolve) => {\n\t\tmarkHolding = () => resolve(\"holding\");\n\t});\n\tconst call = start(() => {\n\t\tmarkHolding();\n\t\treturn mayContinue;\n\t});\n\tconst settled = settle(call).then((outcome) => outcome.status);\n\n\tlet state = await Promise.race([holding, settled]);\n\tif (state === \"holding\") {\n\t\tstate = await Promise.race([settled, Promise.resolve(\"holding\" as const)]);\n\t}\n\tif (state === \"rejected\") await call;\n\tassert(\n\t\tstate === \"holding\",\n\t\t\"run must await its work: the call resolved while its work still holds\",\n\t);\n\treturn { call, release };\n}\n\n/**\n * Starts a `run` call through `startCall` and awaits it. The call must\n * complete while `parked` stays open. On an environment that serializes\n * `run`, it never completes. So this bounds the wait. After `boundMs` it\n * releases the parked call and waits up to `boundMs` for both calls to\n * settle. Then it fails with the requirement. A rejection of the call, or a\n * synchronous throw of `startCall`, releases the parked call the same way\n * and then propagates. On success the parked call stays parked; the proof\n * releases it when it is ready.\n */\nexport async function awaitOverlappingCall<T>(\n\tstartCall: () => Promise<T>,\n\tparked: ParkedRunCall<unknown>,\n\tboundMs: number,\n): Promise<T> {\n\tlet call: Promise<T>;\n\ttry {\n\t\tcall = startCall();\n\t} catch (error) {\n\t\tparked.release();\n\t\tawait settledWithin([parked.call], boundMs);\n\t\tthrow error;\n\t}\n\tconst outcome = await runBoundedExecution(\n\t\t\"overlapping run call\",\n\t\t{ timeoutMs: boundMs },\n\t\t() => settle(call),\n\t).catch(() => undefined);\n\tif (outcome?.status === \"fulfilled\") return outcome.value;\n\n\tparked.release();\n\tawait settledWithin([parked.call, call], boundMs);\n\tassert(outcome !== undefined, overlappingCallsViolation(boundMs));\n\tthrow outcome.reason;\n}\n\n/**\n * Proves that the environment lets two `run` calls stay open at once.\n *\n * The stale-writer proofs hold one transaction open while a second one\n * commits. An environment that serializes `run` (one connection, a mutex)\n * blocks the second call behind the first. The suite then hangs at the test\n * timeout with no cause. This proof turns that hang into a named failure\n * within `boundMs`. It releases the first call before it returns and waits\n * up to `boundMs` for both calls to complete. A second call that is still\n * blocked after that stays in flight, observed, while the failure reports.\n */\nexport async function assertRunPermitsOverlappingCalls(\n\trun: (work: () => Promise<void>) => Promise<unknown>,\n\tboundMs: number,\n): Promise<void> {\n\tconst first = await parkRunCall((hold) => run(hold));\n\n\tawait awaitOverlappingCall(() => run(async () => {}), first, boundMs);\n\n\tfirst.release();\n\tconst firstOutcome = (await settledWithin([first.call], boundMs))?.[0];\n\tassert(\n\t\tfirstOutcome !== undefined,\n\t\t`the first run call did not complete within ${boundMs} ms after the proof released it`,\n\t);\n\tif (firstOutcome.status === \"rejected\") throw firstOutcome.reason;\n}\n\n/** The part of a contract environment that the preflight needs. */\ninterface OverlappingRunEnvironment<TId> {\n\trun<R>(\n\t\twork: (context: {\n\t\t\trepository: { findById(id: TId): Promise<unknown> };\n\t\t}) => Promise<R>,\n\t): Promise<R>;\n}\n\n/**\n * The preflight entry both repository suites put first: it names a\n * serializing environment before the stale-writer proofs can hang on it.\n * Each `run` call of the proof reads `freshId()` before it holds. So an\n * adapter that reserves its connection on the first statement holds the\n * connection while the call stays open.\n */\nexport function overlappingCallsPreflight<\n\tEnv extends OverlappingRunEnvironment<TId>,\n\tTId,\n>(\n\tinEnvironment: (body: (env: Env) => Promise<void>) => () => Promise<void>,\n\tfreshId: () => TId,\n\tboundMs: number,\n): ContractTest {\n\treturn {\n\t\tname: \"environment preflight: a second run call completes while the first call stays open\",\n\t\trun: inEnvironment((env) =>\n\t\t\tassertRunPermitsOverlappingCalls(\n\t\t\t\t(work) =>\n\t\t\t\t\tenv.run(async ({ repository }) => {\n\t\t\t\t\t\tawait repository.findById(freshId());\n\t\t\t\t\t\tawait work();\n\t\t\t\t\t}),\n\t\t\t\tboundMs,\n\t\t\t),\n\t\t),\n\t};\n}\n\n/**\n * Load with a contract diagnostic instead of a bare TypeError downstream.\n * `suspectHint` names the suite-specific likely cause (broken hydration\n * vs broken replay read).\n */\nexport async function loadAggregateOrFail<TAgg, TId>(\n\trepository: { findById(id: TId): Promise<TAgg | null | undefined> },\n\tid: TId,\n\tsuspectHint: string,\n): Promise<TAgg> {\n\tconst loaded = await repository.findById(id);\n\tassert(\n\t\tloaded !== null && loaded !== undefined,\n\t\t`findById(${String(id)}) returned no aggregate for an identity that must exist: ${suspectHint}`,\n\t);\n\treturn loaded;\n}\n\n/**\n * A capability-gated test entry whose `run()` rejects loudly, so a naive\n * binding that ignores `skipped` fails instead of green-no-op'ing.\n * Structurally assignable to both suites' test-entry types.\n */\nexport function skippedContractTest(\n\tname: string,\n\tcapability: string,\n): ContractTest & { skipped: { capability: string } } {\n\treturn {\n\t\tname,\n\t\tskipped: { capability },\n\t\trun: async () => {\n\t\t\tthrow new Error(\n\t\t\t\t`Contract test skipped: harness capability '${capability}' is not provided. ` +\n\t\t\t\t\t`Bind skipped tests with it.skip ((test.skipped ? it.skip : it)(test.name, test.run)) ` +\n\t\t\t\t\t`or provide the capability; each skipped capability is an unproven guarantee.`,\n\t\t\t);\n\t\t},\n\t};\n}\n\n/**\n * Capability gate that keeps a test's NAME single-sourced: a harness\n * that satisfies the gate gets the real test, everyone else gets the\n * loud skipped entry under the same name (see\n * {@link skippedContractTest}). Nests for tests behind several gates;\n * the outermost failing gate's capability wins the skip report.\n */\nexport function gatedContractTest(\n\tgate: { capability: string; satisfiedBy: boolean },\n\ttest: ContractTest,\n): ContractTest {\n\treturn gate.satisfiedBy\n\t\t? test\n\t\t: skippedContractTest(test.name, gate.capability);\n}\n\n/**\n * Identities of an in-memory pending batch, with the shared precondition\n * that every event carries the recorded brand. The `requirement` names\n * the suite-specific rule the harness violated when an event is not\n * recorded.\n */\nexport function recordedPendingEventIds(\n\tevents: ReadonlyArray<unknown>,\n\trequirement: string,\n): string[] {\n\treturn events.map((event) => {\n\t\tassert(\n\t\t\ttypeof event === \"object\" &&\n\t\t\t\tevent !== null &&\n\t\t\t\tisRecordedDomainEvent(event),\n\t\t\trequirement,\n\t\t);\n\t\treturn (event as { readonly eventId: string }).eventId;\n\t});\n}\n\n/**\n * Sorted identities of committed outbox envelopes. Shared by both\n * repository suites so the projection cannot drift between them.\n */\nexport function sortedCommittedEventIds(\n\tcommitted: ReadonlyArray<{ readonly event: { readonly eventId: string } }>,\n): string[] {\n\treturn committed.map(({ event }) => event.eventId).sort();\n}\n\nexport function assert(condition: boolean, message: string): asserts condition {\n\tif (!condition) {\n\t\tthrow new Error(`Contract violated: ${message}`);\n\t}\n}\n\nexport function assertEqual(\n\tactual: unknown,\n\texpected: unknown,\n\tmessage: string,\n): void {\n\tif (actual !== expected) {\n\t\tthrow new Error(\n\t\t\t`Contract violated: ${message} (expected ${String(expected)}, got ${String(actual)})`,\n\t\t);\n\t}\n}\n\n/**\n * Walks the standard `cause` chain (cycle-safe, hostile-getter-safe)\n * looking for an Error that matches the given name. Matching is\n * deliberately by NAME, not `instanceof`: the suite ships in its own\n * bundle entry, and the adapter's errors come from the main entry's\n * copy of the kit (or even a second installed kit version) -\n * cross-copy `instanceof` is always false, name identity is the stable\n * contract. Since v3 the kit's errors are StructuredErrors whose\n * runtime `name` IS their SCREAMING_SNAKE code, minification-stable by\n * construction and inherited by subclasses (a `PgConflictError extends\n * ConcurrencyConflictError` keeps the code as its name). The suites\n * match ONLY the v3 codes. Failure diagnostics render the rejection's\n * cause-chain names ({@link describeError}), so an unexpected error,\n * including one from a different kit copy in the dependency graph, is\n * identifiable from the message without version-specific knowledge in\n * the suite.\n */\nexport function chainContainsErrorNamed(error: unknown, name: string): boolean {\n\tlet found = false;\n\twalkCauseChain(error, (node) => {\n\t\tfound = errorMatchesName(node, name);\n\t\treturn found;\n\t});\n\treturn found;\n}\n\n/**\n * The one cause-chain walk every chain-inspecting helper in this file\n * is expressed through (cycle-safe, hostile-cause-getter-safe): visits\n * each object node until `visit` asks to stop by returning `true`, the\n * chain ends, repeats, or advancing turns hostile. Single-sourced on\n * purpose: a hardening fix (a depth cap, a new hostile shape) must land\n * in ALL walkers at once, or the suites judge the same adapter\n * rejection inconsistently. Per-node property reads stay the visitor's\n * responsibility; only the `cause` advance is guarded here.\n */\nfunction walkCauseChain(\n\terror: unknown,\n\tvisit: (node: object) => boolean,\n): void {\n\tconst seen = new Set<unknown>();\n\tlet current: unknown = error;\n\twhile (\n\t\tcurrent !== null &&\n\t\tcurrent !== undefined &&\n\t\ttypeof current === \"object\" &&\n\t\t!seen.has(current)\n\t) {\n\t\tseen.add(current);\n\t\tif (visit(current)) return;\n\t\ttry {\n\t\t\tcurrent = (current as { cause?: unknown }).cause;\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t}\n}\n\n/**\n * Asserts that the cause chain carries a kit error with one of the given\n * codes (since v3, `error.name === error.code`; the codes are the ONLY\n * accepted identity). Failure messages built with {@link describeError}\n * render the rejection's cause-chain names, so an unexpected error, e.g.\n * one from a different `@shirudo/ddd-kit` copy in the dependency graph,\n * is identifiable from the diagnostic without the suite carrying any\n * version-specific knowledge.\n */\nexport function assertChainContainsKitError(\n\trejection: unknown,\n\tcodes: readonly string[],\n\tmessage: string,\n): void {\n\tif (codes.some((code) => chainContainsErrorNamed(rejection, code))) {\n\t\treturn;\n\t}\n\tthrow new Error(`Contract violated: ${message}`);\n}\n\n/**\n * Walks the `cause` chain (cycle-safe, hostile-getter-safe) looking for\n * `retryable === true`: the same loose, property-based contract the\n * kit's retry classifier (`someChainRetryable`) applies. Suites assert\n * retryability with this instead of reading the top-level rejection, so\n * an adapter that wraps a kit error in its own error chain, which\n * {@link assertChainContainsKitError} deliberately tolerates, is judged\n * exactly the way a consumer's retry loop will judge it.\n *\n * Deliberately NOT a call to `someChainRetryable` itself: that\n * classifier throws on a circular cause chain (its callers handle\n * that), while a hardened suite must survive whatever error shape an\n * adapter rejects with and answer with a contract diagnostic, never a\n * helper crash. Same hardening discipline as\n * {@link chainContainsErrorNamed}.\n */\nexport function chainContainsRetryable(error: unknown): boolean {\n\tlet found = false;\n\twalkCauseChain(error, (node) => {\n\t\ttry {\n\t\t\tfound = (node as { retryable?: unknown }).retryable === true;\n\t\t} catch {\n\t\t\t// Hostile `retryable` getter: stop the walk, keep found=false.\n\t\t\treturn true;\n\t\t}\n\t\treturn found;\n\t});\n\treturn found;\n}\n\nfunction errorMatchesName(candidate: object, name: string): boolean {\n\ttry {\n\t\tif ((candidate as { name?: unknown }).name === name) {\n\t\t\treturn true;\n\t\t}\n\t} catch {\n\t\t// Hostile `name` getter: treat as non-matching, keep walking.\n\t}\n\t// Fallback for errors whose own `name` was overridden (a subclass\n\t// that re-assigns `this.name` after super): the prototype chain\n\t// still carries the base class's constructor name.\n\ttry {\n\t\tlet proto: object | null = Object.getPrototypeOf(candidate);\n\t\tfor (let depth = 0; proto !== null && depth < 20; depth++) {\n\t\t\tif (\n\t\t\t\t(proto.constructor as { name?: unknown } | undefined)?.name === name\n\t\t\t) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tproto = Object.getPrototypeOf(proto);\n\t\t}\n\t} catch {\n\t\t// Hostile `constructor` getter on a prototype: non-matching.\n\t}\n\treturn false;\n}\n\nexport function describeError(error: unknown): string {\n\tif (error instanceof Error) {\n\t\tconst chain = causeChainNames(error);\n\t\tconst suffix =\n\t\t\tchain.length > 1 ? ` (cause chain: ${chain.join(\" -> \")})` : \"\";\n\t\treturn `${error.name}: ${error.message}${suffix}`;\n\t}\n\treturn String(error);\n}\n\n/**\n * Names along the `cause` chain (cycle-safe, hostile-getter-safe), for\n * failure diagnostics: a wrapped rejection shows WHAT it wraps, so an\n * unexpected error deep in the chain (a raw driver error, or an error\n * from a different kit copy) is identifiable from the message alone.\n */\nfunction causeChainNames(error: Error): string[] {\n\tconst names: string[] = [];\n\twalkCauseChain(error, (node) => {\n\t\ttry {\n\t\t\tconst { name } = node as { name?: unknown };\n\t\t\tnames.push(typeof name === \"string\" ? name : \"(unnamed)\");\n\t\t} catch {\n\t\t\t// Hostile `name` getter: stop with the partial chain collected.\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t});\n\treturn names;\n}\n","import type { PublishedCommand } from \"../application/cqrs/command/command\";\nimport type {\n\tCommandOutboxCommitCandidate,\n\tCommandOutboxWriter,\n\tDurableCommandMessage,\n} from \"../application/cqrs/command/command-outbox\";\nimport { deepEqual } from \"../internal/structural/deep-equal\";\nimport {\n\tassert,\n\tassertEqual,\n\tbindContractEnvironment,\n\ttype ContractTest,\n\tcaptureRejection,\n\tgatedContractTest,\n} from \"./contract-assertions\";\n\nexport interface CommandOutboxContractEnvironment<C extends PublishedCommand> {\n\treadonly outbox: CommandOutboxWriter<C>;\n\treadonly addCommitted: (\n\t\tcommits: ReadonlyArray<CommandOutboxCommitCandidate<C>>,\n\t) => Promise<void>;\n\treadonly addRolledBack?: (\n\t\tcommits: ReadonlyArray<CommandOutboxCommitCandidate<C>>,\n\t) => Promise<void>;\n\treadonly readAll: () => Promise<\n\t\tReadonlyArray<CommandOutboxCommitCandidate<C>>\n\t>;\n\treadonly teardown?: () => Promise<void>;\n}\n\nexport interface CommandOutboxContractHarness<C extends PublishedCommand> {\n\treadonly createEnvironment: () => Promise<\n\t\tCommandOutboxContractEnvironment<C>\n\t>;\n\t/**\n\t * Builds one command for the given seed. The suite derives conflicting\n\t * commits from different seeds, so `createCommand` MUST return distinct\n\t * command content per seed (put the seed in the payload). A constant\n\t * command makes a manufactured conflict deep-equal to its original, and\n\t * the conflict tests then fail a compliant adapter that deduplicates\n\t * the exact retry.\n\t */\n\treadonly createCommand: (seed: number) => C;\n\treadonly providesRolledBackAdds?: boolean;\n}\n\nexport type CommandOutboxContractTest = ContractTest;\n\nexport function createCommandOutboxContractTests<C extends PublishedCommand>(\n\tharness: CommandOutboxContractHarness<C>,\n): ReadonlyArray<CommandOutboxContractTest> {\n\tconst inEnv = bindContractEnvironment(harness.createEnvironment);\n\tconst commit = (\n\t\tseed: number,\n\t\tcommandSeeds: ReadonlyArray<number> = [seed],\n\t): CommandOutboxCommitCandidate<C> => ({\n\t\torigin: {\n\t\t\teventId: `process-event-${seed}`,\n\t\t\tsource: {\n\t\t\t\taggregateType: \"CheckoutProcess\",\n\t\t\t\taggregateId: \"order-1\",\n\t\t\t},\n\t\t\tposition: {\n\t\t\t\taggregateVersion: seed,\n\t\t\t\tcommitSequence: 0,\n\t\t\t\tcommitSize: 1,\n\t\t\t},\n\t\t},\n\t\tmessages: commandSeeds.map((commandSeed, index) =>\n\t\t\tmessage(seed, index, harness.createCommand(commandSeed)),\n\t\t),\n\t});\n\tconst tests: CommandOutboxContractTest[] = [\n\t\t{\n\t\t\tname: \"deduplicates an exact retry by origin event id\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst original = commit(1);\n\t\t\t\tawait env.addCommitted([original]);\n\t\t\t\tawait env.addCommitted([original]);\n\t\t\t\tconst stored = await env.readAll();\n\t\t\t\tassertEqual(\n\t\t\t\t\tstored.length,\n\t\t\t\t\t1,\n\t\t\t\t\t\"an exact retry must retain one receipt, not append a duplicate\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(stored[0], original),\n\t\t\t\t\t\"an exact retry must preserve the original receipt and commands\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"rejects conflicting reuse of an origin event id\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst original = commit(1);\n\t\t\t\tawait env.addCommitted([original]);\n\t\t\t\tconst conflict = {\n\t\t\t\t\t...commit(1, [99]),\n\t\t\t\t\torigin: {\n\t\t\t\t\t\t...commit(1, [99]).origin,\n\t\t\t\t\t\teventId: original.origin.eventId,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tassert(\n\t\t\t\t\t!deepEqual(conflict.messages, original.messages),\n\t\t\t\t\t\"harness contract: createCommand must return distinct content \" +\n\t\t\t\t\t\t\"per seed, or the manufactured conflict is an exact retry\",\n\t\t\t\t);\n\t\t\t\tconst rejection = await captureRejection(env.addCommitted([conflict]));\n\t\t\t\tassert(\n\t\t\t\t\trejection !== undefined,\n\t\t\t\t\t\"a reused origin event id with different messages must reject\",\n\t\t\t\t);\n\t\t\t\tconst stored = await env.readAll();\n\t\t\t\tassertEqual(\n\t\t\t\t\tstored.length,\n\t\t\t\t\t1,\n\t\t\t\t\t\"a conflicting retry must not append another receipt\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(stored[0], original),\n\t\t\t\t\t\"a conflicting retry must not replace the original receipt\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"rejects an origin event id reused with a different source\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst original = commit(1);\n\t\t\t\tawait env.addCommitted([original]);\n\t\t\t\tconst conflicts: ReadonlyArray<{\n\t\t\t\t\treadonly fact: \"aggregateId\" | \"aggregateType\";\n\t\t\t\t\treadonly candidate: CommandOutboxCommitCandidate<C>;\n\t\t\t\t}> = [\n\t\t\t\t\t{\n\t\t\t\t\t\tfact: \"aggregateId\",\n\t\t\t\t\t\tcandidate: {\n\t\t\t\t\t\t\t...original,\n\t\t\t\t\t\t\torigin: {\n\t\t\t\t\t\t\t\t...original.origin,\n\t\t\t\t\t\t\t\tsource: {\n\t\t\t\t\t\t\t\t\t...original.origin.source,\n\t\t\t\t\t\t\t\t\taggregateId: \"order-2\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tfact: \"aggregateType\",\n\t\t\t\t\t\tcandidate: {\n\t\t\t\t\t\t\t...original,\n\t\t\t\t\t\t\torigin: {\n\t\t\t\t\t\t\t\t...original.origin,\n\t\t\t\t\t\t\t\tsource: {\n\t\t\t\t\t\t\t\t\t...original.origin.source,\n\t\t\t\t\t\t\t\t\taggregateType: \"Order\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t];\n\t\t\t\tfor (const { fact, candidate } of conflicts) {\n\t\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\t\tenv.addCommitted([candidate]),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\trejection !== undefined,\n\t\t\t\t\t\t`a reused origin event id with a different source.${fact} must reject`,\n\t\t\t\t\t);\n\t\t\t\t\tconst stored = await env.readAll();\n\t\t\t\t\tassert(\n\t\t\t\t\t\tdeepEqual(stored, [original]),\n\t\t\t\t\t\t`a source.${fact} conflict must leave the original receipt unchanged`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"rejects an origin event id reused with a different position\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst original = commit(1);\n\t\t\t\tawait env.addCommitted([original]);\n\t\t\t\tconst positions = [\n\t\t\t\t\t{ fact: \"aggregateVersion\", change: { aggregateVersion: 2 } },\n\t\t\t\t\t{ fact: \"commitSequence\", change: { commitSequence: 1 } },\n\t\t\t\t\t{ fact: \"commitSize\", change: { commitSize: 2 } },\n\t\t\t\t] as const;\n\t\t\t\tfor (const { fact, change } of positions) {\n\t\t\t\t\tconst conflict: CommandOutboxCommitCandidate<C> = {\n\t\t\t\t\t\t...original,\n\t\t\t\t\t\torigin: {\n\t\t\t\t\t\t\t...original.origin,\n\t\t\t\t\t\t\tposition: {\n\t\t\t\t\t\t\t\t...original.origin.position,\n\t\t\t\t\t\t\t\t...change,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\t\tenv.addCommitted([conflict]),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\trejection !== undefined,\n\t\t\t\t\t\t`a reused origin event id with a different position.${fact} must reject`,\n\t\t\t\t\t);\n\t\t\t\t\tconst stored = await env.readAll();\n\t\t\t\t\tassert(\n\t\t\t\t\t\tdeepEqual(stored, [original]),\n\t\t\t\t\t\t`a position.${fact} conflict must leave the original receipt unchanged`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"rejects a conflicting batch atomically\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst original = commit(1);\n\t\t\t\tawait env.addCommitted([original]);\n\t\t\t\tconst newCommit = commit(2);\n\t\t\t\tconst conflictingOriginal = {\n\t\t\t\t\t...commit(1, [77]),\n\t\t\t\t\torigin: {\n\t\t\t\t\t\t...commit(1, [77]).origin,\n\t\t\t\t\t\teventId: original.origin.eventId,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tassert(\n\t\t\t\t\t!deepEqual(conflictingOriginal.messages, original.messages),\n\t\t\t\t\t\"harness contract: createCommand must return distinct content \" +\n\t\t\t\t\t\t\"per seed, or the manufactured conflict is an exact retry\",\n\t\t\t\t);\n\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\tenv.addCommitted([newCommit, conflictingOriginal]),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\trejection !== undefined,\n\t\t\t\t\t\"a batch containing a conflicting origin must reject\",\n\t\t\t\t);\n\t\t\t\tconst stored = await env.readAll();\n\t\t\t\tassertEqual(\n\t\t\t\t\tstored.length,\n\t\t\t\t\t1,\n\t\t\t\t\t\"a rejected batch must not leave its earlier new receipt behind\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(stored[0], original),\n\t\t\t\t\t\"a rejected batch must preserve the pre-existing receipt\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"retains command and commit input order\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst first = commit(1, [10, 11]);\n\t\t\t\tconst second = commit(2, [20, 21]);\n\t\t\t\tawait env.addCommitted([first, second]);\n\t\t\t\tconst stored = await env.readAll();\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\tstored.map(({ origin }) => origin.eventId),\n\t\t\t\t\t\t[first.origin.eventId, second.origin.eventId],\n\t\t\t\t\t),\n\t\t\t\t\t\"commit receipts must retain input order\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\tstored.map(({ messages }) =>\n\t\t\t\t\t\t\tmessages.map(({ command }) => command),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\tfirst.messages.map(({ command }) => command),\n\t\t\t\t\t\t\tsecond.messages.map(({ command }) => command),\n\t\t\t\t\t\t],\n\t\t\t\t\t),\n\t\t\t\t\t\"commands inside each receipt must retain mapper order\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"retains every position in a multi-event aggregate commit\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst first = commit(10);\n\t\t\t\tconst second = commit(11);\n\t\t\t\tconst commitSize = 2;\n\t\t\t\tconst aggregateVersion = 7;\n\t\t\t\tconst multiEventCommit: ReadonlyArray<CommandOutboxCommitCandidate<C>> =\n\t\t\t\t\t[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t...first,\n\t\t\t\t\t\t\torigin: {\n\t\t\t\t\t\t\t\t...first.origin,\n\t\t\t\t\t\t\t\tposition: {\n\t\t\t\t\t\t\t\t\taggregateVersion,\n\t\t\t\t\t\t\t\t\tcommitSequence: 0,\n\t\t\t\t\t\t\t\t\tcommitSize,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t...second,\n\t\t\t\t\t\t\torigin: {\n\t\t\t\t\t\t\t\t...second.origin,\n\t\t\t\t\t\t\t\tposition: {\n\t\t\t\t\t\t\t\t\taggregateVersion,\n\t\t\t\t\t\t\t\t\tcommitSequence: 1,\n\t\t\t\t\t\t\t\t\tcommitSize,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t];\n\t\t\t\tawait env.addCommitted(multiEventCommit);\n\t\t\t\tconst stored = await env.readAll();\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(stored, multiEventCommit),\n\t\t\t\t\t\"a multi-event commit must retain its shared version, sequence, and size for every receipt\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"retains an empty command receipt and advances the source cursor\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst empty = commit(1, []);\n\t\t\t\tconst next = commit(2);\n\t\t\t\tawait env.addCommitted([empty]);\n\t\t\t\tawait env.addCommitted([next]);\n\t\t\t\tconst stored = await env.readAll();\n\t\t\t\tassertEqual(\n\t\t\t\t\tstored.length,\n\t\t\t\t\t2,\n\t\t\t\t\t\"an empty command batch must retain its source receipt\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tstored[0]?.messages.length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"the retained empty receipt must contain no invented command\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\tstored.map(({ origin }) => origin.position.aggregateVersion),\n\t\t\t\t\t\t[1, 2],\n\t\t\t\t\t),\n\t\t\t\t\t\"the source cursor must advance through the empty receipt\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t];\n\ttests.push(\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"providesRolledBackAdds\",\n\t\t\t\tsatisfiedBy: harness.providesRolledBackAdds === true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"a rolled-back add leaves no receipt or command behind\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tif (!env.addRolledBack) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Contract violated: harness declared providesRolledBackAdds but the environment lacks addRolledBack\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait env.addRolledBack([commit(1)]);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\t(await env.readAll()).length,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t\"a rolled-back transaction must persist no command receipt\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t);\n\treturn tests;\n}\n\nfunction message<C extends PublishedCommand>(\n\tcommitSeed: number,\n\tindex: number,\n\tcommand: C,\n): DurableCommandMessage<C> {\n\treturn {\n\t\tmessageId: `process-event-${commitSeed}:command:${index}`,\n\t\trecordedAt: \"2027-04-05T06:07:08.000Z\",\n\t\tdestination: \"participant.commands\",\n\t\tcommand,\n\t\tconversationId: \"checkout-order-1\",\n\t\tcausationId: `process-event-${commitSeed}`,\n\t};\n}\n","import type {\n\tDeadLetterDeadline,\n\tDeadlineStore,\n} from \"../application/deadlines/deadline-store\";\nimport { deepEqual } from \"../internal/structural/deep-equal\";\nimport {\n\tassert,\n\tassertEqual,\n\tbindContractEnvironment,\n\ttype ContractTest,\n\tgatedContractTest,\n} from \"./contract-assertions\";\n\n/** One contract test; bind with `(test.skipped ? it.skip : it)(test.name, test.run)`. */\nexport type DeadlineStoreContractTest = ContractTest;\n\n/** The plain-data payload shape the suite round-trips. */\ninterface SuitePayload {\n\tkind: string;\n\tstep?: number;\n}\n\n/**\n * One isolated test environment: a fresh deadline store. The suite\n * creates one per test and tears it down afterwards.\n */\nexport interface DeadlineStoreContractEnvironment {\n\t/** The adapter under test. */\n\tstore: DeadlineStore<SuitePayload>;\n\n\t/**\n\t * Runs `work` (schedule/cancel calls) the way production does:\n\t * inside a transaction that COMMITS. For a non-transactional store\n\t * this simply invokes `work`.\n\t */\n\trun<R>(work: () => Promise<R>): Promise<R>;\n\n\t/**\n\t * Optional capability: runs `work` inside a transaction that ROLLS\n\t * BACK. Enables the rollback tests: a rolled-back schedule must not\n\t * leave a deadline behind (a ghost input for a state change that\n\t * never happened), and a rolled-back cancel must not have removed\n\t * one. Transactional adapters should always provide this.\n\t */\n\trunRolledBack?<R>(work: () => Promise<R>): Promise<R>;\n\n\t/** Release connections, drop schemas, etc. Called in a finally. */\n\tteardown?(): Promise<void>;\n}\n\n/**\n * What an adapter supplies to run the deadline-store contract suite.\n * For SQL adapters, run against a real database (testcontainers or\n * equivalent): the rollback tests prove YOUR transaction wiring, and\n * schedule/cancel joining the write transaction is the port's central\n * correctness rule.\n */\nexport interface DeadlineStoreContractHarness {\n\tcreateEnvironment(): Promise<DeadlineStoreContractEnvironment>;\n\n\t/**\n\t * The adapter's attempt ceiling: how many `markFailed` reports move\n\t * a deadline to the dead-letter set. Must be at least 2 so the\n\t * attempts-surfacing test can observe a survivor.\n\t */\n\tfailuresToDeadLetter: number;\n\n\t/**\n\t * Declare `true` when environments provide {@link\n\t * DeadlineStoreContractEnvironment.runRolledBack}. Without it, the\n\t * rollback tests are marked skipped: the honest state of an\n\t * in-memory fake, and a loud gap for a transactional adapter.\n\t */\n\tprovidesRolledBackRuns?: boolean;\n\n\t/**\n\t * Declare `true` when the adapter's `due` CLAIMS the returned\n\t * records for competing pollers (lease, visibility timeout), as the\n\t * port sanctions. Tests that re-poll records an earlier poll\n\t * returned without resolving them (attempts surfacing, neighbor\n\t * flow after a dead-letter, successor visibility during a\n\t * reschedule race) assume a non-claiming read and are marked\n\t * skipped for claiming adapters; prove your claim/expiry semantics\n\t * in your own suite.\n\t */\n\tclaimsOnDue?: boolean;\n}\n\nconst at = (iso: string): Date => new Date(iso);\nconst T0 = \"2026-03-01T10:00:00.000Z\";\nconst T1 = \"2026-03-01T10:05:00.000Z\";\nconst T2 = \"2026-03-01T10:10:00.000Z\";\n\n/**\n * The deadline-store contract test suite: the proof that an adapter\n * delivers the schedule/cancel/due/acknowledge semantics the port\n * documents. Store semantics are an **adapter contract, not a kit\n * guarantee**; this suite is how an adapter demonstrates them.\n *\n * Framework-agnostic: bind with\n * `(test.skipped ? it.skip : it)(test.name, test.run)`.\n */\nexport function createDeadlineStoreContractTests(\n\tharness: DeadlineStoreContractHarness,\n): DeadlineStoreContractTest[] {\n\tconst inEnv = bindContractEnvironment(() => harness.createEnvironment());\n\tconst ceiling = harness.failuresToDeadLetter;\n\tif (!Number.isInteger(ceiling) || ceiling < 2) {\n\t\tthrow new Error(\n\t\t\t\"Contract violated: failuresToDeadLetter must be an integer >= 2; observing attempts on a pending deadline needs one that survives a failure\",\n\t\t);\n\t}\n\n\treturn [\n\t\t{\n\t\t\tname: \"a deadline is invisible before its due time and delivered from it onward\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(() =>\n\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\tscope: \"checkout-saga\",\n\t\t\t\t\t\tkey: \"order-1\",\n\t\t\t\t\t\tdueAt: at(T1),\n\t\t\t\t\t\tpayload: { kind: \"payment-timeout\" },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await env.store.due(at(T0), 10)).length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"a deadline must not fire early\",\n\t\t\t\t);\n\t\t\t\tconst dueExactly = await env.store.due(at(T1), 10);\n\t\t\t\tassertEqual(\n\t\t\t\t\tdueExactly.length,\n\t\t\t\t\t1,\n\t\t\t\t\t\"a deadline is due AT its due time (dueAt <= now)\",\n\t\t\t\t);\n\t\t\t\tconst record = dueExactly[0];\n\t\t\t\tassert(record !== undefined, \"expected the due deadline\");\n\t\t\t\tassertEqual(record.scope, \"checkout-saga\", \"scope must round-trip\");\n\t\t\t\tassertEqual(record.key, \"order-1\", \"key must round-trip\");\n\t\t\t\tassertEqual(\n\t\t\t\t\trecord.dueAt.getTime(),\n\t\t\t\t\tat(T1).getTime(),\n\t\t\t\t\t\"dueAt must round-trip with millisecond fidelity\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(record.payload, { kind: \"payment-timeout\" }),\n\t\t\t\t\t\"the payload must round-trip as plain data\",\n\t\t\t\t);\n\t\t\t\tassertEqual(record.attempts, 0, \"a fresh deadline has no attempts\");\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"due returns earliest first and respects the limit\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(async () => {\n\t\t\t\t\tawait env.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"late\",\n\t\t\t\t\t\tdueAt: at(T2),\n\t\t\t\t\t\tpayload: { kind: \"late\" },\n\t\t\t\t\t});\n\t\t\t\t\tawait env.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"early\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"early\" },\n\t\t\t\t\t});\n\t\t\t\t\tawait env.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"middle\",\n\t\t\t\t\t\tdueAt: at(T1),\n\t\t\t\t\t\tpayload: { kind: \"middle\" },\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\tconst firstPage = await env.store.due(at(T2), 2);\n\t\t\t\tassert(\n\t\t\t\t\tfirstPage.length >= 1 && firstPage.length <= 2,\n\t\t\t\t\t\"limit must bound the page: up to limit records, at least one while deadlines are due\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tfirstPage[0]?.key,\n\t\t\t\t\t\"early\",\n\t\t\t\t\t\"the earliest due deadline comes first\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"markDelivered consumes the deadline and is idempotent on unknown and repeated ids\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(() =>\n\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"k\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"x\" },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst [record] = await env.store.due(at(T1), 10);\n\t\t\t\tassert(record !== undefined, \"expected a due deadline\");\n\t\t\t\tawait env.store.markDelivered([record.deliveryId]);\n\t\t\t\tawait env.store.markDelivered([record.deliveryId]);\n\t\t\t\tawait env.store.markDelivered([\"no-such-delivery-id\"]);\n\t\t\t\tassert(\n\t\t\t\t\t!(await env.store.due(at(T2), 10)).some(\n\t\t\t\t\t\t(d) => d.deliveryId === record.deliveryId,\n\t\t\t\t\t),\n\t\t\t\t\t\"a delivered deadline must never come back\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"cancel removes exactly the addressed deadline and tolerates unknown addresses\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(async () => {\n\t\t\t\t\tawait env.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"keep\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"keep\" },\n\t\t\t\t\t});\n\t\t\t\t\tawait env.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"drop\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"drop\" },\n\t\t\t\t\t});\n\t\t\t\t\tawait env.store.cancel(\"s\", \"drop\");\n\t\t\t\t\tawait env.store.cancel(\"s\", \"never-scheduled\");\n\t\t\t\t});\n\t\t\t\tconst due = await env.store.due(at(T1), 10);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\tdue.map((d) => d.key),\n\t\t\t\t\t\t[\"keep\"],\n\t\t\t\t\t),\n\t\t\t\t\t\"cancel must remove the addressed deadline and nothing else\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"addresses are isolated per scope\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(async () => {\n\t\t\t\t\tawait env.store.schedule({\n\t\t\t\t\t\tscope: \"reservation-hold\",\n\t\t\t\t\t\tkey: \"id-1\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"hold\" },\n\t\t\t\t\t});\n\t\t\t\t\tawait env.store.schedule({\n\t\t\t\t\t\tscope: \"checkout-saga\",\n\t\t\t\t\t\tkey: \"id-1\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"timeout\" },\n\t\t\t\t\t});\n\t\t\t\t\tawait env.store.cancel(\"reservation-hold\", \"id-1\");\n\t\t\t\t});\n\t\t\t\tconst due = await env.store.due(at(T1), 10);\n\t\t\t\tassert(\n\t\t\t\t\tdue.length === 1 && due[0]?.scope === \"checkout-saga\",\n\t\t\t\t\t\"the same key under another scope is a different deadline\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t// The successor-visibility half of the race needs a re-poll while the\n\t\t// replaced incarnation is un-acked; an adapter claiming at address\n\t\t// granularity legitimately holds the address until the claim resolves.\n\t\tgatedContractTest(\n\t\t\t{ capability: \"non-claiming due\", satisfiedBy: !harness.claimsOnDue },\n\t\t\t{\n\t\t\t\tname: \"schedule on an occupied address replaces it, and a stale ack cannot consume the successor\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tawait env.run(() =>\n\t\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\t\tkey: \"k\",\n\t\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\t\tpayload: { kind: \"first\", step: 1 },\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tconst [first] = await env.store.due(at(T1), 10);\n\t\t\t\t\tassert(first !== undefined, \"expected the first incarnation\");\n\n\t\t\t\t\t// Reschedule while the first incarnation is in flight.\n\t\t\t\t\tawait env.run(() =>\n\t\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\t\tkey: \"k\",\n\t\t\t\t\t\t\tdueAt: at(T1),\n\t\t\t\t\t\t\tpayload: { kind: \"second\", step: 2 },\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\t// The late ack of the replaced incarnation must be a no-op.\n\t\t\t\t\tawait env.store.markDelivered([first.deliveryId]);\n\n\t\t\t\t\tconst due = await env.store.due(at(T2), 10);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tdue.length,\n\t\t\t\t\t\t1,\n\t\t\t\t\t\t\"exactly one pending deadline exists per address\",\n\t\t\t\t\t);\n\t\t\t\t\tconst successor = due[0];\n\t\t\t\t\tassert(successor !== undefined, \"expected the successor\");\n\t\t\t\t\tassert(\n\t\t\t\t\t\tdeepEqual(successor.payload, { kind: \"second\", step: 2 }),\n\t\t\t\t\t\t\"the successor carries the rescheduled payload\",\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tsuccessor.deliveryId !== first.deliveryId,\n\t\t\t\t\t\t\"a reschedule is a fresh incarnation with a fresh deliveryId\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\t{\n\t\t\tname: \"after delivery the address is free again for a fresh schedule\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(() =>\n\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"k\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"first\" },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst [first] = await env.store.due(at(T1), 10);\n\t\t\t\tassert(first !== undefined, \"expected a due deadline\");\n\t\t\t\tawait env.store.markDelivered([first.deliveryId]);\n\t\t\t\tawait env.run(() =>\n\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"k\",\n\t\t\t\t\t\tdueAt: at(T1),\n\t\t\t\t\t\tpayload: { kind: \"again\" },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst due = await env.store.due(at(T2), 10);\n\t\t\t\tassert(\n\t\t\t\t\tdue.length === 1 && deepEqual(due[0]?.payload, { kind: \"again\" }),\n\t\t\t\t\t\"a consumed address must accept a new deadline\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"the attempt ceiling dead-letters the deadline, visible in deadLetters with its attempt count\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(() =>\n\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"poison\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"poison\" },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst [poison] = await env.store.due(at(T1), 1);\n\t\t\t\tassert(poison !== undefined, \"expected the due deadline\");\n\t\t\t\tlet transition: DeadLetterDeadline<SuitePayload> | undefined;\n\t\t\t\tfor (let i = 0; i < ceiling; i++) {\n\t\t\t\t\tconst current = await env.store.markFailed(\n\t\t\t\t\t\tpoison.deliveryId,\n\t\t\t\t\t\tnew Error(\"boom\"),\n\t\t\t\t\t);\n\t\t\t\t\tif (i < ceiling - 1) {\n\t\t\t\t\t\tassertEqual(\n\t\t\t\t\t\t\tcurrent,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\"markFailed must not report a dead-letter transition below the ceiling\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\ttransition = current;\n\t\t\t\t}\n\t\t\t\tassertEqual(\n\t\t\t\t\ttransition?.deliveryId,\n\t\t\t\t\tpoison.deliveryId,\n\t\t\t\t\t\"the ceiling-crossing markFailed call must return the exact dead-letter transition\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\ttransition?.attempts,\n\t\t\t\t\tceiling,\n\t\t\t\t\t\"the returned transition must carry the final attempt count\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait env.store.markFailed(poison.deliveryId, new Error(\"late\")),\n\t\t\t\t\tundefined,\n\t\t\t\t\t\"a late failure report must not repeat the dead-letter transition\",\n\t\t\t\t);\n\t\t\t\t// Membership, not count: dead-lettered is terminal for every\n\t\t\t\t// adapter, claiming or not.\n\t\t\t\tassert(\n\t\t\t\t\t!(await env.store.due(at(T2), 10)).some(\n\t\t\t\t\t\t(d) => d.deliveryId === poison.deliveryId,\n\t\t\t\t\t),\n\t\t\t\t\t\"a dead-lettered deadline must stop coming back\",\n\t\t\t\t);\n\t\t\t\tconst dead = await env.store.deadLetters();\n\t\t\t\tassert(\n\t\t\t\t\tdead.length === 1 && dead[0]?.attempts === ceiling,\n\t\t\t\t\t\"the dead-lettered deadline must appear in deadLetters() with its attempt count\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t// Observing attempts on a pending record, and a neighbor's continued\n\t\t// flow, both need re-polls of records an earlier poll returned\n\t\t// without resolving them; claiming adapters legitimately hold those\n\t\t// back until the claim expires.\n\t\tgatedContractTest(\n\t\t\t{ capability: \"non-claiming due\", satisfiedBy: !harness.claimsOnDue },\n\t\t\t{\n\t\t\t\tname: \"attempts surface on redelivery, and a poison deadline does not block its neighbors\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tawait env.run(async () => {\n\t\t\t\t\t\tawait env.store.schedule({\n\t\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\t\tkey: \"poison\",\n\t\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\t\tpayload: { kind: \"poison\" },\n\t\t\t\t\t\t});\n\t\t\t\t\t\tawait env.store.schedule({\n\t\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\t\tkey: \"healthy\",\n\t\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\t\tpayload: { kind: \"healthy\" },\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t\tconst [poison] = await env.store.due(at(T1), 1);\n\t\t\t\t\tassert(poison !== undefined, \"expected the earliest due deadline\");\n\t\t\t\t\tawait env.store.markFailed(poison.deliveryId, new Error(\"boom\"));\n\t\t\t\t\tconst afterOne = await env.store.due(at(T1), 10);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tafterOne.find((d) => d.deliveryId === poison.deliveryId)?.attempts,\n\t\t\t\t\t\t1,\n\t\t\t\t\t\t\"attempts must be surfaced on the record after markFailed\",\n\t\t\t\t\t);\n\t\t\t\t\tfor (let i = 1; i < ceiling; i++) {\n\t\t\t\t\t\tawait env.store.markFailed(poison.deliveryId, new Error(\"boom\"));\n\t\t\t\t\t}\n\t\t\t\t\tassert(\n\t\t\t\t\t\t(await env.store.due(at(T1), 10)).some((d) => d.key === \"healthy\"),\n\t\t\t\t\t\t\"deadlines carry no cross-address ordering; a dead-lettered neighbor must not block delivery\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\t{\n\t\t\tname: \"two dead-lettered incarnations of one address are both kept and individually clearable\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(() =>\n\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"k\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"first\" },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst [first] = await env.store.due(at(T1), 10);\n\t\t\t\tassert(first !== undefined, \"expected the first incarnation\");\n\t\t\t\tfor (let i = 0; i < ceiling; i++) {\n\t\t\t\t\tawait env.store.markFailed(first.deliveryId, new Error(\"boom\"));\n\t\t\t\t}\n\t\t\t\t// The dead letter freed the address; the process schedules a\n\t\t\t\t// fresh incarnation, and it dead-letters too.\n\t\t\t\tawait env.run(() =>\n\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"k\",\n\t\t\t\t\t\tdueAt: at(T1),\n\t\t\t\t\t\tpayload: { kind: \"second\" },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst [second] = await env.store.due(at(T2), 10);\n\t\t\t\tassert(second !== undefined, \"expected the second incarnation\");\n\t\t\t\tfor (let i = 0; i < ceiling; i++) {\n\t\t\t\t\tawait env.store.markFailed(second.deliveryId, new Error(\"boom\"));\n\t\t\t\t}\n\t\t\t\tconst dead = await env.store.deadLetters();\n\t\t\t\tassert(\n\t\t\t\t\tdead.length === 2 &&\n\t\t\t\t\t\tdead.some((d) => d.deliveryId === first.deliveryId) &&\n\t\t\t\t\t\tdead.some((d) => d.deliveryId === second.deliveryId),\n\t\t\t\t\t\"dead letters are kept per incarnation; a later dead letter of the same address must not overwrite an earlier un-acked one\",\n\t\t\t\t);\n\t\t\t\tawait env.store.markDelivered([first.deliveryId]);\n\t\t\t\tconst remaining = await env.store.deadLetters();\n\t\t\t\tassert(\n\t\t\t\t\tremaining.length === 1 &&\n\t\t\t\t\t\tremaining[0]?.deliveryId === second.deliveryId,\n\t\t\t\t\t\"acknowledging one dead-lettered incarnation must not clear its sibling\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"late failure reports never resurrect or advance anything, and acking a dead letter clears it\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(() =>\n\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\tkey: \"k\",\n\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\tpayload: { kind: \"x\" },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst [record] = await env.store.due(at(T1), 10);\n\t\t\t\tassert(record !== undefined, \"expected a due deadline\");\n\t\t\t\tfor (let i = 0; i < ceiling; i++) {\n\t\t\t\t\tawait env.store.markFailed(record.deliveryId, new Error(\"boom\"));\n\t\t\t\t}\n\t\t\t\t// Late reports against a dead-lettered incarnation: no-ops.\n\t\t\t\tawait env.store.markFailed(record.deliveryId, new Error(\"late\"));\n\t\t\t\tawait env.store.markFailed(\"no-such-id\", new Error(\"unknown\"));\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await env.store.deadLetters()).length,\n\t\t\t\t\t1,\n\t\t\t\t\t\"late or unknown failure reports must not change the dead-letter set\",\n\t\t\t\t);\n\t\t\t\t// Manual redelivery, then ack: the dead letter clears.\n\t\t\t\tawait env.store.markDelivered([record.deliveryId]);\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await env.store.deadLetters()).length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"acking a dead-lettered deadline must clear it\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"providesRolledBackRuns\",\n\t\t\t\tsatisfiedBy: harness.providesRolledBackRuns === true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"a rolled-back schedule leaves no deadline behind\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tif (!env.runRolledBack) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Contract violated: harness declared providesRolledBackRuns but the environment lacks runRolledBack\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait env\n\t\t\t\t\t\t.runRolledBack(() =>\n\t\t\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\t\t\tkey: \"ghost\",\n\t\t\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\t\t\tpayload: { kind: \"ghost\" },\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\t\t// The rollback mechanism may surface as a rejection; the\n\t\t\t\t\t\t\t// contract under test is the store state afterwards.\n\t\t\t\t\t\t});\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\t(await env.store.due(at(T2), 10)).length,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t\"a deadline from a rolled-back transaction is a ghost input and must not exist\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"providesRolledBackRuns\",\n\t\t\t\tsatisfiedBy: harness.providesRolledBackRuns === true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"a rolled-back cancel leaves the deadline in place\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tif (!env.runRolledBack) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Contract violated: harness declared providesRolledBackRuns but the environment lacks runRolledBack\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait env.run(() =>\n\t\t\t\t\t\tenv.store.schedule({\n\t\t\t\t\t\t\tscope: \"s\",\n\t\t\t\t\t\t\tkey: \"k\",\n\t\t\t\t\t\t\tdueAt: at(T0),\n\t\t\t\t\t\t\tpayload: { kind: \"x\" },\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tawait env\n\t\t\t\t\t\t.runRolledBack(() => env.store.cancel(\"s\", \"k\"))\n\t\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\t\t// See above: only the state afterwards is the contract.\n\t\t\t\t\t\t});\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\t(await env.store.due(at(T1), 10)).length,\n\t\t\t\t\t\t1,\n\t\t\t\t\t\t\"a cancel from a rolled-back transaction must not have removed the deadline\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t];\n}\n","import type { Aggregate } from \"../domain/aggregate/aggregate\";\nimport type { AggregateAddress } from \"../domain/aggregate/aggregate-address\";\nimport type {\n\tAnyDomainEvent,\n\tPendingDomainEvent,\n} from \"../domain/event/domain-event\";\nimport type { Id } from \"../domain/identity/id\";\nimport { deepEqual } from \"../internal/structural/deep-equal\";\nimport type { CommittedDomainEvent } from \"../messaging/committed-event\";\nimport type {\n\tReadStreamOptions,\n\tStreamReadResult,\n} from \"../persistence/event-store/event-store\";\nimport {\n\tassert,\n\tassertChainContainsKitError,\n\tassertEqual,\n\tawaitOverlappingCall,\n\tbindContractEnvironment,\n\ttype ContractTest,\n\tcaptureRejection,\n\tdescribeError,\n\tgatedContractTest,\n\tloadAggregateOrFail,\n\tOVERLAPPING_CALLS_BOUND_MS,\n\toverlappingCallsPreflight,\n\tparkRunCall,\n\trecordedPendingEventIds,\n\tsortedCommittedEventIds,\n} from \"./contract-assertions\";\n\n/** Event-sourced repositories normally expose no physical removal. */\nexport interface EsContractRepository<\n\tTAggregate extends Aggregate<Id<string>, AnyDomainEvent>,\n> {\n\tfindById(id: TAggregate[\"id\"]): Promise<TAggregate | undefined>;\n\tadd(aggregate: TAggregate): void;\n\tupdate(aggregate: TAggregate): void;\n}\n\nexport interface EsRepositoryContractEnvironment<\n\tTAggregate extends Aggregate<Id<string>, TEvent>,\n\tTEvent extends AnyDomainEvent = AnyDomainEvent,\n> {\n\trun<R>(\n\t\twork: (context: {\n\t\t\trepository: EsContractRepository<TAggregate>;\n\t\t}) => Promise<R>,\n\t): Promise<R>;\n\tcommittedOutboxEvents(): Promise<ReadonlyArray<CommittedDomainEvent<TEvent>>>;\n\tfailNextOutboxWrite(error: Error): void;\n\tcommittedStreamEvents(\n\t\tstream: AggregateAddress<TAggregate[\"id\"]>,\n\t\toptions: ReadStreamOptions,\n\t): Promise<StreamReadResult<TEvent>>;\n\tteardown?(): Promise<void>;\n}\n\nexport interface EsRepositoryContractHarness<\n\tTAggregate extends Aggregate<Id<string>, TEvent>,\n\tTEvent extends AnyDomainEvent = AnyDomainEvent,\n> {\n\tcreateEnvironment(): Promise<\n\t\tEsRepositoryContractEnvironment<TAggregate, TEvent>\n\t>;\n\t/** Fresh aggregate with exactly one recorded creation event. */\n\tcreateAggregate(): TAggregate;\n\tcreateAggregateWithId?(id: TAggregate[\"id\"]): TAggregate;\n\tstreamKeyFor(id: TAggregate[\"id\"]): AggregateAddress<TAggregate[\"id\"]>;\n\t/** Applies exactly one event and advances the aggregate version by one. */\n\tmutate(aggregate: TAggregate): void;\n\tsnapshotState?(aggregate: TAggregate): unknown;\n\t/**\n\t * Persists a snapshot of the aggregate at its current version in the\n\t * environment's snapshot store, so the next load there starts from it.\n\t * Enables the snapshot catch-up proof.\n\t */\n\tcaptureSnapshot?(\n\t\taggregate: TAggregate,\n\t\tenvironment: EsRepositoryContractEnvironment<TAggregate, TEvent>,\n\t): Promise<void>;\n\t/**\n\t * Bound for the overlapping `run` calls, in milliseconds: the second call\n\t * of the environment preflight, and the committing call of each\n\t * stale-writer proof. Raise it only for a second connection that needs\n\t * more time to open, or for a slow commit. Keep twice the bound, plus\n\t * environment creation and teardown, below the test timeout of the runner.\n\t */\n\toverlappingCallsBoundMs?: number;\n}\n\nexport type EsRepositoryContractTest = ContractTest;\n\n/**\n * Contract suite for event-stream adapters using v3 Unit-of-Work receipts.\n *\n * `add` and `update` register intent only. At commit, the adapter appends the\n * receipt's exact event batch with the Unit of Work's expected version, in the\n * same transaction as the outbox. `run` must support overlapping calls so the\n * mandatory stale-writer proof exercises a real stream OCC predicate.\n */\nexport function createEsRepositoryContractTests<\n\tTAggregate extends Aggregate<Id<string>, TEvent>,\n\tTEvent extends AnyDomainEvent = AnyDomainEvent,\n>(\n\tharness: EsRepositoryContractHarness<TAggregate, TEvent>,\n): EsRepositoryContractTest[] {\n\ttype Environment = EsRepositoryContractEnvironment<TAggregate, TEvent>;\n\tconst inEnvironment = bindContractEnvironment(() =>\n\t\tharness.createEnvironment(),\n\t);\n\tconst readAll = { limit: 100 } as const;\n\tconst createAggregateWithId = harness.createAggregateWithId;\n\tconst snapshotState = harness.snapshotState;\n\tconst captureSnapshot = harness.captureSnapshot;\n\tconst overlappingCallsBoundMs =\n\t\tharness.overlappingCallsBoundMs ?? OVERLAPPING_CALLS_BOUND_MS;\n\n\tconst load = (\n\t\trepository: EsContractRepository<TAggregate>,\n\t\tid: TAggregate[\"id\"],\n\t): Promise<TAggregate> =>\n\t\tloadAggregateOrFail(\n\t\t\trepository,\n\t\t\tid,\n\t\t\t\"the stream was not appended or replayed correctly\",\n\t\t);\n\tconst streamFor = (id: TAggregate[\"id\"]) => harness.streamKeyFor(id);\n\t// Pre-flush identities: the in-memory batch must be recorded before\n\t// the adapter may flush it.\n\tconst recordedIds = (\n\t\tevents: ReadonlyArray<PendingDomainEvent<TEvent>>,\n\t): string[] =>\n\t\trecordedPendingEventIds(\n\t\t\tevents,\n\t\t\t\"pending events must be recorded before flush\",\n\t\t);\n\t// Read-back identities: adapters may serialize committed events to rows\n\t// and decode them on read. A decoded event does not carry the in-memory\n\t// recorded brand, and no contract demands a re-mint on read, so only\n\t// the persisted identity is asserted here.\n\tconst ids = (events: ReadonlyArray<TEvent>): string[] =>\n\t\tevents.map((event) => {\n\t\t\tassert(\n\t\t\t\ttypeof event.eventId === \"string\" && event.eventId.length > 0,\n\t\t\t\t\"committed events must carry their persisted eventId\",\n\t\t\t);\n\t\t\treturn event.eventId;\n\t\t});\n\tconst outboxIds = (\n\t\tevents: ReadonlyArray<CommittedDomainEvent<TEvent>>,\n\t): string[] => sortedCommittedEventIds(events);\n\n\tasync function seed(environment: Environment): Promise<TAggregate> {\n\t\tconst aggregate = harness.createAggregate();\n\t\tawait environment.run(async ({ repository }) => {\n\t\t\trepository.add(aggregate);\n\t\t});\n\t\treturn aggregate;\n\t}\n\n\tconst tests: EsRepositoryContractTest[] = [\n\t\toverlappingCallsPreflight<Environment, TAggregate[\"id\"]>(\n\t\t\tinEnvironment,\n\t\t\t() => harness.createAggregate().id,\n\t\t\toverlappingCallsBoundMs,\n\t\t),\n\t\t{\n\t\t\tname: \"add appends the exact creation batch to stream and outbox\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tconst expectedIds = recordedIds(aggregate.pendingEvents);\n\t\t\t\tassertEqual(\n\t\t\t\t\texpectedIds.length,\n\t\t\t\t\t1,\n\t\t\t\t\t\"createAggregate must record exactly one creation event\",\n\t\t\t\t);\n\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t});\n\t\t\t\tconst stream = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(aggregate.id),\n\t\t\t\t\treadAll,\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tstream.exists && deepEqual(ids(stream.events), expectedIds),\n\t\t\t\t\t\"the stream must contain exactly the registered creation batch\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\toutboxIds(await environment.committedOutboxEvents()),\n\t\t\t\t\t\t[...expectedIds].sort(),\n\t\t\t\t\t),\n\t\t\t\t\t\"the outbox must contain the same exact creation batch\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\taggregate.pendingEvents.length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"successful commit must acknowledge the creation batch\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"MANDATORY stale append: writer B conflicts after writer A commits and appends no prefix\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\tconst writerB = await parkRunCall((hold) =>\n\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\tconst stale = await load(repository, seeded.id);\n\t\t\t\t\t\tawait hold();\n\t\t\t\t\t\tharness.mutate(stale);\n\t\t\t\t\t\tharness.mutate(stale);\n\t\t\t\t\t\trepository.update(stale);\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\tconst winner = await awaitOverlappingCall(\n\t\t\t\t\t() =>\n\t\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\t\tconst current = await load(repository, seeded.id);\n\t\t\t\t\t\t\tharness.mutate(current);\n\t\t\t\t\t\t\trepository.update(current);\n\t\t\t\t\t\t\treturn current;\n\t\t\t\t\t\t}),\n\t\t\t\t\twriterB,\n\t\t\t\t\toverlappingCallsBoundMs,\n\t\t\t\t);\n\t\t\t\tconst streamAfterWinner = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(seeded.id),\n\t\t\t\t\treadAll,\n\t\t\t\t);\n\t\t\t\twriterB.release();\n\t\t\t\tconst rejection = await captureRejection(writerB.call);\n\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\trejection,\n\t\t\t\t\t[\"CONCURRENCY_CONFLICT\"],\n\t\t\t\t\t`stale append must reject with ConcurrencyConflictError; got ${describeError(rejection)}`,\n\t\t\t\t);\n\t\t\t\tconst finalStream = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(seeded.id),\n\t\t\t\t\treadAll,\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tfinalStream.exists &&\n\t\t\t\t\t\tdeepEqual(ids(finalStream.events), ids(streamAfterWinner.events)),\n\t\t\t\t\t\"a rejected multi-event append must leave no prefix in the stream\",\n\t\t\t\t);\n\t\t\t\tconst reloaded = await environment.run(({ repository }) =>\n\t\t\t\t\tload(repository, seeded.id),\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\treloaded.version,\n\t\t\t\t\twinner.version,\n\t\t\t\t\t\"replay must end at the winning stream version\",\n\t\t\t\t);\n\t\t\t\tif (snapshotState) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\t\tsnapshotState.call(harness, reloaded),\n\t\t\t\t\t\t\tsnapshotState.call(harness, winner),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t\"replay must fold to writer A's state\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"replay preserves emission order and returns no pending events\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tconst expectedIds = recordedIds(aggregate.pendingEvents);\n\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t});\n\t\t\t\tconst reloaded = await environment.run(({ repository }) =>\n\t\t\t\t\tload(repository, aggregate.id),\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\treloaded.version,\n\t\t\t\t\texpectedIds.length,\n\t\t\t\t\t\"event-sourced version must equal the folded event count\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\treloaded.pendingEvents.length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"replay must not re-record historical events\",\n\t\t\t\t);\n\t\t\t\tif (snapshotState) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\t\tsnapshotState.call(harness, reloaded),\n\t\t\t\t\t\t\tsnapshotState.call(harness, aggregate),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t\"replay must fold to the same state in emission order\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst stream = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(aggregate.id),\n\t\t\t\t\treadAll,\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tstream.exists && deepEqual(ids(stream.events), expectedIds),\n\t\t\t\t\t\"the committed stream must preserve emission order\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"rollback leaves stream and outbox absent and acknowledges nothing\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tconst pending = [...aggregate.pendingEvents];\n\t\t\t\tawait captureRejection(\n\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t\t\tthrow new Error(\"rollback probe\");\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst stream = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(aggregate.id),\n\t\t\t\t\treadAll,\n\t\t\t\t);\n\t\t\t\tassert(!stream.exists, \"rollback must leave the stream absent\");\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await environment.committedOutboxEvents()).length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"rollback must leave the outbox empty\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(aggregate.pendingEvents, pending),\n\t\t\t\t\t\"rollback must retain the exact pending batch\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"retrying the same never-persisted instance after rollback creates the full stream\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tconst expectedIds = recordedIds(aggregate.pendingEvents);\n\t\t\t\tawait captureRejection(\n\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t\t\tthrow new Error(\"rollback probe\");\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\t// The documented retry carve-out: a never-persisted instance has\n\t\t\t\t// no row or stream to reload, so the caller re-adds the SAME\n\t\t\t\t// instance with its retained pending batch.\n\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t});\n\t\t\t\tconst stream = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(aggregate.id),\n\t\t\t\t\treadAll,\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tstream.exists && deepEqual(ids(stream.events), expectedIds),\n\t\t\t\t\t\"the retried add must create the stream with the full pending history\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\taggregate.pendingEvents.length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"the successful retry must acknowledge the whole batch\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"outbox failure rolls the already-appended stream batch back\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tconst pending = [...aggregate.pendingEvents];\n\t\t\t\tenvironment.failNextOutboxWrite(new Error(\"outbox failure probe\"));\n\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tassert(rejection !== undefined, \"the outbox failure must reject\");\n\t\t\t\tconst stream = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(aggregate.id),\n\t\t\t\t\treadAll,\n\t\t\t\t);\n\t\t\t\tassert(!stream.exists, \"stream append must roll back with the outbox\");\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await environment.committedOutboxEvents()).length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"failed outbox write must commit no envelope\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(aggregate.pendingEvents, pending),\n\t\t\t\t\t\"failed commit must acknowledge none of the event batch\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"read windows preserve absence, actual head, and point-in-time bounds\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst missingAggregate = harness.createAggregate();\n\t\t\t\tconst missing = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(missingAggregate.id),\n\t\t\t\t\treadAll,\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\t!missing.exists && missing.lastVersion === 0,\n\t\t\t\t\t\"a missing stream must report exists=false and head 0\",\n\t\t\t\t);\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t});\n\t\t\t\tconst afterOne = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(aggregate.id),\n\t\t\t\t\t{ limit: 100, fromVersion: 1 },\n\t\t\t\t);\n\t\t\t\tconst asOfTwo = await environment.committedStreamEvents(\n\t\t\t\t\tstreamFor(aggregate.id),\n\t\t\t\t\t{ limit: 100, toVersion: 2 },\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tafterOne.exists &&\n\t\t\t\t\t\tafterOne.lastVersion === 3 &&\n\t\t\t\t\t\tafterOne.events.length === 2,\n\t\t\t\t\t\"fromVersion is exclusive and preserves the actual stream head\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tasOfTwo.exists &&\n\t\t\t\t\t\tasOfTwo.lastVersion === 3 &&\n\t\t\t\t\t\tasOfTwo.events.length === 2,\n\t\t\t\t\t\"toVersion is inclusive and preserves the actual stream head\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"identity map returns one replayed instance per Unit of Work\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\tconst first = await repository.findById(seeded.id);\n\t\t\t\t\tconst second = await repository.findById(seeded.id);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tfirst !== undefined && first === second,\n\t\t\t\t\t\t\"repeated stream loads must return the same tracked instance\",\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t}),\n\t\t},\n\t];\n\n\ttests.push(\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"createAggregateWithId\",\n\t\t\t\tsatisfiedBy: Boolean(createAggregateWithId),\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"duplicate add conflicts and leaves the existing stream untouched\",\n\t\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\t\tassert(createAggregateWithId !== undefined, \"capability gate\");\n\t\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\t\tconst before = await environment.committedStreamEvents(\n\t\t\t\t\t\tstreamFor(seeded.id),\n\t\t\t\t\t\treadAll,\n\t\t\t\t\t);\n\t\t\t\t\tconst duplicate = createAggregateWithId.call(harness, seeded.id);\n\t\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\t\trepository.add(duplicate);\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\t\trejection,\n\t\t\t\t\t\t[\"CONCURRENCY_CONFLICT\", \"DUPLICATE_AGGREGATE\"],\n\t\t\t\t\t\t`duplicate stream creation must reject with a mapped kit error; got ${describeError(rejection)}`,\n\t\t\t\t\t);\n\t\t\t\t\tconst after = await environment.committedStreamEvents(\n\t\t\t\t\t\tstreamFor(seeded.id),\n\t\t\t\t\t\treadAll,\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tdeepEqual(ids(after.events), ids(before.events)),\n\t\t\t\t\t\t\"duplicate add must not modify the existing stream\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t);\n\n\ttests.push(\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"captureSnapshot\",\n\t\t\t\tsatisfiedBy: Boolean(captureSnapshot),\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"snapshot catch-up ends at the stream head and folds only the tail\",\n\t\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\t\tassert(captureSnapshot !== undefined, \"capability gate\");\n\t\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\t\tconst loaded = await load(repository, seeded.id);\n\t\t\t\t\t\tharness.mutate(loaded);\n\t\t\t\t\t\trepository.update(loaded);\n\t\t\t\t\t});\n\t\t\t\t\tconst snapshotted = await environment.run(({ repository }) =>\n\t\t\t\t\t\tload(repository, seeded.id),\n\t\t\t\t\t);\n\t\t\t\t\tawait captureSnapshot.call(harness, snapshotted, environment);\n\n\t\t\t\t\tconst atHead = await environment.run(({ repository }) =>\n\t\t\t\t\t\tload(repository, seeded.id),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tatHead.version === snapshotted.version,\n\t\t\t\t\t\t`a snapshot at the head must load at the head ${snapshotted.version}, not beyond it; got ${atHead.version}`,\n\t\t\t\t\t);\n\n\t\t\t\t\tconst winner = await environment.run(async ({ repository }) => {\n\t\t\t\t\t\tconst loaded = await load(repository, seeded.id);\n\t\t\t\t\t\tharness.mutate(loaded);\n\t\t\t\t\t\tharness.mutate(loaded);\n\t\t\t\t\t\trepository.update(loaded);\n\t\t\t\t\t\treturn loaded;\n\t\t\t\t\t});\n\t\t\t\t\tconst caughtUp = await environment.run(({ repository }) =>\n\t\t\t\t\t\tload(repository, seeded.id),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tcaughtUp.version === winner.version,\n\t\t\t\t\t\t`snapshot catch-up must end at the stream head ${winner.version}; got ${caughtUp.version}`,\n\t\t\t\t\t);\n\t\t\t\t\tif (snapshotState) {\n\t\t\t\t\t\tassert(\n\t\t\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\t\t\tsnapshotState.call(harness, caughtUp),\n\t\t\t\t\t\t\t\tsnapshotState.call(harness, winner),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\"snapshot catch-up must fold only the tail after the snapshot\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t);\n\n\treturn tests;\n}\n","import type { AnyDomainEvent } from \"../domain/event/domain-event\";\nimport type { EventBus } from \"../messaging/event-bus/ports\";\nimport {\n\tassert,\n\tassertEqual,\n\tbindContractEnvironment,\n\ttype ContractTest,\n\tcaptureRejection,\n} from \"./contract-assertions\";\n\n/** One entry of the event-bus contract suite. */\nexport type EventBusContractTest = ContractTest;\n\n/**\n * What the suite runs against. The harness creates one per test and tears\n * it down afterwards. No transaction wrapper: the port is in-process and\n * transaction-free by design.\n */\nexport interface EventBusContractEnvironment<Evt extends AnyDomainEvent> {\n\t/** The implementation under test. */\n\treadonly bus: EventBus<Evt>;\n\n\t/** Release connections, drop schemas, etc. Called in a finally. */\n\tteardown?(): Promise<void>;\n}\n\n/**\n * What an implementation supplies to run the event-bus contract suite.\n *\n * The suite mints no events, so it stays free of any event union. The two\n * factories must produce DIFFERENT `type` values: the suite subscribes to\n * both to prove that ordering holds across types and that a catch-all\n * subscription sees every type.\n */\nexport interface EventBusContractHarness<Evt extends AnyDomainEvent> {\n\tcreateEnvironment(): Promise<EventBusContractEnvironment<Evt>>;\n\t/** An event of the first type. Called repeatedly; each call may differ. */\n\tcreateFirstEvent(): Evt;\n\t/** An event of the second type, whose `type` differs from the first. */\n\tcreateSecondEvent(): Evt;\n}\n\n/** Resolves after enough turns for a parallel batch to have started. */\nfunction turn(): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, 0));\n}\n\n/**\n * The event-bus contract test suite: the proof that an implementation\n * delivers the guarantees the `EventBus` port documents. Ordering,\n * parallelism within one event, and error collection after the batch are\n * a **port contract, not a kit guarantee**; this suite is how an\n * implementation demonstrates them.\n *\n * The suite covers the port and nothing else. Construction options of the\n * kit's own adapter, such as a publish-depth bound or an observer bundle,\n * are not port behavior and are not pinned here.\n *\n * Framework-agnostic: bind with\n * `(test.skipped ? it.skip : it)(test.name, test.run)`.\n */\nexport function createEventBusContractTests<Evt extends AnyDomainEvent>(\n\tharness: EventBusContractHarness<Evt>,\n): EventBusContractTest[] {\n\ttype Env = EventBusContractEnvironment<Evt>;\n\tconst inEnv = bindContractEnvironment(() => harness.createEnvironment());\n\n\tconst first = () => harness.createFirstEvent();\n\tconst second = () => harness.createSecondEvent();\n\t// Called inside a test, never while the suite is built. A harness whose\n\t// factories need their environment would otherwise throw before a single\n\t// test has a name.\n\tconst types = () => {\n\t\tconst firstType = first().type as Evt[\"type\"];\n\t\tconst secondType = second().type as Evt[\"type\"];\n\t\tassert(\n\t\t\tfirstType !== secondType,\n\t\t\t\"the harness must supply two event factories with different types\",\n\t\t);\n\t\treturn { firstType, secondType };\n\t};\n\n\treturn [\n\t\t{\n\t\t\tname: \"dispatches the events of one batch in input order\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType, secondType } = types();\n\t\t\t\tconst seen: string[] = [];\n\t\t\t\t// The first type is the slower one. Input order must hold\n\t\t\t\t// whatever the handlers cost, so a dispatch that runs the batch\n\t\t\t\t// concurrently reorders here and fails.\n\t\t\t\tbus.subscribe(firstType, async (event) => {\n\t\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, 20));\n\t\t\t\t\tseen.push(event.type);\n\t\t\t\t});\n\t\t\t\tbus.subscribe(secondType, async (event) => {\n\t\t\t\t\tseen.push(event.type);\n\t\t\t\t});\n\n\t\t\t\tawait bus.publish([first(), second(), first()]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tseen.join(\",\"),\n\t\t\t\t\t[firstType, secondType, firstType].join(\",\"),\n\t\t\t\t\t\"a batch dispatches its events in input order\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"starts the handlers of an event only after the previous event finished\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType, secondType } = types();\n\t\t\t\tconst trace: string[] = [];\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\ttrace.push(\"first:start\");\n\t\t\t\t\tawait turn();\n\t\t\t\t\ttrace.push(\"first:end\");\n\t\t\t\t});\n\t\t\t\tbus.subscribe(secondType, async () => {\n\t\t\t\t\ttrace.push(\"second:start\");\n\t\t\t\t});\n\n\t\t\t\tawait bus.publish([first(), second()]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\ttrace.join(\",\"),\n\t\t\t\t\t\"first:start,first:end,second:start\",\n\t\t\t\t\t\"an event dispatches only after the previous one finished\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"runs the handlers of one event in parallel\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst trace: string[] = [];\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\ttrace.push(\"a:start\");\n\t\t\t\t\tawait turn();\n\t\t\t\t\ttrace.push(\"a:end\");\n\t\t\t\t});\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\ttrace.push(\"b:start\");\n\t\t\t\t\tawait turn();\n\t\t\t\t\ttrace.push(\"b:end\");\n\t\t\t\t});\n\n\t\t\t\tawait bus.publish([first()]);\n\n\t\t\t\t// Sequential dispatch would read a:start, a:end, b:start, b:end.\n\t\t\t\tassertEqual(\n\t\t\t\t\ttrace.join(\",\"),\n\t\t\t\t\t\"a:start,b:start,a:end,b:end\",\n\t\t\t\t\t\"the handlers of one event run in parallel\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"runs every handler of an event when a peer fails\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst seen: string[] = [];\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tthrow new Error(\"first handler failed\");\n\t\t\t\t});\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tseen.push(\"peer\");\n\t\t\t\t});\n\n\t\t\t\tawait captureRejection(bus.publish([first()]));\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tseen.join(\",\"),\n\t\t\t\t\t\"peer\",\n\t\t\t\t\t\"a peer of a failing handler still runs\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"reaches the caller with a single failure directly\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst failure = new Error(\"the only handler failed\");\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tthrow failure;\n\t\t\t\t});\n\n\t\t\t\tconst thrown = await captureRejection(bus.publish([first()]));\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tthrown,\n\t\t\t\t\tfailure,\n\t\t\t\t\t\"a single failure reaches the caller unchanged\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"collects two or more failures into an AggregateError\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst one = new Error(\"handler one failed\");\n\t\t\t\tconst two = new Error(\"handler two failed\");\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tthrow one;\n\t\t\t\t});\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tthrow two;\n\t\t\t\t});\n\n\t\t\t\tconst thrown = await captureRejection(bus.publish([first()]));\n\n\t\t\t\tassert(\n\t\t\t\t\tthrown instanceof AggregateError,\n\t\t\t\t\t\"two failures must reach the caller as an AggregateError\",\n\t\t\t\t);\n\t\t\t\t// The port promises that every failure is carried, not the order\n\t\t\t\t// they are carried in. Ordering is an implementation choice.\n\t\t\t\tassertEqual(\n\t\t\t\t\tthrown.errors.length,\n\t\t\t\t\t2,\n\t\t\t\t\t\"the AggregateError carries every failure\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tthrown.errors.includes(one) && thrown.errors.includes(two),\n\t\t\t\t\t\"the AggregateError carries both failures\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"publishes the remaining events of a batch after a failure\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType, secondType } = types();\n\t\t\t\tconst seen: string[] = [];\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tthrow new Error(\"first handler failed\");\n\t\t\t\t});\n\t\t\t\tbus.subscribe(secondType, async (event) => {\n\t\t\t\t\tseen.push(event.type);\n\t\t\t\t});\n\n\t\t\t\tawait captureRejection(bus.publish([first(), second()]));\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tseen.join(\",\"),\n\t\t\t\t\tsecondType,\n\t\t\t\t\t\"a failure does not stop the remaining events of the batch\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"treats a handler that throws synchronously as a rejection\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst seen: string[] = [];\n\t\t\t\tbus.subscribe(firstType, () => {\n\t\t\t\t\tthrow new Error(\"thrown synchronously\");\n\t\t\t\t});\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tseen.push(\"peer\");\n\t\t\t\t});\n\n\t\t\t\tconst thrown = await captureRejection(bus.publish([first()]));\n\n\t\t\t\tassert(thrown instanceof Error, \"the throw must reach the caller\");\n\t\t\t\tassertEqual(\n\t\t\t\t\tseen.join(\",\"),\n\t\t\t\t\t\"peer\",\n\t\t\t\t\t\"a synchronous throw does not skip the peers\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"hands every subscriber the same event object\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst received: unknown[] = [];\n\t\t\t\tbus.subscribe(firstType, (event) => {\n\t\t\t\t\treceived.push(event);\n\t\t\t\t});\n\t\t\t\tbus.subscribeAll((event) => {\n\t\t\t\t\treceived.push(event);\n\t\t\t\t});\n\n\t\t\t\tconst published = first();\n\t\t\t\tawait bus.publish([published]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\treceived.length,\n\t\t\t\t\t2,\n\t\t\t\t\t\"both subscriptions must receive the event\",\n\t\t\t\t);\n\t\t\t\tfor (const one of received) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tone === published,\n\t\t\t\t\t\t\"every subscriber receives the published event itself, so its metadata cannot differ between them\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"delivers every type of a subscribed set to one handler\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType, secondType } = types();\n\t\t\t\tconst seen: string[] = [];\n\t\t\t\tbus.subscribeMany([firstType, secondType], (event) => {\n\t\t\t\t\tseen.push(event.type);\n\t\t\t\t});\n\n\t\t\t\tawait bus.publish([first(), second()]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tseen.join(\",\"),\n\t\t\t\t\t[firstType, secondType].join(\",\"),\n\t\t\t\t\t\"a set subscription receives every type in the set\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"releases every subscription of a set with one call\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType, secondType } = types();\n\t\t\t\tconst seen: string[] = [];\n\t\t\t\tconst release = bus.subscribeMany([firstType, secondType], (event) => {\n\t\t\t\t\tseen.push(event.type);\n\t\t\t\t});\n\n\t\t\t\trelease();\n\t\t\t\tawait bus.publish([first(), second()]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tseen.length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"one release must remove every subscription the set made\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"subscribes a repeated type of a set once\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tlet calls = 0;\n\t\t\t\tbus.subscribeMany([firstType, firstType], () => {\n\t\t\t\t\tcalls++;\n\t\t\t\t});\n\n\t\t\t\tawait bus.publish([first()]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tcalls,\n\t\t\t\t\t1,\n\t\t\t\t\t\"the argument is a set, so a repeated type subscribes once\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"delivers every event type to a catch-all subscription\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType, secondType } = types();\n\t\t\t\tconst seen: string[] = [];\n\t\t\t\tbus.subscribeAll(async (event) => {\n\t\t\t\t\tseen.push(event.type);\n\t\t\t\t});\n\n\t\t\t\tawait bus.publish([first(), second()]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tseen.join(\",\"),\n\t\t\t\t\t[firstType, secondType].join(\",\"),\n\t\t\t\t\t\"a catch-all subscription receives every event type\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"runs a catch-all handler in the same batch as the typed handlers\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst seen: string[] = [];\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tthrow new Error(\"typed handler failed\");\n\t\t\t\t});\n\t\t\t\tbus.subscribeAll(async () => {\n\t\t\t\t\tseen.push(\"catch-all\");\n\t\t\t\t});\n\n\t\t\t\tawait captureRejection(bus.publish([first()]));\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tseen.join(\",\"),\n\t\t\t\t\t\"catch-all\",\n\t\t\t\t\t\"a catch-all handler runs in the same batch as the typed ones\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"removes exactly one subscription when the same handler subscribed twice\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tlet calls = 0;\n\t\t\t\tconst handler = async () => {\n\t\t\t\t\tcalls++;\n\t\t\t\t};\n\t\t\t\tconst release = bus.subscribe(firstType, handler);\n\t\t\t\tbus.subscribe(firstType, handler);\n\n\t\t\t\trelease();\n\t\t\t\tawait bus.publish([first()]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tcalls,\n\t\t\t\t\t1,\n\t\t\t\t\t\"unsubscribe removes exactly one of two identical subscriptions\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"ignores a second call of the unsubscribe function\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tlet calls = 0;\n\t\t\t\tconst release = bus.subscribe(firstType, async () => {\n\t\t\t\t\tcalls++;\n\t\t\t\t});\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tcalls++;\n\t\t\t\t});\n\n\t\t\t\trelease();\n\t\t\t\trelease();\n\t\t\t\tawait bus.publish([first()]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tcalls,\n\t\t\t\t\t1,\n\t\t\t\t\t\"a second unsubscribe removes no further subscription\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"resolves once() with the next event of its type and stops after it\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tlet deliveries = 0;\n\t\t\t\tbus.subscribeAll(async () => {\n\t\t\t\t\tdeliveries++;\n\t\t\t\t});\n\t\t\t\tconst waiting = bus.once(firstType);\n\n\t\t\t\tconst announced = first();\n\t\t\t\tawait bus.publish([announced]);\n\t\t\t\tconst received = await waiting;\n\t\t\t\tawait bus.publish([first()]);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\treceived.eventId,\n\t\t\t\t\tannounced.eventId,\n\t\t\t\t\t\"once() resolves with the first event of that type\",\n\t\t\t\t);\n\t\t\t\t// The catch-all proves the second publication happened, so the\n\t\t\t\t// subscription of once() is gone rather than never reached.\n\t\t\t\tassertEqual(\n\t\t\t\t\tdeliveries,\n\t\t\t\t\t2,\n\t\t\t\t\t\"the second publication must still reach the bus\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"rejects once() when its timeout expires\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst thrown = await captureRejection(\n\t\t\t\t\tbus.once(firstType, { timeoutMs: 5 }),\n\t\t\t\t);\n\n\t\t\t\tassert(thrown !== undefined, \"once() must reject after its timeout\");\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"rejects once() with the reason of an aborted signal\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst controller = new AbortController();\n\t\t\t\tconst reason = new Error(\"the caller stopped waiting\");\n\t\t\t\tconst waiting = captureRejection(\n\t\t\t\t\tbus.once(firstType, { signal: controller.signal }),\n\t\t\t\t);\n\n\t\t\t\tcontroller.abort(reason);\n\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait waiting,\n\t\t\t\t\treason,\n\t\t\t\t\t\"once() rejects with the reason of the signal\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"rejects a publication whose signal is already aborted\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tconst controller = new AbortController();\n\t\t\t\tcontroller.abort(new Error(\"stopped before publish\"));\n\t\t\t\tlet called = false;\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tcalled = true;\n\t\t\t\t});\n\n\t\t\t\tconst thrown = await captureRejection(\n\t\t\t\t\tbus.publish([first()], { signal: controller.signal }),\n\t\t\t\t);\n\n\t\t\t\tassert(thrown !== undefined, \"an aborted publication must reject\");\n\t\t\t\tassertEqual(\n\t\t\t\t\tcalled,\n\t\t\t\t\tfalse,\n\t\t\t\t\t\"an aborted publication dispatches no handler\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"refuses every operation after close\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tbus.close();\n\n\t\t\t\tlet subscribeThrew = false;\n\t\t\t\ttry {\n\t\t\t\t\tbus.subscribe(firstType, () => {});\n\t\t\t\t} catch {\n\t\t\t\t\tsubscribeThrew = true;\n\t\t\t\t}\n\t\t\t\tlet subscribeAllThrew = false;\n\t\t\t\ttry {\n\t\t\t\t\tbus.subscribeAll(() => {});\n\t\t\t\t} catch {\n\t\t\t\t\tsubscribeAllThrew = true;\n\t\t\t\t}\n\n\t\t\t\tassert(subscribeThrew, \"subscribe must refuse a closed bus\");\n\t\t\t\tassert(subscribeAllThrew, \"subscribeAll must refuse a closed bus\");\n\t\t\t\tassert(\n\t\t\t\t\t(await captureRejection(bus.publish([first()]))) !== undefined,\n\t\t\t\t\t\"publish must refuse a closed bus\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\t(await captureRejection(bus.once(firstType))) !== undefined,\n\t\t\t\t\t\"once must refuse a closed bus\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"settles a pending once() when the bus closes\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\t// Without a timeout and without a signal this waiter has no\n\t\t\t\t// other way to end.\n\t\t\t\tconst waiting = captureRejection(bus.once(firstType));\n\n\t\t\t\tbus.close();\n\n\t\t\t\tassert(\n\t\t\t\t\t(await waiting) !== undefined,\n\t\t\t\t\t\"closing must settle a pending once()\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"does nothing when close is called again\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tbus.close();\n\n\t\t\t\tlet threw = false;\n\t\t\t\ttry {\n\t\t\t\t\tbus.close();\n\t\t\t\t} catch {\n\t\t\t\t\tthrew = true;\n\t\t\t\t}\n\n\t\t\t\tassert(threw === false, \"a second close must do nothing\");\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"bounds the wait, not the handler, when the timeout expires\",\n\t\t\trun: inEnv(async ({ bus }: Env) => {\n\t\t\t\tconst { firstType } = types();\n\t\t\t\tlet running = true;\n\t\t\t\tbus.subscribe(firstType, async () => {\n\t\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, 200));\n\t\t\t\t\trunning = false;\n\t\t\t\t});\n\n\t\t\t\tconst thrown = await captureRejection(\n\t\t\t\t\tbus.publish([first()], { timeoutMs: 10 }),\n\t\t\t\t);\n\n\t\t\t\tassert(thrown !== undefined, \"the publication must reject\");\n\t\t\t\tassertEqual(\n\t\t\t\t\trunning,\n\t\t\t\t\ttrue,\n\t\t\t\t\t\"the timeout bounds the wait, so the handler keeps running\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t];\n}\n","import type { AggregateAddress } from \"../domain/aggregate/aggregate-address\";\nimport type { AnyDomainEvent } from \"../domain/event/domain-event\";\nimport type { EventStore } from \"../persistence/event-store/event-store\";\nimport {\n\tassert,\n\tassertChainContainsKitError,\n\tbindContractEnvironment,\n\ttype ContractTest,\n\tcaptureRejection,\n} from \"./contract-assertions\";\n\n/** One named contract test for an EventStore adapter. */\nexport type EventStoreContractTest = ContractTest;\n\n/** One isolated adapter instance. The suite creates one per test. */\nexport interface EventStoreContractEnvironment<Evt extends AnyDomainEvent> {\n\treadonly store: EventStore<Evt>;\n\tteardown?(): Promise<void>;\n}\n\n/**\n * Inputs needed to prove the EventStore's observable port contract.\n *\n * `createCollidingStreamKeys` must return two valid stream keys with the same\n * raw aggregate id and different aggregate types. `createEvent` must return an\n * event addressed to the supplied key; different sequence values must produce\n * different event ids.\n */\nexport interface EventStoreContractHarness<Evt extends AnyDomainEvent> {\n\tcreateEnvironment(): Promise<EventStoreContractEnvironment<Evt>>;\n\tcreateCollidingStreamKeys(): readonly [AggregateAddress, AggregateAddress];\n\tcreateEvent(stream: AggregateAddress, sequence: number): Evt;\n}\n\n/**\n * Reusable proof of an EventStore adapter's portable semantics: qualified\n * value identity, ordered reads and slicing, OCC error mapping and atomicity,\n * no-op empty appends, and detached return arrays. Physical-position\n * corruption needs adapter-specific fixture support and is tested there.\n */\nexport function createEventStoreContractTests<Evt extends AnyDomainEvent>(\n\tharness: EventStoreContractHarness<Evt>,\n): EventStoreContractTest[] {\n\tconst inEnv = bindContractEnvironment(() => harness.createEnvironment());\n\tconst fixtureRead = { limit: 100 } as const;\n\tconst hasSameEventIds = (\n\t\tactual: ReadonlyArray<Evt>,\n\t\texpected: ReadonlyArray<Evt>,\n\t): boolean =>\n\t\tactual.length === expected.length &&\n\t\tactual.every((event, index) => event.eventId === expected[index]?.eventId);\n\n\treturn [\n\t\t{\n\t\t\tname: \"unknown stream: read reports explicit absence at version zero\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst missing = await store.readStream({ ...firstKey }, fixtureRead);\n\t\t\t\tassert(\n\t\t\t\t\t!missing.exists &&\n\t\t\t\t\t\tmissing.lastVersion === 0 &&\n\t\t\t\t\t\tmissing.events.length === 0,\n\t\t\t\t\t\"an unknown qualified stream must return the explicit missing state\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"empty append: no version check and no stream creation\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tawait store.append(firstKey, [], { expectedVersion: 999 });\n\t\t\t\tconst event = harness.createEvent(firstKey, 1);\n\t\t\t\tawait store.append({ ...firstKey }, [event], { expectedVersion: 0 });\n\t\t\t\tconst stored = await store.readStream(firstKey, fixtureRead);\n\t\t\t\tassert(\n\t\t\t\t\tstored.exists &&\n\t\t\t\t\t\tstored.lastVersion === 1 &&\n\t\t\t\t\t\tstored.events.length === 1 &&\n\t\t\t\t\t\tstored.events[0]?.eventId === event.eventId,\n\t\t\t\t\t\"an empty append must not check OCC or create an empty stream\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"qualified stream key: equal aggregate ids remain isolated by aggregate type\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey, secondKey] = harness.createCollidingStreamKeys();\n\t\t\t\tassert(\n\t\t\t\t\tfirstKey.aggregateId === secondKey.aggregateId,\n\t\t\t\t\t\"createCollidingStreamKeys must return equal raw aggregate ids\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tfirstKey.aggregateType !== secondKey.aggregateType,\n\t\t\t\t\t\"createCollidingStreamKeys must return different aggregate types\",\n\t\t\t\t);\n\n\t\t\t\tconst firstEvent = harness.createEvent(firstKey, 1);\n\t\t\t\tconst secondEvent = harness.createEvent(secondKey, 2);\n\t\t\t\tassert(\n\t\t\t\t\tfirstEvent.eventId !== secondEvent.eventId,\n\t\t\t\t\t\"createEvent must produce different event ids for different sequence values\",\n\t\t\t\t);\n\n\t\t\t\tawait store.append(firstKey, [firstEvent], { expectedVersion: 0 });\n\t\t\t\tawait store.append(secondKey, [secondEvent], { expectedVersion: 0 });\n\n\t\t\t\tconst firstStream = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\tfixtureRead,\n\t\t\t\t);\n\t\t\t\tconst secondStream = await store.readStream(\n\t\t\t\t\t{ ...secondKey },\n\t\t\t\t\tfixtureRead,\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tfirstStream.exists &&\n\t\t\t\t\t\tfirstStream.events.length === 1 &&\n\t\t\t\t\t\tfirstStream.events[0]?.eventId === firstEvent.eventId,\n\t\t\t\t\t\"the first aggregate type must retain only its own event; key objects are value addresses, not identity tokens\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tsecondStream.exists &&\n\t\t\t\t\t\tsecondStream.events.length === 1 &&\n\t\t\t\t\t\tsecondStream.events[0]?.eventId === secondEvent.eventId,\n\t\t\t\t\t\"the second aggregate type must retain only its own event when the raw id collides\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"append/read: event order and fromVersion slicing are preserved\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst events = [1, 2, 3].map((sequence) =>\n\t\t\t\t\tharness.createEvent(firstKey, sequence),\n\t\t\t\t);\n\t\t\t\tawait store.append(firstKey, events, { expectedVersion: 0 });\n\t\t\t\tconst whole = await store.readStream({ ...firstKey }, fixtureRead);\n\t\t\t\tconst afterTwo = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{\n\t\t\t\t\t\t...fixtureRead,\n\t\t\t\t\t\tfromVersion: 2,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\twhole.exists &&\n\t\t\t\t\t\twhole.lastVersion === 3 &&\n\t\t\t\t\t\thasSameEventIds(whole.events, events),\n\t\t\t\t\t\"reads must preserve append order\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tafterTwo.exists &&\n\t\t\t\t\t\tafterTwo.lastVersion === 3 &&\n\t\t\t\t\t\tafterTwo.events.length === 1 &&\n\t\t\t\t\t\tafterTwo.events[0]?.eventId === events[2]?.eventId,\n\t\t\t\t\t\"fromVersion 2 must return exactly the events after the first two positions\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"paged read: limit bounds every page and fromVersion continues without gaps or duplicates\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst events = [1, 2, 3, 4, 5].map((sequence) =>\n\t\t\t\t\tharness.createEvent(firstKey, sequence),\n\t\t\t\t);\n\t\t\t\tawait store.append(firstKey, events, { expectedVersion: 0 });\n\n\t\t\t\tconst collected: Evt[] = [];\n\t\t\t\tlet cursor = 0;\n\t\t\t\tlet targetHead: number | undefined;\n\t\t\t\tfor (let attempt = 0; attempt < events.length; attempt += 1) {\n\t\t\t\t\tconst page = await store.readStream(\n\t\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfromVersion: cursor,\n\t\t\t\t\t\t\tlimit: 2,\n\t\t\t\t\t\t\t...(targetHead === undefined ? {} : { toVersion: targetHead }),\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tpage.exists,\n\t\t\t\t\t\t\"a paged read of an existing stream must retain existence\",\n\t\t\t\t\t);\n\t\t\t\t\ttargetHead ??= page.lastVersion;\n\t\t\t\t\tassert(\n\t\t\t\t\t\tpage.lastVersion >= targetHead,\n\t\t\t\t\t\t\"lastVersion must keep reporting at least the head pinned by the first page\",\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tpage.events.length > 0 && page.events.length <= 2,\n\t\t\t\t\t\t\"an unread page must make progress without exceeding the requested limit\",\n\t\t\t\t\t);\n\t\t\t\t\tcollected.push(...page.events);\n\t\t\t\t\tcursor += page.events.length;\n\t\t\t\t\tif (cursor >= targetHead) break;\n\t\t\t\t}\n\n\t\t\t\tassert(\n\t\t\t\t\ttargetHead === events.length && cursor === targetHead,\n\t\t\t\t\t\"following fromVersion by each actual page length must reach the pinned head\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\thasSameEventIds(collected, events),\n\t\t\t\t\t\"paged continuation must reproduce append order without gaps or duplicates\",\n\t\t\t\t);\n\t\t\t\tconst atEnd = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{ fromVersion: cursor, toVersion: targetHead, limit: 2 },\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tatEnd.exists && atEnd.events.length === 0,\n\t\t\t\t\t\"continuing at the pinned head must return an existing empty page\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"read options: invalid limits and stream positions fail loudly\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst invalidOptions: unknown[] = [\n\t\t\t\t\t{},\n\t\t\t\t\t{ limit: 0 },\n\t\t\t\t\t{ limit: 1.5 },\n\t\t\t\t\t{ limit: Number.MAX_SAFE_INTEGER + 1 },\n\t\t\t\t\t{ limit: 1, fromVersion: -1 },\n\t\t\t\t\t{ limit: 1, fromVersion: 1.5 },\n\t\t\t\t\t{ limit: 1, fromVersion: Number.MAX_SAFE_INTEGER + 1 },\n\t\t\t\t\t{ limit: 1, toVersion: -1 },\n\t\t\t\t\t{ limit: 1, toVersion: 1.5 },\n\t\t\t\t\t{ limit: 1, toVersion: Number.MAX_SAFE_INTEGER + 1 },\n\t\t\t\t];\n\n\t\t\t\tfor (const options of invalidOptions) {\n\t\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\t\tstore.readStream(firstKey, options as never),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\trejection instanceof RangeError,\n\t\t\t\t\t\t\"invalid read bounds must reject with RangeError before querying the stream\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"bounded read: toVersion is inclusive while lastVersion remains the actual head\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst events = [1, 2, 3, 4].map((sequence) =>\n\t\t\t\t\tharness.createEvent(firstKey, sequence),\n\t\t\t\t);\n\t\t\t\tawait store.append(firstKey, events, { expectedVersion: 0 });\n\n\t\t\t\tconst bounded = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{ ...fixtureRead, fromVersion: 1, toVersion: 3 },\n\t\t\t\t);\n\n\t\t\t\tassert(\n\t\t\t\t\tbounded.exists &&\n\t\t\t\t\t\tbounded.lastVersion === 4 &&\n\t\t\t\t\t\thasSameEventIds(bounded.events, events.slice(1, 3)),\n\t\t\t\t\t\"(fromVersion, toVersion] must include positions 2 and 3 while lastVersion reports the actual head at 4\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"bounded read edges: zero, beyond-head, and inverted ranges are empty or clamped\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst events = [1, 2, 3].map((sequence) =>\n\t\t\t\t\tharness.createEvent(firstKey, sequence),\n\t\t\t\t);\n\t\t\t\tawait store.append(firstKey, events, { expectedVersion: 0 });\n\n\t\t\t\tconst atZero = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{ ...fixtureRead, toVersion: 0 },\n\t\t\t\t);\n\t\t\t\tconst beyondHead = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{ ...fixtureRead, toVersion: 99 },\n\t\t\t\t);\n\t\t\t\tconst inverted = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{ ...fixtureRead, fromVersion: 2, toVersion: 1 },\n\t\t\t\t);\n\t\t\t\tconst equalBounds = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{ ...fixtureRead, fromVersion: 2, toVersion: 2 },\n\t\t\t\t);\n\n\t\t\t\tassert(\n\t\t\t\t\tatZero.exists &&\n\t\t\t\t\t\tatZero.lastVersion === 3 &&\n\t\t\t\t\t\tatZero.events.length === 0,\n\t\t\t\t\t\"toVersion=0 must return an existing empty window with the actual head\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tbeyondHead.exists &&\n\t\t\t\t\t\tbeyondHead.lastVersion === 3 &&\n\t\t\t\t\t\thasSameEventIds(beyondHead.events, events),\n\t\t\t\t\t\"toVersion beyond the head must clamp to the actual stream head\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tinverted.exists &&\n\t\t\t\t\t\tinverted.lastVersion === 3 &&\n\t\t\t\t\t\tinverted.events.length === 0 &&\n\t\t\t\t\t\tequalBounds.exists &&\n\t\t\t\t\t\tequalBounds.lastVersion === 3 &&\n\t\t\t\t\t\tequalBounds.events.length === 0,\n\t\t\t\t\t\"fromVersion >= toVersion describes an empty interval and must not throw\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"read state: empty and beyond-head windows retain existence and the actual stream head\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tawait store.append(\n\t\t\t\t\tfirstKey,\n\t\t\t\t\t[harness.createEvent(firstKey, 4), harness.createEvent(firstKey, 5)],\n\t\t\t\t\t{ expectedVersion: 0 },\n\t\t\t\t);\n\n\t\t\t\tconst atHead = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{\n\t\t\t\t\t\t...fixtureRead,\n\t\t\t\t\t\tfromVersion: 2,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tconst beyondHead = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{\n\t\t\t\t\t\t...fixtureRead,\n\t\t\t\t\t\tfromVersion: 99,\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tfor (const result of [atHead, beyondHead]) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tresult.exists &&\n\t\t\t\t\t\t\tresult.lastVersion === 2 &&\n\t\t\t\t\t\t\tresult.events.length === 0,\n\t\t\t\t\t\t\"an empty read window must retain stream existence and report the actual head, even when fromVersion is beyond it\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"qualified fromVersion: slicing one type cannot observe a colliding raw id\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey, secondKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst firstEvents = [10, 11, 12].map((sequence) =>\n\t\t\t\t\tharness.createEvent(firstKey, sequence),\n\t\t\t\t);\n\t\t\t\tconst secondEvents = [20, 21].map((sequence) =>\n\t\t\t\t\tharness.createEvent(secondKey, sequence),\n\t\t\t\t);\n\t\t\t\tawait store.append(firstKey, firstEvents, { expectedVersion: 0 });\n\t\t\t\tawait store.append(secondKey, secondEvents, { expectedVersion: 0 });\n\t\t\t\tconst firstTail = await store.readStream(\n\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t{\n\t\t\t\t\t\t...fixtureRead,\n\t\t\t\t\t\tfromVersion: 1,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tconst secondTail = await store.readStream(\n\t\t\t\t\t{ ...secondKey },\n\t\t\t\t\t{\n\t\t\t\t\t\t...fixtureRead,\n\t\t\t\t\t\tfromVersion: 1,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tfirstTail.exists &&\n\t\t\t\t\t\tfirstTail.lastVersion === 3 &&\n\t\t\t\t\t\tfirstTail.events.length === 2 &&\n\t\t\t\t\t\tfirstTail.events[0]?.eventId === firstEvents[1]?.eventId &&\n\t\t\t\t\t\tfirstTail.events[1]?.eventId === firstEvents[2]?.eventId,\n\t\t\t\t\t\"fromVersion must slice only the requested aggregate type's stream\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tsecondTail.exists &&\n\t\t\t\t\t\tsecondTail.lastVersion === 2 &&\n\t\t\t\t\t\tsecondTail.events.length === 1 &&\n\t\t\t\t\t\tsecondTail.events[0]?.eventId === secondEvents[1]?.eventId,\n\t\t\t\t\t\"a colliding raw id under another type must retain its independent version window\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"OCC: a rejected multi-event append is atomic and maps to ConcurrencyConflictError\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst seeded = [\n\t\t\t\t\tharness.createEvent(firstKey, 30),\n\t\t\t\t\tharness.createEvent(firstKey, 31),\n\t\t\t\t];\n\t\t\t\tawait store.append(firstKey, seeded, { expectedVersion: 0 });\n\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\tstore.append(\n\t\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\tharness.createEvent(firstKey, 32),\n\t\t\t\t\t\t\tharness.createEvent(firstKey, 33),\n\t\t\t\t\t\t],\n\t\t\t\t\t\t{ expectedVersion: 1 },\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\trejection,\n\t\t\t\t\t[\"CONCURRENCY_CONFLICT\"],\n\t\t\t\t\t\"a stale append must map the adapter conflict to ConcurrencyConflictError\",\n\t\t\t\t);\n\t\t\t\tconst stored = await store.readStream(firstKey, fixtureRead);\n\t\t\t\tassert(\n\t\t\t\t\tstored.exists &&\n\t\t\t\t\t\tstored.lastVersion === 2 &&\n\t\t\t\t\t\tstored.events.length === 2 &&\n\t\t\t\t\t\tstored.events[0]?.eventId === seeded[0]?.eventId &&\n\t\t\t\t\t\tstored.events[1]?.eventId === seeded[1]?.eventId,\n\t\t\t\t\t\"a rejected multi-event append must leave the stream untouched\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"OCC: duplicate create is rejected atomically with a sanctioned kit error\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst seeded = harness.createEvent(firstKey, 50);\n\t\t\t\tawait store.append(firstKey, [seeded], { expectedVersion: 0 });\n\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\tstore.append(\n\t\t\t\t\t\t{ ...firstKey },\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\tharness.createEvent(firstKey, 51),\n\t\t\t\t\t\t\tharness.createEvent(firstKey, 52),\n\t\t\t\t\t\t],\n\t\t\t\t\t\t{ expectedVersion: 0 },\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\trejection,\n\t\t\t\t\t[\"CONCURRENCY_CONFLICT\", \"DUPLICATE_AGGREGATE\"],\n\t\t\t\t\t\"a duplicate create must map to ConcurrencyConflictError or the sanctioned DuplicateAggregateError\",\n\t\t\t\t);\n\t\t\t\tconst stored = await store.readStream(firstKey, fixtureRead);\n\t\t\t\tassert(\n\t\t\t\t\tstored.exists &&\n\t\t\t\t\t\tstored.lastVersion === 1 &&\n\t\t\t\t\t\tstored.events.length === 1 &&\n\t\t\t\t\t\tstored.events[0]?.eventId === seeded.eventId,\n\t\t\t\t\t\"a rejected duplicate-create batch must leave the existing stream untouched\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"OCC: an expectedVersion ahead of an unknown stream conflicts without creating it\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\tstore.append(firstKey, [harness.createEvent(firstKey, 60)], {\n\t\t\t\t\t\texpectedVersion: 3,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\trejection,\n\t\t\t\t\t[\"CONCURRENCY_CONFLICT\"],\n\t\t\t\t\t\"an expectedVersion ahead of the stream must map to ConcurrencyConflictError\",\n\t\t\t\t);\n\t\t\t\tconst first = harness.createEvent(firstKey, 61);\n\t\t\t\tawait store.append({ ...firstKey }, [first], { expectedVersion: 0 });\n\t\t\t\tconst stored = await store.readStream(firstKey, fixtureRead);\n\t\t\t\tassert(\n\t\t\t\t\tstored.exists &&\n\t\t\t\t\t\tstored.lastVersion === 1 &&\n\t\t\t\t\t\tstored.events.length === 1 &&\n\t\t\t\t\t\tstored.events[0]?.eventId === first.eventId,\n\t\t\t\t\t\"the rejected append must not leave an empty stream or partial events behind\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"read ownership: a mutation attempt cannot mutate the stream\",\n\t\t\trun: inEnv(async ({ store }) => {\n\t\t\t\tconst [firstKey] = harness.createCollidingStreamKeys();\n\t\t\t\tconst seeded = harness.createEvent(firstKey, 40);\n\t\t\t\tawait store.append(firstKey, [seeded], { expectedVersion: 0 });\n\t\t\t\tconst callerOwned = (await store.readStream(firstKey, fixtureRead))\n\t\t\t\t\t.events as Evt[];\n\t\t\t\ttry {\n\t\t\t\t\tcallerOwned.push(harness.createEvent(firstKey, 41));\n\t\t\t\t} catch {\n\t\t\t\t\t// A detached frozen array is also valid: the contract forbids exposing\n\t\t\t\t\t// mutable live state, not defensive immutability.\n\t\t\t\t}\n\t\t\t\tconst stored = await store.readStream({ ...firstKey }, fixtureRead);\n\t\t\t\tassert(\n\t\t\t\t\tstored.exists &&\n\t\t\t\t\t\tstored.events.length === 1 &&\n\t\t\t\t\t\tstored.events[0]?.eventId === seeded.eventId,\n\t\t\t\t\t\"readStream must return an owned array, never live internal state\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t];\n}\n","import type {\n\tIdempotencyClaim,\n\tIdempotencyClaimHandle,\n\tIdempotencyStore,\n} from \"../application/idempotency/idempotency\";\nimport { deepEqual } from \"../internal/structural/deep-equal\";\nimport {\n\tassert,\n\tassertChainContainsKitError,\n\tassertEqual,\n\tbindContractEnvironment,\n\ttype ContractTest,\n\tcaptureRejection,\n\tchainContainsRetryable,\n\tgatedContractTest,\n} from \"./contract-assertions\";\n\n/** One contract test; bind with `(test.skipped ? it.skip : it)(test.name, test.run)`. */\nexport type IdempotencyStoreContractTest = ContractTest;\n\n/**\n * One isolated test environment: a fresh idempotency store. The suite\n * creates one per test and tears it down afterwards.\n */\nexport interface IdempotencyStoreContractEnvironment<TCtx> {\n\t/** The adapter under test. */\n\tstore: IdempotencyStore<TCtx>;\n\n\t/**\n\t * Runs `work` inside a transaction that COMMITS, handing it the\n\t * transaction context the store methods expect, the way\n\t * `withIdempotentCommit` calls them in production. For a\n\t * non-transactional store this simply invokes `work` with a dummy\n\t * context.\n\t */\n\trun<R>(work: (ctx: TCtx) => Promise<R>): Promise<R>;\n\n\t/**\n\t * For the `\"transactional\"` family: runs `work` inside a transaction\n\t * that ROLLS BACK. Required there; the rollback-releases-the-claim\n\t * test is that family's core proof. Irrelevant for the\n\t * `\"non-transactional\"` family.\n\t */\n\trunRolledBack?<R>(work: (ctx: TCtx) => Promise<R>): Promise<R>;\n\n\t/**\n\t * For the `\"non-transactional\"` family: advances or edits adapter test\n\t * state so this exact claim's CURRENT lease is expired. Required there;\n\t * a fake clock or test-only row update keeps the suite deterministic.\n\t */\n\texpireLease?(claim: IdempotencyClaimHandle): Promise<void>;\n\n\t/**\n\t * Moves the adapter's test clock to an exact instant. Required by the\n\t * non-transactional family so renewal is proved without wall-clock sleeps.\n\t */\n\tadvanceTimeTo?(instant: Date): Promise<void>;\n\n\t/** Release connections, drop schemas, etc. Called in a finally. */\n\tteardown?(): Promise<void>;\n}\n\n/**\n * What an adapter supplies to run the idempotency-store contract suite.\n *\n * The port (`IdempotencyStore`) deliberately supports two adapter\n * families with different lifecycle semantics, and the suite follows\n * the declared family instead of forcing one onto the other:\n *\n * - `\"transactional\"` (the single-transaction pattern): the record\n * lives in the same database as the aggregates; a committed\n * `complete` is final and replayable, a rollback releases everything,\n * and `renew`/`confirm`/`abandon`/`reconcile` are no-ops. The family's core proof is the\n * rollback test, so environments MUST provide `runRolledBack`, and\n * run against a real database for SQL adapters.\n * - `\"non-transactional\"` (the leased two-phase pattern, e.g. the\n * in-memory reference): the store cannot see commits, so `complete` only\n * STAGES the outcome, `confirm` finalizes it post-commit, `abandon`\n * compensates failed attempts, and expired staged records require\n * reconciliation. Environments MUST provide deterministic `expireLease` and\n * `advanceTimeTo` controls. The rollback test is skipped.\n */\nexport interface IdempotencyStoreContractHarness<TCtx> {\n\tcreateEnvironment(): Promise<IdempotencyStoreContractEnvironment<TCtx>>;\n\n\t/** Which lifecycle family the adapter implements; see above. */\n\tfamily: \"transactional\" | \"non-transactional\";\n}\n\nfunction claimedHandle(\n\tclaim: IdempotencyClaim,\n\tmessage: string,\n): IdempotencyClaimHandle {\n\tassert(claim.status === \"claimed\", message);\n\treturn claim.claim;\n}\n\nasync function expireLease<TCtx>(\n\tenv: IdempotencyStoreContractEnvironment<TCtx>,\n\tclaim: IdempotencyClaimHandle,\n): Promise<void> {\n\tif (!env.expireLease) {\n\t\tthrow new Error(\n\t\t\t\"Contract violated: the non-transactional family requires expireLease on the environment\",\n\t\t);\n\t}\n\tawait env.expireLease(claim);\n}\n\nasync function advanceTimeTo<TCtx>(\n\tenv: IdempotencyStoreContractEnvironment<TCtx>,\n\tinstant: Date,\n): Promise<void> {\n\tif (!env.advanceTimeTo) {\n\t\tthrow new Error(\n\t\t\t\"Contract violated: the non-transactional family requires advanceTimeTo on the environment\",\n\t\t);\n\t}\n\tawait env.advanceTimeTo(instant);\n}\n\n/**\n * The idempotency-store contract test suite: the proof that an adapter\n * delivers the claim/renew/complete/confirm/abandon/reconcile lifecycle\n * `withIdempotentCommit` documents, for its declared family. Store\n * semantics are an **adapter contract, not a kit guarantee**; this\n * suite is how an adapter demonstrates them.\n *\n * Framework-agnostic: bind with\n * `(test.skipped ? it.skip : it)(test.name, test.run)`.\n */\nexport function createIdempotencyStoreContractTests<TCtx>(\n\tharness: IdempotencyStoreContractHarness<TCtx>,\n): IdempotencyStoreContractTest[] {\n\tconst inEnv = bindContractEnvironment(() => harness.createEnvironment());\n\n\t// Shared tests: hold for BOTH families (confirm/abandon are no-ops in\n\t// the transactional family, which these tests tolerate by design).\n\tconst tests: IdempotencyStoreContractTest[] = [\n\t\t{\n\t\t\tname: \"a fresh key is claimed; the full lifecycle replays the outcome\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\tawait env.run((ctx) => env.store.claim(ctx, \"key-1\", \"fp-1\")),\n\t\t\t\t\t\"a fresh key must be claimed by this execution\",\n\t\t\t\t);\n\t\t\t\tawait env.run((ctx) => env.store.complete(ctx, claim, { total: 42 }));\n\t\t\t\tawait env.store.confirm(claim);\n\t\t\t\tconst replay = await env.run((ctx) =>\n\t\t\t\t\tenv.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\treplay.status === \"completed\",\n\t\t\t\t\t\"a completed and confirmed key must replay as completed\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(replay.outcome, { total: 42 }),\n\t\t\t\t\t\"the replayed outcome must round-trip the stored value\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"the same key with a different fingerprint throws IdempotencyKeyReuseError\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\t// Built on a COMPLETED record: the one same-key/other-command\n\t\t\t\t// state both families can actually reach in production (a\n\t\t\t\t// transactional store never commits a bare pending claim).\n\t\t\t\tconst first = await env.run(async (ctx) => {\n\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\tawait env.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.complete(ctx, claim, \"done\");\n\t\t\t\t\treturn claim;\n\t\t\t\t});\n\t\t\t\tawait env.store.confirm(first);\n\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\tenv.run((ctx) => env.store.claim(ctx, \"key-1\", \"fp-OTHER\")),\n\t\t\t\t);\n\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\trejection,\n\t\t\t\t\t[\"IDEMPOTENCY_KEY_REUSE\"],\n\t\t\t\t\t\"a different fingerprint must throw IdempotencyKeyReuseError, never replay another command's outcome\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"abandon never destroys a completed, confirmed outcome\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst first = await env.run(async (ctx) => {\n\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\tawait env.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.complete(ctx, claim, \"done\");\n\t\t\t\t\treturn claim;\n\t\t\t\t});\n\t\t\t\tawait env.store.confirm(first);\n\t\t\t\tawait env.store.abandon(first);\n\t\t\t\tconst claim = await env.run((ctx) =>\n\t\t\t\t\tenv.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tclaim.status === \"completed\",\n\t\t\t\t\t\"abandon must not release a completed, confirmed record\",\n\t\t\t\t);\n\t\t\t\tassertEqual(claim.outcome, \"done\", \"the outcome survives\");\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"confirm is idempotent, and confirming a missing key is a no-op\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst first = await env.run(async (ctx) => {\n\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\tawait env.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.complete(ctx, claim, \"done\");\n\t\t\t\t\treturn claim;\n\t\t\t\t});\n\t\t\t\tawait env.store.confirm(first);\n\t\t\t\tawait env.store.confirm(first);\n\t\t\t\tawait env.store.confirm({ key: \"never-claimed\", token: \"missing\" });\n\t\t\t\tconst claim = await env.run((ctx) =>\n\t\t\t\t\tenv.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tclaim.status === \"completed\" && claim.outcome === \"done\",\n\t\t\t\t\t\"re-confirms and unknown-key confirms must change nothing\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"complete without a pending claim throws the wiring error\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\tenv.run((ctx) =>\n\t\t\t\t\t\tenv.store.complete(ctx, { key: \"key-1\", token: \"missing\" }, \"x\"),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\trejection,\n\t\t\t\t\t[\"IDEMPOTENCY_COMPLETED_WITHOUT_CLAIM\"],\n\t\t\t\t\t\"complete() without claim() must throw IdempotencyCompletionWithoutClaimError\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t];\n\n\tconst nonTransactional = harness.family === \"non-transactional\";\n\n\t// The commit-is-the-finalize proof only EXISTS for the transactional\n\t// family; a two-phase store must do the OPPOSITE (an unconfirmed\n\t// staged outcome stays in-flight), so there is no skip twin for it.\n\tif (!nonTransactional) {\n\t\ttests.push({\n\t\t\tname: \"a committed complete replays even without confirm (commit is the finalize)\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(async (ctx) => {\n\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\tawait env.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.complete(ctx, claim, \"done\");\n\t\t\t\t});\n\t\t\t\t// No confirm: for a transactional store the commit already\n\t\t\t\t// finalized the record.\n\t\t\t\tconst claim = await env.run((ctx) =>\n\t\t\t\t\tenv.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tclaim.status === \"completed\" && claim.outcome === \"done\",\n\t\t\t\t\t\"a committed complete must replay without a confirm call\",\n\t\t\t\t);\n\t\t\t}),\n\t\t});\n\t}\n\n\ttests.push(\n\t\t// A committed-yet-pending claim is a state only the two-phase family\n\t\t// can reach (its claims commit immediately). In the\n\t\t// single-transaction pattern, concurrent claimers collide on the row\n\t\t// lock of an UNCOMMITTED insert, which a sequential suite cannot\n\t\t// portably provoke, and a committed bare claim is legitimately\n\t\t// treated as a stale crash leftover an adapter may reclaim.\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"family: non-transactional\",\n\t\t\t\tsatisfiedBy: nonTransactional,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"a pending claim is in-flight for concurrent claimers, and the error is retryable\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tawait env.run((ctx) => env.store.claim(ctx, \"key-1\", \"fp-1\"));\n\t\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\t\tenv.run((ctx) => env.store.claim(ctx, \"key-1\", \"fp-1\")),\n\t\t\t\t\t);\n\t\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\t\trejection,\n\t\t\t\t\t\t[\"IDEMPOTENCY_IN_FLIGHT\"],\n\t\t\t\t\t\t\"claiming a pending key must throw IdempotencyInFlightError\",\n\t\t\t\t\t);\n\t\t\t\t\t// Chain-walked like the kit's retry classifier: an adapter may\n\t\t\t\t\t// wrap the kit error, exactly as the code-based check above\n\t\t\t\t\t// tolerates, and a consumer's retry loop still sees retryable.\n\t\t\t\t\tassert(\n\t\t\t\t\t\tchainContainsRetryable(rejection),\n\t\t\t\t\t\t\"the in-flight error must be retryable (on the rejection or its cause chain)\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"family: non-transactional\",\n\t\t\t\tsatisfiedBy: nonTransactional,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"renew extends ownership beyond the original lease expiry\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\tawait env.run((ctx) => env.store.claim(ctx, \"key-renew\", \"fp\")),\n\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tclaim.lease !== undefined,\n\t\t\t\t\t\t\"a non-transactional claim must carry lease timing\",\n\t\t\t\t\t);\n\t\t\t\t\tconst originalExpiry = new Date(claim.lease.expiresAt).getTime();\n\t\t\t\t\tassert(\n\t\t\t\t\t\tNumber.isFinite(originalExpiry) &&\n\t\t\t\t\t\t\tnew Date(originalExpiry).toISOString() ===\n\t\t\t\t\t\t\t\tclaim.lease.expiresAt &&\n\t\t\t\t\t\t\tNumber.isSafeInteger(claim.lease.renewAfterMs) &&\n\t\t\t\t\t\t\tclaim.lease.renewAfterMs > 0,\n\t\t\t\t\t\t\"lease timing must carry a valid expiry and positive safe renewal delay\",\n\t\t\t\t\t);\n\t\t\t\t\tawait advanceTimeTo(env, new Date(originalExpiry - 1));\n\t\t\t\t\tconst renewed = await env.store.renew(claim);\n\t\t\t\t\tassert(\n\t\t\t\t\t\trenewed !== undefined &&\n\t\t\t\t\t\t\tnew Date(renewed.expiresAt).getTime() > originalExpiry,\n\t\t\t\t\t\t\"renew must extend the lease beyond its previous expiry\",\n\t\t\t\t\t);\n\t\t\t\t\tawait advanceTimeTo(env, new Date(originalExpiry + 1));\n\t\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\t\tenv.run((ctx) => env.store.claim(ctx, \"key-renew\", \"fp\")),\n\t\t\t\t\t);\n\t\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\t\trejection,\n\t\t\t\t\t\t[\"IDEMPOTENCY_IN_FLIGHT\"],\n\t\t\t\t\t\t\"the renewed owner must still hold the key after the original expiry\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"family: non-transactional\",\n\t\t\t\tsatisfiedBy: nonTransactional,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"an expired pending lease is reclaimed under a new token and fences its stale owner\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tconst first = claimedHandle(\n\t\t\t\t\t\tawait env.run((ctx) => env.store.claim(ctx, \"key-1\", \"fp-1\")),\n\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tfirst.lease !== undefined,\n\t\t\t\t\t\t\"a non-transactional claim must carry lease timing\",\n\t\t\t\t\t);\n\t\t\t\t\tawait expireLease(env, first);\n\t\t\t\t\tconst successor = claimedHandle(\n\t\t\t\t\t\tawait env.run((ctx) => env.store.claim(ctx, \"key-1\", \"fp-1\")),\n\t\t\t\t\t\t\"an expired pending claim must be reclaimed\",\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tsuccessor.token !== first.token,\n\t\t\t\t\t\t\"each ownership generation must have a different token\",\n\t\t\t\t\t);\n\t\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\t\tenv.run((ctx) => env.store.complete(ctx, first, \"stale\")),\n\t\t\t\t\t);\n\t\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\t\trejection,\n\t\t\t\t\t\t[\"IDEMPOTENCY_CLAIM_LOST\"],\n\t\t\t\t\t\t\"a stale owner must fail before it can complete after takeover\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"family: non-transactional\",\n\t\t\t\tsatisfiedBy: nonTransactional,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"an expired staged outcome requires reconciliation and never auto-replays\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tconst first = await env.run(async (ctx) => {\n\t\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\t\tawait env.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait env.store.complete(ctx, claim, \"uncertain\");\n\t\t\t\t\t\treturn claim;\n\t\t\t\t\t});\n\t\t\t\t\tawait expireLease(env, first);\n\t\t\t\t\tconst claim = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tclaim.status === \"reconciliation-required\",\n\t\t\t\t\t\t\"an expired staged outcome must require authoritative reconciliation\",\n\t\t\t\t\t);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tclaim.reconciliation.token,\n\t\t\t\t\t\tfirst.token,\n\t\t\t\t\t\t\"the reconciliation receipt identifies the staged owner\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"family: non-transactional\",\n\t\t\t\tsatisfiedBy: nonTransactional,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"reconciliation confirms committed work or releases proven rollback\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tconst committedHandle = await env.run(async (ctx) => {\n\t\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\t\tawait env.store.claim(ctx, \"committed\", \"fp\"),\n\t\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait env.store.complete(ctx, claim, \"winner\");\n\t\t\t\t\t\treturn claim;\n\t\t\t\t\t});\n\t\t\t\t\tawait expireLease(env, committedHandle);\n\t\t\t\t\tconst committed = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.claim(ctx, \"committed\", \"fp\"),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tcommitted.status === \"reconciliation-required\",\n\t\t\t\t\t\t\"the staged outcome must expose its reconciliation receipt\",\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.reconcile(committed.reconciliation, \"committed\");\n\t\t\t\t\tconst replay = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.claim(ctx, \"committed\", \"fp\"),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\treplay.status === \"completed\" && replay.outcome === \"winner\",\n\t\t\t\t\t\t\"committed evidence must make the staged outcome replayable\",\n\t\t\t\t\t);\n\n\t\t\t\t\tconst rolledBackHandle = await env.run(async (ctx) => {\n\t\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\t\tawait env.store.claim(ctx, \"rolled-back\", \"fp\"),\n\t\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait env.store.complete(ctx, claim, \"must disappear\");\n\t\t\t\t\t\treturn claim;\n\t\t\t\t\t});\n\t\t\t\t\tawait expireLease(env, rolledBackHandle);\n\t\t\t\t\tconst rolledBack = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.claim(ctx, \"rolled-back\", \"fp\"),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\trolledBack.status === \"reconciliation-required\",\n\t\t\t\t\t\t\"the staged outcome must expose its reconciliation receipt\",\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.reconcile(rolledBack.reconciliation, \"not-committed\");\n\t\t\t\t\tconst fresh = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.claim(ctx, \"rolled-back\", \"fp\"),\n\t\t\t\t\t);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tfresh.status,\n\t\t\t\t\t\t\"claimed\",\n\t\t\t\t\t\t\"not-committed evidence must release the staged outcome\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\t// Two-phase-hooks family: staged semantics and real abandon are the\n\t\t// core proofs; the transactional family's hooks are no-ops instead.\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"family: non-transactional\",\n\t\t\t\tsatisfiedBy: nonTransactional,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"a staged, unconfirmed outcome is in-flight, never replayed\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tawait env.run(async (ctx) => {\n\t\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\t\tawait env.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait env.store.complete(ctx, claim, \"uncommitted\");\n\t\t\t\t\t});\n\t\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\t\tenv.run((ctx) => env.store.claim(ctx, \"key-1\", \"fp-1\")),\n\t\t\t\t\t);\n\t\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\t\trejection,\n\t\t\t\t\t\t[\"IDEMPOTENCY_IN_FLIGHT\"],\n\t\t\t\t\t\t\"a staged outcome must never replay; it is in-flight until confirmed\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"family: non-transactional\",\n\t\t\t\tsatisfiedBy: nonTransactional,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"abandon releases a pending claim so the next attempt claims fresh\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tconst first = claimedHandle(\n\t\t\t\t\t\tawait env.run((ctx) => env.store.claim(ctx, \"key-1\", \"fp-1\")),\n\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.abandon(first);\n\t\t\t\t\tconst claim = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tclaim.status,\n\t\t\t\t\t\t\"claimed\",\n\t\t\t\t\t\t\"an abandoned pending claim must be claimable again\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"family: non-transactional\",\n\t\t\t\tsatisfiedBy: nonTransactional,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"abandon releases a staged outcome so the next attempt claims fresh\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tconst first = await env.run(async (ctx) => {\n\t\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\t\tawait env.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait env.store.complete(ctx, claim, \"uncommitted\");\n\t\t\t\t\t\treturn claim;\n\t\t\t\t\t});\n\t\t\t\t\tawait env.store.abandon(first);\n\t\t\t\t\tconst claim = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tclaim.status,\n\t\t\t\t\t\t\"claimed\",\n\t\t\t\t\t\t\"an abandoned staged outcome must be claimable again\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\t// Single-transaction family: committed state is final, hooks are\n\t\t// no-ops, and the rollback proof is mandatory.\n\t\tgatedContractTest(\n\t\t\t{ capability: \"family: transactional\", satisfiedBy: !nonTransactional },\n\t\t\t{\n\t\t\t\tname: \"a rolled-back transaction releases the claim (single-transaction pattern)\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tif (!env.runRolledBack) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Contract violated: the transactional family requires runRolledBack on the environment\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait env\n\t\t\t\t\t\t.runRolledBack(async (ctx) => {\n\t\t\t\t\t\t\tconst claim = claimedHandle(\n\t\t\t\t\t\t\t\tawait env.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t\t\t\t\"a fresh key must be claimed\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tawait env.store.complete(ctx, claim, \"rolled back\");\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\t\t// The rollback mechanism may surface as a rejection; the\n\t\t\t\t\t\t\t// contract under test is the store state afterwards.\n\t\t\t\t\t\t});\n\t\t\t\t\tconst claim = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.claim(ctx, \"key-1\", \"fp-1\"),\n\t\t\t\t\t);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tclaim.status,\n\t\t\t\t\t\t\"claimed\",\n\t\t\t\t\t\t\"a rolled-back claim/complete must leave the key claimable\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t);\n\n\treturn tests;\n}\n","import type { AggregateAddress } from \"../domain/aggregate/aggregate-address\";\nimport type { AnyDomainEvent } from \"../domain/event/domain-event\";\nimport { deepEqual } from \"../internal/structural/deep-equal\";\nimport type { EventCommitCandidate } from \"../messaging/committed-event\";\nimport type {\n\tDeadLetterRecord,\n\tDispatchTrackingOutbox,\n\tOutbox,\n\tOutboxRecord,\n} from \"../messaging/outbox/ports\";\nimport { isDispatchTrackingOutbox } from \"../messaging/outbox/ports\";\nimport {\n\tassert,\n\tassertEqual,\n\tbindContractEnvironment,\n\ttype ContractTest,\n\tcaptureRejection,\n\tdescribeError,\n\tgatedContractTest,\n} from \"./contract-assertions\";\n\n/** One contract test; bind with `(test.skipped ? it.skip : it)(test.name, test.run)`. */\nexport type OutboxContractTest = ContractTest;\n\n/**\n * One isolated test environment: a fresh outbox store. The suite\n * creates one per test and tears it down afterwards.\n */\nexport interface OutboxContractEnvironment<Evt extends AnyDomainEvent> {\n\t/** The adapter under test. */\n\toutbox: Outbox<Evt> | DispatchTrackingOutbox<Evt>;\n\n\t/**\n\t * Runs `outbox.add(candidates)` inside a transaction that COMMITS, the\n\t * way `withCommit` calls it in production. The suite supplies complete\n\t * candidates with explicit source, aggregate version, zero-based commit\n\t * sequence, and commit size. For a non-transactional store this is simply\n\t * `outbox.add(candidates)`.\n\t */\n\taddCommitted(events: ReadonlyArray<EventCommitCandidate<Evt>>): Promise<void>;\n\n\t/**\n\t * Optional capability: runs `outbox.add(candidates)` inside a\n\t * transaction that ROLLS BACK. Enables the rollback-purity test: a\n\t * rolled-back add must leave nothing behind. Transactional adapters\n\t * should always provide this; it is the half of the outbox promise\n\t * that in-memory fakes cannot keep.\n\t */\n\taddRolledBack?(\n\t\tevents: ReadonlyArray<EventCommitCandidate<Evt>>,\n\t): Promise<void>;\n\n\t/** Release connections, drop schemas, etc. Called in a finally. */\n\tteardown?(): Promise<void>;\n}\n\n/**\n * What an adapter supplies to run the outbox contract suite.\n *\n * For SQL adapters, run against a real database (testcontainers or\n * equivalent): the commit-order and rollback tests prove YOUR schema\n * and transaction wiring, not the kit's.\n *\n * Note on claiming: multi-instance safety (`getPending` claiming via\n * `FOR UPDATE SKIP LOCKED` or equivalent) is part of the port contract\n * for competing dispatchers but is not covered here; concurrency\n * cannot be proven portably by a generic suite. Test it in your\n * adapter's own suite if you run more than one dispatcher.\n */\nexport interface OutboxContractHarness<Evt extends AnyDomainEvent> {\n\tcreateEnvironment(): Promise<OutboxContractEnvironment<Evt>>;\n\n\t/**\n\t * Deterministic event factory: the same `seed` yields an event with\n\t * the SAME `eventId` (the suite uses this for the dedupe test), and\n\t * different seeds yield distinct `eventId`s.\n\t */\n\tcreateEvent(seed: number): Evt;\n\n\t/**\n\t * For a `DispatchTrackingOutbox` adapter: how many `markFailed`\n\t * reports move a record to the dead-letter set (the adapter's\n\t * configured attempt ceiling). Omit for plain `Outbox` adapters;\n\t * the dispatch-tracking tests are then marked skipped. With a\n\t * ceiling of 1 the attempts-surfacing test is marked skipped too:\n\t * observing attempts on a PENDING record needs a record that\n\t * survives one failure.\n\t */\n\tfailuresToDeadLetter?: number;\n\n\t/**\n\t * Declare `true` when environments provide {@link\n\t * OutboxContractEnvironment.addRolledBack}. Without it, the\n\t * rollback-purity test is marked skipped: the honest state of an\n\t * in-memory fake, and a loud gap for a transactional adapter.\n\t */\n\tprovidesRolledBackAdds?: boolean;\n\n\t/**\n\t * Declare `true` when the adapter's `getPending` CLAIMS the returned\n\t * records for competing dispatchers (lease, visibility timeout,\n\t * `FOR UPDATE SKIP LOCKED`), as the port sanctions. Every test that\n\t * re-polls records a previous poll returned without resolving them\n\t * (head stability, re-ack non-disturbance, attempts surfacing)\n\t * assumes a non-claiming read and is marked skipped for claiming\n\t * adapters; prove your claim/expiry semantics in your own suite.\n\t */\n\tclaimsOnGetPending?: boolean;\n\n\t/**\n\t * Declare `true` when `add()` dedupes on `eventId` (the unique-key\n\t * constraint the port RECOMMENDS). The dedupe test is gated on this:\n\t * an adapter without the constraint satisfies the port's normative\n\t * requirements and must not fail the suite, but the skip stays\n\t * visible as the unproven recommendation it is.\n\t */\n\tdedupesOnEventId?: boolean;\n}\n\n/**\n * The outbox contract test suite: the proof that an adapter delivers\n * the guarantees `withCommit` and `OutboxDispatcher` document. The kit\n * is store-agnostic, so commit-order reads, qualified source-position\n * identity, eventful-predecessor linkage, idempotent acks, and rollback\n * purity are an **adapter contract, not a kit guarantee**; this suite is how\n * an adapter demonstrates them. Its source-law tests also prove that colliding\n * raw ids stay isolated by aggregate type and aggregate id.\n *\n * Framework-agnostic: bind with\n * `(test.skipped ? it.skip : it)(test.name, test.run)`.\n */\nexport function createOutboxContractTests<Evt extends AnyDomainEvent>(\n\tharness: OutboxContractHarness<Evt>,\n): OutboxContractTest[] {\n\ttype Env = OutboxContractEnvironment<Evt>;\n\tconst inEnv = bindContractEnvironment(() => harness.createEnvironment());\n\tconst defaultSource: AggregateAddress = {\n\t\taggregateType: \"ContractAggregate\",\n\t\taggregateId: \"contract-aggregate\",\n\t};\n\tconst commit = (\n\t\tevents: ReadonlyArray<Evt>,\n\t\taggregateVersion = 1,\n\t\tsource: AggregateAddress = defaultSource,\n\t): ReadonlyArray<EventCommitCandidate<Evt>> =>\n\t\tevents.map((event, commitSequence) => ({\n\t\t\tevent,\n\t\t\tsource,\n\t\t\tposition: {\n\t\t\t\taggregateVersion,\n\t\t\t\tcommitSequence,\n\t\t\t\tcommitSize: events.length,\n\t\t\t},\n\t\t}));\n\tconst takeAndAck = async (\n\t\tenv: Env,\n\t\tcount: number,\n\t): Promise<ReadonlyArray<OutboxRecord<Evt>>> => {\n\t\tconst records: Array<OutboxRecord<Evt>> = [];\n\t\tfor (let index = 0; index < count; index += 1) {\n\t\t\tconst [record] = await env.outbox.getPending(1);\n\t\t\tassert(\n\t\t\t\trecord !== undefined,\n\t\t\t\t`expected committed outbox record ${index + 1} of ${count}`,\n\t\t\t);\n\t\t\trecords.push(record);\n\t\t\tawait env.outbox.markDispatched([record.dispatchId]);\n\t\t}\n\t\treturn records;\n\t};\n\n\tconst tests: OutboxContractTest[] = [\n\t\t{\n\t\t\tname: \"finalizes complete commit receipts and links the next eventful commit\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.addCommitted(\n\t\t\t\t\tcommit([harness.createEvent(1), harness.createEvent(2)], 1),\n\t\t\t\t);\n\t\t\t\t// Version 2 may have been a state-only commit; the event-source\n\t\t\t\t// predecessor is still the previous EVENTFUL version 1.\n\t\t\t\tawait env.addCommitted(commit([harness.createEvent(3)], 3));\n\t\t\t\tconst records = await takeAndAck(env, 3);\n\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\trecords.map(({ position }) => position),\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\taggregateVersion: 1,\n\t\t\t\t\t\t\t\tcommitSequence: 0,\n\t\t\t\t\t\t\t\tcommitSize: 2,\n\t\t\t\t\t\t\t\tpreviousEventfulAggregateVersion: null,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\taggregateVersion: 1,\n\t\t\t\t\t\t\t\tcommitSequence: 1,\n\t\t\t\t\t\t\t\tcommitSize: 2,\n\t\t\t\t\t\t\t\tpreviousEventfulAggregateVersion: null,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\taggregateVersion: 3,\n\t\t\t\t\t\t\t\tcommitSequence: 0,\n\t\t\t\t\t\t\t\tcommitSize: 1,\n\t\t\t\t\t\t\t\tpreviousEventfulAggregateVersion: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t),\n\t\t\t\t\t\"the source must preserve zero-based commit completeness and link the next eventful commit to version 1\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"rejects different event identities at one qualified source position\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst original = commit([harness.createEvent(1)], 1);\n\t\t\t\tconst collision = commit([harness.createEvent(2)], 1);\n\t\t\t\tawait env.addCommitted(original);\n\t\t\t\tconst rejection = await captureRejection(env.addCommitted(collision));\n\t\t\t\tassert(\n\t\t\t\t\trejection !== undefined,\n\t\t\t\t\t\"a different eventId at one qualified source position must reject\",\n\t\t\t\t);\n\n\t\t\t\tconst [record] = await takeAndAck(env, 1);\n\t\t\t\tassertEqual(\n\t\t\t\t\trecord?.event.eventId,\n\t\t\t\t\toriginal[0]?.event.eventId,\n\t\t\t\t\t\"the rejected collision must not replace the original record\",\n\t\t\t\t);\n\t\t\t\tawait env.addCommitted(commit([harness.createEvent(3)], 2));\n\t\t\t\tconst [next] = await takeAndAck(env, 1);\n\t\t\t\tassertEqual(\n\t\t\t\t\tnext?.position.previousEventfulAggregateVersion,\n\t\t\t\t\t1,\n\t\t\t\t\t\"the rejected collision must not change the source head\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"keeps event-source heads isolated by aggregate type and id\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst sources: ReadonlyArray<AggregateAddress> = [\n\t\t\t\t\t{ aggregateType: \"Order\", aggregateId: \"1\" },\n\t\t\t\t\t{ aggregateType: \"Payment\", aggregateId: \"1\" },\n\t\t\t\t\t{ aggregateType: \"Order\", aggregateId: \"2\" },\n\t\t\t\t];\n\t\t\t\tfor (const [index, source] of sources.entries()) {\n\t\t\t\t\tawait env.addCommitted(\n\t\t\t\t\t\tcommit([harness.createEvent(index + 1)], 1, source),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst records = await takeAndAck(env, sources.length);\n\t\t\t\tassert(\n\t\t\t\t\trecords.every(\n\t\t\t\t\t\t(record, index) =>\n\t\t\t\t\t\t\trecord.source.aggregateType === sources[index]?.aggregateType &&\n\t\t\t\t\t\t\trecord.source.aggregateId === sources[index]?.aggregateId &&\n\t\t\t\t\t\t\trecord.position.previousEventfulAggregateVersion === null,\n\t\t\t\t\t),\n\t\t\t\t\t\"colliding raw ids or aggregate types must each retain an independent genesis head\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"getPending returns records in commit order, across separate committed adds\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.addCommitted(\n\t\t\t\t\tcommit([harness.createEvent(1), harness.createEvent(2)], 1),\n\t\t\t\t);\n\t\t\t\tawait env.addCommitted(commit([harness.createEvent(3)], 2));\n\t\t\t\t// Explicit limit: the port leaves the no-argument page size to\n\t\t\t\t// the implementation, so the suite never relies on it.\n\t\t\t\tconst pending = await env.outbox.getPending(10);\n\t\t\t\t// \"Up to limit\": short pages are port-legal, so the assertion\n\t\t\t\t// is a non-empty PREFIX of commit order, not the full page.\n\t\t\t\tconst expectedIds = [1, 2, 3].map(\n\t\t\t\t\t(seed) => harness.createEvent(seed).eventId,\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tpending.length >= 1,\n\t\t\t\t\t\"a non-empty backlog must surface at least one record\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\tpending.map((record) => record.event.eventId),\n\t\t\t\t\t\texpectedIds.slice(0, pending.length),\n\t\t\t\t\t),\n\t\t\t\t\t\"records must come back in the order add() persisted them\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"getPending respects the limit\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.addCommitted(\n\t\t\t\t\tcommit([1, 2, 3, 4].map((s) => harness.createEvent(s))),\n\t\t\t\t);\n\t\t\t\tconst firstPage = await env.outbox.getPending(2);\n\t\t\t\t// The port promises UP TO `limit` records; a shorter page is\n\t\t\t\t// legal, an empty one against a non-empty backlog is not (the\n\t\t\t\t// dispatcher would spin without progress).\n\t\t\t\tassert(\n\t\t\t\t\tfirstPage.length >= 1 && firstPage.length <= 2,\n\t\t\t\t\t\"limit must bound the page: up to `limit` records, at least one while the backlog is non-empty\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t// Head stability assumes a non-claiming read; the port sanctions\n\t\t// claiming reads (lease, visibility timeout, FOR UPDATE SKIP\n\t\t// LOCKED) for competing dispatchers, and for those an un-acked\n\t\t// head legitimately stays invisible until the claim expires.\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"non-claiming getPending\",\n\t\t\t\tsatisfiedBy: !harness.claimsOnGetPending,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"an un-acked head comes back on the next poll (no silent skipping)\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tawait env.addCommitted(\n\t\t\t\t\t\tcommit([1, 2, 3, 4].map((s) => harness.createEvent(s))),\n\t\t\t\t\t);\n\t\t\t\t\tconst firstPage = await env.outbox.getPending(2);\n\t\t\t\t\tconst again = await env.outbox.getPending(2);\n\t\t\t\t\t// Short pages are port-legal (\"up to limit\"), so compare\n\t\t\t\t\t// the overlapping prefix: what head stability forbids is\n\t\t\t\t\t// silently SKIPPING an un-acked record, not short pages.\n\t\t\t\t\tconst overlap = Math.min(firstPage.length, again.length);\n\t\t\t\t\tassert(\n\t\t\t\t\t\toverlap >= 1,\n\t\t\t\t\t\t\"a non-empty backlog must surface at least one record on every poll\",\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\t\tagain.slice(0, overlap).map((r) => r.dispatchId),\n\t\t\t\t\t\t\tfirstPage.slice(0, overlap).map((r) => r.dispatchId),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t\"an un-acked head must come back on the next poll (no silent skipping)\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\t{\n\t\t\tname: \"markDispatched removes records; re-acks and unknown acks are accepted\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.addCommitted(\n\t\t\t\t\tcommit([harness.createEvent(1), harness.createEvent(2)]),\n\t\t\t\t);\n\t\t\t\tconst [first] = await env.outbox.getPending(1);\n\t\t\t\tassert(first !== undefined, \"expected a pending record\");\n\t\t\t\tawait env.outbox.markDispatched([first.dispatchId]);\n\t\t\t\t// Idempotency: re-acking and acking unknown ids must be no-ops.\n\t\t\t\tawait env.outbox.markDispatched([first.dispatchId]);\n\t\t\t\tawait env.outbox.markDispatched([\"no-such-dispatch-id\"]);\n\t\t\t\t// Membership, not count: claiming adapters may hold back the\n\t\t\t\t// still-pending second record, but a dispatched record must\n\t\t\t\t// never come back for anyone.\n\t\t\t\tconst remaining = await env.outbox.getPending(10);\n\t\t\t\tassert(\n\t\t\t\t\t!remaining.some((r) => r.dispatchId === first.dispatchId),\n\t\t\t\t\t\"a dispatched record must never come back\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t// Observing that OTHER records survive a re-ack needs a re-poll of\n\t\t// records an earlier poll already returned un-acked; claiming\n\t\t// adapters legitimately hold those back until the claim expires.\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"non-claiming getPending\",\n\t\t\t\tsatisfiedBy: !harness.claimsOnGetPending,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"idempotent re-acks do not disturb other pending records\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tawait env.addCommitted(\n\t\t\t\t\t\tcommit([harness.createEvent(1), harness.createEvent(2)]),\n\t\t\t\t\t);\n\t\t\t\t\tconst [first] = await env.outbox.getPending(1);\n\t\t\t\t\tassert(first !== undefined, \"expected a pending record\");\n\t\t\t\t\tawait env.outbox.markDispatched([first.dispatchId]);\n\t\t\t\t\tawait env.outbox.markDispatched([first.dispatchId]);\n\t\t\t\t\tawait env.outbox.markDispatched([\"no-such-dispatch-id\"]);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\t(await env.outbox.getPending(10)).length,\n\t\t\t\t\t\t1,\n\t\t\t\t\t\t\"idempotent re-acks must not disturb other records\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\t// Dedupe on eventId is the port's RECOMMENDATION, not a normative\n\t\t// requirement; only adapters that declare the unique-key constraint\n\t\t// are held to it.\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"dedupesOnEventId\",\n\t\t\t\tsatisfiedBy: harness.dedupesOnEventId === true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"re-adding an event with the same eventId is deduped, not duplicated\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tconst original = commit([harness.createEvent(1)]);\n\t\t\t\t\tawait env.addCommitted(original);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait env.addCommitted(original);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t// A bare UNIQUE(eventId) constraint makes the duplicate\n\t\t\t\t\t\t// INSERT throw; the contract wants an idempotent add.\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Contract violated: add() must swallow a duplicate eventId, not throw. \" +\n\t\t\t\t\t\t\t\t\"Dedupe means an idempotent add (INSERT ... ON CONFLICT DO NOTHING or \" +\n\t\t\t\t\t\t\t\t`equivalent), not a raised unique violation. Got: ${describeError(error)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst pending = await env.outbox.getPending(10);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tpending.length,\n\t\t\t\t\t\t1,\n\t\t\t\t\t\t\"the same eventId must yield one record (unique-key dedupe)\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t];\n\n\t// Rollback purity: capability-gated (in-memory fakes cannot keep it).\n\ttests.push(\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"providesRolledBackAdds\",\n\t\t\t\tsatisfiedBy: harness.providesRolledBackAdds === true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"a rolled-back add leaves nothing behind (transactional participation)\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tif (!env.addRolledBack) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Contract violated: harness declared providesRolledBackAdds but the environment lacks addRolledBack\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait env.addRolledBack(commit([harness.createEvent(1)], 1));\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\t(await env.outbox.getPending(10)).length,\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t\"events added in a rolled-back transaction must not appear\",\n\t\t\t\t\t);\n\t\t\t\t\tawait env.addCommitted(commit([harness.createEvent(2)], 2));\n\t\t\t\t\tconst [afterRollback] = await takeAndAck(env, 1);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tafterRollback?.position.previousEventfulAggregateVersion,\n\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\"a rolled-back add must not advance the event-source head\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t);\n\n\t// Dispatch tracking: gated on the harness declaring the ceiling.\n\t// `attemptCeiling` is only ever read inside enabled tests, where the\n\t// gate guarantees the harness declared it.\n\tconst trackingEnabled = harness.failuresToDeadLetter !== undefined;\n\tconst attemptCeiling = harness.failuresToDeadLetter ?? 0;\n\tconst trackingGate = (test: ContractTest): ContractTest =>\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"failuresToDeadLetter (DispatchTrackingOutbox)\",\n\t\t\t\tsatisfiedBy: trackingEnabled,\n\t\t\t},\n\t\t\ttest,\n\t\t);\n\ttests.push(\n\t\ttrackingGate(\n\t\t\t// Observing attempts needs the record back on a re-poll after an\n\t\t\t// un-acked poll (a claiming adapter may hold it until the claim\n\t\t\t// expires) AND a record that survives one failure (with a\n\t\t\t// ceiling of 1, the single markFailed dead-letters it before\n\t\t\t// the re-poll, exactly as the port requires).\n\t\t\tgatedContractTest(\n\t\t\t\t{\n\t\t\t\t\tcapability: \"non-claiming getPending\",\n\t\t\t\t\tsatisfiedBy: !harness.claimsOnGetPending,\n\t\t\t\t},\n\t\t\t\tgatedContractTest(\n\t\t\t\t\t{\n\t\t\t\t\t\tcapability: \"failuresToDeadLetter >= 2\",\n\t\t\t\t\t\tsatisfiedBy: attemptCeiling >= 2,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"markFailed increments attempts surfaced on pending records\",\n\t\t\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\t\t\tconst outbox = env.outbox;\n\t\t\t\t\t\t\tassert(\n\t\t\t\t\t\t\t\tisDispatchTrackingOutbox(outbox),\n\t\t\t\t\t\t\t\t\"harness declared a tracking outbox\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tawait env.addCommitted(commit([harness.createEvent(1)]));\n\t\t\t\t\t\t\tconst [record] = await outbox.getPending(1);\n\t\t\t\t\t\t\tassert(record !== undefined, \"expected a pending record\");\n\t\t\t\t\t\t\tawait outbox.markFailed(record.dispatchId, new Error(\"boom\"));\n\t\t\t\t\t\t\tconst [after] = await outbox.getPending(1);\n\t\t\t\t\t\t\tassertEqual(\n\t\t\t\t\t\t\t\tafter?.attempts,\n\t\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\t\t\"attempts must be surfaced on the record after markFailed\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}),\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t),\n\t\t),\n\t\ttrackingGate({\n\t\t\tname: \"reaching the attempt ceiling dead-letters the record and unblocks getPending\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst outbox = env.outbox;\n\t\t\t\tassert(\n\t\t\t\t\tisDispatchTrackingOutbox(outbox),\n\t\t\t\t\t\"harness declared a tracking outbox\",\n\t\t\t\t);\n\t\t\t\tawait env.addCommitted(\n\t\t\t\t\tcommit([harness.createEvent(1), harness.createEvent(2)]),\n\t\t\t\t);\n\t\t\t\tconst [poison] = await outbox.getPending(1);\n\t\t\t\tassert(poison !== undefined, \"expected a pending record\");\n\t\t\t\tlet transition: DeadLetterRecord<Evt> | undefined;\n\t\t\t\tfor (let i = 0; i < attemptCeiling; i++) {\n\t\t\t\t\tconst current = await outbox.markFailed(\n\t\t\t\t\t\tpoison.dispatchId,\n\t\t\t\t\t\tnew Error(\"poison\"),\n\t\t\t\t\t);\n\t\t\t\t\tif (i < attemptCeiling - 1) {\n\t\t\t\t\t\tassertEqual(\n\t\t\t\t\t\t\tcurrent,\n\t\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\t\"markFailed must not report a dead-letter transition below the ceiling\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\ttransition = current;\n\t\t\t\t}\n\t\t\t\tassertEqual(\n\t\t\t\t\ttransition?.dispatchId,\n\t\t\t\t\tpoison.dispatchId,\n\t\t\t\t\t\"the ceiling-crossing markFailed call must return the exact dead-letter transition\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\ttransition?.attempts,\n\t\t\t\t\tattemptCeiling,\n\t\t\t\t\t\"the returned transition must carry the final attempt count\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait outbox.markFailed(poison.dispatchId, new Error(\"late\")),\n\t\t\t\t\tundefined,\n\t\t\t\t\t\"a late failure report must not repeat the dead-letter transition\",\n\t\t\t\t);\n\t\t\t\tconst pending = await outbox.getPending(10);\n\t\t\t\tassertEqual(\n\t\t\t\t\tpending.length,\n\t\t\t\t\t1,\n\t\t\t\t\t\"the dead-lettered record must stop coming back; successors must flow\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tpending[0]?.dispatchId !== poison.dispatchId,\n\t\t\t\t\t\"the surviving record must be the successor, not the poison one\",\n\t\t\t\t);\n\t\t\t\tconst dead = await outbox.deadLetters();\n\t\t\t\tassertEqual(dead.length, 1, \"the record must appear in deadLetters()\");\n\t\t\t\tassertEqual(\n\t\t\t\t\tdead[0]?.attempts,\n\t\t\t\t\tattemptCeiling,\n\t\t\t\t\t\"the dead-letter record must carry its attempt count\",\n\t\t\t\t);\n\t\t\t}),\n\t\t}),\n\t\ttrackingGate({\n\t\t\tname: \"markFailed on unknown or dispatched ids never resurrects a record\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst outbox = env.outbox;\n\t\t\t\tassert(\n\t\t\t\t\tisDispatchTrackingOutbox(outbox),\n\t\t\t\t\t\"harness declared a tracking outbox\",\n\t\t\t\t);\n\t\t\t\tawait env.addCommitted(commit([harness.createEvent(1)]));\n\t\t\t\tconst [record] = await outbox.getPending(1);\n\t\t\t\tassert(record !== undefined, \"expected a pending record\");\n\t\t\t\tawait outbox.markDispatched([record.dispatchId]);\n\t\t\t\tawait outbox.markFailed(record.dispatchId, new Error(\"late report\"));\n\t\t\t\tawait outbox.markFailed(\"no-such-id\", new Error(\"unknown\"));\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await outbox.getPending(10)).length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"late or unknown failure reports must not resurrect records\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await outbox.deadLetters()).length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"late or unknown failure reports must not dead-letter anything\",\n\t\t\t\t);\n\t\t\t}),\n\t\t}),\n\t\ttrackingGate({\n\t\t\tname: \"markDispatched clears a dead-lettered record (manual redelivery then ack)\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst outbox = env.outbox;\n\t\t\t\tassert(\n\t\t\t\t\tisDispatchTrackingOutbox(outbox),\n\t\t\t\t\t\"harness declared a tracking outbox\",\n\t\t\t\t);\n\t\t\t\tawait env.addCommitted(commit([harness.createEvent(1)]));\n\t\t\t\tconst [record] = await outbox.getPending(1);\n\t\t\t\tassert(record !== undefined, \"expected a pending record\");\n\t\t\t\tfor (let i = 0; i < attemptCeiling; i++) {\n\t\t\t\t\tawait outbox.markFailed(record.dispatchId, new Error(\"poison\"));\n\t\t\t\t}\n\t\t\t\tawait outbox.markDispatched([record.dispatchId]);\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await outbox.deadLetters()).length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"acking a dead-lettered record must clear it\",\n\t\t\t\t);\n\t\t\t}),\n\t\t}),\n\t);\n\n\treturn tests;\n}\n","import type {\n\tProjectionCheckpoint,\n\tProjectionCheckpointStore,\n\tProjectionPosition,\n} from \"../application/projections/ports\";\nimport type { AggregateAddress } from \"../domain/aggregate/aggregate-address\";\nimport {\n\tassert,\n\tassertEqual,\n\tbindContractEnvironment,\n\ttype ContractTest,\n\tcaptureRejection,\n\tgatedContractTest,\n} from \"./contract-assertions\";\n\n/** One contract test; bind with `(test.skipped ? it.skip : it)(test.name, test.run)`. */\nexport type ProjectionCheckpointStoreContractTest = ContractTest;\n\n/**\n * One isolated test environment: a fresh checkpoint store. The suite\n * creates one per test and tears it down afterwards.\n */\nexport interface ProjectionCheckpointStoreContractEnvironment<TCtx> {\n\t/** The adapter under test. */\n\tstore: ProjectionCheckpointStore<TCtx>;\n\n\t/**\n\t * Runs `work` inside a transaction that COMMITS, handing it the\n\t * transaction context the store methods expect, the way the\n\t * `Projector` calls them in production. For a non-transactional\n\t * store this simply invokes `work` with a dummy context.\n\t */\n\trun<R>(work: (ctx: TCtx) => Promise<R>): Promise<R>;\n\n\t/**\n\t * Optional capability: starts every supplied transaction independently and\n\t * concurrently. Each callback must receive its own transaction context for\n\t * database adapters (normally a separate pooled connection). Enables the\n\t * missing-key/existing-key exclusion test; implementing this as sequential\n\t * calls would make that proof meaningless.\n\t */\n\trunConcurrently?<R>(\n\t\tworks: ReadonlyArray<(ctx: TCtx) => Promise<R>>,\n\t): Promise<R[]>;\n\n\t/**\n\t * Optional capability: runs `work` inside a transaction that ROLLS\n\t * BACK. Enables the rollback test: a rolled-back save must leave no\n\t * checkpoint behind, the half of the atomic update+checkpoint\n\t * promise the store contributes. Transactional adapters should\n\t * always provide this; in-memory fakes cannot.\n\t */\n\trunRolledBack?<R>(work: (ctx: TCtx) => Promise<R>): Promise<R>;\n\n\t/** Release connections, drop schemas, etc. Called in a finally. */\n\tteardown?(): Promise<void>;\n}\n\n/**\n * What an adapter supplies to run the projection-checkpoint-store\n * contract suite. For SQL adapters, run against a real database\n * (testcontainers or equivalent): concurrent runs prove missing-key locking,\n * the rollback test proves YOUR transaction wiring, and the checkpoint table\n * must live in the same database as the read models it accounts for.\n */\nexport interface ProjectionCheckpointStoreContractHarness<TCtx> {\n\tcreateEnvironment(): Promise<\n\t\tProjectionCheckpointStoreContractEnvironment<TCtx>\n\t>;\n\n\t/**\n\t * Declare `true` when environments provide {@link\n\t * ProjectionCheckpointStoreContractEnvironment.runRolledBack}.\n\t * Without it, the rollback test is marked skipped: the honest state\n\t * of an in-memory fake, and a loud gap for a transactional adapter.\n\t */\n\tprovidesRolledBackRuns?: boolean;\n\n\t/**\n\t * Declare `true` when environments provide {@link\n\t * ProjectionCheckpointStoreContractEnvironment.runConcurrently}. Without\n\t * it, missing-key lock safety is marked skipped and remains an explicitly\n\t * unproven adapter guarantee.\n\t */\n\tprovidesConcurrentRuns?: boolean;\n}\n\nconst pos = (\n\taggregateVersion: number,\n\tcommitSequence: number,\n\tcommitSize = commitSequence + 1,\n\tpreviousEventfulAggregateVersion: number | null = null,\n): ProjectionPosition => ({\n\taggregateVersion,\n\tcommitSequence,\n\tcommitSize,\n\tpreviousEventfulAggregateVersion,\n});\n\nconst order = (aggregateId: string): AggregateAddress => ({\n\taggregateType: \"Order\",\n\taggregateId,\n});\n\nconst checkpoint = (\n\tposition: ProjectionPosition,\n\tlastAppliedEventId = \"evt-at-watermark\",\n): ProjectionCheckpoint => ({ position, lastAppliedEventId });\n\n/**\n * The projection-checkpoint-store contract test suite: the proof that\n * an adapter delivers the watermark semantics the `Projector`\n * documents. Checkpoint semantics are an **adapter contract, not a\n * kit guarantee**; this suite is how an adapter demonstrates them. Enable its\n * concurrent-runs capability to prove genesis-safe exclusion rather than\n * leaving that guarantee visibly skipped.\n *\n * The concurrent test exercises commit visibility, but cannot deterministically\n * hold an adapter between return from `withCheckpointLocks` and its surrounding\n * transaction commit. It can therefore expose an early lock release only when\n * a waiter enters during that window; holding database locks through commit or\n * rollback remains an explicit adapter responsibility, not a complete proof\n * supplied by this suite.\n *\n * Framework-agnostic: bind with\n * `(test.skipped ? it.skip : it)(test.name, test.run)`.\n */\nexport function createProjectionCheckpointStoreContractTests<TCtx>(\n\tharness: ProjectionCheckpointStoreContractHarness<TCtx>,\n): ProjectionCheckpointStoreContractTest[] {\n\tconst inEnv = bindContractEnvironment(() => harness.createEnvironment());\n\n\treturn [\n\t\t{\n\t\t\tname: \"a never-seen (projection, aggregate) pair loads undefined\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst loaded = await env.run((ctx) =>\n\t\t\t\t\tenv.store.load(ctx, \"order-list\", order(\"o-1\")),\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tloaded,\n\t\t\t\t\tundefined,\n\t\t\t\t\t\"a fresh store must report no watermark\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"providesConcurrentRuns\",\n\t\t\t\tsatisfiedBy: harness.providesConcurrentRuns === true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"checkpoint locks serialize competing critical sections for absent and existing rows\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tconst runConcurrently = env.runConcurrently;\n\t\t\t\t\tif (!runConcurrently) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Contract violated: harness declared providesConcurrentRuns but the environment lacks runConcurrently\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst contenders = 8;\n\t\t\t\t\tconst address = order(\"o-locked\");\n\t\t\t\t\tconst advanceOnce = async (\n\t\t\t\t\t\texpectedVersion: number | undefined,\n\t\t\t\t\t\tnextVersion: number,\n\t\t\t\t\t): Promise<number> => {\n\t\t\t\t\t\tconst outcomes = await runConcurrently(\n\t\t\t\t\t\t\tArray.from(\n\t\t\t\t\t\t\t\t{ length: contenders },\n\t\t\t\t\t\t\t\t() => (ctx) =>\n\t\t\t\t\t\t\t\t\tenv.store.withCheckpointLocks(\n\t\t\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\t\t\t\t\t[address],\n\t\t\t\t\t\t\t\t\t\tasync () => {\n\t\t\t\t\t\t\t\t\t\t\tconst stored = await env.store.load(\n\t\t\t\t\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\t\t\t\t\t\t\taddress,\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\t\t\texpectedVersion === undefined\n\t\t\t\t\t\t\t\t\t\t\t\t\t? stored !== undefined\n\t\t\t\t\t\t\t\t\t\t\t\t\t: stored?.position.aggregateVersion !==\n\t\t\t\t\t\t\t\t\t\t\t\t\t\texpectedVersion\n\t\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tawait Promise.resolve();\n\t\t\t\t\t\t\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\t\t\t\t\t\t\taddress,\n\t\t\t\t\t\t\t\t\t\t\t\tcheckpoint(pos(nextVersion, 0), `evt-v${nextVersion}`),\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn outcomes.filter((advanced) => advanced).length;\n\t\t\t\t\t};\n\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tawait advanceOnce(undefined, 1),\n\t\t\t\t\t\t1,\n\t\t\t\t\t\t\"exactly one competing callback may advance a missing checkpoint key; genesis has no row that SELECT FOR UPDATE could lock\",\n\t\t\t\t\t);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tawait advanceOnce(1, 2),\n\t\t\t\t\t\t1,\n\t\t\t\t\t\t\"exactly one competing callback may advance an existing checkpoint key from the observed watermark\",\n\t\t\t\t\t);\n\t\t\t\t\tconst stored = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.load(ctx, \"order-list\", address),\n\t\t\t\t\t);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tstored?.position.aggregateVersion === 2,\n\t\t\t\t\t\t\"serialized genesis and existing-row advances must leave the final watermark visible\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t\t{\n\t\t\tname: \"checkpoint locks release after a rejected critical section\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst address = order(\"o-rejected-lock\");\n\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\tenv.run((ctx) =>\n\t\t\t\t\t\tenv.store.withCheckpointLocks(\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\t\t[address],\n\t\t\t\t\t\t\tasync () => {\n\t\t\t\t\t\t\t\tthrow new Error(\"projection failed\");\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\trejection !== undefined,\n\t\t\t\t\t\"the store must propagate a rejected critical section\",\n\t\t\t\t);\n\n\t\t\t\tlet retried = false;\n\t\t\t\tawait env.run((ctx) =>\n\t\t\t\t\tenv.store.withCheckpointLocks(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\t[address],\n\t\t\t\t\t\tasync () => {\n\t\t\t\t\t\t\tretried = true;\n\t\t\t\t\t\t},\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tretried,\n\t\t\t\t\t\"a rejected callback must release its key so redelivery can enter\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"save/load round-trips the complete checkpoint receipt\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run((ctx) =>\n\t\t\t\t\tenv.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\tcheckpoint(pos(5, 2, 3, 3), \"evt-o-1-5-2\"),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tconst loaded = await env.run((ctx) =>\n\t\t\t\t\tenv.store.load(ctx, \"order-list\", order(\"o-1\")),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tloaded?.position.aggregateVersion === 5 &&\n\t\t\t\t\t\tloaded.position.commitSequence === 2 &&\n\t\t\t\t\t\tloaded.position.commitSize === 3 &&\n\t\t\t\t\t\tloaded.position.previousEventfulAggregateVersion === 3 &&\n\t\t\t\t\t\tloaded.lastAppliedEventId === \"evt-o-1-5-2\",\n\t\t\t\t\t\"the stored checkpoint must round-trip every cursor field and the watermark event identity\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"save overwrites the previous watermark (last write wins; monotonicity is the projector's job)\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(async (ctx) => {\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\tcheckpoint(pos(5, 0), \"evt-first\"),\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\tcheckpoint(pos(5, 1), \"evt-second\"),\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t\tconst loaded = await env.run((ctx) =>\n\t\t\t\t\tenv.store.load(ctx, \"order-list\", order(\"o-1\")),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tloaded?.position.aggregateVersion === 5 &&\n\t\t\t\t\t\tloaded.position.commitSequence === 1 &&\n\t\t\t\t\t\tloaded.lastAppliedEventId === \"evt-second\",\n\t\t\t\t\t\"a later save must replace the stored watermark verbatim\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"a loaded position is a detached copy; mutating it must not move the watermark\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run((ctx) =>\n\t\t\t\t\tenv.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\tcheckpoint(pos(2, 0)),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tconst loaded = await env.run((ctx) =>\n\t\t\t\t\tenv.store.load(ctx, \"order-list\", order(\"o-1\")),\n\t\t\t\t);\n\t\t\t\tassert(loaded !== undefined, \"expected a stored watermark\");\n\t\t\t\t(loaded.position as { aggregateVersion: number }).aggregateVersion = 99;\n\t\t\t\tconst reloaded = await env.run((ctx) =>\n\t\t\t\t\tenv.store.load(ctx, \"order-list\", order(\"o-1\")),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\treloaded?.position.aggregateVersion === 2,\n\t\t\t\t\t\"the stored watermark must be immune to mutation of a previously loaded copy\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"watermarks are isolated per projection and per aggregate\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(async (ctx) => {\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\tcheckpoint(pos(3, 0)),\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-detail\",\n\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\tcheckpoint(pos(1, 0)),\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\torder(\"o-2\"),\n\t\t\t\t\t\tcheckpoint(pos(7, 0)),\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t\tconst [listO1, detailO1, listO2] = await env.run((ctx) =>\n\t\t\t\t\tPromise.all([\n\t\t\t\t\t\tenv.store.load(ctx, \"order-list\", order(\"o-1\")),\n\t\t\t\t\t\tenv.store.load(ctx, \"order-detail\", order(\"o-1\")),\n\t\t\t\t\t\tenv.store.load(ctx, \"order-list\", order(\"o-2\")),\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tlistO1?.position.aggregateVersion === 3 &&\n\t\t\t\t\t\tdetailO1?.position.aggregateVersion === 1 &&\n\t\t\t\t\t\tlistO2?.position.aggregateVersion === 7,\n\t\t\t\t\t\"the watermark key is the (projection, aggregateType, aggregateId) triple; no part may bleed into another\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"watermarks are isolated per aggregate TYPE: colliding raw ids do not share a checkpoint\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(async (ctx) => {\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\t{ aggregateType: \"Order\", aggregateId: \"1\" },\n\t\t\t\t\t\tcheckpoint(pos(10, 0)),\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\t{ aggregateType: \"Payment\", aggregateId: \"1\" },\n\t\t\t\t\t\tcheckpoint(pos(1, 0)),\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t\tconst [orderMark, paymentMark] = await env.run((ctx) =>\n\t\t\t\t\tPromise.all([\n\t\t\t\t\t\tenv.store.load(ctx, \"order-list\", {\n\t\t\t\t\t\t\taggregateType: \"Order\",\n\t\t\t\t\t\t\taggregateId: \"1\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tenv.store.load(ctx, \"order-list\", {\n\t\t\t\t\t\t\taggregateType: \"Payment\",\n\t\t\t\t\t\t\taggregateId: \"1\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\torderMark?.position.aggregateVersion === 10 &&\n\t\t\t\t\t\tpaymentMark?.position.aggregateVersion === 1,\n\t\t\t\t\t\"identities are type-scoped: Order 1 at version 10 must not make Payment 1 look processed\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"address encoding is collision-free even with separator-like characters in either half\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\t// The two classic composite-key collisions: a separator\n\t\t\t\t// smuggled into the type vs. into the id. Whatever encoding\n\t\t\t\t// the adapter uses (composite column, JSON tuple, nested\n\t\t\t\t// key), these addresses must keep distinct watermarks.\n\t\t\t\tconst inType: AggregateAddress = {\n\t\t\t\t\taggregateType: \"A\\u0000B\",\n\t\t\t\t\taggregateId: \"C\",\n\t\t\t\t};\n\t\t\t\tconst inId: AggregateAddress = {\n\t\t\t\t\taggregateType: \"A\",\n\t\t\t\t\taggregateId: \"B\\u0000C\",\n\t\t\t\t};\n\t\t\t\tawait env.run(async (ctx) => {\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\tinType,\n\t\t\t\t\t\tcheckpoint(pos(10, 0)),\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.save(ctx, \"order-list\", inId, checkpoint(pos(1, 0)));\n\t\t\t\t});\n\t\t\t\tconst [first, second] = await env.run((ctx) =>\n\t\t\t\t\tPromise.all([\n\t\t\t\t\t\tenv.store.load(ctx, \"order-list\", inType),\n\t\t\t\t\t\tenv.store.load(ctx, \"order-list\", inId),\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tfirst?.position.aggregateVersion === 10 &&\n\t\t\t\t\t\tsecond?.position.aggregateVersion === 1,\n\t\t\t\t\t\"two addresses that differ only in where a hostile separator sits must not share a watermark\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"hasReached compares the full pair: unseen is false, behind is false, at and past are true\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run((ctx) =>\n\t\t\t\t\tenv.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\tcheckpoint(pos(5, 0)),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait env.store.hasReached(\"order-list\", order(\"o-2\"), pos(1, 0)),\n\t\t\t\t\tfalse,\n\t\t\t\t\t\"an unseen aggregate has reached nothing\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait env.store.hasReached(\"order-list\", order(\"o-1\"), pos(5, 1)),\n\t\t\t\t\tfalse,\n\t\t\t\t\t\"a later commitSequence of the SAME version is not yet reached; comparing on the version alone would lie mid-commit\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait env.store.hasReached(\"order-list\", order(\"o-1\"), pos(6, 0)),\n\t\t\t\t\tfalse,\n\t\t\t\t\t\"a later version is not yet reached\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait env.store.hasReached(\"order-list\", order(\"o-1\"), pos(5, 0)),\n\t\t\t\t\ttrue,\n\t\t\t\t\t\"the stored position itself is reached\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait env.store.hasReached(\"order-list\", order(\"o-1\"), pos(4, 7)),\n\t\t\t\t\ttrue,\n\t\t\t\t\t\"any earlier version is reached regardless of its commitSequence\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"reset clears only the named projection's checkpoints\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.run(async (ctx) => {\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\tcheckpoint(pos(3, 0)),\n\t\t\t\t\t);\n\t\t\t\t\tawait env.store.save(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\"order-detail\",\n\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\tcheckpoint(pos(2, 0)),\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t\tawait env.run((ctx) => env.store.reset(ctx, \"order-list\"));\n\t\t\t\tconst [cleared, untouched] = await env.run((ctx) =>\n\t\t\t\t\tPromise.all([\n\t\t\t\t\t\tenv.store.load(ctx, \"order-list\", order(\"o-1\")),\n\t\t\t\t\t\tenv.store.load(ctx, \"order-detail\", order(\"o-1\")),\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tcleared,\n\t\t\t\t\tundefined,\n\t\t\t\t\t\"the reset projection must start from zero (rebuild entry point)\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tuntouched?.position.aggregateVersion === 2,\n\t\t\t\t\t\"a sibling projection's checkpoints must survive the reset\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait env.store.hasReached(\"order-list\", order(\"o-1\"), pos(1, 0)),\n\t\t\t\t\tfalse,\n\t\t\t\t\t\"hasReached must report false after a reset\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"providesRolledBackRuns\",\n\t\t\t\tsatisfiedBy: harness.providesRolledBackRuns === true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"a rolled-back save leaves no checkpoint behind (atomic update+checkpoint)\",\n\t\t\t\trun: inEnv(async (env) => {\n\t\t\t\t\tif (!env.runRolledBack) {\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"Contract violated: harness declared providesRolledBackRuns but the environment lacks runRolledBack\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tawait env\n\t\t\t\t\t\t.runRolledBack((ctx) =>\n\t\t\t\t\t\t\tenv.store.save(\n\t\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\t\t\"order-list\",\n\t\t\t\t\t\t\t\torder(\"o-1\"),\n\t\t\t\t\t\t\t\tcheckpoint(pos(1, 0)),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\t\t// The rollback mechanism may surface as a rejection; the\n\t\t\t\t\t\t\t// contract under test is the store state afterwards.\n\t\t\t\t\t\t});\n\t\t\t\t\tconst loaded = await env.run((ctx) =>\n\t\t\t\t\t\tenv.store.load(ctx, \"order-list\", order(\"o-1\")),\n\t\t\t\t\t);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tloaded,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t\"a checkpoint from a rolled-back transaction must not exist; otherwise events are lost while marked processed\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t];\n}\n","import type { Aggregate } from \"../domain/aggregate/aggregate\";\nimport type {\n\tAnyDomainEvent,\n\tPendingDomainEvent,\n} from \"../domain/event/domain-event\";\nimport type { Id } from \"../domain/identity/id\";\nimport { deepEqual } from \"../internal/structural/deep-equal\";\nimport type { CommittedDomainEvent } from \"../messaging/committed-event\";\nimport {\n\tassert,\n\tassertChainContainsKitError,\n\tassertEqual,\n\tawaitOverlappingCall,\n\tbindContractEnvironment,\n\ttype ContractTest,\n\tcaptureRejection,\n\tdescribeError,\n\tgatedContractTest,\n\tloadAggregateOrFail,\n\tOVERLAPPING_CALLS_BOUND_MS,\n\toverlappingCallsPreflight,\n\tparkRunCall,\n\trecordedPendingEventIds,\n\tsortedCommittedEventIds,\n} from \"./contract-assertions\";\n\n/** Application-facing state-stored repository exercised by the suite. */\nexport interface ContractRepository<\n\tTAggregate extends Aggregate<Id<string>, AnyDomainEvent>,\n> {\n\tfindById(id: TAggregate[\"id\"]): Promise<TAggregate | undefined>;\n\tadd(aggregate: TAggregate): void;\n\t/** An append-only port declares no update. */\n\tupdate?(aggregate: TAggregate): void;\n\t/** Physical removal is an optional persistence capability. */\n\tremove?(aggregate: TAggregate): void;\n}\n\n/** One isolated real-adapter environment. `run` must permit overlapping calls. */\nexport interface RepositoryContractEnvironment<\n\tTAggregate extends Aggregate<Id<string>, TEvent>,\n\tTEvent extends AnyDomainEvent = AnyDomainEvent,\n> {\n\trun<R>(\n\t\twork: (context: {\n\t\t\trepository: ContractRepository<TAggregate>;\n\t\t}) => Promise<R>,\n\t): Promise<R>;\n\tcommittedOutboxEvents(): Promise<ReadonlyArray<CommittedDomainEvent<TEvent>>>;\n\t/** Makes the next transactional outbox write fail for atomicity proof. */\n\tfailNextOutboxWrite(error: Error): void;\n\tteardown?(): Promise<void>;\n}\n\n/** Fixtures and observable projections supplied by an adapter package. */\nexport interface RepositoryContractHarness<\n\tTAggregate extends Aggregate<Id<string>, TEvent>,\n\tTEvent extends AnyDomainEvent = AnyDomainEvent,\n> {\n\tcreateEnvironment(): Promise<\n\t\tRepositoryContractEnvironment<TAggregate, TEvent>\n\t>;\n\t/** A fresh aggregate with a unique id. */\n\tcreateAggregate(): TAggregate;\n\t/** One version-bumping decision that records at least one event. */\n\tmutate(aggregate: TAggregate): void;\n\t/** Required for duplicate-add and same-UoW deletion-finality proofs. */\n\tcreateAggregateWithId?(id: TAggregate[\"id\"]): TAggregate;\n\t/**\n\t * A version-bumping decision with no event whose resulting state is\n\t * deep-equal to the previous state (`setState({ ...state })`). The\n\t * deep-equal requirement is load-bearing: it forces a diff-based\n\t * `PersistenceModel` to derive an EMPTY change set, so the suite proves\n\t * that an adapter persists the bumped version even when\n\t * `changes.empty` is true. Skipping that write desyncs the persisted\n\t * version and produces false concurrency conflicts later.\n\t */\n\tmutateVersionOnly?(aggregate: TAggregate): void;\n\t/** A decision that changes a nested collection. */\n\tmutateChildCollection?(aggregate: TAggregate): void;\n\t/** Round-trip-stable adapter persistence projection. */\n\tsnapshotState?(aggregate: TAggregate): unknown;\n\t/** Opt out only for an intentionally upserting add implementation. */\n\tinsertsAreDuplicateChecked?: boolean;\n\t/**\n\t * Opt out only for an append-only port, one that the definition marks\n\t * with `appendOnly: true`. The suite then skips every update proof. The\n\t * duplicate-add proof is the concurrency proof that remains, so it is\n\t * mandatory. Provide `createAggregateWithId` and keep\n\t * `insertsAreDuplicateChecked`, or the proof fails instead of skipping.\n\t */\n\tupdatesAreSupported?: boolean;\n\t/** Enables physical-remove behavior and stale-remove OCC tests. */\n\tremovesAreSupported?: boolean;\n\t/** The remove flush predicates on the version captured at load. */\n\tremovesAreVersionChecked?: boolean;\n\t/**\n\t * Bound for the overlapping `run` calls, in milliseconds: the second call\n\t * of the environment preflight, and the committing call of each\n\t * stale-writer proof. Raise it only for a second connection that needs\n\t * more time to open, or for a slow commit. Keep twice the bound, plus\n\t * environment creation and teardown, below the test timeout of the runner.\n\t */\n\toverlappingCallsBoundMs?: number;\n}\n\nexport type RepositoryContractTest = ContractTest;\n\n/**\n * Contract suite for the v3 explicit-intent, commit-time-flush protocol.\n *\n * The harness must use the public `UnitOfWork` with a real adapter. In\n * particular, `run` must create a fresh Unit of Work and transaction for each\n * call and allow two calls to overlap; the mandatory stale-writer proof keeps\n * writer B open while writer A commits. SQL/ORM adapters therefore need a\n * real database and connection pool. An in-memory harness proves only itself.\n *\n * Writes are synchronous registrations. Durable adapter I/O happens after the\n * callback returns, while the transaction is still open. A test that passes\n * because `add` or `update` writes early is not a conforming implementation.\n */\nexport function createRepositoryContractTests<\n\tTAggregate extends Aggregate<Id<string>, TEvent>,\n\tTEvent extends AnyDomainEvent = AnyDomainEvent,\n>(\n\tharness: RepositoryContractHarness<TAggregate, TEvent>,\n): RepositoryContractTest[] {\n\ttype Environment = RepositoryContractEnvironment<TAggregate, TEvent>;\n\tconst inEnvironment = bindContractEnvironment(() =>\n\t\tharness.createEnvironment(),\n\t);\n\tconst snapshotState = harness.snapshotState;\n\tconst createAggregateWithId = harness.createAggregateWithId;\n\tconst mutateVersionOnly = harness.mutateVersionOnly;\n\tconst mutateChildCollection = harness.mutateChildCollection;\n\tconst insertsAreDuplicateChecked =\n\t\tharness.insertsAreDuplicateChecked !== false;\n\tconst updatesAreSupported = harness.updatesAreSupported !== false;\n\tconst removesAreSupported = harness.removesAreSupported === true;\n\tconst removesAreVersionChecked =\n\t\tremovesAreSupported && harness.removesAreVersionChecked === true;\n\tconst overlappingCallsBoundMs =\n\t\tharness.overlappingCallsBoundMs ?? OVERLAPPING_CALLS_BOUND_MS;\n\n\tconst load = (\n\t\trepository: ContractRepository<TAggregate>,\n\t\tid: TAggregate[\"id\"],\n\t): Promise<TAggregate> =>\n\t\tloadAggregateOrFail(\n\t\t\trepository,\n\t\t\tid,\n\t\t\t\"the adapter did not commit or reconstitute the aggregate\",\n\t\t);\n\n\tconst update = (\n\t\trepository: ContractRepository<TAggregate>,\n\t\taggregate: TAggregate,\n\t): void => {\n\t\tassert(\n\t\t\trepository.update !== undefined,\n\t\t\t\"the harness keeps updatesAreSupported, but the repository has no update\",\n\t\t);\n\t\trepository.update(aggregate);\n\t};\n\tconst updateGate = {\n\t\tcapability: \"updatesAreSupported\",\n\t\tsatisfiedBy: updatesAreSupported,\n\t};\n\n\tasync function seed(environment: Environment): Promise<TAggregate> {\n\t\tconst aggregate = harness.createAggregate();\n\t\tharness.mutate(aggregate);\n\t\tawait environment.run(async ({ repository }) => {\n\t\t\trepository.add(aggregate);\n\t\t});\n\t\treturn aggregate;\n\t}\n\n\tconst reload = (environment: Environment, id: TAggregate[\"id\"]) =>\n\t\tenvironment.run(({ repository }) => load(repository, id));\n\n\tconst eventIds = (\n\t\tevents: ReadonlyArray<CommittedDomainEvent<TEvent>>,\n\t): string[] => sortedCommittedEventIds(events);\n\tconst pendingEventIds = (\n\t\tevents: ReadonlyArray<PendingDomainEvent<TEvent>>,\n\t): string[] =>\n\t\trecordedPendingEventIds(\n\t\t\tevents,\n\t\t\t\"the harness must record pending events before persistence\",\n\t\t);\n\n\tconst tests: RepositoryContractTest[] = [\n\t\toverlappingCallsPreflight<Environment, TAggregate[\"id\"]>(\n\t\t\tinEnvironment,\n\t\t\t() => harness.createAggregate().id,\n\t\t\toverlappingCallsBoundMs,\n\t\t),\n\t\t{\n\t\t\tname: \"add flushes a new aggregate and its exact event batch atomically\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tconst registeredEvents = [...aggregate.pendingEvents];\n\n\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t});\n\n\t\t\t\tconst reloaded = await reload(environment, aggregate.id);\n\t\t\t\tassertEqual(\n\t\t\t\t\treloaded.version,\n\t\t\t\t\taggregate.version,\n\t\t\t\t\t\"add must store the version registered by the Unit of Work\",\n\t\t\t\t);\n\t\t\t\tif (snapshotState) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\t\tsnapshotState.call(harness, reloaded),\n\t\t\t\t\t\t\tsnapshotState.call(harness, aggregate),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t\"add must store the adapter's complete persistence projection\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst outbox = await environment.committedOutboxEvents();\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(eventIds(outbox), pendingEventIds(registeredEvents).sort()),\n\t\t\t\t\t\"the outbox must contain exactly the batch registered by add\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\taggregate.pendingEvents.length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"only a committed add acknowledges its registered event batch\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"committed outbox envelopes carry exact position facts\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\t// Position facts must be provable through the repository suite\n\t\t\t\t// alone: OutboxWriter-only adapters (CDC, broker-native) cannot\n\t\t\t\t// run the outbox suite, and idempotent consumers key their\n\t\t\t\t// watermarks on (aggregateVersion, commitSequence).\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tconst batchSize = aggregate.pendingEvents.length;\n\t\t\t\tconst committedVersion = aggregate.version;\n\n\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t});\n\n\t\t\t\tconst positions = (await environment.committedOutboxEvents())\n\t\t\t\t\t.map(({ position }) => position)\n\t\t\t\t\t.sort((a, b) => a.commitSequence - b.commitSequence);\n\t\t\t\tassertEqual(\n\t\t\t\t\tpositions.length,\n\t\t\t\t\tbatchSize,\n\t\t\t\t\t\"every registered event must commit exactly one envelope\",\n\t\t\t\t);\n\t\t\t\tpositions.forEach((position, index) => {\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tposition.aggregateVersion,\n\t\t\t\t\t\tcommittedVersion,\n\t\t\t\t\t\t\"every envelope must carry the version the commit persisted\",\n\t\t\t\t\t);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tposition.commitSequence,\n\t\t\t\t\t\tindex,\n\t\t\t\t\t\t\"commitSequence must be gapless and zero-based over the batch\",\n\t\t\t\t\t);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tposition.commitSize,\n\t\t\t\t\t\tbatchSize,\n\t\t\t\t\t\t\"commitSize must equal the exact batch length\",\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t}),\n\t\t},\n\t\tgatedContractTest(updateGate, {\n\t\t\tname: \"MANDATORY stale update: writer B conflicts after writer A commits and persists nothing\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\tconst writerB = await parkRunCall((hold) =>\n\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\tconst stale = await load(repository, seeded.id);\n\t\t\t\t\t\tawait hold();\n\t\t\t\t\t\tharness.mutate(stale);\n\t\t\t\t\t\tupdate(repository, stale);\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\t\tconst committedA = await awaitOverlappingCall(\n\t\t\t\t\t() =>\n\t\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\t\tconst current = await load(repository, seeded.id);\n\t\t\t\t\t\t\tharness.mutate(current);\n\t\t\t\t\t\t\tupdate(repository, current);\n\t\t\t\t\t\t\treturn current;\n\t\t\t\t\t\t}),\n\t\t\t\t\twriterB,\n\t\t\t\t\toverlappingCallsBoundMs,\n\t\t\t\t);\n\t\t\t\tconst outboxAfterA = await environment.committedOutboxEvents();\n\t\t\t\twriterB.release();\n\t\t\t\tconst rejection = await captureRejection(writerB.call);\n\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\trejection,\n\t\t\t\t\t[\"CONCURRENCY_CONFLICT\"],\n\t\t\t\t\t`stale update must reject with ConcurrencyConflictError; got ${describeError(rejection)}`,\n\t\t\t\t);\n\n\t\t\t\tconst final = await reload(environment, seeded.id);\n\t\t\t\tassertEqual(\n\t\t\t\t\tfinal.version,\n\t\t\t\t\tcommittedA.version,\n\t\t\t\t\t\"the stale writer must not replace writer A's version\",\n\t\t\t\t);\n\t\t\t\tif (snapshotState) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\t\tsnapshotState.call(harness, final),\n\t\t\t\t\t\t\tsnapshotState.call(harness, committedA),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t\"the stale writer must not replace writer A's state\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\teventIds(await environment.committedOutboxEvents()),\n\t\t\t\t\t\teventIds(outboxAfterA),\n\t\t\t\t\t),\n\t\t\t\t\t\"a rejected stale flush must add no outbox records\",\n\t\t\t\t);\n\t\t\t}),\n\t\t}),\n\t\t{\n\t\t\tname: \"rollback acknowledges nothing and commits neither state nor outbox\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tconst pending = [...aggregate.pendingEvents];\n\t\t\t\tawait captureRejection(\n\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t\t\tthrow new Error(\"rollback probe\");\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst absent = await environment.run(({ repository }) =>\n\t\t\t\t\trepository.findById(aggregate.id),\n\t\t\t\t);\n\t\t\t\tassert(absent === undefined, \"a rolled-back add must leave no row\");\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await environment.committedOutboxEvents()).length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"a rolled-back add must leave no outbox record\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(aggregate.pendingEvents, pending),\n\t\t\t\t\t\"rollback must acknowledge none of the registered event batch\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"outbox failure rolls the already-flushed aggregate write back\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst aggregate = harness.createAggregate();\n\t\t\t\tharness.mutate(aggregate);\n\t\t\t\tconst pending = [...aggregate.pendingEvents];\n\t\t\t\tenvironment.failNextOutboxWrite(new Error(\"outbox failure probe\"));\n\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\trepository.add(aggregate);\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tassert(rejection !== undefined, \"the outbox failure must reject\");\n\t\t\t\tconst absent = await environment.run(({ repository }) =>\n\t\t\t\t\trepository.findById(aggregate.id),\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tabsent === undefined,\n\t\t\t\t\t\"state flush must roll back when the outbox write fails\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await environment.committedOutboxEvents()).length,\n\t\t\t\t\t0,\n\t\t\t\t\t\"failed outbox write must commit no envelope\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(aggregate.pendingEvents, pending),\n\t\t\t\t\t\"failed commit must acknowledge none of the event batch\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"identity map returns one instance for repeated loads in one Unit of Work\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\tconst first = await repository.findById(seeded.id);\n\t\t\t\t\tconst second = await repository.findById(seeded.id);\n\t\t\t\t\tassert(\n\t\t\t\t\t\tfirst !== undefined && first === second,\n\t\t\t\t\t\t\"repeated reads must return the same tracked aggregate instance\",\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t}),\n\t\t},\n\t\tgatedContractTest(updateGate, {\n\t\t\tname: \"an unchanged explicit update is safe and emits no event\",\n\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\tconst before = await environment.committedOutboxEvents();\n\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\tconst aggregate = await load(repository, seeded.id);\n\t\t\t\t\tupdate(repository, aggregate);\n\t\t\t\t});\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\teventIds(await environment.committedOutboxEvents()),\n\t\t\t\t\t\teventIds(before),\n\t\t\t\t\t),\n\t\t\t\t\t\"an unchanged update must not manufacture an outbox event\",\n\t\t\t\t);\n\t\t\t}),\n\t\t}),\n\t];\n\n\ttests.push(\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: createAggregateWithId\n\t\t\t\t\t? \"insertsAreDuplicateChecked\"\n\t\t\t\t\t: \"createAggregateWithId\",\n\t\t\t\t// An append-only harness has no other concurrency proof, so\n\t\t\t\t// the proof runs and fails instead of skipping.\n\t\t\t\tsatisfiedBy:\n\t\t\t\t\t(Boolean(createAggregateWithId) && insertsAreDuplicateChecked) ||\n\t\t\t\t\t!updatesAreSupported,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"duplicate add rejects and preserves the existing aggregate\",\n\t\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tcreateAggregateWithId !== undefined && insertsAreDuplicateChecked,\n\t\t\t\t\t\t\"an append-only harness must provide createAggregateWithId \" +\n\t\t\t\t\t\t\t\"and keep insertsAreDuplicateChecked: the duplicate-add \" +\n\t\t\t\t\t\t\t\"proof is its only concurrency proof\",\n\t\t\t\t\t);\n\t\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\t\t// Mutated twice so its version differs from the seeded\n\t\t\t\t\t// row's: a clobbering insert is then visible in the\n\t\t\t\t\t// version check even without a state snapshot.\n\t\t\t\t\tconst duplicate = createAggregateWithId.call(harness, seeded.id);\n\t\t\t\t\tharness.mutate(duplicate);\n\t\t\t\t\tharness.mutate(duplicate);\n\t\t\t\t\tconst rejection = await captureRejection(\n\t\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\t\trepository.add(duplicate);\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\t// Exactly DUPLICATE_AGGREGATE, not a retryable conflict:\n\t\t\t\t\t// the docs instruct mapping uniqueness violations\n\t\t\t\t\t// (Postgres 23505, MySQL 1062, SQLite\n\t\t\t\t\t// SQLITE_CONSTRAINT_UNIQUE) to DuplicateAggregateError,\n\t\t\t\t\t// and a duplicate add is deterministic and must not be\n\t\t\t\t\t// retried unchanged.\n\t\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\t\trejection,\n\t\t\t\t\t\t[\"DUPLICATE_AGGREGATE\"],\n\t\t\t\t\t\t`duplicate add must reject with (or wrap) ` +\n\t\t\t\t\t\t\t`DuplicateAggregateError; map your driver's ` +\n\t\t\t\t\t\t\t`unique-violation signal instead of a retryable ` +\n\t\t\t\t\t\t\t`conflict; got ${describeError(rejection)}`,\n\t\t\t\t\t);\n\t\t\t\t\t// The existing row is untouched by the rejected insert:\n\t\t\t\t\t// version and (capability permitting) state.\n\t\t\t\t\tconst final = await reload(environment, seeded.id);\n\t\t\t\t\tassertEqual(\n\t\t\t\t\t\tfinal.version,\n\t\t\t\t\t\tseeded.version,\n\t\t\t\t\t\t\"the existing row must be untouched by the rejected \" +\n\t\t\t\t\t\t\t\"duplicate add; a duplicate check firing after the \" +\n\t\t\t\t\t\t\t\"write clobbers it\",\n\t\t\t\t\t);\n\t\t\t\t\tif (snapshotState) {\n\t\t\t\t\t\tassert(\n\t\t\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\t\t\tsnapshotState.call(harness, final),\n\t\t\t\t\t\t\t\tsnapshotState.call(harness, seeded),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\"the existing row's state must be untouched by the \" +\n\t\t\t\t\t\t\t\t\"rejected duplicate add\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t);\n\n\ttests.push(\n\t\tgatedContractTest(\n\t\t\tupdateGate,\n\t\t\tgatedContractTest(\n\t\t\t\t{\n\t\t\t\t\tcapability: \"mutateVersionOnly\",\n\t\t\t\t\tsatisfiedBy: Boolean(mutateVersionOnly),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: \"version-only change still persists (skip-save must not desync the OCC baseline)\",\n\t\t\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\t\t\tassert(mutateVersionOnly !== undefined, \"capability gate\");\n\t\t\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\t\t\tconst outboxBefore = await environment.committedOutboxEvents();\n\t\t\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\t\t\tconst aggregate = await load(repository, seeded.id);\n\t\t\t\t\t\t\tmutateVersionOnly.call(harness, aggregate);\n\t\t\t\t\t\t\tupdate(repository, aggregate);\n\t\t\t\t\t\t});\n\t\t\t\t\t\tconst reloaded = await reload(environment, seeded.id);\n\t\t\t\t\t\t// The harness contract keeps the projection deep-equal, so a\n\t\t\t\t\t\t// diff-based model derives an EMPTY change set here: an\n\t\t\t\t\t\t// adapter that skips empty writes fails this reload.\n\t\t\t\t\t\tassertEqual(\n\t\t\t\t\t\t\treloaded.version,\n\t\t\t\t\t\t\tseeded.version + 1,\n\t\t\t\t\t\t\t\"a version-only change (empty change set, bumped version) \" +\n\t\t\t\t\t\t\t\t\"must still be persisted; skipping it desyncs the \" +\n\t\t\t\t\t\t\t\t\"persisted version and produces false concurrency \" +\n\t\t\t\t\t\t\t\t\"conflicts later\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert(\n\t\t\t\t\t\t\tdeepEqual(\n\t\t\t\t\t\t\t\teventIds(await environment.committedOutboxEvents()),\n\t\t\t\t\t\t\t\teventIds(outboxBefore),\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\"state-only update must not create an outbox event\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t),\n\t\t),\n\t);\n\n\ttests.push(\n\t\tgatedContractTest(\n\t\t\tupdateGate,\n\t\t\tgatedContractTest(\n\t\t\t\t{\n\t\t\t\t\tcapability: \"mutateChildCollection\",\n\t\t\t\t\tsatisfiedBy: Boolean(mutateChildCollection),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: \"nested collection changes survive the adapter change-set projection\",\n\t\t\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\t\t\tassert(mutateChildCollection !== undefined, \"capability gate\");\n\t\t\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\t\t\tconst aggregate = await load(repository, seeded.id);\n\t\t\t\t\t\t\tmutateChildCollection.call(harness, aggregate);\n\t\t\t\t\t\t\tupdate(repository, aggregate);\n\t\t\t\t\t\t});\n\t\t\t\t\t\tconst reloaded = await reload(environment, seeded.id);\n\t\t\t\t\t\tassertEqual(\n\t\t\t\t\t\t\treloaded.version,\n\t\t\t\t\t\t\tseeded.version + 1,\n\t\t\t\t\t\t\t\"nested collection update must advance the persisted root version\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t),\n\t\t),\n\t);\n\n\ttests.push(\n\t\tgatedContractTest(\n\t\t\t{\n\t\t\t\tcapability: \"removesAreSupported\",\n\t\t\t\tsatisfiedBy: removesAreSupported,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"remove tombstones the identity and physically removes at commit\",\n\t\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\t\tawait environment.run(async ({ repository }) => {\n\t\t\t\t\t\tassert(repository.remove !== undefined, \"remove capability gate\");\n\t\t\t\t\t\tconst aggregate = await load(repository, seeded.id);\n\t\t\t\t\t\trepository.remove(aggregate);\n\t\t\t\t\t\tassert(\n\t\t\t\t\t\t\t(await repository.findById(seeded.id)) === undefined,\n\t\t\t\t\t\t\t\"a removed aggregate is immediately absent from the Unit of Work\",\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t\t\tassert(\n\t\t\t\t\t\t(await environment.run(({ repository }) =>\n\t\t\t\t\t\t\trepository.findById(seeded.id),\n\t\t\t\t\t\t)) === undefined,\n\t\t\t\t\t\t\"remove must physically remove the aggregate after commit\",\n\t\t\t\t\t);\n\t\t\t\t}),\n\t\t\t},\n\t\t),\n\t);\n\n\ttests.push(\n\t\tgatedContractTest(\n\t\t\tupdateGate,\n\t\t\tgatedContractTest(\n\t\t\t\t{\n\t\t\t\t\tcapability: \"removesAreVersionChecked\",\n\t\t\t\t\tsatisfiedBy: removesAreVersionChecked,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: \"stale remove conflicts and cannot delete a concurrent update\",\n\t\t\t\t\trun: inEnvironment(async (environment) => {\n\t\t\t\t\t\tconst seeded = await seed(environment);\n\t\t\t\t\t\tconst staleRemove = await parkRunCall((hold) =>\n\t\t\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\t\t\tassert(\n\t\t\t\t\t\t\t\t\trepository.remove !== undefined,\n\t\t\t\t\t\t\t\t\t\"remove capability gate\",\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tconst stale = await load(repository, seeded.id);\n\t\t\t\t\t\t\t\tawait hold();\n\t\t\t\t\t\t\t\trepository.remove(stale);\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait awaitOverlappingCall(\n\t\t\t\t\t\t\t() =>\n\t\t\t\t\t\t\t\tenvironment.run(async ({ repository }) => {\n\t\t\t\t\t\t\t\t\tconst current = await load(repository, seeded.id);\n\t\t\t\t\t\t\t\t\tharness.mutate(current);\n\t\t\t\t\t\t\t\t\tupdate(repository, current);\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tstaleRemove,\n\t\t\t\t\t\t\toverlappingCallsBoundMs,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tstaleRemove.release();\n\t\t\t\t\t\tconst rejection = await captureRejection(staleRemove.call);\n\t\t\t\t\t\tassertChainContainsKitError(\n\t\t\t\t\t\t\trejection,\n\t\t\t\t\t\t\t[\"CONCURRENCY_CONFLICT\"],\n\t\t\t\t\t\t\t`stale remove must reject with ConcurrencyConflictError; got ${describeError(rejection)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert(\n\t\t\t\t\t\t\t(await reload(environment, seeded.id)) !== undefined,\n\t\t\t\t\t\t\t\"stale remove must not delete the concurrent winner\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t),\n\t\t),\n\t);\n\n\treturn tests;\n}\n","import type { AggregateSnapshot, Version } from \"../domain/aggregate/aggregate\";\nimport type { AggregateAddress } from \"../domain/aggregate/aggregate-address\";\nimport type { Id } from \"../domain/identity/id\";\nimport { deepEqual } from \"../internal/structural/deep-equal\";\nimport type { SnapshotStore } from \"../persistence/snapshot-store/snapshot-store\";\nimport {\n\tassert,\n\tassertEqual,\n\tbindContractEnvironment,\n\ttype ContractTest,\n} from \"./contract-assertions\";\n\n/** One contract test; bind with `(test.skipped ? it.skip : it)(test.name, test.run)`. */\nexport type SnapshotStoreContractTest = ContractTest;\n\n/** The plain-data state shape the suite round-trips. */\ninterface SuiteState {\n\ttotal: number;\n\titems: Array<{ sku: string; qty: number }>;\n\tnote?: string;\n}\n\n/**\n * One isolated test environment: a fresh snapshot store. The suite\n * creates one per test and tears it down afterwards. No transaction\n * wrapper: the port is transaction-free by design (snapshots are\n * derived data written after the commit; see `SnapshotStore`).\n */\nexport interface SnapshotStoreContractEnvironment {\n\t/** The adapter under test. */\n\tstore: SnapshotStore<SuiteState>;\n\n\t/** Release connections, drop schemas, etc. Called in a finally. */\n\tteardown?(): Promise<void>;\n}\n\n/**\n * What an adapter supplies to run the snapshot-store contract suite.\n * For SQL adapters, run against a real database (testcontainers or\n * equivalent). Note the fidelity demands the suite enforces:\n * `snapshotAt` must survive with millisecond precision (store it as\n * ISO-8601 text or epoch milliseconds; MySQL `DATETIME` without\n * fractional seconds truncates), and an ABSENT `schemaVersion` must\n * come back absent, not as `0` or `null`-coerced.\n */\nexport interface SnapshotStoreContractHarness {\n\tcreateEnvironment(): Promise<SnapshotStoreContractEnvironment>;\n}\n\nconst AT = new Date(\"2026-01-05T10:20:30.456Z\");\n\nfunction snapshot(\n\tversion: number,\n\tstate: SuiteState,\n\tschemaVersion?: number,\n): AggregateSnapshot<SuiteState> {\n\treturn {\n\t\tstate,\n\t\tversion: version as Version,\n\t\t// A fresh Date per snapshot: an adapter that normalizes the input\n\t\t// Date IN PLACE must not be able to mutate the suite's expected\n\t\t// value into agreeing with it.\n\t\tsnapshotAt: new Date(AT),\n\t\t...(schemaVersion === undefined ? {} : { schemaVersion }),\n\t};\n}\n\nconst id = (value: string): Id<string> => value as Id<string>;\nconst address = (\n\taggregateType: string,\n\taggregateId: string,\n): AggregateAddress<Id<string>> => ({\n\taggregateType,\n\taggregateId: id(aggregateId),\n});\n\n/**\n * The snapshot-store contract test suite: the proof that an adapter\n * delivers the round-trip and isolation semantics the\n * snapshot-plus-recent-events load path relies on. Store semantics are\n * an **adapter contract, not a kit guarantee**; this suite is how an\n * adapter demonstrates them.\n *\n * Framework-agnostic: bind with\n * `(test.skipped ? it.skip : it)(test.name, test.run)`.\n */\nexport function createSnapshotStoreContractTests(\n\tharness: SnapshotStoreContractHarness,\n): SnapshotStoreContractTest[] {\n\tconst inEnv = bindContractEnvironment(() => harness.createEnvironment());\n\n\treturn [\n\t\t{\n\t\t\tname: \"an aggregate without a snapshot loads undefined\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait env.store.load(address(\"Order\", \"o-1\")),\n\t\t\t\t\tundefined,\n\t\t\t\t\t\"a fresh store must report no snapshot; the repository falls back to full replay\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"save/load round-trips state, version, snapshotAt (millisecond fidelity), and schemaVersion\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst stored = snapshot(\n\t\t\t\t\t42,\n\t\t\t\t\t{ total: 7, items: [{ sku: \"a\", qty: 2 }], note: \"hi\" },\n\t\t\t\t\t3,\n\t\t\t\t);\n\t\t\t\tawait env.store.save(address(\"Order\", \"o-1\"), stored);\n\t\t\t\tconst loaded = await env.store.load(address(\"Order\", \"o-1\"));\n\t\t\t\tassert(loaded !== undefined, \"the saved snapshot must load\");\n\t\t\t\tassert(\n\t\t\t\t\tdeepEqual(loaded.state, stored.state),\n\t\t\t\t\t\"the state must round-trip deep-equal as plain data\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tloaded.version,\n\t\t\t\t\t42,\n\t\t\t\t\t\"the aggregate version must round-trip\",\n\t\t\t\t);\n\t\t\t\tassert(\n\t\t\t\t\tloaded.snapshotAt instanceof Date,\n\t\t\t\t\t\"snapshotAt must round-trip as a Date; rehydrate your storage format (ISO-8601 text, epoch ms) on load\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tloaded.snapshotAt.getTime(),\n\t\t\t\t\tAT.getTime(),\n\t\t\t\t\t\"snapshotAt must survive with millisecond precision (store ISO-8601 text or epoch ms)\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\tloaded.schemaVersion,\n\t\t\t\t\t3,\n\t\t\t\t\t\"schemaVersion must round-trip verbatim; the restore path compares it against the aggregate's declared schema\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"an absent schemaVersion round-trips as absent\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.store.save(\n\t\t\t\t\taddress(\"Order\", \"o-1\"),\n\t\t\t\t\tsnapshot(1, { total: 0, items: [] }),\n\t\t\t\t);\n\t\t\t\tconst loaded = await env.store.load(address(\"Order\", \"o-1\"));\n\t\t\t\tassertEqual(\n\t\t\t\t\tloaded?.schemaVersion,\n\t\t\t\t\tundefined,\n\t\t\t\t\t\"a snapshot stored without schemaVersion must not come back with a fabricated one; restore treats absence as schema 1\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"save replaces the previous snapshot: latest wins, no history\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.store.save(\n\t\t\t\t\taddress(\"Order\", \"o-1\"),\n\t\t\t\t\tsnapshot(10, { total: 1, items: [] }),\n\t\t\t\t);\n\t\t\t\tawait env.store.save(\n\t\t\t\t\taddress(\"Order\", \"o-1\"),\n\t\t\t\t\tsnapshot(20, { total: 2, items: [] }),\n\t\t\t\t);\n\t\t\t\tconst loaded = await env.store.load(address(\"Order\", \"o-1\"));\n\t\t\t\tassert(\n\t\t\t\t\tloaded?.version === 20 && loaded.state.total === 2,\n\t\t\t\t\t\"load must return the latest snapshot only\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"snapshots are isolated per aggregate type AND per aggregate id\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.store.save(\n\t\t\t\t\taddress(\"Order\", \"x-1\"),\n\t\t\t\t\tsnapshot(1, { total: 1, items: [] }),\n\t\t\t\t);\n\t\t\t\tawait env.store.save(\n\t\t\t\t\taddress(\"Invoice\", \"x-1\"),\n\t\t\t\t\tsnapshot(2, { total: 2, items: [] }),\n\t\t\t\t);\n\t\t\t\tawait env.store.save(\n\t\t\t\t\taddress(\"Order\", \"x-2\"),\n\t\t\t\t\tsnapshot(3, { total: 3, items: [] }),\n\t\t\t\t);\n\t\t\t\tconst [orderX1, invoiceX1, orderX2] = await Promise.all([\n\t\t\t\t\tenv.store.load(address(\"Order\", \"x-1\")),\n\t\t\t\t\tenv.store.load(address(\"Invoice\", \"x-1\")),\n\t\t\t\t\tenv.store.load(address(\"Order\", \"x-2\")),\n\t\t\t\t]);\n\t\t\t\tassert(\n\t\t\t\t\torderX1?.version === 1 &&\n\t\t\t\t\t\tinvoiceX1?.version === 2 &&\n\t\t\t\t\t\torderX2?.version === 3,\n\t\t\t\t\t\"the key is the (aggregateType, aggregateId) pair; neither half may bleed into the other\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"delete removes exactly the addressed snapshot and tolerates unknown keys\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tawait env.store.save(\n\t\t\t\t\taddress(\"Order\", \"o-1\"),\n\t\t\t\t\tsnapshot(1, { total: 1, items: [] }),\n\t\t\t\t);\n\t\t\t\tawait env.store.save(\n\t\t\t\t\taddress(\"Order\", \"o-2\"),\n\t\t\t\t\tsnapshot(2, { total: 2, items: [] }),\n\t\t\t\t);\n\t\t\t\tawait env.store.delete(address(\"Order\", \"o-1\"));\n\t\t\t\tawait env.store.delete(address(\"Order\", \"never-saved\"));\n\t\t\t\tassertEqual(\n\t\t\t\t\tawait env.store.load(address(\"Order\", \"o-1\")),\n\t\t\t\t\tundefined,\n\t\t\t\t\t\"the deleted snapshot must be gone (schema-migration fallback and erasure both rely on it)\",\n\t\t\t\t);\n\t\t\t\tassertEqual(\n\t\t\t\t\t(await env.store.load(address(\"Order\", \"o-2\")))?.version,\n\t\t\t\t\t2,\n\t\t\t\t\t\"a sibling snapshot must survive the delete\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t\t{\n\t\t\tname: \"loads are detached copies and saves capture the input: later mutations touch nothing\",\n\t\t\trun: inEnv(async (env) => {\n\t\t\t\tconst input = snapshot(5, { total: 5, items: [{ sku: \"a\", qty: 1 }] });\n\t\t\t\tawait env.store.save(address(\"Order\", \"o-1\"), input);\n\t\t\t\t// Mutating the caller's input AFTER save must not reach the store.\n\t\t\t\tinput.state.items.push({ sku: \"hacked\", qty: 99 });\n\n\t\t\t\tconst loaded = await env.store.load(address(\"Order\", \"o-1\"));\n\t\t\t\tassert(loaded !== undefined, \"expected the saved snapshot\");\n\t\t\t\tassertEqual(\n\t\t\t\t\tloaded.state.items.length,\n\t\t\t\t\t1,\n\t\t\t\t\t\"save must capture the snapshot by value, not hold the caller's reference\",\n\t\t\t\t);\n\t\t\t\t// Mutating the loaded copy must not corrupt the stored one.\n\t\t\t\tloaded.state.total = 999;\n\t\t\t\tconst reloaded = await env.store.load(address(\"Order\", \"o-1\"));\n\t\t\t\tassertEqual(\n\t\t\t\t\treloaded?.state.total,\n\t\t\t\t\t5,\n\t\t\t\t\t\"load must hand out a detached copy, never live internal state\",\n\t\t\t\t);\n\t\t\t}),\n\t\t},\n\t];\n}\n"],"mappings":"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"}