@fabricorg/platform-host 1.0.0 → 2.0.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.
package/dist/index.js CHANGED
@@ -14,6 +14,12 @@ var RecoverableFinalizationError = class extends Error {
14
14
  name = "RecoverableFinalizationError";
15
15
  };
16
16
  function createGovernedActionHost(options) {
17
+ if (options.outbox) {
18
+ const outboxStore = asOutboxStore(options.store);
19
+ if (!outboxStore || !asAtomicMutationStore(options.store) || outboxStore.transactionalOutbox !== true) {
20
+ throw new Error("Outbox egress requires a store with transactionalOutbox and transactionWithEvents capabilities.");
21
+ }
22
+ }
17
23
  const adapters = new AdapterRegistry();
18
24
  for (const adapter of options.adapters ?? []) adapters.register(adapter);
19
25
  const now = options.now ?? (() => /* @__PURE__ */ new Date());
@@ -320,6 +326,9 @@ function createGovernedActionHost(options) {
320
326
  let domainEvents = [];
321
327
  try {
322
328
  const runHandler = async (db, transaction) => {
329
+ if (options.outbox && !transaction?.appendEventWithOutbox) {
330
+ throw new Error("Outbox egress requires transactionWithEvents to provide appendEventWithOutbox before handler execution.");
331
+ }
323
332
  const handlerResult = action.handler ? await action.handler(
324
333
  {
325
334
  actionInvocationId,
@@ -338,6 +347,13 @@ function createGovernedActionHost(options) {
338
347
  throw new Error(handlerResult.error ?? "Action handler failed");
339
348
  }
340
349
  const handlerData = handlerResult.data ?? {};
350
+ if (action.resultSchema) {
351
+ const publicResult = withoutPrivateHostFields(handlerData, eventResultFields);
352
+ const parsedResult = action.resultSchema.safeParse(publicResult);
353
+ if (!parsedResult.success) {
354
+ throw new Error(`Action result validation failed at ${parsedResult.error.issues.map((issue) => issue.path.map(String).join(".") || "result").join(", ")}`);
355
+ }
356
+ }
341
357
  const events = extractEvents(handlerData);
342
358
  const undeclaredEvent = events.find(
343
359
  (event) => !action.emitsEvents.includes(event.eventType)
@@ -678,7 +694,30 @@ function createGovernedActionHost(options) {
678
694
  correlationId: invocation.correlationId,
679
695
  ...invocation.causationId ? { causationId: invocation.causationId } : {}
680
696
  };
681
- await (transaction ?? options.store).appendEvent(envelope);
697
+ if (options.outbox) {
698
+ const hostLifecycleEvent = (/* @__PURE__ */ new Set(["AdapterInvocationStarted", "AdapterInvocationSucceeded", "AdapterInvocationFailed", "ComplianceBlocked"])).has(envelope.eventType);
699
+ const shouldPublish = options.outbox.shouldPublish?.(envelope) ?? !hostLifecycleEvent;
700
+ if (!shouldPublish) {
701
+ await (transaction ?? options.store).appendEvent(envelope);
702
+ return;
703
+ }
704
+ const traceContext = options.outbox.traceContext?.(envelope);
705
+ const metadata = {
706
+ producerModuleVersion: options.outbox.producerModuleVersion(invocation.actionId, invocation.actionVersion),
707
+ payloadClassification: options.outbox.classifyPayload(envelope),
708
+ ...traceContext ? { traceContext } : {}
709
+ };
710
+ if (transaction) {
711
+ if (!transaction.appendEventWithOutbox) throw new Error("Outbox egress requires an atomic transaction with appendEventWithOutbox.");
712
+ await transaction.appendEventWithOutbox(envelope, metadata);
713
+ } else {
714
+ const outboxStore = asOutboxStore(options.store);
715
+ if (!outboxStore) throw new Error("Outbox egress requires an outbox-capable Platform Host store.");
716
+ await outboxStore.appendEventWithOutbox(envelope, metadata);
717
+ }
718
+ } else {
719
+ await (transaction ?? options.store).appendEvent(envelope);
720
+ }
682
721
  }
683
722
  async function fail(invocation, status, error) {
684
723
  await options.store.updateActionInvocation(
@@ -715,6 +754,10 @@ function asAtomicMutationStore(store) {
715
754
  const candidate = store;
716
755
  return typeof candidate.transactionWithEvents === "function" ? store : void 0;
717
756
  }
757
+ function asOutboxStore(store) {
758
+ const candidate = store;
759
+ return typeof candidate.appendEventWithOutbox === "function" && typeof candidate.claimOutbox === "function" ? store : void 0;
760
+ }
718
761
  function asGovernanceStore(store) {
719
762
  const candidate = store;
720
763
  return typeof candidate.recordMutationGovernance === "function" && typeof candidate.appendPolicyObligations === "function" && typeof candidate.appendExecutionAttestation === "function" ? store : void 0;
@@ -771,12 +814,83 @@ function lifecycleId(prefix, invocationId, key) {
771
814
  return `${prefix}_${invocationId}_${safeKey}`;
772
815
  }
773
816
 
817
+ // src/outbox.ts
818
+ function toEnterpriseEventEnvelope(event, metadata) {
819
+ return {
820
+ eventId: event.id,
821
+ eventType: event.eventType,
822
+ eventSchemaVersion: event.eventSchemaVersion,
823
+ tenantId: event.tenantId,
824
+ spaceId: event.spaceId,
825
+ subjectType: event.subjectType,
826
+ subjectId: event.subjectId,
827
+ sequence: event.sequence,
828
+ ...event.actionInvocationId ? { actionInvocationId: event.actionInvocationId } : {},
829
+ correlationId: event.correlationId,
830
+ ...event.causationId ? { causationId: event.causationId } : {},
831
+ occurredAt: event.occurredAt,
832
+ recordedAt: event.recordedAt,
833
+ producerModuleVersion: metadata.producerModuleVersion,
834
+ payloadClassification: metadata.payloadClassification,
835
+ ...metadata.traceContext ? { traceContext: { ...metadata.traceContext } } : {},
836
+ payload: event.payload
837
+ };
838
+ }
839
+ async function runOutboxRelayCycle(options) {
840
+ const now = options.now ?? (() => /* @__PURE__ */ new Date());
841
+ const maxAttempts = options.maxAttempts ?? 10;
842
+ const records = await options.store.claimOutbox({
843
+ workerId: options.workerId,
844
+ leaseDurationMs: options.leaseDurationMs ?? 3e4,
845
+ limit: options.batchSize ?? 100,
846
+ now: now()
847
+ });
848
+ const result = { claimed: records.length, published: 0, failed: 0, deadLettered: 0 };
849
+ for (const record of records) {
850
+ try {
851
+ await options.publisher.publish(record.event);
852
+ try {
853
+ await options.store.markOutboxPublished(record.id, options.workerId, now());
854
+ } catch {
855
+ result.failed += 1;
856
+ continue;
857
+ }
858
+ result.published += 1;
859
+ } catch {
860
+ const deadLetter = record.attemptCount >= maxAttempts;
861
+ try {
862
+ await options.store.markOutboxFailed({
863
+ id: record.id,
864
+ workerId: options.workerId,
865
+ error: "Event publisher failed",
866
+ availableAt: new Date(now().getTime() + (options.retryDelayMs?.(record.attemptCount) ?? 1e3)),
867
+ deadLetter
868
+ });
869
+ } catch {
870
+ }
871
+ result.failed += 1;
872
+ if (deadLetter) result.deadLettered += 1;
873
+ }
874
+ }
875
+ return result;
876
+ }
877
+ function cloneOutboxRecord(record) {
878
+ return {
879
+ ...record,
880
+ event: { ...record.event, ...record.event.traceContext ? { traceContext: { ...record.event.traceContext } } : {} }
881
+ };
882
+ }
883
+
774
884
  // src/memory-store.ts
775
885
  var MemoryPlatformHostStore = class {
776
- constructor(db) {
886
+ constructor(db, transactionProvider) {
777
887
  this.db = db;
888
+ this.transactionalOutbox = transactionProvider !== void 0;
889
+ if (transactionProvider) this.transactionWithEvents = (run) => this.runTransactionWithEvents(run, transactionProvider);
778
890
  }
779
891
  db;
892
+ transactionalOutbox;
893
+ transactionTail = Promise.resolve();
780
894
  invocations = [];
781
895
  policyEvaluations = [];
782
896
  adapterInvocations = [];
@@ -784,9 +898,54 @@ var MemoryPlatformHostStore = class {
784
898
  policyObligations = [];
785
899
  executionAttestations = [];
786
900
  externalReconciliations = [];
901
+ outbox = [];
787
902
  async transaction(run) {
788
903
  return run(this.db);
789
904
  }
905
+ async runTransactionWithEvents(run, transactionProvider) {
906
+ let release;
907
+ const previous = this.transactionTail;
908
+ this.transactionTail = new Promise((resolve) => {
909
+ release = resolve;
910
+ });
911
+ await previous;
912
+ let domainSnapshot;
913
+ let snapshotCreated = false;
914
+ try {
915
+ domainSnapshot = transactionProvider.snapshot(this.db);
916
+ snapshotCreated = true;
917
+ const pendingEvents = [];
918
+ const pendingUpdates = [];
919
+ const appendPending = async (event, metadata) => {
920
+ if (this.events.some((candidate) => candidate.id === event.id) || pendingEvents.some((candidate) => candidate.event.id === event.id)) return;
921
+ pendingEvents.push({ event, ...metadata ? { metadata } : {} });
922
+ };
923
+ const result = await run({
924
+ db: this.db,
925
+ appendEvent: (event) => appendPending(event),
926
+ appendEventWithOutbox: (event, metadata) => appendPending(event, metadata),
927
+ nextEventSequence: async (tenantId, spaceId) => (await this.listEvents(tenantId, spaceId)).length + pendingEvents.filter((candidate) => candidate.event.tenantId === tenantId && candidate.event.spaceId === spaceId).length + 1,
928
+ listEvents: async (tenantId, spaceId) => [...await this.listEvents(tenantId, spaceId), ...pendingEvents.map((candidate) => candidate.event).filter((event) => event.tenantId === tenantId && event.spaceId === spaceId)],
929
+ updateActionInvocation: async (id, tenantId, spaceId, patch) => {
930
+ pendingUpdates.push({ id, tenantId, spaceId, patch });
931
+ }
932
+ });
933
+ for (const update of pendingUpdates) {
934
+ if (!await this.getActionInvocation(update.id, update.tenantId, update.spaceId)) throw new Error(`ActionInvocation not found: ${update.id}`);
935
+ }
936
+ for (const pending of pendingEvents) {
937
+ if (pending.metadata) await this.appendEventWithOutbox(pending.event, pending.metadata);
938
+ else await this.appendEvent(pending.event);
939
+ }
940
+ for (const update of pendingUpdates) await this.updateActionInvocation(update.id, update.tenantId, update.spaceId, update.patch);
941
+ return result;
942
+ } catch (error) {
943
+ if (snapshotCreated) transactionProvider.restore(this.db, domainSnapshot);
944
+ throw error;
945
+ } finally {
946
+ release();
947
+ }
948
+ }
790
949
  async createActionInvocation(input) {
791
950
  if (input.idempotencyKey) {
792
951
  const existing = this.invocations.find(
@@ -902,6 +1061,53 @@ var MemoryPlatformHostStore = class {
902
1061
  if (this.events.some((candidate) => candidate.id === event.id)) return;
903
1062
  this.events.push(event);
904
1063
  }
1064
+ async appendEventWithOutbox(event, metadata) {
1065
+ if (this.events.some((candidate) => candidate.id === event.id)) return;
1066
+ const createdAt = new Date(event.recordedAt);
1067
+ this.events.push(event);
1068
+ this.outbox.push({
1069
+ id: event.id,
1070
+ tenantId: event.tenantId,
1071
+ spaceId: event.spaceId,
1072
+ event: toEnterpriseEventEnvelope(event, metadata),
1073
+ status: "pending",
1074
+ attemptCount: 0,
1075
+ availableAt: createdAt,
1076
+ createdAt
1077
+ });
1078
+ }
1079
+ async claimOutbox(input) {
1080
+ const current = input.now ?? /* @__PURE__ */ new Date();
1081
+ return this.outbox.filter((record) => record.status === "pending" && record.availableAt <= current && (!record.leaseExpiresAt || record.leaseExpiresAt <= current) && (!input.tenantId || record.tenantId === input.tenantId) && (!input.spaceId || record.spaceId === input.spaceId)).sort((left, right) => left.createdAt.getTime() - right.createdAt.getTime() || left.id.localeCompare(right.id)).slice(0, Math.max(1, Math.min(input.limit ?? 100, 1e3))).map((record) => {
1082
+ record.leaseOwner = input.workerId;
1083
+ record.leaseExpiresAt = new Date(current.getTime() + input.leaseDurationMs);
1084
+ record.attemptCount += 1;
1085
+ return cloneOutboxRecord(record);
1086
+ });
1087
+ }
1088
+ async markOutboxPublished(id, workerId, publishedAt) {
1089
+ const record = this.requireLeasedOutbox(id, workerId);
1090
+ record.status = "published";
1091
+ record.publishedAt = publishedAt;
1092
+ delete record.leaseOwner;
1093
+ delete record.leaseExpiresAt;
1094
+ }
1095
+ async markOutboxFailed(input) {
1096
+ const record = this.requireLeasedOutbox(input.id, input.workerId);
1097
+ record.status = input.deadLetter ? "dead_letter" : "pending";
1098
+ record.lastError = input.error;
1099
+ record.availableAt = input.availableAt;
1100
+ delete record.leaseOwner;
1101
+ delete record.leaseExpiresAt;
1102
+ }
1103
+ async listOutbox(input = {}) {
1104
+ return this.outbox.filter((record) => (!input.tenantId || record.tenantId === input.tenantId) && (!input.spaceId || record.spaceId === input.spaceId) && (!input.statuses?.length || input.statuses.includes(record.status))).map(cloneOutboxRecord);
1105
+ }
1106
+ requireLeasedOutbox(id, workerId) {
1107
+ const record = this.outbox.find((candidate) => candidate.id === id);
1108
+ if (!record || record.leaseOwner !== workerId) throw new Error(`Outbox record ${id} is not leased by ${workerId}.`);
1109
+ return record;
1110
+ }
905
1111
  async nextEventSequence(tenantId, spaceId) {
906
1112
  return this.events.filter((event) => event.tenantId === tenantId && event.spaceId === spaceId).length + 1;
907
1113
  }
@@ -945,12 +1151,14 @@ var PostgresPlatformHostStore = class _PostgresPlatformHostStore {
945
1151
  constructor(db, sql, transactionProvider) {
946
1152
  this.db = db;
947
1153
  this.sql = sql;
1154
+ this.transactionalOutbox = transactionProvider !== void 0;
948
1155
  if (transactionProvider) {
949
1156
  this.transactionWithEvents = async (run) => transactionProvider.run(async ({ db: db2, sql: sql2 }) => {
950
1157
  const scoped = new _PostgresPlatformHostStore(db2, sql2);
951
1158
  return run({
952
1159
  db: db2,
953
1160
  appendEvent: (event) => scoped.appendEvent(event),
1161
+ appendEventWithOutbox: (event, metadata) => scoped.appendEventWithOutbox(event, metadata),
954
1162
  nextEventSequence: (tenantId, spaceId) => scoped.nextEventSequence(tenantId, spaceId),
955
1163
  listEvents: (tenantId, spaceId) => scoped.listEvents(tenantId, spaceId),
956
1164
  updateActionInvocation: (id, tenantId, spaceId, patch) => scoped.updateActionInvocation(id, tenantId, spaceId, patch)
@@ -961,6 +1169,7 @@ var PostgresPlatformHostStore = class _PostgresPlatformHostStore {
961
1169
  db;
962
1170
  sql;
963
1171
  transactionWithEvents;
1172
+ transactionalOutbox;
964
1173
  async ensureSchema() {
965
1174
  await this.sql.query(`
966
1175
  CREATE SCHEMA IF NOT EXISTS fabric_platform;
@@ -1044,6 +1253,15 @@ var PostgresPlatformHostStore = class _PostgresPlatformHostStore {
1044
1253
  CREATE INDEX IF NOT EXISTS asset_events_subject_idx
1045
1254
  ON fabric_platform.asset_events
1046
1255
  (tenant_id, space_id, subject_type, subject_id, sequence);
1256
+ CREATE TABLE IF NOT EXISTS fabric_platform.event_outbox (
1257
+ id text PRIMARY KEY, tenant_id text NOT NULL, space_id text NOT NULL,
1258
+ event jsonb NOT NULL, status text NOT NULL DEFAULT 'pending',
1259
+ attempt_count integer NOT NULL DEFAULT 0, available_at timestamptz NOT NULL,
1260
+ lease_owner text, lease_expires_at timestamptz, last_error text,
1261
+ created_at timestamptz NOT NULL, published_at timestamptz
1262
+ );
1263
+ CREATE INDEX IF NOT EXISTS event_outbox_claim_idx
1264
+ ON fabric_platform.event_outbox (status, available_at, lease_expires_at, created_at);
1047
1265
  `);
1048
1266
  }
1049
1267
  async transaction(run) {
@@ -1326,6 +1544,86 @@ var PostgresPlatformHostStore = class _PostgresPlatformHostStore {
1326
1544
  ]
1327
1545
  );
1328
1546
  }
1547
+ async appendEventWithOutbox(event, metadata) {
1548
+ const envelope = toEnterpriseEventEnvelope(event, metadata);
1549
+ await this.sql.query(
1550
+ `WITH inserted_event AS (
1551
+ INSERT INTO fabric_platform.asset_events
1552
+ (id,tenant_id,space_id,event_type,event_schema_version,subject_type,subject_id,
1553
+ actor_id,actor_type,action_invocation_id,payload,sequence,occurred_at,recorded_at,
1554
+ correlation_id,causation_id)
1555
+ VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11::jsonb,$12,$13,$14,$15,$16)
1556
+ ON CONFLICT (id) DO NOTHING RETURNING id
1557
+ )
1558
+ INSERT INTO fabric_platform.event_outbox
1559
+ (id,tenant_id,space_id,event,status,attempt_count,available_at,created_at)
1560
+ SELECT $1,$2,$3,$17::jsonb,'pending',0,$14,$14 FROM inserted_event
1561
+ ON CONFLICT (id) DO NOTHING`,
1562
+ [
1563
+ event.id,
1564
+ event.tenantId,
1565
+ event.spaceId,
1566
+ event.eventType,
1567
+ event.eventSchemaVersion,
1568
+ event.subjectType,
1569
+ event.subjectId,
1570
+ event.actorId,
1571
+ event.actorType,
1572
+ event.actionInvocationId ?? null,
1573
+ JSON.stringify(event.payload),
1574
+ event.sequence,
1575
+ event.occurredAt,
1576
+ event.recordedAt,
1577
+ event.correlationId,
1578
+ event.causationId ?? null,
1579
+ JSON.stringify(envelope)
1580
+ ]
1581
+ );
1582
+ }
1583
+ async claimOutbox(input) {
1584
+ const current = input.now ?? /* @__PURE__ */ new Date();
1585
+ const leaseExpiresAt = new Date(current.getTime() + input.leaseDurationMs);
1586
+ const result = await this.sql.query(
1587
+ `WITH claimable AS (
1588
+ SELECT id FROM fabric_platform.event_outbox
1589
+ WHERE status='pending' AND available_at <= $1
1590
+ AND (lease_expires_at IS NULL OR lease_expires_at <= $1)
1591
+ AND ($2::text IS NULL OR tenant_id=$2)
1592
+ AND ($3::text IS NULL OR space_id=$3)
1593
+ ORDER BY created_at,id FOR UPDATE SKIP LOCKED LIMIT $4
1594
+ )
1595
+ UPDATE fabric_platform.event_outbox AS item
1596
+ SET lease_owner=$5, lease_expires_at=$6, attempt_count=attempt_count+1
1597
+ FROM claimable WHERE item.id=claimable.id RETURNING item.*`,
1598
+ [current, input.tenantId ?? null, input.spaceId ?? null, Math.max(1, Math.min(input.limit ?? 100, 1e3)), input.workerId, leaseExpiresAt]
1599
+ );
1600
+ return result.rows.map(toOutboxRecord);
1601
+ }
1602
+ async markOutboxPublished(id, workerId, publishedAt) {
1603
+ const result = await this.sql.query(
1604
+ `UPDATE fabric_platform.event_outbox SET status='published',published_at=$3,
1605
+ lease_owner=NULL,lease_expires_at=NULL WHERE id=$1 AND lease_owner=$2 RETURNING id`,
1606
+ [id, workerId, publishedAt]
1607
+ );
1608
+ if (result.rows.length === 0) throw new Error(`Outbox record ${id} is not leased by ${workerId}.`);
1609
+ }
1610
+ async markOutboxFailed(input) {
1611
+ const result = await this.sql.query(
1612
+ `UPDATE fabric_platform.event_outbox SET status=$3,last_error=$4,available_at=$5,
1613
+ lease_owner=NULL,lease_expires_at=NULL WHERE id=$1 AND lease_owner=$2 RETURNING id`,
1614
+ [input.id, input.workerId, input.deadLetter ? "dead_letter" : "pending", input.error, input.availableAt]
1615
+ );
1616
+ if (result.rows.length === 0) throw new Error(`Outbox record ${input.id} is not leased by ${input.workerId}.`);
1617
+ }
1618
+ async listOutbox(input = {}) {
1619
+ const result = await this.sql.query(
1620
+ `SELECT * FROM fabric_platform.event_outbox
1621
+ WHERE ($1::text IS NULL OR tenant_id=$1) AND ($2::text IS NULL OR space_id=$2)
1622
+ AND ($3::text[] IS NULL OR status=ANY($3::text[])) ORDER BY created_at,id`,
1623
+ [input.tenantId ?? null, input.spaceId ?? null, input.statuses?.length ? input.statuses : null]
1624
+ );
1625
+ return result.rows.map(toOutboxRecord);
1626
+ }
1329
1627
  async nextEventSequence(tenantId, spaceId) {
1330
1628
  const result = await this.sql.query(
1331
1629
  `INSERT INTO fabric_platform.event_sequences (tenant_id,space_id,next_sequence)
@@ -1514,6 +1812,41 @@ function toEventRecord(row) {
1514
1812
  ...row.causation_id ? { causationId: String(row.causation_id) } : {}
1515
1813
  };
1516
1814
  }
1815
+ function toOutboxRecord(row) {
1816
+ const event = row.event;
1817
+ return {
1818
+ id: String(row.id),
1819
+ tenantId: String(row.tenant_id),
1820
+ spaceId: String(row.space_id),
1821
+ event: {
1822
+ eventId: String(event.eventId),
1823
+ eventType: String(event.eventType),
1824
+ eventSchemaVersion: Number(event.eventSchemaVersion),
1825
+ tenantId: String(event.tenantId),
1826
+ spaceId: String(event.spaceId),
1827
+ subjectType: String(event.subjectType),
1828
+ subjectId: String(event.subjectId),
1829
+ sequence: Number(event.sequence),
1830
+ ...event.actionInvocationId ? { actionInvocationId: String(event.actionInvocationId) } : {},
1831
+ correlationId: String(event.correlationId),
1832
+ ...event.causationId ? { causationId: String(event.causationId) } : {},
1833
+ occurredAt: new Date(event.occurredAt),
1834
+ recordedAt: new Date(event.recordedAt),
1835
+ producerModuleVersion: String(event.producerModuleVersion),
1836
+ payloadClassification: String(event.payloadClassification),
1837
+ ...event.traceContext ? { traceContext: event.traceContext } : {},
1838
+ payload: event.payload
1839
+ },
1840
+ status: String(row.status),
1841
+ attemptCount: Number(row.attempt_count),
1842
+ availableAt: new Date(row.available_at),
1843
+ ...row.lease_owner ? { leaseOwner: String(row.lease_owner) } : {},
1844
+ ...row.lease_expires_at ? { leaseExpiresAt: new Date(row.lease_expires_at) } : {},
1845
+ ...row.last_error ? { lastError: String(row.last_error) } : {},
1846
+ createdAt: new Date(row.created_at),
1847
+ ...row.published_at ? { publishedAt: new Date(row.published_at) } : {}
1848
+ };
1849
+ }
1517
1850
 
1518
1851
  // src/worker.ts
1519
1852
  var DEFAULT_BATCH_SIZE = 10;
@@ -1583,6 +1916,6 @@ async function abortableDelay(milliseconds, signal) {
1583
1916
  });
1584
1917
  }
1585
1918
 
1586
- export { MemoryPlatformHostStore, PLATFORM_HOST_CONTRACT_VERSION, PostgresPlatformHostStore, createGovernedActionHost, createStoreBackedActionDispatcher, runPlatformActionWorker, runPlatformActionWorkerCycle };
1919
+ export { MemoryPlatformHostStore, PLATFORM_HOST_CONTRACT_VERSION, PostgresPlatformHostStore, cloneOutboxRecord, createGovernedActionHost, createStoreBackedActionDispatcher, runOutboxRelayCycle, runPlatformActionWorker, runPlatformActionWorkerCycle, toEnterpriseEventEnvelope };
1587
1920
  //# sourceMappingURL=index.js.map
1588
1921
  //# sourceMappingURL=index.js.map