@eventsdk/sdk 0.3.1 → 0.4.0

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.
@@ -0,0 +1,13 @@
1
+ import type { EventLinkTokenRequest } from '@eventsdk/sdk/contracts';
2
+ import type { EventLinkReceiver, EventLinkReceiverActor } from '@eventsdk/sdk/event-link';
3
+ export interface EventLinkReceiverHarness {
4
+ readonly receiver: EventLinkReceiver;
5
+ readonly params: URLSearchParams;
6
+ readonly actor: EventLinkReceiverActor;
7
+ token(code: string): EventLinkTokenRequest;
8
+ revokeActor(): Promise<void>;
9
+ revokeGrant(): Promise<void>;
10
+ reopen(): Promise<void>;
11
+ close(): Promise<void>;
12
+ }
13
+ export type EventLinkReceiverHarnessFactory = () => Promise<EventLinkReceiverHarness>;
@@ -0,0 +1,2 @@
1
+ import type { EventLinkReceiverHarnessFactory } from './harness.js';
2
+ export declare function runEventLinkReceiverConformance(factory: EventLinkReceiverHarnessFactory): Promise<readonly import("../index.js").ConformanceCaseResult[]>;
@@ -18,3 +18,5 @@ export { runReceiptProjectionConformance } from './receipt/run-projection-suite.
18
18
  export type { ReceiptProjectionHarness, ReceiptProjectionHarnessFactory, } from './receipt/projection-harness.js';
19
19
  export { runFanoutConformance } from './fanout/run-suite.js';
20
20
  export type { FanoutHarness, FanoutHarnessFactory, FanoutTarget, FanoutObservation, } from './fanout/harness.js';
21
+ export { runEventLinkReceiverConformance } from './event-link/run-suite.js';
22
+ export type { EventLinkReceiverHarness, EventLinkReceiverHarnessFactory, } from './event-link/harness.js';
@@ -1 +1 @@
1
- import assert from"node:assert/strict";import{acceptDelivery}from"@eventsdk/sdk/core";var options={timeoutMs:1e3};function input(harness,consumerRef="conformance-consumer"){return{event:harness.event,origin:harness.origin,deliveryRef:"delivery-1",consumerRef}}async function duplicateCase(harness){const first=await acceptDelivery(input(harness),harness.dependencies(),options);const second=await acceptDelivery(input(harness),harness.dependencies(),options);assert.equal(first.kind,"RECEIVED");assert.equal(second.kind,"DUPLICATE");assert.equal((await harness.accepted()).length,1)}async function conflictCase(harness){await acceptDelivery(input(harness),harness.dependencies(),options);const changed={...input(harness),event:{...harness.event,data:{conflict:true}}};const result=await acceptDelivery(changed,harness.dependencies(),options);assert.equal(result.kind,"REJECTED");assert.equal((await harness.accepted()).length,1);assert.equal((await harness.quarantined())[0]?.reasonCode,"EVENT_ID_CONFLICT")}async function consumerIsolationCase(harness){await acceptDelivery(input(harness,"consumer-a"),harness.dependencies(),options);await acceptDelivery(input(harness,"consumer-b"),harness.dependencies(),options);assert.equal((await harness.accepted()).length,2)}async function tenantIsolationCase(harness){await acceptDelivery(input(harness),harness.dependencies(),options);harness.setAuthorization({decision:"ALLOW",source:harness.event.source,targetScope:"urn:target:tenant:other",connectionRef:harness.event.connectionref,grantRef:harness.event.grantref,grantVersion:harness.event.grantversion});await acceptDelivery(input(harness),harness.dependencies(),options);const records=await harness.accepted();assert.equal(records.length,2);assert.notEqual(records[0]?.key.targetScope,records[1]?.key.targetScope)}async function commitFailureCase(harness){harness.failNextCommit();await assert.rejects(acceptDelivery(input(harness),harness.dependencies(),options));assert.equal((await harness.accepted()).length,0);const retry=await acceptDelivery(input(harness),harness.dependencies(),options);assert.equal(retry.kind,"RECEIVED")}async function reopenCase(harness){await acceptDelivery(input(harness),harness.dependencies(),options);await harness.reopen();const retry=await acceptDelivery(input(harness),harness.dependencies(),options);assert.equal(retry.kind,"DUPLICATE")}async function revokedCase(harness){harness.setAuthorization({decision:"DENY",reasonCode:"GRANT_REVOKED"});const result=await acceptDelivery(input(harness),harness.dependencies(),options);assert.equal(result.kind,"REJECTED");assert.equal((await harness.accepted()).length,0)}async function unknownCase(harness){harness.setAuthorization({decision:"UNKNOWN",reasonCode:"AUTHORITY_UNAVAILABLE"});await assert.rejects(acceptDelivery(input(harness),harness.dependencies(),options),{code:"AUTHORIZATION_UNKNOWN"});assert.equal((await harness.accepted()).length,0)}async function spoofedOriginCase(harness){const delivery={...input(harness),origin:{...harness.origin,serviceRef:"spoofed"}};const result=await acceptDelivery(delivery,harness.dependencies(),options);assert.equal(result.kind,"REJECTED");assert.equal((await harness.accepted()).length,0)}var scenarios=[["E4.DEDUPLICATE",duplicateCase],["E1.EVENT_ID_CONFLICT",conflictCase],["E4.CONSUMER_ISOLATION",consumerIsolationCase],["E2.TENANT_ISOLATION",tenantIsolationCase],["E4.COMMIT_BEFORE_ACK",commitFailureCase],["E5.REOPEN_DEDUPLICATION",reopenCase],["E2.GRANT_REVOKED",revokedCase],["E2.UNKNOWN_FAIL_CLOSED",unknownCase],["E2.ORIGIN_MISMATCH",spoofedOriginCase]];async function runAdmissionConformance(factory){const results=[];for(const[id,scenario]of scenarios){const harness=await factory();try{await scenario(harness);results.push({id,passed:true})}catch{results.push({id,passed:false,failureCode:"ASSERTION_FAILED"})}finally{await harness.close()}}return results}var profilesBySdk={"0.1.0":["eventsdk/1.0"],"0.2.0":["eventsdk/1.0","eventsdk/1.1"],"0.3.0":["eventsdk/1.0","eventsdk/1.1","eventsdk/1.2"],"0.3.1":["eventsdk/1.0","eventsdk/1.1","eventsdk/1.2"]};function checkCompatibility(producer,consumer){for(const version of[producer,consumer]){if(!Object.hasOwn(profilesBySdk,version.sdkVersion)||version.schemaMajor!==1||version.cloudEvents!=="1.0")return{compatible:false,reason:"UNSUPPORTED_VERSION"}}if(producer.profile!==consumer.profile)return{compatible:false,reason:"PROFILE_MISMATCH"};for(const version of[producer,consumer]){if(!profilesBySdk[version.sdkVersion]?.includes(version.profile))return{compatible:false,reason:"UNSUPPORTED_VERSION"}}return{compatible:true}}import assert2 from"node:assert/strict";import{assertLiveLease,decideRetry,recoverGap,recoverReceipt,stageEventLogPage}from"@eventsdk/sdk/core";function checkRetryAndFence(){const policy={maxAttempts:4,baseDelayMs:100,maxDelayMs:250,jitterRatio:.25};for(const sample of[0,.5,.999999]){for(let attempt=1;attempt<4;attempt++){const result=decideRetry(attempt,1e3,policy,{next:()=>sample});assert2.equal(result.kind,"RETRY");if(result.kind==="RETRY")assert2.ok(result.nextAttemptAt>=1e3&&result.nextAttemptAt<=1250)}}assert2.deepEqual(decideRetry(4,1e3,policy,{next:()=>0}),{kind:"EXHAUSTED"});for(const lease of[{token:"old",generation:1,expiresAt:999},{token:"",generation:1,expiresAt:2e3},{token:"token",generation:0,expiresAt:2e3}])assert2.throws(()=>assertLiveLease(lease,1e3),{code:"STALE_LEASE"})}async function checkGapIsNotSkipped(){let staged=false;let gapRecorded=false;const result=await stageEventLogPage("3",10,{readAfter:async()=>({kind:"GAP",oldestAvailableCursor:"9"})},{recordGap:async(expected,oldest)=>{assert2.equal(expected,"3");assert2.equal(oldest,"9");gapRecorded=true},stageAndAdvance:async()=>{staged=true}},{timeoutMs:1e3});assert2.equal(result,"GAP");assert2.equal(gapRecorded,true);assert2.equal(staged,false);await assert2.rejects(recoverGap("source-a","tenant-a","3",{readAuthorized:async()=>null,applyAndCheckpoint:async()=>{staged=true}},{timeoutMs:1e3}),{code:"RECOVERY_REQUIRED"});assert2.equal(staged,false)}async function checkUnknownReceipt(receipt){const key2={source:receipt.originSource,id:receipt.originEventId,consumerRef:receipt.consumerRef,targetScope:receipt.targetScope};for(const disposition of["RECEIVED","UNKNOWN","HOLD"]){const observation=await recoverReceipt(key2,receipt.deliveryRef,{read:async()=>({...receipt,disposition})},{timeoutMs:1e3});assert2.equal(observation.status,"WAIT")}await assert2.rejects(recoverReceipt(key2,receipt.deliveryRef,{read:async()=>({...receipt,originEventId:"different-event"})},{timeoutMs:1e3}),{code:"RECEIPT_MISMATCH"})}async function runCases(factory,cases){const results=[];for(const[id,check]of cases){const harness=await factory();try{await check(harness);results.push({id,passed:true})}catch{results.push({id,passed:false,failureCode:"ASSERTION_FAILED"})}finally{await harness.close()}}return results}import assert3 from"node:assert/strict";import{recordEvent,relayOutbox}from"@eventsdk/sdk/core";var options2={timeoutMs:2e3};var relayOptions={...options2,batchSize:1,leaseMs:1e4,retry:{maxAttempts:4,baseDelayMs:0,maxDelayMs:1,jitterRatio:0}};async function record(h){await h.transaction(async tx=>{await h.writeDomain(tx);await recordEvent(tx,h.event,h.origin,h.dependencies(),options2)})}async function rollbackCase(h){await assert3.rejects(h.transaction(async tx=>{await h.writeDomain(tx);await recordEvent(tx,h.event,h.origin,h.dependencies(),options2);throw new Error("SYNTHETIC_DOMAIN_ROLLBACK")}),{message:"SYNTHETIC_DOMAIN_ROLLBACK"});assert3.deepEqual(await h.inspect(),{domainCount:0,outboxCount:0,states:[]})}async function unknownReopenCase(h){await record(h);const ids=[];const first=await relayOutbox({...h.dependencies(),publisher:{publish:async(event,context)=>{assert3.equal(event.source,h.event.source);assert3.equal(event.id,h.event.id);ids.push(context.messageId);throw new Error("SYNTHETIC_PUBACK_LOSS")}}},relayOptions);assert3.equal(first.unknown,1);assert3.deepEqual((await h.inspect()).states,["UNKNOWN"]);await h.reopen();assert3.deepEqual((await h.inspect()).states,["UNKNOWN"]);const second=await relayOutbox({...h.dependencies(),publisher:{publish:async(event,context)=>{assert3.equal(event.id,h.event.id);ids.push(context.messageId);return{stream:"probe",sequence:1,duplicate:true}}}},relayOptions);assert3.equal(second.published,1);assert3.equal(ids.length,2);assert3.equal(ids[0],ids[1]);assert3.deepEqual(await h.inspect(),{domainCount:1,outboxCount:1,states:["PUBLISHED"]})}function settleClaim(outbox,claim,outcome,signal){if(claim.event.profile==="eventsdk/1.2"){assert3.ok(outbox.settleFanoutPublish,"profile1.2 requires per-delivery fenced settlement");return outbox.settleFanoutPublish(claim.event,claim.lease,outcome,signal)}return outbox.settlePublish(claim.event,claim.lease,outcome,signal)}async function fencingCase(h){await record(h);const deps=h.dependencies();const claimInput={limit:1,now:deps.clock.now(),leaseMs:1e4,signal:AbortSignal.timeout(2e3)};const old=(await deps.outbox.claimReady(claimInput))[0];assert3.ok(old);await h.expireLease();const fresh=(await deps.outbox.claimReady({...claimInput,now:deps.clock.now()}))[0];assert3.ok(fresh);assert3.ok(fresh.lease.generation>old.lease.generation);const published={status:"PUBLISHED",ack:{stream:"probe",sequence:1,duplicate:false}};await assert3.rejects(settleClaim(deps.outbox,old,published,claimInput.signal),{code:"STALE_LEASE"});await settleClaim(deps.outbox,fresh,published,claimInput.signal);assert3.deepEqual((await h.inspect()).states,["PUBLISHED"])}async function revocationCase(h){await record(h);await h.setAuthorized(false);let calls=0;const result=await relayOutbox({...h.dependencies(),publisher:{publish:async()=>{calls++;return{stream:"probe",sequence:1,duplicate:false}}}},relayOptions);assert3.equal(result.held,1);assert3.equal(calls,0);assert3.deepEqual((await h.inspect()).states,["HOLD"])}function runProducerConformance(factory){return runCases(factory,[["E4.PRODUCER_ATOMIC_ROLLBACK",rollbackCase],["E5.PRODUCER_UNKNOWN_REOPEN_STABLE_ID",unknownReopenCase],["E5.PRODUCER_FENCING",fencingCase],["E2.PRODUCER_CURRENT_AUTHORIZATION",revocationCase]])}import assert4 from"node:assert/strict";import{recoverReceipt as recoverReceipt2}from"@eventsdk/sdk/core";var read=h=>recoverReceipt2(h.key,h.receipt.deliveryRef,h.reader(),{timeoutMs:2e3});async function waiting(h){for(const disposition of["RECEIVED","HOLD","UNKNOWN"]){await h.persist({...h.receipt,disposition});assert4.equal((await read(h)).status,"WAIT")}}async function correlation(h){for(const field of["originSource","originEventId","deliveryRef","consumerRef","targetScope"]){await h.persist({...h.receipt,[field]:h.receipt[field]+"-wrong"});await assert4.rejects(read(h),{code:"RECEIPT_MISMATCH"})}}async function durable(h){const receipt={...h.receipt,disposition:"APPLIED"};await h.persist(receipt);await h.reopen();assert4.deepEqual(await read(h),{status:"RESOLVED",receipt})}async function rejected(h){const receipt={...h.receipt,disposition:"REJECTED",reasonCode:"BUSINESS_REFUSED"};await h.persist(receipt);await h.reopen();assert4.deepEqual(await read(h),{status:"RESOLVED",receipt})}async function denial(h){await h.persist(h.receipt);await h.setAuthorized(false);await assert4.rejects(read(h),{code:"AUTHORIZATION_DENIED"})}function runReceiptConformance(factory){return runCases(factory,[["E6.RECEIPT_UNKNOWN_WAIT",waiting],["E6.RECEIPT_EXACT_CORRELATION",correlation],["E6.RECEIPT_DURABLE_REOPEN",durable],["E6.RECEIPT_REJECTED_DURABLE_REOPEN",rejected],["E2.RECEIPT_CURRENT_AUTHORIZATION",denial]])}import assert5 from"node:assert/strict";import{readAuthorizedResult}from"@eventsdk/sdk/core";var read2=h=>readAuthorizedResult(h.request,h.reader,h.authorization,h.digest,AbortSignal.timeout(2e3),h.clock);async function exact(h){assert5.deepEqual((await read2(h)).reference,h.request.reference)}async function revision(h){await h.mutateSource("REVISION");await assert5.rejects(read2(h),{code:"RESULT_MISMATCH"})}async function digest(h){await h.mutateSource("VALUE");await assert5.rejects(read2(h),{code:"RESULT_MISMATCH"})}async function missing(h){await h.mutateSource("ABSENT");await assert5.rejects(read2(h),{code:"RECOVERY_REQUIRED"})}async function sourceDenial(h){await h.setSourceAuthorized(false);await assert5.rejects(read2(h),{code:"AUTHORIZATION_DENIED"})}async function sourceScope(h){await assert5.rejects(h.reader.read(h.request.reference,{event:h.request.event,origin:h.request.origin,targetScope:h.request.targetScope+"-unauthorized",signal:AbortSignal.timeout(2e3)}),{code:"AUTHORIZATION_DENIED"})}async function receiverDenial(h){await h.setReceiverAuthorized(false);await assert5.rejects(read2(h),{code:"AUTHORIZATION_DENIED"});assert5.equal(h.sourceReads(),0)}function runResultConformance(factory){return runCases(factory,[["E7.RESULT_EXACT_REFERENCE",exact],["E7.RESULT_REVISION_MISMATCH",revision],["E7.RESULT_DIGEST_MISMATCH",digest],["E7.RESULT_MISSING",missing],["E2.RESULT_SOURCE_AUTHORIZATION",sourceDenial],["E2.RESULT_SOURCE_SCOPE",sourceScope],["E2.RESULT_RECEIVER_DENIAL_NO_READ",receiverDenial]])}import assert6 from"node:assert/strict";import{applyDelivery}from"@eventsdk/sdk/core";function observedEffect(h,claim){let calls=0;return{calls:()=>calls,domain:{apply:async tx=>{calls++;await h.writeEffect(tx,claim)}}}}async function rollback(h){const claim=await h.claim();const before=await h.inspect();await assert6.rejects(applyDelivery(claim,{...h.dependencies(),domain:{apply:async(tx,current)=>{await h.writeEffect(tx,current);throw new Error("CONFORMANCE_AFTER_EFFECT")}}},h.options));assert6.deepEqual(await h.inspect(),before)}async function terminal(h){const claim=await h.claim();const effect=observedEffect(h,claim);const deps={...h.dependencies(),domain:effect.domain};const receipt=await applyDelivery(claim,deps,h.options);assert6.equal(receipt.disposition,"APPLIED");await assert6.rejects(applyDelivery(claim,deps,h.options));assert6.equal(effect.calls(),1);await h.reopen();const actual=await h.inspect();assert6.deepEqual(actual.receipt,receipt);assert6.equal(actual.effects,1)}async function receiptFailure(h){const claim=await h.claim();const effect=observedEffect(h,claim);const before=await h.inspect();await h.failNextReceiptCommit();await assert6.rejects(applyDelivery(claim,{...h.dependencies(),domain:effect.domain},h.options));assert6.equal(effect.calls(),1);assert6.deepEqual(await h.inspect(),before)}async function staleFence(h){const claim=await h.claim();const effect=observedEffect(h,claim);const before=await h.inspect();await h.invalidateLease();await assert6.rejects(applyDelivery(claim,{...h.dependencies(),domain:effect.domain},h.options));assert6.equal(effect.calls(),0);assert6.deepEqual(await h.inspect(),before)}async function revoked(h){const claim=await h.claim();const effect=observedEffect(h,claim);await h.setAuthorized(false);const receipt=await applyDelivery(claim,{...h.dependencies(),domain:effect.domain},h.options);assert6.equal(effect.calls(),0);assert6.equal(receipt.disposition,"REJECTED");assert6.equal((await h.inspect()).effects,0);await h.reopen();assert6.deepEqual((await h.inspect()).receipt,receipt)}async function businessOutcome(h,disposition){const claim=await h.claim();const receipt=await applyDelivery(claim,{...h.dependencies(),domain:{apply:async tx=>{await h.writeEffect(tx,claim);return{disposition,reasonCode:"BUSINESS_CONDITION_UNMET"}}}},h.options);assert6.equal(receipt.disposition,disposition);assert6.equal(receipt.reasonCode,"BUSINESS_CONDITION_UNMET");assert6.equal((await h.inspect()).effects,0);await h.reopen();assert6.deepEqual((await h.inspect()).receipt,receipt)}function runApplyConformance(factory){return runCases(factory,[["E4.APPLY_EFFECT_ROLLBACK",rollback],["E4.APPLY_TERMINAL_DURABLE_ONCE",terminal],["E4.APPLY_RECEIPT_FAILURE_ROLLBACK",receiptFailure],["E5.APPLY_STALE_FENCE",staleFence],["E2.APPLY_REVOKED",revoked],["E6.BUSINESS_REJECTED_NO_EFFECT",h=>businessOutcome(h,"REJECTED")],["E6.BUSINESS_HOLD_NO_EFFECT",h=>businessOutcome(h,"HOLD")]])}import assert7 from"node:assert/strict";import{applyDelivery as applyDelivery2}from"@eventsdk/sdk/core";function gate(){let resolve=()=>{};const promise=new Promise(done=>{resolve=done});return{promise,resolve}}async function lateCommit(h){const claim=await h.claim();const before=await h.inspect();const entered=gate();const release=gate();let called=false;const applying=applyDelivery2(claim,{...h.dependencies(),domain:{apply:async tx=>{await h.writeEffect(tx,claim);called=true;entered.resolve();await release.promise}}},h.options);try{await Promise.race([entered.promise,applying]);assert7.equal(called,true);const deferring=h.work().defer(claim.key,claim.lease,claim.receipt,0,"CONFORMANCE_CONCURRENT_DEFER",AbortSignal.timeout(h.options.timeoutMs));const joined=Promise.allSettled([applying,deferring]);release.resolve();const results=await joined;assert7.equal(results.filter(result=>result.status==="fulfilled").length,1);const actual=await h.inspect();if(results[0]?.status==="fulfilled"){assert7.equal(actual.receipt.disposition,"APPLIED");assert7.equal(actual.effects,1)}else{assert7.deepEqual(actual.receipt,before.receipt);assert7.equal(actual.effects,0)}await h.reopen();assert7.deepEqual(await h.inspect(),actual)}finally{release.resolve();await applying.catch(()=>{})}}import assert8 from"node:assert/strict";import{applyDelivery as applyDelivery3,replayDeadLetter,runInboxWorker}from"@eventsdk/sdk/core";function options3(h){return{...h.options,batchSize:1,leaseMs:h.options.timeoutMs*4,retry:{maxAttempts:2,baseDelayMs:0,maxDelayMs:0,jitterRatio:0}}}function dependencies(h){let sequence=0;return{work:h.work(),receipts:h.dependencies().inbox,deadLetters:h.deadLetters(),clock:h.dependencies().clock,random:{next:()=>0},ids:{next:()=>`conformance-dlq-${++sequence}`},process:claim=>applyDelivery3(claim,{...h.dependencies(),domain:{apply:tx=>h.writeEffect(tx,claim)}},h.options)}}async function exhaust(h){const deps={...dependencies(h),process:async()=>{throw new Error("CONFORMANCE_POISON")}};assert8.equal((await runInboxWorker(deps,options3(h))).RETRY,1);assert8.equal((await runInboxWorker(deps,options3(h))).QUARANTINED,1);const before=await h.inspect();assert8.equal(before.effects,0);assert8.equal(before.quarantined,true);assert8.equal(before.deadLetters.length,1);const entry=before.deadLetters[0];assert8.ok(entry);assert8.equal(entry.originalDeliveryRef,before.receipt.deliveryRef);assert8.equal(entry.key.id,before.receipt.originEventId);assert8.equal(entry.attempts,2);await h.reopen();assert8.deepEqual(await h.inspect(),before);return entry}async function lostReply(h){const deps=dependencies(h);const result=await runInboxWorker({...deps,process:async(claim,opts)=>{await deps.process(claim,opts);throw new Error("CONFORMANCE_COMMITTED_REPLY_LOST")}},options3(h));assert8.equal(result.APPLIED,1);await h.reopen();assert8.equal((await h.inspect()).effects,1);assert8.equal((await h.inspect()).receipt.disposition,"APPLIED");assert8.equal((await runInboxWorker(dependencies(h),options3(h))).APPLIED,0);assert8.equal((await h.inspect()).effects,1)}async function replay(h){const entry=await exhaust(h);await h.setAuthorized(false);await assert8.rejects(replayDeadLetter(entry,h.deadLetters(),h.dependencies().authorization,h.options));assert8.equal((await h.inspect()).quarantined,true);await h.setAuthorized(true);const letters=h.deadLetters();const races=await Promise.allSettled([1,2].map(()=>replayDeadLetter(entry,letters,h.dependencies().authorization,h.options)));assert8.equal(races.filter(r=>r.status==="fulfilled").length,1);assert8.equal((await runInboxWorker(dependencies(h),options3(h))).APPLIED,1);const actual=await h.inspect();assert8.equal(actual.effects,1);assert8.equal(actual.receipt.originEventId,entry.key.id);assert8.equal(actual.receipt.deliveryRef,entry.originalDeliveryRef)}async function unknown(h){await h.seedUnknown();let called=0;const result=await runInboxWorker({...dependencies(h),process:async()=>{called++;throw new Error("UNKNOWN_MUST_NOT_PROCESS")}},options3(h));assert8.equal(called,0);assert8.equal(result.QUARANTINED,1);await h.reopen();const actual=await h.inspect();assert8.equal(actual.effects,0);assert8.equal(actual.receipt.disposition,"UNKNOWN");assert8.equal(actual.quarantined,true);const entry=actual.deadLetters[0];assert8.ok(entry);await assert8.rejects(replayDeadLetter(entry,h.deadLetters(),h.dependencies().authorization,h.options));assert8.deepEqual(await h.inspect(),actual)}async function exclusive(h){const request={limit:1,now:h.dependencies().clock.now(),leaseMs:h.options.timeoutMs*4,signal:new AbortController().signal};const results=await Promise.all([h.work().claimReady(request),h.work().claimReady(request)]);assert8.equal(results.flat().length,1)}async function deferFence(h){const claim=await h.claim();const before=await h.inspect();await h.work().defer(claim.key,claim.lease,claim.receipt,0,"CONFORMANCE_DEFER",new AbortController().signal);await assert8.rejects(applyDelivery3(claim,{...h.dependencies(),domain:{apply:tx=>h.writeEffect(tx,claim)}},h.options));assert8.deepEqual(await h.inspect(),before);assert8.equal((await runInboxWorker(dependencies(h),options3(h))).APPLIED,1);assert8.equal((await h.inspect()).effects,1)}function runWorkerConformance(factory){return runCases(factory,[["E5.WORKER_LOST_REPLY_READBACK",lostReply],["E5.DLQ_DURABLE_AUTHORIZED_REPLAY",replay],["E5.UNKNOWN_NEVER_REAPPLIED",unknown],["E5.WORKER_EXCLUSIVE_CLAIM",exclusive],["E5.WORKER_DEFER_FENCES_OLD_APPLY",deferFence],["E5.WORKER_LATE_COMMIT_VS_DEFER",lateCommit]])}import assert9 from"node:assert/strict";import{recoverGap as recoverGap2}from"@eventsdk/sdk/core";var recover=(h,expected=h.initialWatermark)=>recoverGap2(h.source,h.scope,expected,h.port(),h.options);async function denied(h){const before=await h.inspect();for(const side of["SOURCE","TARGET"]){await h.setAuthorized(side,false);await assert9.rejects(recover(h));assert9.deepEqual(await h.inspect(),before);await h.setAuthorized(side,true)}}async function rollback2(h){const before=await h.inspect();await h.failAfterCheckpoint();await assert9.rejects(recover(h));assert9.deepEqual(await h.inspect(),before);await h.reopen();assert9.deepEqual(await h.inspect(),before)}async function stale(h){const before=await h.inspect();await assert9.rejects(recover(h,h.initialWatermark+"-stale"));assert9.deepEqual(await h.inspect(),before)}async function durableWinner(h){const results=await Promise.allSettled([recover(h),recover(h)]);assert9.equal(results.filter(result=>result.status==="fulfilled").length,1);const expected={watermark:h.expected.watermark,snapshot:h.expected};assert9.deepEqual(await h.inspect(),expected);await h.reopen();assert9.deepEqual(await h.inspect(),expected);await assert9.rejects(recover(h));assert9.deepEqual(await h.inspect(),expected)}function runGapConformance(factory){return runCases(factory,[["E5.GAP_CURRENT_BOTH_AUTHORIZATIONS",denied],["E5.GAP_SNAPSHOT_CHECKPOINT_ROLLBACK",rollback2],["E5.GAP_STALE_WATERMARK_NO_EFFECT",stale],["E5.GAP_DURABLE_SINGLE_WINNER",durableWinner]])}import assert10 from"node:assert/strict";async function terminal2(h,disposition){const initial=h.initial;const final={...initial,revision:initial.revision+2,disposition,...disposition==="REJECTED"?{reasonCode:"BUSINESS_REFUSED"}:{}};await h.deliver(initial);await h.deliver(final);await h.deliver(final);await h.deliver({...initial,revision:initial.revision+1,disposition:"HOLD",reasonCode:"OLDER_HOLD"});assert10.deepEqual(await h.read(),final);await h.reopen();assert10.deepEqual(await h.read(),final);await assert10.rejects(h.deliver({...final,revision:final.revision+1,disposition:disposition==="APPLIED"?"REJECTED":"APPLIED"}));assert10.deepEqual(await h.read(),final)}async function conflict(h){await h.deliver(h.initial);await assert10.rejects(h.deliver({...h.initial,disposition:"HOLD",reasonCode:"CONFLICTING_REVISION"}));assert10.deepEqual(await h.read(),h.initial)}function runReceiptProjectionConformance(factory){return runCases(factory,[["E6.PROJECTION_APPLIED_TERMINAL_ORDERING",h=>terminal2(h,"APPLIED")],["E6.PROJECTION_REJECTED_TERMINAL_ORDERING",h=>terminal2(h,"REJECTED")],["E6.PROJECTION_SAME_REVISION_CONFLICT",conflict]])}import assert12 from"node:assert/strict";import{relayOutbox as relayOutbox2}from"@eventsdk/sdk/core";import assert11 from"node:assert/strict";import{acceptDelivery as acceptDelivery2,applyDelivery as applyDelivery4,prepareFanoutDelivery,recordFanoutEvent}from"@eventsdk/sdk/core";function key(h,target){return{source:h.draft.source,id:h.draft.id,consumerRef:target.consumerRef,targetScope:target.targetScope}}async function record2(h,targets=h.targets.slice(0,2),draft=h.draft){let deliveries=[];await h.transaction(async tx=>{deliveries=await recordFanoutEvent(tx,draft,targets.map(t=>t.recipient),h.producer(),h.options)});return deliveries}async function receive(h,target,event){const delivery=event??await prepareFanoutDelivery(h.draft,target.recipient.route,h.producer().digest);return acceptDelivery2({event:delivery,origin:target.recipient.origin,deliveryRef:`fanout-${delivery.deliveryid}`,consumerRef:target.consumerRef},h.admission(target),h.options)}async function apply(h,target){const claim=await h.claim(key(h,target));assert11.ok(claim);return applyDelivery4(claim,h.application(),h.options)}async function independentRoutes(h){const deliveries=await record2(h);assert12.equal(deliveries.length,2);assert12.equal(new Set(deliveries.map(event=>event.deliveryid)).size,2);assert12.ok(deliveries.every(event=>event.source===h.draft.source&&event.id===h.draft.id));assert12.notDeepEqual(key(h,h.targets[0]),key(h,h.targets[1]));const failed=deliveries[1];assert12.ok(failed);await settleIndependently(h,failed.deliveryid);for(const target of h.targets.slice(0,2)){assert12.equal((await receive(h,target)).kind,"RECEIVED");assert12.equal((await apply(h,target)).disposition,"APPLIED");assert12.equal((await receive(h,target)).kind,"DUPLICATE")}const actual=await h.inspect();assert12.equal(actual.effects.length,2);for(const target of h.targets.slice(0,2))assert12.deepEqual(actual.effects.find(item=>item.targetScope===target.targetScope&&item.consumerRef===target.consumerRef),key(h,target));assert12.equal(actual.accepted.length,2);assert12.equal(actual.inboundDeliveries,2)}async function settleIndependently(h,failedDelivery){const options4={...h.options,batchSize:2,leaseMs:h.options.timeoutMs*4,retry:{maxAttempts:3,baseDelayMs:0,maxDelayMs:0,jitterRatio:0}};const first=await relayOutbox2({...h.producer(),publisher:{publish:async event=>{if(event.profile!=="eventsdk/1.2")throw new Error("WRONG_FANOUT_PROFILE");if(event.deliveryid===failedDelivery)throw new Error("CONFORMANCE_ONE_ROUTE_ACK_LOST");return{stream:"conformance",sequence:1,duplicate:false}}}},options4);assert12.deepEqual(first,{published:1,unknown:1,held:0});const before=await h.inspect();assert12.equal(before.logicalFacts,1);assert12.equal(before.outbound.find(r=>r.event.deliveryid===failedDelivery)?.status,"UNKNOWN");assert12.equal(before.outbound.find(r=>r.event.deliveryid!==failedDelivery)?.status,"PUBLISHED");await h.reopen();assert12.deepEqual(await h.inspect(),before);const published=[];const retry=await relayOutbox2({...h.producer(),publisher:{publish:async event=>{if(event.profile!=="eventsdk/1.2")throw new Error("WRONG_FANOUT_PROFILE");published.push(event.deliveryid);return{stream:"conformance",sequence:2,duplicate:true}}}},options4);assert12.deepEqual(retry,{published:1,unknown:0,held:0});assert12.deepEqual(published,[failedDelivery])}import assert13 from"node:assert/strict";import{prepareFanoutDelivery as prepareFanoutDelivery2,recordFanoutEvent as recordFanoutEvent2}from"@eventsdk/sdk/core";async function logicalConflict(h){await record2(h);assert13.equal((await receive(h,h.targets[0])).kind,"RECEIVED");const before=await h.inspect();const changedDraft={...h.draft,data:{conformanceOriginal:h.draft.data}};await assert13.rejects(record2(h,h.targets.slice(0,2),changedDraft),{code:"EVENT_ID_CONFLICT"});const alias=h.targets[2];const changed=await prepareFanoutDelivery2(changedDraft,alias.recipient.route,h.producer().digest);assert13.deepEqual(await receive(h,alias,changed),{kind:"REJECTED",reasonCode:"EVENT_ID_CONFLICT"});assert13.deepEqual(await h.inspect(),before)}async function deliveryConflict(h){const target=h.targets[0];await record2(h,[target]);assert13.equal((await receive(h,target)).kind,"RECEIVED");const before=await h.inspect();const replacement=await h.replacementGrant(target);const original=await prepareFanoutDelivery2(h.draft,target.recipient.route,h.producer().digest);const changed=await prepareFanoutDelivery2(h.draft,replacement.recipient.route,h.producer().digest);assert13.equal(original.deliveryid,changed.deliveryid);await assert13.rejects(record2(h,[replacement]),{code:"EVENT_ID_CONFLICT"});assert13.deepEqual(await receive(h,replacement,changed),{kind:"REJECTED",reasonCode:"EVENT_ID_CONFLICT"});assert13.deepEqual(await h.inspect(),before)}async function aliasDedup(h){const first=h.targets[0];const alias=h.targets[2];assert13.deepEqual(key(h,alias),key(h,first));assert13.notEqual(first.recipient.route.connectionref,alias.recipient.route.connectionref);await record2(h,[first,alias]);assert13.equal((await receive(h,first)).kind,"RECEIVED");assert13.equal((await apply(h,first)).disposition,"APPLIED");const accepted=(await h.inspect()).accepted;assert13.equal((await receive(h,alias)).kind,"DUPLICATE");assert13.equal(await h.claim(key(h,alias)),null);const actual=await h.inspect();assert13.deepEqual(actual.accepted,accepted);assert13.deepEqual(actual.effects,[key(h,first)]);assert13.equal(actual.inboundDeliveries,2);await h.reopen();assert13.equal((await receive(h,alias)).kind,"DUPLICATE");assert13.deepEqual(await h.inspect(),actual)}async function rollback3(h){const before=await h.inspect();await assert13.rejects(h.transaction(async tx=>{await h.writeDomain(tx);await recordFanoutEvent2(tx,h.draft,h.targets.map(t=>t.recipient),h.producer(),h.options);throw new Error("CONFORMANCE_AFTER_ALL_ROUTES")}),/CONFORMANCE_AFTER_ALL_ROUTES/);assert13.deepEqual(await h.inspect(),before);await h.reopen();assert13.deepEqual(await h.inspect(),before)}async function deniedRouteRollback(h){const before=await h.inspect();await h.setAuthorized(h.targets[1],false);await assert13.rejects(h.transaction(async tx=>{await h.writeDomain(tx);await recordFanoutEvent2(tx,h.draft,h.targets.slice(0,2).map(t=>t.recipient),h.producer(),h.options)}),{code:"AUTHORIZATION_DENIED"});assert13.deepEqual(await h.inspect(),before)}async function concurrentRecord(h){await Promise.all([record2(h),record2(h)]);const actual=await h.inspect();assert13.equal(actual.logicalFacts,1);assert13.equal(actual.outbound.length,2);await h.reopen();await record2(h);assert13.deepEqual(await h.inspect(),actual)}function runFanoutConformance(factory){return runCases(factory,[["E4.FANOUT_INDEPENDENT_DELIVERY_SETTLEMENT",independentRoutes],["E1.FANOUT_LOGICAL_CONTENT_CONFLICT",logicalConflict],["E2.FANOUT_DELIVERY_GRANT_CONFLICT",deliveryConflict],["E4.FANOUT_SAME_SCOPE_ALIAS_DEDUP",aliasDedup],["E4.FANOUT_ENTIRE_TRANSACTION_ROLLBACK",rollback3],["E2.FANOUT_DENIED_ROUTE_ROLLBACK",deniedRouteRollback],["E5.FANOUT_CONCURRENT_RECORD_REOPEN",concurrentRecord]])}export{checkCompatibility,checkGapIsNotSkipped,checkRetryAndFence,checkUnknownReceipt,runAdmissionConformance,runApplyConformance,runFanoutConformance,runGapConformance,runProducerConformance,runReceiptConformance,runReceiptProjectionConformance,runResultConformance,runWorkerConformance};
1
+ import assert from"node:assert/strict";import{acceptDelivery}from"@eventsdk/sdk/core";var options={timeoutMs:1e3};function input(harness,consumerRef="conformance-consumer"){return{event:harness.event,origin:harness.origin,deliveryRef:"delivery-1",consumerRef}}async function duplicateCase(harness){const first=await acceptDelivery(input(harness),harness.dependencies(),options);const second=await acceptDelivery(input(harness),harness.dependencies(),options);assert.equal(first.kind,"RECEIVED");assert.equal(second.kind,"DUPLICATE");assert.equal((await harness.accepted()).length,1)}async function conflictCase(harness){await acceptDelivery(input(harness),harness.dependencies(),options);const changed={...input(harness),event:{...harness.event,data:{conflict:true}}};const result=await acceptDelivery(changed,harness.dependencies(),options);assert.equal(result.kind,"REJECTED");assert.equal((await harness.accepted()).length,1);assert.equal((await harness.quarantined())[0]?.reasonCode,"EVENT_ID_CONFLICT")}async function consumerIsolationCase(harness){await acceptDelivery(input(harness,"consumer-a"),harness.dependencies(),options);await acceptDelivery(input(harness,"consumer-b"),harness.dependencies(),options);assert.equal((await harness.accepted()).length,2)}async function tenantIsolationCase(harness){await acceptDelivery(input(harness),harness.dependencies(),options);harness.setAuthorization({decision:"ALLOW",source:harness.event.source,targetScope:"urn:target:tenant:other",connectionRef:harness.event.connectionref,grantRef:harness.event.grantref,grantVersion:harness.event.grantversion});await acceptDelivery(input(harness),harness.dependencies(),options);const records=await harness.accepted();assert.equal(records.length,2);assert.notEqual(records[0]?.key.targetScope,records[1]?.key.targetScope)}async function commitFailureCase(harness){harness.failNextCommit();await assert.rejects(acceptDelivery(input(harness),harness.dependencies(),options));assert.equal((await harness.accepted()).length,0);const retry=await acceptDelivery(input(harness),harness.dependencies(),options);assert.equal(retry.kind,"RECEIVED")}async function reopenCase(harness){await acceptDelivery(input(harness),harness.dependencies(),options);await harness.reopen();const retry=await acceptDelivery(input(harness),harness.dependencies(),options);assert.equal(retry.kind,"DUPLICATE")}async function revokedCase(harness){harness.setAuthorization({decision:"DENY",reasonCode:"GRANT_REVOKED"});const result=await acceptDelivery(input(harness),harness.dependencies(),options);assert.equal(result.kind,"REJECTED");assert.equal((await harness.accepted()).length,0)}async function unknownCase(harness){harness.setAuthorization({decision:"UNKNOWN",reasonCode:"AUTHORITY_UNAVAILABLE"});await assert.rejects(acceptDelivery(input(harness),harness.dependencies(),options),{code:"AUTHORIZATION_UNKNOWN"});assert.equal((await harness.accepted()).length,0)}async function spoofedOriginCase(harness){const delivery={...input(harness),origin:{...harness.origin,serviceRef:"spoofed"}};const result=await acceptDelivery(delivery,harness.dependencies(),options);assert.equal(result.kind,"REJECTED");assert.equal((await harness.accepted()).length,0)}var scenarios=[["E4.DEDUPLICATE",duplicateCase],["E1.EVENT_ID_CONFLICT",conflictCase],["E4.CONSUMER_ISOLATION",consumerIsolationCase],["E2.TENANT_ISOLATION",tenantIsolationCase],["E4.COMMIT_BEFORE_ACK",commitFailureCase],["E5.REOPEN_DEDUPLICATION",reopenCase],["E2.GRANT_REVOKED",revokedCase],["E2.UNKNOWN_FAIL_CLOSED",unknownCase],["E2.ORIGIN_MISMATCH",spoofedOriginCase]];async function runAdmissionConformance(factory){const results=[];for(const[id,scenario]of scenarios){const harness=await factory();try{await scenario(harness);results.push({id,passed:true})}catch{results.push({id,passed:false,failureCode:"ASSERTION_FAILED"})}finally{await harness.close()}}return results}var profilesBySdk={"0.1.0":["eventsdk/1.0"],"0.2.0":["eventsdk/1.0","eventsdk/1.1"],"0.3.0":["eventsdk/1.0","eventsdk/1.1","eventsdk/1.2"],"0.3.1":["eventsdk/1.0","eventsdk/1.1","eventsdk/1.2"],"0.4.0":["eventsdk/1.0","eventsdk/1.1","eventsdk/1.2"]};function checkCompatibility(producer,consumer){for(const version of[producer,consumer]){if(!Object.hasOwn(profilesBySdk,version.sdkVersion)||version.schemaMajor!==1||version.cloudEvents!=="1.0")return{compatible:false,reason:"UNSUPPORTED_VERSION"}}if(producer.profile!==consumer.profile)return{compatible:false,reason:"PROFILE_MISMATCH"};for(const version of[producer,consumer]){if(!profilesBySdk[version.sdkVersion]?.includes(version.profile))return{compatible:false,reason:"UNSUPPORTED_VERSION"}}return{compatible:true}}import assert2 from"node:assert/strict";import{assertLiveLease,decideRetry,recoverGap,recoverReceipt,stageEventLogPage}from"@eventsdk/sdk/core";function checkRetryAndFence(){const policy={maxAttempts:4,baseDelayMs:100,maxDelayMs:250,jitterRatio:.25};for(const sample of[0,.5,.999999]){for(let attempt=1;attempt<4;attempt++){const result=decideRetry(attempt,1e3,policy,{next:()=>sample});assert2.equal(result.kind,"RETRY");if(result.kind==="RETRY")assert2.ok(result.nextAttemptAt>=1e3&&result.nextAttemptAt<=1250)}}assert2.deepEqual(decideRetry(4,1e3,policy,{next:()=>0}),{kind:"EXHAUSTED"});for(const lease of[{token:"old",generation:1,expiresAt:999},{token:"",generation:1,expiresAt:2e3},{token:"token",generation:0,expiresAt:2e3}])assert2.throws(()=>assertLiveLease(lease,1e3),{code:"STALE_LEASE"})}async function checkGapIsNotSkipped(){let staged=false;let gapRecorded=false;const result=await stageEventLogPage("3",10,{readAfter:async()=>({kind:"GAP",oldestAvailableCursor:"9"})},{recordGap:async(expected,oldest)=>{assert2.equal(expected,"3");assert2.equal(oldest,"9");gapRecorded=true},stageAndAdvance:async()=>{staged=true}},{timeoutMs:1e3});assert2.equal(result,"GAP");assert2.equal(gapRecorded,true);assert2.equal(staged,false);await assert2.rejects(recoverGap("source-a","tenant-a","3",{readAuthorized:async()=>null,applyAndCheckpoint:async()=>{staged=true}},{timeoutMs:1e3}),{code:"RECOVERY_REQUIRED"});assert2.equal(staged,false)}async function checkUnknownReceipt(receipt){const key2={source:receipt.originSource,id:receipt.originEventId,consumerRef:receipt.consumerRef,targetScope:receipt.targetScope};for(const disposition of["RECEIVED","UNKNOWN","HOLD"]){const observation=await recoverReceipt(key2,receipt.deliveryRef,{read:async()=>({...receipt,disposition})},{timeoutMs:1e3});assert2.equal(observation.status,"WAIT")}await assert2.rejects(recoverReceipt(key2,receipt.deliveryRef,{read:async()=>({...receipt,originEventId:"different-event"})},{timeoutMs:1e3}),{code:"RECEIPT_MISMATCH"})}async function runCases(factory,cases){const results=[];for(const[id,check]of cases){const harness=await factory();try{await check(harness);results.push({id,passed:true})}catch{results.push({id,passed:false,failureCode:"ASSERTION_FAILED"})}finally{await harness.close()}}return results}import assert3 from"node:assert/strict";import{recordEvent,relayOutbox}from"@eventsdk/sdk/core";var options2={timeoutMs:2e3};var relayOptions={...options2,batchSize:1,leaseMs:1e4,retry:{maxAttempts:4,baseDelayMs:0,maxDelayMs:1,jitterRatio:0}};async function record(h){await h.transaction(async tx=>{await h.writeDomain(tx);await recordEvent(tx,h.event,h.origin,h.dependencies(),options2)})}async function rollbackCase(h){await assert3.rejects(h.transaction(async tx=>{await h.writeDomain(tx);await recordEvent(tx,h.event,h.origin,h.dependencies(),options2);throw new Error("SYNTHETIC_DOMAIN_ROLLBACK")}),{message:"SYNTHETIC_DOMAIN_ROLLBACK"});assert3.deepEqual(await h.inspect(),{domainCount:0,outboxCount:0,states:[]})}async function unknownReopenCase(h){await record(h);const ids=[];const first=await relayOutbox({...h.dependencies(),publisher:{publish:async(event,context)=>{assert3.equal(event.source,h.event.source);assert3.equal(event.id,h.event.id);ids.push(context.messageId);throw new Error("SYNTHETIC_PUBACK_LOSS")}}},relayOptions);assert3.equal(first.unknown,1);assert3.deepEqual((await h.inspect()).states,["UNKNOWN"]);await h.reopen();assert3.deepEqual((await h.inspect()).states,["UNKNOWN"]);const second=await relayOutbox({...h.dependencies(),publisher:{publish:async(event,context)=>{assert3.equal(event.id,h.event.id);ids.push(context.messageId);return{stream:"probe",sequence:1,duplicate:true}}}},relayOptions);assert3.equal(second.published,1);assert3.equal(ids.length,2);assert3.equal(ids[0],ids[1]);assert3.deepEqual(await h.inspect(),{domainCount:1,outboxCount:1,states:["PUBLISHED"]})}function settleClaim(outbox,claim,outcome,signal){if(claim.event.profile==="eventsdk/1.2"){assert3.ok(outbox.settleFanoutPublish,"profile1.2 requires per-delivery fenced settlement");return outbox.settleFanoutPublish(claim.event,claim.lease,outcome,signal)}return outbox.settlePublish(claim.event,claim.lease,outcome,signal)}async function fencingCase(h){await record(h);const deps=h.dependencies();const claimInput={limit:1,now:deps.clock.now(),leaseMs:1e4,signal:AbortSignal.timeout(2e3)};const old=(await deps.outbox.claimReady(claimInput))[0];assert3.ok(old);await h.expireLease();const fresh=(await deps.outbox.claimReady({...claimInput,now:deps.clock.now()}))[0];assert3.ok(fresh);assert3.ok(fresh.lease.generation>old.lease.generation);const published={status:"PUBLISHED",ack:{stream:"probe",sequence:1,duplicate:false}};await assert3.rejects(settleClaim(deps.outbox,old,published,claimInput.signal),{code:"STALE_LEASE"});await settleClaim(deps.outbox,fresh,published,claimInput.signal);assert3.deepEqual((await h.inspect()).states,["PUBLISHED"])}async function revocationCase(h){await record(h);await h.setAuthorized(false);let calls=0;const result=await relayOutbox({...h.dependencies(),publisher:{publish:async()=>{calls++;return{stream:"probe",sequence:1,duplicate:false}}}},relayOptions);assert3.equal(result.held,1);assert3.equal(calls,0);assert3.deepEqual((await h.inspect()).states,["HOLD"])}function runProducerConformance(factory){return runCases(factory,[["E4.PRODUCER_ATOMIC_ROLLBACK",rollbackCase],["E5.PRODUCER_UNKNOWN_REOPEN_STABLE_ID",unknownReopenCase],["E5.PRODUCER_FENCING",fencingCase],["E2.PRODUCER_CURRENT_AUTHORIZATION",revocationCase]])}import assert4 from"node:assert/strict";import{recoverReceipt as recoverReceipt2}from"@eventsdk/sdk/core";var read=h=>recoverReceipt2(h.key,h.receipt.deliveryRef,h.reader(),{timeoutMs:2e3});async function waiting(h){for(const disposition of["RECEIVED","HOLD","UNKNOWN"]){await h.persist({...h.receipt,disposition});assert4.equal((await read(h)).status,"WAIT")}}async function correlation(h){for(const field of["originSource","originEventId","deliveryRef","consumerRef","targetScope"]){await h.persist({...h.receipt,[field]:h.receipt[field]+"-wrong"});await assert4.rejects(read(h),{code:"RECEIPT_MISMATCH"})}}async function durable(h){const receipt={...h.receipt,disposition:"APPLIED"};await h.persist(receipt);await h.reopen();assert4.deepEqual(await read(h),{status:"RESOLVED",receipt})}async function rejected(h){const receipt={...h.receipt,disposition:"REJECTED",reasonCode:"BUSINESS_REFUSED"};await h.persist(receipt);await h.reopen();assert4.deepEqual(await read(h),{status:"RESOLVED",receipt})}async function denial(h){await h.persist(h.receipt);await h.setAuthorized(false);await assert4.rejects(read(h),{code:"AUTHORIZATION_DENIED"})}function runReceiptConformance(factory){return runCases(factory,[["E6.RECEIPT_UNKNOWN_WAIT",waiting],["E6.RECEIPT_EXACT_CORRELATION",correlation],["E6.RECEIPT_DURABLE_REOPEN",durable],["E6.RECEIPT_REJECTED_DURABLE_REOPEN",rejected],["E2.RECEIPT_CURRENT_AUTHORIZATION",denial]])}import assert5 from"node:assert/strict";import{readAuthorizedResult}from"@eventsdk/sdk/core";var read2=h=>readAuthorizedResult(h.request,h.reader,h.authorization,h.digest,AbortSignal.timeout(2e3),h.clock);async function exact(h){assert5.deepEqual((await read2(h)).reference,h.request.reference)}async function revision(h){await h.mutateSource("REVISION");await assert5.rejects(read2(h),{code:"RESULT_MISMATCH"})}async function digest(h){await h.mutateSource("VALUE");await assert5.rejects(read2(h),{code:"RESULT_MISMATCH"})}async function missing(h){await h.mutateSource("ABSENT");await assert5.rejects(read2(h),{code:"RECOVERY_REQUIRED"})}async function sourceDenial(h){await h.setSourceAuthorized(false);await assert5.rejects(read2(h),{code:"AUTHORIZATION_DENIED"})}async function sourceScope(h){await assert5.rejects(h.reader.read(h.request.reference,{event:h.request.event,origin:h.request.origin,targetScope:h.request.targetScope+"-unauthorized",signal:AbortSignal.timeout(2e3)}),{code:"AUTHORIZATION_DENIED"})}async function receiverDenial(h){await h.setReceiverAuthorized(false);await assert5.rejects(read2(h),{code:"AUTHORIZATION_DENIED"});assert5.equal(h.sourceReads(),0)}function runResultConformance(factory){return runCases(factory,[["E7.RESULT_EXACT_REFERENCE",exact],["E7.RESULT_REVISION_MISMATCH",revision],["E7.RESULT_DIGEST_MISMATCH",digest],["E7.RESULT_MISSING",missing],["E2.RESULT_SOURCE_AUTHORIZATION",sourceDenial],["E2.RESULT_SOURCE_SCOPE",sourceScope],["E2.RESULT_RECEIVER_DENIAL_NO_READ",receiverDenial]])}import assert6 from"node:assert/strict";import{applyDelivery}from"@eventsdk/sdk/core";function observedEffect(h,claim){let calls=0;return{calls:()=>calls,domain:{apply:async tx=>{calls++;await h.writeEffect(tx,claim)}}}}async function rollback(h){const claim=await h.claim();const before=await h.inspect();await assert6.rejects(applyDelivery(claim,{...h.dependencies(),domain:{apply:async(tx,current)=>{await h.writeEffect(tx,current);throw new Error("CONFORMANCE_AFTER_EFFECT")}}},h.options));assert6.deepEqual(await h.inspect(),before)}async function terminal(h){const claim=await h.claim();const effect=observedEffect(h,claim);const deps={...h.dependencies(),domain:effect.domain};const receipt=await applyDelivery(claim,deps,h.options);assert6.equal(receipt.disposition,"APPLIED");await assert6.rejects(applyDelivery(claim,deps,h.options));assert6.equal(effect.calls(),1);await h.reopen();const actual=await h.inspect();assert6.deepEqual(actual.receipt,receipt);assert6.equal(actual.effects,1)}async function receiptFailure(h){const claim=await h.claim();const effect=observedEffect(h,claim);const before=await h.inspect();await h.failNextReceiptCommit();await assert6.rejects(applyDelivery(claim,{...h.dependencies(),domain:effect.domain},h.options));assert6.equal(effect.calls(),1);assert6.deepEqual(await h.inspect(),before)}async function staleFence(h){const claim=await h.claim();const effect=observedEffect(h,claim);const before=await h.inspect();await h.invalidateLease();await assert6.rejects(applyDelivery(claim,{...h.dependencies(),domain:effect.domain},h.options));assert6.equal(effect.calls(),0);assert6.deepEqual(await h.inspect(),before)}async function revoked(h){const claim=await h.claim();const effect=observedEffect(h,claim);await h.setAuthorized(false);const receipt=await applyDelivery(claim,{...h.dependencies(),domain:effect.domain},h.options);assert6.equal(effect.calls(),0);assert6.equal(receipt.disposition,"REJECTED");assert6.equal((await h.inspect()).effects,0);await h.reopen();assert6.deepEqual((await h.inspect()).receipt,receipt)}async function businessOutcome(h,disposition){const claim=await h.claim();const receipt=await applyDelivery(claim,{...h.dependencies(),domain:{apply:async tx=>{await h.writeEffect(tx,claim);return{disposition,reasonCode:"BUSINESS_CONDITION_UNMET"}}}},h.options);assert6.equal(receipt.disposition,disposition);assert6.equal(receipt.reasonCode,"BUSINESS_CONDITION_UNMET");assert6.equal((await h.inspect()).effects,0);await h.reopen();assert6.deepEqual((await h.inspect()).receipt,receipt)}function runApplyConformance(factory){return runCases(factory,[["E4.APPLY_EFFECT_ROLLBACK",rollback],["E4.APPLY_TERMINAL_DURABLE_ONCE",terminal],["E4.APPLY_RECEIPT_FAILURE_ROLLBACK",receiptFailure],["E5.APPLY_STALE_FENCE",staleFence],["E2.APPLY_REVOKED",revoked],["E6.BUSINESS_REJECTED_NO_EFFECT",h=>businessOutcome(h,"REJECTED")],["E6.BUSINESS_HOLD_NO_EFFECT",h=>businessOutcome(h,"HOLD")]])}import assert7 from"node:assert/strict";import{applyDelivery as applyDelivery2}from"@eventsdk/sdk/core";function gate(){let resolve=()=>{};const promise=new Promise(done=>{resolve=done});return{promise,resolve}}async function lateCommit(h){const claim=await h.claim();const before=await h.inspect();const entered=gate();const release=gate();let called=false;const applying=applyDelivery2(claim,{...h.dependencies(),domain:{apply:async tx=>{await h.writeEffect(tx,claim);called=true;entered.resolve();await release.promise}}},h.options);try{await Promise.race([entered.promise,applying]);assert7.equal(called,true);const deferring=h.work().defer(claim.key,claim.lease,claim.receipt,0,"CONFORMANCE_CONCURRENT_DEFER",AbortSignal.timeout(h.options.timeoutMs));const joined=Promise.allSettled([applying,deferring]);release.resolve();const results=await joined;assert7.equal(results.filter(result=>result.status==="fulfilled").length,1);const actual=await h.inspect();if(results[0]?.status==="fulfilled"){assert7.equal(actual.receipt.disposition,"APPLIED");assert7.equal(actual.effects,1)}else{assert7.deepEqual(actual.receipt,before.receipt);assert7.equal(actual.effects,0)}await h.reopen();assert7.deepEqual(await h.inspect(),actual)}finally{release.resolve();await applying.catch(()=>{})}}import assert8 from"node:assert/strict";import{applyDelivery as applyDelivery3,replayDeadLetter,runInboxWorker}from"@eventsdk/sdk/core";function options3(h){return{...h.options,batchSize:1,leaseMs:h.options.timeoutMs*4,retry:{maxAttempts:2,baseDelayMs:0,maxDelayMs:0,jitterRatio:0}}}function dependencies(h){let sequence=0;return{work:h.work(),receipts:h.dependencies().inbox,deadLetters:h.deadLetters(),clock:h.dependencies().clock,random:{next:()=>0},ids:{next:()=>`conformance-dlq-${++sequence}`},process:claim=>applyDelivery3(claim,{...h.dependencies(),domain:{apply:tx=>h.writeEffect(tx,claim)}},h.options)}}async function exhaust(h){const deps={...dependencies(h),process:async()=>{throw new Error("CONFORMANCE_POISON")}};assert8.equal((await runInboxWorker(deps,options3(h))).RETRY,1);assert8.equal((await runInboxWorker(deps,options3(h))).QUARANTINED,1);const before=await h.inspect();assert8.equal(before.effects,0);assert8.equal(before.quarantined,true);assert8.equal(before.deadLetters.length,1);const entry=before.deadLetters[0];assert8.ok(entry);assert8.equal(entry.originalDeliveryRef,before.receipt.deliveryRef);assert8.equal(entry.key.id,before.receipt.originEventId);assert8.equal(entry.attempts,2);await h.reopen();assert8.deepEqual(await h.inspect(),before);return entry}async function lostReply(h){const deps=dependencies(h);const result=await runInboxWorker({...deps,process:async(claim,opts)=>{await deps.process(claim,opts);throw new Error("CONFORMANCE_COMMITTED_REPLY_LOST")}},options3(h));assert8.equal(result.APPLIED,1);await h.reopen();assert8.equal((await h.inspect()).effects,1);assert8.equal((await h.inspect()).receipt.disposition,"APPLIED");assert8.equal((await runInboxWorker(dependencies(h),options3(h))).APPLIED,0);assert8.equal((await h.inspect()).effects,1)}async function replay(h){const entry=await exhaust(h);await h.setAuthorized(false);await assert8.rejects(replayDeadLetter(entry,h.deadLetters(),h.dependencies().authorization,h.options));assert8.equal((await h.inspect()).quarantined,true);await h.setAuthorized(true);const letters=h.deadLetters();const races=await Promise.allSettled([1,2].map(()=>replayDeadLetter(entry,letters,h.dependencies().authorization,h.options)));assert8.equal(races.filter(r=>r.status==="fulfilled").length,1);assert8.equal((await runInboxWorker(dependencies(h),options3(h))).APPLIED,1);const actual=await h.inspect();assert8.equal(actual.effects,1);assert8.equal(actual.receipt.originEventId,entry.key.id);assert8.equal(actual.receipt.deliveryRef,entry.originalDeliveryRef)}async function unknown(h){await h.seedUnknown();let called=0;const result=await runInboxWorker({...dependencies(h),process:async()=>{called++;throw new Error("UNKNOWN_MUST_NOT_PROCESS")}},options3(h));assert8.equal(called,0);assert8.equal(result.QUARANTINED,1);await h.reopen();const actual=await h.inspect();assert8.equal(actual.effects,0);assert8.equal(actual.receipt.disposition,"UNKNOWN");assert8.equal(actual.quarantined,true);const entry=actual.deadLetters[0];assert8.ok(entry);await assert8.rejects(replayDeadLetter(entry,h.deadLetters(),h.dependencies().authorization,h.options));assert8.deepEqual(await h.inspect(),actual)}async function exclusive(h){const request={limit:1,now:h.dependencies().clock.now(),leaseMs:h.options.timeoutMs*4,signal:new AbortController().signal};const results=await Promise.all([h.work().claimReady(request),h.work().claimReady(request)]);assert8.equal(results.flat().length,1)}async function deferFence(h){const claim=await h.claim();const before=await h.inspect();await h.work().defer(claim.key,claim.lease,claim.receipt,0,"CONFORMANCE_DEFER",new AbortController().signal);await assert8.rejects(applyDelivery3(claim,{...h.dependencies(),domain:{apply:tx=>h.writeEffect(tx,claim)}},h.options));assert8.deepEqual(await h.inspect(),before);assert8.equal((await runInboxWorker(dependencies(h),options3(h))).APPLIED,1);assert8.equal((await h.inspect()).effects,1)}function runWorkerConformance(factory){return runCases(factory,[["E5.WORKER_LOST_REPLY_READBACK",lostReply],["E5.DLQ_DURABLE_AUTHORIZED_REPLAY",replay],["E5.UNKNOWN_NEVER_REAPPLIED",unknown],["E5.WORKER_EXCLUSIVE_CLAIM",exclusive],["E5.WORKER_DEFER_FENCES_OLD_APPLY",deferFence],["E5.WORKER_LATE_COMMIT_VS_DEFER",lateCommit]])}import assert9 from"node:assert/strict";import{recoverGap as recoverGap2}from"@eventsdk/sdk/core";var recover=(h,expected=h.initialWatermark)=>recoverGap2(h.source,h.scope,expected,h.port(),h.options);async function denied(h){const before=await h.inspect();for(const side of["SOURCE","TARGET"]){await h.setAuthorized(side,false);await assert9.rejects(recover(h));assert9.deepEqual(await h.inspect(),before);await h.setAuthorized(side,true)}}async function rollback2(h){const before=await h.inspect();await h.failAfterCheckpoint();await assert9.rejects(recover(h));assert9.deepEqual(await h.inspect(),before);await h.reopen();assert9.deepEqual(await h.inspect(),before)}async function stale(h){const before=await h.inspect();await assert9.rejects(recover(h,h.initialWatermark+"-stale"));assert9.deepEqual(await h.inspect(),before)}async function durableWinner(h){const results=await Promise.allSettled([recover(h),recover(h)]);assert9.equal(results.filter(result=>result.status==="fulfilled").length,1);const expected={watermark:h.expected.watermark,snapshot:h.expected};assert9.deepEqual(await h.inspect(),expected);await h.reopen();assert9.deepEqual(await h.inspect(),expected);await assert9.rejects(recover(h));assert9.deepEqual(await h.inspect(),expected)}function runGapConformance(factory){return runCases(factory,[["E5.GAP_CURRENT_BOTH_AUTHORIZATIONS",denied],["E5.GAP_SNAPSHOT_CHECKPOINT_ROLLBACK",rollback2],["E5.GAP_STALE_WATERMARK_NO_EFFECT",stale],["E5.GAP_DURABLE_SINGLE_WINNER",durableWinner]])}import assert10 from"node:assert/strict";async function terminal2(h,disposition){const initial=h.initial;const final={...initial,revision:initial.revision+2,disposition,...disposition==="REJECTED"?{reasonCode:"BUSINESS_REFUSED"}:{}};await h.deliver(initial);await h.deliver(final);await h.deliver(final);await h.deliver({...initial,revision:initial.revision+1,disposition:"HOLD",reasonCode:"OLDER_HOLD"});assert10.deepEqual(await h.read(),final);await h.reopen();assert10.deepEqual(await h.read(),final);await assert10.rejects(h.deliver({...final,revision:final.revision+1,disposition:disposition==="APPLIED"?"REJECTED":"APPLIED"}));assert10.deepEqual(await h.read(),final)}async function conflict(h){await h.deliver(h.initial);await assert10.rejects(h.deliver({...h.initial,disposition:"HOLD",reasonCode:"CONFLICTING_REVISION"}));assert10.deepEqual(await h.read(),h.initial)}function runReceiptProjectionConformance(factory){return runCases(factory,[["E6.PROJECTION_APPLIED_TERMINAL_ORDERING",h=>terminal2(h,"APPLIED")],["E6.PROJECTION_REJECTED_TERMINAL_ORDERING",h=>terminal2(h,"REJECTED")],["E6.PROJECTION_SAME_REVISION_CONFLICT",conflict]])}import assert12 from"node:assert/strict";import{relayOutbox as relayOutbox2}from"@eventsdk/sdk/core";import assert11 from"node:assert/strict";import{acceptDelivery as acceptDelivery2,applyDelivery as applyDelivery4,prepareFanoutDelivery,recordFanoutEvent}from"@eventsdk/sdk/core";function key(h,target){return{source:h.draft.source,id:h.draft.id,consumerRef:target.consumerRef,targetScope:target.targetScope}}async function record2(h,targets=h.targets.slice(0,2),draft=h.draft){let deliveries=[];await h.transaction(async tx=>{deliveries=await recordFanoutEvent(tx,draft,targets.map(t=>t.recipient),h.producer(),h.options)});return deliveries}async function receive(h,target,event){const delivery=event??await prepareFanoutDelivery(h.draft,target.recipient.route,h.producer().digest);return acceptDelivery2({event:delivery,origin:target.recipient.origin,deliveryRef:`fanout-${delivery.deliveryid}`,consumerRef:target.consumerRef},h.admission(target),h.options)}async function apply(h,target){const claim=await h.claim(key(h,target));assert11.ok(claim);return applyDelivery4(claim,h.application(),h.options)}async function independentRoutes(h){const deliveries=await record2(h);assert12.equal(deliveries.length,2);assert12.equal(new Set(deliveries.map(event=>event.deliveryid)).size,2);assert12.ok(deliveries.every(event=>event.source===h.draft.source&&event.id===h.draft.id));assert12.notDeepEqual(key(h,h.targets[0]),key(h,h.targets[1]));const failed=deliveries[1];assert12.ok(failed);await settleIndependently(h,failed.deliveryid);for(const target of h.targets.slice(0,2)){assert12.equal((await receive(h,target)).kind,"RECEIVED");assert12.equal((await apply(h,target)).disposition,"APPLIED");assert12.equal((await receive(h,target)).kind,"DUPLICATE")}const actual=await h.inspect();assert12.equal(actual.effects.length,2);for(const target of h.targets.slice(0,2))assert12.deepEqual(actual.effects.find(item=>item.targetScope===target.targetScope&&item.consumerRef===target.consumerRef),key(h,target));assert12.equal(actual.accepted.length,2);assert12.equal(actual.inboundDeliveries,2)}async function settleIndependently(h,failedDelivery){const options4={...h.options,batchSize:2,leaseMs:h.options.timeoutMs*4,retry:{maxAttempts:3,baseDelayMs:0,maxDelayMs:0,jitterRatio:0}};const first=await relayOutbox2({...h.producer(),publisher:{publish:async event=>{if(event.profile!=="eventsdk/1.2")throw new Error("WRONG_FANOUT_PROFILE");if(event.deliveryid===failedDelivery)throw new Error("CONFORMANCE_ONE_ROUTE_ACK_LOST");return{stream:"conformance",sequence:1,duplicate:false}}}},options4);assert12.deepEqual(first,{published:1,unknown:1,held:0});const before=await h.inspect();assert12.equal(before.logicalFacts,1);assert12.equal(before.outbound.find(r=>r.event.deliveryid===failedDelivery)?.status,"UNKNOWN");assert12.equal(before.outbound.find(r=>r.event.deliveryid!==failedDelivery)?.status,"PUBLISHED");await h.reopen();assert12.deepEqual(await h.inspect(),before);const published=[];const retry=await relayOutbox2({...h.producer(),publisher:{publish:async event=>{if(event.profile!=="eventsdk/1.2")throw new Error("WRONG_FANOUT_PROFILE");published.push(event.deliveryid);return{stream:"conformance",sequence:2,duplicate:true}}}},options4);assert12.deepEqual(retry,{published:1,unknown:0,held:0});assert12.deepEqual(published,[failedDelivery])}import assert13 from"node:assert/strict";import{prepareFanoutDelivery as prepareFanoutDelivery2,recordFanoutEvent as recordFanoutEvent2}from"@eventsdk/sdk/core";async function logicalConflict(h){await record2(h);assert13.equal((await receive(h,h.targets[0])).kind,"RECEIVED");const before=await h.inspect();const changedDraft={...h.draft,data:{conformanceOriginal:h.draft.data}};await assert13.rejects(record2(h,h.targets.slice(0,2),changedDraft),{code:"EVENT_ID_CONFLICT"});const alias=h.targets[2];const changed=await prepareFanoutDelivery2(changedDraft,alias.recipient.route,h.producer().digest);assert13.deepEqual(await receive(h,alias,changed),{kind:"REJECTED",reasonCode:"EVENT_ID_CONFLICT"});assert13.deepEqual(await h.inspect(),before)}async function deliveryConflict(h){const target=h.targets[0];await record2(h,[target]);assert13.equal((await receive(h,target)).kind,"RECEIVED");const before=await h.inspect();const replacement=await h.replacementGrant(target);const original=await prepareFanoutDelivery2(h.draft,target.recipient.route,h.producer().digest);const changed=await prepareFanoutDelivery2(h.draft,replacement.recipient.route,h.producer().digest);assert13.equal(original.deliveryid,changed.deliveryid);await assert13.rejects(record2(h,[replacement]),{code:"EVENT_ID_CONFLICT"});assert13.deepEqual(await receive(h,replacement,changed),{kind:"REJECTED",reasonCode:"EVENT_ID_CONFLICT"});assert13.deepEqual(await h.inspect(),before)}async function aliasDedup(h){const first=h.targets[0];const alias=h.targets[2];assert13.deepEqual(key(h,alias),key(h,first));assert13.notEqual(first.recipient.route.connectionref,alias.recipient.route.connectionref);await record2(h,[first,alias]);assert13.equal((await receive(h,first)).kind,"RECEIVED");assert13.equal((await apply(h,first)).disposition,"APPLIED");const accepted=(await h.inspect()).accepted;assert13.equal((await receive(h,alias)).kind,"DUPLICATE");assert13.equal(await h.claim(key(h,alias)),null);const actual=await h.inspect();assert13.deepEqual(actual.accepted,accepted);assert13.deepEqual(actual.effects,[key(h,first)]);assert13.equal(actual.inboundDeliveries,2);await h.reopen();assert13.equal((await receive(h,alias)).kind,"DUPLICATE");assert13.deepEqual(await h.inspect(),actual)}async function rollback3(h){const before=await h.inspect();await assert13.rejects(h.transaction(async tx=>{await h.writeDomain(tx);await recordFanoutEvent2(tx,h.draft,h.targets.map(t=>t.recipient),h.producer(),h.options);throw new Error("CONFORMANCE_AFTER_ALL_ROUTES")}),/CONFORMANCE_AFTER_ALL_ROUTES/);assert13.deepEqual(await h.inspect(),before);await h.reopen();assert13.deepEqual(await h.inspect(),before)}async function deniedRouteRollback(h){const before=await h.inspect();await h.setAuthorized(h.targets[1],false);await assert13.rejects(h.transaction(async tx=>{await h.writeDomain(tx);await recordFanoutEvent2(tx,h.draft,h.targets.slice(0,2).map(t=>t.recipient),h.producer(),h.options)}),{code:"AUTHORIZATION_DENIED"});assert13.deepEqual(await h.inspect(),before)}async function concurrentRecord(h){await Promise.all([record2(h),record2(h)]);const actual=await h.inspect();assert13.equal(actual.logicalFacts,1);assert13.equal(actual.outbound.length,2);await h.reopen();await record2(h);assert13.deepEqual(await h.inspect(),actual)}function runFanoutConformance(factory){return runCases(factory,[["E4.FANOUT_INDEPENDENT_DELIVERY_SETTLEMENT",independentRoutes],["E1.FANOUT_LOGICAL_CONTENT_CONFLICT",logicalConflict],["E2.FANOUT_DELIVERY_GRANT_CONFLICT",deliveryConflict],["E4.FANOUT_SAME_SCOPE_ALIAS_DEDUP",aliasDedup],["E4.FANOUT_ENTIRE_TRANSACTION_ROLLBACK",rollback3],["E2.FANOUT_DENIED_ROUTE_ROLLBACK",deniedRouteRollback],["E5.FANOUT_CONCURRENT_RECORD_REOPEN",concurrentRecord]])}import assert14 from"node:assert/strict";async function approve(h){const pending=await h.receiver.begin(h.params);const consent=await h.receiver.consent(pending.ref,pending.proof,h.actor);const redirect=await h.receiver.decide(pending.ref,pending.proof,h.actor,consent.consentBinding,"allow");const code=new URL(redirect.location).searchParams.get("code");assert14.ok(code);return h.token(code)}async function singleUse(h){const token=await approve(h);const result=await h.receiver.exchange(token);assert14.equal(result.requestId,h.params.get("request_id"));await assert14.rejects(h.receiver.exchange(token))}async function concurrent(h){const token=await approve(h);const results=await Promise.allSettled([h.receiver.exchange(token),h.receiver.exchange(token)]);assert14.equal(results.filter(result=>result.status==="fulfilled").length,1)}async function durable2(h){const token=await approve(h);await h.reopen();await h.receiver.exchange(token);await h.reopen();await assert14.rejects(h.receiver.exchange(token))}async function actorRevoked(h){const token=await approve(h);await h.revokeActor();await assert14.rejects(h.receiver.exchange(token))}async function grantRevoked(h){const token=await approve(h);await h.revokeGrant();await assert14.rejects(h.receiver.exchange(token))}async function pkce(h){const token=await approve(h);await assert14.rejects(h.receiver.exchange({...token,code_verifier:"x".repeat(64)}));await assert14.rejects(h.receiver.exchange({...token,client_id:token.client_id+"-wrong"}));await assert14.rejects(h.receiver.exchange({...token,redirect_uri:token.redirect_uri+"/wrong"}));await h.receiver.exchange(token)}async function deny(h){const pending=await h.receiver.begin(h.params);const consent=await h.receiver.consent(pending.ref,pending.proof,h.actor);const result=await h.receiver.decide(pending.ref,pending.proof,h.actor,consent.consentBinding,"deny");assert14.equal(new URL(result.location).searchParams.get("error"),"access_denied");await assert14.rejects(h.receiver.decide(pending.ref,pending.proof,h.actor,consent.consentBinding,"allow"));await assert14.rejects(h.receiver.begin(h.params))}function runEventLinkReceiverConformance(factory){return runCases(factory,[["EVENT_LINK.ONE_TIME_CODE",singleUse],["EVENT_LINK.CONCURRENT_CONSUMPTION",concurrent],["EVENT_LINK.DURABLE_REOPEN",durable2],["EVENT_LINK.CURRENT_ACTOR",actorRevoked],["EVENT_LINK.CURRENT_GRANT",grantRevoked],["EVENT_LINK.PKCE_CLIENT_CALLBACK",pkce],["EVENT_LINK.DENIAL_NO_REPLAY",deny]])}export{checkCompatibility,checkGapIsNotSkipped,checkRetryAndFence,checkUnknownReceipt,runAdmissionConformance,runApplyConformance,runEventLinkReceiverConformance,runFanoutConformance,runGapConformance,runProducerConformance,runReceiptConformance,runReceiptProjectionConformance,runResultConformance,runWorkerConformance};
@@ -0,0 +1,22 @@
1
+ export interface EventLinkAuthorizationRequest {
2
+ profile: 'event-link/1';
3
+ response_type: 'code';
4
+ client_id: string;
5
+ redirect_uri: string;
6
+ scope: 'eventsdk.connection.authorize';
7
+ state: string;
8
+ code_challenge: string;
9
+ code_challenge_method: 'S256';
10
+ request_id: string;
11
+ source: Source;
12
+ event_type: string;
13
+ grant_ref: string;
14
+ grant_version: '1';
15
+ }
16
+ export interface Source {
17
+ source: string;
18
+ serviceRef: string;
19
+ tenantRef: string;
20
+ issuer: string;
21
+ subject: string;
22
+ }
@@ -0,0 +1,27 @@
1
+ export interface EventLinkProposal {
2
+ schemaVersion: 1;
3
+ requestId: string;
4
+ source: Source;
5
+ target: TenantContext;
6
+ grant: {
7
+ grantRef: string;
8
+ version: 1;
9
+ eventType: string;
10
+ consumerRef: string;
11
+ };
12
+ connectionRef: string;
13
+ targetDisplayName: string;
14
+ approvalRef: string;
15
+ expiresAt: string;
16
+ }
17
+ export interface Source {
18
+ source: string;
19
+ serviceRef: string;
20
+ tenantRef: string;
21
+ issuer: string;
22
+ subject: string;
23
+ }
24
+ export interface TenantContext {
25
+ serviceRef: string;
26
+ tenantRef: string;
27
+ }
@@ -0,0 +1,7 @@
1
+ export interface EventLinkTokenRequest {
2
+ grant_type: 'authorization_code';
3
+ client_id: string;
4
+ redirect_uri: string;
5
+ code: string;
6
+ code_verifier: string;
7
+ }
@@ -0,0 +1,98 @@
1
+ export declare const eventLinkAuthorizationRequestJsonSchema: {
2
+ readonly title: "EventLinkAuthorizationRequest";
3
+ readonly type: "object";
4
+ readonly additionalProperties: false;
5
+ readonly required: readonly ["profile", "response_type", "client_id", "redirect_uri", "scope", "state", "code_challenge", "code_challenge_method", "request_id", "source", "event_type", "grant_ref", "grant_version"];
6
+ readonly properties: {
7
+ readonly profile: {
8
+ readonly const: "event-link/1";
9
+ };
10
+ readonly response_type: {
11
+ readonly const: "code";
12
+ };
13
+ readonly client_id: {
14
+ readonly type: "string";
15
+ readonly minLength: 1;
16
+ readonly maxLength: 256;
17
+ readonly pattern: "^[^\\u0000-\\u0020\\u007f]+$";
18
+ };
19
+ readonly redirect_uri: {
20
+ readonly type: "string";
21
+ readonly format: "uri";
22
+ readonly maxLength: 2048;
23
+ };
24
+ readonly scope: {
25
+ readonly const: "eventsdk.connection.authorize";
26
+ };
27
+ readonly state: {
28
+ readonly type: "string";
29
+ readonly minLength: 32;
30
+ readonly maxLength: 512;
31
+ readonly pattern: "^[A-Za-z0-9_-]+$";
32
+ };
33
+ readonly code_challenge: {
34
+ readonly type: "string";
35
+ readonly minLength: 43;
36
+ readonly maxLength: 43;
37
+ readonly pattern: "^[A-Za-z0-9_-]+$";
38
+ };
39
+ readonly code_challenge_method: {
40
+ readonly const: "S256";
41
+ };
42
+ readonly request_id: {
43
+ readonly type: "string";
44
+ readonly minLength: 1;
45
+ readonly maxLength: 256;
46
+ readonly pattern: "^[^\\u0000-\\u0020\\u007f]+$";
47
+ };
48
+ readonly source: {
49
+ readonly type: "object";
50
+ readonly additionalProperties: false;
51
+ readonly required: readonly ["source", "serviceRef", "tenantRef", "issuer", "subject"];
52
+ readonly properties: {
53
+ readonly source: {
54
+ readonly type: "string";
55
+ readonly format: "uri";
56
+ readonly maxLength: 2048;
57
+ };
58
+ readonly serviceRef: {
59
+ readonly type: "string";
60
+ readonly minLength: 1;
61
+ readonly maxLength: 256;
62
+ readonly pattern: "^[^\\u0000-\\u0020\\u007f]+$";
63
+ };
64
+ readonly tenantRef: {
65
+ readonly type: "string";
66
+ readonly minLength: 1;
67
+ readonly maxLength: 256;
68
+ readonly pattern: "^[^\\u0000-\\u0020\\u007f]+$";
69
+ };
70
+ readonly issuer: {
71
+ readonly type: "string";
72
+ readonly format: "uri";
73
+ readonly maxLength: 2048;
74
+ };
75
+ readonly subject: {
76
+ readonly type: "string";
77
+ readonly minLength: 1;
78
+ readonly maxLength: 256;
79
+ readonly pattern: "^[^\\u0000-\\u0020\\u007f]+$";
80
+ };
81
+ };
82
+ };
83
+ readonly event_type: {
84
+ readonly type: "string";
85
+ readonly pattern: "^[A-Za-z0-9][A-Za-z0-9._-]*\\.v[1-9][0-9]*$";
86
+ readonly maxLength: 256;
87
+ };
88
+ readonly grant_ref: {
89
+ readonly type: "string";
90
+ readonly minLength: 1;
91
+ readonly maxLength: 256;
92
+ readonly pattern: "^[^\\u0000-\\u0020\\u007f]+$";
93
+ };
94
+ readonly grant_version: {
95
+ readonly const: "1";
96
+ };
97
+ };
98
+ };
@@ -0,0 +1,121 @@
1
+ export declare const eventLinkProposalJsonSchema: {
2
+ readonly title: "EventLinkProposal";
3
+ readonly type: "object";
4
+ readonly additionalProperties: false;
5
+ readonly required: readonly ["schemaVersion", "requestId", "source", "target", "grant", "connectionRef", "targetDisplayName", "approvalRef", "expiresAt"];
6
+ readonly properties: {
7
+ readonly schemaVersion: {
8
+ readonly const: 1;
9
+ };
10
+ readonly requestId: {
11
+ readonly type: "string";
12
+ readonly minLength: 1;
13
+ readonly maxLength: 256;
14
+ readonly pattern: "^[^\\u0000-\\u0020\\u007f]+$";
15
+ };
16
+ readonly source: {
17
+ readonly type: "object";
18
+ readonly additionalProperties: false;
19
+ readonly required: readonly ["source", "serviceRef", "tenantRef", "issuer", "subject"];
20
+ readonly properties: {
21
+ readonly source: {
22
+ readonly type: "string";
23
+ readonly format: "uri";
24
+ readonly maxLength: 2048;
25
+ };
26
+ readonly serviceRef: {
27
+ readonly type: "string";
28
+ readonly minLength: 1;
29
+ readonly maxLength: 256;
30
+ readonly pattern: "^[^\\u0000-\\u0020\\u007f]+$";
31
+ };
32
+ readonly tenantRef: {
33
+ readonly type: "string";
34
+ readonly minLength: 1;
35
+ readonly maxLength: 256;
36
+ readonly pattern: "^[^\\u0000-\\u0020\\u007f]+$";
37
+ };
38
+ readonly issuer: {
39
+ readonly type: "string";
40
+ readonly format: "uri";
41
+ readonly maxLength: 2048;
42
+ };
43
+ readonly subject: {
44
+ readonly type: "string";
45
+ readonly minLength: 1;
46
+ readonly maxLength: 256;
47
+ readonly pattern: "^[^\\u0000-\\u0020\\u007f]+$";
48
+ };
49
+ };
50
+ };
51
+ readonly target: {
52
+ readonly title: "TenantContext";
53
+ readonly type: "object";
54
+ readonly additionalProperties: false;
55
+ readonly properties: {
56
+ readonly serviceRef: {
57
+ readonly type: "string";
58
+ readonly minLength: 1;
59
+ readonly maxLength: 256;
60
+ readonly pattern: "^[^\\u0000-\\u001f\\u007f]+$";
61
+ };
62
+ readonly tenantRef: {
63
+ readonly type: "string";
64
+ readonly minLength: 1;
65
+ readonly maxLength: 256;
66
+ readonly pattern: "^[^\\u0000-\\u001f\\u007f]+$";
67
+ };
68
+ };
69
+ readonly required: readonly ["serviceRef", "tenantRef"];
70
+ };
71
+ readonly grant: {
72
+ readonly type: "object";
73
+ readonly additionalProperties: false;
74
+ readonly required: readonly ["grantRef", "version", "eventType", "consumerRef"];
75
+ readonly properties: {
76
+ readonly grantRef: {
77
+ readonly type: "string";
78
+ readonly minLength: 1;
79
+ readonly maxLength: 256;
80
+ readonly pattern: "^[^\\u0000-\\u0020\\u007f]+$";
81
+ };
82
+ readonly version: {
83
+ readonly const: 1;
84
+ };
85
+ readonly eventType: {
86
+ readonly type: "string";
87
+ readonly pattern: "^[A-Za-z0-9][A-Za-z0-9._-]*\\.v[1-9][0-9]*$";
88
+ readonly maxLength: 256;
89
+ };
90
+ readonly consumerRef: {
91
+ readonly type: "string";
92
+ readonly minLength: 1;
93
+ readonly maxLength: 256;
94
+ readonly pattern: "^[^\\u0000-\\u0020\\u007f]+$";
95
+ };
96
+ };
97
+ };
98
+ readonly connectionRef: {
99
+ readonly type: "string";
100
+ readonly minLength: 1;
101
+ readonly maxLength: 256;
102
+ readonly pattern: "^[^\\u0000-\\u0020\\u007f]+$";
103
+ };
104
+ readonly targetDisplayName: {
105
+ readonly type: "string";
106
+ readonly minLength: 1;
107
+ readonly maxLength: 160;
108
+ readonly pattern: "\\S";
109
+ };
110
+ readonly approvalRef: {
111
+ readonly type: "string";
112
+ readonly minLength: 1;
113
+ readonly maxLength: 256;
114
+ readonly pattern: "^[^\\u0000-\\u0020\\u007f]+$";
115
+ };
116
+ readonly expiresAt: {
117
+ readonly type: "string";
118
+ readonly format: "date-time";
119
+ };
120
+ };
121
+ };
@@ -0,0 +1,34 @@
1
+ export declare const eventLinkTokenRequestJsonSchema: {
2
+ readonly title: "EventLinkTokenRequest";
3
+ readonly type: "object";
4
+ readonly additionalProperties: false;
5
+ readonly required: readonly ["grant_type", "client_id", "redirect_uri", "code", "code_verifier"];
6
+ readonly properties: {
7
+ readonly grant_type: {
8
+ readonly const: "authorization_code";
9
+ };
10
+ readonly client_id: {
11
+ readonly type: "string";
12
+ readonly minLength: 1;
13
+ readonly maxLength: 256;
14
+ readonly pattern: "^[^\\u0000-\\u0020\\u007f]+$";
15
+ };
16
+ readonly redirect_uri: {
17
+ readonly type: "string";
18
+ readonly format: "uri";
19
+ readonly maxLength: 2048;
20
+ };
21
+ readonly code: {
22
+ readonly type: "string";
23
+ readonly minLength: 32;
24
+ readonly maxLength: 256;
25
+ readonly pattern: "^[A-Za-z0-9_-]+$";
26
+ };
27
+ readonly code_verifier: {
28
+ readonly type: "string";
29
+ readonly minLength: 43;
30
+ readonly maxLength: 128;
31
+ readonly pattern: "^[A-Za-z0-9._~-]+$";
32
+ };
33
+ };
34
+ };
@@ -3,7 +3,7 @@ export { canonicalJson } from './canonical/canonical-json.js';
3
3
  export { EVENTSDK_ORIGIN_PROOF_HEADER, EVENTSDK_ORIGIN_PROOF_TYPE, isEventOriginProofWireForm, } from './validation/origin-proof-wire.js';
4
4
  export { ContractError } from './validation/contract-error.js';
5
5
  export type { ValidationIssue, ValidationResult } from './validation/contract-error.js';
6
- export { validateCloudEvent, validateCloudEventV1, validateCloudEventV11, validateCloudEventV12, validateFanoutEventDraft, parseFanoutEventDraft, validateNamespacedReference, validateIdentityContext, parseNamespacedReference, parseIdentityContext, validateBusinessReceipt, validateResultRef, validateTenantContext, validateTenantConnection, validateExchangeGrant, parseCloudEvent, parseBusinessReceipt, parseResultRef, parseTenantContext, parseTenantConnection, parseExchangeGrant, validateEventOriginClaims, parseEventOriginClaims, validateNodeConnectionProfile, parseNodeConnectionProfile, validatePublicJwksSnapshot, parsePublicJwksSnapshot, } from './validation/contracts.js';
6
+ export { parseNativeEventCatalog, parseNodeWorkerObservation, validateCloudEvent, validateCloudEventV1, validateCloudEventV11, validateCloudEventV12, validateFanoutEventDraft, parseFanoutEventDraft, validateNamespacedReference, validateIdentityContext, parseNamespacedReference, parseIdentityContext, validateBusinessReceipt, validateResultRef, validateTenantContext, validateTenantConnection, validateExchangeGrant, parseCloudEvent, parseBusinessReceipt, parseResultRef, parseTenantContext, parseTenantConnection, parseExchangeGrant, validateEventOriginClaims, parseEventOriginClaims, validateNodeConnectionProfile, parseNodeConnectionProfile, validatePublicJwksSnapshot, parsePublicJwksSnapshot, } from './validation/contracts.js';
7
7
  export { decodeCloudEvent } from './validation/decode-cloud-event.js';
8
8
  export { parseJsonStrict } from './validation/strict-json.js';
9
9
  export { extractIdentityContext, assertWireGrantVersion } from './validation/identity-context.js';
@@ -15,8 +15,6 @@ export { parseExchangeRegistration, validateExchangeRegistration } from './valid
15
15
  export type { OutboxRecoveryCommand } from './generated/outbox-recovery-command.js';
16
16
  export type { NodeWorkerObservation } from './generated/node-worker-observation.js';
17
17
  export type { NativeEventCatalog } from './generated/native-event-catalog.js';
18
- export { parseNativeEventCatalog } from './validation/contracts.js';
19
- export { parseNodeWorkerObservation } from './validation/contracts.js';
20
18
  export { outboxRecoveryCommandJsonSchema } from './generated/portable-outbox-recovery-command.js';
21
19
  export { parseOutboxRecoveryCommand, validateOutboxRecoveryCommand, } from './validation/contracts.js';
22
20
  export type { GapBaseline } from './generated/gap-baseline.js';
@@ -24,3 +22,10 @@ export type { GapRecoveryCommand } from './generated/gap-recovery-command.js';
24
22
  export { parseGapBaseline, parseGapRecoveryCommand } from './validation/contracts.js';
25
23
  export { gapBaselineJsonSchema } from './generated/portable-gap-baseline.js';
26
24
  export { gapRecoveryCommandJsonSchema } from './generated/portable-gap-recovery-command.js';
25
+ export type { EventLinkAuthorizationRequest } from './generated/event-link-authorization-request.js';
26
+ export type { EventLinkTokenRequest } from './generated/event-link-token-request.js';
27
+ export type { EventLinkProposal } from './generated/event-link-proposal.js';
28
+ export { eventLinkAuthorizationRequestJsonSchema } from './generated/portable-event-link-authorization-request.js';
29
+ export { eventLinkTokenRequestJsonSchema } from './generated/portable-event-link-token-request.js';
30
+ export { eventLinkProposalJsonSchema } from './generated/portable-event-link-proposal.js';
31
+ export { validateEventLinkAuthorizationRequest, validateEventLinkTokenRequest, validateEventLinkProposal, parseEventLinkAuthorizationRequest, parseEventLinkTokenRequest, parseEventLinkProposal, } from './validation/event-link.js';