@dxos/client-services 0.8.4-main.937b3ca → 0.8.4-main.9be5663bfe
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.
- package/dist/lib/browser/{chunk-UDCUM4WV.mjs → chunk-CK3KJB3B.mjs} +1737 -1199
- package/dist/lib/browser/chunk-CK3KJB3B.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +33 -16
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +14 -7
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/{chunk-Q56HAUWS.mjs → chunk-WHBWCIEN.mjs} +1737 -1199
- package/dist/lib/node-esm/chunk-WHBWCIEN.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +33 -16
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +14 -7
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/packlets/agents/edge-agent-manager.d.ts +3 -2
- package/dist/types/src/packlets/agents/edge-agent-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/devtools.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/contacts-service.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-manager.d.ts +3 -3
- package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +5 -4
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-service.d.ts +1 -6
- package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity.d.ts +6 -9
- package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-manager.d.ts +3 -3
- package/dist/types/src/packlets/invitations/invitations-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/logging/logging-service.d.ts +4 -0
- package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
- package/dist/types/src/packlets/network/network-service.d.ts.map +1 -1
- package/dist/types/src/packlets/services/feed-syncer.d.ts +59 -0
- package/dist/types/src/packlets/services/feed-syncer.d.ts.map +1 -0
- package/dist/types/src/packlets/services/feed-syncer.test.d.ts +2 -0
- package/dist/types/src/packlets/services/feed-syncer.test.d.ts.map +1 -0
- package/dist/types/src/packlets/services/platform.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-context.d.ts +3 -4
- package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/types/src/packlets/space-export/space-archive-reader.d.ts +9 -1
- package/dist/types/src/packlets/space-export/space-archive-reader.d.ts.map +1 -1
- package/dist/types/src/packlets/space-export/space-archive-writer.d.ts +6 -0
- package/dist/types/src/packlets/space-export/space-archive-writer.d.ts.map +1 -1
- package/dist/types/src/packlets/space-export/space-archive.test.d.ts +2 -0
- package/dist/types/src/packlets/space-export/space-archive.test.d.ts.map +1 -0
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts +17 -10
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts +22 -6
- package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/genesis.d.ts +2 -1
- package/dist/types/src/packlets/spaces/genesis.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/spaces-service.d.ts +2 -2
- package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
- package/dist/types/src/packlets/worker/worker-runtime.d.ts +11 -3
- package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
- package/dist/types/src/version.d.ts +1 -1
- package/dist/types/src/version.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +43 -43
- package/src/index.ts +1 -0
- package/src/packlets/agents/edge-agent-manager.ts +8 -5
- package/src/packlets/agents/edge-agent-service.ts +2 -1
- package/src/packlets/devices/devices-service.test.ts +0 -1
- package/src/packlets/devtools/devtools.ts +0 -1
- package/src/packlets/identity/contacts-service.ts +0 -1
- package/src/packlets/identity/identity-manager.test.ts +5 -5
- package/src/packlets/identity/identity-manager.ts +16 -13
- package/src/packlets/identity/identity-recovery-manager.ts +20 -16
- package/src/packlets/identity/identity-service.test.ts +6 -27
- package/src/packlets/identity/identity-service.ts +5 -76
- package/src/packlets/identity/identity.test.ts +2 -2
- package/src/packlets/identity/identity.ts +7 -30
- package/src/packlets/invitations/device-invitation-protocol.ts +0 -1
- package/src/packlets/invitations/edge-invitation-handler.ts +4 -3
- package/src/packlets/invitations/invitations-handler.test.ts +4 -5
- package/src/packlets/invitations/invitations-handler.ts +3 -3
- package/src/packlets/invitations/invitations-manager.ts +37 -14
- package/src/packlets/invitations/invitations-service.ts +4 -4
- package/src/packlets/invitations/space-invitation-protocol.test.ts +17 -16
- package/src/packlets/invitations/space-invitation-protocol.ts +3 -2
- package/src/packlets/logging/logging-service.ts +4 -0
- package/src/packlets/network/network-service.test.ts +0 -1
- package/src/packlets/network/network-service.ts +5 -4
- package/src/packlets/services/feed-syncer.test.ts +340 -0
- package/src/packlets/services/feed-syncer.ts +337 -0
- package/src/packlets/services/platform.ts +7 -1
- package/src/packlets/services/service-context.test.ts +3 -2
- package/src/packlets/services/service-context.ts +105 -31
- package/src/packlets/services/service-host.test.ts +8 -8
- package/src/packlets/services/service-host.ts +10 -9
- package/src/packlets/services/service-registry.test.ts +0 -1
- package/src/packlets/space-export/space-archive-reader.ts +64 -3
- package/src/packlets/space-export/space-archive-writer.ts +36 -1
- package/src/packlets/space-export/space-archive.test.ts +287 -0
- package/src/packlets/spaces/data-space-manager.test.ts +79 -13
- package/src/packlets/spaces/data-space-manager.ts +71 -104
- package/src/packlets/spaces/data-space.ts +46 -24
- package/src/packlets/spaces/edge-feed-replicator.test.ts +1 -1
- package/src/packlets/spaces/edge-feed-replicator.ts +8 -7
- package/src/packlets/spaces/epoch-migrations.ts +3 -3
- package/src/packlets/spaces/genesis.ts +6 -1
- package/src/packlets/spaces/notarization-plugin.ts +2 -1
- package/src/packlets/spaces/spaces-service.test.ts +9 -7
- package/src/packlets/spaces/spaces-service.ts +30 -9
- package/src/packlets/testing/invitation-utils.ts +3 -2
- package/src/packlets/worker/worker-runtime.ts +14 -7
- package/src/packlets/worker/worker-session.ts +4 -4
- package/src/version.ts +1 -1
- package/dist/lib/browser/chunk-UDCUM4WV.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-Q56HAUWS.mjs.map +0 -7
- package/dist/types/src/packlets/identity/default-space-state-machine.d.ts +0 -19
- package/dist/types/src/packlets/identity/default-space-state-machine.d.ts.map +0 -1
- 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
|
|
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,11 @@ 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
38
|
export type IdentityProps = {
|
|
42
39
|
did: IdentityDid;
|
|
@@ -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;
|
|
@@ -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
107
|
@trace.span()
|
|
120
|
-
async open(ctx:
|
|
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
123
|
@trace.span()
|
|
137
|
-
async close(ctx:
|
|
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,
|
|
@@ -16,7 +16,6 @@ import {
|
|
|
16
16
|
} from '@dxos/protocols/proto/dxos/halo/invitations';
|
|
17
17
|
|
|
18
18
|
import { type Identity, type JoinIdentityProps } from '../identity';
|
|
19
|
-
|
|
20
19
|
import { type InvitationProtocol } from './invitation-protocol';
|
|
21
20
|
|
|
22
21
|
export class DeviceInvitationProtocol implements InvitationProtocol {
|
|
@@ -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
|
});
|
|
@@ -12,7 +12,6 @@ import { openAndClose } from '@dxos/test-utils';
|
|
|
12
12
|
import { range } from '@dxos/util';
|
|
13
13
|
|
|
14
14
|
import { TestBuilder, type TestPeer } from '../testing';
|
|
15
|
-
|
|
16
15
|
import { type InvitationProtocol } from './invitation-protocol';
|
|
17
16
|
import { InvitationsHandler } from './invitations-handler';
|
|
18
17
|
import { SpaceInvitationProtocol } from './space-invitation-protocol';
|
|
@@ -95,7 +94,7 @@ describe.skipIf(process.env.CI && !process.env.RUN_FLAKY_TESTS)(
|
|
|
95
94
|
await acceptInvitation(guest, invitation);
|
|
96
95
|
|
|
97
96
|
await guest.sink.waitFor(Invitation.State.READY_FOR_AUTHENTICATION);
|
|
98
|
-
await guest.peer.networkManager.close();
|
|
97
|
+
await guest.peer.networkManager.close(Context.default());
|
|
99
98
|
await host.sink.waitFor(Invitation.State.CONNECTING);
|
|
100
99
|
|
|
101
100
|
await sleep(10);
|
|
@@ -254,9 +253,9 @@ describe.skipIf(process.env.CI && !process.env.RUN_FLAKY_TESTS)(
|
|
|
254
253
|
const peer = testBuilder.createPeer();
|
|
255
254
|
await peer.createIdentity();
|
|
256
255
|
await openAndClose(peer.echoHost, peer.dataSpaceManager);
|
|
257
|
-
await peer.echoHost.addReplicator(peer.meshEchoReplicator);
|
|
256
|
+
await peer.echoHost.addReplicator(Context.default(), peer.meshEchoReplicator);
|
|
258
257
|
if (spaceKey == null) {
|
|
259
|
-
const space = await peer.dataSpaceManager.createSpace();
|
|
258
|
+
const space = await peer.dataSpaceManager.createSpace(new Context());
|
|
260
259
|
spaceKey = space.key;
|
|
261
260
|
}
|
|
262
261
|
const invitationHandler = new InvitationsHandler(peer.networkManager, undefined, {
|
|
@@ -359,7 +358,7 @@ describe.skipIf(process.env.CI && !process.env.RUN_FLAKY_TESTS)(
|
|
|
359
358
|
};
|
|
360
359
|
|
|
361
360
|
const createInvitation = async (setup: PeerSetup, options?: Partial<Invitation>): Promise<Invitation> => {
|
|
362
|
-
const observable = await setup.peer.invitationsManager.createInvitation({
|
|
361
|
+
const observable = await setup.peer.invitationsManager.createInvitation(setup.ctx, {
|
|
363
362
|
type: Invitation.Type.DELEGATED,
|
|
364
363
|
kind: Invitation.Kind.SPACE,
|
|
365
364
|
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
|
-
|
|
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 {
|
|
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(
|
|
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 {
|
|
127
|
-
|
|
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,
|
|
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
|
|
262
|
+
const invitationCtx = ctx.derive({
|
|
240
263
|
onError: (err) => {
|
|
241
264
|
stream.error(err);
|
|
242
|
-
void
|
|
265
|
+
void invitationCtx.dispose();
|
|
243
266
|
},
|
|
244
267
|
});
|
|
245
|
-
|
|
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
|
|
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
|
-
|
|
44
|
-
|
|
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,
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { Context } from '@dxos/context';
|
|
5
6
|
import {
|
|
6
7
|
createCancelDelegatedSpaceInvitationCredential,
|
|
7
8
|
createDelegatedSpaceInvitationCredential,
|
|
@@ -22,7 +23,6 @@ import {
|
|
|
22
23
|
} from '@dxos/protocols/proto/dxos/halo/invitations';
|
|
23
24
|
|
|
24
25
|
import { type DataSpaceManager, type SigningContext } from '../spaces';
|
|
25
|
-
|
|
26
26
|
import { type InvitationProtocol } from './invitation-protocol';
|
|
27
27
|
import { computeExpirationTime } from './utils';
|
|
28
28
|
|
|
@@ -182,11 +182,12 @@ export class SpaceInvitationProtocol implements InvitationProtocol {
|
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
// Create local space.
|
|
185
|
-
await this._spaceManager.acceptSpace({
|
|
185
|
+
await this._spaceManager.acceptSpace(Context.default(), {
|
|
186
186
|
spaceKey: assertion.spaceKey,
|
|
187
187
|
genesisFeedKey: assertion.genesisFeedKey,
|
|
188
188
|
controlTimeframe,
|
|
189
189
|
dataTimeframe,
|
|
190
|
+
tags: assertion.tags,
|
|
190
191
|
});
|
|
191
192
|
|
|
192
193
|
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>();
|
|
@@ -10,7 +10,6 @@ import { ConnectionState, type NetworkService } from '@dxos/protocols/proto/dxos
|
|
|
10
10
|
|
|
11
11
|
import { type ServiceContext } from '../services';
|
|
12
12
|
import { createServiceContext } from '../testing';
|
|
13
|
-
|
|
14
13
|
import { NetworkServiceImpl } from './network-service';
|
|
15
14
|
|
|
16
15
|
describe('NetworkService', () => {
|
|
@@ -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> {
|