@dxos/client-services 0.8.4-main.bc674ce → 0.8.4-main.bcb3aa67d6

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 (113) hide show
  1. package/dist/lib/browser/{chunk-J33W6T4Q.mjs → chunk-5A3KX2RY.mjs} +1745 -1208
  2. package/dist/lib/browser/chunk-5A3KX2RY.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +33 -16
  4. package/dist/lib/browser/index.mjs.map +3 -3
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/testing/index.mjs +14 -7
  7. package/dist/lib/browser/testing/index.mjs.map +3 -3
  8. package/dist/lib/node-esm/{chunk-34HKLADW.mjs → chunk-FNPO5UMU.mjs} +1745 -1208
  9. package/dist/lib/node-esm/chunk-FNPO5UMU.mjs.map +7 -0
  10. package/dist/lib/node-esm/index.mjs +33 -16
  11. package/dist/lib/node-esm/index.mjs.map +3 -3
  12. package/dist/lib/node-esm/meta.json +1 -1
  13. package/dist/lib/node-esm/testing/index.mjs +14 -7
  14. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  15. package/dist/types/src/index.d.ts +1 -0
  16. package/dist/types/src/index.d.ts.map +1 -1
  17. package/dist/types/src/packlets/agents/edge-agent-manager.d.ts +3 -2
  18. package/dist/types/src/packlets/agents/edge-agent-manager.d.ts.map +1 -1
  19. package/dist/types/src/packlets/identity/identity-manager.d.ts +3 -3
  20. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  21. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +5 -4
  22. package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
  23. package/dist/types/src/packlets/identity/identity-service.d.ts +1 -6
  24. package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
  25. package/dist/types/src/packlets/identity/identity.d.ts +6 -9
  26. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  27. package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts.map +1 -1
  28. package/dist/types/src/packlets/invitations/invitations-manager.d.ts +3 -3
  29. package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -1
  30. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
  31. package/dist/types/src/packlets/logging/logging-service.d.ts +4 -0
  32. package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
  33. package/dist/types/src/packlets/network/network-service.d.ts.map +1 -1
  34. package/dist/types/src/packlets/services/feed-syncer.d.ts +59 -0
  35. package/dist/types/src/packlets/services/feed-syncer.d.ts.map +1 -0
  36. package/dist/types/src/packlets/services/feed-syncer.test.d.ts +2 -0
  37. package/dist/types/src/packlets/services/feed-syncer.test.d.ts.map +1 -0
  38. package/dist/types/src/packlets/services/platform.d.ts.map +1 -1
  39. package/dist/types/src/packlets/services/service-context.d.ts +3 -4
  40. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  41. package/dist/types/src/packlets/services/service-host.d.ts +1 -1
  42. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  43. package/dist/types/src/packlets/space-export/space-archive-reader.d.ts +9 -1
  44. package/dist/types/src/packlets/space-export/space-archive-reader.d.ts.map +1 -1
  45. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts +6 -0
  46. package/dist/types/src/packlets/space-export/space-archive-writer.d.ts.map +1 -1
  47. package/dist/types/src/packlets/space-export/space-archive.test.d.ts +2 -0
  48. package/dist/types/src/packlets/space-export/space-archive.test.d.ts.map +1 -0
  49. package/dist/types/src/packlets/spaces/data-space-manager.d.ts +17 -10
  50. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  51. package/dist/types/src/packlets/spaces/data-space.d.ts +22 -6
  52. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  53. package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
  54. package/dist/types/src/packlets/spaces/genesis.d.ts +2 -1
  55. package/dist/types/src/packlets/spaces/genesis.d.ts.map +1 -1
  56. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
  57. package/dist/types/src/packlets/spaces/spaces-service.d.ts +2 -2
  58. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  59. package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
  60. package/dist/types/src/packlets/worker/worker-runtime.d.ts +11 -3
  61. package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
  62. package/dist/types/src/version.d.ts +1 -1
  63. package/dist/types/src/version.d.ts.map +1 -1
  64. package/dist/types/tsconfig.tsbuildinfo +1 -1
  65. package/package.json +43 -43
  66. package/src/index.ts +1 -0
  67. package/src/packlets/agents/edge-agent-manager.ts +8 -5
  68. package/src/packlets/agents/edge-agent-service.ts +2 -2
  69. package/src/packlets/identity/identity-manager.test.ts +5 -5
  70. package/src/packlets/identity/identity-manager.ts +16 -13
  71. package/src/packlets/identity/identity-recovery-manager.ts +20 -16
  72. package/src/packlets/identity/identity-service.test.ts +6 -26
  73. package/src/packlets/identity/identity-service.ts +5 -76
  74. package/src/packlets/identity/identity.test.ts +2 -2
  75. package/src/packlets/identity/identity.ts +7 -29
  76. package/src/packlets/invitations/edge-invitation-handler.ts +4 -3
  77. package/src/packlets/invitations/invitations-handler.test.ts +4 -4
  78. package/src/packlets/invitations/invitations-handler.ts +3 -3
  79. package/src/packlets/invitations/invitations-manager.ts +37 -14
  80. package/src/packlets/invitations/invitations-service.ts +4 -4
  81. package/src/packlets/invitations/space-invitation-protocol.test.ts +17 -16
  82. package/src/packlets/invitations/space-invitation-protocol.ts +3 -1
  83. package/src/packlets/logging/logging-service.ts +4 -0
  84. package/src/packlets/network/network-service.ts +5 -4
  85. package/src/packlets/services/feed-syncer.test.ts +340 -0
  86. package/src/packlets/services/feed-syncer.ts +337 -0
  87. package/src/packlets/services/platform.ts +7 -1
  88. package/src/packlets/services/service-context.test.ts +3 -2
  89. package/src/packlets/services/service-context.ts +106 -31
  90. package/src/packlets/services/service-host.test.ts +8 -7
  91. package/src/packlets/services/service-host.ts +9 -7
  92. package/src/packlets/space-export/space-archive-reader.ts +64 -3
  93. package/src/packlets/space-export/space-archive-writer.ts +36 -1
  94. package/src/packlets/space-export/space-archive.test.ts +287 -0
  95. package/src/packlets/spaces/data-space-manager.test.ts +79 -13
  96. package/src/packlets/spaces/data-space-manager.ts +71 -103
  97. package/src/packlets/spaces/data-space.ts +46 -23
  98. package/src/packlets/spaces/edge-feed-replicator.test.ts +1 -1
  99. package/src/packlets/spaces/edge-feed-replicator.ts +8 -7
  100. package/src/packlets/spaces/epoch-migrations.ts +3 -3
  101. package/src/packlets/spaces/genesis.ts +6 -1
  102. package/src/packlets/spaces/notarization-plugin.ts +2 -1
  103. package/src/packlets/spaces/spaces-service.test.ts +9 -6
  104. package/src/packlets/spaces/spaces-service.ts +30 -8
  105. package/src/packlets/testing/invitation-utils.ts +3 -2
  106. package/src/packlets/worker/worker-runtime.ts +14 -6
  107. package/src/packlets/worker/worker-session.ts +4 -4
  108. package/src/version.ts +1 -1
  109. package/dist/lib/browser/chunk-J33W6T4Q.mjs.map +0 -7
  110. package/dist/lib/node-esm/chunk-34HKLADW.mjs.map +0 -7
  111. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts +0 -19
  112. package/dist/types/src/packlets/identity/default-space-state-machine.d.ts.map +0 -1
  113. package/src/packlets/identity/default-space-state-machine.ts +0 -44
@@ -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,14 +29,12 @@ 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
36
 
38
37
  import { TrustedKeySetAuthVerifier } from './authenticator';
39
- import { DefaultSpaceStateMachine } from './default-space-state-machine';
40
38
 
41
39
  export type IdentityProps = {
42
40
  did: IdentityDid;
@@ -60,7 +58,6 @@ export class Identity {
60
58
  private readonly _presence?: Presence;
61
59
  private readonly _deviceStateMachine: DeviceStateMachine;
62
60
  private readonly _profileStateMachine: ProfileStateMachine;
63
- private readonly _defaultSpaceStateMachine: DefaultSpaceStateMachine;
64
61
  private readonly _edgeFeedReplicator?: EdgeFeedReplicator = undefined;
65
62
 
66
63
  public readonly authVerifier: TrustedKeySetAuthVerifier;
@@ -91,10 +88,6 @@ export class Identity {
91
88
  identityKey: this.identityKey,
92
89
  onUpdate: () => this.stateUpdate.emit(),
93
90
  });
94
- this._defaultSpaceStateMachine = new DefaultSpaceStateMachine({
95
- identityKey: this.identityKey,
96
- onUpdate: () => this.stateUpdate.emit(),
97
- });
98
91
 
99
92
  this.authVerifier = new TrustedKeySetAuthVerifier({
100
93
  trustedKeysProvider: () => new ComplexSet(PublicKey.hash, this.authorizedDeviceKeys.keys()),
@@ -112,32 +105,26 @@ export class Identity {
112
105
  return this._deviceStateMachine.authorizedDeviceKeys;
113
106
  }
114
107
 
115
- get defaultSpaceId(): SpaceId | undefined {
116
- return this._defaultSpaceStateMachine.spaceId;
117
- }
118
-
119
108
  @trace.span()
120
- async open(ctx: Context): Promise<void> {
109
+ async open(ctx: DxosContext): Promise<void> {
121
110
  await this._presence?.open();
122
111
  await this.space.spaceState.addCredentialProcessor(this._deviceStateMachine);
123
112
  await this.space.spaceState.addCredentialProcessor(this._profileStateMachine);
124
- await this.space.spaceState.addCredentialProcessor(this._defaultSpaceStateMachine);
125
113
  if (this._edgeFeedReplicator) {
126
114
  this.space.protocol.feedAdded.append(this._onFeedAdded);
127
115
  }
128
116
  await this.space.open(ctx);
129
117
  }
130
118
 
131
- public async joinNetwork(): Promise<void> {
132
- await this.space.startProtocol();
119
+ public async joinNetwork(ctx: DxosContext): Promise<void> {
120
+ await this.space.startProtocol(ctx);
133
121
  await this._edgeFeedReplicator?.open();
134
122
  }
135
123
 
136
124
  @trace.span()
137
- async close(ctx: Context): Promise<void> {
125
+ async close(ctx: DxosContext): Promise<void> {
138
126
  await this._presence?.close();
139
127
  await this.authVerifier.close();
140
- await this.space.spaceState.removeCredentialProcessor(this._defaultSpaceStateMachine);
141
128
  await this.space.spaceState.removeCredentialProcessor(this._profileStateMachine);
142
129
  await this.space.spaceState.removeCredentialProcessor(this._deviceStateMachine);
143
130
 
@@ -147,7 +134,7 @@ export class Identity {
147
134
 
148
135
  await this._edgeFeedReplicator?.close();
149
136
 
150
- await this.space.close();
137
+ await this.space.close(ctx);
151
138
  }
152
139
 
153
140
  async ready(): Promise<void> {
@@ -211,15 +198,6 @@ export class Identity {
211
198
  return createCredentialSignerWithKey(this._signer, this.deviceKey);
212
199
  }
213
200
 
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
201
  async admitDevice({ deviceKey, controlFeedKey, dataFeedKey }: DeviceAdmissionRequest): Promise<Credential> {
224
202
  log('Admitting device:', {
225
203
  identityKey: this.identityKey,
@@ -126,7 +126,7 @@ export class EdgeInvitationHandler implements FlowLockHolder {
126
126
 
127
127
  guardedState.set(this, Invitation.State.CONNECTING);
128
128
 
129
- const response = await this._joinSpaceByInvitation(guardedState, spaceId, {
129
+ const response = await this._joinSpaceByInvitation(ctx, guardedState, spaceId, {
130
130
  identityKey: admissionRequest.identityKey.toHex(),
131
131
  invitationId: guardedState.current.invitationId,
132
132
  });
@@ -153,13 +153,14 @@ export class EdgeInvitationHandler implements FlowLockHolder {
153
153
  }
154
154
 
155
155
  private async _joinSpaceByInvitation(
156
+ ctx: Context,
156
157
  guardedState: GuardedInvitationState,
157
158
  spaceId: SpaceId,
158
159
  request: JoinSpaceRequest,
159
160
  ): Promise<JoinSpaceResponseBody> {
160
161
  invariant(this._client);
161
162
  try {
162
- return await this._client.joinSpaceByInvitation(spaceId, request);
163
+ return await this._client.joinSpaceByInvitation(ctx, spaceId, request);
163
164
  } catch (error: any) {
164
165
  if (error instanceof EdgeAuthChallengeError) {
165
166
  const publicKey = guardedState.current.guestKeypair?.publicKey;
@@ -168,7 +169,7 @@ export class EdgeInvitationHandler implements FlowLockHolder {
168
169
  throw error;
169
170
  }
170
171
  const signature = sign(Buffer.from(error.challenge, 'base64'), privateKey);
171
- return this._client.joinSpaceByInvitation(spaceId, {
172
+ return this._client.joinSpaceByInvitation(ctx, spaceId, {
172
173
  ...request,
173
174
  signature: Buffer.from(signature).toString('base64'),
174
175
  });
@@ -95,7 +95,7 @@ describe.skipIf(process.env.CI && !process.env.RUN_FLAKY_TESTS)(
95
95
  await acceptInvitation(guest, invitation);
96
96
 
97
97
  await guest.sink.waitFor(Invitation.State.READY_FOR_AUTHENTICATION);
98
- await guest.peer.networkManager.close();
98
+ await guest.peer.networkManager.close(Context.default());
99
99
  await host.sink.waitFor(Invitation.State.CONNECTING);
100
100
 
101
101
  await sleep(10);
@@ -254,9 +254,9 @@ describe.skipIf(process.env.CI && !process.env.RUN_FLAKY_TESTS)(
254
254
  const peer = testBuilder.createPeer();
255
255
  await peer.createIdentity();
256
256
  await openAndClose(peer.echoHost, peer.dataSpaceManager);
257
- await peer.echoHost.addReplicator(peer.meshEchoReplicator);
257
+ await peer.echoHost.addReplicator(Context.default(), peer.meshEchoReplicator);
258
258
  if (spaceKey == null) {
259
- const space = await peer.dataSpaceManager.createSpace();
259
+ const space = await peer.dataSpaceManager.createSpace(new Context());
260
260
  spaceKey = space.key;
261
261
  }
262
262
  const invitationHandler = new InvitationsHandler(peer.networkManager, undefined, {
@@ -359,7 +359,7 @@ describe.skipIf(process.env.CI && !process.env.RUN_FLAKY_TESTS)(
359
359
  };
360
360
 
361
361
  const createInvitation = async (setup: PeerSetup, options?: Partial<Invitation>): Promise<Invitation> => {
362
- const observable = await setup.peer.invitationsManager.createInvitation({
362
+ const observable = await setup.peer.invitationsManager.createInvitation(setup.ctx, {
363
363
  type: Invitation.Type.DELEGATED,
364
364
  kind: Invitation.Kind.SPACE,
365
365
  authMethod: Invitation.AuthMethod.SHARED_SECRET,
@@ -200,7 +200,7 @@ export class InvitationsHandler {
200
200
  ctx,
201
201
  async () => {
202
202
  // ensure the swarm is closed before changing state and closing the stream.
203
- await swarmConnection.close();
203
+ await swarmConnection.close(ctx);
204
204
  guardedState.set(null, Invitation.State.EXPIRED);
205
205
  metrics.increment('dxos.invitation.expired');
206
206
  await ctx.dispose();
@@ -436,7 +436,7 @@ export class InvitationsHandler {
436
436
  } else {
437
437
  label = `invitation host for space ${invitation.spaceKey?.truncate()}`;
438
438
  }
439
- const swarmConnection = await this._networkManager.joinSwarm({
439
+ const swarmConnection = await this._networkManager.joinSwarm(ctx, {
440
440
  topic: invitation.swarmKey,
441
441
  protocolProvider: createTeleportProtocolFactory(async (teleport) => {
442
442
  teleport.addExtension('dxos.halo.invitations', extensionFactory());
@@ -444,7 +444,7 @@ export class InvitationsHandler {
444
444
  topology: new InvitationTopology(role),
445
445
  label,
446
446
  });
447
- ctx.onDispose(() => swarmConnection.close());
447
+ ctx.onDispose(() => swarmConnection.close(ctx));
448
448
  return swarmConnection;
449
449
  }
450
450
 
@@ -21,6 +21,7 @@ import {
21
21
  Invitation,
22
22
  } from '@dxos/protocols/proto/dxos/client/services';
23
23
  import { SpaceMember } from '@dxos/protocols/proto/dxos/halo/credentials';
24
+ import { trace } from '@dxos/tracing';
24
25
 
25
26
  import type { InvitationProtocol } from './invitation-protocol';
26
27
  import { type InvitationsHandler, createAdmissionKeypair } from './invitations-handler';
@@ -29,6 +30,7 @@ import { type InvitationsHandler, createAdmissionKeypair } from './invitations-h
29
30
  * Entry point for creating and accepting invitations, keeps track of existing invitation set and
30
31
  * emits events when the set changes.
31
32
  */
33
+ @trace.resource()
32
34
  export class InvitationsManager {
33
35
  private readonly _createInvitations = new Map<string, CancellableInvitation>();
34
36
  private readonly _acceptInvitations = new Map<string, AuthenticatingInvitation>();
@@ -48,7 +50,11 @@ export class InvitationsManager {
48
50
  private readonly _metadataStore: MetadataStore,
49
51
  ) {}
50
52
 
51
- async createInvitation(options: Partial<Invitation> & Pick<Invitation, 'kind'>): Promise<CancellableInvitation> {
53
+ @trace.span({ showInBrowserTimeline: true })
54
+ async createInvitation(
55
+ ctx: Context,
56
+ options: Partial<Invitation> & Pick<Invitation, 'kind'>,
57
+ ): Promise<CancellableInvitation> {
52
58
  if (options.invitationId) {
53
59
  const existingInvitation = this._createInvitations.get(options.invitationId);
54
60
  if (existingInvitation) {
@@ -63,7 +69,11 @@ export class InvitationsManager {
63
69
  }
64
70
  const invitation = this._createInvitation(handler, options);
65
71
 
66
- const { ctx, stream, observableInvitation } = this._createObservableInvitation(handler, invitation);
72
+ const {
73
+ ctx: invitationCtx,
74
+ stream,
75
+ observableInvitation,
76
+ } = this._createObservableInvitation(ctx, handler, invitation);
67
77
 
68
78
  this._createInvitations.set(invitation.invitationId, observableInvitation);
69
79
  this.invitationCreated.emit(invitation);
@@ -84,12 +94,12 @@ export class InvitationsManager {
84
94
  return observableInvitation;
85
95
  }
86
96
 
87
- this._invitationsHandler.handleInvitationFlow(ctx, stream, handler, observableInvitation.get());
97
+ this._invitationsHandler.handleInvitationFlow(invitationCtx, stream, handler, observableInvitation.get());
88
98
 
89
99
  return observableInvitation;
90
100
  }
91
101
 
92
- async loadPersistentInvitations(): Promise<{ invitations: Invitation[] }> {
102
+ async loadPersistentInvitations(ctx: Context): Promise<{ invitations: Invitation[] }> {
93
103
  if (this._persistentInvitationsLoaded) {
94
104
  const invitations = this.getCreatedInvitations().filter((i) => i.persistent);
95
105
  return { invitations };
@@ -101,7 +111,7 @@ export class InvitationsManager {
101
111
 
102
112
  const loadTasks = freshInvitations.map((persistentInvitation) => {
103
113
  invariant(!this._createInvitations.get(persistentInvitation.invitationId), 'invitation already exists');
104
- return this.createInvitation({ ...persistentInvitation, persistent: false });
114
+ return this.createInvitation(ctx, { ...persistentInvitation, persistent: false });
105
115
  });
106
116
  const cInvitations = await Promise.all(loadTasks);
107
117
 
@@ -115,7 +125,7 @@ export class InvitationsManager {
115
125
  }
116
126
  }
117
127
 
118
- acceptInvitation(request: AcceptInvitationRequest): AuthenticatingInvitation {
128
+ acceptInvitation(_ctx: Context, request: AcceptInvitationRequest): AuthenticatingInvitation {
119
129
  const options = request.invitation;
120
130
  const existingInvitation = this._acceptInvitations.get(options.invitationId);
121
131
  if (existingInvitation) {
@@ -123,8 +133,20 @@ export class InvitationsManager {
123
133
  }
124
134
 
125
135
  const handler = this._getHandler(options);
126
- const { ctx, invitation, stream, otpEnteredTrigger } = this._createObservableAcceptingInvitation(handler, options);
127
- this._invitationsHandler.acceptInvitation(ctx, stream, handler, options, otpEnteredTrigger, request.deviceProfile);
136
+ const {
137
+ ctx: invitationCtx,
138
+ invitation,
139
+ stream,
140
+ otpEnteredTrigger,
141
+ } = this._createObservableAcceptingInvitation(handler, options);
142
+ this._invitationsHandler.acceptInvitation(
143
+ invitationCtx,
144
+ stream,
145
+ handler,
146
+ options,
147
+ otpEnteredTrigger,
148
+ request.deviceProfile,
149
+ );
128
150
  this._acceptInvitations.set(invitation.get().invitationId, invitation);
129
151
  this.invitationAccepted.emit(invitation.get());
130
152
 
@@ -198,7 +220,7 @@ export class InvitationsManager {
198
220
  state = Invitation.State.INIT,
199
221
  timeout = INVITATION_TIMEOUT,
200
222
  swarmKey = PublicKey.random(),
201
- persistent = _options?.authMethod !== Invitation.AuthMethod.KNOWN_PUBLIC_KEY, // default no not storing keypairs
223
+ persistent = _options?.authMethod !== Invitation.AuthMethod.KNOWN_PUBLIC_KEY,
202
224
  created = new Date(),
203
225
  guestKeypair = undefined,
204
226
  role = SpaceMember.Role.ADMIN,
@@ -232,17 +254,18 @@ export class InvitationsManager {
232
254
  }
233
255
 
234
256
  private _createObservableInvitation(
257
+ ctx: Context,
235
258
  handler: InvitationProtocol,
236
259
  invitation: Invitation,
237
260
  ): { ctx: Context; stream: PushStream<Invitation>; observableInvitation: CancellableInvitation } {
238
261
  const stream = new PushStream<Invitation>();
239
- const ctx = new Context({
262
+ const invitationCtx = ctx.derive({
240
263
  onError: (err) => {
241
264
  stream.error(err);
242
- void ctx.dispose();
265
+ void invitationCtx.dispose();
243
266
  },
244
267
  });
245
- ctx.onDispose(() => {
268
+ invitationCtx.onDispose(() => {
246
269
  log('complete', { ...handler.toJSON() });
247
270
  stream.complete();
248
271
  });
@@ -251,10 +274,10 @@ export class InvitationsManager {
251
274
  subscriber: stream.observable,
252
275
  onCancel: async () => {
253
276
  stream.next({ ...invitation, state: Invitation.State.CANCELLED });
254
- await ctx.dispose();
277
+ await invitationCtx.dispose();
255
278
  },
256
279
  });
257
- return { ctx, stream, observableInvitation };
280
+ return { ctx: invitationCtx, stream, observableInvitation };
258
281
  }
259
282
 
260
283
  private _createObservableAcceptingInvitation(
@@ -28,9 +28,9 @@ export class InvitationsServiceImpl implements InvitationsService {
28
28
  }
29
29
 
30
30
  createInvitation(options: Invitation): Stream<Invitation> {
31
- return new Stream<Invitation>(({ next, close }) => {
31
+ return new Stream<Invitation>(({ ctx, next, close }) => {
32
32
  void this._invitationsManager
33
- .createInvitation(options)
33
+ .createInvitation(ctx, options)
34
34
  .then((invitation) => {
35
35
  trace.metrics.increment('dxos.invitation.created');
36
36
  invitation.subscribe(next, close, close);
@@ -40,8 +40,8 @@ export class InvitationsServiceImpl implements InvitationsService {
40
40
  }
41
41
 
42
42
  acceptInvitation(request: AcceptInvitationRequest): Stream<Invitation> {
43
- const invitation = this._invitationsManager.acceptInvitation(request);
44
- return new Stream<Invitation>(({ next, close }) => {
43
+ return new Stream<Invitation>(({ ctx, next, close }) => {
44
+ const invitation = this._invitationsManager.acceptInvitation(ctx, request);
45
45
  invitation.subscribe(next, close, close);
46
46
  });
47
47
  }
@@ -5,6 +5,7 @@
5
5
  import { describe, expect, onTestFinished, test } from 'vitest';
6
6
 
7
7
  import { Trigger, chain } from '@dxos/async';
8
+ import { Context } from '@dxos/context';
8
9
  import { raise } from '@dxos/debug';
9
10
  import { AlreadyJoinedError } from '@dxos/protocols';
10
11
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
@@ -24,26 +25,26 @@ describe('services/space-invitations-protocol', () => {
24
25
  test('genesis', async () => {
25
26
  const [peer] = await chain<ServiceContext>([createIdentity, closeAfterTest])(createPeers(1));
26
27
 
27
- const space = await peer.dataSpaceManager!.createSpace();
28
+ const space = await peer.dataSpaceManager!.createSpace(new Context());
28
29
  expect(peer.dataSpaceManager!.spaces.has(space.key)).to.be.true;
29
30
 
30
- await space.close();
31
+ await space.close(new Context());
31
32
  });
32
33
 
33
34
  test('genesis & ready', async () => {
34
35
  const [peer] = await chain<ServiceContext>([createIdentity, closeAfterTest])(createPeers(1));
35
36
 
36
- const space = await peer.dataSpaceManager!.createSpace();
37
+ const space = await peer.dataSpaceManager!.createSpace(new Context());
37
38
  expect(peer.dataSpaceManager!.spaces.has(space.key)).to.be.true;
38
39
 
39
40
  await peer.dataSpaceManager?.waitUntilSpaceReady(space.key);
40
- await space.close();
41
+ await space.close(new Context());
41
42
  });
42
43
 
43
44
  test('invitation with no auth', async () => {
44
45
  const [host, guest] = await chain<ServiceContext>([createIdentity, closeAfterTest])(createPeers(2));
45
46
 
46
- const space1 = await host.dataSpaceManager!.createSpace();
47
+ const space1 = await host.dataSpaceManager!.createSpace(new Context());
47
48
  const spaceKey = space1.key;
48
49
 
49
50
  await Promise.all(performInvitation({ host, guest, options: { kind: Invitation.Kind.SPACE, spaceKey } }));
@@ -59,15 +60,15 @@ describe('services/space-invitations-protocol', () => {
59
60
 
60
61
  await space2.inner.controlPipeline.state.waitUntilTimeframe(space1.inner.controlPipeline.state.timeframe);
61
62
 
62
- await space1.close();
63
- await space2.close();
63
+ await space1.close(new Context());
64
+ await space2.close(new Context());
64
65
  }
65
66
  });
66
67
 
67
68
  test('invitation when already joined', async () => {
68
69
  const [host, guest] = await chain<ServiceContext>([createIdentity, closeAfterTest])(createPeers(2));
69
70
 
70
- const space1 = await host.dataSpaceManager!.createSpace();
71
+ const space1 = await host.dataSpaceManager!.createSpace(new Context());
71
72
  const spaceKey = space1.key;
72
73
 
73
74
  await Promise.all(performInvitation({ host, guest, options: { kind: Invitation.Kind.SPACE, spaceKey } }));
@@ -96,7 +97,7 @@ describe('services/space-invitations-protocol', () => {
96
97
 
97
98
  let attempt = 0;
98
99
 
99
- const space1 = await host.dataSpaceManager!.createSpace();
100
+ const space1 = await host.dataSpaceManager!.createSpace(new Context());
100
101
 
101
102
  const [{ invitation: invitation1, error: error1 }, { invitation: invitation2, error: error2 }] = await Promise.all(
102
103
  performInvitation({
@@ -143,8 +144,8 @@ describe('services/space-invitations-protocol', () => {
143
144
 
144
145
  await space2.inner.controlPipeline.state.waitUntilTimeframe(space1.inner.controlPipeline.state.timeframe);
145
146
 
146
- await space1.close();
147
- await space2.close();
147
+ await space1.close(new Context());
148
+ await space2.close(new Context());
148
149
  }
149
150
 
150
151
  expect(
@@ -154,14 +155,14 @@ describe('services/space-invitations-protocol', () => {
154
155
 
155
156
  test('timeout', async () => {
156
157
  const [host, guest] = await chain<ServiceContext>([createIdentity, closeAfterTest])(createPeers(2));
157
- const space = await host.dataSpaceManager!.createSpace();
158
+ const space = await host.dataSpaceManager!.createSpace(new Context());
158
159
  const hostInvitation = await createInvitation(host, {
159
160
  kind: Invitation.Kind.SPACE,
160
161
  spaceKey: space.key,
161
162
  timeout: 100,
162
163
  });
163
164
  const invitation = hostInvitation.get();
164
- await host.close();
165
+ await host.close(Context.default());
165
166
 
166
167
  const guestTimeout = new Trigger();
167
168
  const guestInvitation = await acceptInvitation(guest, invitation);
@@ -180,7 +181,7 @@ describe('services/space-invitations-protocol', () => {
180
181
  const hostConnected = new Trigger<Invitation>();
181
182
  const guestConnected = new Trigger<Invitation>();
182
183
 
183
- const space1 = await host.dataSpaceManager!.createSpace();
184
+ const space1 = await host.dataSpaceManager!.createSpace(new Context());
184
185
 
185
186
  const invitationPromises = performInvitation({
186
187
  host,
@@ -213,7 +214,7 @@ describe('services/space-invitations-protocol', () => {
213
214
  expect(invitation1?.state).to.eq(Invitation.State.CANCELLED);
214
215
  expect(error).to.exist;
215
216
 
216
- await space1.close();
217
+ await space1.close(new Context());
217
218
  });
218
219
 
219
220
  // TODO(burdon): Flaky.
@@ -223,7 +224,7 @@ describe('services/space-invitations-protocol', () => {
223
224
  // createPeers(GUEST_COUNT + 1)
224
225
  // );
225
226
 
226
- // const hostSpace = await host.dataSpaceManager!.createSpace();
227
+ // const hostSpace = await host.dataSpaceManager!.createSpace(new Context());
227
228
  // const swarmKey = PublicKey.random();
228
229
  // const hostObservable = await host.spaceInvitations!.createInvitation(hostSpace, {
229
230
  // swarmKey,
@@ -7,6 +7,7 @@ import {
7
7
  createDelegatedSpaceInvitationCredential,
8
8
  getCredentialAssertion,
9
9
  } from '@dxos/credentials';
10
+ import { Context } from '@dxos/context';
10
11
  import { writeMessages } from '@dxos/feed-store';
11
12
  import { invariant } from '@dxos/invariant';
12
13
  import { type Keyring } from '@dxos/keyring';
@@ -182,11 +183,12 @@ export class SpaceInvitationProtocol implements InvitationProtocol {
182
183
  }
183
184
 
184
185
  // Create local space.
185
- await this._spaceManager.acceptSpace({
186
+ await this._spaceManager.acceptSpace(Context.default(), {
186
187
  spaceKey: assertion.spaceKey,
187
188
  genesisFeedKey: assertion.genesisFeedKey,
188
189
  controlTimeframe,
189
190
  dataTimeframe,
191
+ tags: assertion.tags,
190
192
  });
191
193
 
192
194
  await this._signingContext.recordCredential(credential);
@@ -26,6 +26,10 @@ import { getDebugName, jsonify, numericalValues, tracer } from '@dxos/util';
26
26
 
27
27
  /**
28
28
  * Logging service used to spy on logs of the host.
29
+ *
30
+ * @deprecated This was created so that logs from the shared worker (WorkerClientServices) could be
31
+ * seen in the main window console without opening the shared worker DevTools. Shared worker client
32
+ * services is deprecated; dedicated worker logs already show in the main window console.
29
33
  */
30
34
  export class LoggingServiceImpl implements LoggingService {
31
35
  private readonly _logs = new Event<NaturalLogEntry>();
@@ -3,6 +3,7 @@
3
3
  //
4
4
 
5
5
  import { Stream } from '@dxos/codec-protobuf/stream';
6
+ import { Context } from '@dxos/context';
6
7
  import { type EdgeConnection } from '@dxos/edge-client';
7
8
  import { type SignalManager } from '@dxos/messaging';
8
9
  import { type SwarmNetworkManager } from '@dxos/network-manager';
@@ -48,15 +49,15 @@ export class NetworkServiceImpl implements NetworkService {
48
49
  }
49
50
 
50
51
  async joinSwarm(request: JoinRequest): Promise<void> {
51
- return this.signalManager.join(request);
52
+ return this.signalManager.join(Context.default(), request);
52
53
  }
53
54
 
54
55
  async leaveSwarm(request: LeaveRequest): Promise<void> {
55
- return this.signalManager.leave(request);
56
+ return this.signalManager.leave(Context.default(), request);
56
57
  }
57
58
 
58
59
  async querySwarm(request: QueryRequest): Promise<SwarmResponse> {
59
- return this.signalManager.query(request);
60
+ return this.signalManager.query(Context.default(), request);
60
61
  }
61
62
 
62
63
  subscribeSwarmState(request: SubscribeSwarmStateRequest): Stream<SwarmResponse> {
@@ -70,7 +71,7 @@ export class NetworkServiceImpl implements NetworkService {
70
71
  }
71
72
 
72
73
  async sendMessage(message: Message): Promise<void> {
73
- return this.signalManager.sendMessage(message);
74
+ return this.signalManager.sendMessage(Context.default(), message);
74
75
  }
75
76
 
76
77
  subscribeMessages(peer: Peer): Stream<Message> {