@eventsdk/sdk 0.0.0-stage → 0.3.1

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.
Files changed (159) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +9 -0
  3. package/dist/compatibility-http/bridge/receive.d.ts +3 -0
  4. package/dist/compatibility-http/bridge/types.d.ts +44 -0
  5. package/dist/compatibility-http/index.d.ts +4 -0
  6. package/dist/compatibility-http/index.js +1 -0
  7. package/dist/compatibility-http/policy/validate-policy.d.ts +3 -0
  8. package/dist/conformance/admission/harness.d.ts +20 -0
  9. package/dist/conformance/admission/run-suite.d.ts +2 -0
  10. package/dist/conformance/consumer/harness.d.ts +24 -0
  11. package/dist/conformance/consumer/run-apply-suite.d.ts +2 -0
  12. package/dist/conformance/consumer/run-worker-suite.d.ts +2 -0
  13. package/dist/conformance/fanout/harness.d.ts +39 -0
  14. package/dist/conformance/fanout/run-suite.d.ts +2 -0
  15. package/dist/conformance/gap/harness.d.ts +19 -0
  16. package/dist/conformance/gap/run-suite.d.ts +2 -0
  17. package/dist/conformance/index.d.ts +20 -0
  18. package/dist/conformance/index.js +1 -0
  19. package/dist/conformance/producer/harness.d.ts +21 -0
  20. package/dist/conformance/producer/run-suite.d.ts +2 -0
  21. package/dist/conformance/receipt/harness.d.ts +12 -0
  22. package/dist/conformance/receipt/projection-harness.d.ts +9 -0
  23. package/dist/conformance/receipt/run-projection-suite.d.ts +2 -0
  24. package/dist/conformance/receipt/run-suite.d.ts +2 -0
  25. package/dist/conformance/reliability/checks.d.ts +4 -0
  26. package/dist/conformance/result/harness.d.ts +15 -0
  27. package/dist/conformance/result/run-suite.d.ts +2 -0
  28. package/dist/conformance/version/compatibility.d.ts +13 -0
  29. package/dist/contracts/canonical/canonical-json.d.ts +1 -0
  30. package/dist/contracts/contract-types.d.ts +34 -0
  31. package/dist/contracts/generated/business-receipt.d.ts +21 -0
  32. package/dist/contracts/generated/cloud-event-context.d.ts +32 -0
  33. package/dist/contracts/generated/cloud-event-fanout.d.ts +33 -0
  34. package/dist/contracts/generated/cloud-event.d.ts +24 -0
  35. package/dist/contracts/generated/event-origin-claims.d.ts +13 -0
  36. package/dist/contracts/generated/exchange-grant.d.ts +11 -0
  37. package/dist/contracts/generated/exchange-registration.d.ts +24 -0
  38. package/dist/contracts/generated/fanout-event-draft.d.ts +28 -0
  39. package/dist/contracts/generated/gap-baseline.d.ts +18 -0
  40. package/dist/contracts/generated/gap-recovery-command.d.ts +7 -0
  41. package/dist/contracts/generated/identity-context.d.ts +15 -0
  42. package/dist/contracts/generated/namespaced-reference.d.ts +4 -0
  43. package/dist/contracts/generated/native-event-catalog.d.ts +19 -0
  44. package/dist/contracts/generated/node-connection-profile.d.ts +217 -0
  45. package/dist/contracts/generated/node-worker-observation.d.ts +7 -0
  46. package/dist/contracts/generated/outbox-recovery-command.d.ts +8 -0
  47. package/dist/contracts/generated/portable-exchange-registration.d.ts +109 -0
  48. package/dist/contracts/generated/portable-gap-baseline.d.ts +93 -0
  49. package/dist/contracts/generated/portable-gap-recovery-command.d.ts +35 -0
  50. package/dist/contracts/generated/portable-outbox-recovery-command.d.ts +37 -0
  51. package/dist/contracts/generated/public-jwks-snapshot.d.ts +141 -0
  52. package/dist/contracts/generated/result-ref.d.ts +8 -0
  53. package/dist/contracts/generated/supported-profiles.d.ts +3 -0
  54. package/dist/contracts/generated/tenant-connection.d.ts +13 -0
  55. package/dist/contracts/generated/tenant-context.d.ts +4 -0
  56. package/dist/contracts/index.d.ts +26 -0
  57. package/dist/contracts/index.js +1 -0
  58. package/dist/contracts/validation/contract-error.d.ts +16 -0
  59. package/dist/contracts/validation/contracts.d.ts +316 -0
  60. package/dist/contracts/validation/decode-cloud-event.d.ts +2 -0
  61. package/dist/contracts/validation/identity-context.d.ts +3 -0
  62. package/dist/contracts/validation/origin-proof-wire.d.ts +3 -0
  63. package/dist/contracts/validation/strict-json.d.ts +1 -0
  64. package/dist/core/inbox/accept-delivery.d.ts +26 -0
  65. package/dist/core/inbox/apply-delivery.d.ts +29 -0
  66. package/dist/core/inbox/domain-apply-result.d.ts +13 -0
  67. package/dist/core/inbox/inbox-worker.d.ts +2 -0
  68. package/dist/core/inbox/read-result.d.ts +12 -0
  69. package/dist/core/inbox/worker-types.d.ts +21 -0
  70. package/dist/core/index.d.ts +50 -0
  71. package/dist/core/index.js +1 -0
  72. package/dist/core/outbox/authorize-recovery.d.ts +75 -0
  73. package/dist/core/outbox/outbox-relay.d.ts +26 -0
  74. package/dist/core/outbox/record-event.d.ts +10 -0
  75. package/dist/core/outbox/record-fanout.d.ts +16 -0
  76. package/dist/core/ports/dead-letter.d.ts +29 -0
  77. package/dist/core/ports/inbox.d.ts +43 -0
  78. package/dist/core/ports/observability.d.ts +21 -0
  79. package/dist/core/ports/origin-refresh.d.ts +5 -0
  80. package/dist/core/ports/outbox.d.ts +46 -0
  81. package/dist/core/ports/result-reader.d.ts +14 -0
  82. package/dist/core/ports/transport.d.ts +13 -0
  83. package/dist/core/receipt/receipt-state.d.ts +3 -0
  84. package/dist/core/recovery/event-log.d.ts +28 -0
  85. package/dist/core/recovery/gap-baseline-binding.d.ts +2 -0
  86. package/dist/core/recovery/gap-recovery.d.ts +15 -0
  87. package/dist/core/recovery/receipt-identity-recovery.d.ts +8 -0
  88. package/dist/core/recovery/receipt-recovery.d.ts +14 -0
  89. package/dist/core/recovery/replay-dead-letter.d.ts +4 -0
  90. package/dist/core/runtime/dependencies.d.ts +19 -0
  91. package/dist/core/runtime/errors.d.ts +6 -0
  92. package/dist/core/runtime/event-identity.d.ts +14 -0
  93. package/dist/core/runtime/exchange-connection.d.ts +7 -0
  94. package/dist/core/runtime/fanout-identity.d.ts +6 -0
  95. package/dist/core/runtime/lease.d.ts +6 -0
  96. package/dist/core/runtime/observe-health.d.ts +3 -0
  97. package/dist/core/runtime/operation.d.ts +2 -0
  98. package/dist/core/runtime/retry.d.ts +14 -0
  99. package/dist/identity-contracts/authorization/authorization-port.d.ts +35 -0
  100. package/dist/identity-contracts/index.d.ts +2 -0
  101. package/dist/identity-contracts/index.js +0 -0
  102. package/dist/identity-contracts/origin/verified-origin.d.ts +28 -0
  103. package/dist/identity-verifier/index.d.ts +6 -0
  104. package/dist/identity-verifier/index.js +1 -0
  105. package/dist/identity-verifier/jwt/service-token-verifier.d.ts +15 -0
  106. package/dist/identity-verifier/origin/event-origin-policy.d.ts +36 -0
  107. package/dist/identity-verifier/origin/event-origin-signer.d.ts +6 -0
  108. package/dist/identity-verifier/origin/event-origin-verifier.d.ts +6 -0
  109. package/dist/index.d.ts +22 -0
  110. package/dist/index.js +20 -0
  111. package/dist/node-config/configuration-error.d.ts +4 -0
  112. package/dist/node-config/diagnostics/check-configuration.d.ts +40 -0
  113. package/dist/node-config/identity/load-identity.d.ts +14 -0
  114. package/dist/node-config/identity/local-recovery-origin.d.ts +3 -0
  115. package/dist/node-config/identity/public-identity.d.ts +87 -0
  116. package/dist/node-config/identity/public-snapshot.d.ts +2 -0
  117. package/dist/node-config/identity/signing-identity.d.ts +5 -0
  118. package/dist/node-config/index.d.ts +12 -0
  119. package/dist/node-config/index.js +1 -0
  120. package/dist/node-config/main.js +3 -0
  121. package/dist/node-config/operations/export-own-public.d.ts +8 -0
  122. package/dist/node-config/operations/refresh-trust.d.ts +10 -0
  123. package/dist/node-config/profile/load-profile.d.ts +6 -0
  124. package/dist/node-config/profile/validate-profile.d.ts +2 -0
  125. package/dist/node-worker/index.d.ts +3 -0
  126. package/dist/node-worker/index.js +1 -0
  127. package/dist/node-worker/lifecycle.d.ts +19 -0
  128. package/dist/node-worker/route-scheduler.d.ts +17 -0
  129. package/dist/node-worker/session.d.ts +15 -0
  130. package/dist/provisioner/application/apply.d.ts +11 -0
  131. package/dist/provisioner/application/ports.d.ts +44 -0
  132. package/dist/provisioner/application/verify.d.ts +7 -0
  133. package/dist/provisioner/cli/arguments.d.ts +9 -0
  134. package/dist/provisioner/cli/live-command.d.ts +7 -0
  135. package/dist/provisioner/cli/main.js +2 -0
  136. package/dist/provisioner/cli/run.d.ts +2 -0
  137. package/dist/provisioner/cli/session-types.d.ts +26 -0
  138. package/dist/provisioner/conformance/policy.d.ts +9 -0
  139. package/dist/provisioner/index.d.ts +17 -0
  140. package/dist/provisioner/index.js +1 -0
  141. package/dist/provisioner/manifest/types.d.ts +55 -0
  142. package/dist/provisioner/manifest/validate.d.ts +3 -0
  143. package/dist/provisioner/nats/inspector.d.ts +13 -0
  144. package/dist/provisioner/nats/types.d.ts +38 -0
  145. package/dist/provisioner/nats/writer-types.d.ts +11 -0
  146. package/dist/provisioner/nats/writer.d.ts +18 -0
  147. package/dist/provisioner/planning/digest.d.ts +1 -0
  148. package/dist/provisioner/planning/plan.d.ts +18 -0
  149. package/dist/transport-nats/connection/delivery-session.d.ts +10 -0
  150. package/dist/transport-nats/connection/verified-connection.d.ts +12 -0
  151. package/dist/transport-nats/consume/delivery-handler.d.ts +34 -0
  152. package/dist/transport-nats/consume/nats-consumer.d.ts +18 -0
  153. package/dist/transport-nats/index.d.ts +12 -0
  154. package/dist/transport-nats/index.js +3 -0
  155. package/dist/transport-nats/publish/nats-publisher.d.ts +24 -0
  156. package/dist/transport-nats/transport-error.d.ts +5 -0
  157. package/licenses/NATS-LICENSE +201 -0
  158. package/package.json +75 -3
  159. package/README.md +0 -3
@@ -0,0 +1,75 @@
1
+ import { type CloudEventV12, type OutboxRecoveryCommand } from '@eventsdk/sdk/contracts';
2
+ import type { AuthorizationPort } from '@eventsdk/sdk/identity-contracts';
3
+ import type { OutboxRecord } from '../ports/outbox.js';
4
+ import type { OriginRefreshPort } from '../ports/origin-refresh.js';
5
+ import type { Clock, Digest, OperationOptions } from '../runtime/dependencies.js';
6
+ export interface HeldOutboxRecord extends OutboxRecord {
7
+ readonly event: CloudEventV12;
8
+ readonly status: string;
9
+ readonly generation: number;
10
+ }
11
+ export declare function authorizeOutboxRecovery(command: OutboxRecoveryCommand, stored: HeldOutboxRecord, deps: {
12
+ authorization: AuthorizationPort;
13
+ originRefresh: OriginRefreshPort;
14
+ clock: Clock;
15
+ digest: Digest;
16
+ }, options: OperationOptions): Promise<{
17
+ event: {
18
+ readonly specversion: "1.0";
19
+ readonly id: string;
20
+ readonly source: string;
21
+ readonly type: string;
22
+ readonly time: string;
23
+ readonly dataschema: string;
24
+ readonly datacontenttype: "application/json";
25
+ readonly profile: "eventsdk/1.2";
26
+ readonly kind: "EVENT";
27
+ readonly serviceorigin: string;
28
+ readonly sourcetenant: string;
29
+ readonly audience: string;
30
+ readonly connectionref: string;
31
+ readonly grantref: string;
32
+ readonly grantversion: number;
33
+ readonly correlationid: string;
34
+ readonly causationid?: string;
35
+ readonly subject?: string;
36
+ readonly data: string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | any | {
37
+ readonly [x: string]: string | number | boolean | any | any | null;
38
+ } | null)[] | {
39
+ readonly [x: string]: string | number | boolean | readonly (string | number | boolean | any | any | null)[] | any | null;
40
+ } | null)[] | {
41
+ readonly [x: string]: string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | any | any | null)[] | any | null)[] | any | null;
42
+ } | null)[] | {
43
+ readonly [x: string]: string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | any | any | null)[] | any | null)[] | any | null)[] | any | null;
44
+ } | null)[] | {
45
+ readonly [x: string]: string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | any | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null;
46
+ } | null)[] | {
47
+ readonly [x: string]: string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | any | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null;
48
+ } | null)[] | {
49
+ readonly [x: string]: string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | any | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null;
50
+ } | null)[] | {
51
+ readonly [x: string]: string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | any | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null;
52
+ } | null)[] | {
53
+ readonly [x: string]: string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | any | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null;
54
+ } | null)[] | {
55
+ readonly [x: string]: string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | any | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null;
56
+ } | null)[] | {
57
+ readonly [x: string]: string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | any | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null;
58
+ } | null)[] | {
59
+ readonly [x: string]: string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | readonly (string | number | boolean | any | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null)[] | any | null;
60
+ } | null;
61
+ readonly orgnamespace?: string;
62
+ readonly orgref?: string;
63
+ readonly projectnamespace?: string;
64
+ readonly projectref?: string;
65
+ readonly principalnamespace?: string;
66
+ readonly principalref?: string;
67
+ readonly resourcenamespace?: string;
68
+ readonly resourceref?: string;
69
+ readonly deliveryid: string;
70
+ };
71
+ digest: string;
72
+ generation: number;
73
+ origin: import("@eventsdk/sdk/identity-contracts").VerifiedOrigin;
74
+ targetScope: string;
75
+ }>;
@@ -0,0 +1,26 @@
1
+ import type { AuthorizationPort } from '@eventsdk/sdk/identity-contracts';
2
+ import type { OutboxRelayPort } from '../ports/outbox.js';
3
+ import type { PublishPort } from '../ports/transport.js';
4
+ import type { Clock, Digest, OperationOptions, Random } from '../runtime/dependencies.js';
5
+ import type { OriginRefreshPort } from '../ports/origin-refresh.js';
6
+ import { type RetryPolicy } from '../runtime/retry.js';
7
+ export interface RelayDependencies {
8
+ readonly outbox: OutboxRelayPort;
9
+ readonly publisher: PublishPort;
10
+ readonly authorization: AuthorizationPort;
11
+ readonly clock: Clock;
12
+ readonly digest: Digest;
13
+ readonly random: Random;
14
+ readonly originRefresh?: OriginRefreshPort;
15
+ }
16
+ export interface RelayOptions extends OperationOptions {
17
+ readonly batchSize: number;
18
+ readonly leaseMs: number;
19
+ readonly retry: RetryPolicy;
20
+ }
21
+ export interface RelaySummary {
22
+ readonly published: number;
23
+ readonly unknown: number;
24
+ readonly held: number;
25
+ }
26
+ export declare function relayOutbox(deps: RelayDependencies, options: RelayOptions): Promise<RelaySummary>;
@@ -0,0 +1,10 @@
1
+ import type { AuthorizationPort, VerifiedOrigin } from '@eventsdk/sdk/identity-contracts';
2
+ import type { OutboxRecordPort } from '../ports/outbox.js';
3
+ import type { Clock, Digest, OperationOptions } from '../runtime/dependencies.js';
4
+ export interface RecordDependencies<TTransaction> {
5
+ readonly outbox: OutboxRecordPort<TTransaction>;
6
+ readonly authorization: AuthorizationPort;
7
+ readonly digest: Digest;
8
+ readonly clock: Clock;
9
+ }
10
+ export declare function recordEvent<TTransaction>(tx: TTransaction, input: unknown, origin: VerifiedOrigin, dependencies: RecordDependencies<TTransaction>, options: OperationOptions): Promise<void>;
@@ -0,0 +1,16 @@
1
+ import { type CloudEventV12 } from '@eventsdk/sdk/contracts';
2
+ import type { VerifiedOrigin } from '@eventsdk/sdk/identity-contracts';
3
+ import type { Digest, OperationOptions } from '../runtime/dependencies.js';
4
+ import { type RecordDependencies } from './record-event.js';
5
+ export interface FanoutRoute {
6
+ readonly audience: string;
7
+ readonly connectionref: string;
8
+ readonly grantref: string;
9
+ readonly grantversion: number;
10
+ }
11
+ export interface FanoutRecipient {
12
+ readonly route: FanoutRoute;
13
+ readonly origin: VerifiedOrigin;
14
+ }
15
+ export declare function prepareFanoutDelivery(input: unknown, route: FanoutRoute, digest: Digest): Promise<CloudEventV12>;
16
+ export declare function recordFanoutEvent<T>(tx: T, draft: unknown, recipients: readonly FanoutRecipient[], deps: RecordDependencies<T>, options: OperationOptions): Promise<readonly CloudEventV12[]>;
@@ -0,0 +1,29 @@
1
+ import type { BusinessReceipt } from '@eventsdk/sdk/contracts';
2
+ import type { ClaimedInbox } from './inbox.js';
3
+ import type { InboxKey } from '../runtime/event-identity.js';
4
+ import type { Lease } from '../runtime/lease.js';
5
+ export interface DeadLetterEntry {
6
+ readonly ref: string;
7
+ readonly key: InboxKey;
8
+ readonly originalDeliveryRef: string;
9
+ readonly reasonCode: string;
10
+ readonly attempts: number;
11
+ readonly recordedAt: string;
12
+ }
13
+ export interface DeadLetterPort<TTransaction> {
14
+ quarantine(claim: ClaimedInbox, entry: DeadLetterEntry, signal: AbortSignal): Promise<void>;
15
+ transactReplay(entry: DeadLetterEntry, operation: (tx: TTransaction, claim: ClaimedInbox) => Promise<void>, signal: AbortSignal): Promise<void>;
16
+ requeueInTransaction(tx: TTransaction, claim: ClaimedInbox, signal: AbortSignal): Promise<void>;
17
+ }
18
+ export interface InboxWorkClaim extends ClaimedInbox {
19
+ readonly attempt: number;
20
+ }
21
+ export interface InboxWorkPort {
22
+ claimReady(input: {
23
+ limit: number;
24
+ now: number;
25
+ leaseMs: number;
26
+ signal: AbortSignal;
27
+ }): Promise<readonly InboxWorkClaim[]>;
28
+ defer(key: InboxKey, lease: Lease, expectedReceipt: Pick<BusinessReceipt, 'receiptRef' | 'revision' | 'disposition'>, nextAttemptAt: number, reasonCode: string, signal: AbortSignal): Promise<void>;
29
+ }
@@ -0,0 +1,43 @@
1
+ import type { BusinessReceipt, CloudEvent } from '@eventsdk/sdk/contracts';
2
+ import type { VerifiedOrigin } from '@eventsdk/sdk/identity-contracts';
3
+ import type { InboxKey } from '../runtime/event-identity.js';
4
+ import type { Lease } from '../runtime/lease.js';
5
+ import type { DomainApplyOutcome } from '../inbox/domain-apply-result.js';
6
+ export interface AcceptedEvent {
7
+ readonly key: InboxKey;
8
+ readonly event: CloudEvent;
9
+ readonly origin: VerifiedOrigin;
10
+ readonly digest: string;
11
+ readonly deliveryRef: string;
12
+ readonly receipt: BusinessReceipt;
13
+ }
14
+ export type PersistResult = {
15
+ readonly kind: 'RECEIVED' | 'DUPLICATE';
16
+ readonly receipt: BusinessReceipt;
17
+ } | {
18
+ readonly kind: 'CONFLICT';
19
+ };
20
+ export interface QuarantineRecord {
21
+ readonly deliveryRef: string;
22
+ readonly consumerRef: string;
23
+ readonly reasonCode: string;
24
+ readonly recordedAt: string;
25
+ }
26
+ export interface FanoutAcceptedEvent extends AcceptedEvent {
27
+ readonly logicalDigest: string;
28
+ readonly deliveryId: string;
29
+ }
30
+ export interface InboxAdmissionPort {
31
+ persistFanoutAccepted?(record: FanoutAcceptedEvent, signal: AbortSignal): Promise<PersistResult>;
32
+ persistAccepted(record: AcceptedEvent, signal: AbortSignal): Promise<PersistResult>;
33
+ persistQuarantine(record: QuarantineRecord, signal: AbortSignal): Promise<void>;
34
+ }
35
+ export interface ClaimedInbox extends AcceptedEvent {
36
+ readonly lease: Lease;
37
+ }
38
+ export interface InboxApplyPort<TTransaction> {
39
+ transact(claim: ClaimedInbox, operation: (tx: TTransaction) => Promise<BusinessReceipt>, signal: AbortSignal): Promise<BusinessReceipt>;
40
+ withDomainSavepoint?(tx: TTransaction, operation: () => Promise<DomainApplyOutcome>, signal: AbortSignal): Promise<DomainApplyOutcome>;
41
+ completeInTransaction(tx: TTransaction, claim: ClaimedInbox, receipt: BusinessReceipt, signal: AbortSignal): Promise<void>;
42
+ readReceipt(key: InboxKey, signal: AbortSignal): Promise<BusinessReceipt | null>;
43
+ }
@@ -0,0 +1,21 @@
1
+ export interface DeliveryHealth {
2
+ readonly observedAt: number;
3
+ readonly outboxPending: number;
4
+ readonly oldestPendingAt: number | null;
5
+ readonly consumerLag: number;
6
+ readonly retryPending: number;
7
+ readonly quarantined: number;
8
+ readonly unresolvedReceipts: number;
9
+ readonly gaps: number;
10
+ readonly authorizationDenials: number;
11
+ readonly watermark: string;
12
+ readonly brokerStoredBytes?: number;
13
+ readonly brokerQuotaBytes?: number;
14
+ readonly bridgeUnconfirmed?: number;
15
+ }
16
+ export interface DeliveryHealthPort {
17
+ read(signal: AbortSignal): Promise<DeliveryHealth>;
18
+ }
19
+ export interface HealthMetricSink {
20
+ gauge(name: string, value: number): void;
21
+ }
@@ -0,0 +1,5 @@
1
+ import type { CloudEvent } from '@eventsdk/sdk/contracts';
2
+ import type { VerifiedOrigin } from '@eventsdk/sdk/identity-contracts';
3
+ export interface OriginRefreshPort {
4
+ refresh(event: CloudEvent, previous: VerifiedOrigin, signal: AbortSignal): Promise<VerifiedOrigin>;
5
+ }
@@ -0,0 +1,46 @@
1
+ import type { CloudEvent } from '@eventsdk/sdk/contracts';
2
+ import type { VerifiedOrigin } from '@eventsdk/sdk/identity-contracts';
3
+ import type { EventIdentity } from '../runtime/event-identity.js';
4
+ import type { Lease } from '../runtime/lease.js';
5
+ import type { PublishAck } from './transport.js';
6
+ export interface OutboxRecord {
7
+ readonly event: CloudEvent;
8
+ readonly digest: string;
9
+ readonly origin: VerifiedOrigin;
10
+ }
11
+ export interface ClaimedEvent extends OutboxRecord {
12
+ readonly lease: Lease;
13
+ readonly attempt: number;
14
+ }
15
+ export type PublishOutcome = {
16
+ readonly status: 'PUBLISHED';
17
+ readonly ack: PublishAck;
18
+ } | {
19
+ readonly status: 'UNKNOWN';
20
+ readonly nextAttemptAt: number;
21
+ } | {
22
+ readonly status: 'HOLD';
23
+ readonly reasonCode: string;
24
+ };
25
+ export interface FanoutOutboxRecord extends OutboxRecord {
26
+ readonly logicalDigest: string;
27
+ readonly deliveryId: string;
28
+ }
29
+ export interface OutboxRecordPort<TTransaction> {
30
+ recordFanoutInTransaction?(tx: TTransaction, record: FanoutOutboxRecord, signal: AbortSignal): Promise<void>;
31
+ recordInTransaction(tx: TTransaction, record: OutboxRecord, signal: AbortSignal): Promise<void>;
32
+ }
33
+ export interface OutboxRelayPort {
34
+ settleFanoutPublish?(identity: EventIdentity & {
35
+ readonly deliveryid: string;
36
+ }, lease: Lease, outcome: PublishOutcome, signal: AbortSignal): Promise<void>;
37
+ claimReady(input: {
38
+ limit: number;
39
+ now: number;
40
+ leaseMs: number;
41
+ signal: AbortSignal;
42
+ }): Promise<readonly ClaimedEvent[]>;
43
+ settlePublish(identity: EventIdentity, lease: Lease, outcome: PublishOutcome, signal: AbortSignal): Promise<void>;
44
+ }
45
+ export interface OutboxPort<TTransaction> extends OutboxRecordPort<TTransaction>, OutboxRelayPort {
46
+ }
@@ -0,0 +1,14 @@
1
+ import type { CloudEvent, JsonValue, ResultRef } from '@eventsdk/sdk/contracts';
2
+ import type { VerifiedOrigin } from '@eventsdk/sdk/identity-contracts';
3
+ export interface ResultSnapshot {
4
+ readonly reference: ResultRef;
5
+ readonly value: JsonValue;
6
+ }
7
+ export interface ResultReadPort {
8
+ read(reference: ResultRef, context: {
9
+ event: CloudEvent;
10
+ origin: VerifiedOrigin;
11
+ targetScope: string;
12
+ signal: AbortSignal;
13
+ }): Promise<ResultSnapshot | null>;
14
+ }
@@ -0,0 +1,13 @@
1
+ import type { CloudEvent } from '@eventsdk/sdk/contracts';
2
+ export interface PublishAck {
3
+ readonly stream: string;
4
+ readonly sequence: number;
5
+ readonly duplicate: boolean;
6
+ }
7
+ export interface PublishContext {
8
+ readonly messageId: string;
9
+ readonly signal: AbortSignal;
10
+ }
11
+ export interface PublishPort {
12
+ publish(event: CloudEvent, context: PublishContext): Promise<PublishAck>;
13
+ }
@@ -0,0 +1,3 @@
1
+ import { type BusinessReceipt } from '@eventsdk/sdk/contracts';
2
+ export declare function assertReceiptTransition(previous: BusinessReceipt, next: BusinessReceipt): void;
3
+ export declare function classifyReceiptCommit(previous: BusinessReceipt, next: BusinessReceipt): 'UNCHANGED' | 'TRANSITION';
@@ -0,0 +1,28 @@
1
+ import type { CloudEvent } from '@eventsdk/sdk/contracts';
2
+ import type { VerifiedOrigin } from '@eventsdk/sdk/identity-contracts';
3
+ import type { OperationOptions } from '../runtime/dependencies.js';
4
+ export interface EventLogItem {
5
+ readonly cursor: string;
6
+ readonly revision: string;
7
+ readonly commitEvidenceRef: string;
8
+ readonly event: CloudEvent;
9
+ readonly origin: VerifiedOrigin;
10
+ }
11
+ export type EventLogPage = {
12
+ readonly kind: 'PAGE';
13
+ readonly items: readonly EventLogItem[];
14
+ readonly nextCursor: string;
15
+ } | {
16
+ readonly kind: 'GAP';
17
+ readonly oldestAvailableCursor: string;
18
+ };
19
+ export interface NativeEventLogPort {
20
+ readAfter(cursor: string, limit: number, signal: AbortSignal): Promise<EventLogPage>;
21
+ }
22
+ export interface EventLogCheckpointPort {
23
+ stageAndAdvance(expectedCursor: string, page: Extract<EventLogPage, {
24
+ kind: 'PAGE';
25
+ }>, signal: AbortSignal): Promise<void>;
26
+ recordGap(expectedCursor: string, oldestAvailableCursor: string, signal: AbortSignal): Promise<void>;
27
+ }
28
+ export declare function stageEventLogPage(cursor: string, limit: number, source: NativeEventLogPort, checkpoint: EventLogCheckpointPort, options: OperationOptions): Promise<EventLogPage['kind']>;
@@ -0,0 +1,2 @@
1
+ import type { CloudEvent, GapBaseline } from '@eventsdk/sdk/contracts';
2
+ export declare function assertGapBaselineBinding(event: CloudEvent, value: GapBaseline, targetScope?: string): void;
@@ -0,0 +1,15 @@
1
+ import { type JsonValue } from '@eventsdk/sdk/contracts';
2
+ import type { OperationOptions } from '../runtime/dependencies.js';
3
+ export interface AuthorizedSnapshot {
4
+ readonly source: string;
5
+ readonly scope: string;
6
+ readonly revision: string;
7
+ readonly watermark: string;
8
+ readonly evidenceRef: string;
9
+ readonly value: JsonValue;
10
+ }
11
+ export interface SnapshotRecoveryPort {
12
+ readAuthorized(source: string, scope: string, signal: AbortSignal): Promise<AuthorizedSnapshot | null>;
13
+ applyAndCheckpoint(expectedWatermark: string, snapshot: AuthorizedSnapshot, signal: AbortSignal): Promise<void>;
14
+ }
15
+ export declare function recoverGap(source: string, scope: string, expectedWatermark: string, port: SnapshotRecoveryPort, options: OperationOptions): Promise<AuthorizedSnapshot>;
@@ -0,0 +1,8 @@
1
+ import { type BusinessReceipt } from '@eventsdk/sdk/contracts';
2
+ import type { InboxKey } from '../runtime/event-identity.js';
3
+ import type { OperationOptions } from '../runtime/dependencies.js';
4
+ import type { RecoveryObservation } from './receipt-recovery.js';
5
+ export interface ReceiptIdentityLookupPort {
6
+ readByIdentity(key: InboxKey, signal: AbortSignal): Promise<BusinessReceipt | null>;
7
+ }
8
+ export declare function recoverReceiptByIdentity(key: InboxKey, reader: ReceiptIdentityLookupPort, options: OperationOptions): Promise<RecoveryObservation>;
@@ -0,0 +1,14 @@
1
+ import { type BusinessReceipt } from '@eventsdk/sdk/contracts';
2
+ import type { InboxKey } from '../runtime/event-identity.js';
3
+ import type { OperationOptions } from '../runtime/dependencies.js';
4
+ export interface ReceiptLookupPort {
5
+ read(key: InboxKey, deliveryRef: string, signal: AbortSignal): Promise<BusinessReceipt | null>;
6
+ }
7
+ export type RecoveryObservation = {
8
+ readonly status: 'RESOLVED';
9
+ readonly receipt: BusinessReceipt;
10
+ } | {
11
+ readonly status: 'WAIT';
12
+ readonly receipt: BusinessReceipt | null;
13
+ };
14
+ export declare function recoverReceipt(key: InboxKey, deliveryRef: string, reader: ReceiptLookupPort, options: OperationOptions): Promise<RecoveryObservation>;
@@ -0,0 +1,4 @@
1
+ import type { DeadLetterEntry, DeadLetterPort } from '../ports/dead-letter.js';
2
+ import type { ApplyAuthorizationPort } from '../inbox/apply-delivery.js';
3
+ import type { OperationOptions } from '../runtime/dependencies.js';
4
+ export declare function replayDeadLetter<T>(entry: DeadLetterEntry, port: DeadLetterPort<T>, authorization: ApplyAuthorizationPort<T>, options: OperationOptions): Promise<void>;
@@ -0,0 +1,19 @@
1
+ export interface Clock {
2
+ now(): number;
3
+ }
4
+ export interface IdGenerator {
5
+ next(): string;
6
+ }
7
+ export interface Digest {
8
+ sha256(value: string): Promise<string>;
9
+ }
10
+ export interface Random {
11
+ next(): number;
12
+ }
13
+ export interface OperationOptions {
14
+ signal?: AbortSignal;
15
+ timeoutMs: number;
16
+ }
17
+ export interface MetricSink {
18
+ increment(name: string, labels: Readonly<Record<string, string>>): void;
19
+ }
@@ -0,0 +1,6 @@
1
+ export type CoreErrorCode = 'ABORTED' | 'TIMEOUT' | 'INVALID_CONFIGURATION' | 'INVALID_DOMAIN_RESULT' | 'ADAPTER_CAPABILITY_REQUIRED' | 'STALE_LEASE' | 'EVENT_ID_CONFLICT' | 'AUTHORIZATION_DENIED' | 'AUTHORIZATION_UNKNOWN' | 'ORIGIN_MISMATCH' | 'TARGET_SCOPE_CHANGED' | 'RESULT_MISMATCH' | 'RECEIPT_MISMATCH' | 'RECOVERY_REQUIRED' | 'GAP' | 'INVALID_TRANSITION';
2
+ export declare class CoreError extends Error {
3
+ readonly code: CoreErrorCode;
4
+ constructor(code: CoreErrorCode);
5
+ }
6
+ export declare function assertNotAborted(signal?: AbortSignal): void;
@@ -0,0 +1,14 @@
1
+ import { type CloudEvent } from '@eventsdk/sdk/contracts';
2
+ import type { Digest } from './dependencies.js';
3
+ export interface EventIdentity {
4
+ readonly source: string;
5
+ readonly id: string;
6
+ readonly deliveryid?: string;
7
+ }
8
+ export interface InboxKey extends EventIdentity {
9
+ readonly consumerRef: string;
10
+ readonly targetScope: string;
11
+ }
12
+ export declare function eventMessageId(event: EventIdentity, digest: Digest): Promise<string>;
13
+ export declare function eventDigest(event: CloudEvent, digest: Digest): Promise<string>;
14
+ export declare function inboxKey(key: InboxKey): string;
@@ -0,0 +1,7 @@
1
+ import { type TenantContext } from '@eventsdk/sdk/contracts';
2
+ import type { Digest } from './dependencies.js';
3
+ export declare function deriveExchangeConnectionRef(input: {
4
+ source: string;
5
+ from: TenantContext;
6
+ to: TenantContext;
7
+ }, digest: Digest): Promise<string>;
@@ -0,0 +1,6 @@
1
+ import { type CloudEvent, type CloudEventV12, type FanoutEventDraft } from '@eventsdk/sdk/contracts';
2
+ import type { Digest } from './dependencies.js';
3
+ export declare function fanoutLogicalEvent(event: CloudEventV12): FanoutEventDraft;
4
+ export declare function logicalEventDigest(event: CloudEvent, digest: Digest): Promise<string>;
5
+ export declare function deriveDeliveryId(event: Pick<CloudEventV12, 'source' | 'id' | 'audience' | 'connectionref'>, digest: Digest): Promise<string>;
6
+ export declare function assertDeliveryIdentity(event: CloudEvent, digest: Digest): Promise<void>;
@@ -0,0 +1,6 @@
1
+ export interface Lease {
2
+ readonly token: string;
3
+ readonly generation: number;
4
+ readonly expiresAt: number;
5
+ }
6
+ export declare function assertLiveLease(lease: Lease, now: number): void;
@@ -0,0 +1,3 @@
1
+ import type { DeliveryHealth, DeliveryHealthPort, HealthMetricSink } from '../ports/observability.js';
2
+ import type { OperationOptions } from './dependencies.js';
3
+ export declare function observeDeliveryHealth(port: DeliveryHealthPort, sink: HealthMetricSink, options: OperationOptions): Promise<DeliveryHealth>;
@@ -0,0 +1,2 @@
1
+ import type { OperationOptions } from './dependencies.js';
2
+ export declare function boundedOperation<T>(options: OperationOptions, operation: (signal: AbortSignal) => Promise<T>): Promise<T>;
@@ -0,0 +1,14 @@
1
+ import type { Random } from './dependencies.js';
2
+ export interface RetryPolicy {
3
+ readonly maxAttempts: number;
4
+ readonly baseDelayMs: number;
5
+ readonly maxDelayMs: number;
6
+ readonly jitterRatio: number;
7
+ }
8
+ export type RetryDecision = {
9
+ readonly kind: 'RETRY';
10
+ readonly nextAttemptAt: number;
11
+ } | {
12
+ readonly kind: 'EXHAUSTED';
13
+ };
14
+ export declare function decideRetry(attempt: number, now: number, policy: RetryPolicy, random: Random): RetryDecision;
@@ -0,0 +1,35 @@
1
+ import type { CloudEvent, ResultRef } from '@eventsdk/sdk/contracts';
2
+ import type { VerifiedOrigin } from '../origin/verified-origin.js';
3
+ export type AuthorizationPhase = 'OUTBOUND' | 'RECEIVE' | 'APPLY' | 'RESULT_READ';
4
+ export interface AuthorizationRequest {
5
+ readonly phase: AuthorizationPhase;
6
+ readonly event: CloudEvent;
7
+ readonly origin: VerifiedOrigin;
8
+ readonly consumerRef?: string;
9
+ readonly targetScope?: string;
10
+ readonly resultRef?: ResultRef;
11
+ readonly signal?: AbortSignal;
12
+ }
13
+ export type AuthorizationDecision = {
14
+ readonly decision: 'ALLOW';
15
+ readonly source: string;
16
+ readonly targetScope: string;
17
+ readonly connectionRef: string;
18
+ readonly grantRef: string;
19
+ readonly grantVersion: number;
20
+ } | {
21
+ readonly decision: 'DENY' | 'UNKNOWN';
22
+ readonly reasonCode: string;
23
+ };
24
+ export interface AuthorizationPort {
25
+ authorize(request: AuthorizationRequest): Promise<AuthorizationDecision>;
26
+ }
27
+ export interface ResultReadRequest {
28
+ readonly reference: ResultRef;
29
+ readonly origin: VerifiedOrigin;
30
+ readonly targetScope: string;
31
+ readonly connectionRef: string;
32
+ readonly grantRef: string;
33
+ readonly grantVersion: number;
34
+ readonly signal?: AbortSignal;
35
+ }
@@ -0,0 +1,2 @@
1
+ export type { VerifiedOrigin, ServicePrincipal, VerifyOriginRequest, OriginVerification, OriginVerifierPort, } from './origin/verified-origin.js';
2
+ export type { AuthorizationPhase, AuthorizationRequest, AuthorizationDecision, AuthorizationPort, ResultReadRequest, } from './authorization/authorization-port.js';
File without changes
@@ -0,0 +1,28 @@
1
+ export interface VerifiedOrigin {
2
+ readonly serviceRef: string;
3
+ readonly issuer: string;
4
+ readonly subject: string;
5
+ readonly audience: readonly string[];
6
+ readonly verifiedAt: string;
7
+ readonly expiresAt: string;
8
+ }
9
+ export interface ServicePrincipal {
10
+ readonly serviceRef: string;
11
+ readonly issuer: string;
12
+ readonly subject: string;
13
+ }
14
+ export interface VerifyOriginRequest {
15
+ readonly credential: string;
16
+ readonly expectedAudience: string;
17
+ readonly signal?: AbortSignal;
18
+ }
19
+ export type OriginVerification = {
20
+ readonly verified: true;
21
+ readonly origin: VerifiedOrigin;
22
+ } | {
23
+ readonly verified: false;
24
+ readonly reasonCode: string;
25
+ };
26
+ export interface OriginVerifierPort {
27
+ verify(request: VerifyOriginRequest): Promise<OriginVerification>;
28
+ }
@@ -0,0 +1,6 @@
1
+ export { createServiceTokenVerifier } from './jwt/service-token-verifier.js';
2
+ export type { ServiceTokenPolicy } from './jwt/service-token-verifier.js';
3
+ export { createEventOriginSigner } from './origin/event-origin-signer.js';
4
+ export { createEventOriginVerifier } from './origin/event-origin-verifier.js';
5
+ export { EventOriginError, eventOriginTyp, validatePublicOriginKeys, } from './origin/event-origin-policy.js';
6
+ export type { EventOriginAlgorithm, EventOriginSignerPolicy, EventOriginVerifierPolicy, } from './origin/event-origin-policy.js';
@@ -0,0 +1 @@
1
+ import{createLocalJWKSet,decodeProtectedHeader,jwtVerify}from"jose";function createServiceTokenVerifier(input){const policy={...structuredClone({...input,clock:void 0}),clock:input.clock};validatePolicy(policy);const resolve=createLocalJWKSet(policy.jwks);return{async verify(request){try{request.signal?.throwIfAborted();const now=policy.clock();if(!Number.isFinite(now.getTime())||now.getTime()>=Date.parse(policy.keysValidUntil))return{verified:false,reasonCode:"TRUST_SNAPSHOT_EXPIRED"};if(request.expectedAudience!==policy.audience||request.credential.length>16384)return{verified:false,reasonCode:"TOKEN_REJECTED"};const header=decodeProtectedHeader(request.credential);if(typeof header.kid!=="string"||!header.kid||header.jku!==void 0||header.x5u!==void 0)return{verified:false,reasonCode:"TOKEN_REJECTED"};const result=await jwtVerify(request.credential,resolve,{issuer:policy.issuer,audience:policy.audience,subject:policy.subject,algorithms:[...policy.algorithms],typ:"at+jwt",currentDate:now,requiredClaims:["iss","sub","aud","exp","iat","client_id"],maxTokenAge:policy.maxTokenLifetimeSeconds});request.signal?.throwIfAborted();return verifiedClaims(result,policy,policy.clock())}catch{return{verified:false,reasonCode:request.signal?.aborted?"CANCELLED":"TOKEN_REJECTED"}}}}}function validatePolicy(p){if(![p.issuer,p.audience,p.clientId,p.subject,p.serviceRef].every(v=>v.length>0)||!Number.isFinite(Date.parse(p.keysValidUntil))||!Number.isSafeInteger(p.maxTokenLifetimeSeconds)||p.maxTokenLifetimeSeconds<1||!p.algorithms.length||p.algorithms.some(a=>!["RS256","PS256","ES256","EdDSA"].includes(a))||!p.jwks.keys.length||new Set(p.jwks.keys.map(k=>k.kid)).size!==p.jwks.keys.length||p.jwks.keys.some(k=>typeof k.kid!=="string"||!k.kid)||p.jwks.keys.some(k=>k.kty==="oct"||["d","k","p","q","dp","dq","qi","oth"].some(member=>member in k))){throw new Error("INVALID_SERVICE_TOKEN_POLICY")}}function verifiedClaims(result,policy,now){const p=result.payload;if(p.client_id!==policy.clientId||typeof p.exp!=="number"||typeof p.iat!=="number"||p.exp<=p.iat||p.exp-p.iat>policy.maxTokenLifetimeSeconds||!Number.isFinite(now.getTime())||now.getTime()>=p.exp*1e3||now.getTime()<p.iat*1e3||now.getTime()>=Date.parse(policy.keysValidUntil))return{verified:false,reasonCode:"TOKEN_REJECTED"};return{verified:true,origin:{serviceRef:policy.serviceRef,issuer:policy.issuer,subject:policy.subject,audience:[policy.audience],verifiedAt:now.toISOString(),expiresAt:new Date(Math.min(p.exp*1e3,Date.parse(policy.keysValidUntil))).toISOString()}}}import{CompactSign,importPKCS8}from"jose";import{canonicalJson as canonicalJson2,parseCloudEvent,parseEventOriginClaims}from"@eventsdk/sdk/contracts";import{createHash}from"node:crypto";import{canonicalJson}from"@eventsdk/sdk/contracts";function originEventDigest(event){return`sha256:${createHash("sha256").update(canonicalJson(event)).digest("hex")}`}import{EVENTSDK_ORIGIN_PROOF_TYPE}from"@eventsdk/sdk/contracts";var EventOriginError=class extends Error{constructor(code){super(code);this.code=code}code};var eventOriginTyp=EVENTSDK_ORIGIN_PROOF_TYPE;var originAlgorithms=["RS256","PS256","ES256","EdDSA"];var publicJwkFields=new Set(["kty","kid","alg","use","key_ops","ext","n","e","crv","x","y","x5c","x5t","x5t#S256"]);function validateOriginBinding(policy){if(![policy.issuer,policy.subject,policy.serviceRef,policy.source].every(ref)||!Number.isFinite(Date.parse(policy.keysValidUntil))||!Number.isInteger(policy.verificationTtlMs??6e4)||(policy.verificationTtlMs??6e4)<1||(policy.verificationTtlMs??6e4)>3e5)throw new EventOriginError("INVALID_ORIGIN_POLICY")}function validatePublicOriginKeys(jwks){if(!jwks||!Array.isArray(jwks.keys)||jwks.keys.length<1||jwks.keys.length>32||new Set(jwks.keys.map(key=>key.kid)).size!==jwks.keys.length||jwks.keys.some(key=>!ref(key.kid)||key.kty==="oct"||Object.keys(key).some(member=>!publicJwkFields.has(member))||["d","k","p","q","dp","dq","qi","oth"].some(member=>member in key)))throw new EventOriginError("INVALID_ORIGIN_POLICY")}function ref(value){return typeof value==="string"&&value.length>0&&value.length<=2048&&[...value].every(character=>character.charCodeAt(0)>32&&character.charCodeAt(0)!==127)}function assertCurrentOriginTrust(policy,now){if(!Number.isFinite(now.getTime())||now.getTime()>=Date.parse(policy.keysValidUntil))throw new EventOriginError("TRUST_SNAPSHOT_EXPIRED")}function assertOriginEvent(policy,event){if(event.source!==policy.source||event.serviceorigin!==policy.serviceRef)throw new EventOriginError("ORIGIN_PROOF_REJECTED")}function freshEventOrigin(policy,audience){const now=policy.clock();assertCurrentOriginTrust(policy,now);return Object.freeze({serviceRef:policy.serviceRef,issuer:policy.issuer,subject:policy.subject,audience:Object.freeze([audience]),verifiedAt:now.toISOString(),expiresAt:new Date(Math.min(Date.parse(policy.keysValidUntil),now.getTime()+(policy.verificationTtlMs??6e4))).toISOString()})}async function createEventOriginSigner(input){const policy={...structuredClone({...input,clock:void 0}),clock:input.clock};validateOriginBinding(policy);if(!ref(policy.keyId)||!originAlgorithms.includes(policy.algorithm)||!policy.audiences.length||policy.audiences.length>32||policy.audiences.some(a=>!ref(a))||new Set(policy.audiences).size!==policy.audiences.length)throw new EventOriginError("INVALID_ORIGIN_POLICY");let key;try{key=await importPKCS8(policy.privateKeyPkcs8,policy.algorithm)}catch{throw new EventOriginError("INVALID_ORIGIN_POLICY")}const currentOrigin=audience=>{if(!policy.audiences.includes(audience))throw new EventOriginError("ORIGIN_PROOF_REJECTED");return freshEventOrigin(policy,audience)};return{currentOrigin,async sign(raw,signal){signal.throwIfAborted();const event=parseCloudEvent(structuredClone(raw));assertOriginEvent(policy,event);currentOrigin(event.audience);const claims=parseEventOriginClaims({schemaVersion:1,purpose:"eventsdk-origin/1",issuer:policy.issuer,subject:policy.subject,serviceRef:policy.serviceRef,audience:event.audience,source:event.source,eventId:event.id,...event.profile==="eventsdk/1.2"?{deliveryId:event.deliveryid}:{},eventDigest:originEventDigest(event),signedAt:policy.clock().toISOString()});const proof=await new CompactSign(new TextEncoder().encode(canonicalJson2(claims))).setProtectedHeader({typ:eventOriginTyp,alg:policy.algorithm,kid:policy.keyId}).sign(key);signal.throwIfAborted();assertCurrentOriginTrust(policy,policy.clock());if(proof.length>8192)throw new EventOriginError("ORIGIN_PROOF_REJECTED");return proof}}}import{compactVerify,createLocalJWKSet as createLocalJWKSet2,decodeProtectedHeader as decodeProtectedHeader2,errors}from"jose";import{parseCloudEvent as parseCloudEvent2,parseEventOriginClaims as parseEventOriginClaims2,parseJsonStrict}from"@eventsdk/sdk/contracts";function createEventOriginVerifier(input){const policy={...structuredClone({...input,clock:void 0}),clock:input.clock};validateOriginBinding(policy);validatePublicOriginKeys(policy.jwks);if(!ref(policy.audience)||!policy.algorithms.length||policy.algorithms.some(a=>!originAlgorithms.includes(a)))throw new EventOriginError("INVALID_ORIGIN_POLICY");const resolve=createLocalJWKSet2(policy.jwks);return{async verify(eventInput,proof,signal){try{signal.throwIfAborted();assertCurrentOriginTrust(policy,policy.clock());const event=parseCloudEvent2(structuredClone(eventInput));assertOriginEvent(policy,event);if(typeof proof!=="string"||!proof.length||proof.length>8192)throw rejected();const header=decodeProtectedHeader2(proof);if(header.typ!==eventOriginTyp||!ref(header.kid)||Object.keys(header).some(key=>!["typ","alg","kid"].includes(key)))throw rejected();const verified=await compactVerify(proof,resolve,{algorithms:[...policy.algorithms]});const claims=parseEventOriginClaims2(parseJsonStrict(new TextDecoder("utf-8",{fatal:true}).decode(verified.payload)));assertClaims(policy,event,claims);signal.throwIfAborted();assertCurrentOriginTrust(policy,policy.clock());return{verified:true,origin:freshEventOrigin(policy,policy.audience)}}catch(error){return{verified:false,reasonCode:signal.aborted?"CANCELLED":error instanceof errors.JWKSNoMatchingKey?"ORIGIN_KEY_UNAVAILABLE":error instanceof EventOriginError?error.code:"ORIGIN_PROOF_REJECTED"}}}}}function rejected(){return new EventOriginError("ORIGIN_PROOF_REJECTED")}function assertClaims(policy,event,claims){if(claims.issuer!==policy.issuer||claims.subject!==policy.subject||claims.serviceRef!==policy.serviceRef||claims.audience!==policy.audience||event.audience!==policy.audience||claims.source!==event.source||claims.eventId!==event.id||claims.deliveryId!==(event.profile==="eventsdk/1.2"?event.deliveryid:void 0)||claims.eventDigest!==originEventDigest(event)||!Number.isFinite(Date.parse(claims.signedAt)))throw rejected();if(Date.parse(claims.signedAt)>policy.clock().getTime())throw new EventOriginError("ORIGIN_PROOF_NOT_YET_VALID")}export{EventOriginError,createEventOriginSigner,createEventOriginVerifier,createServiceTokenVerifier,eventOriginTyp,validatePublicOriginKeys};
@@ -0,0 +1,15 @@
1
+ import type { JSONWebKeySet } from 'jose';
2
+ import type { OriginVerifierPort } from '@eventsdk/sdk/identity-contracts';
3
+ export interface ServiceTokenPolicy {
4
+ readonly issuer: string;
5
+ readonly audience: string;
6
+ readonly clientId: string;
7
+ readonly subject: string;
8
+ readonly serviceRef: string;
9
+ readonly algorithms: readonly ('RS256' | 'PS256' | 'ES256' | 'EdDSA')[];
10
+ readonly jwks: JSONWebKeySet;
11
+ readonly keysValidUntil: string;
12
+ readonly maxTokenLifetimeSeconds: number;
13
+ readonly clock: () => Date;
14
+ }
15
+ export declare function createServiceTokenVerifier(input: ServiceTokenPolicy): OriginVerifierPort;