@dxos/client-services 0.8.4-main.fd6878d → 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 (254) hide show
  1. package/LICENSE +102 -5
  2. package/README.md +1 -1
  3. package/dist/lib/browser/{chunk-6C7MTZLC.mjs → chunk-HPR4MJ4W.mjs} +2916 -3802
  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 +59 -55
  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-YOHACH7G.mjs → chunk-JW6QHPRJ.mjs} +2859 -3614
  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 +59 -55
  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 +10 -7
  177. package/src/packlets/agents/edge-agent-service.ts +15 -3
  178. package/src/packlets/devices/devices-service.test.ts +0 -1
  179. package/src/packlets/devices/devices-service.ts +1 -1
  180. package/src/packlets/devtools/devtools.ts +28 -7
  181. package/src/packlets/devtools/feeds.ts +1 -1
  182. package/src/packlets/devtools/keys.ts +2 -2
  183. package/src/packlets/devtools/spaces.ts +1 -1
  184. package/src/packlets/diagnostics/diagnostics.ts +1 -2
  185. package/src/packlets/diagnostics/index.ts +1 -1
  186. package/src/packlets/identity/authenticator.ts +3 -3
  187. package/src/packlets/identity/contacts-service.ts +1 -2
  188. package/src/packlets/identity/identity-manager.test.ts +6 -6
  189. package/src/packlets/identity/identity-manager.ts +29 -28
  190. package/src/packlets/identity/identity-recovery-manager.ts +31 -22
  191. package/src/packlets/identity/identity-service.test.ts +6 -27
  192. package/src/packlets/identity/identity-service.ts +17 -83
  193. package/src/packlets/identity/identity.test.ts +7 -7
  194. package/src/packlets/identity/identity.ts +12 -35
  195. package/src/packlets/invitations/device-invitation-protocol.ts +10 -9
  196. package/src/packlets/invitations/edge-invitation-handler.ts +9 -5
  197. package/src/packlets/invitations/invitation-guest-extenstion.ts +6 -4
  198. package/src/packlets/invitations/invitation-host-extension.ts +13 -14
  199. package/src/packlets/invitations/invitation-protocol.ts +7 -4
  200. package/src/packlets/invitations/invitation-state.ts +1 -15
  201. package/src/packlets/invitations/invitations-handler.test.ts +4 -5
  202. package/src/packlets/invitations/invitations-handler.ts +74 -22
  203. package/src/packlets/invitations/invitations-manager.ts +42 -17
  204. package/src/packlets/invitations/invitations-service.ts +9 -9
  205. package/src/packlets/invitations/space-invitation-protocol.test.ts +17 -16
  206. package/src/packlets/invitations/space-invitation-protocol.ts +13 -18
  207. package/src/packlets/locks/index.ts +1 -1
  208. package/src/packlets/logging/logging-service.ts +20 -16
  209. package/src/packlets/network/network-service.test.ts +0 -1
  210. package/src/packlets/network/network-service.ts +10 -8
  211. package/src/packlets/services/client-rpc-server.ts +19 -16
  212. package/src/packlets/services/feed-syncer.test.ts +376 -0
  213. package/src/packlets/services/feed-syncer.ts +536 -0
  214. package/src/packlets/services/index.ts +1 -0
  215. package/src/packlets/services/platform.ts +7 -1
  216. package/src/packlets/services/service-context.test.ts +3 -2
  217. package/src/packlets/services/service-context.ts +218 -80
  218. package/src/packlets/services/service-host.test.ts +8 -10
  219. package/src/packlets/services/service-host.ts +104 -65
  220. package/src/packlets/services/service-registry.test.ts +0 -1
  221. package/src/packlets/services/sqlite-storage.ts +390 -0
  222. package/src/packlets/space-export/archive-format.ts +42 -0
  223. package/src/packlets/space-export/index.ts +4 -1
  224. package/src/packlets/space-export/serialized-space-reader.ts +129 -0
  225. package/src/packlets/space-export/serialized-space-writer.ts +260 -0
  226. package/src/packlets/space-export/space-archive-reader.ts +65 -4
  227. package/src/packlets/space-export/space-archive-writer.ts +43 -5
  228. package/src/packlets/space-export/space-archive.test.ts +482 -0
  229. package/src/packlets/spaces/data-space-manager.test.ts +169 -14
  230. package/src/packlets/spaces/data-space-manager.ts +209 -128
  231. package/src/packlets/spaces/data-space.ts +89 -43
  232. package/src/packlets/spaces/edge-feed-replicator.test.ts +3 -3
  233. package/src/packlets/spaces/edge-feed-replicator.ts +12 -10
  234. package/src/packlets/spaces/epoch-migrations.ts +7 -6
  235. package/src/packlets/spaces/genesis.ts +9 -4
  236. package/src/packlets/spaces/notarization-plugin.test.ts +2 -2
  237. package/src/packlets/spaces/notarization-plugin.ts +10 -9
  238. package/src/packlets/spaces/spaces-service.test.ts +18 -11
  239. package/src/packlets/spaces/spaces-service.ts +131 -25
  240. package/src/packlets/storage/index.ts +1 -0
  241. package/src/packlets/storage/profile-archive-sqlite.test.ts +79 -0
  242. package/src/packlets/storage/profile-archive-sqlite.ts +100 -0
  243. package/src/packlets/storage/profile-archive.ts +3 -0
  244. package/src/packlets/storage/storage.ts +4 -4
  245. package/src/packlets/testing/invitation-utils.ts +10 -6
  246. package/src/packlets/testing/test-builder.ts +59 -40
  247. package/src/packlets/worker/worker-runtime.ts +173 -17
  248. package/src/packlets/worker/worker-session.ts +12 -18
  249. package/src/version.ts +1 -1
  250. package/dist/lib/browser/chunk-6C7MTZLC.mjs.map +0 -7
  251. package/dist/lib/node-esm/chunk-YOHACH7G.mjs.map +0 -7
  252. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts +0 -19
  253. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts.map +0 -1
  254. 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 { Type } from '@dxos/echo';
18
19
  import {
19
20
  AuthStatus,
20
21
  CredentialServerExtension,
21
22
  DatabaseRoot,
22
- type EchoEdgeReplicator,
23
23
  type EchoHost,
24
- FIND_PARAMS,
24
+ type EdgeAutomergeReplicator,
25
25
  type MeshEchoReplicator,
26
- type MetadataStore,
26
+ type IMetadataStore,
27
27
  type Space,
28
28
  type SpaceManager,
29
29
  type SpaceProtocol,
30
30
  type SpaceProtocolSession,
31
31
  findInlineObjectOfType,
32
- } from '@dxos/echo-pipeline';
33
- import {
34
- type DatabaseDirectory,
35
- type ObjectStructure,
36
- SpaceDocVersion,
37
- createIdFromSpaceKey,
38
- encodeReference,
39
- } from '@dxos/echo-protocol';
40
- import { ObjectId, getTypeReference } from '@dxos/echo-schema';
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,10 +263,17 @@ 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> {
248
- assertArgument(!!options.rootUrl === !!options.documents, 'root url must be required when providing documents');
266
+ @trace.span({ showInBrowserTimeline: true, op: 'lifecycle' })
267
+ async createSpace(ctx: Context, options: CreateSpaceOptions = {}): Promise<DataSpace> {
268
+ assertArgument(
269
+ !!options.rootUrl === !!options.documents,
270
+ 'options',
271
+ 'root url must be required when providing documents',
272
+ );
249
273
 
250
274
  assertState(this._lifecycleState === LifecycleState.OPEN, 'Not open.');
275
+
276
+ const tags = options.tags ? Array.from(options.tags) : [];
251
277
  const spaceKey = await this._keyring.createKey();
252
278
  const controlFeedKey = await this._keyring.createKey();
253
279
  const dataFeedKey = await this._keyring.createKey();
@@ -260,6 +286,7 @@ export class DataSpaceManager extends Resource {
260
286
  controlFeedKey,
261
287
  dataFeedKey,
262
288
  state: SpaceState.SPACE_ACTIVE,
289
+ tags,
263
290
  };
264
291
 
265
292
  log('creating space...', { spaceId, spaceKey });
@@ -275,7 +302,18 @@ export class DataSpaceManager extends Resource {
275
302
  await Promise.all(
276
303
  Object.entries(options.documents).map(async ([documentId, data]) => {
277
304
  log('creating document...', { documentId });
278
- const newDoc = await this._echoHost.createDoc(data, { preserveHistory: true });
305
+ // TODO(dmaretskyi): Broken types -- the bytes get interpreted as CRDT data.
306
+ const newDoc = await this._echoHost.createDoc(data as any as DatabaseDirectory, {
307
+ preserveHistory: true,
308
+ });
309
+
310
+ // The archived documents might have the spaceKey from the space they were expored from, we need to update it to the new spaceKey.
311
+ if (newDoc.doc().access !== undefined && newDoc.doc().access!.spaceKey !== spaceKey.toHex()) {
312
+ newDoc.change((doc) => {
313
+ doc.access!.spaceKey = spaceKey.toHex();
314
+ });
315
+ }
316
+
279
317
  documentIdMapping[documentId as DocumentId] = newDoc.documentId;
280
318
  }),
281
319
  );
@@ -286,29 +324,38 @@ export class DataSpaceManager extends Resource {
286
324
  let root: DatabaseRoot;
287
325
  if (options.rootUrl) {
288
326
  const newRootDocId = documentIdMapping[interpretAsDocumentId(options.rootUrl)] ?? failedInvariant();
289
- 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.');
290
329
  DatabaseRoot.mapLinks(rootDocHandle, documentIdMapping);
291
330
 
292
- root = await this._echoHost.openSpaceRoot(spaceId, `automerge:${newRootDocId}` as AutomergeUrl);
331
+ root = await this._echoHost.openSpaceRoot(ctx, spaceId, `automerge:${newRootDocId}` as AutomergeUrl);
293
332
  } else {
294
- root = await this._echoHost.createSpaceRoot(spaceKey);
333
+ root = await this._echoHost.createSpaceRoot(ctx, spaceKey);
295
334
  }
335
+ await this._echoHost.flush(ctx);
296
336
 
297
337
  log('constructing space...', { spaceKey });
298
338
 
299
- const space = await this._constructSpace(metadata);
300
- await space.open();
339
+ const space = await this._constructSpace(ctx, metadata);
340
+ await space.open(ctx);
301
341
 
302
342
  log('adding space...', { spaceKey });
303
343
 
304
- 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
+ );
305
352
  await this._metadataStore.addSpace(metadata);
306
353
 
307
354
  const memberCredential = credentials[1];
308
355
  invariant(getCredentialAssertion(memberCredential)['@type'] === 'dxos.halo.credentials.SpaceMember');
309
356
  await this._signingContext.recordCredential(memberCredential);
310
357
 
311
- await space.initializeDataPipeline();
358
+ await space.initializeDataPipeline(ctx);
312
359
 
313
360
  log('space ready.', { spaceId, spaceKey });
314
361
 
@@ -316,86 +363,113 @@ export class DataSpaceManager extends Resource {
316
363
  return space;
317
364
  }
318
365
 
319
- async isDefaultSpace(space: DataSpace): Promise<boolean> {
320
- if (!space.databaseRoot) {
321
- return false;
322
- }
323
- switch (space.databaseRoot.getVersion()) {
324
- case SpaceDocVersion.CURRENT: {
325
- if (!space.databaseRoot.handle.isReady()) {
326
- log.warn('waiting for space root to be ready', { spaceId: space.id });
327
- await space.databaseRoot.handle.whenReady();
328
- }
329
- const [_, properties] = findInlineObjectOfType(space.databaseRoot.doc()!, TYPE_PROPERTIES) ?? [];
330
- return properties?.data?.[DEFAULT_SPACE_KEY] === this._signingContext.identityKey.toHex();
331
- }
332
- case SpaceDocVersion.LEGACY: {
333
- throw new Error('Legacy space version is not supported');
334
- }
335
-
336
- default:
337
- log.warn('unknown space version', { version: space.databaseRoot.getVersion(), spaceId: space.id });
338
- return false;
339
- }
340
- }
341
-
342
- async createDefaultSpace(): Promise<DataSpace> {
343
- const space = await this.createSpace();
344
- const document = await this._getSpaceRootDocument(space);
345
-
346
- // TODO(dmaretskyi): Better API for low-level data access.
347
- const properties: ObjectStructure = {
348
- system: {
349
- type: encodeReference(getTypeReference(PropertiesType)!),
350
- },
351
- data: {
352
- [DEFAULT_SPACE_KEY]: this._signingContext.identityKey.toHex(),
353
- },
354
- meta: {
355
- keys: [],
356
- },
357
- };
358
-
359
- const propertiesId = ObjectId.random();
360
- document.change((doc: DatabaseDirectory) => {
361
- setDeep(doc, ['objects', propertiesId], properties);
362
- });
363
-
364
- await this._echoHost.flush();
365
- return space;
366
- }
367
-
368
- private async _getSpaceRootDocument(space: DataSpace): Promise<DocHandle<DatabaseDirectory>> {
369
- const automergeIndex = space.automergeSpaceState.rootUrl;
370
- invariant(automergeIndex);
371
- const document = await this._echoHost.automergeRepo.find<DatabaseDirectory>(automergeIndex as any, FIND_PARAMS);
372
- await document.whenReady();
373
- return document;
374
- }
375
-
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
+ */
376
371
  // TODO(burdon): Rename join space.
377
372
  @synchronized
378
- async acceptSpace(opts: AcceptSpaceOptions): Promise<DataSpace> {
373
+ @trace.span({ showInBrowserTimeline: true, op: 'lifecycle' })
374
+ async acceptSpace(ctx: Context, opts: AcceptSpaceOptions): Promise<DataSpace> {
379
375
  log('accept space', { opts });
380
376
  invariant(this._lifecycleState === LifecycleState.OPEN, 'Not open.');
381
377
  invariant(!this._spaces.has(opts.spaceKey), 'Space already exists.');
378
+ invariant(!this.isSpaceDeleted(opts.spaceKey), 'Cannot accept a deleted space.');
382
379
 
380
+ const tags = opts.tags ? Array.from(opts.tags) : [];
383
381
  const metadata: SpaceMetadata = {
384
382
  key: opts.spaceKey,
385
383
  genesisFeedKey: opts.genesisFeedKey,
386
384
  controlTimeframe: opts.controlTimeframe,
387
385
  dataTimeframe: opts.dataTimeframe,
386
+ tags,
388
387
  };
389
388
 
390
- const space = await this._constructSpace(metadata);
391
- await space.open();
389
+ const space = await this._constructSpace(ctx, metadata);
390
+ await space.open(ctx);
392
391
  await this._metadataStore.addSpace(metadata);
393
- 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);
394
397
 
395
398
  this.updated.emit();
396
399
  return space;
397
400
  }
398
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
+
399
473
  async admitMember(options: AdmitMemberOptions): Promise<Credential> {
400
474
  const space = this._spaceManager.spaces.get(options.spaceKey);
401
475
  invariant(space);
@@ -414,6 +488,7 @@ export class DataSpaceManager extends Resource {
414
488
  space.spaceState.membershipChainHeads,
415
489
  options.profile,
416
490
  options.delegationCredentialId,
491
+ space.spaceState.tags,
417
492
  );
418
493
 
419
494
  // TODO(dmaretskyi): Refactor.
@@ -440,8 +515,8 @@ export class DataSpaceManager extends Resource {
440
515
  );
441
516
  }
442
517
 
443
- public async requestSpaceAdmissionCredential(spaceKey: PublicKey): Promise<Credential> {
444
- return this._spaceManager.requestSpaceAdmissionCredential({
518
+ public async requestSpaceAdmissionCredential(ctx: Context, spaceKey: PublicKey): Promise<Credential> {
519
+ return this._spaceManager.requestSpaceAdmissionCredential(ctx, {
445
520
  spaceKey,
446
521
  identityKey: this._signingContext.identityKey,
447
522
  timeout: 15_000,
@@ -454,7 +529,11 @@ export class DataSpaceManager extends Resource {
454
529
  });
455
530
  }
456
531
 
457
- async setSpaceEdgeReplicationSetting(spaceKey: PublicKey, setting: EdgeReplicationSetting): Promise<void> {
532
+ async setSpaceEdgeReplicationSetting(
533
+ ctx: Context,
534
+ spaceKey: PublicKey,
535
+ setting: EdgeReplicationSetting,
536
+ ): Promise<void> {
458
537
  const space = this._spaces.get(spaceKey);
459
538
  invariant(space, 'Space not found.');
460
539
 
@@ -466,7 +545,7 @@ export class DataSpaceManager extends Resource {
466
545
  await this._echoEdgeReplicator?.disconnectFromSpace(space.id);
467
546
  break;
468
547
  case EdgeReplicationSetting.ENABLED:
469
- await this._echoEdgeReplicator?.connectToSpace(space.id);
548
+ await this._echoEdgeReplicator?.connectToSpace(ctx, space.id);
470
549
  break;
471
550
  }
472
551
  }
@@ -474,14 +553,14 @@ export class DataSpaceManager extends Resource {
474
553
  space.stateUpdate.emit();
475
554
  }
476
555
 
477
- private async _constructSpace(metadata: SpaceMetadata): Promise<DataSpace> {
556
+ private async _constructSpace(ctx: Context, metadata: SpaceMetadata): Promise<DataSpace> {
478
557
  log('construct space', { metadata });
479
558
  const gossip = new Gossip({
480
559
  localPeerId: this._signingContext.deviceKey,
481
560
  });
482
561
  const presence = new Presence({
483
- announceInterval: this._runtimeParams?.spaceMemberPresenceAnnounceInterval ?? PRESENCE_ANNOUNCE_INTERVAL,
484
- offlineTimeout: this._runtimeParams?.spaceMemberPresenceOfflineTimeout ?? PRESENCE_OFFLINE_TIMEOUT,
562
+ announceInterval: this._runtimeProps?.spaceMemberPresenceAnnounceInterval ?? PRESENCE_ANNOUNCE_INTERVAL,
563
+ offlineTimeout: this._runtimeProps?.spaceMemberPresenceOfflineTimeout ?? PRESENCE_OFFLINE_TIMEOUT,
485
564
  identityKey: this._signingContext.identityKey,
486
565
  gossip,
487
566
  });
@@ -564,17 +643,19 @@ export class DataSpaceManager extends Resource {
564
643
  },
565
644
  },
566
645
  cache: metadata.cache,
646
+ tags: metadata.tags,
567
647
  edgeConnection: this._edgeConnection,
568
648
  edgeHttpClient: this._edgeHttpClient,
569
649
  edgeFeatures: this._edgeFeatures,
570
- activeEdgeNotarizationPollingInterval: this._runtimeParams?.activeEdgeNotarizationPollingInterval,
650
+ activeEdgeNotarizationPollingInterval: this._runtimeProps?.activeEdgeNotarizationPollingInterval,
571
651
  });
572
652
  dataSpace.postOpen.append(async () => {
573
653
  const setting = dataSpace.getEdgeReplicationSetting();
574
654
  if (!setting || setting === EdgeReplicationSetting.ENABLED) {
575
- 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);
576
657
  } else if (this._echoEdgeReplicator) {
577
- log('not connecting EchoEdgeReplicator because of EdgeReplicationSetting', { spaceId: dataSpace.id });
658
+ log('not connecting edge replicator because of EdgeReplicationSetting', { spaceId: dataSpace.id });
578
659
  }
579
660
  });
580
661
  dataSpace.preClose.append(async () => {
@@ -669,7 +750,7 @@ export class DataSpaceManager extends Resource {
669
750
  invitations: Array<[PublicKey, DelegateSpaceInvitation]>,
670
751
  ): Promise<void> {
671
752
  const tasks = invitations.map(([credentialId, invitation]) => {
672
- return this._invitationsManager.createInvitation({
753
+ return this._invitationsManager.createInvitation(this._ctx, {
673
754
  type: Invitation.Type.DELEGATED,
674
755
  kind: Invitation.Kind.SPACE,
675
756
  spaceKey: space.key,