@dxos/client-services 0.8.4-main.fffef41 → 0.8.4-staging.60fe92afc8

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 (253) hide show
  1. package/LICENSE +102 -5
  2. package/README.md +1 -1
  3. package/dist/lib/browser/{chunk-I2RGLVJF.mjs → chunk-HPR4MJ4W.mjs} +2870 -3767
  4. package/dist/lib/browser/chunk-HPR4MJ4W.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-QCWEHHJW.mjs +24 -0
  6. package/dist/lib/browser/chunk-QCWEHHJW.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-XJRPB3GA.mjs +22 -0
  8. package/dist/lib/browser/chunk-XJRPB3GA.mjs.map +7 -0
  9. package/dist/lib/browser/index.mjs +576 -139
  10. package/dist/lib/browser/index.mjs.map +4 -4
  11. package/dist/lib/browser/meta.json +1 -1
  12. package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs +88 -0
  13. package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +7 -0
  14. package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs +11 -0
  15. package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs.map +7 -0
  16. package/dist/lib/browser/packlets/locks/browser.mjs +86 -0
  17. package/dist/lib/browser/packlets/locks/browser.mjs.map +7 -0
  18. package/dist/lib/browser/packlets/locks/node.mjs +48 -0
  19. package/dist/lib/browser/packlets/locks/node.mjs.map +7 -0
  20. package/dist/lib/browser/testing/index.mjs +58 -53
  21. package/dist/lib/browser/testing/index.mjs.map +3 -3
  22. package/dist/lib/node-esm/chunk-2DT3MZRL.mjs +22 -0
  23. package/dist/lib/node-esm/chunk-2DT3MZRL.mjs.map +7 -0
  24. package/dist/lib/node-esm/chunk-2SZHAWBN.mjs +24 -0
  25. package/dist/lib/node-esm/chunk-2SZHAWBN.mjs.map +7 -0
  26. package/dist/lib/node-esm/{chunk-QTUURCR4.mjs → chunk-JW6QHPRJ.mjs} +2810 -3576
  27. package/dist/lib/node-esm/chunk-JW6QHPRJ.mjs.map +7 -0
  28. package/dist/lib/node-esm/index.mjs +576 -139
  29. package/dist/lib/node-esm/index.mjs.map +4 -4
  30. package/dist/lib/node-esm/meta.json +1 -1
  31. package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs +88 -0
  32. package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +7 -0
  33. package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs +11 -0
  34. package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs.map +7 -0
  35. package/dist/lib/node-esm/packlets/locks/browser.mjs +86 -0
  36. package/dist/lib/node-esm/packlets/locks/browser.mjs.map +7 -0
  37. package/dist/lib/node-esm/packlets/locks/node.mjs +48 -0
  38. package/dist/lib/node-esm/packlets/locks/node.mjs.map +7 -0
  39. package/dist/lib/node-esm/testing/index.mjs +58 -53
  40. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  41. package/dist/types/src/index.d.ts +1 -0
  42. package/dist/types/src/index.d.ts.map +1 -1
  43. package/dist/types/src/packlets/agents/edge-agent-manager.d.ts +3 -2
  44. package/dist/types/src/packlets/agents/edge-agent-manager.d.ts.map +1 -1
  45. package/dist/types/src/packlets/agents/edge-agent-service.d.ts +2 -1
  46. package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -1
  47. package/dist/types/src/packlets/devices/devices-service.d.ts.map +1 -1
  48. package/dist/types/src/packlets/devtools/devtools.d.ts +7 -3
  49. package/dist/types/src/packlets/devtools/devtools.d.ts.map +1 -1
  50. package/dist/types/src/packlets/devtools/feeds.d.ts +1 -1
  51. package/dist/types/src/packlets/devtools/feeds.d.ts.map +1 -1
  52. package/dist/types/src/packlets/devtools/keys.d.ts +2 -2
  53. package/dist/types/src/packlets/devtools/keys.d.ts.map +1 -1
  54. package/dist/types/src/packlets/devtools/metadata.d.ts.map +1 -1
  55. package/dist/types/src/packlets/devtools/network.d.ts.map +1 -1
  56. package/dist/types/src/packlets/devtools/spaces.d.ts.map +1 -1
  57. package/dist/types/src/packlets/diagnostics/browser-diagnostics-broadcast.d.ts.map +1 -1
  58. package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
  59. package/dist/types/src/packlets/diagnostics/diagnostics-collector.d.ts.map +1 -1
  60. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts +2 -3
  61. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts.map +1 -1
  62. package/dist/types/src/packlets/diagnostics/index.d.ts +1 -1
  63. package/dist/types/src/packlets/diagnostics/index.d.ts.map +1 -1
  64. package/dist/types/src/packlets/identity/authenticator.d.ts +3 -3
  65. package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
  66. package/dist/types/src/packlets/identity/contacts-service.d.ts +1 -1
  67. package/dist/types/src/packlets/identity/contacts-service.d.ts.map +1 -1
  68. package/dist/types/src/packlets/identity/identity-manager.d.ts +10 -10
  69. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  70. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +14 -9
  71. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
  72. package/dist/types/src/packlets/identity/identity-service.d.ts +7 -11
  73. package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
  74. package/dist/types/src/packlets/identity/identity.d.ts +10 -13
  75. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  76. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +7 -6
  77. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
  78. package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts +1 -1
  79. package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts.map +1 -1
  80. package/dist/types/src/packlets/invitations/invitation-guest-extenstion.d.ts.map +1 -1
  81. package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -1
  82. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts +7 -4
  83. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts.map +1 -1
  84. package/dist/types/src/packlets/invitations/invitation-state.d.ts.map +1 -1
  85. package/dist/types/src/packlets/invitations/invitation-topology.d.ts.map +1 -1
  86. package/dist/types/src/packlets/invitations/invitations-handler.d.ts +4 -4
  87. package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
  88. package/dist/types/src/packlets/invitations/invitations-manager.d.ts +5 -5
  89. package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -1
  90. package/dist/types/src/packlets/invitations/invitations-service.d.ts +3 -3
  91. package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -1
  92. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +6 -5
  93. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
  94. package/dist/types/src/packlets/invitations/utils.d.ts.map +1 -1
  95. package/dist/types/src/packlets/locks/browser.d.ts.map +1 -1
  96. package/dist/types/src/packlets/locks/index.d.ts +1 -1
  97. package/dist/types/src/packlets/locks/index.d.ts.map +1 -1
  98. package/dist/types/src/packlets/locks/node.d.ts.map +1 -1
  99. package/dist/types/src/packlets/logging/logging-service.d.ts +4 -0
  100. package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
  101. package/dist/types/src/packlets/network/network-service.d.ts +5 -4
  102. package/dist/types/src/packlets/network/network-service.d.ts.map +1 -1
  103. package/dist/types/src/packlets/services/client-rpc-server.d.ts +5 -5
  104. package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
  105. package/dist/types/src/packlets/services/feed-syncer.d.ts +75 -0
  106. package/dist/types/src/packlets/services/feed-syncer.d.ts.map +1 -0
  107. package/dist/types/src/packlets/services/feed-syncer.test.d.ts +2 -0
  108. package/dist/types/src/packlets/services/feed-syncer.test.d.ts.map +1 -0
  109. package/dist/types/src/packlets/services/index.d.ts +1 -0
  110. package/dist/types/src/packlets/services/index.d.ts.map +1 -1
  111. package/dist/types/src/packlets/services/platform.d.ts.map +1 -1
  112. package/dist/types/src/packlets/services/service-context.d.ts +22 -19
  113. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  114. package/dist/types/src/packlets/services/service-host.d.ts +20 -13
  115. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  116. package/dist/types/src/packlets/services/service-registry.d.ts.map +1 -1
  117. package/dist/types/src/packlets/services/sqlite-storage.d.ts +27 -0
  118. package/dist/types/src/packlets/services/sqlite-storage.d.ts.map +1 -0
  119. package/dist/types/src/packlets/services/util.d.ts.map +1 -1
  120. package/dist/types/src/packlets/space-export/archive-format.d.ts +9 -0
  121. package/dist/types/src/packlets/space-export/archive-format.d.ts.map +1 -0
  122. package/dist/types/src/packlets/space-export/index.d.ts +4 -1
  123. package/dist/types/src/packlets/space-export/index.d.ts.map +1 -1
  124. package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts +23 -0
  125. package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts.map +1 -0
  126. package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts +36 -0
  127. package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts.map +1 -0
  128. package/dist/types/src/packlets/space-export/space-archive-reader.d.ts +9 -1
  129. package/dist/types/src/packlets/space-export/space-archive-reader.d.ts.map +1 -1
  130. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts +7 -1
  131. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts.map +1 -1
  132. package/dist/types/src/packlets/space-export/space-archive.test.d.ts +2 -0
  133. package/dist/types/src/packlets/space-export/space-archive.test.d.ts.map +1 -0
  134. package/dist/types/src/packlets/spaces/automerge-space-state.d.ts.map +1 -1
  135. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +49 -22
  136. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  137. package/dist/types/src/packlets/spaces/data-space.d.ts +38 -13
  138. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  139. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts +2 -2
  140. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
  141. package/dist/types/src/packlets/spaces/epoch-migrations.d.ts +1 -1
  142. package/dist/types/src/packlets/spaces/epoch-migrations.d.ts.map +1 -1
  143. package/dist/types/src/packlets/spaces/genesis.d.ts +4 -3
  144. package/dist/types/src/packlets/spaces/genesis.d.ts.map +1 -1
  145. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +6 -9
  146. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
  147. package/dist/types/src/packlets/spaces/spaces-service.d.ts +10 -7
  148. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  149. package/dist/types/src/packlets/storage/index.d.ts +1 -0
  150. package/dist/types/src/packlets/storage/index.d.ts.map +1 -1
  151. package/dist/types/src/packlets/storage/level.d.ts.map +1 -1
  152. package/dist/types/src/packlets/storage/profile-archive-sqlite.d.ts +24 -0
  153. package/dist/types/src/packlets/storage/profile-archive-sqlite.d.ts.map +1 -0
  154. package/dist/types/src/packlets/storage/profile-archive-sqlite.test.d.ts +2 -0
  155. package/dist/types/src/packlets/storage/profile-archive-sqlite.test.d.ts.map +1 -0
  156. package/dist/types/src/packlets/storage/profile-archive.d.ts.map +1 -1
  157. package/dist/types/src/packlets/storage/storage.d.ts.map +1 -1
  158. package/dist/types/src/packlets/storage/util.d.ts.map +1 -1
  159. package/dist/types/src/packlets/system/system-service.d.ts +1 -1
  160. package/dist/types/src/packlets/system/system-service.d.ts.map +1 -1
  161. package/dist/types/src/packlets/testing/credential-utils.d.ts.map +1 -1
  162. package/dist/types/src/packlets/testing/invitation-utils.d.ts +6 -3
  163. package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
  164. package/dist/types/src/packlets/testing/test-builder.d.ts +20 -22
  165. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  166. package/dist/types/src/packlets/worker/worker-runtime.d.ts +41 -4
  167. package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
  168. package/dist/types/src/packlets/worker/worker-session.d.ts +2 -4
  169. package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
  170. package/dist/types/src/testing/setup.d.ts.map +1 -1
  171. package/dist/types/src/version.d.ts +1 -1
  172. package/dist/types/src/version.d.ts.map +1 -1
  173. package/dist/types/tsconfig.tsbuildinfo +1 -1
  174. package/package.json +71 -57
  175. package/src/index.ts +1 -0
  176. package/src/packlets/agents/edge-agent-manager.ts +8 -5
  177. package/src/packlets/agents/edge-agent-service.ts +4 -2
  178. package/src/packlets/devices/devices-service.test.ts +0 -1
  179. package/src/packlets/devtools/devtools.ts +28 -7
  180. package/src/packlets/devtools/feeds.ts +1 -1
  181. package/src/packlets/devtools/keys.ts +2 -2
  182. package/src/packlets/devtools/spaces.ts +1 -1
  183. package/src/packlets/diagnostics/diagnostics.ts +1 -2
  184. package/src/packlets/diagnostics/index.ts +1 -1
  185. package/src/packlets/identity/authenticator.ts +3 -3
  186. package/src/packlets/identity/contacts-service.ts +1 -2
  187. package/src/packlets/identity/identity-manager.test.ts +6 -6
  188. package/src/packlets/identity/identity-manager.ts +29 -28
  189. package/src/packlets/identity/identity-recovery-manager.ts +31 -22
  190. package/src/packlets/identity/identity-service.test.ts +6 -27
  191. package/src/packlets/identity/identity-service.ts +17 -83
  192. package/src/packlets/identity/identity.test.ts +3 -3
  193. package/src/packlets/identity/identity.ts +12 -35
  194. package/src/packlets/invitations/device-invitation-protocol.ts +10 -9
  195. package/src/packlets/invitations/edge-invitation-handler.ts +9 -5
  196. package/src/packlets/invitations/invitation-guest-extenstion.ts +6 -4
  197. package/src/packlets/invitations/invitation-host-extension.ts +13 -14
  198. package/src/packlets/invitations/invitation-protocol.ts +7 -4
  199. package/src/packlets/invitations/invitation-state.ts +1 -15
  200. package/src/packlets/invitations/invitations-handler.test.ts +4 -5
  201. package/src/packlets/invitations/invitations-handler.ts +74 -22
  202. package/src/packlets/invitations/invitations-manager.ts +42 -17
  203. package/src/packlets/invitations/invitations-service.ts +9 -9
  204. package/src/packlets/invitations/space-invitation-protocol.test.ts +17 -16
  205. package/src/packlets/invitations/space-invitation-protocol.ts +13 -18
  206. package/src/packlets/locks/index.ts +1 -1
  207. package/src/packlets/logging/logging-service.ts +19 -15
  208. package/src/packlets/network/network-service.test.ts +0 -1
  209. package/src/packlets/network/network-service.ts +10 -8
  210. package/src/packlets/services/client-rpc-server.ts +19 -16
  211. package/src/packlets/services/feed-syncer.test.ts +376 -0
  212. package/src/packlets/services/feed-syncer.ts +536 -0
  213. package/src/packlets/services/index.ts +1 -0
  214. package/src/packlets/services/platform.ts +7 -1
  215. package/src/packlets/services/service-context.test.ts +3 -2
  216. package/src/packlets/services/service-context.ts +215 -78
  217. package/src/packlets/services/service-host.test.ts +8 -10
  218. package/src/packlets/services/service-host.ts +102 -70
  219. package/src/packlets/services/service-registry.test.ts +0 -1
  220. package/src/packlets/services/sqlite-storage.ts +390 -0
  221. package/src/packlets/space-export/archive-format.ts +42 -0
  222. package/src/packlets/space-export/index.ts +4 -1
  223. package/src/packlets/space-export/serialized-space-reader.ts +129 -0
  224. package/src/packlets/space-export/serialized-space-writer.ts +260 -0
  225. package/src/packlets/space-export/space-archive-reader.ts +64 -3
  226. package/src/packlets/space-export/space-archive-writer.ts +41 -4
  227. package/src/packlets/space-export/space-archive.test.ts +482 -0
  228. package/src/packlets/spaces/data-space-manager.test.ts +169 -14
  229. package/src/packlets/spaces/data-space-manager.ts +192 -127
  230. package/src/packlets/spaces/data-space.ts +89 -43
  231. package/src/packlets/spaces/edge-feed-replicator.test.ts +2 -2
  232. package/src/packlets/spaces/edge-feed-replicator.ts +11 -9
  233. package/src/packlets/spaces/epoch-migrations.ts +7 -6
  234. package/src/packlets/spaces/genesis.ts +9 -4
  235. package/src/packlets/spaces/notarization-plugin.test.ts +2 -2
  236. package/src/packlets/spaces/notarization-plugin.ts +10 -9
  237. package/src/packlets/spaces/spaces-service.test.ts +18 -11
  238. package/src/packlets/spaces/spaces-service.ts +130 -24
  239. package/src/packlets/storage/index.ts +1 -0
  240. package/src/packlets/storage/profile-archive-sqlite.test.ts +79 -0
  241. package/src/packlets/storage/profile-archive-sqlite.ts +100 -0
  242. package/src/packlets/storage/profile-archive.ts +3 -0
  243. package/src/packlets/storage/storage.ts +4 -4
  244. package/src/packlets/testing/invitation-utils.ts +10 -6
  245. package/src/packlets/testing/test-builder.ts +59 -40
  246. package/src/packlets/worker/worker-runtime.ts +173 -17
  247. package/src/packlets/worker/worker-session.ts +12 -18
  248. package/src/version.ts +1 -1
  249. package/dist/lib/browser/chunk-I2RGLVJF.mjs.map +0 -7
  250. package/dist/lib/node-esm/chunk-QTUURCR4.mjs.map +0 -7
  251. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts +0 -19
  252. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts.map +0 -1
  253. package/src/packlets/identity/default-space-state-machine.ts +0 -44
@@ -3,10 +3,10 @@
3
3
  //
4
4
 
5
5
  import { type Doc } from '@automerge/automerge';
6
- import { type AutomergeUrl, type DocHandle, type DocumentId, interpretAsDocumentId } from '@automerge/automerge-repo';
6
+ import { type AutomergeUrl, type DocumentId, interpretAsDocumentId } from '@automerge/automerge-repo';
7
7
 
8
8
  import { Event, synchronized, trackLeaks } from '@dxos/async';
9
- import { PropertiesType, TYPE_PROPERTIES } from '@dxos/client-protocol';
9
+ import { SpaceProperties } from '@dxos/client-protocol';
10
10
  import { Context, LifecycleState, Resource, cancelWithContext } from '@dxos/context';
11
11
  import {
12
12
  type CredentialSigner,
@@ -15,61 +15,55 @@ import {
15
15
  createAdmissionCredentials,
16
16
  getCredentialAssertion,
17
17
  } from '@dxos/credentials';
18
- import { ObjectId, getTypeReference } from '@dxos/echo/internal';
18
+ import { Type } from '@dxos/echo';
19
19
  import {
20
20
  AuthStatus,
21
21
  CredentialServerExtension,
22
22
  DatabaseRoot,
23
- type EchoEdgeReplicator,
24
23
  type EchoHost,
25
- FIND_PARAMS,
24
+ type EdgeAutomergeReplicator,
26
25
  type MeshEchoReplicator,
27
- type MetadataStore,
26
+ type IMetadataStore,
28
27
  type Space,
29
28
  type SpaceManager,
30
29
  type SpaceProtocol,
31
30
  type SpaceProtocolSession,
32
31
  findInlineObjectOfType,
33
- } from '@dxos/echo-pipeline';
34
- import {
35
- type DatabaseDirectory,
36
- type ObjectStructure,
37
- SpaceDocVersion,
38
- createIdFromSpaceKey,
39
- encodeReference,
40
- } from '@dxos/echo-protocol';
32
+ } from '@dxos/echo-host';
33
+ import { type DatabaseDirectory, createIdFromSpaceKey } from '@dxos/echo-protocol';
41
34
  import type { EdgeConnection, EdgeHttpClient } from '@dxos/edge-client';
42
35
  import { type FeedStore, writeMessages } from '@dxos/feed-store';
43
36
  import { assertArgument, assertState, failedInvariant, invariant } from '@dxos/invariant';
44
- import { type Keyring } from '@dxos/keyring';
37
+ import { type KeyringApi } from '@dxos/keyring';
45
38
  import { PublicKey, type SpaceId } from '@dxos/keys';
46
39
  import { log } from '@dxos/log';
47
- import { AlreadyJoinedError, trace as Trace } from '@dxos/protocols';
40
+ import { AlreadyJoinedError } from '@dxos/protocols';
48
41
  import { Invitation, SpaceState } from '@dxos/protocols/proto/dxos/client/services';
49
42
  import { type Runtime } from '@dxos/protocols/proto/dxos/config';
50
43
  import { type FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
51
44
  import { EdgeReplicationSetting, type SpaceMetadata } from '@dxos/protocols/proto/dxos/echo/metadata';
52
- import { type Credential, type ProfileDocument, SpaceMember } from '@dxos/protocols/proto/dxos/halo/credentials';
45
+ import {
46
+ type Credential,
47
+ MembershipPolicy,
48
+ type ProfileDocument,
49
+ SpaceMember,
50
+ } from '@dxos/protocols/proto/dxos/halo/credentials';
53
51
  import { type DelegateSpaceInvitation } from '@dxos/protocols/proto/dxos/halo/invitations';
54
52
  import { type PeerState } from '@dxos/protocols/proto/dxos/mesh/presence';
55
53
  import { type Teleport } from '@dxos/teleport';
56
54
  import { Gossip, Presence } from '@dxos/teleport-extension-gossip';
57
55
  import { type Timeframe } from '@dxos/timeframe';
58
56
  import { trace } from '@dxos/tracing';
59
- import { ComplexMap, deferFunction, forEachAsync, setDeep } from '@dxos/util';
57
+ import { ComplexMap, deferFunction, forEachAsync } from '@dxos/util';
60
58
 
61
59
  import { createAuthProvider } from '../identity';
62
60
  import { type InvitationsManager } from '../invitations';
63
-
64
61
  import { DataSpace } from './data-space';
65
62
  import { spaceGenesis } from './genesis';
66
63
 
67
64
  const PRESENCE_ANNOUNCE_INTERVAL = 10_000;
68
65
  const PRESENCE_OFFLINE_TIMEOUT = 20_000;
69
66
 
70
- // Space properties key for default metadata.
71
- const DEFAULT_SPACE_KEY = '__DEFAULT__';
72
-
73
67
  export interface SigningContext {
74
68
  identityKey: PublicKey;
75
69
  deviceKey: PublicKey;
@@ -94,6 +88,9 @@ export type AcceptSpaceOptions = {
94
88
  * We will try to catch up to this timeframe before initializing the database.
95
89
  */
96
90
  dataTimeframe?: Timeframe;
91
+
92
+ /** Tags assigned to the space member. */
93
+ tags?: string[];
97
94
  };
98
95
 
99
96
  export type AdmitMemberOptions = {
@@ -102,12 +99,13 @@ export type AdmitMemberOptions = {
102
99
  role: SpaceMember.Role;
103
100
  profile?: ProfileDocument;
104
101
  delegationCredentialId?: PublicKey;
102
+ tags?: string[];
105
103
  };
106
104
 
107
- export type DataSpaceManagerParams = {
105
+ export type DataSpaceManagerProps = {
108
106
  spaceManager: SpaceManager;
109
- metadataStore: MetadataStore;
110
- keyring: Keyring;
107
+ metadataStore: IMetadataStore;
108
+ keyring: KeyringApi;
111
109
  signingContext: SigningContext;
112
110
  feedStore: FeedStore<FeedMessage>;
113
111
  echoHost: EchoHost;
@@ -115,34 +113,40 @@ export type DataSpaceManagerParams = {
115
113
  edgeConnection?: EdgeConnection;
116
114
  edgeHttpClient?: EdgeHttpClient;
117
115
  meshReplicator?: MeshEchoReplicator;
118
- echoEdgeReplicator?: EchoEdgeReplicator;
119
- runtimeParams?: DataSpaceManagerRuntimeParams;
116
+ echoEdgeReplicator?: EdgeAutomergeReplicator;
117
+ runtimeProps?: DataSpaceManagerRuntimeProps;
120
118
  edgeFeatures?: Runtime.Client.EdgeFeatures;
121
119
  };
122
120
 
123
- export type DataSpaceManagerRuntimeParams = {
121
+ export type DataSpaceManagerRuntimeProps = {
124
122
  spaceMemberPresenceAnnounceInterval?: number;
125
123
  spaceMemberPresenceOfflineTimeout?: number;
126
124
  activeEdgeNotarizationPollingInterval?: number;
127
125
  disableP2pReplication?: boolean;
126
+ /**
127
+ * If true, spaces that were previously SPACE_ACTIVE will be automatically activated on startup.
128
+ * This is used in dedicated worker mode to restore space state after leader changeover.
129
+ */
130
+ autoActivateSpaces?: boolean;
128
131
  };
129
132
 
130
133
  export type CreateSpaceOptions = {
131
134
  rootUrl?: AutomergeUrl;
132
135
  documents?: Record<DocumentId, Uint8Array>;
136
+ tags?: string[];
137
+ membershipPolicy?: MembershipPolicy;
133
138
  };
134
139
 
135
140
  @trackLeaks('open', 'close')
141
+ @trace.resource({ lifecycle: true })
136
142
  export class DataSpaceManager extends Resource {
137
143
  public readonly updated = new Event();
138
144
 
139
145
  private readonly _spaces = new ComplexMap<PublicKey, DataSpace>(PublicKey.hash);
140
146
 
141
- private readonly _instanceId = PublicKey.random().toHex();
142
-
143
147
  private readonly _spaceManager: SpaceManager;
144
- private readonly _metadataStore: MetadataStore;
145
- private readonly _keyring: Keyring;
148
+ private readonly _metadataStore: IMetadataStore;
149
+ private readonly _keyring: KeyringApi;
146
150
  private readonly _signingContext: SigningContext;
147
151
  private readonly _feedStore: FeedStore<FeedMessage>;
148
152
  private readonly _echoHost: EchoHost;
@@ -151,10 +155,10 @@ export class DataSpaceManager extends Resource {
151
155
  private readonly _edgeHttpClient?: EdgeHttpClient = undefined;
152
156
  private readonly _edgeFeatures?: Runtime.Client.EdgeFeatures = undefined;
153
157
  private readonly _meshReplicator?: MeshEchoReplicator = undefined;
154
- private readonly _echoEdgeReplicator?: EchoEdgeReplicator = undefined;
155
- private readonly _runtimeParams?: DataSpaceManagerRuntimeParams = undefined;
158
+ private readonly _echoEdgeReplicator?: EdgeAutomergeReplicator = undefined;
159
+ private readonly _runtimeProps?: DataSpaceManagerRuntimeProps = undefined;
156
160
 
157
- constructor(params: DataSpaceManagerParams) {
161
+ constructor(params: DataSpaceManagerProps) {
158
162
  super();
159
163
 
160
164
  this._spaceManager = params.spaceManager;
@@ -169,7 +173,7 @@ export class DataSpaceManager extends Resource {
169
173
  this._edgeFeatures = params.edgeFeatures;
170
174
  this._echoEdgeReplicator = params.echoEdgeReplicator;
171
175
  this._edgeHttpClient = params.edgeHttpClient;
172
- this._runtimeParams = params.runtimeParams;
176
+ this._runtimeProps = params.runtimeProps;
173
177
 
174
178
  trace.diagnostic({
175
179
  id: 'spaces',
@@ -179,12 +183,11 @@ export class DataSpaceManager extends Resource {
179
183
  Array.from(this._spaces.values()).map(async (space) => {
180
184
  const rootUrl = space.automergeSpaceState.rootUrl;
181
185
  const rootHandle = rootUrl
182
- ? await this._echoHost.automergeRepo.find<Doc<DatabaseDirectory>>(rootUrl as AutomergeUrl, FIND_PARAMS)
186
+ ? await this._echoHost.loadDoc<Doc<DatabaseDirectory>>(this._ctx, rootUrl as AutomergeUrl)
183
187
  : undefined;
184
- await rootHandle?.whenReady();
185
188
  const rootDoc = rootHandle?.doc();
186
189
 
187
- const properties = rootDoc && findInlineObjectOfType(rootDoc, TYPE_PROPERTIES);
190
+ const properties = rootDoc && findInlineObjectOfType(rootDoc, Type.getTypename(SpaceProperties));
188
191
 
189
192
  return {
190
193
  key: space.key.toHex(),
@@ -212,30 +215,46 @@ export class DataSpaceManager extends Resource {
212
215
  }
213
216
 
214
217
  @synchronized
215
- protected override async _open(): Promise<void> {
218
+ @trace.span({ showInBrowserTimeline: true, op: 'lifecycle' })
219
+ protected override async _open(ctx: Context): Promise<void> {
216
220
  log('open');
217
- log.trace('dxos.echo.data-space-manager.open', Trace.begin({ id: this._instanceId }));
218
221
  log('metadata loaded', { spaces: this._metadataStore.spaces.length });
219
222
 
223
+ const spacesToActivate: DataSpace[] = [];
220
224
  await forEachAsync(this._metadataStore.spaces, async (spaceMetadata) => {
221
225
  try {
226
+ // Tombstoned spaces are never constructed, opened, or replicated.
227
+ if (spaceMetadata.state === SpaceState.SPACE_DELETED || this.isSpaceDeleted(spaceMetadata.key)) {
228
+ log('skipping deleted space', { spaceKey: spaceMetadata.key });
229
+ return;
230
+ }
222
231
  log('load space', { spaceMetadata });
223
- await this._constructSpace(spaceMetadata);
232
+ const space = await this._constructSpace(ctx, spaceMetadata);
233
+ // Track spaces that were previously active for auto-activation (used in dedicated worker mode).
234
+ if (this._runtimeProps?.autoActivateSpaces && spaceMetadata.state === SpaceState.SPACE_ACTIVE) {
235
+ spacesToActivate.push(space);
236
+ }
224
237
  } catch (err) {
225
238
  log.error('Error loading space', { spaceMetadata, err });
226
239
  }
227
240
  });
228
241
 
229
- this.updated.emit();
242
+ // Auto-activate spaces that were previously active (used in dedicated worker mode after leader changeover).
243
+ for (const space of spacesToActivate) {
244
+ log('auto-activating space', { spaceKey: space.key });
245
+ space.activate(ctx).catch((err) => {
246
+ log.error('Error auto-activating space', { spaceKey: space.key, err });
247
+ });
248
+ }
230
249
 
231
- log.trace('dxos.echo.data-space-manager.open', Trace.end({ id: this._instanceId }));
250
+ this.updated.emit();
232
251
  }
233
252
 
234
253
  @synchronized
235
- protected override async _close(): Promise<void> {
254
+ protected override async _close(ctx: Context): Promise<void> {
236
255
  log('close');
237
256
  for (const space of this._spaces.values()) {
238
- await space.close();
257
+ await space.close(ctx);
239
258
  }
240
259
  this._spaces.clear();
241
260
  }
@@ -244,7 +263,8 @@ export class DataSpaceManager extends Resource {
244
263
  * Creates a new space writing the genesis credentials to the control feed.
245
264
  */
246
265
  @synchronized
247
- async createSpace(options: CreateSpaceOptions = {}): Promise<DataSpace> {
266
+ @trace.span({ showInBrowserTimeline: true, op: 'lifecycle' })
267
+ async createSpace(ctx: Context, options: CreateSpaceOptions = {}): Promise<DataSpace> {
248
268
  assertArgument(
249
269
  !!options.rootUrl === !!options.documents,
250
270
  'options',
@@ -252,6 +272,8 @@ export class DataSpaceManager extends Resource {
252
272
  );
253
273
 
254
274
  assertState(this._lifecycleState === LifecycleState.OPEN, 'Not open.');
275
+
276
+ const tags = options.tags ? Array.from(options.tags) : [];
255
277
  const spaceKey = await this._keyring.createKey();
256
278
  const controlFeedKey = await this._keyring.createKey();
257
279
  const dataFeedKey = await this._keyring.createKey();
@@ -264,6 +286,7 @@ export class DataSpaceManager extends Resource {
264
286
  controlFeedKey,
265
287
  dataFeedKey,
266
288
  state: SpaceState.SPACE_ACTIVE,
289
+ tags,
267
290
  };
268
291
 
269
292
  log('creating space...', { spaceId, spaceKey });
@@ -301,30 +324,38 @@ export class DataSpaceManager extends Resource {
301
324
  let root: DatabaseRoot;
302
325
  if (options.rootUrl) {
303
326
  const newRootDocId = documentIdMapping[interpretAsDocumentId(options.rootUrl)] ?? failedInvariant();
304
- const rootDocHandle = await this._echoHost.loadDoc<DatabaseDirectory>(Context.default(), newRootDocId);
327
+ const rootDocHandle = await this._echoHost.loadDoc<DatabaseDirectory>(ctx, newRootDocId);
328
+ invariant(rootDocHandle, 'Root document must be available after import.');
305
329
  DatabaseRoot.mapLinks(rootDocHandle, documentIdMapping);
306
330
 
307
- root = await this._echoHost.openSpaceRoot(spaceId, `automerge:${newRootDocId}` as AutomergeUrl);
331
+ root = await this._echoHost.openSpaceRoot(ctx, spaceId, `automerge:${newRootDocId}` as AutomergeUrl);
308
332
  } else {
309
- root = await this._echoHost.createSpaceRoot(spaceKey);
333
+ root = await this._echoHost.createSpaceRoot(ctx, spaceKey);
310
334
  }
311
- await this._echoHost.flush();
335
+ await this._echoHost.flush(ctx);
312
336
 
313
337
  log('constructing space...', { spaceKey });
314
338
 
315
- const space = await this._constructSpace(metadata);
316
- await space.open();
339
+ const space = await this._constructSpace(ctx, metadata);
340
+ await space.open(ctx);
317
341
 
318
342
  log('adding space...', { spaceKey });
319
343
 
320
- const credentials = await spaceGenesis(this._keyring, this._signingContext, space.inner, root.url);
344
+ const credentials = await spaceGenesis(
345
+ this._keyring,
346
+ this._signingContext,
347
+ space.inner,
348
+ root.url,
349
+ tags,
350
+ options.membershipPolicy,
351
+ );
321
352
  await this._metadataStore.addSpace(metadata);
322
353
 
323
354
  const memberCredential = credentials[1];
324
355
  invariant(getCredentialAssertion(memberCredential)['@type'] === 'dxos.halo.credentials.SpaceMember');
325
356
  await this._signingContext.recordCredential(memberCredential);
326
357
 
327
- await space.initializeDataPipeline();
358
+ await space.initializeDataPipeline(ctx);
328
359
 
329
360
  log('space ready.', { spaceId, spaceKey });
330
361
 
@@ -332,86 +363,113 @@ export class DataSpaceManager extends Resource {
332
363
  return space;
333
364
  }
334
365
 
335
- async isDefaultSpace(space: DataSpace): Promise<boolean> {
336
- if (!space.databaseRoot) {
337
- return false;
338
- }
339
- switch (space.databaseRoot.getVersion()) {
340
- case SpaceDocVersion.CURRENT: {
341
- if (!space.databaseRoot.handle.isReady()) {
342
- log.warn('waiting for space root to be ready', { spaceId: space.id });
343
- await space.databaseRoot.handle.whenReady();
344
- }
345
- const [_, properties] = findInlineObjectOfType(space.databaseRoot.doc()!, TYPE_PROPERTIES) ?? [];
346
- return properties?.data?.[DEFAULT_SPACE_KEY] === this._signingContext.identityKey.toHex();
347
- }
348
- case SpaceDocVersion.LEGACY: {
349
- throw new Error('Legacy space version is not supported');
350
- }
351
-
352
- default:
353
- log.warn('unknown space version', { version: space.databaseRoot.getVersion(), spaceId: space.id });
354
- return false;
355
- }
356
- }
357
-
358
- async createDefaultSpace(): Promise<DataSpace> {
359
- const space = await this.createSpace();
360
- const document = await this._getSpaceRootDocument(space);
361
-
362
- // TODO(dmaretskyi): Better API for low-level data access.
363
- const properties: ObjectStructure = {
364
- system: {
365
- type: encodeReference(getTypeReference(PropertiesType)!),
366
- },
367
- data: {
368
- [DEFAULT_SPACE_KEY]: this._signingContext.identityKey.toHex(),
369
- },
370
- meta: {
371
- keys: [],
372
- },
373
- };
374
-
375
- const propertiesId = ObjectId.random();
376
- document.change((doc: DatabaseDirectory) => {
377
- setDeep(doc, ['objects', propertiesId], properties);
378
- });
379
-
380
- await this._echoHost.flush();
381
- return space;
382
- }
383
-
384
- private async _getSpaceRootDocument(space: DataSpace): Promise<DocHandle<DatabaseDirectory>> {
385
- const automergeIndex = space.automergeSpaceState.rootUrl;
386
- invariant(automergeIndex);
387
- const document = await this._echoHost.automergeRepo.find<DatabaseDirectory>(automergeIndex as any, FIND_PARAMS);
388
- await document.whenReady();
389
- return document;
390
- }
391
-
366
+ /**
367
+ * Accepts an existing space by joining its swarm and initializing the data pipeline.
368
+ * @param ctx - Caller context for cancellation and tracing.
369
+ * @param opts - Space keys and optional timeframes for catch-up.
370
+ */
392
371
  // TODO(burdon): Rename join space.
393
372
  @synchronized
394
- async acceptSpace(opts: AcceptSpaceOptions): Promise<DataSpace> {
373
+ @trace.span({ showInBrowserTimeline: true, op: 'lifecycle' })
374
+ async acceptSpace(ctx: Context, opts: AcceptSpaceOptions): Promise<DataSpace> {
395
375
  log('accept space', { opts });
396
376
  invariant(this._lifecycleState === LifecycleState.OPEN, 'Not open.');
397
377
  invariant(!this._spaces.has(opts.spaceKey), 'Space already exists.');
378
+ invariant(!this.isSpaceDeleted(opts.spaceKey), 'Cannot accept a deleted space.');
398
379
 
380
+ const tags = opts.tags ? Array.from(opts.tags) : [];
399
381
  const metadata: SpaceMetadata = {
400
382
  key: opts.spaceKey,
401
383
  genesisFeedKey: opts.genesisFeedKey,
402
384
  controlTimeframe: opts.controlTimeframe,
403
385
  dataTimeframe: opts.dataTimeframe,
386
+ tags,
404
387
  };
405
388
 
406
- const space = await this._constructSpace(metadata);
407
- await space.open();
389
+ const space = await this._constructSpace(ctx, metadata);
390
+ await space.open(ctx);
408
391
  await this._metadataStore.addSpace(metadata);
409
- space.initializeDataPipelineAsync();
392
+ // Use DSM lifecycle ctx: the invitation accept flow disposes `ctx` as soon as
393
+ // `acceptSpace` returns (guardedState.complete -> ctx.dispose). Detached data-pipeline
394
+ // initialization must outlive the invitation flow, and its span must be parented to a
395
+ // long-lived context.
396
+ space.initializeDataPipelineAsync(this._ctx);
410
397
 
411
398
  this.updated.emit();
412
399
  return space;
413
400
  }
414
401
 
402
+ /**
403
+ * Whether the space has been tombstoned (soft-deleted). Deleted spaces are never opened or replicated.
404
+ */
405
+ isSpaceDeleted(spaceKey: PublicKey): boolean {
406
+ // Mirror the deletion predicate used in `_open`: the tombstone list or a persisted SPACE_DELETED state.
407
+ return (
408
+ this._metadataStore.deletedSpaces.some((key) => key.equals(spaceKey)) ||
409
+ this._metadataStore.spaces.some(
410
+ (spaceMetadata) => spaceMetadata.key.equals(spaceKey) && spaceMetadata.state === SpaceState.SPACE_DELETED,
411
+ )
412
+ );
413
+ }
414
+
415
+ /**
416
+ * Tombstones (soft-deletes) a space initiated locally on this device.
417
+ * Records a SpaceDeleted credential in the HALO so the deletion replicates to the user's other devices,
418
+ * then unloads the space locally. Data is not removed until garbage collection (future work).
419
+ */
420
+ @synchronized
421
+ async markSpaceDeleted(ctx: Context, spaceKey: PublicKey): Promise<void> {
422
+ if (this.isSpaceDeleted(spaceKey)) {
423
+ return;
424
+ }
425
+
426
+ // Replicates to the user's other devices via the HALO control feed.
427
+ const credential = await this._signingContext.credentialSigner.createCredential({
428
+ subject: spaceKey,
429
+ assertion: {
430
+ '@type': 'dxos.halo.credentials.SpaceDeleted',
431
+ spaceKey,
432
+ deletedAt: new Date(),
433
+ },
434
+ });
435
+ await this._signingContext.recordCredential(credential);
436
+
437
+ await this._tombstoneSpace(ctx, spaceKey);
438
+ }
439
+
440
+ /**
441
+ * Tombstones a space in response to a SpaceDeleted credential replicated from another device.
442
+ * Does not write a credential (one already exists in the HALO).
443
+ */
444
+ @synchronized
445
+ async handleRemoteSpaceDeleted(ctx: Context, spaceKey: PublicKey): Promise<void> {
446
+ if (this.isSpaceDeleted(spaceKey)) {
447
+ return;
448
+ }
449
+
450
+ await this._tombstoneSpace(ctx, spaceKey);
451
+ }
452
+
453
+ /**
454
+ * Persists the tombstone and unloads the space if it is currently loaded.
455
+ * Must be called while holding the DataSpaceManager lock (see callers).
456
+ */
457
+ private async _tombstoneSpace(ctx: Context, spaceKey: PublicKey): Promise<void> {
458
+ await this._metadataStore.addDeletedSpace(spaceKey);
459
+
460
+ const space = this._spaces.get(spaceKey);
461
+ if (space) {
462
+ // Separate teardown (resource lifecycle) from the terminal state transition.
463
+ if (space.isOpen) {
464
+ await space.close(ctx);
465
+ }
466
+ await space.delete();
467
+ this._spaces.delete(spaceKey);
468
+ }
469
+
470
+ this.updated.emit();
471
+ }
472
+
415
473
  async admitMember(options: AdmitMemberOptions): Promise<Credential> {
416
474
  const space = this._spaceManager.spaces.get(options.spaceKey);
417
475
  invariant(space);
@@ -430,6 +488,7 @@ export class DataSpaceManager extends Resource {
430
488
  space.spaceState.membershipChainHeads,
431
489
  options.profile,
432
490
  options.delegationCredentialId,
491
+ space.spaceState.tags,
433
492
  );
434
493
 
435
494
  // TODO(dmaretskyi): Refactor.
@@ -456,8 +515,8 @@ export class DataSpaceManager extends Resource {
456
515
  );
457
516
  }
458
517
 
459
- public async requestSpaceAdmissionCredential(spaceKey: PublicKey): Promise<Credential> {
460
- return this._spaceManager.requestSpaceAdmissionCredential({
518
+ public async requestSpaceAdmissionCredential(ctx: Context, spaceKey: PublicKey): Promise<Credential> {
519
+ return this._spaceManager.requestSpaceAdmissionCredential(ctx, {
461
520
  spaceKey,
462
521
  identityKey: this._signingContext.identityKey,
463
522
  timeout: 15_000,
@@ -470,7 +529,11 @@ export class DataSpaceManager extends Resource {
470
529
  });
471
530
  }
472
531
 
473
- async setSpaceEdgeReplicationSetting(spaceKey: PublicKey, setting: EdgeReplicationSetting): Promise<void> {
532
+ async setSpaceEdgeReplicationSetting(
533
+ ctx: Context,
534
+ spaceKey: PublicKey,
535
+ setting: EdgeReplicationSetting,
536
+ ): Promise<void> {
474
537
  const space = this._spaces.get(spaceKey);
475
538
  invariant(space, 'Space not found.');
476
539
 
@@ -482,7 +545,7 @@ export class DataSpaceManager extends Resource {
482
545
  await this._echoEdgeReplicator?.disconnectFromSpace(space.id);
483
546
  break;
484
547
  case EdgeReplicationSetting.ENABLED:
485
- await this._echoEdgeReplicator?.connectToSpace(space.id);
548
+ await this._echoEdgeReplicator?.connectToSpace(ctx, space.id);
486
549
  break;
487
550
  }
488
551
  }
@@ -490,14 +553,14 @@ export class DataSpaceManager extends Resource {
490
553
  space.stateUpdate.emit();
491
554
  }
492
555
 
493
- private async _constructSpace(metadata: SpaceMetadata): Promise<DataSpace> {
556
+ private async _constructSpace(ctx: Context, metadata: SpaceMetadata): Promise<DataSpace> {
494
557
  log('construct space', { metadata });
495
558
  const gossip = new Gossip({
496
559
  localPeerId: this._signingContext.deviceKey,
497
560
  });
498
561
  const presence = new Presence({
499
- announceInterval: this._runtimeParams?.spaceMemberPresenceAnnounceInterval ?? PRESENCE_ANNOUNCE_INTERVAL,
500
- offlineTimeout: this._runtimeParams?.spaceMemberPresenceOfflineTimeout ?? PRESENCE_OFFLINE_TIMEOUT,
562
+ announceInterval: this._runtimeProps?.spaceMemberPresenceAnnounceInterval ?? PRESENCE_ANNOUNCE_INTERVAL,
563
+ offlineTimeout: this._runtimeProps?.spaceMemberPresenceOfflineTimeout ?? PRESENCE_OFFLINE_TIMEOUT,
501
564
  identityKey: this._signingContext.identityKey,
502
565
  gossip,
503
566
  });
@@ -580,17 +643,19 @@ export class DataSpaceManager extends Resource {
580
643
  },
581
644
  },
582
645
  cache: metadata.cache,
646
+ tags: metadata.tags,
583
647
  edgeConnection: this._edgeConnection,
584
648
  edgeHttpClient: this._edgeHttpClient,
585
649
  edgeFeatures: this._edgeFeatures,
586
- activeEdgeNotarizationPollingInterval: this._runtimeParams?.activeEdgeNotarizationPollingInterval,
650
+ activeEdgeNotarizationPollingInterval: this._runtimeProps?.activeEdgeNotarizationPollingInterval,
587
651
  });
588
652
  dataSpace.postOpen.append(async () => {
589
653
  const setting = dataSpace.getEdgeReplicationSetting();
590
654
  if (!setting || setting === EdgeReplicationSetting.ENABLED) {
591
- await this._echoEdgeReplicator?.connectToSpace(dataSpace.id);
655
+ // Use lifecycle ctx: the caller ctx from _constructSpace may be disposed by the time postOpen fires.
656
+ await this._echoEdgeReplicator?.connectToSpace(this._ctx, dataSpace.id);
592
657
  } else if (this._echoEdgeReplicator) {
593
- log('not connecting EchoEdgeReplicator because of EdgeReplicationSetting', { spaceId: dataSpace.id });
658
+ log('not connecting edge replicator because of EdgeReplicationSetting', { spaceId: dataSpace.id });
594
659
  }
595
660
  });
596
661
  dataSpace.preClose.append(async () => {
@@ -685,7 +750,7 @@ export class DataSpaceManager extends Resource {
685
750
  invitations: Array<[PublicKey, DelegateSpaceInvitation]>,
686
751
  ): Promise<void> {
687
752
  const tasks = invitations.map(([credentialId, invitation]) => {
688
- return this._invitationsManager.createInvitation({
753
+ return this._invitationsManager.createInvitation(this._ctx, {
689
754
  type: Invitation.Type.DELEGATED,
690
755
  kind: Invitation.Kind.SPACE,
691
756
  spaceKey: space.key,