@dxos/client-services 0.8.4-main.ae835ea → 0.8.4-main.bc2380dfbc

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 (230) hide show
  1. package/LICENSE +102 -5
  2. package/README.md +1 -1
  3. package/dist/lib/browser/chunk-QCWEHHJW.mjs +24 -0
  4. package/dist/lib/browser/chunk-QCWEHHJW.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-KPYVJG6G.mjs → chunk-TUCJORVO.mjs} +2153 -3654
  6. package/dist/lib/browser/chunk-TUCJORVO.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 +424 -137
  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 +28 -29
  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-BBBSS6UL.mjs → chunk-IQLAKNSR.mjs} +2099 -3469
  27. package/dist/lib/node-esm/chunk-IQLAKNSR.mjs.map +7 -0
  28. package/dist/lib/node-esm/index.mjs +424 -137
  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 +28 -29
  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 +2 -2
  49. package/dist/types/src/packlets/devtools/devtools.d.ts.map +1 -1
  50. package/dist/types/src/packlets/devtools/feeds.d.ts.map +1 -1
  51. package/dist/types/src/packlets/devtools/keys.d.ts.map +1 -1
  52. package/dist/types/src/packlets/devtools/metadata.d.ts.map +1 -1
  53. package/dist/types/src/packlets/devtools/network.d.ts.map +1 -1
  54. package/dist/types/src/packlets/devtools/spaces.d.ts.map +1 -1
  55. package/dist/types/src/packlets/diagnostics/browser-diagnostics-broadcast.d.ts.map +1 -1
  56. package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
  57. package/dist/types/src/packlets/diagnostics/diagnostics-collector.d.ts.map +1 -1
  58. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts +2 -3
  59. package/dist/types/src/packlets/diagnostics/diagnostics.d.ts.map +1 -1
  60. package/dist/types/src/packlets/diagnostics/index.d.ts +1 -1
  61. package/dist/types/src/packlets/diagnostics/index.d.ts.map +1 -1
  62. package/dist/types/src/packlets/identity/authenticator.d.ts +2 -2
  63. package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
  64. package/dist/types/src/packlets/identity/contacts-service.d.ts.map +1 -1
  65. package/dist/types/src/packlets/identity/identity-manager.d.ts +6 -6
  66. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  67. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +8 -7
  68. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
  69. package/dist/types/src/packlets/identity/identity-service.d.ts +6 -10
  70. package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
  71. package/dist/types/src/packlets/identity/identity.d.ts +8 -11
  72. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  73. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +6 -5
  74. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
  75. package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts +1 -1
  76. package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts.map +1 -1
  77. package/dist/types/src/packlets/invitations/invitation-guest-extenstion.d.ts.map +1 -1
  78. package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -1
  79. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts +7 -4
  80. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts.map +1 -1
  81. package/dist/types/src/packlets/invitations/invitation-state.d.ts.map +1 -1
  82. package/dist/types/src/packlets/invitations/invitation-topology.d.ts.map +1 -1
  83. package/dist/types/src/packlets/invitations/invitations-handler.d.ts +4 -4
  84. package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
  85. package/dist/types/src/packlets/invitations/invitations-manager.d.ts +3 -3
  86. package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -1
  87. package/dist/types/src/packlets/invitations/invitations-service.d.ts +3 -3
  88. package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -1
  89. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +4 -3
  90. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
  91. package/dist/types/src/packlets/invitations/utils.d.ts.map +1 -1
  92. package/dist/types/src/packlets/locks/browser.d.ts.map +1 -1
  93. package/dist/types/src/packlets/locks/index.d.ts +1 -1
  94. package/dist/types/src/packlets/locks/index.d.ts.map +1 -1
  95. package/dist/types/src/packlets/locks/node.d.ts.map +1 -1
  96. package/dist/types/src/packlets/logging/logging-service.d.ts +4 -0
  97. package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
  98. package/dist/types/src/packlets/network/network-service.d.ts +5 -4
  99. package/dist/types/src/packlets/network/network-service.d.ts.map +1 -1
  100. package/dist/types/src/packlets/services/client-rpc-server.d.ts +5 -5
  101. package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
  102. package/dist/types/src/packlets/services/feed-syncer.d.ts +59 -0
  103. package/dist/types/src/packlets/services/feed-syncer.d.ts.map +1 -0
  104. package/dist/types/src/packlets/services/feed-syncer.test.d.ts +2 -0
  105. package/dist/types/src/packlets/services/feed-syncer.test.d.ts.map +1 -0
  106. package/dist/types/src/packlets/services/platform.d.ts.map +1 -1
  107. package/dist/types/src/packlets/services/service-context.d.ts +13 -9
  108. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  109. package/dist/types/src/packlets/services/service-host.d.ts +20 -7
  110. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  111. package/dist/types/src/packlets/services/service-registry.d.ts.map +1 -1
  112. package/dist/types/src/packlets/services/util.d.ts.map +1 -1
  113. package/dist/types/src/packlets/space-export/archive-format.d.ts +9 -0
  114. package/dist/types/src/packlets/space-export/archive-format.d.ts.map +1 -0
  115. package/dist/types/src/packlets/space-export/index.d.ts +4 -1
  116. package/dist/types/src/packlets/space-export/index.d.ts.map +1 -1
  117. package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts +23 -0
  118. package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts.map +1 -0
  119. package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts +36 -0
  120. package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts.map +1 -0
  121. package/dist/types/src/packlets/space-export/space-archive-reader.d.ts +9 -1
  122. package/dist/types/src/packlets/space-export/space-archive-reader.d.ts.map +1 -1
  123. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts +7 -1
  124. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts.map +1 -1
  125. package/dist/types/src/packlets/space-export/space-archive.test.d.ts +2 -0
  126. package/dist/types/src/packlets/space-export/space-archive.test.d.ts.map +1 -0
  127. package/dist/types/src/packlets/spaces/automerge-space-state.d.ts.map +1 -1
  128. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +30 -19
  129. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  130. package/dist/types/src/packlets/spaces/data-space.d.ts +26 -9
  131. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  132. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts +2 -2
  133. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
  134. package/dist/types/src/packlets/spaces/epoch-migrations.d.ts.map +1 -1
  135. package/dist/types/src/packlets/spaces/genesis.d.ts +2 -1
  136. package/dist/types/src/packlets/spaces/genesis.d.ts.map +1 -1
  137. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +6 -9
  138. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
  139. package/dist/types/src/packlets/spaces/spaces-service.d.ts +10 -7
  140. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  141. package/dist/types/src/packlets/storage/level.d.ts.map +1 -1
  142. package/dist/types/src/packlets/storage/profile-archive.d.ts.map +1 -1
  143. package/dist/types/src/packlets/storage/storage.d.ts.map +1 -1
  144. package/dist/types/src/packlets/storage/util.d.ts.map +1 -1
  145. package/dist/types/src/packlets/system/system-service.d.ts +1 -1
  146. package/dist/types/src/packlets/system/system-service.d.ts.map +1 -1
  147. package/dist/types/src/packlets/testing/credential-utils.d.ts.map +1 -1
  148. package/dist/types/src/packlets/testing/invitation-utils.d.ts +6 -3
  149. package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
  150. package/dist/types/src/packlets/testing/test-builder.d.ts +6 -5
  151. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  152. package/dist/types/src/packlets/worker/worker-runtime.d.ts +41 -4
  153. package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
  154. package/dist/types/src/packlets/worker/worker-session.d.ts +2 -4
  155. package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
  156. package/dist/types/src/testing/setup.d.ts.map +1 -1
  157. package/dist/types/src/version.d.ts +1 -1
  158. package/dist/types/src/version.d.ts.map +1 -1
  159. package/dist/types/tsconfig.tsbuildinfo +1 -1
  160. package/package.json +71 -56
  161. package/src/index.ts +1 -0
  162. package/src/packlets/agents/edge-agent-manager.ts +8 -5
  163. package/src/packlets/agents/edge-agent-service.ts +4 -2
  164. package/src/packlets/devices/devices-service.test.ts +0 -1
  165. package/src/packlets/devtools/devtools.ts +2 -3
  166. package/src/packlets/diagnostics/diagnostics.ts +1 -2
  167. package/src/packlets/diagnostics/index.ts +1 -1
  168. package/src/packlets/identity/authenticator.ts +2 -2
  169. package/src/packlets/identity/contacts-service.ts +0 -1
  170. package/src/packlets/identity/identity-manager.test.ts +5 -5
  171. package/src/packlets/identity/identity-manager.ts +23 -22
  172. package/src/packlets/identity/identity-recovery-manager.ts +22 -18
  173. package/src/packlets/identity/identity-service.test.ts +6 -27
  174. package/src/packlets/identity/identity-service.ts +13 -81
  175. package/src/packlets/identity/identity.test.ts +2 -2
  176. package/src/packlets/identity/identity.ts +11 -34
  177. package/src/packlets/invitations/device-invitation-protocol.ts +8 -7
  178. package/src/packlets/invitations/edge-invitation-handler.ts +9 -5
  179. package/src/packlets/invitations/invitation-guest-extenstion.ts +6 -4
  180. package/src/packlets/invitations/invitation-host-extension.ts +13 -14
  181. package/src/packlets/invitations/invitation-protocol.ts +7 -4
  182. package/src/packlets/invitations/invitation-state.ts +1 -15
  183. package/src/packlets/invitations/invitations-handler.test.ts +4 -5
  184. package/src/packlets/invitations/invitations-handler.ts +74 -22
  185. package/src/packlets/invitations/invitations-manager.ts +40 -15
  186. package/src/packlets/invitations/invitations-service.ts +9 -9
  187. package/src/packlets/invitations/space-invitation-protocol.test.ts +17 -16
  188. package/src/packlets/invitations/space-invitation-protocol.ts +11 -16
  189. package/src/packlets/locks/index.ts +1 -1
  190. package/src/packlets/logging/logging-service.ts +20 -16
  191. package/src/packlets/network/network-service.test.ts +0 -1
  192. package/src/packlets/network/network-service.ts +10 -8
  193. package/src/packlets/services/client-rpc-server.ts +19 -16
  194. package/src/packlets/services/feed-syncer.test.ts +340 -0
  195. package/src/packlets/services/feed-syncer.ts +377 -0
  196. package/src/packlets/services/platform.ts +7 -1
  197. package/src/packlets/services/service-context.test.ts +3 -2
  198. package/src/packlets/services/service-context.ts +153 -61
  199. package/src/packlets/services/service-host.test.ts +8 -8
  200. package/src/packlets/services/service-host.ts +70 -40
  201. package/src/packlets/services/service-registry.test.ts +0 -1
  202. package/src/packlets/space-export/archive-format.ts +42 -0
  203. package/src/packlets/space-export/index.ts +4 -1
  204. package/src/packlets/space-export/serialized-space-reader.ts +111 -0
  205. package/src/packlets/space-export/serialized-space-writer.ts +252 -0
  206. package/src/packlets/space-export/space-archive-reader.ts +64 -3
  207. package/src/packlets/space-export/space-archive-writer.ts +41 -3
  208. package/src/packlets/space-export/space-archive.test.ts +461 -0
  209. package/src/packlets/spaces/data-space-manager.test.ts +79 -13
  210. package/src/packlets/spaces/data-space-manager.ts +108 -120
  211. package/src/packlets/spaces/data-space.ts +64 -36
  212. package/src/packlets/spaces/edge-feed-replicator.test.ts +1 -1
  213. package/src/packlets/spaces/edge-feed-replicator.ts +11 -9
  214. package/src/packlets/spaces/epoch-migrations.ts +6 -5
  215. package/src/packlets/spaces/genesis.ts +6 -1
  216. package/src/packlets/spaces/notarization-plugin.test.ts +2 -2
  217. package/src/packlets/spaces/notarization-plugin.ts +10 -9
  218. package/src/packlets/spaces/spaces-service.test.ts +18 -11
  219. package/src/packlets/spaces/spaces-service.ts +124 -24
  220. package/src/packlets/storage/storage.ts +4 -4
  221. package/src/packlets/testing/invitation-utils.ts +10 -6
  222. package/src/packlets/testing/test-builder.ts +36 -10
  223. package/src/packlets/worker/worker-runtime.ts +188 -17
  224. package/src/packlets/worker/worker-session.ts +12 -18
  225. package/src/version.ts +1 -1
  226. package/dist/lib/browser/chunk-KPYVJG6G.mjs.map +0 -7
  227. package/dist/lib/node-esm/chunk-BBBSS6UL.mjs.map +0 -7
  228. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts +0 -19
  229. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts.map +0 -1
  230. package/src/packlets/identity/default-space-state-machine.ts +0 -44
@@ -11,7 +11,6 @@ import { type Identity, type IdentityService } from '@dxos/protocols/proto/dxos/
11
11
 
12
12
  import { type ServiceContext } from '../services';
13
13
  import { createServiceContext } from '../testing';
14
-
15
14
  import { IdentityServiceImpl } from './identity-service';
16
15
 
17
16
  describe('IdentityService', () => {
@@ -48,6 +47,12 @@ describe('IdentityService', () => {
48
47
  await identityService.createIdentity({});
49
48
  await expect(identityService.createIdentity({})).rejects.toThrowError('Identity already exists');
50
49
  });
50
+
51
+ test('creates identity with no spaces', async () => {
52
+ await identityService.createIdentity({});
53
+ const dataSpaces = [...(serviceContext.dataSpaceManager?.spaces?.values() ?? [])];
54
+ expect(dataSpaces.length).to.eq(0);
55
+ });
51
56
  });
52
57
 
53
58
  describe.skip('recoverIdentity', () => {});
@@ -89,37 +94,11 @@ describe('IdentityService', () => {
89
94
  });
90
95
  });
91
96
 
92
- describe('open', () => {
93
- test('identity without default space fixed', async () => {
94
- const serviceContext = await createServiceContext();
95
- await serviceContext.open(new Context());
96
- const identity = await serviceContext.createIdentity();
97
- const identityService = createIdentityService(serviceContext);
98
- const getDataSpaces = () => [...(serviceContext.dataSpaceManager?.spaces?.values() ?? [])];
99
- expect(getDataSpaces().length).to.eq(0);
100
- expect(identity.defaultSpaceId).to.be.undefined;
101
- await identityService.open();
102
- expect(getDataSpaces()[0].id === identity.defaultSpaceId).to.be.true;
103
- });
104
-
105
- test('identity without default space credential fixed', async () => {
106
- const serviceContext = await createServiceContext();
107
- await serviceContext.open(new Context());
108
- const identity = await serviceContext.createIdentity();
109
- const space = await serviceContext.dataSpaceManager!.createDefaultSpace();
110
- const identityService = createIdentityService(serviceContext);
111
- expect(identity.defaultSpaceId).to.be.undefined;
112
- await identityService.open();
113
- expect(identity.defaultSpaceId === space.id).to.be.true;
114
- });
115
- });
116
-
117
97
  const createIdentityService = (serviceContext: ServiceContext) => {
118
98
  return new IdentityServiceImpl(
119
99
  serviceContext.identityManager,
120
100
  serviceContext.recoveryManager,
121
101
  serviceContext.keyring,
122
- () => serviceContext.dataSpaceManager!,
123
102
  (options) => serviceContext.createIdentity(options),
124
103
  );
125
104
  };
@@ -2,13 +2,12 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { Trigger, sleep } from '@dxos/async';
5
+ import { type RequestOptions } from '@dxos/codec-protobuf';
6
6
  import { Stream } from '@dxos/codec-protobuf/stream';
7
- import { Resource } from '@dxos/context';
7
+ import { Context, Resource } from '@dxos/context';
8
8
  import { createCredential, signPresentation } from '@dxos/credentials';
9
9
  import { invariant } from '@dxos/invariant';
10
10
  import { type Keyring } from '@dxos/keyring';
11
- import { log } from '@dxos/log';
12
11
  import {
13
12
  type CreateIdentityRequest,
14
13
  type CreateRecoveryCredentialRequest,
@@ -17,52 +16,30 @@ import {
17
16
  type QueryIdentityResponse,
18
17
  type RecoverIdentityRequest,
19
18
  type SignPresentationRequest,
20
- SpaceState,
21
19
  } from '@dxos/protocols/proto/dxos/client/services';
22
20
  import { type Presentation, type ProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
23
- import { safeAwaitAll } from '@dxos/util';
24
-
25
- import { type DataSpaceManager } from '../spaces';
26
21
 
27
22
  import { type Identity } from './identity';
28
23
  import { type CreateIdentityOptions, type IdentityManager } from './identity-manager';
29
24
  import { type EdgeIdentityRecoveryManager } from './identity-recovery-manager';
30
25
 
31
- const DEFAULT_SPACE_SEARCH_TIMEOUT = 10_000;
32
-
33
26
  export class IdentityServiceImpl extends Resource implements IdentityService {
34
27
  constructor(
35
28
  private readonly _identityManager: IdentityManager,
36
29
  private readonly _recoveryManager: EdgeIdentityRecoveryManager,
37
30
  private readonly _keyring: Keyring,
38
- private readonly _dataSpaceManagerProvider: () => DataSpaceManager,
39
- private readonly _createIdentity: (params: CreateIdentityOptions) => Promise<Identity>,
31
+ private readonly _createIdentity: (params: CreateIdentityOptions, ctx?: Context) => Promise<Identity>,
40
32
  private readonly _onProfileUpdate?: (profile: ProfileDocument | undefined) => Promise<void>,
41
33
  ) {
42
34
  super();
43
35
  }
44
36
 
45
- protected override async _open(): Promise<void> {
46
- const identity = this._identityManager.identity;
47
- if (identity && !identity.defaultSpaceId) {
48
- await this._fixIdentityWithoutDefaultSpace(identity);
49
- }
50
- }
51
-
52
- async createIdentity(request: CreateIdentityRequest): Promise<IdentityProto> {
53
- await this._createIdentity({ profile: request.profile, deviceProfile: request.deviceProfile });
54
- const dataSpaceManager = this._dataSpaceManagerProvider();
55
- await this._createDefaultSpace(dataSpaceManager);
37
+ async createIdentity(request: CreateIdentityRequest, options?: RequestOptions): Promise<IdentityProto> {
38
+ const ctx = options?.ctx ?? Context.default();
39
+ await this._createIdentity({ profile: request.profile, deviceProfile: request.deviceProfile }, ctx);
56
40
  return this._getIdentity()!;
57
41
  }
58
42
 
59
- private async _createDefaultSpace(dataSpaceManager: DataSpaceManager): Promise<void> {
60
- const space = await dataSpaceManager!.createDefaultSpace();
61
- const identity = this._identityManager.identity;
62
- invariant(identity);
63
- await identity.updateDefaultSpace(space.id);
64
- }
65
-
66
43
  queryIdentity(): Stream<QueryIdentityResponse> {
67
44
  return new Stream(({ next }) => {
68
45
  const emitNext = () => next({ identity: this._getIdentity() });
@@ -96,17 +73,18 @@ export class IdentityServiceImpl extends Resource implements IdentityService {
96
73
  return this._recoveryManager.createRecoveryCredential(request);
97
74
  }
98
75
 
99
- async requestRecoveryChallenge() {
100
- return this._recoveryManager.requestRecoveryChallenge();
76
+ async requestRecoveryChallenge(_request: void, options?: RequestOptions) {
77
+ return this._recoveryManager.requestRecoveryChallenge(options?.ctx ?? Context.default());
101
78
  }
102
79
 
103
- async recoverIdentity(request: RecoverIdentityRequest): Promise<IdentityProto> {
80
+ async recoverIdentity(request: RecoverIdentityRequest, options?: RequestOptions): Promise<IdentityProto> {
81
+ const ctx = options?.ctx ?? Context.default();
104
82
  if (request.recoveryCode) {
105
- await this._recoveryManager.recoverIdentity({ recoveryCode: request.recoveryCode });
83
+ await this._recoveryManager.recoverIdentity(ctx, { recoveryCode: request.recoveryCode });
106
84
  } else if (request.external) {
107
- await this._recoveryManager.recoverIdentityWithExternalSignature(request.external);
85
+ await this._recoveryManager.recoverIdentityWithExternalSignature(ctx, request.external);
108
86
  } else if (request.token) {
109
- await this._recoveryManager.recoverIdentityWithToken({ token: request.token });
87
+ await this._recoveryManager.recoverIdentityWithToken(ctx, { token: request.token });
110
88
  } else {
111
89
  throw new Error('Invalid request.');
112
90
  }
@@ -141,50 +119,4 @@ export class IdentityServiceImpl extends Resource implements IdentityService {
141
119
  signer: this._keyring,
142
120
  });
143
121
  }
144
-
145
- private async _fixIdentityWithoutDefaultSpace(identity: Identity): Promise<void> {
146
- let recodedDefaultSpace = false;
147
- let foundDefaultSpace = false;
148
- const dataSpaceManager = this._dataSpaceManagerProvider();
149
-
150
- const recordedDefaultSpaceTrigger = new Trigger();
151
-
152
- const allProcessed = safeAwaitAll(
153
- dataSpaceManager.spaces.values(),
154
- async (space) => {
155
- if (space.state === SpaceState.SPACE_CLOSED) {
156
- await space.open();
157
-
158
- // Wait until the space is either READY or REQUIRES_MIGRATION.
159
- // NOTE: Space could potentially never initialize if the space data is corrupted.
160
- const requiresMigration = space.stateUpdate.waitForCondition(
161
- () => space.state === SpaceState.SPACE_REQUIRES_MIGRATION,
162
- );
163
- await Promise.race([space.initializeDataPipeline(), requiresMigration]);
164
- }
165
- if (await dataSpaceManager.isDefaultSpace(space)) {
166
- if (foundDefaultSpace) {
167
- log.warn('Multiple default spaces found. Using the first one.', { duplicate: space.id });
168
- return;
169
- }
170
-
171
- foundDefaultSpace = true;
172
- await identity.updateDefaultSpace(space.id);
173
- recodedDefaultSpace = true;
174
- recordedDefaultSpaceTrigger.wake();
175
- }
176
- },
177
- (err) => {
178
- log.catch(err);
179
- },
180
- );
181
-
182
- // Wait for all spaces to be processed or until the default space is recorded.
183
- // If the timeout is reached, create a new default space.
184
- await Promise.race([allProcessed, recordedDefaultSpaceTrigger.wait(), sleep(DEFAULT_SPACE_SEARCH_TIMEOUT)]);
185
-
186
- if (!recodedDefaultSpace) {
187
- await this._createDefaultSpace(dataSpaceManager);
188
- }
189
- }
190
122
  }
@@ -130,7 +130,7 @@ describe('identity/identity', () => {
130
130
  onMessage: (_: MessageListener): (() => void) => {
131
131
  return () => {};
132
132
  },
133
- send: async (_) => {
133
+ send: async (..._) => {
134
134
  replicationStarted = true;
135
135
  },
136
136
  } as EdgeConnection,
@@ -218,7 +218,7 @@ describe('identity/identity', () => {
218
218
  });
219
219
 
220
220
  await identity.open(new Context());
221
- await identity.joinNetwork();
221
+ await identity.joinNetwork(Context.default());
222
222
  onTestFinished(() => identity.close(new Context()));
223
223
  return { identity, identityKey, keyring, deviceKey, controlFeed, spaceKey, dataFeed };
224
224
  };
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { Event } from '@dxos/async';
6
6
  import { AUTH_TIMEOUT, LOAD_CONTROL_FEEDS_TIMEOUT } from '@dxos/client-protocol';
7
- import { type Context } from '@dxos/context';
7
+ import { type Context as DxosContext } from '@dxos/context';
8
8
  import {
9
9
  type CredentialSigner,
10
10
  DeviceStateMachine,
@@ -17,7 +17,7 @@ import { type Space } from '@dxos/echo-pipeline';
17
17
  import { type EdgeConnection } from '@dxos/edge-client';
18
18
  import { type FeedWrapper, writeMessages } from '@dxos/feed-store';
19
19
  import { invariant } from '@dxos/invariant';
20
- import { type IdentityDid, PublicKey, type SpaceId } from '@dxos/keys';
20
+ import { type IdentityDid, PublicKey } from '@dxos/keys';
21
21
  import { log } from '@dxos/log';
22
22
  import { type Runtime } from '@dxos/protocols/proto/dxos/config';
23
23
  import { type FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
@@ -29,16 +29,13 @@ import {
29
29
  } from '@dxos/protocols/proto/dxos/halo/credentials';
30
30
  import { type DeviceAdmissionRequest } from '@dxos/protocols/proto/dxos/halo/invitations';
31
31
  import { type Presence } from '@dxos/teleport-extension-gossip';
32
- import { Timeframe } from '@dxos/timeframe';
33
32
  import { trace } from '@dxos/tracing';
34
33
  import { type ComplexMap, ComplexSet } from '@dxos/util';
35
34
 
36
35
  import { EdgeFeedReplicator } from '../spaces';
37
-
38
36
  import { TrustedKeySetAuthVerifier } from './authenticator';
39
- import { DefaultSpaceStateMachine } from './default-space-state-machine';
40
37
 
41
- export type IdentityParams = {
38
+ export type IdentityProps = {
42
39
  did: IdentityDid;
43
40
  identityKey: PublicKey;
44
41
  deviceKey: PublicKey;
@@ -60,7 +57,6 @@ export class Identity {
60
57
  private readonly _presence?: Presence;
61
58
  private readonly _deviceStateMachine: DeviceStateMachine;
62
59
  private readonly _profileStateMachine: ProfileStateMachine;
63
- private readonly _defaultSpaceStateMachine: DefaultSpaceStateMachine;
64
60
  private readonly _edgeFeedReplicator?: EdgeFeedReplicator = undefined;
65
61
 
66
62
  public readonly authVerifier: TrustedKeySetAuthVerifier;
@@ -71,7 +67,7 @@ export class Identity {
71
67
 
72
68
  public readonly stateUpdate = new Event();
73
69
 
74
- constructor(params: IdentityParams) {
70
+ constructor(params: IdentityProps) {
75
71
  this.space = params.space;
76
72
  this._signer = params.signer;
77
73
  this._presence = params.presence;
@@ -91,10 +87,6 @@ export class Identity {
91
87
  identityKey: this.identityKey,
92
88
  onUpdate: () => this.stateUpdate.emit(),
93
89
  });
94
- this._defaultSpaceStateMachine = new DefaultSpaceStateMachine({
95
- identityKey: this.identityKey,
96
- onUpdate: () => this.stateUpdate.emit(),
97
- });
98
90
 
99
91
  this.authVerifier = new TrustedKeySetAuthVerifier({
100
92
  trustedKeysProvider: () => new ComplexSet(PublicKey.hash, this.authorizedDeviceKeys.keys()),
@@ -112,32 +104,26 @@ export class Identity {
112
104
  return this._deviceStateMachine.authorizedDeviceKeys;
113
105
  }
114
106
 
115
- get defaultSpaceId(): SpaceId | undefined {
116
- return this._defaultSpaceStateMachine.spaceId;
117
- }
118
-
119
- @trace.span()
120
- async open(ctx: Context): Promise<void> {
107
+ @trace.span({ op: 'lifecycle' })
108
+ async open(ctx: DxosContext): Promise<void> {
121
109
  await this._presence?.open();
122
110
  await this.space.spaceState.addCredentialProcessor(this._deviceStateMachine);
123
111
  await this.space.spaceState.addCredentialProcessor(this._profileStateMachine);
124
- await this.space.spaceState.addCredentialProcessor(this._defaultSpaceStateMachine);
125
112
  if (this._edgeFeedReplicator) {
126
113
  this.space.protocol.feedAdded.append(this._onFeedAdded);
127
114
  }
128
115
  await this.space.open(ctx);
129
116
  }
130
117
 
131
- public async joinNetwork(): Promise<void> {
132
- await this.space.startProtocol();
118
+ public async joinNetwork(ctx: DxosContext): Promise<void> {
119
+ await this.space.startProtocol(ctx);
133
120
  await this._edgeFeedReplicator?.open();
134
121
  }
135
122
 
136
- @trace.span()
137
- async close(ctx: Context): Promise<void> {
123
+ @trace.span({ op: 'lifecycle' })
124
+ async close(ctx: DxosContext): Promise<void> {
138
125
  await this._presence?.close();
139
126
  await this.authVerifier.close();
140
- await this.space.spaceState.removeCredentialProcessor(this._defaultSpaceStateMachine);
141
127
  await this.space.spaceState.removeCredentialProcessor(this._profileStateMachine);
142
128
  await this.space.spaceState.removeCredentialProcessor(this._deviceStateMachine);
143
129
 
@@ -147,7 +133,7 @@ export class Identity {
147
133
 
148
134
  await this._edgeFeedReplicator?.close();
149
135
 
150
- await this.space.close();
136
+ await this.space.close(ctx);
151
137
  }
152
138
 
153
139
  async ready(): Promise<void> {
@@ -211,15 +197,6 @@ export class Identity {
211
197
  return createCredentialSignerWithKey(this._signer, this.deviceKey);
212
198
  }
213
199
 
214
- async updateDefaultSpace(spaceId: SpaceId): Promise<void> {
215
- const credential = await this.getDeviceCredentialSigner().createCredential({
216
- subject: this.identityKey,
217
- assertion: { '@type': 'dxos.halo.credentials.DefaultSpace', spaceId },
218
- });
219
- const receipt = await this.controlPipeline.writer.write({ credential: { credential } });
220
- await this.controlPipeline.state.waitUntilTimeframe(new Timeframe([[receipt.feedKey, receipt.seq]]));
221
- }
222
-
223
200
  async admitDevice({ deviceKey, controlFeedKey, dataFeedKey }: DeviceAdmissionRequest): Promise<Credential> {
224
201
  log('Admitting device:', {
225
202
  identityKey: this.identityKey,
@@ -2,11 +2,12 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ import { type Context } from '@dxos/context';
5
6
  import { getCredentialAssertion } from '@dxos/credentials';
6
7
  import { invariant } from '@dxos/invariant';
7
8
  import { type Keyring } from '@dxos/keyring';
8
9
  import { type PublicKey } from '@dxos/keys';
9
- import { AlreadyJoinedError, type ApiError } from '@dxos/protocols';
10
+ import { AlreadyJoinedError } from '@dxos/protocols';
10
11
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
11
12
  import type { DeviceProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
12
13
  import {
@@ -15,15 +16,14 @@ import {
15
16
  type IntroductionRequest,
16
17
  } from '@dxos/protocols/proto/dxos/halo/invitations';
17
18
 
18
- import { type Identity, type JoinIdentityParams } from '../identity';
19
-
19
+ import { type Identity, type JoinIdentityProps } from '../identity';
20
20
  import { type InvitationProtocol } from './invitation-protocol';
21
21
 
22
22
  export class DeviceInvitationProtocol implements InvitationProtocol {
23
23
  constructor(
24
24
  private readonly _keyring: Keyring,
25
25
  private readonly _getIdentity: () => Identity,
26
- private readonly _acceptIdentity: (identity: JoinIdentityParams) => Promise<Identity>,
26
+ private readonly _acceptIdentity: (identity: JoinIdentityProps) => Promise<Identity>,
27
27
  ) {}
28
28
 
29
29
  toJSON(): object {
@@ -32,7 +32,7 @@ export class DeviceInvitationProtocol implements InvitationProtocol {
32
32
  };
33
33
  }
34
34
 
35
- checkCanInviteNewMembers(): ApiError | undefined {
35
+ checkCanInviteNewMembers(): Error | undefined {
36
36
  return undefined;
37
37
  }
38
38
 
@@ -71,7 +71,7 @@ export class DeviceInvitationProtocol implements InvitationProtocol {
71
71
  try {
72
72
  const identity = this._getIdentity();
73
73
  if (identity) {
74
- return new AlreadyJoinedError('Currently only one identity per client is supported.');
74
+ return new AlreadyJoinedError({ message: 'Currently only one identity per client is supported.' });
75
75
  }
76
76
  } catch {
77
77
  // No identity.
@@ -97,7 +97,7 @@ export class DeviceInvitationProtocol implements InvitationProtocol {
97
97
  };
98
98
  }
99
99
 
100
- async accept(response: AdmissionResponse, request: AdmissionRequest): Promise<Partial<Invitation>> {
100
+ async accept(_ctx: Context, response: AdmissionResponse, request: AdmissionRequest): Promise<Partial<Invitation>> {
101
101
  invariant(response.device);
102
102
  const { identityKey, haloSpaceKey, genesisFeedKey, controlTimeframe } = response.device;
103
103
 
@@ -105,6 +105,7 @@ export class DeviceInvitationProtocol implements InvitationProtocol {
105
105
  const { deviceKey, controlFeedKey, dataFeedKey, profile } = request.device;
106
106
 
107
107
  // TODO(wittjosiah): When multiple identities are supported, verify identity doesn't already exist before accepting.
108
+ // ctx is unused here because _acceptIdentity uses ServiceContext's lifecycle ctx internally.
108
109
 
109
110
  await this._acceptIdentity({
110
111
  identityKey,
@@ -23,13 +23,14 @@ import {
23
23
  type AdmissionResponse,
24
24
  type SpaceAdmissionRequest,
25
25
  } from '@dxos/protocols/proto/dxos/halo/invitations';
26
+ import { trace } from '@dxos/tracing';
26
27
 
27
28
  import { type InvitationProtocol } from './invitation-protocol';
28
29
  import { type FlowLockHolder, type GuardedInvitationState } from './invitation-state';
29
30
  import { tryAcquireBeforeContextDisposed } from './utils';
30
31
 
31
32
  export interface EdgeInvitationHandlerCallbacks {
32
- onInvitationSuccess(response: AdmissionResponse, request: AdmissionRequest): Promise<void>;
33
+ onInvitationSuccess(ctx: Context, response: AdmissionResponse, request: AdmissionRequest): Promise<void>;
33
34
  }
34
35
 
35
36
  export const MAX_RETRIES_PER_INVITATION = 5;
@@ -41,6 +42,7 @@ export type EdgeInvitationConfig = {
41
42
  retryJitter?: number;
42
43
  };
43
44
 
45
+ @trace.resource()
44
46
  export class EdgeInvitationHandler implements FlowLockHolder {
45
47
  private _flowLock: MutexGuard | undefined;
46
48
 
@@ -113,6 +115,7 @@ export class EdgeInvitationHandler implements FlowLockHolder {
113
115
  scheduleMicroTask(ctx, tryHandleInvitation);
114
116
  }
115
117
 
118
+ @trace.span({ op: 'invitation.edge' })
116
119
  private async _handleSpaceInvitationFlow(
117
120
  ctx: Context,
118
121
  guardedState: GuardedInvitationState,
@@ -126,13 +129,13 @@ export class EdgeInvitationHandler implements FlowLockHolder {
126
129
 
127
130
  guardedState.set(this, Invitation.State.CONNECTING);
128
131
 
129
- const response = await this._joinSpaceByInvitation(guardedState, spaceId, {
132
+ const response = await this._joinSpaceByInvitation(ctx, guardedState, spaceId, {
130
133
  identityKey: admissionRequest.identityKey.toHex(),
131
134
  invitationId: guardedState.current.invitationId,
132
135
  });
133
136
 
134
137
  const admissionResponse = await this._mapToAdmissionResponse(response);
135
- await this._callbacks.onInvitationSuccess(admissionResponse, { space: admissionRequest });
138
+ await this._callbacks.onInvitationSuccess(ctx, admissionResponse, { space: admissionRequest });
136
139
  } catch (error) {
137
140
  guardedState.set(this, Invitation.State.ERROR);
138
141
  throw error;
@@ -153,13 +156,14 @@ export class EdgeInvitationHandler implements FlowLockHolder {
153
156
  }
154
157
 
155
158
  private async _joinSpaceByInvitation(
159
+ ctx: Context,
156
160
  guardedState: GuardedInvitationState,
157
161
  spaceId: SpaceId,
158
162
  request: JoinSpaceRequest,
159
163
  ): Promise<JoinSpaceResponseBody> {
160
164
  invariant(this._client);
161
165
  try {
162
- return await this._client.joinSpaceByInvitation(spaceId, request);
166
+ return await this._client.joinSpaceByInvitation(ctx, spaceId, request);
163
167
  } catch (error: any) {
164
168
  if (error instanceof EdgeAuthChallengeError) {
165
169
  const publicKey = guardedState.current.guestKeypair?.publicKey;
@@ -168,7 +172,7 @@ export class EdgeInvitationHandler implements FlowLockHolder {
168
172
  throw error;
169
173
  }
170
174
  const signature = sign(Buffer.from(error.challenge, 'base64'), privateKey);
171
- return this._client.joinSpaceByInvitation(spaceId, {
175
+ return this._client.joinSpaceByInvitation(ctx, spaceId, {
172
176
  ...request,
173
177
  signature: Buffer.from(signature).toString('base64'),
174
178
  });
@@ -97,10 +97,12 @@ export class InvitationGuestExtension
97
97
  await cancelWithContext(this._ctx, this._remoteOptionsTrigger.wait({ timeout: OPTIONS_TIMEOUT }));
98
98
  log.verbose('options received');
99
99
  if (this._remoteOptions?.role !== InvitationOptions.Role.HOST) {
100
- throw new InvalidInvitationExtensionRoleError(undefined, {
101
- expected: InvitationOptions.Role.HOST,
102
- remoteOptions: this._remoteOptions,
103
- remotePeerId: context.remotePeerId,
100
+ throw new InvalidInvitationExtensionRoleError({
101
+ context: {
102
+ expected: InvitationOptions.Role.HOST,
103
+ remoteOptions: this._remoteOptions,
104
+ remotePeerId: context.remotePeerId,
105
+ },
104
106
  });
105
107
  }
106
108
 
@@ -8,7 +8,7 @@ import { randomBytes, verify } from '@dxos/crypto';
8
8
  import { InvariantViolation, invariant } from '@dxos/invariant';
9
9
  import { PublicKey } from '@dxos/keys';
10
10
  import { log } from '@dxos/log';
11
- import { InvalidInvitationExtensionRoleError, trace } from '@dxos/protocols';
11
+ import { InvalidInvitationExtensionRoleError } from '@dxos/protocols';
12
12
  import { schema } from '@dxos/protocols/proto';
13
13
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
14
14
  import { type ProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
@@ -110,8 +110,7 @@ export class InvitationHostExtension
110
110
 
111
111
  introduce: async (request) => {
112
112
  const { profile, invitationId } = request;
113
- const traceId = PublicKey.random().toHex();
114
- log.trace('dxos.sdk.invitation-handler.host.introduce', trace.begin({ id: traceId }));
113
+ log('introducing host invitation');
115
114
 
116
115
  const invitation = this._requireActiveInvitation();
117
116
  this._assertInvitationState(Invitation.State.CONNECTED);
@@ -131,7 +130,7 @@ export class InvitationHostExtension
131
130
  this._challenge =
132
131
  invitation.authMethod === Invitation.AuthMethod.KNOWN_PUBLIC_KEY ? randomBytes(32) : undefined;
133
132
 
134
- log.trace('dxos.sdk.invitation-handler.host.introduce', trace.end({ id: traceId }));
133
+ log('introduced host invitation');
135
134
  return {
136
135
  authMethod: invitation.authMethod,
137
136
  challenge: this._challenge,
@@ -139,8 +138,7 @@ export class InvitationHostExtension
139
138
  },
140
139
 
141
140
  authenticate: async ({ authCode: code, signedChallenge }) => {
142
- const traceId = PublicKey.random().toHex();
143
- log.trace('dxos.sdk.invitation-handler.host.authenticate', trace.begin({ id: traceId }));
141
+ log('authenticating host invitation');
144
142
 
145
143
  const invitation = this._requireActiveInvitation();
146
144
  log.verbose('received authentication request', { authCode: code });
@@ -201,13 +199,12 @@ export class InvitationHostExtension
201
199
  return { status };
202
200
  }
203
201
 
204
- log.trace('dxos.sdk.invitation-handler.host.authenticate', trace.end({ id: traceId, data: { status } }));
202
+ log('authenticated host invitation', { status });
205
203
  return { status };
206
204
  },
207
205
 
208
206
  admit: async (request) => {
209
- const traceId = PublicKey.random().toHex();
210
- log.trace('dxos.sdk.invitation-handler.host.admit', trace.begin({ id: traceId }));
207
+ log('admitting guest');
211
208
  const invitation = this._requireActiveInvitation();
212
209
 
213
210
  try {
@@ -221,7 +218,7 @@ export class InvitationHostExtension
221
218
 
222
219
  const response = await this._callbacks.admit(request);
223
220
 
224
- log.trace('dxos.sdk.invitation-handler.host.admit', trace.end({ id: traceId }));
221
+ log('admitted guest');
225
222
  return response;
226
223
  } catch (err: any) {
227
224
  this._callbacks.onError(err);
@@ -245,10 +242,12 @@ export class InvitationHostExtension
245
242
  await cancelWithContext(this._ctx, this._remoteOptionsTrigger.wait({ timeout: OPTIONS_TIMEOUT }));
246
243
  log.verbose('options received');
247
244
  if (this._remoteOptions?.role !== InvitationOptions.Role.GUEST) {
248
- throw new InvalidInvitationExtensionRoleError(undefined, {
249
- expected: InvitationOptions.Role.GUEST,
250
- remoteOptions: this._remoteOptions,
251
- remotePeerId: context.remotePeerId,
245
+ throw new InvalidInvitationExtensionRoleError({
246
+ context: {
247
+ expected: InvitationOptions.Role.GUEST,
248
+ remoteOptions: this._remoteOptions,
249
+ remotePeerId: context.remotePeerId,
250
+ },
252
251
  });
253
252
  }
254
253
  this._callbacks.onStateUpdate(Invitation.State.CONNECTED);
@@ -2,8 +2,8 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ import { type Context } from '@dxos/context';
5
6
  import { type PublicKey } from '@dxos/keys';
6
- import type { ApiError } from '@dxos/protocols';
7
7
  import type { Invitation } from '@dxos/protocols/proto/dxos/client/services';
8
8
  import type { DeviceProfileDocument, ProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
9
9
  import type {
@@ -26,7 +26,7 @@ export interface InvitationProtocol {
26
26
  // Host
27
27
  //
28
28
 
29
- checkCanInviteNewMembers(): ApiError | undefined;
29
+ checkCanInviteNewMembers(): Error | undefined;
30
30
 
31
31
  /**
32
32
  * Protocol-specific information to include in the invitation.
@@ -58,7 +58,7 @@ export interface InvitationProtocol {
58
58
  *
59
59
  * For example, the guest may already be a member of the space.
60
60
  */
61
- checkInvitation(invitation: Partial<Invitation>): ApiError | undefined;
61
+ checkInvitation(invitation: Partial<Invitation>): Error | undefined;
62
62
 
63
63
  /**
64
64
  * Get profile information to send to the host to identify the guest.
@@ -72,6 +72,9 @@ export interface InvitationProtocol {
72
72
 
73
73
  /**
74
74
  * Redeem the admission credential.
75
+ * @param ctx - Caller context used for tracing and cancellation. Forwarded to downstream
76
+ * internal methods (e.g. `DataSpaceManager.acceptSpace`) so their spans become children of
77
+ * the invitation flow span.
75
78
  */
76
- accept(response: AdmissionResponse, request: AdmissionRequest): Promise<Partial<Invitation>>;
79
+ accept(ctx: Context, response: AdmissionResponse, request: AdmissionRequest): Promise<Partial<Invitation>>;
77
80
  }
@@ -31,12 +31,6 @@ export const createGuardedInvitationState = (
31
31
  invitation: Invitation,
32
32
  stream: PushStream<Invitation>,
33
33
  ): GuardedInvitationState => {
34
- // the mutex guards invitation flow on host and guest side, making sure only one flow is currently active
35
- // deadlocks seem very unlikely because hosts don't initiate multiple connections
36
- // even if this somehow happens that there are 2 guests (A, B) and 2 hosts (1, 2) and:
37
- // A has lock for flow with 1, B has lock for flow with 2
38
- // 1 has lock for flow with B, 2 has lock for flow with A
39
- // there'll be a 10-second introduction timeout after which connection will be closed and deadlock broken
40
34
  const mutex = new Mutex();
41
35
  let lastActiveLockHolder: FlowLockHolder | null = null;
42
36
  let currentInvitation = { ...invitation };
@@ -44,9 +38,6 @@ export const createGuardedInvitationState = (
44
38
  if (ctx.disposed || (lockHolder !== null && mutex.isLocked() && !lockHolder.hasFlowLock())) {
45
39
  return false;
46
40
  }
47
- // don't allow transitions from a terminal state unless a new extension acquired mutex
48
- // handles a case when error occurs (e.g. connection is closed) after we completed the flow
49
- // successfully or already reported another error
50
41
  return lockHolder == null || lastActiveLockHolder !== lockHolder || isNonTerminalState(currentInvitation.state);
51
42
  };
52
43
  return {
@@ -54,7 +45,6 @@ export const createGuardedInvitationState = (
54
45
  get current() {
55
46
  return currentInvitation;
56
47
  },
57
- // disposing context prevents any further state updates
58
48
  complete: (newState: Partial<Invitation>) => {
59
49
  logStateUpdate(currentInvitation, undefined, invitation.state);
60
50
  currentInvitation = { ...currentInvitation, ...newState };
@@ -94,11 +84,7 @@ const logStateUpdate = (invitation: Invitation, actor: any, newState: Invitation
94
84
  error: error?.message,
95
85
  errorStack: error?.stack,
96
86
  };
97
- if (isNonTerminalState(newState)) {
98
- log.verbose('dxos.sdk.invitations-handler.state.update', logContext);
99
- } else {
100
- log.info('dxos.sdk.invitations-handler.state.update', logContext);
101
- }
87
+ log.verbose('dxos.sdk.invitations-handler.state.update', logContext);
102
88
  };
103
89
 
104
90
  const isNonTerminalState = (currentState: Invitation.State): boolean => {