@dxos/client-services 0.8.4-main.ae835ea → 0.8.4-main.bc2380dfbc
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +102 -5
- package/README.md +1 -1
- package/dist/lib/browser/chunk-QCWEHHJW.mjs +24 -0
- package/dist/lib/browser/chunk-QCWEHHJW.mjs.map +7 -0
- package/dist/lib/browser/{chunk-KPYVJG6G.mjs → chunk-TUCJORVO.mjs} +2153 -3654
- package/dist/lib/browser/chunk-TUCJORVO.mjs.map +7 -0
- package/dist/lib/browser/chunk-XJRPB3GA.mjs +22 -0
- package/dist/lib/browser/chunk-XJRPB3GA.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +424 -137
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs +88 -0
- package/dist/lib/browser/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +7 -0
- package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs +11 -0
- package/dist/lib/browser/packlets/diagnostics/diagnostics-broadcast.mjs.map +7 -0
- package/dist/lib/browser/packlets/locks/browser.mjs +86 -0
- package/dist/lib/browser/packlets/locks/browser.mjs.map +7 -0
- package/dist/lib/browser/packlets/locks/node.mjs +48 -0
- package/dist/lib/browser/packlets/locks/node.mjs.map +7 -0
- package/dist/lib/browser/testing/index.mjs +28 -29
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/chunk-2DT3MZRL.mjs +22 -0
- package/dist/lib/node-esm/chunk-2DT3MZRL.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-2SZHAWBN.mjs +24 -0
- package/dist/lib/node-esm/chunk-2SZHAWBN.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-BBBSS6UL.mjs → chunk-IQLAKNSR.mjs} +2099 -3469
- package/dist/lib/node-esm/chunk-IQLAKNSR.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +424 -137
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs +88 -0
- package/dist/lib/node-esm/packlets/diagnostics/browser-diagnostics-broadcast.mjs.map +7 -0
- package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs +11 -0
- package/dist/lib/node-esm/packlets/diagnostics/diagnostics-broadcast.mjs.map +7 -0
- package/dist/lib/node-esm/packlets/locks/browser.mjs +86 -0
- package/dist/lib/node-esm/packlets/locks/browser.mjs.map +7 -0
- package/dist/lib/node-esm/packlets/locks/node.mjs +48 -0
- package/dist/lib/node-esm/packlets/locks/node.mjs.map +7 -0
- package/dist/lib/node-esm/testing/index.mjs +28 -29
- 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 +2 -1
- package/dist/types/src/packlets/agents/edge-agent-service.d.ts.map +1 -1
- package/dist/types/src/packlets/devices/devices-service.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/devtools.d.ts +2 -2
- package/dist/types/src/packlets/devtools/devtools.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/feeds.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/keys.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/metadata.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/network.d.ts.map +1 -1
- package/dist/types/src/packlets/devtools/spaces.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/browser-diagnostics-broadcast.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/diagnostics-broadcast.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/diagnostics-collector.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/diagnostics.d.ts +2 -3
- package/dist/types/src/packlets/diagnostics/diagnostics.d.ts.map +1 -1
- package/dist/types/src/packlets/diagnostics/index.d.ts +1 -1
- package/dist/types/src/packlets/diagnostics/index.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/authenticator.d.ts +2 -2
- package/dist/types/src/packlets/identity/authenticator.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 +6 -6
- package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts +8 -7
- package/dist/types/src/packlets/identity/identity-recovery-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-service.d.ts +6 -10
- package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity.d.ts +8 -11
- package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +6 -5
- 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 +1 -1
- package/dist/types/src/packlets/invitations/edge-invitation-handler.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-protocol.d.ts +7 -4
- package/dist/types/src/packlets/invitations/invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-state.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-topology.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations-handler.d.ts +4 -4
- package/dist/types/src/packlets/invitations/invitations-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/invitations-service.d.ts +3 -3
- package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +4 -3
- package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/utils.d.ts.map +1 -1
- package/dist/types/src/packlets/locks/browser.d.ts.map +1 -1
- package/dist/types/src/packlets/locks/index.d.ts +1 -1
- package/dist/types/src/packlets/locks/index.d.ts.map +1 -1
- package/dist/types/src/packlets/locks/node.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 +5 -4
- package/dist/types/src/packlets/network/network-service.d.ts.map +1 -1
- package/dist/types/src/packlets/services/client-rpc-server.d.ts +5 -5
- package/dist/types/src/packlets/services/client-rpc-server.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 +13 -9
- package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts +20 -7
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-registry.d.ts.map +1 -1
- package/dist/types/src/packlets/services/util.d.ts.map +1 -1
- package/dist/types/src/packlets/space-export/archive-format.d.ts +9 -0
- package/dist/types/src/packlets/space-export/archive-format.d.ts.map +1 -0
- package/dist/types/src/packlets/space-export/index.d.ts +4 -1
- package/dist/types/src/packlets/space-export/index.d.ts.map +1 -1
- package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts +23 -0
- package/dist/types/src/packlets/space-export/serialized-space-reader.d.ts.map +1 -0
- package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts +36 -0
- package/dist/types/src/packlets/space-export/serialized-space-writer.d.ts.map +1 -0
- 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 +7 -1
- 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/automerge-space-state.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts +30 -19
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts +26 -9
- package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts +2 -2
- package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/epoch-migrations.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 +6 -9
- package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/spaces-service.d.ts +10 -7
- package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/level.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/profile-archive.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/storage.d.ts.map +1 -1
- package/dist/types/src/packlets/storage/util.d.ts.map +1 -1
- package/dist/types/src/packlets/system/system-service.d.ts +1 -1
- package/dist/types/src/packlets/system/system-service.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/credential-utils.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/invitation-utils.d.ts +6 -3
- package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/test-builder.d.ts +6 -5
- package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
- package/dist/types/src/packlets/worker/worker-runtime.d.ts +41 -4
- package/dist/types/src/packlets/worker/worker-runtime.d.ts.map +1 -1
- package/dist/types/src/packlets/worker/worker-session.d.ts +2 -4
- package/dist/types/src/packlets/worker/worker-session.d.ts.map +1 -1
- package/dist/types/src/testing/setup.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 +71 -56
- package/src/index.ts +1 -0
- package/src/packlets/agents/edge-agent-manager.ts +8 -5
- package/src/packlets/agents/edge-agent-service.ts +4 -2
- package/src/packlets/devices/devices-service.test.ts +0 -1
- package/src/packlets/devtools/devtools.ts +2 -3
- package/src/packlets/diagnostics/diagnostics.ts +1 -2
- package/src/packlets/diagnostics/index.ts +1 -1
- package/src/packlets/identity/authenticator.ts +2 -2
- 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 +23 -22
- package/src/packlets/identity/identity-recovery-manager.ts +22 -18
- package/src/packlets/identity/identity-service.test.ts +6 -27
- package/src/packlets/identity/identity-service.ts +13 -81
- package/src/packlets/identity/identity.test.ts +2 -2
- package/src/packlets/identity/identity.ts +11 -34
- package/src/packlets/invitations/device-invitation-protocol.ts +8 -7
- package/src/packlets/invitations/edge-invitation-handler.ts +9 -5
- package/src/packlets/invitations/invitation-guest-extenstion.ts +6 -4
- package/src/packlets/invitations/invitation-host-extension.ts +13 -14
- package/src/packlets/invitations/invitation-protocol.ts +7 -4
- package/src/packlets/invitations/invitation-state.ts +1 -15
- package/src/packlets/invitations/invitations-handler.test.ts +4 -5
- package/src/packlets/invitations/invitations-handler.ts +74 -22
- package/src/packlets/invitations/invitations-manager.ts +40 -15
- package/src/packlets/invitations/invitations-service.ts +9 -9
- package/src/packlets/invitations/space-invitation-protocol.test.ts +17 -16
- package/src/packlets/invitations/space-invitation-protocol.ts +11 -16
- package/src/packlets/locks/index.ts +1 -1
- package/src/packlets/logging/logging-service.ts +20 -16
- package/src/packlets/network/network-service.test.ts +0 -1
- package/src/packlets/network/network-service.ts +10 -8
- package/src/packlets/services/client-rpc-server.ts +19 -16
- package/src/packlets/services/feed-syncer.test.ts +340 -0
- package/src/packlets/services/feed-syncer.ts +377 -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 +153 -61
- package/src/packlets/services/service-host.test.ts +8 -8
- package/src/packlets/services/service-host.ts +70 -40
- package/src/packlets/services/service-registry.test.ts +0 -1
- package/src/packlets/space-export/archive-format.ts +42 -0
- package/src/packlets/space-export/index.ts +4 -1
- package/src/packlets/space-export/serialized-space-reader.ts +111 -0
- package/src/packlets/space-export/serialized-space-writer.ts +252 -0
- package/src/packlets/space-export/space-archive-reader.ts +64 -3
- package/src/packlets/space-export/space-archive-writer.ts +41 -3
- package/src/packlets/space-export/space-archive.test.ts +461 -0
- package/src/packlets/spaces/data-space-manager.test.ts +79 -13
- package/src/packlets/spaces/data-space-manager.ts +108 -120
- package/src/packlets/spaces/data-space.ts +64 -36
- package/src/packlets/spaces/edge-feed-replicator.test.ts +1 -1
- package/src/packlets/spaces/edge-feed-replicator.ts +11 -9
- package/src/packlets/spaces/epoch-migrations.ts +6 -5
- package/src/packlets/spaces/genesis.ts +6 -1
- package/src/packlets/spaces/notarization-plugin.test.ts +2 -2
- package/src/packlets/spaces/notarization-plugin.ts +10 -9
- package/src/packlets/spaces/spaces-service.test.ts +18 -11
- package/src/packlets/spaces/spaces-service.ts +124 -24
- package/src/packlets/storage/storage.ts +4 -4
- package/src/packlets/testing/invitation-utils.ts +10 -6
- package/src/packlets/testing/test-builder.ts +36 -10
- package/src/packlets/worker/worker-runtime.ts +188 -17
- package/src/packlets/worker/worker-session.ts +12 -18
- package/src/version.ts +1 -1
- package/dist/lib/browser/chunk-KPYVJG6G.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-BBBSS6UL.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
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { save } from '@automerge/automerge';
|
|
6
|
-
import { type DocHandle } from '@automerge/automerge-repo';
|
|
6
|
+
import { type AutomergeUrl, type DocHandle } from '@automerge/automerge-repo';
|
|
7
7
|
|
|
8
8
|
import { Event, Mutex, scheduleTask, sleep, synchronized, trackLeaks } from '@dxos/async';
|
|
9
9
|
import { AUTH_TIMEOUT } from '@dxos/client-protocol';
|
|
@@ -13,7 +13,6 @@ import { timed, warnAfterTimeout } from '@dxos/debug';
|
|
|
13
13
|
import {
|
|
14
14
|
type DatabaseRoot,
|
|
15
15
|
type EchoHost,
|
|
16
|
-
FIND_PARAMS,
|
|
17
16
|
type MetadataStore,
|
|
18
17
|
type Space,
|
|
19
18
|
createMappedFeedWriter,
|
|
@@ -25,7 +24,7 @@ import { failedInvariant, invariant } from '@dxos/invariant';
|
|
|
25
24
|
import { type Keyring } from '@dxos/keyring';
|
|
26
25
|
import { PublicKey } from '@dxos/keys';
|
|
27
26
|
import { log } from '@dxos/log';
|
|
28
|
-
import { CancelledError, SystemError } from '@dxos/protocols';
|
|
27
|
+
import { CancelledError, type FeedProtocol, SystemError } from '@dxos/protocols';
|
|
29
28
|
import {
|
|
30
29
|
type CreateEpochRequest,
|
|
31
30
|
type Space as SpaceProto,
|
|
@@ -38,6 +37,7 @@ import {
|
|
|
38
37
|
AdmittedFeed,
|
|
39
38
|
type Credential,
|
|
40
39
|
type Epoch,
|
|
40
|
+
MembershipPolicy,
|
|
41
41
|
type ProfileDocument,
|
|
42
42
|
SpaceMember,
|
|
43
43
|
} from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
@@ -48,7 +48,6 @@ import { trace } from '@dxos/tracing';
|
|
|
48
48
|
import { type AsyncCallback, CallbackCollection, ComplexSet } from '@dxos/util';
|
|
49
49
|
|
|
50
50
|
import { TrustedKeySetAuthVerifier } from '../identity';
|
|
51
|
-
|
|
52
51
|
import { AutomergeSpaceState } from './automerge-space-state';
|
|
53
52
|
import { type SigningContext } from './data-space-manager';
|
|
54
53
|
import { EdgeFeedReplicator } from './edge-feed-replicator';
|
|
@@ -72,7 +71,7 @@ export type DataSpaceCallbacks = {
|
|
|
72
71
|
beforeClose?: () => Promise<void>;
|
|
73
72
|
};
|
|
74
73
|
|
|
75
|
-
export type
|
|
74
|
+
export type DataSpaceProps = {
|
|
76
75
|
initialState: SpaceState;
|
|
77
76
|
inner: Space;
|
|
78
77
|
metadataStore: MetadataStore;
|
|
@@ -84,6 +83,7 @@ export type DataSpaceParams = {
|
|
|
84
83
|
signingContext: SigningContext;
|
|
85
84
|
callbacks?: DataSpaceCallbacks;
|
|
86
85
|
cache?: SpaceCache;
|
|
86
|
+
tags?: string[];
|
|
87
87
|
edgeConnection?: EdgeConnection;
|
|
88
88
|
edgeHttpClient?: EdgeHttpClient;
|
|
89
89
|
edgeFeatures?: Runtime.Client.EdgeFeatures;
|
|
@@ -121,6 +121,9 @@ export class DataSpace {
|
|
|
121
121
|
|
|
122
122
|
private _state = SpaceState.SPACE_CLOSED;
|
|
123
123
|
|
|
124
|
+
/** Immutable tags from space metadata, available immediately. */
|
|
125
|
+
readonly tags: string[];
|
|
126
|
+
|
|
124
127
|
private _databaseRoot: DatabaseRoot | null = null;
|
|
125
128
|
|
|
126
129
|
/**
|
|
@@ -136,7 +139,7 @@ export class DataSpace {
|
|
|
136
139
|
|
|
137
140
|
public metrics: SpaceProto.Metrics = {};
|
|
138
141
|
|
|
139
|
-
constructor(params:
|
|
142
|
+
constructor(params: DataSpaceProps) {
|
|
140
143
|
this._inner = params.inner;
|
|
141
144
|
this._inner.stateUpdate.on(this._ctx, () => this.stateUpdate.emit());
|
|
142
145
|
|
|
@@ -168,6 +171,7 @@ export class DataSpace {
|
|
|
168
171
|
});
|
|
169
172
|
|
|
170
173
|
this._cache = params.cache;
|
|
174
|
+
this.tags = params.tags ?? [];
|
|
171
175
|
|
|
172
176
|
if (params.edgeConnection && params.edgeFeatures?.feedReplicator) {
|
|
173
177
|
this._edgeFeedReplicator = new EdgeFeedReplicator({ messenger: params.edgeConnection, spaceId: this.id });
|
|
@@ -213,6 +217,11 @@ export class DataSpace {
|
|
|
213
217
|
return this._cache;
|
|
214
218
|
}
|
|
215
219
|
|
|
220
|
+
/** Membership policy from the genesis credential, defaults to INVITE. */
|
|
221
|
+
get membershipPolicy(): MembershipPolicy {
|
|
222
|
+
return this._inner.spaceState.genesisCredential ? this._inner.spaceState.membershipPolicy : MembershipPolicy.INVITE;
|
|
223
|
+
}
|
|
224
|
+
|
|
216
225
|
get automergeSpaceState() {
|
|
217
226
|
return this._automergeSpaceState;
|
|
218
227
|
}
|
|
@@ -230,13 +239,14 @@ export class DataSpace {
|
|
|
230
239
|
}
|
|
231
240
|
|
|
232
241
|
@synchronized
|
|
233
|
-
|
|
242
|
+
@trace.span({ showInBrowserTimeline: true, op: 'lifecycle' })
|
|
243
|
+
async open(ctx: Context): Promise<void> {
|
|
234
244
|
if (this._state === SpaceState.SPACE_CLOSED) {
|
|
235
|
-
await this._open();
|
|
245
|
+
await this._open(ctx);
|
|
236
246
|
}
|
|
237
247
|
}
|
|
238
248
|
|
|
239
|
-
private async _open(): Promise<void> {
|
|
249
|
+
private async _open(ctx: Context): Promise<void> {
|
|
240
250
|
await this._presence.open();
|
|
241
251
|
await this._gossip.open();
|
|
242
252
|
await this._notarizationPlugin.open();
|
|
@@ -248,8 +258,8 @@ export class DataSpace {
|
|
|
248
258
|
this.inner.protocol.feedAdded.append(this._onFeedAdded);
|
|
249
259
|
}
|
|
250
260
|
|
|
251
|
-
await this._inner.open(
|
|
252
|
-
await this._inner.startProtocol();
|
|
261
|
+
await this._inner.open(ctx);
|
|
262
|
+
await this._inner.startProtocol(ctx);
|
|
253
263
|
|
|
254
264
|
await this._edgeFeedReplicator?.open();
|
|
255
265
|
|
|
@@ -263,11 +273,12 @@ export class DataSpace {
|
|
|
263
273
|
}
|
|
264
274
|
|
|
265
275
|
@synchronized
|
|
266
|
-
|
|
267
|
-
|
|
276
|
+
@trace.span({ showInBrowserTimeline: true, op: 'lifecycle' })
|
|
277
|
+
async close(ctx: Context): Promise<void> {
|
|
278
|
+
await this._close(ctx);
|
|
268
279
|
}
|
|
269
280
|
|
|
270
|
-
private async _close(): Promise<void> {
|
|
281
|
+
private async _close(ctx: Context): Promise<void> {
|
|
271
282
|
await this._callbacks.beforeClose?.();
|
|
272
283
|
|
|
273
284
|
await this.preClose.callSerial();
|
|
@@ -285,7 +296,7 @@ export class DataSpace {
|
|
|
285
296
|
|
|
286
297
|
await this.authVerifier.close();
|
|
287
298
|
|
|
288
|
-
await this._inner.close();
|
|
299
|
+
await this._inner.close(ctx);
|
|
289
300
|
await this._inner.spaceState.removeCredentialProcessor(this._automergeSpaceState);
|
|
290
301
|
await this._automergeSpaceState.close();
|
|
291
302
|
await this._inner.spaceState.removeCredentialProcessor(this._notarizationPlugin);
|
|
@@ -305,12 +316,14 @@ export class DataSpace {
|
|
|
305
316
|
|
|
306
317
|
/**
|
|
307
318
|
* Initialize the data pipeline in a separate task.
|
|
319
|
+
* @param callerCtx - Trace context from the caller (e.g., activate or createSpace) for span parenting.
|
|
308
320
|
*/
|
|
309
|
-
initializeDataPipelineAsync(): void {
|
|
321
|
+
initializeDataPipelineAsync(callerCtx?: Context): void {
|
|
322
|
+
const traceCtx = callerCtx ?? this._ctx;
|
|
310
323
|
scheduleTask(this._ctx, async () => {
|
|
311
324
|
try {
|
|
312
325
|
this.metrics.pipelineInitBegin = new Date();
|
|
313
|
-
await this.initializeDataPipeline();
|
|
326
|
+
await this.initializeDataPipeline(traceCtx);
|
|
314
327
|
} catch (err) {
|
|
315
328
|
if (err instanceof CancelledError || err instanceof ContextDisposedError) {
|
|
316
329
|
log('data pipeline initialization cancelled', err);
|
|
@@ -328,17 +341,17 @@ export class DataSpace {
|
|
|
328
341
|
});
|
|
329
342
|
}
|
|
330
343
|
|
|
331
|
-
@trace.span({ showInBrowserTimeline: true })
|
|
332
|
-
async initializeDataPipeline(): Promise<void> {
|
|
344
|
+
@trace.span({ showInBrowserTimeline: true, op: 'lifecycle' })
|
|
345
|
+
async initializeDataPipeline(ctx: Context): Promise<void> {
|
|
333
346
|
if (this._state !== SpaceState.SPACE_CONTROL_ONLY) {
|
|
334
|
-
throw new SystemError('Invalid operation');
|
|
347
|
+
throw new SystemError({ message: 'Invalid operation' });
|
|
335
348
|
}
|
|
336
349
|
|
|
337
350
|
this._state = SpaceState.SPACE_INITIALIZING;
|
|
338
351
|
log('new state', { state: SpaceState[this._state] });
|
|
339
352
|
|
|
340
353
|
log('initializing control pipeline');
|
|
341
|
-
await this._initializeAndReadControlPipeline();
|
|
354
|
+
await this._initializeAndReadControlPipeline(ctx);
|
|
342
355
|
|
|
343
356
|
// Allow other tasks to run before loading the data pipeline.
|
|
344
357
|
await sleep(1);
|
|
@@ -361,11 +374,19 @@ export class DataSpace {
|
|
|
361
374
|
yield [this._databaseRoot.documentId, root];
|
|
362
375
|
|
|
363
376
|
for (const documentUrl of this._databaseRoot.getAllLinkedDocuments()) {
|
|
364
|
-
const data = await this._echoHost.exportDoc(
|
|
377
|
+
const data = await this._echoHost.exportDoc(documentUrl);
|
|
365
378
|
yield [documentUrl.replace(/^automerge:/, ''), data];
|
|
366
379
|
}
|
|
367
380
|
}
|
|
368
381
|
|
|
382
|
+
/**
|
|
383
|
+
* Get all feeds and their blocks for this space.
|
|
384
|
+
* Used for space archive export.
|
|
385
|
+
*/
|
|
386
|
+
async getAllFeeds(): Promise<Array<{ feedId: string; feedNamespace: string; blocks: FeedProtocol.Block[] }>> {
|
|
387
|
+
return this._echoHost.getAllFeedsForSpace(this.id);
|
|
388
|
+
}
|
|
389
|
+
|
|
369
390
|
private async _enterReadyState(): Promise<void> {
|
|
370
391
|
await this._callbacks.beforeReady?.();
|
|
371
392
|
|
|
@@ -376,10 +397,10 @@ export class DataSpace {
|
|
|
376
397
|
await this._callbacks.afterReady?.();
|
|
377
398
|
}
|
|
378
399
|
|
|
379
|
-
@trace.span({ showInBrowserTimeline: true })
|
|
380
|
-
private async _initializeAndReadControlPipeline(): Promise<void> {
|
|
400
|
+
@trace.span({ showInBrowserTimeline: true, op: 'lifecycle' })
|
|
401
|
+
private async _initializeAndReadControlPipeline(ctx: Context): Promise<void> {
|
|
381
402
|
await this._inner.controlPipeline.state.waitUntilReachedTargetTimeframe({
|
|
382
|
-
ctx
|
|
403
|
+
ctx,
|
|
383
404
|
timeout: 10_000,
|
|
384
405
|
breakOnStall: false,
|
|
385
406
|
});
|
|
@@ -451,6 +472,9 @@ export class DataSpace {
|
|
|
451
472
|
|
|
452
473
|
log('credentials notarized');
|
|
453
474
|
} catch (err) {
|
|
475
|
+
if (err instanceof ContextDisposedError) {
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
454
478
|
log.error('error notarizing credentials for feed admission', err);
|
|
455
479
|
throw err;
|
|
456
480
|
}
|
|
@@ -463,7 +487,7 @@ export class DataSpace {
|
|
|
463
487
|
private _onNewAutomergeRoot(rootUrl: string): void {
|
|
464
488
|
log('loading automerge root doc for space', { space: this.key, rootUrl });
|
|
465
489
|
|
|
466
|
-
let handle: DocHandle<DatabaseDirectory
|
|
490
|
+
let handle: DocHandle<DatabaseDirectory> | null = null;
|
|
467
491
|
|
|
468
492
|
// TODO(dmaretskyi): Make this single-threaded (but doc loading should still be parallel to not block epoch processing).
|
|
469
493
|
queueMicrotask(async () => {
|
|
@@ -471,19 +495,24 @@ export class DataSpace {
|
|
|
471
495
|
await warnAfterTimeout(5_000, 'Automerge root doc load timeout (DataSpace)', async () => {
|
|
472
496
|
handle = await cancelWithContext(
|
|
473
497
|
this._ctx,
|
|
474
|
-
this._echoHost.
|
|
498
|
+
this._echoHost.loadDoc<DatabaseDirectory>(this._ctx, rootUrl as AutomergeUrl, {
|
|
499
|
+
fetchFromNetwork: true,
|
|
500
|
+
}),
|
|
475
501
|
);
|
|
476
|
-
await cancelWithContext(this._ctx, handle.whenReady());
|
|
477
502
|
});
|
|
478
503
|
if (this._ctx.disposed) {
|
|
479
504
|
return;
|
|
480
505
|
}
|
|
506
|
+
if (!handle) {
|
|
507
|
+
log.warn('automerge root doc not available yet', { space: this.key, rootUrl });
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
481
510
|
|
|
482
511
|
// Ensure only one root is processed at a time.
|
|
483
512
|
using _guard = await this._epochProcessingMutex.acquire();
|
|
484
513
|
|
|
485
514
|
// Attaching space keys to legacy documents.
|
|
486
|
-
const doc = handle.doc()
|
|
515
|
+
const doc = handle.doc();
|
|
487
516
|
if (!doc.access?.spaceKey) {
|
|
488
517
|
handle.change((doc: any) => {
|
|
489
518
|
doc.access = { spaceKey: this.key.toHex() };
|
|
@@ -492,7 +521,7 @@ export class DataSpace {
|
|
|
492
521
|
|
|
493
522
|
// TODO(dmaretskyi): Close roots.
|
|
494
523
|
// TODO(dmaretskyi): How do we handle changing to the next EPOCH?
|
|
495
|
-
const root = await this._echoHost.openSpaceRoot(this.id, handle.url);
|
|
524
|
+
const root = await this._echoHost.openSpaceRoot(this._ctx, this.id, handle.url);
|
|
496
525
|
|
|
497
526
|
// NOTE: Make sure this assignment happens synchronously together with the state change.
|
|
498
527
|
this._databaseRoot = root;
|
|
@@ -569,25 +598,24 @@ export class DataSpace {
|
|
|
569
598
|
}
|
|
570
599
|
|
|
571
600
|
@synchronized
|
|
572
|
-
async activate(): Promise<void> {
|
|
601
|
+
async activate(ctx: Context): Promise<void> {
|
|
573
602
|
if (![SpaceState.SPACE_CLOSED, SpaceState.SPACE_INACTIVE].includes(this._state)) {
|
|
574
603
|
return;
|
|
575
604
|
}
|
|
576
605
|
|
|
577
606
|
await this._metadataStore.setSpaceState(this.key, SpaceState.SPACE_ACTIVE);
|
|
578
|
-
await this._open();
|
|
579
|
-
this.initializeDataPipelineAsync();
|
|
607
|
+
await this._open(ctx);
|
|
608
|
+
this.initializeDataPipelineAsync(ctx);
|
|
580
609
|
}
|
|
581
610
|
|
|
582
611
|
@synchronized
|
|
583
|
-
async deactivate(): Promise<void> {
|
|
612
|
+
async deactivate(ctx: Context): Promise<void> {
|
|
584
613
|
if (this._state === SpaceState.SPACE_INACTIVE) {
|
|
585
614
|
return;
|
|
586
615
|
}
|
|
587
|
-
// Unregister from data service.
|
|
588
616
|
await this._metadataStore.setSpaceState(this.key, SpaceState.SPACE_INACTIVE);
|
|
589
617
|
if (this._state !== SpaceState.SPACE_CLOSED) {
|
|
590
|
-
await this._close();
|
|
618
|
+
await this._close(ctx);
|
|
591
619
|
}
|
|
592
620
|
this._state = SpaceState.SPACE_INACTIVE;
|
|
593
621
|
log('new state', { state: SpaceState[this._state] });
|
|
@@ -107,7 +107,7 @@ describe('EdgeFeedReplicator', () => {
|
|
|
107
107
|
const { feed } = await attachReplicator(messenger);
|
|
108
108
|
await appendMessage(feed);
|
|
109
109
|
|
|
110
|
-
sendSpy.mockImplementationOnce(async (request: any) => {
|
|
110
|
+
sendSpy.mockImplementationOnce(async (_ctx: any, request: any) => {
|
|
111
111
|
sendResponseMessage(request, encodeCbor({ type: 'metadata', feedKey: feed.key.toHex(), length: 0 }));
|
|
112
112
|
return Promise.resolve();
|
|
113
113
|
});
|
|
@@ -22,7 +22,7 @@ import type { FeedBlock, ProtocolMessage } from '@dxos/protocols/feed-replicatio
|
|
|
22
22
|
import { EdgeStatus } from '@dxos/protocols/proto/dxos/client/services';
|
|
23
23
|
import { ComplexMap, arrayToBuffer, bufferToArray, defaultMap, rangeFromTo } from '@dxos/util';
|
|
24
24
|
|
|
25
|
-
export type
|
|
25
|
+
export type EdgeFeedReplicatorProps = {
|
|
26
26
|
messenger: EdgeConnection;
|
|
27
27
|
spaceId: SpaceId;
|
|
28
28
|
};
|
|
@@ -47,7 +47,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
47
47
|
*/
|
|
48
48
|
private _pushMutex = new ComplexMap<PublicKey, Mutex>(PublicKey.hash);
|
|
49
49
|
|
|
50
|
-
constructor({ messenger, spaceId }:
|
|
50
|
+
constructor({ messenger, spaceId }: EdgeFeedReplicatorProps) {
|
|
51
51
|
super();
|
|
52
52
|
this._messenger = messenger;
|
|
53
53
|
this._spaceId = spaceId;
|
|
@@ -132,7 +132,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
132
132
|
|
|
133
133
|
private async _replicateFeed(ctx: Context, feed: FeedWrapper<any>): Promise<void> {
|
|
134
134
|
log('replicateFeed', { key: feed.key });
|
|
135
|
-
await this._sendMessage({
|
|
135
|
+
await this._sendMessage(ctx, {
|
|
136
136
|
type: 'get-metadata',
|
|
137
137
|
feedKey: feed.key.toHex(),
|
|
138
138
|
});
|
|
@@ -142,7 +142,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
142
142
|
});
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
-
private async _sendMessage(message: ProtocolMessage): Promise<void> {
|
|
145
|
+
private async _sendMessage(ctx: Context, message: ProtocolMessage): Promise<void> {
|
|
146
146
|
if (!this._connectionCtx) {
|
|
147
147
|
log('message dropped because connection was disposed');
|
|
148
148
|
return;
|
|
@@ -160,6 +160,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
160
160
|
|
|
161
161
|
log('send', { type: message.type });
|
|
162
162
|
await this._messenger.send(
|
|
163
|
+
ctx,
|
|
163
164
|
buf.create(RouterMessageSchema, {
|
|
164
165
|
source: {
|
|
165
166
|
identityKey: this._messenger.identityKey,
|
|
@@ -194,7 +195,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
194
195
|
if (message.length > feed.length) {
|
|
195
196
|
log('requesting missing blocks', logMeta);
|
|
196
197
|
|
|
197
|
-
await this._sendMessage({
|
|
198
|
+
await this._sendMessage(this._connectionCtx!, {
|
|
198
199
|
type: 'request',
|
|
199
200
|
feedKey: feedKey.toHex(),
|
|
200
201
|
range: { from: feed.length, to: message.length },
|
|
@@ -202,7 +203,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
202
203
|
} else if (message.length < feed.length) {
|
|
203
204
|
log('pushing blocks to remote', logMeta);
|
|
204
205
|
|
|
205
|
-
await this._pushBlocks(feed, message.length, feed.length);
|
|
206
|
+
await this._pushBlocks(this._connectionCtx!, feed, message.length, feed.length);
|
|
206
207
|
}
|
|
207
208
|
|
|
208
209
|
break;
|
|
@@ -229,7 +230,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
229
230
|
});
|
|
230
231
|
}
|
|
231
232
|
|
|
232
|
-
private async _pushBlocks(feed: FeedWrapper<any>, from: number, to: number): Promise<void> {
|
|
233
|
+
private async _pushBlocks(ctx: Context, feed: FeedWrapper<any>, from: number, to: number): Promise<void> {
|
|
233
234
|
log('pushing blocks', { feed: feed.key.toHex(), from, to });
|
|
234
235
|
|
|
235
236
|
const blocks: FeedBlock[] = await Promise.all(
|
|
@@ -247,7 +248,7 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
247
248
|
}),
|
|
248
249
|
);
|
|
249
250
|
|
|
250
|
-
await this._sendMessage({
|
|
251
|
+
await this._sendMessage(ctx, {
|
|
251
252
|
type: 'data',
|
|
252
253
|
feedKey: feed.key.toHex(),
|
|
253
254
|
blocks,
|
|
@@ -283,12 +284,13 @@ export class EdgeFeedReplicator extends Resource {
|
|
|
283
284
|
|
|
284
285
|
const remoteLength = this._remoteLength.get(feed.key)!;
|
|
285
286
|
if (remoteLength < feed.length) {
|
|
286
|
-
await this._pushBlocks(feed, remoteLength, feed.length);
|
|
287
|
+
await this._pushBlocks(this._connectionCtx!, feed, remoteLength, feed.length);
|
|
287
288
|
}
|
|
288
289
|
}
|
|
289
290
|
|
|
290
291
|
private _createConnectionContext(): Context {
|
|
291
292
|
const connectionCtx = new Context({
|
|
293
|
+
parent: this._ctx,
|
|
292
294
|
onError: async (err: any) => {
|
|
293
295
|
if (connectionCtx !== this._connectionCtx) {
|
|
294
296
|
return;
|
|
@@ -36,8 +36,8 @@ const LOAD_DOC_TIMEOUT = 10_000;
|
|
|
36
36
|
export const runEpochMigration = async (ctx: Context, context: MigrationContext): Promise<MigrationResult> => {
|
|
37
37
|
switch (context.migration) {
|
|
38
38
|
case CreateEpochRequest.Migration.INIT_AUTOMERGE: {
|
|
39
|
-
const document = context.echoHost.createDoc();
|
|
40
|
-
await context.echoHost.flush();
|
|
39
|
+
const document = await context.echoHost.createDoc();
|
|
40
|
+
await context.echoHost.flush(ctx);
|
|
41
41
|
return { newRoot: document.url };
|
|
42
42
|
}
|
|
43
43
|
case CreateEpochRequest.Migration.PRUNE_AUTOMERGE_ROOT_HISTORY: {
|
|
@@ -47,9 +47,10 @@ export const runEpochMigration = async (ctx: Context, context: MigrationContext)
|
|
|
47
47
|
const rootHandle = await context.echoHost.loadDoc(ctx, context.currentRoot as AutomergeUrl, {
|
|
48
48
|
timeout: LOAD_DOC_TIMEOUT,
|
|
49
49
|
});
|
|
50
|
+
invariant(rootHandle, 'Automerge root document must load for history prune migration.');
|
|
50
51
|
|
|
51
|
-
const newRoot = context.echoHost.createDoc(rootHandle.doc());
|
|
52
|
-
await context.echoHost.flush();
|
|
52
|
+
const newRoot = await context.echoHost.createDoc(rootHandle.doc());
|
|
53
|
+
await context.echoHost.flush(ctx);
|
|
53
54
|
return { newRoot: newRoot.url };
|
|
54
55
|
}
|
|
55
56
|
case CreateEpochRequest.Migration.FRAGMENT_AUTOMERGE_ROOT: {
|
|
@@ -63,7 +64,7 @@ export const runEpochMigration = async (ctx: Context, context: MigrationContext)
|
|
|
63
64
|
invariant(context.newAutomergeRoot);
|
|
64
65
|
|
|
65
66
|
// Defensive programming - it should be the responsibility of the caller to flush the new root.
|
|
66
|
-
await context.echoHost.flush();
|
|
67
|
+
await context.echoHost.flush(ctx);
|
|
67
68
|
return {
|
|
68
69
|
newRoot: context.newAutomergeRoot,
|
|
69
70
|
};
|
|
@@ -6,7 +6,7 @@ import { createCredential } from '@dxos/credentials';
|
|
|
6
6
|
import { failUndefined } from '@dxos/debug';
|
|
7
7
|
import { type Space } from '@dxos/echo-pipeline';
|
|
8
8
|
import { type Keyring } from '@dxos/keyring';
|
|
9
|
-
import { AdmittedFeed, SpaceMember } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
9
|
+
import { AdmittedFeed, MembershipPolicy, SpaceMember } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
10
10
|
import { Timeframe } from '@dxos/timeframe';
|
|
11
11
|
|
|
12
12
|
import { type SigningContext } from './data-space-manager';
|
|
@@ -16,6 +16,8 @@ export const spaceGenesis = async (
|
|
|
16
16
|
signingContext: SigningContext,
|
|
17
17
|
space: Space,
|
|
18
18
|
automergeRoot?: string,
|
|
19
|
+
tags?: string[],
|
|
20
|
+
membershipPolicy?: MembershipPolicy,
|
|
19
21
|
) => {
|
|
20
22
|
// TODO(dmaretskyi): Find a way to reconcile with credential generator.
|
|
21
23
|
const credentials = [
|
|
@@ -26,6 +28,8 @@ export const spaceGenesis = async (
|
|
|
26
28
|
assertion: {
|
|
27
29
|
'@type': 'dxos.halo.credentials.SpaceGenesis',
|
|
28
30
|
spaceKey: space.key,
|
|
31
|
+
tags: tags ?? [],
|
|
32
|
+
membershipPolicy: membershipPolicy ?? MembershipPolicy.INVITE,
|
|
29
33
|
},
|
|
30
34
|
}),
|
|
31
35
|
|
|
@@ -39,6 +43,7 @@ export const spaceGenesis = async (
|
|
|
39
43
|
role: SpaceMember.Role.OWNER,
|
|
40
44
|
profile: signingContext.getProfile(),
|
|
41
45
|
genesisFeedKey: space.controlFeedKey ?? failUndefined(),
|
|
46
|
+
tags: tags ?? [],
|
|
42
47
|
},
|
|
43
48
|
}),
|
|
44
49
|
|
|
@@ -13,7 +13,7 @@ import { log } from '@dxos/log';
|
|
|
13
13
|
import { AdmittedFeed, type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
14
14
|
import { TestBuilder, type TestConnection, TestPeer } from '@dxos/teleport/testing';
|
|
15
15
|
|
|
16
|
-
import { NotarizationPlugin, type
|
|
16
|
+
import { NotarizationPlugin, type NotarizationPluginProps } from './notarization-plugin';
|
|
17
17
|
|
|
18
18
|
class TestAgent extends TestPeer {
|
|
19
19
|
private readonly _ctx = new Context();
|
|
@@ -21,7 +21,7 @@ class TestAgent extends TestPeer {
|
|
|
21
21
|
feed = new MockFeedWriter<Credential>();
|
|
22
22
|
notarizationPlugin: NotarizationPlugin;
|
|
23
23
|
|
|
24
|
-
constructor(params:
|
|
24
|
+
constructor(params: NotarizationPluginProps) {
|
|
25
25
|
super();
|
|
26
26
|
this.notarizationPlugin = new NotarizationPlugin(params);
|
|
27
27
|
this.feed.written.on(this._ctx, async ([credential]) => {
|
|
@@ -33,14 +33,14 @@ const WRITER_NOT_SET_ERROR_CODE = 'WRITER_NOT_SET';
|
|
|
33
33
|
|
|
34
34
|
const credentialCodec = schema.getCodecForType('dxos.halo.credentials.Credential');
|
|
35
35
|
|
|
36
|
-
export type
|
|
36
|
+
export type NotarizationPluginProps = {
|
|
37
37
|
spaceId: SpaceId;
|
|
38
38
|
edgeClient?: EdgeHttpClient;
|
|
39
39
|
edgeFeatures?: Runtime.Client.EdgeFeatures;
|
|
40
40
|
activeEdgePollingInterval?: number;
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
-
export type
|
|
43
|
+
export type NotarizeProps = {
|
|
44
44
|
/**
|
|
45
45
|
* For cancellation.
|
|
46
46
|
*/
|
|
@@ -97,7 +97,7 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
|
|
|
97
97
|
|
|
98
98
|
private readonly _edgeClient: EdgeHttpClient | undefined;
|
|
99
99
|
|
|
100
|
-
constructor(params:
|
|
100
|
+
constructor(params: NotarizationPluginProps) {
|
|
101
101
|
super();
|
|
102
102
|
this._spaceId = params.spaceId;
|
|
103
103
|
this._activeEdgePollingInterval = params.activeEdgePollingInterval ?? DEFAULT_ACTIVE_EDGE_POLLING_INTERVAL;
|
|
@@ -149,7 +149,7 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
|
|
|
149
149
|
retryTimeout = DEFAULT_RETRY_TIMEOUT,
|
|
150
150
|
successDelay = DEFAULT_SUCCESS_DELAY,
|
|
151
151
|
edgeRetryJitter,
|
|
152
|
-
}:
|
|
152
|
+
}: NotarizeProps): Promise<void> {
|
|
153
153
|
log('notarize', { credentials });
|
|
154
154
|
invariant(
|
|
155
155
|
credentials.every((credential) => credential.id),
|
|
@@ -246,6 +246,7 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
|
|
|
246
246
|
scheduleTask(ctx, async () => {
|
|
247
247
|
try {
|
|
248
248
|
await client.notarizeCredentials(
|
|
249
|
+
ctx,
|
|
249
250
|
this._spaceId,
|
|
250
251
|
{ credentials: encodedCredentials },
|
|
251
252
|
{ retry: { count: MAX_EDGE_RETRIES, timeout: timeouts.retryTimeout, jitter: timeouts.jitter } },
|
|
@@ -302,7 +303,7 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
|
|
|
302
303
|
private _notarizePendingEdgeCredentials(client: EdgeHttpClient, writer: FeedWriter<Credential>): void {
|
|
303
304
|
scheduleMicroTask(this._ctx, async () => {
|
|
304
305
|
try {
|
|
305
|
-
const response = await client.getCredentialsForNotarization(this._spaceId, {
|
|
306
|
+
const response = await client.getCredentialsForNotarization(this._ctx, this._spaceId, {
|
|
306
307
|
retry: { count: MAX_EDGE_RETRIES },
|
|
307
308
|
});
|
|
308
309
|
|
|
@@ -392,21 +393,21 @@ export class NotarizationPlugin extends Resource implements CredentialProcessor
|
|
|
392
393
|
}
|
|
393
394
|
|
|
394
395
|
const handleEdgeError = (error: any) => {
|
|
395
|
-
if (!(error instanceof EdgeCallFailedError) || error.
|
|
396
|
+
if (!(error instanceof EdgeCallFailedError) || error.data) {
|
|
396
397
|
log.catch(error);
|
|
397
398
|
} else {
|
|
398
|
-
log.info('Edge notarization failure', {
|
|
399
|
+
log.info('Edge notarization failure', { message: error.message });
|
|
399
400
|
}
|
|
400
401
|
};
|
|
401
402
|
|
|
402
|
-
export type
|
|
403
|
+
export type NotarizationTeleportExtensionProps = {
|
|
403
404
|
onOpen: () => Promise<void>;
|
|
404
405
|
onClose: () => Promise<void>;
|
|
405
406
|
onNotarize: (request: NotarizeRequest) => Promise<void>;
|
|
406
407
|
};
|
|
407
408
|
|
|
408
409
|
export class NotarizationTeleportExtension extends RpcExtension<Services, Services> {
|
|
409
|
-
constructor(private readonly _params:
|
|
410
|
+
constructor(private readonly _params: NotarizationTeleportExtensionProps) {
|
|
410
411
|
super({
|
|
411
412
|
requested: {
|
|
412
413
|
NotarizationService: schema.getService('dxos.mesh.teleport.notarization.NotarizationService'),
|
|
@@ -8,10 +8,10 @@ import { Trigger } from '@dxos/async';
|
|
|
8
8
|
import { Context } from '@dxos/context';
|
|
9
9
|
import { PublicKey } from '@dxos/keys';
|
|
10
10
|
import { type Space, type SpacesService } from '@dxos/protocols/proto/dxos/client/services';
|
|
11
|
+
import { MembershipPolicy } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
11
12
|
|
|
12
13
|
import { type ServiceContext } from '../services';
|
|
13
14
|
import { createServiceContext } from '../testing';
|
|
14
|
-
|
|
15
15
|
import { SpacesServiceImpl } from './spaces-service';
|
|
16
16
|
|
|
17
17
|
describe('SpacesService', () => {
|
|
@@ -21,10 +21,15 @@ describe('SpacesService', () => {
|
|
|
21
21
|
beforeEach(async () => {
|
|
22
22
|
serviceContext = await createServiceContext();
|
|
23
23
|
await serviceContext.open(new Context());
|
|
24
|
-
spacesService = new SpacesServiceImpl(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
spacesService = new SpacesServiceImpl(
|
|
25
|
+
serviceContext.identityManager,
|
|
26
|
+
serviceContext.spaceManager,
|
|
27
|
+
serviceContext.echoHost,
|
|
28
|
+
async () => {
|
|
29
|
+
await serviceContext.initialized.wait();
|
|
30
|
+
return serviceContext.dataSpaceManager!;
|
|
31
|
+
},
|
|
32
|
+
);
|
|
28
33
|
});
|
|
29
34
|
|
|
30
35
|
afterEach(async () => {
|
|
@@ -33,12 +38,14 @@ describe('SpacesService', () => {
|
|
|
33
38
|
|
|
34
39
|
describe('createSpace', () => {
|
|
35
40
|
test('fails if no identity is available', async () => {
|
|
36
|
-
await expect(spacesService.createSpace()).rejects.toBeInstanceOf(
|
|
41
|
+
await expect(spacesService.createSpace({ membershipPolicy: MembershipPolicy.INVITE })).rejects.toBeInstanceOf(
|
|
42
|
+
Error,
|
|
43
|
+
);
|
|
37
44
|
});
|
|
38
45
|
|
|
39
46
|
test('creates a new space', async () => {
|
|
40
47
|
await serviceContext.createIdentity();
|
|
41
|
-
const space = await spacesService.createSpace();
|
|
48
|
+
const space = await spacesService.createSpace({ membershipPolicy: MembershipPolicy.INVITE });
|
|
42
49
|
expect(space).to.exist;
|
|
43
50
|
expect(space.spaceKey).to.be.instanceof(PublicKey);
|
|
44
51
|
});
|
|
@@ -60,9 +67,9 @@ describe('SpacesService', () => {
|
|
|
60
67
|
test('returns list of existing spaces', async () => {
|
|
61
68
|
await serviceContext.createIdentity();
|
|
62
69
|
const existingSpaces = [
|
|
63
|
-
await spacesService.createSpace(),
|
|
64
|
-
await spacesService.createSpace(),
|
|
65
|
-
await spacesService.createSpace(),
|
|
70
|
+
await spacesService.createSpace({ membershipPolicy: MembershipPolicy.INVITE }),
|
|
71
|
+
await spacesService.createSpace({ membershipPolicy: MembershipPolicy.INVITE }),
|
|
72
|
+
await spacesService.createSpace({ membershipPolicy: MembershipPolicy.INVITE }),
|
|
66
73
|
];
|
|
67
74
|
|
|
68
75
|
const query = spacesService.querySpaces();
|
|
@@ -88,7 +95,7 @@ describe('SpacesService', () => {
|
|
|
88
95
|
expect(await result.wait()).to.be.length(0);
|
|
89
96
|
|
|
90
97
|
result.reset();
|
|
91
|
-
const space = await spacesService.createSpace();
|
|
98
|
+
const space = await spacesService.createSpace({ membershipPolicy: MembershipPolicy.INVITE });
|
|
92
99
|
const spaces = await result.wait();
|
|
93
100
|
expect(spaces).to.be.length(1);
|
|
94
101
|
expect(spaces?.[0].spaceKey.equals(space.spaceKey)).to.be.true;
|