@dxos/client-services 0.6.13-main.ed424a1 → 0.6.13
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-IPWEAPT2.mjs → chunk-CRXXOI45.mjs} +5186 -6222
- package/dist/lib/browser/chunk-CRXXOI45.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +3 -7
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +7 -12
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node/{chunk-DJIOUOAF.cjs → chunk-PZ3JJJ3K.cjs} +5137 -6167
- package/dist/lib/node/chunk-PZ3JJJ3K.cjs.map +7 -0
- package/dist/lib/node/index.cjs +46 -50
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +13 -18
- package/dist/lib/node/testing/index.cjs.map +3 -3
- package/dist/types/src/index.d.ts +0 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/authenticator.test.d.ts +2 -0
- package/dist/types/src/packlets/identity/authenticator.test.d.ts.map +1 -0
- package/dist/types/src/packlets/identity/contacts-service.d.ts +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 +9 -25
- package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity.d.ts +3 -12
- 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/invitation-guest-extenstion.d.ts +1 -2
- package/dist/types/src/packlets/invitations/invitation-guest-extenstion.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts +1 -2
- package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts +8 -8
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/services/automerge-host.test.d.ts +2 -0
- package/dist/types/src/packlets/services/automerge-host.test.d.ts.map +1 -0
- package/dist/types/src/packlets/services/service-context.d.ts +9 -12
- package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts +0 -1
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts +3 -7
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts +3 -5
- package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts +0 -3
- package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/epoch-migrations.d.ts +1 -1
- package/dist/types/src/packlets/spaces/epoch-migrations.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +6 -35
- package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/spaces-service.d.ts +1 -1
- package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/storage.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/test-builder.d.ts +2 -1
- package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
- 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/package.json +39 -43
- package/src/index.ts +0 -1
- package/src/packlets/devices/devices-service.test.ts +5 -4
- package/src/packlets/diagnostics/diagnostics-broadcast.ts +0 -1
- package/src/packlets/identity/{authenticator.node.test.ts → authenticator.test.ts} +3 -2
- package/src/packlets/identity/authenticator.ts +2 -5
- package/src/packlets/identity/contacts-service.ts +1 -1
- package/src/packlets/identity/identity-manager.test.ts +16 -31
- package/src/packlets/identity/identity-manager.ts +31 -47
- package/src/packlets/identity/identity-service.test.ts +8 -4
- package/src/packlets/identity/identity.test.ts +239 -130
- package/src/packlets/identity/identity.ts +17 -60
- package/src/packlets/invitations/device-invitation-protocol.test.ts +4 -7
- package/src/packlets/invitations/device-invitation-protocol.ts +1 -5
- package/src/packlets/invitations/invitation-guest-extenstion.ts +4 -8
- package/src/packlets/invitations/invitation-host-extension.ts +7 -8
- package/src/packlets/invitations/invitations-handler.test.ts +9 -16
- package/src/packlets/invitations/invitations-handler.ts +93 -23
- package/src/packlets/invitations/space-invitation-protocol.test.ts +3 -4
- package/src/packlets/invitations/space-invitation-protocol.ts +0 -4
- package/src/packlets/logging/logging.test.ts +2 -1
- package/src/packlets/network/network-service.test.ts +3 -2
- package/src/packlets/services/automerge-host.test.ts +60 -0
- package/src/packlets/services/service-context.test.ts +1 -3
- package/src/packlets/services/service-context.ts +37 -104
- package/src/packlets/services/service-host.test.ts +12 -8
- package/src/packlets/services/service-host.ts +6 -16
- package/src/packlets/services/service-registry.test.ts +2 -1
- package/src/packlets/spaces/data-space-manager.test.ts +2 -2
- package/src/packlets/spaces/data-space-manager.ts +7 -44
- package/src/packlets/spaces/data-space.ts +6 -37
- package/src/packlets/spaces/edge-feed-replicator.ts +22 -80
- package/src/packlets/spaces/epoch-migrations.ts +2 -2
- package/src/packlets/spaces/notarization-plugin.test.ts +7 -10
- package/src/packlets/spaces/notarization-plugin.ts +29 -196
- package/src/packlets/spaces/spaces-service.test.ts +9 -5
- package/src/packlets/spaces/spaces-service.ts +1 -6
- package/src/packlets/storage/storage.ts +1 -0
- package/src/packlets/system/system-service.test.ts +2 -1
- package/src/packlets/testing/test-builder.ts +4 -7
- package/src/packlets/worker/worker-runtime.ts +2 -2
- package/src/version.ts +5 -1
- package/dist/lib/browser/chunk-IPWEAPT2.mjs.map +0 -7
- package/dist/lib/node/chunk-DJIOUOAF.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-MMU5KC57.mjs +0 -8752
- package/dist/lib/node-esm/chunk-MMU5KC57.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -420
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/testing/index.mjs +0 -424
- package/dist/lib/node-esm/testing/index.mjs.map +0 -7
- package/dist/types/src/packlets/agents/edge-agent-manager.d.ts +0 -35
- package/dist/types/src/packlets/agents/edge-agent-manager.d.ts.map +0 -1
- package/dist/types/src/packlets/agents/edge-agent-service.d.ts +0 -10
- package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +0 -1
- package/dist/types/src/packlets/agents/index.d.ts +0 -3
- package/dist/types/src/packlets/agents/index.d.ts.map +0 -1
- package/dist/types/src/packlets/identity/authenticator.node.test.d.ts +0 -2
- package/dist/types/src/packlets/identity/authenticator.node.test.d.ts.map +0 -1
- package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts +0 -30
- package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts.map +0 -1
- package/dist/types/src/packlets/invitations/invitation-state.d.ts +0 -19
- package/dist/types/src/packlets/invitations/invitation-state.d.ts.map +0 -1
- package/dist/types/src/packlets/spaces/edge-feed-replicator.test.d.ts +0 -2
- package/dist/types/src/packlets/spaces/edge-feed-replicator.test.d.ts.map +0 -1
- package/dist/types/src/testing/setup.d.ts +0 -3
- package/dist/types/src/testing/setup.d.ts.map +0 -1
- package/src/packlets/agents/edge-agent-manager.ts +0 -163
- package/src/packlets/agents/edge-agent-service.ts +0 -42
- package/src/packlets/agents/index.ts +0 -6
- package/src/packlets/invitations/edge-invitation-handler.ts +0 -185
- package/src/packlets/invitations/invitation-state.ts +0 -111
- package/src/packlets/spaces/edge-feed-replicator.test.ts +0 -252
- package/src/testing/setup.ts +0 -11
|
@@ -2,18 +2,14 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { DeferredTask, Event, scheduleTask, sleep, TimeoutError, Trigger
|
|
6
|
-
import {
|
|
7
|
-
import { type CredentialProcessor
|
|
8
|
-
import { type EdgeHttpClient } from '@dxos/edge-client';
|
|
5
|
+
import { DeferredTask, Event, scheduleTask, sleep, TimeoutError, Trigger } from '@dxos/async';
|
|
6
|
+
import { Context, rejectOnDispose } from '@dxos/context';
|
|
7
|
+
import { type CredentialProcessor } from '@dxos/credentials';
|
|
9
8
|
import { type FeedWriter } from '@dxos/feed-store';
|
|
10
9
|
import { invariant } from '@dxos/invariant';
|
|
11
10
|
import { PublicKey } from '@dxos/keys';
|
|
12
|
-
import {
|
|
13
|
-
import { logInfo, log } from '@dxos/log';
|
|
14
|
-
import { EdgeCallFailedError } from '@dxos/protocols';
|
|
11
|
+
import { log } from '@dxos/log';
|
|
15
12
|
import { schema } from '@dxos/protocols/proto';
|
|
16
|
-
import { type Runtime } from '@dxos/protocols/proto/dxos/config';
|
|
17
13
|
import { type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
18
14
|
import { type NotarizationService, type NotarizeRequest } from '@dxos/protocols/proto/dxos/mesh/teleport/notarization';
|
|
19
15
|
import { type ExtensionContext, RpcExtension } from '@dxos/teleport';
|
|
@@ -25,21 +21,8 @@ const DEFAULT_SUCCESS_DELAY = 1_000;
|
|
|
25
21
|
|
|
26
22
|
const DEFAULT_NOTARIZE_TIMEOUT = 10_000;
|
|
27
23
|
|
|
28
|
-
const DEFAULT_ACTIVE_EDGE_POLLING_INTERVAL = 3_000;
|
|
29
|
-
|
|
30
|
-
const MAX_EDGE_RETRIES = 2;
|
|
31
|
-
|
|
32
24
|
const WRITER_NOT_SET_ERROR_CODE = 'WRITER_NOT_SET';
|
|
33
25
|
|
|
34
|
-
const credentialCodec = schema.getCodecForType('dxos.halo.credentials.Credential');
|
|
35
|
-
|
|
36
|
-
export type NotarizationPluginParams = {
|
|
37
|
-
spaceId: SpaceId;
|
|
38
|
-
edgeClient?: EdgeHttpClient;
|
|
39
|
-
edgeFeatures?: Runtime.Client.EdgeFeatures;
|
|
40
|
-
activeEdgePollingInterval?: number;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
26
|
export type NotarizeParams = {
|
|
44
27
|
/**
|
|
45
28
|
* For cancellation.
|
|
@@ -70,17 +53,13 @@ export type NotarizeParams = {
|
|
|
70
53
|
* @default {@link DEFAULT_SUCCESS_DELAY}
|
|
71
54
|
*/
|
|
72
55
|
successDelay?: number;
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* A random amount of time before making or retrying an edge request to help prevent large bursts of requests.
|
|
76
|
-
*/
|
|
77
|
-
edgeRetryJitter?: number;
|
|
78
56
|
};
|
|
79
57
|
|
|
80
58
|
/**
|
|
81
59
|
* See NotarizationService proto.
|
|
82
60
|
*/
|
|
83
|
-
export class NotarizationPlugin
|
|
61
|
+
export class NotarizationPlugin implements CredentialProcessor {
|
|
62
|
+
private readonly _ctx = new Context();
|
|
84
63
|
private readonly _extensionOpened = new Event();
|
|
85
64
|
|
|
86
65
|
private _writer: FeedWriter<Credential> | undefined;
|
|
@@ -88,54 +67,13 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
|
|
|
88
67
|
private readonly _processedCredentials = new ComplexSet<PublicKey>(PublicKey.hash);
|
|
89
68
|
private readonly _processCredentialsTriggers = new ComplexMap<PublicKey, Trigger>(PublicKey.hash);
|
|
90
69
|
|
|
91
|
-
private _activeEdgePollingIntervalHandle: any | undefined = undefined;
|
|
92
|
-
private readonly _activeEdgePollingInterval: number;
|
|
93
|
-
|
|
94
|
-
@logInfo
|
|
95
|
-
private readonly _spaceId: SpaceId;
|
|
96
|
-
|
|
97
|
-
private readonly _edgeClient: EdgeHttpClient | undefined;
|
|
98
|
-
|
|
99
|
-
constructor(params: NotarizationPluginParams) {
|
|
100
|
-
super();
|
|
101
|
-
this._spaceId = params.spaceId;
|
|
102
|
-
this._activeEdgePollingInterval = params.activeEdgePollingInterval ?? DEFAULT_ACTIVE_EDGE_POLLING_INTERVAL;
|
|
103
|
-
if (params.edgeClient && params.edgeFeatures?.feedReplicator) {
|
|
104
|
-
this._edgeClient = params.edgeClient;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
setActiveEdgePollingEnabled(enabled: boolean) {
|
|
109
|
-
invariant(this.isOpen);
|
|
110
|
-
const client = this._edgeClient;
|
|
111
|
-
invariant(client);
|
|
112
|
-
if (enabled && !this._activeEdgePollingIntervalHandle) {
|
|
113
|
-
this._activeEdgePollingIntervalHandle = setInterval(() => {
|
|
114
|
-
if (this._writer) {
|
|
115
|
-
this._notarizePendingEdgeCredentials(client, this._writer);
|
|
116
|
-
}
|
|
117
|
-
}, this._activeEdgePollingInterval);
|
|
118
|
-
} else if (!enabled && this._activeEdgePollingIntervalHandle) {
|
|
119
|
-
clearInterval(this._activeEdgePollingIntervalHandle);
|
|
120
|
-
this._activeEdgePollingIntervalHandle = undefined;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
70
|
get hasWriter() {
|
|
125
71
|
return !!this._writer;
|
|
126
72
|
}
|
|
127
73
|
|
|
128
|
-
|
|
129
|
-
if (this._edgeClient && this._writer) {
|
|
130
|
-
this._notarizePendingEdgeCredentials(this._edgeClient, this._writer);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
74
|
+
async open() {}
|
|
133
75
|
|
|
134
|
-
|
|
135
|
-
if (this._activeEdgePollingIntervalHandle) {
|
|
136
|
-
clearInterval(this._activeEdgePollingIntervalHandle);
|
|
137
|
-
this._activeEdgePollingIntervalHandle = undefined;
|
|
138
|
-
}
|
|
76
|
+
async close() {
|
|
139
77
|
await this._ctx.dispose();
|
|
140
78
|
}
|
|
141
79
|
|
|
@@ -148,7 +86,6 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
|
|
|
148
86
|
timeout = DEFAULT_NOTARIZE_TIMEOUT,
|
|
149
87
|
retryTimeout = DEFAULT_RETRY_TIMEOUT,
|
|
150
88
|
successDelay = DEFAULT_SUCCESS_DELAY,
|
|
151
|
-
edgeRetryJitter,
|
|
152
89
|
}: NotarizeParams) {
|
|
153
90
|
log('notarize', { credentials });
|
|
154
91
|
invariant(
|
|
@@ -166,35 +103,24 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
|
|
|
166
103
|
});
|
|
167
104
|
opCtx?.onDispose(() => ctx.dispose());
|
|
168
105
|
|
|
106
|
+
// Timeout/
|
|
169
107
|
if (timeout !== 0) {
|
|
170
|
-
|
|
108
|
+
scheduleTask(
|
|
109
|
+
ctx,
|
|
110
|
+
() => {
|
|
111
|
+
log.warn('Notarization timeout', {
|
|
112
|
+
timeout,
|
|
113
|
+
peers: Array.from(this._extensions).map((extension) => extension.remotePeerId),
|
|
114
|
+
});
|
|
115
|
+
void ctx.dispose();
|
|
116
|
+
errors.throw(new TimeoutError(timeout, 'Notarization timed out'));
|
|
117
|
+
},
|
|
118
|
+
timeout,
|
|
119
|
+
);
|
|
171
120
|
}
|
|
172
121
|
|
|
173
122
|
const allNotarized = Promise.all(credentials.map((credential) => this._waitUntilProcessed(credential.id!)));
|
|
174
123
|
|
|
175
|
-
this._tryNotarizeCredentialsWithPeers(ctx, credentials, { retryTimeout, successDelay });
|
|
176
|
-
|
|
177
|
-
if (this._edgeClient) {
|
|
178
|
-
this._tryNotarizeCredentialsWithEdge(ctx, this._edgeClient, credentials, {
|
|
179
|
-
retryTimeout,
|
|
180
|
-
successDelay,
|
|
181
|
-
jitter: edgeRetryJitter,
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
try {
|
|
186
|
-
await Promise.race([rejectOnDispose(ctx), allNotarized, errors.wait()]);
|
|
187
|
-
log('done');
|
|
188
|
-
} finally {
|
|
189
|
-
await ctx.dispose();
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
private _tryNotarizeCredentialsWithPeers(
|
|
194
|
-
ctx: Context,
|
|
195
|
-
credentials: Credential[],
|
|
196
|
-
{ retryTimeout, successDelay }: NotarizationTimeouts,
|
|
197
|
-
) {
|
|
198
124
|
const peersTried = new Set<NotarizationTeleportExtension>();
|
|
199
125
|
|
|
200
126
|
// Repeatable task that tries to notarize credentials with one of the available peers.
|
|
@@ -219,7 +145,6 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
|
|
|
219
145
|
credentials: credentials.filter((credential) => !this._processedCredentials.has(credential.id!)),
|
|
220
146
|
});
|
|
221
147
|
log('success');
|
|
222
|
-
|
|
223
148
|
await sleep(successDelay); // wait before trying with a new peer
|
|
224
149
|
} catch (err: any) {
|
|
225
150
|
if (!ctx.disposed && !err.message.includes(WRITER_NOT_SET_ERROR_CODE)) {
|
|
@@ -231,31 +156,13 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
|
|
|
231
156
|
|
|
232
157
|
notarizeTask.schedule();
|
|
233
158
|
this._extensionOpened.on(ctx, () => notarizeTask.schedule());
|
|
234
|
-
}
|
|
235
159
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
const encodedCredentials = credentials.map((credential) => {
|
|
243
|
-
const binary = credentialCodec.encode(credential);
|
|
244
|
-
return Buffer.from(binary).toString('base64');
|
|
245
|
-
});
|
|
246
|
-
scheduleTask(ctx, async () => {
|
|
247
|
-
try {
|
|
248
|
-
await client.notarizeCredentials(
|
|
249
|
-
this._spaceId,
|
|
250
|
-
{ credentials: encodedCredentials },
|
|
251
|
-
{ retry: { count: MAX_EDGE_RETRIES, timeout: timeouts.retryTimeout, jitter: timeouts.jitter } },
|
|
252
|
-
);
|
|
253
|
-
|
|
254
|
-
log('edge notarization success');
|
|
255
|
-
} catch (error: any) {
|
|
256
|
-
handleEdgeError(error);
|
|
257
|
-
}
|
|
258
|
-
});
|
|
160
|
+
try {
|
|
161
|
+
await Promise.race([rejectOnDispose(ctx), allNotarized, errors.wait()]);
|
|
162
|
+
log('done');
|
|
163
|
+
} finally {
|
|
164
|
+
await ctx.dispose();
|
|
165
|
+
}
|
|
259
166
|
}
|
|
260
167
|
|
|
261
168
|
/**
|
|
@@ -273,44 +180,6 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
|
|
|
273
180
|
setWriter(writer: FeedWriter<Credential>) {
|
|
274
181
|
invariant(!this._writer, 'Writer already set.');
|
|
275
182
|
this._writer = writer;
|
|
276
|
-
if (this._edgeClient) {
|
|
277
|
-
this._notarizePendingEdgeCredentials(this._edgeClient, writer);
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* The method is used only for adding agent feeds to spaces.
|
|
283
|
-
* When an agent is created we can admit them into all the existing spaces. In case the operation fails
|
|
284
|
-
* this method will fix it on the next space open.
|
|
285
|
-
* Given how rarely this happens there's no need to poll the endpoint.
|
|
286
|
-
*/
|
|
287
|
-
private _notarizePendingEdgeCredentials(client: EdgeHttpClient, writer: FeedWriter<Credential>) {
|
|
288
|
-
scheduleMicroTask(this._ctx, async () => {
|
|
289
|
-
try {
|
|
290
|
-
const response = await client.getCredentialsForNotarization(this._spaceId, {
|
|
291
|
-
retry: { count: MAX_EDGE_RETRIES },
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
const credentials = response.awaitingNotarization.credentials;
|
|
295
|
-
if (!credentials.length) {
|
|
296
|
-
log('edge did not return credentials for notarization');
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
log('got edge credentials for notarization', { count: credentials.length });
|
|
301
|
-
|
|
302
|
-
const decodedCredentials = credentials.map((credential) => {
|
|
303
|
-
const binary = Buffer.from(credential, 'base64');
|
|
304
|
-
return credentialCodec.decode(binary);
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
await this._notarizeCredentials(writer, decodedCredentials);
|
|
308
|
-
|
|
309
|
-
log.info('notarized edge credentials', { count: decodedCredentials.length });
|
|
310
|
-
} catch (error: any) {
|
|
311
|
-
handleEdgeError(error);
|
|
312
|
-
}
|
|
313
|
-
});
|
|
314
183
|
}
|
|
315
184
|
|
|
316
185
|
private async _waitUntilProcessed(id: PublicKey) {
|
|
@@ -327,20 +196,12 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
|
|
|
327
196
|
if (!this._writer) {
|
|
328
197
|
throw new Error(WRITER_NOT_SET_ERROR_CODE);
|
|
329
198
|
}
|
|
330
|
-
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
private async _notarizeCredentials(writer: FeedWriter<Credential>, credentials: Credential[]) {
|
|
334
|
-
for (const credential of credentials) {
|
|
199
|
+
for (const credential of request.credentials ?? []) {
|
|
335
200
|
invariant(credential.id, 'Credential must have an id');
|
|
336
201
|
if (this._processedCredentials.has(credential.id)) {
|
|
337
202
|
continue;
|
|
338
203
|
}
|
|
339
|
-
|
|
340
|
-
if (verificationResult.kind === 'fail') {
|
|
341
|
-
throw new Error(`Credential verification failed: ${verificationResult.errors.join('\n')}.`);
|
|
342
|
-
}
|
|
343
|
-
await writer.write(credential);
|
|
204
|
+
await this._writer.write(credential);
|
|
344
205
|
}
|
|
345
206
|
}
|
|
346
207
|
|
|
@@ -359,31 +220,8 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
|
|
|
359
220
|
});
|
|
360
221
|
return extension;
|
|
361
222
|
}
|
|
362
|
-
|
|
363
|
-
private _scheduleTimeout(ctx: Context, errors: Trigger, timeout: number) {
|
|
364
|
-
scheduleTask(
|
|
365
|
-
ctx,
|
|
366
|
-
() => {
|
|
367
|
-
log.warn('Notarization timeout', {
|
|
368
|
-
timeout,
|
|
369
|
-
peers: Array.from(this._extensions).map((extension) => extension.remotePeerId),
|
|
370
|
-
});
|
|
371
|
-
void ctx.dispose();
|
|
372
|
-
errors.throw(new TimeoutError(timeout, 'Notarization timed out'));
|
|
373
|
-
},
|
|
374
|
-
timeout,
|
|
375
|
-
);
|
|
376
|
-
}
|
|
377
223
|
}
|
|
378
224
|
|
|
379
|
-
const handleEdgeError = (error: any) => {
|
|
380
|
-
if (!(error instanceof EdgeCallFailedError) || error.errorData) {
|
|
381
|
-
log.catch(error);
|
|
382
|
-
} else {
|
|
383
|
-
log.info('Edge notarization failure', { reason: error.reason });
|
|
384
|
-
}
|
|
385
|
-
};
|
|
386
|
-
|
|
387
225
|
export type NotarizationTeleportExtensionParams = {
|
|
388
226
|
onOpen: () => Promise<void>;
|
|
389
227
|
onClose: () => Promise<void>;
|
|
@@ -423,11 +261,6 @@ export class NotarizationTeleportExtension extends RpcExtension<Services, Servic
|
|
|
423
261
|
}
|
|
424
262
|
}
|
|
425
263
|
|
|
426
|
-
type NotarizationTimeouts = {
|
|
427
|
-
retryTimeout: number;
|
|
428
|
-
successDelay: number;
|
|
429
|
-
};
|
|
430
|
-
|
|
431
264
|
type Services = {
|
|
432
265
|
NotarizationService: NotarizationService;
|
|
433
266
|
};
|
|
@@ -2,17 +2,21 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import chai, { expect } from 'chai';
|
|
6
|
+
import chaiAsPromised from 'chai-as-promised';
|
|
6
7
|
|
|
7
8
|
import { Trigger } from '@dxos/async';
|
|
8
9
|
import { Context } from '@dxos/context';
|
|
9
10
|
import { PublicKey } from '@dxos/keys';
|
|
10
11
|
import { type Space, type SpacesService } from '@dxos/protocols/proto/dxos/client/services';
|
|
12
|
+
import { afterEach, afterTest, beforeEach, describe, test } from '@dxos/test';
|
|
11
13
|
|
|
12
14
|
import { SpacesServiceImpl } from './spaces-service';
|
|
13
15
|
import { type ServiceContext } from '../services';
|
|
14
16
|
import { createServiceContext } from '../testing';
|
|
15
17
|
|
|
18
|
+
chai.use(chaiAsPromised);
|
|
19
|
+
|
|
16
20
|
describe('SpacesService', () => {
|
|
17
21
|
let serviceContext: ServiceContext;
|
|
18
22
|
let spacesService: SpacesService;
|
|
@@ -32,7 +36,7 @@ describe('SpacesService', () => {
|
|
|
32
36
|
|
|
33
37
|
describe('createSpace', () => {
|
|
34
38
|
test('fails if no identity is available', async () => {
|
|
35
|
-
await expect(spacesService.createSpace()).
|
|
39
|
+
await expect(spacesService.createSpace()).to.be.rejectedWith();
|
|
36
40
|
});
|
|
37
41
|
|
|
38
42
|
test('creates a new space', async () => {
|
|
@@ -52,7 +56,7 @@ describe('SpacesService', () => {
|
|
|
52
56
|
query.subscribe(({ spaces }) => {
|
|
53
57
|
result.wake(spaces);
|
|
54
58
|
});
|
|
55
|
-
|
|
59
|
+
afterTest(() => query.close());
|
|
56
60
|
expect(await result.wait()).to.be.length(0);
|
|
57
61
|
});
|
|
58
62
|
|
|
@@ -69,7 +73,7 @@ describe('SpacesService', () => {
|
|
|
69
73
|
query.subscribe(({ spaces }) => {
|
|
70
74
|
result.wake(spaces);
|
|
71
75
|
});
|
|
72
|
-
|
|
76
|
+
afterTest(() => query.close());
|
|
73
77
|
|
|
74
78
|
const spaces = await result.wait();
|
|
75
79
|
expect(spaces).to.be.length(3);
|
|
@@ -83,7 +87,7 @@ describe('SpacesService', () => {
|
|
|
83
87
|
query.subscribe(({ spaces }) => {
|
|
84
88
|
result.wake(spaces);
|
|
85
89
|
});
|
|
86
|
-
|
|
90
|
+
afterTest(() => query.close());
|
|
87
91
|
expect(await result.wait()).to.be.length(0);
|
|
88
92
|
|
|
89
93
|
result.reset();
|
|
@@ -60,7 +60,7 @@ export class SpacesServiceImpl implements SpacesService {
|
|
|
60
60
|
return this._serializeSpace(space);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
async updateSpace({ spaceKey, state
|
|
63
|
+
async updateSpace({ spaceKey, state }: UpdateSpaceRequest) {
|
|
64
64
|
const dataSpaceManager = await this._getDataSpaceManager();
|
|
65
65
|
const space = dataSpaceManager.spaces.get(spaceKey) ?? raise(new SpaceNotFoundError(spaceKey));
|
|
66
66
|
|
|
@@ -77,10 +77,6 @@ export class SpacesServiceImpl implements SpacesService {
|
|
|
77
77
|
throw new ApiError('Invalid space state');
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
|
-
|
|
81
|
-
if (edgeReplication !== undefined) {
|
|
82
|
-
await dataSpaceManager.setSpaceEdgeReplicationSetting(spaceKey, edgeReplication);
|
|
83
|
-
}
|
|
84
80
|
}
|
|
85
81
|
|
|
86
82
|
async updateMemberRole(request: UpdateMemberRoleRequest): Promise<void> {
|
|
@@ -312,7 +308,6 @@ export class SpacesServiceImpl implements SpacesService {
|
|
|
312
308
|
creator: space.inner.spaceState.creator?.key,
|
|
313
309
|
cache: space.cache,
|
|
314
310
|
metrics: space.metrics,
|
|
315
|
-
edgeReplication: space.getEdgeReplicationSetting(),
|
|
316
311
|
};
|
|
317
312
|
}
|
|
318
313
|
|
|
@@ -14,6 +14,7 @@ import { getRootPath } from './util';
|
|
|
14
14
|
// TODO(burdon): Factor out.
|
|
15
15
|
export const createStorageObjects = (config: Runtime.Client.Storage) => {
|
|
16
16
|
const { persistent = false, keyStore, dataStore } = config ?? {};
|
|
17
|
+
|
|
17
18
|
if (persistent && dataStore === StorageDriver.RAM) {
|
|
18
19
|
throw new InvalidConfigError('RAM storage cannot be used in persistent mode.');
|
|
19
20
|
}
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { expect } from 'chai';
|
|
6
6
|
|
|
7
7
|
import { Event, Trigger } from '@dxos/async';
|
|
8
8
|
import { Config } from '@dxos/config';
|
|
9
9
|
import { type SystemService, SystemStatus, type QueryStatusResponse } from '@dxos/protocols/proto/dxos/client/services';
|
|
10
|
+
import { beforeEach, describe, test } from '@dxos/test';
|
|
10
11
|
|
|
11
12
|
import { SystemServiceImpl } from './system-service';
|
|
12
13
|
|
|
@@ -6,7 +6,8 @@ import { type Config } from '@dxos/config';
|
|
|
6
6
|
import { Context } from '@dxos/context';
|
|
7
7
|
import { createCredentialSignerWithChain, CredentialGenerator } from '@dxos/credentials';
|
|
8
8
|
import { failUndefined } from '@dxos/debug';
|
|
9
|
-
import { EchoHost
|
|
9
|
+
import { EchoHost } from '@dxos/echo-db';
|
|
10
|
+
import { MetadataStore, SpaceManager, valueEncoding, MeshEchoReplicator } from '@dxos/echo-pipeline';
|
|
10
11
|
import { FeedFactory, FeedStore } from '@dxos/feed-store';
|
|
11
12
|
import { Keyring } from '@dxos/keyring';
|
|
12
13
|
import { type LevelDB } from '@dxos/kv-store';
|
|
@@ -53,8 +54,8 @@ export const createServiceContext = async ({
|
|
|
53
54
|
const level = createTestLevel();
|
|
54
55
|
await level.open();
|
|
55
56
|
|
|
56
|
-
return new ServiceContext(storage, level, networkManager, signalManager, undefined,
|
|
57
|
-
invitationConnectionDefaultParams: {
|
|
57
|
+
return new ServiceContext(storage, level, networkManager, signalManager, undefined, {
|
|
58
|
+
invitationConnectionDefaultParams: { controlHeartbeatInterval: 200 },
|
|
58
59
|
...runtimeParams,
|
|
59
60
|
});
|
|
60
61
|
};
|
|
@@ -218,10 +219,6 @@ export class TestPeer {
|
|
|
218
219
|
|
|
219
220
|
async createIdentity() {
|
|
220
221
|
this._props.signingContext ??= await createSigningContext(this.keyring);
|
|
221
|
-
this.networkManager.setPeerInfo({
|
|
222
|
-
identityKey: this._props.signingContext.identityKey.toHex(),
|
|
223
|
-
peerKey: this._props.signingContext.deviceKey.toHex(),
|
|
224
|
-
});
|
|
225
222
|
}
|
|
226
223
|
|
|
227
224
|
async destroy() {
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
WebsocketSignalManager,
|
|
15
15
|
setIdentityTags,
|
|
16
16
|
} from '@dxos/messaging';
|
|
17
|
-
import {
|
|
17
|
+
import { SimplePeerTransportProxyFactory } from '@dxos/network-manager';
|
|
18
18
|
import { type RpcPort } from '@dxos/rpc';
|
|
19
19
|
import { type MaybePromise } from '@dxos/util';
|
|
20
20
|
|
|
@@ -46,7 +46,7 @@ export class WorkerRuntime {
|
|
|
46
46
|
private readonly _acquireLock: () => Promise<void>;
|
|
47
47
|
private readonly _releaseLock: () => void;
|
|
48
48
|
private readonly _onStop?: () => Promise<void>;
|
|
49
|
-
private readonly _transportFactory = new
|
|
49
|
+
private readonly _transportFactory = new SimplePeerTransportProxyFactory();
|
|
50
50
|
private readonly _ready = new Trigger<Error | undefined>();
|
|
51
51
|
private readonly _sessions = new Set<WorkerSession>();
|
|
52
52
|
private readonly _clientServices!: ClientServicesHost;
|
package/src/version.ts
CHANGED