@dxos/client-services 0.1.31 → 0.1.32-next.77d513e

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 (52) hide show
  1. package/dist/lib/browser/{chunk-DFO3FW2W.mjs → chunk-E3FD43YN.mjs} +423 -209
  2. package/dist/lib/browser/chunk-E3FD43YN.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +1 -1
  4. package/dist/lib/browser/meta.json +1 -1
  5. package/dist/lib/browser/packlets/testing/index.mjs +3 -3
  6. package/dist/lib/browser/packlets/testing/index.mjs.map +3 -3
  7. package/dist/lib/node/index.cjs +424 -210
  8. package/dist/lib/node/index.cjs.map +3 -3
  9. package/dist/lib/node/meta.json +1 -1
  10. package/dist/lib/node/packlets/testing/index.cjs +432 -218
  11. package/dist/lib/node/packlets/testing/index.cjs.map +3 -3
  12. package/dist/types/src/packlets/identity/identity-manager.d.ts +6 -0
  13. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  14. package/dist/types/src/packlets/invitations/device-invitations-handler.d.ts.map +1 -1
  15. package/dist/types/src/packlets/invitations/space-invitations-handler.d.ts.map +1 -1
  16. package/dist/types/src/packlets/services/service-host.d.ts +1 -0
  17. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  18. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +19 -1
  19. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  20. package/dist/types/src/packlets/spaces/data-space.d.ts +24 -4
  21. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  22. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +29 -1
  23. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
  24. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  25. package/dist/types/src/packlets/testing/host-test-builder.d.ts +2 -2
  26. package/dist/types/src/packlets/testing/host-test-builder.d.ts.map +1 -1
  27. package/dist/types/src/packlets/vault/vault-resource-lock.d.ts +1 -0
  28. package/dist/types/src/packlets/vault/vault-resource-lock.d.ts.map +1 -1
  29. package/package.json +30 -30
  30. package/src/packlets/identity/identity-manager.ts +32 -17
  31. package/src/packlets/invitations/device-invitations-handler.ts +5 -3
  32. package/src/packlets/invitations/space-invitations-handler.test.ts +20 -3
  33. package/src/packlets/invitations/space-invitations-handler.ts +15 -8
  34. package/src/packlets/services/service-context.test.ts +6 -5
  35. package/src/packlets/services/service-host.ts +7 -2
  36. package/src/packlets/spaces/data-space-manager.test.ts +17 -2
  37. package/src/packlets/spaces/data-space-manager.ts +76 -30
  38. package/src/packlets/spaces/data-space.ts +90 -15
  39. package/src/packlets/spaces/notarization-plugin.test.ts +3 -1
  40. package/src/packlets/spaces/notarization-plugin.ts +64 -23
  41. package/src/packlets/spaces/spaces-service.test.ts +1 -1
  42. package/src/packlets/spaces/spaces-service.ts +28 -17
  43. package/src/packlets/testing/host-test-builder.ts +2 -2
  44. package/src/packlets/testing/test-builder.ts +2 -2
  45. package/src/packlets/tests/client-services.test.ts +24 -11
  46. package/src/packlets/tests/client.test.ts +3 -6
  47. package/src/packlets/tests/halo-profile.test.ts +5 -5
  48. package/src/packlets/tests/spaces-invitations.test.ts +4 -4
  49. package/src/packlets/tests/spaces.test.ts +20 -11
  50. package/src/packlets/tests/text.test.ts +6 -6
  51. package/src/packlets/vault/vault-resource-lock.ts +10 -1
  52. package/dist/lib/browser/chunk-DFO3FW2W.mjs.map +0 -7
@@ -65,7 +65,7 @@ var createMockCredential = async ({ signer, issuer }) => (0, import_credentials.
65
65
  });
66
66
 
67
67
  // packages/sdk/client-services/src/packlets/testing/host-test-builder.ts
68
- var import_client7 = require("@dxos/client");
68
+ var import_client9 = require("@dxos/client");
69
69
  var import_credentials13 = require("@dxos/credentials");
70
70
  var import_echo_pipeline6 = require("@dxos/echo-pipeline");
71
71
  var import_testing = require("@dxos/echo-pipeline/testing");
@@ -78,10 +78,10 @@ var import_random_access_storage2 = require("@dxos/random-access-storage");
78
78
  // packages/sdk/client-services/src/packlets/services/service-host.ts
79
79
  var import_node_assert12 = __toESM(require("node:assert"));
80
80
  var import_async19 = require("@dxos/async");
81
- var import_client6 = require("@dxos/client");
81
+ var import_client8 = require("@dxos/client");
82
82
  var import_debug7 = require("@dxos/debug");
83
83
  var import_echo_pipeline5 = require("@dxos/echo-pipeline");
84
- var import_log15 = require("@dxos/log");
84
+ var import_log16 = require("@dxos/log");
85
85
  var import_services8 = require("@dxos/protocols/proto/dxos/client/services");
86
86
 
87
87
  // packages/sdk/client-services/src/packlets/deprecated/tracing.ts
@@ -698,7 +698,7 @@ var IdentityManager = class {
698
698
  identityRecord
699
699
  }, {
700
700
  file: "identity-manager.ts",
701
- line: 63,
701
+ line: 71,
702
702
  scope: this,
703
703
  callSite: (f, a) => f(...a)
704
704
  });
@@ -717,7 +717,7 @@ var IdentityManager = class {
717
717
  (0, import_node_assert2.default)(!this._identity, "Identity already exists.");
718
718
  (0, import_log3.log)("creating identity...", {}, {
719
719
  file: "identity-manager.ts",
720
- line: 78,
720
+ line: 86,
721
721
  scope: this,
722
722
  callSite: (f, a) => f(...a)
723
723
  });
@@ -726,21 +726,23 @@ var IdentityManager = class {
726
726
  identityKey: await this._keyring.createKey(),
727
727
  deviceKey: await this._keyring.createKey(),
728
728
  haloSpace: {
729
- spaceKey: await this._keyring.createKey(),
729
+ key: await this._keyring.createKey(),
730
730
  genesisFeedKey: controlFeedKey,
731
- writeControlFeedKey: controlFeedKey,
732
- writeDataFeedKey: await this._keyring.createKey()
731
+ controlFeedKey,
732
+ dataFeedKey: await this._keyring.createKey()
733
733
  }
734
734
  };
735
735
  const identity = await this._constructIdentity(identityRecord);
736
736
  await identity.open();
737
737
  {
738
738
  const generator = new import_credentials5.CredentialGenerator(this._keyring, identityRecord.identityKey, identityRecord.deviceKey);
739
+ (0, import_node_assert2.default)(identityRecord.haloSpace.genesisFeedKey, "Genesis feed key is required.");
740
+ (0, import_node_assert2.default)(identityRecord.haloSpace.dataFeedKey, "Data feed key is required.");
739
741
  const credentials = [
740
742
  // Space genesis.
741
- ...await generator.createSpaceGenesis(identityRecord.haloSpace.spaceKey, identityRecord.haloSpace.genesisFeedKey),
743
+ ...await generator.createSpaceGenesis(identityRecord.haloSpace.key, identityRecord.haloSpace.genesisFeedKey),
742
744
  // Feed admission.
743
- await generator.createFeedAdmission(identityRecord.haloSpace.spaceKey, identityRecord.haloSpace.writeDataFeedKey, import_credentials6.AdmittedFeed.Designation.DATA)
745
+ await generator.createFeedAdmission(identityRecord.haloSpace.key, identityRecord.haloSpace.dataFeedKey, import_credentials6.AdmittedFeed.Designation.DATA)
744
746
  ];
745
747
  if (displayName) {
746
748
  credentials.push(await generator.createProfileCredential({
@@ -765,7 +767,7 @@ var IdentityManager = class {
765
767
  deviceKey: identity.deviceKey
766
768
  }, {
767
769
  file: "identity-manager.ts",
768
- line: 136,
770
+ line: 143,
769
771
  scope: this,
770
772
  callSite: (f, a) => f(...a)
771
773
  });
@@ -779,7 +781,7 @@ var IdentityManager = class {
779
781
  params
780
782
  }, {
781
783
  file: "identity-manager.ts",
782
- line: 144,
784
+ line: 151,
783
785
  scope: this,
784
786
  callSite: (f, a) => f(...a)
785
787
  });
@@ -788,10 +790,11 @@ var IdentityManager = class {
788
790
  identityKey: params.identityKey,
789
791
  deviceKey: params.deviceKey,
790
792
  haloSpace: {
791
- spaceKey: params.haloSpaceKey,
793
+ key: params.haloSpaceKey,
792
794
  genesisFeedKey: params.haloGenesisFeedKey,
793
- writeControlFeedKey: params.controlFeedKey,
794
- writeDataFeedKey: params.dataFeedKey
795
+ controlFeedKey: params.controlFeedKey,
796
+ dataFeedKey: params.dataFeedKey,
797
+ controlTimeframe: params.controlTimeframe
795
798
  }
796
799
  };
797
800
  const identity = await this._constructIdentity(identityRecord);
@@ -805,7 +808,7 @@ var IdentityManager = class {
805
808
  deviceKey: identity.deviceKey
806
809
  }, {
807
810
  file: "identity-manager.ts",
808
- line: 164,
811
+ line: 172,
809
812
  scope: this,
810
813
  callSite: (f, a) => f(...a)
811
814
  });
@@ -817,14 +820,16 @@ var IdentityManager = class {
817
820
  identityRecord
818
821
  }, {
819
822
  file: "identity-manager.ts",
820
- line: 170,
823
+ line: 178,
821
824
  scope: this,
822
825
  callSite: (f, a) => f(...a)
823
826
  });
824
- const controlFeed = await this._feedStore.openFeed(identityRecord.haloSpace.writeControlFeedKey, {
827
+ (0, import_node_assert2.default)(identityRecord.haloSpace.controlFeedKey);
828
+ const controlFeed = await this._feedStore.openFeed(identityRecord.haloSpace.controlFeedKey, {
825
829
  writable: true
826
830
  });
827
- const dataFeed = await this._feedStore.openFeed(identityRecord.haloSpace.writeDataFeedKey, {
831
+ (0, import_node_assert2.default)(identityRecord.haloSpace.dataFeedKey);
832
+ const dataFeed = await this._feedStore.openFeed(identityRecord.haloSpace.dataFeedKey, {
828
833
  writable: true
829
834
  });
830
835
  const space = await this._constructSpace({
@@ -848,16 +853,19 @@ var IdentityManager = class {
848
853
  identityKey: identityRecord.identityKey
849
854
  }, {
850
855
  file: "identity-manager.ts",
851
- line: 196,
856
+ line: 206,
852
857
  scope: this,
853
858
  callSite: (f, a) => f(...a)
854
859
  });
860
+ if (identityRecord.haloSpace.controlTimeframe) {
861
+ identity.controlPipeline.state.setTargetTimeframe(identityRecord.haloSpace.controlTimeframe);
862
+ }
855
863
  return identity;
856
864
  }
857
865
  async _constructSpace({ spaceRecord, swarmIdentity, identityKey }) {
858
866
  return this._spaceManager.constructSpace({
859
867
  metadata: {
860
- key: spaceRecord.spaceKey,
868
+ key: spaceRecord.key,
861
869
  genesisFeedKey: spaceRecord.genesisFeedKey
862
870
  },
863
871
  swarmIdentity,
@@ -973,7 +981,8 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
973
981
  return {
974
982
  identityKey: identity.identityKey,
975
983
  haloSpaceKey: identity.haloSpaceKey,
976
- genesisFeedKey: identity.haloGenesisFeedKey
984
+ genesisFeedKey: identity.haloGenesisFeedKey,
985
+ controlTimeframe: identity.controlPipeline.state.timeframe
977
986
  };
978
987
  },
979
988
  authenticate: async ({ authenticationCode: code }) => {
@@ -981,7 +990,7 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
981
990
  authenticationCode: code
982
991
  }, {
983
992
  file: "device-invitations-handler.ts",
984
- line: 106,
993
+ line: 107,
985
994
  scope: this,
986
995
  callSite: (f, a) => f(...a)
987
996
  });
@@ -1003,7 +1012,7 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
1003
1012
  guest: credentials.deviceKey
1004
1013
  }, {
1005
1014
  file: "device-invitations-handler.ts",
1006
- line: 121,
1015
+ line: 122,
1007
1016
  scope: this,
1008
1017
  callSite: (f, a) => f(...a)
1009
1018
  });
@@ -1022,7 +1031,7 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
1022
1031
  host: identity.deviceKey
1023
1032
  }, {
1024
1033
  file: "device-invitations-handler.ts",
1025
- line: 137,
1034
+ line: 138,
1026
1035
  scope: this,
1027
1036
  callSite: (f, a) => f(...a)
1028
1037
  });
@@ -1035,7 +1044,7 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
1035
1044
  guest: deviceKey
1036
1045
  }, {
1037
1046
  file: "device-invitations-handler.ts",
1038
- line: 140,
1047
+ line: 141,
1039
1048
  scope: this,
1040
1049
  callSite: (f, a) => f(...a)
1041
1050
  });
@@ -1044,7 +1053,7 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
1044
1053
  if (!observable.cancelled) {
1045
1054
  import_log4.log.error("failed", err, {
1046
1055
  file: "device-invitations-handler.ts",
1047
- line: 144,
1056
+ line: 145,
1048
1057
  scope: this,
1049
1058
  callSite: (f, a) => f(...a)
1050
1059
  });
@@ -1109,22 +1118,22 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
1109
1118
  }
1110
1119
  (0, import_log4.log)("connected", {}, {
1111
1120
  file: "device-invitations-handler.ts",
1112
- line: 215,
1121
+ line: 216,
1113
1122
  scope: this,
1114
1123
  callSite: (f, a) => f(...a)
1115
1124
  });
1116
1125
  (_b = (_a = observable.callback).onConnected) == null ? void 0 : _b.call(_a, invitation);
1117
1126
  (0, import_log4.log)("sending admission request", {}, {
1118
1127
  file: "device-invitations-handler.ts",
1119
- line: 219,
1128
+ line: 220,
1120
1129
  scope: this,
1121
1130
  callSite: (f, a) => f(...a)
1122
1131
  });
1123
- const { identityKey, haloSpaceKey, genesisFeedKey } = await extension.rpc.HaloHostService.requestAdmission();
1132
+ const { identityKey, haloSpaceKey, genesisFeedKey, controlTimeframe } = await extension.rpc.HaloHostService.requestAdmission();
1124
1133
  if (invitation.type === void 0 || invitation.type === import_services2.Invitation.Type.INTERACTIVE) {
1125
1134
  (0, import_log4.log)("guest waiting for authentication code...", {}, {
1126
1135
  file: "device-invitations-handler.ts",
1127
- line: 226,
1136
+ line: 227,
1128
1137
  scope: this,
1129
1138
  callSite: (f, a) => f(...a)
1130
1139
  });
@@ -1134,7 +1143,7 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
1134
1143
  });
1135
1144
  (0, import_log4.log)("sending authentication request", {}, {
1136
1145
  file: "device-invitations-handler.ts",
1137
- line: 229,
1146
+ line: 230,
1138
1147
  scope: this,
1139
1148
  callSite: (f, a) => f(...a)
1140
1149
  });
@@ -1152,7 +1161,7 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
1152
1161
  dataFeedKey
1153
1162
  }, {
1154
1163
  file: "device-invitations-handler.ts",
1155
- line: 238,
1164
+ line: 239,
1156
1165
  scope: this,
1157
1166
  callSite: (f, a) => f(...a)
1158
1167
  });
@@ -1167,14 +1176,15 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
1167
1176
  haloSpaceKey,
1168
1177
  haloGenesisFeedKey: genesisFeedKey,
1169
1178
  controlFeedKey,
1170
- dataFeedKey
1179
+ dataFeedKey,
1180
+ controlTimeframe
1171
1181
  });
1172
1182
  (0, import_log4.log)("admitted by host", {
1173
1183
  guest: identity.deviceKey,
1174
1184
  identityKey
1175
1185
  }, {
1176
1186
  file: "device-invitations-handler.ts",
1177
- line: 257,
1187
+ line: 259,
1178
1188
  scope: this,
1179
1189
  callSite: (f, a) => f(...a)
1180
1190
  });
@@ -1183,7 +1193,7 @@ var DeviceInvitationsHandler = class extends import_client.AbstractInvitationsHa
1183
1193
  if (!observable.cancelled) {
1184
1194
  import_log4.log.warn("auth failed", err, {
1185
1195
  file: "device-invitations-handler.ts",
1186
- line: 261,
1196
+ line: 263,
1187
1197
  scope: this,
1188
1198
  callSite: (f, a) => f(...a)
1189
1199
  });
@@ -1627,6 +1637,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1627
1637
  };
1628
1638
  },
1629
1639
  requestAdmission: async ({ identityKey, deviceKey, controlFeedKey, dataFeedKey }) => {
1640
+ var _a2;
1630
1641
  try {
1631
1642
  if (isAuthenticationRequired(invitation) && !authenticationPassed) {
1632
1643
  throw new Error("Not authenticated");
@@ -1647,7 +1658,9 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1647
1658
  await (0, import_feed_store3.writeMessages)(space.inner.controlPipeline.writer, credentials);
1648
1659
  complete.wake(deviceKey);
1649
1660
  return {
1650
- credential: spaceMemberCredential
1661
+ credential: spaceMemberCredential,
1662
+ controlTimeframe: space.inner.controlPipeline.state.timeframe,
1663
+ dataTimeframe: (_a2 = space.dataPipeline.pipelineState) == null ? void 0 : _a2.timeframe
1651
1664
  };
1652
1665
  } catch (err) {
1653
1666
  observable.callback.onError(err);
@@ -1662,7 +1675,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1662
1675
  host: this._signingContext.deviceKey
1663
1676
  }, {
1664
1677
  file: "space-invitations-handler.ts",
1665
- line: 191,
1678
+ line: 195,
1666
1679
  scope: this,
1667
1680
  callSite: (f, a) => f(...a)
1668
1681
  });
@@ -1675,7 +1688,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1675
1688
  guest: deviceKey
1676
1689
  }, {
1677
1690
  file: "space-invitations-handler.ts",
1678
- line: 194,
1691
+ line: 198,
1679
1692
  scope: this,
1680
1693
  callSite: (f, a) => f(...a)
1681
1694
  });
@@ -1684,7 +1697,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1684
1697
  if (!observable.cancelled) {
1685
1698
  import_log6.log.error("failed", err, {
1686
1699
  file: "space-invitations-handler.ts",
1687
- line: 198,
1700
+ line: 202,
1688
1701
  scope: this,
1689
1702
  callSite: (f, a) => f(...a)
1690
1703
  });
@@ -1754,7 +1767,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1754
1767
  guest: this._signingContext.deviceKey
1755
1768
  }, {
1756
1769
  file: "space-invitations-handler.ts",
1757
- line: 271,
1770
+ line: 275,
1758
1771
  scope: this,
1759
1772
  callSite: (f, a) => f(...a)
1760
1773
  });
@@ -1763,7 +1776,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1763
1776
  guest: this._signingContext.deviceKey
1764
1777
  }, {
1765
1778
  file: "space-invitations-handler.ts",
1766
- line: 275,
1779
+ line: 279,
1767
1780
  scope: this,
1768
1781
  callSite: (f, a) => f(...a)
1769
1782
  });
@@ -1775,7 +1788,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1775
1788
  response: introductionResponse
1776
1789
  }, {
1777
1790
  file: "space-invitations-handler.ts",
1778
- line: 279,
1791
+ line: 283,
1779
1792
  scope: this,
1780
1793
  callSite: (f, a) => f(...a)
1781
1794
  });
@@ -1788,7 +1801,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1788
1801
  for (let attempt = 1; attempt <= MAX_OTP_ATTEMPTS; attempt++) {
1789
1802
  (0, import_log6.log)("guest waiting for authentication code...", {}, {
1790
1803
  file: "space-invitations-handler.ts",
1791
- line: 293,
1804
+ line: 297,
1792
1805
  scope: this,
1793
1806
  callSite: (f, a) => f(...a)
1794
1807
  });
@@ -1798,7 +1811,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1798
1811
  });
1799
1812
  (0, import_log6.log)("sending authentication request", {}, {
1800
1813
  file: "space-invitations-handler.ts",
1801
- line: 297,
1814
+ line: 301,
1802
1815
  scope: this,
1803
1816
  callSite: (f, a) => f(...a)
1804
1817
  });
@@ -1816,7 +1829,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1816
1829
  attempt
1817
1830
  }, {
1818
1831
  file: "space-invitations-handler.ts",
1819
- line: 307,
1832
+ line: 311,
1820
1833
  scope: this,
1821
1834
  callSite: (f, a) => f(...a)
1822
1835
  });
@@ -1831,11 +1844,11 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1831
1844
  guest: this._signingContext.deviceKey
1832
1845
  }, {
1833
1846
  file: "space-invitations-handler.ts",
1834
- line: 318,
1847
+ line: 322,
1835
1848
  scope: this,
1836
1849
  callSite: (f, a) => f(...a)
1837
1850
  });
1838
- const { credential } = await extension.rpc.SpaceHostService.requestAdmission({
1851
+ const { credential, controlTimeframe, dataTimeframe } = await extension.rpc.SpaceHostService.requestAdmission({
1839
1852
  identityKey: this._signingContext.identityKey,
1840
1853
  deviceKey: this._signingContext.deviceKey,
1841
1854
  controlFeedKey,
@@ -1846,7 +1859,9 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1846
1859
  (0, import_node_assert6.default)(credential.subject.id.equals(this._signingContext.identityKey));
1847
1860
  const space = await this._spaceManager.acceptSpace({
1848
1861
  spaceKey: assertion.spaceKey,
1849
- genesisFeedKey: assertion.genesisFeedKey
1862
+ genesisFeedKey: assertion.genesisFeedKey,
1863
+ controlTimeframe,
1864
+ dataTimeframe
1850
1865
  });
1851
1866
  await this._signingContext.recordCredential(credential);
1852
1867
  (0, import_log6.log)("admitted by host", {
@@ -1854,7 +1869,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1854
1869
  spaceKey: space.key
1855
1870
  }, {
1856
1871
  file: "space-invitations-handler.ts",
1857
- line: 340,
1872
+ line: 347,
1858
1873
  scope: this,
1859
1874
  callSite: (f, a) => f(...a)
1860
1875
  });
@@ -1863,7 +1878,7 @@ var SpaceInvitationsHandler = class extends import_client2.AbstractInvitationsHa
1863
1878
  if (!observable.cancelled) {
1864
1879
  import_log6.log.warn("auth failed", err, {
1865
1880
  file: "space-invitations-handler.ts",
1866
- line: 344,
1881
+ line: 351,
1867
1882
  scope: this,
1868
1883
  callSite: (f, a) => f(...a)
1869
1884
  });
@@ -1991,20 +2006,24 @@ var NetworkServiceImpl = class {
1991
2006
  // packages/sdk/client-services/src/packlets/spaces/data-space-manager.ts
1992
2007
  var import_node_assert9 = __toESM(require("node:assert"));
1993
2008
  var import_async11 = require("@dxos/async");
2009
+ var import_client4 = require("@dxos/client");
1994
2010
  var import_context7 = require("@dxos/context");
1995
2011
  var import_credentials11 = require("@dxos/credentials");
1996
2012
  var import_echo_pipeline2 = require("@dxos/echo-pipeline");
1997
2013
  var import_keys9 = require("@dxos/keys");
1998
- var import_log8 = require("@dxos/log");
2014
+ var import_log9 = require("@dxos/log");
1999
2015
  var import_teleport_extension_gossip = require("@dxos/teleport-extension-gossip");
2000
2016
  var import_util5 = require("@dxos/util");
2001
2017
 
2002
2018
  // packages/sdk/client-services/src/packlets/spaces/data-space.ts
2003
2019
  var import_async10 = require("@dxos/async");
2020
+ var import_client3 = require("@dxos/client");
2004
2021
  var import_context6 = require("@dxos/context");
2005
2022
  var import_debug3 = require("@dxos/debug");
2006
2023
  var import_echo_pipeline = require("@dxos/echo-pipeline");
2024
+ var import_errors = require("@dxos/errors");
2007
2025
  var import_keys8 = require("@dxos/keys");
2026
+ var import_log8 = require("@dxos/log");
2008
2027
  var import_credentials10 = require("@dxos/protocols/proto/dxos/halo/credentials");
2009
2028
  var import_util4 = require("@dxos/util");
2010
2029
 
@@ -2017,9 +2036,9 @@ var import_log7 = require("@dxos/log");
2017
2036
  var import_protocols4 = require("@dxos/protocols");
2018
2037
  var import_teleport3 = require("@dxos/teleport");
2019
2038
  var import_util3 = require("@dxos/util");
2020
- var RETRY_TIMEOUT = 1e3;
2021
- var SUCCESS_DELAY = 1e3;
2022
- var NOTARIZE_TIMEOUT = 1e4;
2039
+ var DEFAULT_RETRY_TIMEOUT = 1e3;
2040
+ var DEFAULT_SUCCESS_DELAY = 1e3;
2041
+ var DEFAULT_NOTARIZE_TIMEOUT = 1e4;
2023
2042
  var NotarizationPlugin = class {
2024
2043
  constructor() {
2025
2044
  this._ctx = new import_context5.Context();
@@ -2036,12 +2055,12 @@ var NotarizationPlugin = class {
2036
2055
  /**
2037
2056
  * Request credentials to be notarized.
2038
2057
  */
2039
- async notarize(credentials) {
2058
+ async notarize({ ctx: opCtx, credentials, timeout = DEFAULT_NOTARIZE_TIMEOUT, retryTimeout = DEFAULT_RETRY_TIMEOUT, successDelay = DEFAULT_SUCCESS_DELAY }) {
2040
2059
  (0, import_log7.log)("notarize", {
2041
2060
  credentials
2042
2061
  }, {
2043
2062
  file: "notarization-plugin.ts",
2044
- line: 50,
2063
+ line: 85,
2045
2064
  scope: this,
2046
2065
  callSite: (f, a) => f(...a)
2047
2066
  });
@@ -2053,7 +2072,7 @@ var NotarizationPlugin = class {
2053
2072
  err
2054
2073
  }, {
2055
2074
  file: "notarization-plugin.ts",
2056
- line: 59,
2075
+ line: 94,
2057
2076
  scope: this,
2058
2077
  callSite: (f, a) => f(...a)
2059
2078
  });
@@ -2061,27 +2080,27 @@ var NotarizationPlugin = class {
2061
2080
  errors.throw(err);
2062
2081
  }
2063
2082
  });
2064
- (0, import_async9.scheduleTask)(ctx, () => {
2065
- import_log7.log.warn("Notarization timeout", {}, {
2066
- file: "notarization-plugin.ts",
2067
- line: 67,
2068
- scope: this,
2069
- callSite: (f, a) => f(...a)
2070
- });
2071
- void ctx.dispose();
2072
- errors.throw(new import_async9.TimeoutError(NOTARIZE_TIMEOUT, "Notarization timed out"));
2073
- }, NOTARIZE_TIMEOUT);
2083
+ opCtx == null ? void 0 : opCtx.onDispose(() => ctx.dispose());
2084
+ if (timeout !== 0) {
2085
+ (0, import_async9.scheduleTask)(ctx, () => {
2086
+ import_log7.log.warn("Notarization timeout", {
2087
+ timeout,
2088
+ peers: Array.from(this._extensions).map((extension) => extension.remotePeerId)
2089
+ }, {
2090
+ file: "notarization-plugin.ts",
2091
+ line: 106,
2092
+ scope: this,
2093
+ callSite: (f, a) => f(...a)
2094
+ });
2095
+ void ctx.dispose();
2096
+ errors.throw(new import_async9.TimeoutError(timeout, "Notarization timed out"));
2097
+ }, timeout);
2098
+ }
2074
2099
  const allNotarized = Promise.all(credentials.map((credential) => this._waitUntilProcessed(credential.id)));
2075
2100
  const peersTried = /* @__PURE__ */ new Set();
2076
2101
  const notarizeTask = new import_async9.DeferredTask(ctx, async () => {
2077
2102
  try {
2078
2103
  if (this._extensions.size === 0) {
2079
- import_log7.log.warn("No peers to notarize with", {}, {
2080
- file: "notarization-plugin.ts",
2081
- line: 82,
2082
- scope: this,
2083
- callSite: (f, a) => f(...a)
2084
- });
2085
2104
  return;
2086
2105
  }
2087
2106
  const peer = [
@@ -2089,15 +2108,15 @@ var NotarizationPlugin = class {
2089
2108
  ].find((peer2) => !peersTried.has(peer2));
2090
2109
  if (!peer) {
2091
2110
  import_log7.log.warn("Exhausted all peers to notarize with", {
2092
- retryIn: RETRY_TIMEOUT
2111
+ retryIn: retryTimeout
2093
2112
  }, {
2094
2113
  file: "notarization-plugin.ts",
2095
- line: 89,
2114
+ line: 131,
2096
2115
  scope: this,
2097
2116
  callSite: (f, a) => f(...a)
2098
2117
  });
2099
2118
  peersTried.clear();
2100
- (0, import_async9.scheduleTask)(ctx, () => notarizeTask.schedule(), RETRY_TIMEOUT);
2119
+ (0, import_async9.scheduleTask)(ctx, () => notarizeTask.schedule(), retryTimeout);
2101
2120
  return;
2102
2121
  }
2103
2122
  peersTried.add(peer);
@@ -2106,7 +2125,7 @@ var NotarizationPlugin = class {
2106
2125
  credentialId: credentials.map((credential) => credential.id)
2107
2126
  }, {
2108
2127
  file: "notarization-plugin.ts",
2109
- line: 96,
2128
+ line: 138,
2110
2129
  scope: this,
2111
2130
  callSite: (f, a) => f(...a)
2112
2131
  });
@@ -2115,15 +2134,15 @@ var NotarizationPlugin = class {
2115
2134
  });
2116
2135
  (0, import_log7.log)("success", {}, {
2117
2136
  file: "notarization-plugin.ts",
2118
- line: 100,
2137
+ line: 142,
2119
2138
  scope: this,
2120
2139
  callSite: (f, a) => f(...a)
2121
2140
  });
2122
- await (0, import_async9.sleep)(SUCCESS_DELAY);
2141
+ await (0, import_async9.sleep)(successDelay);
2123
2142
  } catch (err) {
2124
2143
  import_log7.log.warn("error notarizing (recoverable)", err, {
2125
2144
  file: "notarization-plugin.ts",
2126
- line: 103,
2145
+ line: 145,
2127
2146
  scope: this,
2128
2147
  callSite: (f, a) => f(...a)
2129
2148
  });
@@ -2134,12 +2153,13 @@ var NotarizationPlugin = class {
2134
2153
  this._extensionOpened.on(ctx, () => notarizeTask.schedule());
2135
2154
  try {
2136
2155
  await Promise.race([
2156
+ (0, import_context5.rejectOnDispose)(ctx),
2137
2157
  allNotarized,
2138
2158
  errors.wait()
2139
2159
  ]);
2140
2160
  (0, import_log7.log)("done", {}, {
2141
2161
  file: "notarization-plugin.ts",
2142
- line: 114,
2162
+ line: 155,
2143
2163
  scope: this,
2144
2164
  callSite: (f, a) => f(...a)
2145
2165
  });
@@ -2192,7 +2212,7 @@ var NotarizationPlugin = class {
2192
2212
  peer: extension.localPeerId
2193
2213
  }, {
2194
2214
  file: "notarization-plugin.ts",
2195
- line: 163,
2215
+ line: 204,
2196
2216
  scope: this,
2197
2217
  callSite: (f, a) => f(...a)
2198
2218
  });
@@ -2204,7 +2224,7 @@ var NotarizationPlugin = class {
2204
2224
  peer: extension.localPeerId
2205
2225
  }, {
2206
2226
  file: "notarization-plugin.ts",
2207
- line: 168,
2227
+ line: 209,
2208
2228
  scope: this,
2209
2229
  callSite: (f, a) => f(...a)
2210
2230
  });
@@ -2258,18 +2278,22 @@ var __decorate = function(decorators, target, key, desc) {
2258
2278
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2259
2279
  };
2260
2280
  var AUTH_TIMEOUT2 = 3e4;
2261
- var CONTROL_PIPELINE_READY_TIMEFRAME = 3e3;
2262
2281
  var DataSpace = class DataSpace2 {
2263
2282
  constructor(params) {
2264
2283
  this._ctx = new import_context6.Context();
2284
+ this._state = import_client3.SpaceState.CLOSED;
2285
+ this.stateUpdate = new import_async10.Event();
2286
+ var _a;
2265
2287
  this._inner = params.inner;
2288
+ this._inner.stateUpdate.on(this._ctx, () => this.stateUpdate.emit());
2266
2289
  this._gossip = params.gossip;
2267
2290
  this._presence = params.presence;
2268
2291
  this._keyring = params.keyring;
2269
2292
  this._feedStore = params.feedStore;
2270
2293
  this._metadataStore = params.metadataStore;
2271
2294
  this._signingContext = params.signingContext;
2272
- this._dataPipelineController = new import_echo_pipeline.DataPipelineControllerImpl({
2295
+ this._callbacks = (_a = params.callbacks) != null ? _a : {};
2296
+ this._dataPipeline = new import_echo_pipeline.DataPipeline({
2273
2297
  modelFactory: params.modelFactory,
2274
2298
  metadataStore: params.metadataStore,
2275
2299
  snapshotManager: params.snapshotManager,
@@ -2291,15 +2315,15 @@ var DataSpace = class DataSpace2 {
2291
2315
  get isOpen() {
2292
2316
  return this._inner.isOpen;
2293
2317
  }
2318
+ get state() {
2319
+ return this._state;
2320
+ }
2294
2321
  // TODO(burdon): Can we mark this for debugging only?
2295
2322
  get inner() {
2296
2323
  return this._inner;
2297
2324
  }
2298
- get dataPipelineController() {
2299
- return this._dataPipelineController;
2300
- }
2301
- get stateUpdate() {
2302
- return this._inner.stateUpdate;
2325
+ get dataPipeline() {
2326
+ return this._dataPipeline;
2303
2327
  }
2304
2328
  get presence() {
2305
2329
  return this._presence;
@@ -2311,9 +2335,12 @@ var DataSpace = class DataSpace2 {
2311
2335
  await this.notarizationPlugin.open();
2312
2336
  await this._notarizationPluginConsumer.open();
2313
2337
  await this._inner.open();
2338
+ this._state = import_client3.SpaceState.INACTIVE;
2314
2339
  }
2315
2340
  async close() {
2341
+ this._state = import_client3.SpaceState.CLOSED;
2316
2342
  await this._ctx.dispose();
2343
+ await this._dataPipeline.close();
2317
2344
  await this.authVerifier.close();
2318
2345
  await this._inner.close();
2319
2346
  await this._notarizationPluginConsumer.close();
@@ -2326,17 +2353,84 @@ var DataSpace = class DataSpace2 {
2326
2353
  listen(channel, callback) {
2327
2354
  return this._gossip.listen(channel, callback);
2328
2355
  }
2356
+ /**
2357
+ * Initialize the data pipeline in a separate task.
2358
+ */
2359
+ initializeDataPipelineAsync() {
2360
+ (0, import_async10.scheduleTask)(this._ctx, async () => {
2361
+ try {
2362
+ await this.initializeDataPipeline();
2363
+ } catch (err) {
2364
+ if (err instanceof import_errors.CancelledError) {
2365
+ (0, import_log8.log)("Data pipeline initialization cancelled", err, {
2366
+ file: "data-space.ts",
2367
+ line: 178,
2368
+ scope: this,
2369
+ callSite: (f, a) => f(...a)
2370
+ });
2371
+ return;
2372
+ }
2373
+ import_log8.log.error("Error initializing data pipeline", err, {
2374
+ file: "data-space.ts",
2375
+ line: 182,
2376
+ scope: this,
2377
+ callSite: (f, a) => f(...a)
2378
+ });
2379
+ }
2380
+ });
2381
+ }
2329
2382
  async initializeDataPipeline() {
2383
+ var _a, _b, _c, _d;
2384
+ if (this._state !== import_client3.SpaceState.INACTIVE) {
2385
+ throw new import_errors.SystemError("Invalid operation");
2386
+ }
2387
+ this._state = import_client3.SpaceState.INITIALIZING;
2330
2388
  await this._inner.controlPipeline.state.waitUntilReachedTargetTimeframe({
2331
- timeout: CONTROL_PIPELINE_READY_TIMEFRAME
2389
+ ctx: this._ctx,
2390
+ breakOnStall: false
2332
2391
  });
2333
2392
  await this._createWritableFeeds();
2393
+ (0, import_log8.log)("Writable feeds created", {}, {
2394
+ file: "data-space.ts",
2395
+ line: 200,
2396
+ scope: this,
2397
+ callSite: (f, a) => f(...a)
2398
+ });
2399
+ this.stateUpdate.emit();
2334
2400
  this.notarizationPlugin.setWriter((0, import_echo_pipeline.createMappedFeedWriter)((credential) => ({
2335
2401
  credential: {
2336
2402
  credential
2337
2403
  }
2338
2404
  }), this._inner.controlPipeline.writer));
2339
- await this._inner.initDataPipeline(this._dataPipelineController);
2405
+ await this._dataPipeline.open({
2406
+ openPipeline: async (start) => {
2407
+ const pipeline = await this._inner.createDataPipeline({
2408
+ start
2409
+ });
2410
+ await pipeline.start();
2411
+ return pipeline;
2412
+ }
2413
+ });
2414
+ (0, import_log8.log)("waiting for data pipeline to reach target timeframe", {}, {
2415
+ file: "data-space.ts",
2416
+ line: 220,
2417
+ scope: this,
2418
+ callSite: (f, a) => f(...a)
2419
+ });
2420
+ await this._dataPipeline.pipelineState.waitUntilReachedTargetTimeframe({
2421
+ ctx: this._ctx,
2422
+ breakOnStall: false
2423
+ });
2424
+ (0, import_log8.log)("data pipeline ready", {}, {
2425
+ file: "data-space.ts",
2426
+ line: 227,
2427
+ scope: this,
2428
+ callSite: (f, a) => f(...a)
2429
+ });
2430
+ await ((_b = (_a = this._callbacks).beforeReady) == null ? void 0 : _b.call(_a));
2431
+ this._state = import_client3.SpaceState.READY;
2432
+ this.stateUpdate.emit();
2433
+ await ((_d = (_c = this._callbacks).afterReady) == null ? void 0 : _d.call(_c));
2340
2434
  }
2341
2435
  async _createWritableFeeds() {
2342
2436
  const credentials = [];
@@ -2373,7 +2467,11 @@ var DataSpace = class DataSpace2 {
2373
2467
  }));
2374
2468
  }
2375
2469
  if (credentials.length > 0) {
2376
- await this.notarizationPlugin.notarize(credentials);
2470
+ await this.notarizationPlugin.notarize({
2471
+ ctx: this._ctx,
2472
+ credentials,
2473
+ timeout: 0
2474
+ });
2377
2475
  }
2378
2476
  await this._metadataStore.setWritableFeedKeys(this.key, this.inner.controlFeedKey, this.inner.dataFeedKey);
2379
2477
  }
@@ -2396,7 +2494,6 @@ var __decorate2 = function(decorators, target, key, desc) {
2396
2494
  r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
2397
2495
  return c > 3 && r && Object.defineProperty(target, key, r), r;
2398
2496
  };
2399
- var DATA_PIPELINE_READY_TIMEOUT = 3e3;
2400
2497
  var DataSpaceManager = class DataSpaceManager2 {
2401
2498
  constructor(_spaceManager, _metadataStore, _dataServiceSubscriptions, _keyring, _signingContext, _modelFactory, _feedStore, _snapshotStore) {
2402
2499
  this._spaceManager = _spaceManager;
@@ -2410,50 +2507,51 @@ var DataSpaceManager = class DataSpaceManager2 {
2410
2507
  this._ctx = new import_context7.Context();
2411
2508
  this.updated = new import_async11.Event();
2412
2509
  this._spaces = new import_util5.ComplexMap(import_keys9.PublicKey.hash);
2510
+ this._isOpen = false;
2413
2511
  }
2414
2512
  // TODO(burdon): Remove.
2415
2513
  get spaces() {
2416
2514
  return this._spaces;
2417
2515
  }
2418
2516
  async open() {
2517
+ (0, import_log9.log)("open", {}, {
2518
+ file: "data-space-manager.ts",
2519
+ line: 80,
2520
+ scope: this,
2521
+ callSite: (f, a) => f(...a)
2522
+ });
2419
2523
  await this._metadataStore.load();
2420
- (0, import_log8.log)("metadata loaded", {
2524
+ (0, import_log9.log)("metadata loaded", {
2421
2525
  spaces: this._metadataStore.spaces.length
2422
2526
  }, {
2423
2527
  file: "data-space-manager.ts",
2424
- line: 67,
2528
+ line: 82,
2425
2529
  scope: this,
2426
2530
  callSite: (f, a) => f(...a)
2427
2531
  });
2428
2532
  for (const spaceMetadata of this._metadataStore.spaces) {
2429
- (0, import_log8.log)("load space", {
2533
+ (0, import_log9.log)("load space", {
2430
2534
  spaceMetadata
2431
2535
  }, {
2432
2536
  file: "data-space-manager.ts",
2433
- line: 70,
2537
+ line: 85,
2434
2538
  scope: this,
2435
2539
  callSite: (f, a) => f(...a)
2436
2540
  });
2437
2541
  const space = await this._constructSpace(spaceMetadata);
2438
- await space.initializeDataPipeline();
2439
- if (spaceMetadata.dataTimeframe) {
2440
- (0, import_log8.log)("waiting for latest timeframe", {
2441
- spaceMetadata
2442
- }, {
2443
- file: "data-space-manager.ts",
2444
- line: 74,
2445
- scope: this,
2446
- callSite: (f, a) => f(...a)
2447
- });
2448
- await space.dataPipelineController.pipelineState.setTargetTimeframe(spaceMetadata.dataTimeframe);
2449
- }
2450
- await space.dataPipelineController.pipelineState.waitUntilReachedTargetTimeframe({
2451
- timeout: DATA_PIPELINE_READY_TIMEOUT
2452
- });
2453
- this._dataServiceSubscriptions.registerSpace(space.key, space.dataPipelineController.databaseBackend.createDataServiceHost());
2542
+ space.initializeDataPipelineAsync();
2454
2543
  }
2544
+ this._isOpen = true;
2545
+ this.updated.emit();
2455
2546
  }
2456
2547
  async close() {
2548
+ (0, import_log9.log)("close", {}, {
2549
+ file: "data-space-manager.ts",
2550
+ line: 96,
2551
+ scope: this,
2552
+ callSite: (f, a) => f(...a)
2553
+ });
2554
+ this._isOpen = false;
2457
2555
  await this._ctx.dispose();
2458
2556
  for (const space of this._spaces.values()) {
2459
2557
  await space.close();
@@ -2463,6 +2561,7 @@ var DataSpaceManager = class DataSpaceManager2 {
2463
2561
  * Creates a new space writing the genesis credentials to the control feed.
2464
2562
  */
2465
2563
  async createSpace() {
2564
+ (0, import_node_assert9.default)(this._isOpen, "Not open.");
2466
2565
  const spaceKey = await this._keyring.createKey();
2467
2566
  const controlFeedKey = await this._keyring.createKey();
2468
2567
  const dataFeedKey = await this._keyring.createKey();
@@ -2472,11 +2571,11 @@ var DataSpaceManager = class DataSpaceManager2 {
2472
2571
  controlFeedKey,
2473
2572
  dataFeedKey
2474
2573
  };
2475
- (0, import_log8.log)("creating space...", {
2574
+ (0, import_log9.log)("creating space...", {
2476
2575
  spaceKey
2477
2576
  }, {
2478
2577
  file: "data-space-manager.ts",
2479
- line: 110,
2578
+ line: 120,
2480
2579
  scope: this,
2481
2580
  callSite: (f, a) => f(...a)
2482
2581
  });
@@ -2487,25 +2586,53 @@ var DataSpaceManager = class DataSpaceManager2 {
2487
2586
  (0, import_node_assert9.default)((0, import_credentials11.getCredentialAssertion)(memberCredential)["@type"] === "dxos.halo.credentials.SpaceMember");
2488
2587
  await this._signingContext.recordCredential(memberCredential);
2489
2588
  await space.initializeDataPipeline();
2490
- this._dataServiceSubscriptions.registerSpace(space.key, space.dataPipelineController.databaseBackend.createDataServiceHost());
2491
2589
  this.updated.emit();
2492
2590
  return space;
2493
2591
  }
2494
2592
  // TODO(burdon): Rename join space.
2495
2593
  async acceptSpace(opts) {
2594
+ (0, import_log9.log)("accept space", {
2595
+ opts
2596
+ }, {
2597
+ file: "data-space-manager.ts",
2598
+ line: 139,
2599
+ scope: this,
2600
+ callSite: (f, a) => f(...a)
2601
+ });
2602
+ (0, import_node_assert9.default)(this._isOpen, "Not open.");
2496
2603
  (0, import_node_assert9.default)(!this._spaces.has(opts.spaceKey), "Space already exists.");
2497
2604
  const metadata = {
2498
2605
  key: opts.spaceKey,
2499
- genesisFeedKey: opts.genesisFeedKey
2606
+ genesisFeedKey: opts.genesisFeedKey,
2607
+ controlTimeframe: opts.controlTimeframe,
2608
+ dataTimeframe: opts.dataTimeframe
2500
2609
  };
2501
2610
  const space = await this._constructSpace(metadata);
2502
2611
  await this._metadataStore.addSpace(metadata);
2503
- await space.initializeDataPipeline();
2504
- this._dataServiceSubscriptions.registerSpace(space.key, space.dataPipelineController.databaseBackend.createDataServiceHost());
2612
+ space.initializeDataPipelineAsync();
2505
2613
  this.updated.emit();
2506
2614
  return space;
2507
2615
  }
2616
+ /**
2617
+ * Wait until the space data pipeline is fully initialized.
2618
+ * Used by invitation handler.
2619
+ * TODO(dmaretskyi): Consider removing.
2620
+ */
2621
+ async waitUntilSpaceReady(spaceKey) {
2622
+ await (0, import_context7.cancelWithContext)(this._ctx, this.updated.waitForCondition(() => {
2623
+ const space = this._spaces.get(spaceKey);
2624
+ return !!space && space.state === import_client4.SpaceState.READY;
2625
+ }));
2626
+ }
2508
2627
  async _constructSpace(metadata) {
2628
+ (0, import_log9.log)("construct space", {
2629
+ metadata
2630
+ }, {
2631
+ file: "data-space-manager.ts",
2632
+ line: 175,
2633
+ scope: this,
2634
+ callSite: (f, a) => f(...a)
2635
+ });
2509
2636
  const gossip = new import_teleport_extension_gossip.Gossip({
2510
2637
  localPeerId: this._signingContext.deviceKey
2511
2638
  });
@@ -2550,9 +2677,42 @@ var DataSpaceManager = class DataSpaceManager2 {
2550
2677
  keyring: this._keyring,
2551
2678
  feedStore: this._feedStore,
2552
2679
  signingContext: this._signingContext,
2553
- snapshotId: metadata.snapshot
2680
+ snapshotId: metadata.snapshot,
2681
+ callbacks: {
2682
+ beforeReady: async () => {
2683
+ (0, import_log9.log)("before space ready", {
2684
+ space: space.key
2685
+ }, {
2686
+ file: "data-space-manager.ts",
2687
+ line: 224,
2688
+ scope: this,
2689
+ callSite: (f, a) => f(...a)
2690
+ });
2691
+ this._dataServiceSubscriptions.registerSpace(space.key, dataSpace.dataPipeline.databaseBackend.createDataServiceHost());
2692
+ },
2693
+ afterReady: async () => {
2694
+ (0, import_log9.log)("after space ready", {
2695
+ space: space.key,
2696
+ open: this._isOpen
2697
+ }, {
2698
+ file: "data-space-manager.ts",
2699
+ line: 231,
2700
+ scope: this,
2701
+ callSite: (f, a) => f(...a)
2702
+ });
2703
+ if (this._isOpen) {
2704
+ this.updated.emit();
2705
+ }
2706
+ }
2707
+ }
2554
2708
  });
2555
2709
  await dataSpace.open();
2710
+ if (metadata.controlTimeframe) {
2711
+ dataSpace.inner.controlPipeline.state.setTargetTimeframe(metadata.controlTimeframe);
2712
+ }
2713
+ if (metadata.dataTimeframe) {
2714
+ dataSpace.dataPipeline.setTargetTimeframe(metadata.dataTimeframe);
2715
+ }
2556
2716
  this._spaces.set(metadata.key, dataSpace);
2557
2717
  return dataSpace;
2558
2718
  }
@@ -2578,9 +2738,10 @@ var import_async12 = require("@dxos/async");
2578
2738
  var import_codec_protobuf10 = require("@dxos/codec-protobuf");
2579
2739
  var import_debug4 = require("@dxos/debug");
2580
2740
  var import_echo_pipeline3 = require("@dxos/echo-pipeline");
2581
- var import_log9 = require("@dxos/log");
2741
+ var import_log10 = require("@dxos/log");
2582
2742
  var import_services5 = require("@dxos/protocols/proto/dxos/client/services");
2583
2743
  var import_util6 = require("@dxos/util");
2744
+ var TIMEFRAME_UPDATE_DEBOUNCE_TIME = 500;
2584
2745
  var SpacesServiceImpl = class {
2585
2746
  constructor(_identityManager, _spaceManager, _dataServiceSubscriptions, _getDataSpaceManager) {
2586
2747
  this._identityManager = _identityManager;
@@ -2603,12 +2764,12 @@ var SpacesServiceImpl = class {
2603
2764
  return new import_codec_protobuf10.Stream(({ next, ctx }) => {
2604
2765
  const onUpdate = async () => {
2605
2766
  const dataSpaceManager = await this._getDataSpaceManager();
2606
- const spaces = Array.from(dataSpaceManager.spaces.values()).filter((space) => this._dataServiceSubscriptions.getDataService(space.key)).map((space) => this._transformSpace(space));
2607
- (0, import_log9.log)("update", {
2767
+ const spaces = Array.from(dataSpaceManager.spaces.values()).map((space) => this._transformSpace(space));
2768
+ (0, import_log10.log)("update", {
2608
2769
  spaces
2609
2770
  }, {
2610
2771
  file: "spaces-service.ts",
2611
- line: 62,
2772
+ line: 60,
2612
2773
  scope: this,
2613
2774
  callSite: (f, a) => f(...a)
2614
2775
  });
@@ -2616,28 +2777,27 @@ var SpacesServiceImpl = class {
2616
2777
  spaces
2617
2778
  });
2618
2779
  };
2619
- setTimeout(async () => {
2780
+ (0, import_async12.scheduleTask)(ctx, async () => {
2620
2781
  const dataSpaceManager = await this._getDataSpaceManager();
2621
2782
  const subscriptions = new import_async12.EventSubscriptions();
2783
+ ctx.onDispose(() => subscriptions.clear());
2622
2784
  const subscribeSpaces = () => {
2623
2785
  subscriptions.clear();
2624
2786
  for (const space of dataSpaceManager.spaces.values()) {
2625
- if (!this._dataServiceSubscriptions.getDataService(space.key)) {
2626
- continue;
2627
- }
2628
2787
  subscriptions.add(space.stateUpdate.on(ctx, onUpdate));
2629
2788
  subscriptions.add(space.presence.updated.on(ctx, onUpdate));
2789
+ space.inner.controlPipeline.state.timeframeUpdate.debounce(TIMEFRAME_UPDATE_DEBOUNCE_TIME).on(ctx, onUpdate);
2790
+ if (space.dataPipeline.pipelineState) {
2791
+ subscriptions.add(space.dataPipeline.pipelineState.timeframeUpdate.debounce(TIMEFRAME_UPDATE_DEBOUNCE_TIME).on(ctx, onUpdate));
2792
+ }
2630
2793
  }
2631
2794
  };
2632
2795
  dataSpaceManager.updated.on(ctx, () => {
2633
2796
  subscribeSpaces();
2634
2797
  void onUpdate();
2635
2798
  });
2636
- ctx.onDispose(() => subscriptions.clear());
2637
- (0, import_async12.scheduleTask)(ctx, () => {
2638
- subscribeSpaces();
2639
- void onUpdate();
2640
- });
2799
+ subscribeSpaces();
2800
+ void onUpdate();
2641
2801
  });
2642
2802
  if (!this._identityManager.identity) {
2643
2803
  next({
@@ -2690,16 +2850,23 @@ var SpacesServiceImpl = class {
2690
2850
  }
2691
2851
  }
2692
2852
  _transformSpace(space) {
2853
+ var _a, _b;
2693
2854
  return {
2694
2855
  spaceKey: space.key,
2695
- status: space.isOpen ? import_services5.SpaceStatus.ACTIVE : import_services5.SpaceStatus.INACTIVE,
2856
+ state: space.state,
2857
+ pipeline: {
2858
+ targetControlTimeframe: space.inner.controlPipeline.state.targetTimeframe,
2859
+ currentControlTimeframe: space.inner.controlPipeline.state.timeframe,
2860
+ currentDataTimeframe: (_a = space.dataPipeline.pipelineState) == null ? void 0 : _a.timeframe,
2861
+ targetDataTimeframe: (_b = space.dataPipeline.pipelineState) == null ? void 0 : _b.targetTimeframe
2862
+ },
2696
2863
  members: Array.from(space.inner.spaceState.members.values()).map((member) => {
2697
- var _a, _b, _c;
2864
+ var _a2, _b2, _c;
2698
2865
  return {
2699
2866
  identity: {
2700
2867
  identityKey: member.key,
2701
2868
  profile: {
2702
- displayName: (_b = (_a = member.assertion.profile) == null ? void 0 : _a.displayName) != null ? _b : (0, import_util6.humanize)(member.key)
2869
+ displayName: (_b2 = (_a2 = member.assertion.profile) == null ? void 0 : _a2.displayName) != null ? _b2 : (0, import_util6.humanize)(member.key)
2703
2870
  }
2704
2871
  },
2705
2872
  presence: ((_c = this._identityManager.identity) == null ? void 0 : _c.identityKey.equals(member.key)) || space.presence.getPeersOnline().filter(({ identityKey }) => identityKey.equals(member.key)).length > 0 ? import_services5.SpaceMember.PresenceState.ONLINE : import_services5.SpaceMember.PresenceState.OFFLINE
@@ -2711,23 +2878,23 @@ var SpacesServiceImpl = class {
2711
2878
  var getChannelId = (channel) => `user-channel/${channel}`;
2712
2879
 
2713
2880
  // packages/sdk/client-services/src/packlets/storage/storage.ts
2714
- var import_errors = require("@dxos/errors");
2881
+ var import_errors2 = require("@dxos/errors");
2715
2882
  var import_config = require("@dxos/protocols/proto/dxos/config");
2716
2883
  var import_random_access_storage = require("@dxos/random-access-storage");
2717
2884
  var StorageDriver = import_config.Runtime.Client.Storage.StorageDriver;
2718
2885
  var createStorageObjects = (config) => {
2719
2886
  const { path = "dxos/storage", storageType, keyStorage, persistent = false } = config != null ? config : {};
2720
2887
  if (persistent && storageType === StorageDriver.RAM) {
2721
- throw new import_errors.InvalidConfigError("RAM storage cannot be used in persistent mode.");
2888
+ throw new import_errors2.InvalidConfigError("RAM storage cannot be used in persistent mode.");
2722
2889
  }
2723
2890
  if (!persistent && storageType !== void 0 && storageType !== StorageDriver.RAM) {
2724
- throw new import_errors.InvalidConfigError("Cannot use a persistent storage in not persistent mode.");
2891
+ throw new import_errors2.InvalidConfigError("Cannot use a persistent storage in not persistent mode.");
2725
2892
  }
2726
2893
  if (persistent && keyStorage === StorageDriver.RAM) {
2727
- throw new import_errors.InvalidConfigError("RAM key storage cannot be used in persistent mode.");
2894
+ throw new import_errors2.InvalidConfigError("RAM key storage cannot be used in persistent mode.");
2728
2895
  }
2729
2896
  if (!persistent && keyStorage !== StorageDriver.RAM && keyStorage !== void 0) {
2730
- throw new import_errors.InvalidConfigError("Cannot use a persistent key storage in not persistent mode.");
2897
+ throw new import_errors2.InvalidConfigError("Cannot use a persistent key storage in not persistent mode.");
2731
2898
  }
2732
2899
  return {
2733
2900
  storage: (0, import_random_access_storage.createStorage)({
@@ -2795,7 +2962,7 @@ var SystemServiceImpl = class {
2795
2962
 
2796
2963
  // packages/sdk/client-services/src/packlets/vault/iframe-host-runtime.ts
2797
2964
  var import_async14 = require("@dxos/async");
2798
- var import_log10 = require("@dxos/log");
2965
+ var import_log11 = require("@dxos/log");
2799
2966
  var import_messaging = require("@dxos/messaging");
2800
2967
  var import_network_manager3 = require("@dxos/network-manager");
2801
2968
  var import_util7 = require("@dxos/util");
@@ -2856,7 +3023,7 @@ var ClientRpcServer = class {
2856
3023
  // packages/sdk/client-services/src/packlets/vault/shell-runtime.ts
2857
3024
  var import_node_assert10 = __toESM(require("node:assert"));
2858
3025
  var import_async13 = require("@dxos/async");
2859
- var import_client3 = require("@dxos/client");
3026
+ var import_client5 = require("@dxos/client");
2860
3027
  var import_iframe = require("@dxos/protocols/proto/dxos/iframe");
2861
3028
  var import_rpc2 = require("@dxos/rpc");
2862
3029
  var ShellRuntimeImpl = class {
@@ -2889,8 +3056,8 @@ var ShellRuntimeImpl = class {
2889
3056
  }
2890
3057
  async open() {
2891
3058
  this._appRpc = (0, import_rpc2.createProtoRpcPeer)({
2892
- requested: import_client3.appServiceBundle,
2893
- exposed: import_client3.shellServiceBundle,
3059
+ requested: import_client5.appServiceBundle,
3060
+ exposed: import_client5.shellServiceBundle,
2894
3061
  handlers: {
2895
3062
  ShellService: {
2896
3063
  setLayout: async (request) => {
@@ -2943,7 +3110,7 @@ var IFrameHostRuntime = class {
2943
3110
  }
2944
3111
  async start() {
2945
3112
  var _a;
2946
- (0, import_log10.log)("starting...", {}, {
3113
+ (0, import_log11.log)("starting...", {}, {
2947
3114
  file: "iframe-host-runtime.ts",
2948
3115
  line: 67,
2949
3116
  scope: this,
@@ -2994,7 +3161,7 @@ var IFrameHostRuntime = class {
2994
3161
  (_a = this._shellRuntime) == null ? void 0 : _a.open()
2995
3162
  ]);
2996
3163
  this._ready.wake(void 0);
2997
- (0, import_log10.log)("started", {}, {
3164
+ (0, import_log11.log)("started", {}, {
2998
3165
  file: "iframe-host-runtime.ts",
2999
3166
  line: 110,
3000
3167
  scope: this,
@@ -3002,7 +3169,7 @@ var IFrameHostRuntime = class {
3002
3169
  });
3003
3170
  } catch (err) {
3004
3171
  this._ready.wake(err);
3005
- import_log10.log.catch(err, {}, {
3172
+ import_log11.log.catch(err, {}, {
3006
3173
  file: "iframe-host-runtime.ts",
3007
3174
  line: 113,
3008
3175
  scope: this,
@@ -3012,7 +3179,7 @@ var IFrameHostRuntime = class {
3012
3179
  }
3013
3180
  async stop() {
3014
3181
  var _a;
3015
- (0, import_log10.log)("stopping...", {}, {
3182
+ (0, import_log11.log)("stopping...", {}, {
3016
3183
  file: "iframe-host-runtime.ts",
3017
3184
  line: 118,
3018
3185
  scope: this,
@@ -3021,7 +3188,7 @@ var IFrameHostRuntime = class {
3021
3188
  await this._clientRpc.close();
3022
3189
  await this._clientServices.close();
3023
3190
  await ((_a = this._shellRuntime) == null ? void 0 : _a.close());
3024
- (0, import_log10.log)("stopped", {}, {
3191
+ (0, import_log11.log)("stopped", {}, {
3025
3192
  file: "iframe-host-runtime.ts",
3026
3193
  line: 122,
3027
3194
  scope: this,
@@ -3030,17 +3197,27 @@ var IFrameHostRuntime = class {
3030
3197
  }
3031
3198
  };
3032
3199
  __decorate3([
3033
- import_log10.logInfo
3200
+ import_log11.logInfo
3034
3201
  ], IFrameHostRuntime.prototype, "origin", void 0);
3035
3202
 
3036
3203
  // packages/sdk/client-services/src/packlets/vault/iframe-proxy-runtime.ts
3037
- var import_client4 = require("@dxos/client");
3204
+ var import_client6 = require("@dxos/client");
3038
3205
  var import_network_manager4 = require("@dxos/network-manager");
3039
3206
  var import_rpc3 = require("@dxos/rpc");
3040
3207
 
3041
3208
  // packages/sdk/client-services/src/packlets/vault/vault-resource-lock.ts
3042
3209
  var import_async15 = require("@dxos/async");
3043
- var import_log11 = require("@dxos/log");
3210
+ var import_log12 = require("@dxos/log");
3211
+ var __decorate4 = function(decorators, target, key, desc) {
3212
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3213
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
3214
+ r = Reflect.decorate(decorators, target, key, desc);
3215
+ else
3216
+ for (var i = decorators.length - 1; i >= 0; i--)
3217
+ if (d = decorators[i])
3218
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3219
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
3220
+ };
3044
3221
  var Message;
3045
3222
  (function(Message2) {
3046
3223
  Message2["ACQUIRING"] = "acquiring";
@@ -3054,14 +3231,41 @@ var VaultResourceLock = class {
3054
3231
  this._onRelease = onRelease;
3055
3232
  this._broadcastChannel.onmessage = this._onMessage.bind(this);
3056
3233
  }
3234
+ get lockKey() {
3235
+ return this._lockKey;
3236
+ }
3057
3237
  async acquire() {
3058
3238
  this._broadcastChannel.postMessage({
3059
3239
  message: Message.ACQUIRING
3060
3240
  });
3061
3241
  try {
3242
+ (0, import_log12.log)("aquiring lock...", {}, {
3243
+ file: "vault-resource-lock.ts",
3244
+ line: 44,
3245
+ scope: this,
3246
+ callSite: (f, a) => f(...a)
3247
+ });
3062
3248
  await (0, import_async15.asyncTimeout)(this._requestLock(), 3e3);
3249
+ (0, import_log12.log)("acquired lock", {}, {
3250
+ file: "vault-resource-lock.ts",
3251
+ line: 46,
3252
+ scope: this,
3253
+ callSite: (f, a) => f(...a)
3254
+ });
3063
3255
  } catch (e) {
3256
+ (0, import_log12.log)("stealing lock...", {}, {
3257
+ file: "vault-resource-lock.ts",
3258
+ line: 48,
3259
+ scope: this,
3260
+ callSite: (f, a) => f(...a)
3261
+ });
3064
3262
  await this._requestLock(true);
3263
+ (0, import_log12.log)("stolen lock", {}, {
3264
+ file: "vault-resource-lock.ts",
3265
+ line: 50,
3266
+ scope: this,
3267
+ callSite: (f, a) => f(...a)
3268
+ });
3065
3269
  }
3066
3270
  }
3067
3271
  async release() {
@@ -3073,11 +3277,11 @@ var VaultResourceLock = class {
3073
3277
  }
3074
3278
  }
3075
3279
  async _requestLock(steal = false) {
3076
- (0, import_log11.log)("requesting lock...", {
3280
+ (0, import_log12.log)("requesting lock...", {
3077
3281
  steal
3078
3282
  }, {
3079
3283
  file: "vault-resource-lock.ts",
3080
- line: 56,
3284
+ line: 65,
3081
3285
  scope: this,
3082
3286
  callSite: (f, a) => f(...a)
3083
3287
  });
@@ -3090,16 +3294,16 @@ var VaultResourceLock = class {
3090
3294
  acquired.wake();
3091
3295
  this._releaseTrigger = new import_async15.Trigger();
3092
3296
  await this._releaseTrigger.wait();
3093
- (0, import_log11.log)("releasing lock...", {}, {
3297
+ (0, import_log12.log)("releasing lock...", {}, {
3094
3298
  file: "vault-resource-lock.ts",
3095
- line: 65,
3299
+ line: 74,
3096
3300
  scope: this,
3097
3301
  callSite: (f, a) => f(...a)
3098
3302
  });
3099
3303
  await ((_b = this._onRelease) == null ? void 0 : _b.call(this));
3100
- (0, import_log11.log)("released lock", {}, {
3304
+ (0, import_log12.log)("released lock", {}, {
3101
3305
  file: "vault-resource-lock.ts",
3102
- line: 67,
3306
+ line: 76,
3103
3307
  scope: this,
3104
3308
  callSite: (f, a) => f(...a)
3105
3309
  });
@@ -3108,31 +3312,34 @@ var VaultResourceLock = class {
3108
3312
  await ((_a = this._onRelease) == null ? void 0 : _a.call(this));
3109
3313
  });
3110
3314
  await acquired.wait();
3111
- (0, import_log11.log)("recieved lock", {
3315
+ (0, import_log12.log)("recieved lock", {
3112
3316
  steal
3113
3317
  }, {
3114
3318
  file: "vault-resource-lock.ts",
3115
- line: 74,
3319
+ line: 83,
3116
3320
  scope: this,
3117
3321
  callSite: (f, a) => f(...a)
3118
3322
  });
3119
3323
  }
3120
3324
  };
3325
+ __decorate4([
3326
+ import_log12.logInfo
3327
+ ], VaultResourceLock.prototype, "lockKey", null);
3121
3328
 
3122
3329
  // packages/sdk/client-services/src/packlets/vault/worker-runtime.ts
3123
3330
  var import_async17 = require("@dxos/async");
3124
- var import_log13 = require("@dxos/log");
3331
+ var import_log14 = require("@dxos/log");
3125
3332
  var import_messaging2 = require("@dxos/messaging");
3126
3333
  var import_network_manager5 = require("@dxos/network-manager");
3127
3334
 
3128
3335
  // packages/sdk/client-services/src/packlets/vault/worker-session.ts
3129
3336
  var import_node_assert11 = __toESM(require("node:assert"));
3130
3337
  var import_async16 = require("@dxos/async");
3131
- var import_client5 = require("@dxos/client");
3132
- var import_log12 = require("@dxos/log");
3338
+ var import_client7 = require("@dxos/client");
3339
+ var import_log13 = require("@dxos/log");
3133
3340
  var import_rpc4 = require("@dxos/rpc");
3134
3341
  var import_util8 = require("@dxos/util");
3135
- var __decorate4 = function(decorators, target, key, desc) {
3342
+ var __decorate5 = function(decorators, target, key, desc) {
3136
3343
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3137
3344
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
3138
3345
  r = Reflect.decorate(decorators, target, key, desc);
@@ -3183,8 +3390,8 @@ var WorkerSession = class {
3183
3390
  ...middleware
3184
3391
  });
3185
3392
  this._iframeRpc = (0, import_rpc4.createProtoRpcPeer)({
3186
- requested: import_client5.iframeServiceBundle,
3187
- exposed: import_client5.workerServiceBundle,
3393
+ requested: import_client7.iframeServiceBundle,
3394
+ exposed: import_client7.workerServiceBundle,
3188
3395
  handlers: {
3189
3396
  WorkerService: {
3190
3397
  start: async (request) => {
@@ -3196,7 +3403,7 @@ var WorkerSession = class {
3196
3403
  try {
3197
3404
  await this.close();
3198
3405
  } catch (err) {
3199
- import_log12.log.catch(err, {}, {
3406
+ import_log13.log.catch(err, {}, {
3200
3407
  file: "worker-session.ts",
3201
3408
  line: 107,
3202
3409
  scope: this,
@@ -3214,7 +3421,7 @@ var WorkerSession = class {
3214
3421
  this.bridgeService = this._iframeRpc.rpc.BridgeService;
3215
3422
  }
3216
3423
  async open() {
3217
- import_log12.log.info("opening..", {}, {
3424
+ import_log13.log.info("opening..", {}, {
3218
3425
  file: "worker-session.ts",
3219
3426
  line: 121,
3220
3427
  scope: this,
@@ -3232,7 +3439,7 @@ var WorkerSession = class {
3232
3439
  try {
3233
3440
  await this._iframeRpc.rpc.IframeService.heartbeat();
3234
3441
  } catch (err1) {
3235
- import_log12.log.warn("Heartbeat failed", {
3442
+ import_log13.log.warn("Heartbeat failed", {
3236
3443
  err: err1
3237
3444
  }, {
3238
3445
  file: "worker-session.ts",
@@ -3243,7 +3450,7 @@ var WorkerSession = class {
3243
3450
  try {
3244
3451
  await this.close();
3245
3452
  } catch (err) {
3246
- import_log12.log.catch(err, {}, {
3453
+ import_log13.log.catch(err, {}, {
3247
3454
  file: "worker-session.ts",
3248
3455
  line: 137,
3249
3456
  scope: this,
@@ -3254,7 +3461,7 @@ var WorkerSession = class {
3254
3461
  }, this._options.heartbeatInterval);
3255
3462
  }
3256
3463
  async close() {
3257
- import_log12.log.info("closing..", {}, {
3464
+ import_log13.log.info("closing..", {}, {
3258
3465
  file: "worker-session.ts",
3259
3466
  line: 144,
3260
3467
  scope: this,
@@ -3263,7 +3470,7 @@ var WorkerSession = class {
3263
3470
  try {
3264
3471
  await this.onClose.callIfSet();
3265
3472
  } catch (err) {
3266
- import_log12.log.catch(err, {}, {
3473
+ import_log13.log.catch(err, {}, {
3267
3474
  file: "worker-session.ts",
3268
3475
  line: 148,
3269
3476
  scope: this,
@@ -3282,7 +3489,7 @@ var WorkerSession = class {
3282
3489
  try {
3283
3490
  await (0, import_async16.asyncTimeout)(this._shellClientRpc.open(), 1e3);
3284
3491
  } catch (e) {
3285
- import_log12.log.info("No shell connected.", {}, {
3492
+ import_log13.log.info("No shell connected.", {}, {
3286
3493
  file: "worker-session.ts",
3287
3494
  line: 162,
3288
3495
  scope: this,
@@ -3291,8 +3498,8 @@ var WorkerSession = class {
3291
3498
  }
3292
3499
  }
3293
3500
  };
3294
- __decorate4([
3295
- import_log12.logInfo
3501
+ __decorate5([
3502
+ import_log13.logInfo
3296
3503
  ], WorkerSession.prototype, "origin", void 0);
3297
3504
 
3298
3505
  // packages/sdk/client-services/src/packlets/services/service-context.ts
@@ -3302,7 +3509,7 @@ var import_debug6 = require("@dxos/debug");
3302
3509
  var import_echo_pipeline4 = require("@dxos/echo-pipeline");
3303
3510
  var import_feed_store4 = require("@dxos/feed-store");
3304
3511
  var import_keyring = require("@dxos/keyring");
3305
- var import_log14 = require("@dxos/log");
3512
+ var import_log15 = require("@dxos/log");
3306
3513
  var ServiceContext = class {
3307
3514
  // prettier-ignore
3308
3515
  constructor(storage, networkManager, modelFactory) {
@@ -3339,7 +3546,7 @@ var ServiceContext = class {
3339
3546
  });
3340
3547
  }
3341
3548
  async open() {
3342
- (0, import_log14.log)("opening...", {}, {
3549
+ (0, import_log15.log)("opening...", {}, {
3343
3550
  file: "service-context.ts",
3344
3551
  line: 94,
3345
3552
  scope: this,
@@ -3351,7 +3558,7 @@ var ServiceContext = class {
3351
3558
  if (this.identityManager.identity) {
3352
3559
  await this._initialize();
3353
3560
  }
3354
- (0, import_log14.log)("opened", {}, {
3561
+ (0, import_log15.log)("opened", {}, {
3355
3562
  file: "service-context.ts",
3356
3563
  line: 101,
3357
3564
  scope: this,
@@ -3360,7 +3567,7 @@ var ServiceContext = class {
3360
3567
  }
3361
3568
  async close() {
3362
3569
  var _a, _b;
3363
- (0, import_log14.log)("closing...", {}, {
3570
+ (0, import_log15.log)("closing...", {}, {
3364
3571
  file: "service-context.ts",
3365
3572
  line: 105,
3366
3573
  scope: this,
@@ -3373,7 +3580,7 @@ var ServiceContext = class {
3373
3580
  await this.feedStore.close();
3374
3581
  await this.networkManager.close();
3375
3582
  this.dataServiceSubscriptions.clear();
3376
- (0, import_log14.log)("closed", {}, {
3583
+ (0, import_log15.log)("closed", {}, {
3377
3584
  file: "service-context.ts",
3378
3585
  line: 113,
3379
3586
  scope: this,
@@ -3381,7 +3588,7 @@ var ServiceContext = class {
3381
3588
  });
3382
3589
  }
3383
3590
  async reset() {
3384
- (0, import_log14.log)("resetting...", {}, {
3591
+ (0, import_log15.log)("resetting...", {}, {
3385
3592
  file: "service-context.ts",
3386
3593
  line: 117,
3387
3594
  scope: this,
@@ -3389,7 +3596,7 @@ var ServiceContext = class {
3389
3596
  });
3390
3597
  await this.close();
3391
3598
  await this.storage.reset();
3392
- (0, import_log14.log)("reset", {}, {
3599
+ (0, import_log15.log)("reset", {}, {
3393
3600
  file: "service-context.ts",
3394
3601
  line: 120,
3395
3602
  scope: this,
@@ -3409,7 +3616,7 @@ var ServiceContext = class {
3409
3616
  // Called when identity is created.
3410
3617
  async _initialize() {
3411
3618
  var _a;
3412
- (0, import_log14.log)("initializing spaces...", {}, {
3619
+ (0, import_log15.log)("initializing spaces...", {}, {
3413
3620
  file: "service-context.ts",
3414
3621
  line: 139,
3415
3622
  scope: this,
@@ -3443,7 +3650,7 @@ var ServiceContext = class {
3443
3650
  return;
3444
3651
  }
3445
3652
  if (!this.dataSpaceManager) {
3446
- (0, import_log14.log)("dataSpaceManager not initialized yet, ignoring space admission", {
3653
+ (0, import_log15.log)("dataSpaceManager not initialized yet, ignoring space admission", {
3447
3654
  details: assertion
3448
3655
  }, {
3449
3656
  file: "service-context.ts",
@@ -3454,7 +3661,7 @@ var ServiceContext = class {
3454
3661
  return;
3455
3662
  }
3456
3663
  if (this.dataSpaceManager.spaces.has(assertion.spaceKey)) {
3457
- (0, import_log14.log)("space already exists, ignoring space admission", {
3664
+ (0, import_log15.log)("space already exists, ignoring space admission", {
3458
3665
  details: assertion
3459
3666
  }, {
3460
3667
  file: "service-context.ts",
@@ -3465,7 +3672,7 @@ var ServiceContext = class {
3465
3672
  return;
3466
3673
  }
3467
3674
  try {
3468
- (0, import_log14.log)("accepting space recorded in halo", {
3675
+ (0, import_log15.log)("accepting space recorded in halo", {
3469
3676
  details: assertion
3470
3677
  }, {
3471
3678
  file: "service-context.ts",
@@ -3478,7 +3685,7 @@ var ServiceContext = class {
3478
3685
  genesisFeedKey: assertion.genesisFeedKey
3479
3686
  });
3480
3687
  } catch (err) {
3481
- import_log14.log.catch(err, {}, {
3688
+ import_log15.log.catch(err, {}, {
3482
3689
  file: "service-context.ts",
3483
3690
  line: 197,
3484
3691
  scope: this,
@@ -3519,7 +3726,7 @@ var ServiceRegistry = class {
3519
3726
  var ClientServicesHost = class {
3520
3727
  constructor({
3521
3728
  config,
3522
- modelFactory = (0, import_client6.createDefaultModelFactory)(),
3729
+ modelFactory = (0, import_client8.createDefaultModelFactory)(),
3523
3730
  // TODO(burdon): Create ApolloLink abstraction (see Client).
3524
3731
  networkManager,
3525
3732
  storage,
@@ -3527,6 +3734,7 @@ var ClientServicesHost = class {
3527
3734
  lockKey
3528
3735
  } = {}) {
3529
3736
  this._statusUpdate = new import_async19.Event();
3737
+ this._opening = false;
3530
3738
  this._open = false;
3531
3739
  this._storage = storage;
3532
3740
  this._modelFactory = modelFactory;
@@ -3538,7 +3746,9 @@ var ClientServicesHost = class {
3538
3746
  }
3539
3747
  this._resourceLock = lockKey ? new VaultResourceLock({
3540
3748
  lockKey,
3541
- onAcquire: () => this.open(),
3749
+ onAcquire: () => {
3750
+ this._opening || this.open();
3751
+ },
3542
3752
  onRelease: () => this.close()
3543
3753
  }) : void 0;
3544
3754
  this._systemService = new SystemServiceImpl({
@@ -3558,7 +3768,7 @@ var ClientServicesHost = class {
3558
3768
  await this._serviceContext.reset();
3559
3769
  }
3560
3770
  });
3561
- this._serviceRegistry = new ServiceRegistry(import_client6.clientServiceBundle, {
3771
+ this._serviceRegistry = new ServiceRegistry(import_client8.clientServiceBundle, {
3562
3772
  SystemService: this._systemService
3563
3773
  });
3564
3774
  }
@@ -3594,20 +3804,23 @@ var ClientServicesHost = class {
3594
3804
  }
3595
3805
  }
3596
3806
  async open() {
3597
- var _a, _b;
3807
+ var _a, _b, _c;
3598
3808
  if (this._open) {
3599
3809
  return;
3600
3810
  }
3601
3811
  (0, import_node_assert12.default)(this._config, "config not set");
3602
3812
  (0, import_node_assert12.default)(this._storage, "storage not set");
3603
3813
  (0, import_node_assert12.default)(this._networkManager, "network manager not set");
3604
- (0, import_log15.log)("opening...", {}, {
3814
+ this._opening = true;
3815
+ (0, import_log16.log)("opening...", {
3816
+ lockKey: (_a = this._resourceLock) == null ? void 0 : _a.lockKey
3817
+ }, {
3605
3818
  file: "service-host.ts",
3606
- line: 166,
3819
+ line: 170,
3607
3820
  scope: this,
3608
3821
  callSite: (f, a) => f(...a)
3609
3822
  });
3610
- await ((_a = this._resourceLock) == null ? void 0 : _a.acquire());
3823
+ await ((_b = this._resourceLock) == null ? void 0 : _b.acquire());
3611
3824
  this._serviceContext = new ServiceContext(this._storage, this._networkManager, this._modelFactory);
3612
3825
  this._serviceRegistry.setServices({
3613
3826
  SystemService: this._systemService,
@@ -3636,14 +3849,15 @@ var ClientServicesHost = class {
3636
3849
  })
3637
3850
  });
3638
3851
  await this._serviceContext.open();
3852
+ this._opening = false;
3639
3853
  this._open = true;
3640
3854
  this._statusUpdate.emit();
3641
- const deviceKey = (_b = this._serviceContext.identityManager.identity) == null ? void 0 : _b.deviceKey;
3642
- (0, import_log15.log)("opened", {
3855
+ const deviceKey = (_c = this._serviceContext.identityManager.identity) == null ? void 0 : _c.deviceKey;
3856
+ (0, import_log16.log)("opened", {
3643
3857
  deviceKey
3644
3858
  }, {
3645
3859
  file: "service-host.ts",
3646
- line: 219,
3860
+ line: 224,
3647
3861
  scope: this,
3648
3862
  callSite: (f, a) => f(...a)
3649
3863
  });
@@ -3654,11 +3868,11 @@ var ClientServicesHost = class {
3654
3868
  return;
3655
3869
  }
3656
3870
  const deviceKey = (_a = this._serviceContext.identityManager.identity) == null ? void 0 : _a.deviceKey;
3657
- (0, import_log15.log)("closing...", {
3871
+ (0, import_log16.log)("closing...", {
3658
3872
  deviceKey
3659
3873
  }, {
3660
3874
  file: "service-host.ts",
3661
- line: 228,
3875
+ line: 233,
3662
3876
  scope: this,
3663
3877
  callSite: (f, a) => f(...a)
3664
3878
  });
@@ -3668,11 +3882,11 @@ var ClientServicesHost = class {
3668
3882
  await this._serviceContext.close();
3669
3883
  this._open = false;
3670
3884
  this._statusUpdate.emit();
3671
- (0, import_log15.log)("closed", {
3885
+ (0, import_log16.log)("closed", {
3672
3886
  deviceKey
3673
3887
  }, {
3674
3888
  file: "service-host.ts",
3675
- line: 233,
3889
+ line: 238,
3676
3890
  scope: this,
3677
3891
  callSite: (f, a) => f(...a)
3678
3892
  });
@@ -3703,7 +3917,7 @@ var LocalClientServices = class {
3703
3917
 
3704
3918
  // packages/sdk/client-services/src/packlets/services/utils.ts
3705
3919
  var import_config2 = require("@dxos/config");
3706
- var import_log16 = require("@dxos/log");
3920
+ var import_log17 = require("@dxos/log");
3707
3921
  var import_messaging3 = require("@dxos/messaging");
3708
3922
  var import_network_manager6 = require("@dxos/network-manager");
3709
3923
 
@@ -3725,7 +3939,7 @@ var createServiceContext = ({ signalContext = new import_messaging4.MemorySignal
3725
3939
  signalManager: new import_messaging4.MemorySignalManager(signalContext),
3726
3940
  transportFactory: import_network_manager7.MemoryTransportFactory
3727
3941
  });
3728
- const modelFactory = (0, import_client7.createDefaultModelFactory)();
3942
+ const modelFactory = (0, import_client9.createDefaultModelFactory)();
3729
3943
  return new ServiceContext(storage, networkManager, modelFactory);
3730
3944
  };
3731
3945
  var createPeers = async (numPeers) => {
@@ -3865,13 +4079,13 @@ var performInvitation = async (host, guest, context) => {
3865
4079
  // packages/sdk/client-services/src/packlets/testing/test-builder.ts
3866
4080
  var import_node_assert14 = __toESM(require("node:assert"));
3867
4081
  var import_async21 = require("@dxos/async");
3868
- var import_client8 = require("@dxos/client");
4082
+ var import_client10 = require("@dxos/client");
3869
4083
  var import_config3 = require("@dxos/config");
3870
4084
  var import_debug9 = require("@dxos/debug");
3871
4085
  var import_document_model = require("@dxos/document-model");
3872
4086
  var import_echo_db = require("@dxos/echo-db");
3873
4087
  var import_keys10 = require("@dxos/keys");
3874
- var import_log17 = require("@dxos/log");
4088
+ var import_log18 = require("@dxos/log");
3875
4089
  var import_messaging5 = require("@dxos/messaging");
3876
4090
  var import_network_manager8 = require("@dxos/network-manager");
3877
4091
  var import_rpc5 = require("@dxos/rpc");
@@ -3888,7 +4102,7 @@ var testConfigWithLocalSignal = new import_config3.Config({
3888
4102
  });
3889
4103
  var TestBuilder = class {
3890
4104
  // prettier-ignore
3891
- constructor(config, _modelFactory = (0, import_client8.createDefaultModelFactory)(), _signalManagerContext = new import_messaging5.MemorySignalManagerContext()) {
4105
+ constructor(config, _modelFactory = (0, import_client10.createDefaultModelFactory)(), _signalManagerContext = new import_messaging5.MemorySignalManagerContext()) {
3892
4106
  this._modelFactory = _modelFactory;
3893
4107
  this._signalManagerContext = _signalManagerContext;
3894
4108
  this._config = config != null ? config : new import_config3.Config();
@@ -3950,8 +4164,8 @@ var TestBuilder = class {
3950
4164
  handlers: host.services,
3951
4165
  port: hostPort
3952
4166
  });
3953
- const client = new import_client8.Client({
3954
- services: new import_client8.ClientServicesProxy(proxyPort)
4167
+ const client = new import_client10.Client({
4168
+ services: new import_client10.ClientServicesProxy(proxyPort)
3955
4169
  });
3956
4170
  return [
3957
4171
  client,
@@ -3972,15 +4186,15 @@ var syncItems = async (db1, db2) => {
3972
4186
  await testSpace(db2, db1);
3973
4187
  };
3974
4188
  var joinCommonSpace = async ([initialPeer, ...peers], spaceKey) => {
3975
- const rootSpace = spaceKey ? initialPeer.echo.getSpace(spaceKey) : await initialPeer.echo.createSpace();
4189
+ const rootSpace = spaceKey ? initialPeer.getSpace(spaceKey) : await initialPeer.createSpace();
3976
4190
  (0, import_node_assert14.default)(rootSpace, "Space not found.");
3977
4191
  await Promise.all(peers.map(async (peer) => {
3978
4192
  const hostDone = new import_async21.Trigger();
3979
4193
  const guestDone = new import_async21.Trigger();
3980
4194
  const hostObservabli = rootSpace.createInvitation({
3981
- type: import_client8.Invitation.Type.INTERACTIVE_TESTING
4195
+ type: import_client10.Invitation.Type.INTERACTIVE_TESTING
3982
4196
  });
3983
- (0, import_log17.log)("invitation created", {}, {
4197
+ (0, import_log18.log)("invitation created", {}, {
3984
4198
  file: "test-builder.ts",
3985
4199
  line: 154,
3986
4200
  scope: void 0,
@@ -3988,8 +4202,8 @@ var joinCommonSpace = async ([initialPeer, ...peers], spaceKey) => {
3988
4202
  });
3989
4203
  hostObservabli.subscribe({
3990
4204
  onConnecting: (invitation) => {
3991
- const guestObservable = peer.echo.acceptInvitation(invitation);
3992
- (0, import_log17.log)("invitation accepted", {}, {
4205
+ const guestObservable = peer.acceptInvitation(invitation);
4206
+ (0, import_log18.log)("invitation accepted", {}, {
3993
4207
  file: "test-builder.ts",
3994
4208
  line: 158,
3995
4209
  scope: void 0,
@@ -3998,7 +4212,7 @@ var joinCommonSpace = async ([initialPeer, ...peers], spaceKey) => {
3998
4212
  guestObservable.subscribe({
3999
4213
  onSuccess: (invitation2) => {
4000
4214
  guestDone.wake(invitation2);
4001
- (0, import_log17.log)("invitation guestDone", {}, {
4215
+ (0, import_log18.log)("invitation guestDone", {}, {
4002
4216
  file: "test-builder.ts",
4003
4217
  line: 163,
4004
4218
  scope: void 0,
@@ -4010,7 +4224,7 @@ var joinCommonSpace = async ([initialPeer, ...peers], spaceKey) => {
4010
4224
  },
4011
4225
  onSuccess: (invitation) => {
4012
4226
  hostDone.wake(invitation);
4013
- (0, import_log17.log)("invitation hostDone", {}, {
4227
+ (0, import_log18.log)("invitation hostDone", {}, {
4014
4228
  file: "test-builder.ts",
4015
4229
  line: 170,
4016
4230
  scope: void 0,