@dxos/client-services 0.1.23 → 0.1.24-next.6b1f434
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-ZPZBLOQW.mjs +4086 -0
- package/dist/lib/browser/chunk-ZPZBLOQW.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +66 -3066
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/packlets/testing/index.mjs +198 -0
- package/dist/lib/browser/packlets/testing/index.mjs.map +7 -0
- package/dist/lib/node/index.cjs +1655 -669
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/packlets/testing/index.cjs +3806 -0
- package/dist/lib/node/packlets/testing/index.cjs.map +7 -0
- package/dist/types/src/packlets/deprecated/profile.d.ts +3 -1
- package/dist/types/src/packlets/deprecated/profile.d.ts.map +1 -1
- package/dist/types/src/packlets/deprecated/space.d.ts.map +1 -1
- package/dist/types/src/packlets/deprecated/system.d.ts +15 -9
- package/dist/types/src/packlets/deprecated/system.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/network.d.ts +3 -3
- 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/identity/authenticator.d.ts +2 -2
- package/dist/types/src/packlets/identity/authenticator.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity-manager.d.ts +8 -2
- package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity.d.ts +3 -2
- package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/halo-invitations-handler.d.ts +11 -3
- package/dist/types/src/packlets/invitations/halo-invitations-handler.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitations.d.ts +1 -1
- package/dist/types/src/packlets/invitations/invitations.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/space-invitations-handler.d.ts +1 -1
- package/dist/types/src/packlets/invitations/space-invitations-handler.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-context.d.ts +3 -1
- package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-context.test.d.ts +2 -0
- package/dist/types/src/packlets/services/service-context.test.d.ts.map +1 -0
- package/dist/types/src/packlets/services/service-definitions.d.ts +1 -1
- package/dist/types/src/packlets/services/service-definitions.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts +9 -6
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-registry.d.ts +4 -3
- package/dist/types/src/packlets/services/service-registry.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts +9 -2
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space.d.ts +18 -4
- package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/notarization-plugin.d.ts +50 -0
- package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -0
- package/dist/types/src/packlets/spaces/notarization-plugin.test.d.ts +2 -0
- package/dist/types/src/packlets/spaces/notarization-plugin.test.d.ts.map +1 -0
- package/dist/types/src/packlets/spaces/spaces-service.d.ts +3 -2
- package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/credential-utils.d.ts +8 -0
- package/dist/types/src/packlets/testing/credential-utils.d.ts.map +1 -0
- package/dist/types/src/packlets/testing/index.d.ts +2 -0
- package/dist/types/src/packlets/testing/index.d.ts.map +1 -1
- package/dist/types/src/packlets/testing/invitation-utils.d.ts +3 -0
- package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -0
- package/dist/types/src/packlets/testing/test-builder.d.ts +2 -2
- package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
- package/dist/types/src/packlets/vault/iframe-host-runtime.d.ts +35 -0
- package/dist/types/src/packlets/vault/iframe-host-runtime.d.ts.map +1 -0
- package/dist/types/src/packlets/vault/{iframe-runtime.d.ts → iframe-proxy-runtime.d.ts} +9 -4
- package/dist/types/src/packlets/vault/iframe-proxy-runtime.d.ts.map +1 -0
- package/dist/types/src/packlets/vault/index.d.ts +6 -1
- package/dist/types/src/packlets/vault/index.d.ts.map +1 -1
- package/dist/types/src/packlets/vault/services.d.ts +9 -1
- package/dist/types/src/packlets/vault/services.d.ts.map +1 -1
- package/dist/types/src/packlets/vault/shell-controller.d.ts +24 -0
- package/dist/types/src/packlets/vault/shell-controller.d.ts.map +1 -0
- package/dist/types/src/packlets/vault/shell-runtime.d.ts +45 -0
- package/dist/types/src/packlets/vault/shell-runtime.d.ts.map +1 -0
- package/dist/types/src/packlets/vault/vault-resource-lock.d.ts +19 -0
- package/dist/types/src/packlets/vault/vault-resource-lock.d.ts.map +1 -0
- package/dist/types/src/packlets/vault/worker-runtime.d.ts +2 -1
- package/dist/types/src/packlets/vault/worker-runtime.d.ts.map +1 -1
- package/dist/types/src/packlets/vault/worker-session.d.ts +7 -4
- package/dist/types/src/packlets/vault/worker-session.d.ts.map +1 -1
- package/package.json +30 -29
- package/src/packlets/deprecated/profile.ts +20 -2
- package/src/packlets/deprecated/space.ts +41 -37
- package/src/packlets/deprecated/system.ts +26 -13
- package/src/packlets/devtools/devtools.ts +4 -4
- package/src/packlets/devtools/feeds.ts +11 -6
- package/src/packlets/devtools/network.ts +20 -9
- package/src/packlets/devtools/spaces.ts +8 -7
- package/src/packlets/identity/authenticator.ts +12 -7
- package/src/packlets/identity/identity-manager.test.ts +25 -16
- package/src/packlets/identity/identity-manager.ts +23 -9
- package/src/packlets/identity/identity.test.ts +22 -23
- package/src/packlets/identity/identity.ts +11 -6
- package/src/packlets/invitations/halo-invitations-handler.test.ts +4 -45
- package/src/packlets/invitations/halo-invitations-handler.ts +33 -17
- package/src/packlets/invitations/invitations.ts +2 -1
- package/src/packlets/invitations/space-invitations-handler.test.ts +43 -26
- package/src/packlets/invitations/space-invitations-handler.ts +9 -12
- package/src/packlets/services/service-context.test.ts +56 -0
- package/src/packlets/services/service-context.ts +62 -6
- package/src/packlets/services/service-definitions.ts +1 -1
- package/src/packlets/services/service-host.test.ts +74 -5
- package/src/packlets/services/service-host.ts +86 -24
- package/src/packlets/services/service-registry.test.ts +2 -1
- package/src/packlets/services/service-registry.ts +5 -1
- package/src/packlets/spaces/data-space-manager.test.ts +72 -15
- package/src/packlets/spaces/data-space-manager.ts +53 -12
- package/src/packlets/spaces/data-space.ts +113 -14
- package/src/packlets/spaces/notarization-plugin.test.ts +81 -0
- package/src/packlets/spaces/notarization-plugin.ts +211 -0
- package/src/packlets/spaces/spaces-service.ts +10 -2
- package/src/packlets/testing/credential-utils.ts +28 -0
- package/src/packlets/testing/index.ts +2 -0
- package/src/packlets/testing/invitation-utils.ts +44 -0
- package/src/packlets/testing/test-builder.ts +14 -18
- package/src/packlets/vault/iframe-host-runtime.ts +131 -0
- package/src/packlets/vault/{iframe-runtime.ts → iframe-proxy-runtime.ts} +18 -3
- package/src/packlets/vault/index.ts +6 -1
- package/src/packlets/vault/services.ts +17 -1
- package/src/packlets/vault/shell-controller.ts +77 -0
- package/src/packlets/vault/shell-runtime.ts +133 -0
- package/src/packlets/vault/vault-resource-lock.ts +76 -0
- package/src/packlets/vault/worker-runtime.ts +16 -4
- package/src/packlets/vault/worker-session.ts +36 -26
- package/dist/types/src/packlets/vault/iframe-runtime.d.ts.map +0 -1
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
import assert from 'node:assert';
|
|
6
6
|
|
|
7
|
-
import { EventSubscriptions } from '@dxos/async';
|
|
8
7
|
import { Stream } from '@dxos/codec-protobuf';
|
|
9
8
|
import { todo } from '@dxos/debug';
|
|
10
9
|
import { log } from '@dxos/log';
|
|
@@ -94,29 +93,29 @@ export class SpaceServiceImpl implements SpaceService {
|
|
|
94
93
|
}
|
|
95
94
|
|
|
96
95
|
subscribeSpaces() {
|
|
97
|
-
return new Stream<SubscribeSpacesResponse>(({ next }) => {
|
|
98
|
-
const subscriptions = new EventSubscriptions();
|
|
99
|
-
|
|
96
|
+
return new Stream<SubscribeSpacesResponse>(({ next, ctx }) => {
|
|
100
97
|
const onUpdate = () => {
|
|
101
|
-
const spaces = Array.from(this.serviceContext.dataSpaceManager!.spaces.values())
|
|
102
|
-
(space)
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
98
|
+
const spaces = Array.from(this.serviceContext.dataSpaceManager!.spaces.values())
|
|
99
|
+
.filter((space) => this.serviceContext.dataServiceSubscriptions.getDataService(space.key)) // Skip spaces without data service available.
|
|
100
|
+
.map(
|
|
101
|
+
(space): Space => ({
|
|
102
|
+
publicKey: space.key,
|
|
103
|
+
isOpen: true,
|
|
104
|
+
isActive: true,
|
|
105
|
+
members: Array.from(space.inner.spaceState.members.values()).map((member) => ({
|
|
109
106
|
identityKey: member.key,
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
107
|
+
profile: {
|
|
108
|
+
identityKey: member.key,
|
|
109
|
+
displayName: member.assertion.profile?.displayName ?? humanize(member.key)
|
|
110
|
+
},
|
|
111
|
+
presence:
|
|
112
|
+
this.serviceContext.identityManager.identity?.identityKey.equals(member.key) ||
|
|
113
|
+
space.presence.getPeersOnline().filter(({ identityKey }) => identityKey.equals(member.key)).length > 0
|
|
114
|
+
? SpaceMember.PresenceState.ONLINE
|
|
115
|
+
: SpaceMember.PresenceState.OFFLINE
|
|
116
|
+
}))
|
|
117
|
+
})
|
|
118
|
+
);
|
|
120
119
|
log('update', { spaces });
|
|
121
120
|
next({ spaces });
|
|
122
121
|
};
|
|
@@ -128,25 +127,27 @@ export class SpaceServiceImpl implements SpaceService {
|
|
|
128
127
|
|
|
129
128
|
await this.serviceContext.initialized.wait();
|
|
130
129
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
130
|
+
// TODO(dmaretskyi): Create a pattern for subscribing to a set of objects.
|
|
131
|
+
const subscribeSpaces = () => {
|
|
132
|
+
for (const space of this.serviceContext.dataSpaceManager!.spaces.values()) {
|
|
133
|
+
if (!this.serviceContext.dataServiceSubscriptions.getDataService(space.key)) {
|
|
134
|
+
// Skip spaces without data service available.
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
space.stateUpdate.on(ctx, onUpdate);
|
|
139
|
+
space.presence.updated.on(ctx, onUpdate);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
this.serviceContext.dataSpaceManager!.updated.on(ctx, () => {
|
|
144
|
+
subscribeSpaces();
|
|
145
|
+
onUpdate();
|
|
144
146
|
});
|
|
145
147
|
|
|
148
|
+
subscribeSpaces();
|
|
146
149
|
onUpdate();
|
|
147
150
|
});
|
|
148
|
-
|
|
149
|
-
return () => subscriptions.clear();
|
|
150
151
|
});
|
|
151
152
|
}
|
|
152
153
|
|
|
@@ -159,6 +160,9 @@ export class SpaceServiceImpl implements SpaceService {
|
|
|
159
160
|
}
|
|
160
161
|
|
|
161
162
|
async createSpace(): Promise<Space> {
|
|
163
|
+
if (!this.serviceContext.identityManager.identity) {
|
|
164
|
+
throw new Error('This device has no HALO identity available. See https://docs.dxos.org/guide/halo');
|
|
165
|
+
}
|
|
162
166
|
await this.serviceContext.initialized.wait();
|
|
163
167
|
const space = await this.serviceContext.dataSpaceManager!.createSpace();
|
|
164
168
|
return {
|
|
@@ -3,33 +3,46 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { Config } from '@dxos/config';
|
|
6
|
-
import { SystemService } from '@dxos/protocols/proto/dxos/client';
|
|
6
|
+
import { StatusResponse, SystemService } from '@dxos/protocols/proto/dxos/client';
|
|
7
|
+
import { MaybePromise } from '@dxos/util';
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
export type SystemServiceOptions = {
|
|
10
|
+
config: Config;
|
|
11
|
+
onInit: () => MaybePromise<void>;
|
|
12
|
+
onStatus: () => MaybePromise<StatusResponse>;
|
|
13
|
+
onReset: () => MaybePromise<void>;
|
|
14
|
+
};
|
|
9
15
|
|
|
10
16
|
/**
|
|
11
17
|
* @deprecated
|
|
12
18
|
*/
|
|
13
19
|
export class SystemServiceImpl implements SystemService {
|
|
14
|
-
|
|
20
|
+
private readonly _config: Config;
|
|
21
|
+
private readonly _onInit: () => MaybePromise<void>;
|
|
22
|
+
private readonly _onStatus: () => MaybePromise<StatusResponse>;
|
|
23
|
+
private readonly _onReset: () => MaybePromise<void>;
|
|
15
24
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
25
|
+
constructor({ config, onInit, onStatus, onReset }: SystemServiceOptions) {
|
|
26
|
+
this._config = config;
|
|
27
|
+
this._onInit = onInit;
|
|
28
|
+
this._onStatus = onStatus;
|
|
29
|
+
this._onReset = onReset;
|
|
19
30
|
}
|
|
20
31
|
|
|
21
|
-
async getConfig(
|
|
32
|
+
async getConfig() {
|
|
22
33
|
return this._config.values;
|
|
23
34
|
}
|
|
24
35
|
|
|
25
36
|
// TODO(burdon): Connect to iframe RPC heartbeat for network status?
|
|
26
|
-
async getStatus(
|
|
27
|
-
return
|
|
28
|
-
|
|
29
|
-
|
|
37
|
+
async getStatus() {
|
|
38
|
+
return this._onStatus();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async initSession() {
|
|
42
|
+
await this._onInit();
|
|
30
43
|
}
|
|
31
44
|
|
|
32
|
-
async reset(
|
|
33
|
-
await this.
|
|
45
|
+
async reset() {
|
|
46
|
+
await this._onReset();
|
|
34
47
|
}
|
|
35
48
|
}
|
|
@@ -33,14 +33,14 @@ import {
|
|
|
33
33
|
SubscribeToSpacesRequest,
|
|
34
34
|
SubscribeToSpacesResponse,
|
|
35
35
|
SubscribeToSignalStatusResponse,
|
|
36
|
-
|
|
36
|
+
SignalResponse,
|
|
37
37
|
SubscribeToSwarmInfoResponse
|
|
38
38
|
} from '@dxos/protocols/proto/dxos/devtools/host';
|
|
39
39
|
|
|
40
40
|
import { ServiceContext } from '../services';
|
|
41
41
|
import { subscribeToFeedBlocks, subscribeToFeeds } from './feeds';
|
|
42
42
|
import { subscribeToKeyringKeys } from './keys';
|
|
43
|
-
import { subscribeToNetworkStatus,
|
|
43
|
+
import { subscribeToNetworkStatus, subscribeToSignal, subscribeToSwarmInfo } from './network';
|
|
44
44
|
import { subscribeToSpaces } from './spaces';
|
|
45
45
|
|
|
46
46
|
export class DevtoolsHostEvents {
|
|
@@ -133,8 +133,8 @@ export class DevtoolsServiceImpl implements DevtoolsHost {
|
|
|
133
133
|
return subscribeToNetworkStatus({ networkManager: this.params.context.networkManager });
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
return
|
|
136
|
+
subscribeToSignal(): Stream<SignalResponse> {
|
|
137
|
+
return subscribeToSignal({ networkManager: this.params.context.networkManager });
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
subscribeToSwarmInfo(): Stream<SubscribeToSwarmInfoResponse> {
|
|
@@ -18,17 +18,17 @@ import { ComplexMap } from '@dxos/util';
|
|
|
18
18
|
export const subscribeToFeeds = (
|
|
19
19
|
{ feedStore }: { feedStore: FeedStore<FeedMessage> },
|
|
20
20
|
{ feedKeys }: SubscribeToFeedsRequest
|
|
21
|
-
) =>
|
|
22
|
-
new Stream<SubscribeToFeedsResponse>(({ next }) => {
|
|
21
|
+
) => {
|
|
22
|
+
return new Stream<SubscribeToFeedsResponse>(({ next }) => {
|
|
23
23
|
if (feedKeys?.length === 0) {
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
const feedMap = new ComplexMap<PublicKey, FeedWrapper<FeedMessage>>(PublicKey.hash);
|
|
28
27
|
const subscriptions = new EventSubscriptions();
|
|
28
|
+
const feedMap = new ComplexMap<PublicKey, FeedWrapper<FeedMessage>>(PublicKey.hash);
|
|
29
29
|
|
|
30
30
|
const update = () => {
|
|
31
|
-
const feeds = feedStore
|
|
31
|
+
const { feeds } = feedStore;
|
|
32
32
|
feeds
|
|
33
33
|
.filter((feed) => !feedKeys?.length || feedKeys.some((feedKey) => feedKey.equals(feed.key)))
|
|
34
34
|
.forEach((feed) => {
|
|
@@ -38,6 +38,7 @@ export const subscribeToFeeds = (
|
|
|
38
38
|
subscriptions.add(feed.off('close', update));
|
|
39
39
|
}
|
|
40
40
|
});
|
|
41
|
+
|
|
41
42
|
next({
|
|
42
43
|
feeds: Array.from(feedMap.values()).map((feed) => ({ feedKey: feed.key, length: feed.properties.length }))
|
|
43
44
|
});
|
|
@@ -50,12 +51,13 @@ export const subscribeToFeeds = (
|
|
|
50
51
|
subscriptions.clear();
|
|
51
52
|
};
|
|
52
53
|
});
|
|
54
|
+
};
|
|
53
55
|
|
|
54
56
|
export const subscribeToFeedBlocks = (
|
|
55
57
|
{ feedStore }: { feedStore: FeedStore<FeedMessage> },
|
|
56
58
|
{ feedKey, maxBlocks = 10 }: SubscribeToFeedBlocksRequest
|
|
57
|
-
) =>
|
|
58
|
-
new Stream<SubscribeToFeedBlocksResponse>(({ next }) => {
|
|
59
|
+
) => {
|
|
60
|
+
return new Stream<SubscribeToFeedBlocksResponse>(({ next }) => {
|
|
59
61
|
if (!feedKey) {
|
|
60
62
|
return;
|
|
61
63
|
}
|
|
@@ -77,9 +79,11 @@ export const subscribeToFeedBlocks = (
|
|
|
77
79
|
break;
|
|
78
80
|
}
|
|
79
81
|
}
|
|
82
|
+
|
|
80
83
|
next({
|
|
81
84
|
blocks: blocks.slice(-maxBlocks)
|
|
82
85
|
});
|
|
86
|
+
|
|
83
87
|
await iterator.close();
|
|
84
88
|
};
|
|
85
89
|
|
|
@@ -96,3 +100,4 @@ export const subscribeToFeedBlocks = (
|
|
|
96
100
|
clearTimeout(timeout);
|
|
97
101
|
};
|
|
98
102
|
});
|
|
103
|
+
};
|
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { Stream } from '@dxos/codec-protobuf';
|
|
6
|
+
import { Context } from '@dxos/context';
|
|
6
7
|
import { PublicKey } from '@dxos/keys';
|
|
7
|
-
import { CommandTrace } from '@dxos/messaging';
|
|
8
8
|
import { NetworkManager } from '@dxos/network-manager';
|
|
9
9
|
import {
|
|
10
10
|
GetNetworkPeersRequest,
|
|
11
11
|
GetNetworkPeersResponse,
|
|
12
12
|
SubscribeToNetworkTopicsResponse,
|
|
13
13
|
SubscribeToSignalStatusResponse,
|
|
14
|
-
|
|
14
|
+
SignalResponse,
|
|
15
15
|
SubscribeToSwarmInfoResponse
|
|
16
16
|
} from '@dxos/protocols/proto/dxos/devtools/host';
|
|
17
17
|
|
|
@@ -30,14 +30,25 @@ export const subscribeToNetworkStatus = ({ networkManager }: { networkManager: N
|
|
|
30
30
|
update();
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
export const
|
|
34
|
-
new Stream<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
export const subscribeToSignal = ({ networkManager }: { networkManager: NetworkManager }) =>
|
|
34
|
+
new Stream<SignalResponse>(({ next }) => {
|
|
35
|
+
const ctx = new Context();
|
|
36
|
+
networkManager.signalManager.onMessage.on(ctx, (message) => {
|
|
37
|
+
next({
|
|
38
|
+
message: {
|
|
39
|
+
author: message.author.asUint8Array(),
|
|
40
|
+
recipient: message.recipient.asUint8Array(),
|
|
41
|
+
payload: message.payload
|
|
42
|
+
},
|
|
43
|
+
receivedAt: new Date()
|
|
44
|
+
});
|
|
40
45
|
});
|
|
46
|
+
networkManager.signalManager.swarmEvent.on(ctx, (swarmEvent) => {
|
|
47
|
+
next({ swarmEvent: swarmEvent.swarmEvent, receivedAt: new Date() });
|
|
48
|
+
});
|
|
49
|
+
return () => {
|
|
50
|
+
return ctx.dispose();
|
|
51
|
+
};
|
|
41
52
|
});
|
|
42
53
|
|
|
43
54
|
export const subscribeToNetworkTopics = ({ networkManager }: { networkManager: NetworkManager }) =>
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { Stream } from '@dxos/codec-protobuf';
|
|
6
|
-
import { Space } from '@dxos/echo-
|
|
6
|
+
import { Space } from '@dxos/echo-pipeline';
|
|
7
7
|
import { SubscribeToSpacesRequest, SubscribeToSpacesResponse } from '@dxos/protocols/proto/dxos/devtools/host';
|
|
8
8
|
import { SpaceMetadata } from '@dxos/protocols/proto/dxos/echo/metadata';
|
|
9
9
|
|
|
10
10
|
import { ServiceContext } from '../services';
|
|
11
11
|
|
|
12
|
-
export const subscribeToSpaces = (context: ServiceContext, { spaceKeys = [] }: SubscribeToSpacesRequest) =>
|
|
13
|
-
new Stream<SubscribeToSpacesResponse>(({ next }) => {
|
|
12
|
+
export const subscribeToSpaces = (context: ServiceContext, { spaceKeys = [] }: SubscribeToSpacesRequest) => {
|
|
13
|
+
return new Stream<SubscribeToSpacesResponse>(({ next }) => {
|
|
14
14
|
let unsubscribe: () => void;
|
|
15
15
|
|
|
16
16
|
const update = async () => {
|
|
@@ -20,7 +20,7 @@ export const subscribeToSpaces = (context: ServiceContext, { spaceKeys = [] }: S
|
|
|
20
20
|
);
|
|
21
21
|
|
|
22
22
|
next({
|
|
23
|
-
spaces: filteredSpaces.map((space) => {
|
|
23
|
+
spaces: filteredSpaces.map((space): SubscribeToSpacesResponse.SpaceInfo => {
|
|
24
24
|
const spaceMetadata = context.metadataStore.spaces.find((spaceMetadata: SpaceMetadata) =>
|
|
25
25
|
spaceMetadata.key.equals(space.key)
|
|
26
26
|
);
|
|
@@ -28,10 +28,10 @@ export const subscribeToSpaces = (context: ServiceContext, { spaceKeys = [] }: S
|
|
|
28
28
|
return {
|
|
29
29
|
key: space.key,
|
|
30
30
|
isOpen: space.isOpen,
|
|
31
|
-
timeframe: spaceMetadata?.
|
|
31
|
+
timeframe: spaceMetadata?.dataTimeframe,
|
|
32
32
|
genesisFeed: space.genesisFeedKey,
|
|
33
|
-
controlFeed: space.controlFeedKey
|
|
34
|
-
dataFeed: space.dataFeedKey
|
|
33
|
+
controlFeed: space.controlFeedKey!, // TODO(dmaretskyi): Those keys may be missing.
|
|
34
|
+
dataFeed: space.dataFeedKey!
|
|
35
35
|
};
|
|
36
36
|
})
|
|
37
37
|
});
|
|
@@ -50,3 +50,4 @@ export const subscribeToSpaces = (context: ServiceContext, { spaceKeys = [] }: S
|
|
|
50
50
|
clearTimeout(timeout);
|
|
51
51
|
};
|
|
52
52
|
});
|
|
53
|
+
};
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { Event, Trigger } from '@dxos/async';
|
|
6
6
|
import { Context } from '@dxos/context';
|
|
7
7
|
import { verifyCredential, CredentialSigner } from '@dxos/credentials';
|
|
8
|
-
import { AuthProvider, AuthVerifier } from '@dxos/echo-
|
|
8
|
+
import { AuthProvider, AuthVerifier } from '@dxos/echo-pipeline';
|
|
9
9
|
import { PublicKey } from '@dxos/keys';
|
|
10
10
|
import { log } from '@dxos/log';
|
|
11
11
|
import { schema } from '@dxos/protocols';
|
|
@@ -42,17 +42,15 @@ export type TrustedKeySetAuthVerifierParams = {
|
|
|
42
42
|
export class TrustedKeySetAuthVerifier {
|
|
43
43
|
private _ctx = new Context();
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
// prettier-ignore
|
|
46
|
+
constructor(
|
|
47
|
+
private readonly _params: TrustedKeySetAuthVerifierParams
|
|
48
|
+
) {}
|
|
46
49
|
|
|
47
50
|
async close() {
|
|
48
51
|
await this._ctx.dispose();
|
|
49
52
|
}
|
|
50
53
|
|
|
51
|
-
private _isTrustedKey(deviceKey: PublicKey) {
|
|
52
|
-
const deviceSet = this._params.trustedKeysProvider();
|
|
53
|
-
return deviceSet.has(deviceKey);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
54
|
get verifier(): AuthVerifier {
|
|
57
55
|
return async (nonce, auth) => {
|
|
58
56
|
const credential = schema.getCodecForType('dxos.halo.credentials.Credential').decode(auth);
|
|
@@ -78,6 +76,7 @@ export class TrustedKeySetAuthVerifier {
|
|
|
78
76
|
this._ctx.onDispose(() => {
|
|
79
77
|
trigger.wake(false);
|
|
80
78
|
});
|
|
79
|
+
|
|
81
80
|
const clear = this._params.update.on(this._ctx, () => {
|
|
82
81
|
if (this._isTrustedKey(credential.issuer)) {
|
|
83
82
|
log('auth success', { key: credential.issuer });
|
|
@@ -86,6 +85,7 @@ export class TrustedKeySetAuthVerifier {
|
|
|
86
85
|
log('key is not currently in trusted set, waiting...', { key: credential.issuer });
|
|
87
86
|
}
|
|
88
87
|
});
|
|
88
|
+
|
|
89
89
|
try {
|
|
90
90
|
return await trigger.wait({ timeout: this._params.authTimeout });
|
|
91
91
|
} catch {
|
|
@@ -95,4 +95,9 @@ export class TrustedKeySetAuthVerifier {
|
|
|
95
95
|
}
|
|
96
96
|
};
|
|
97
97
|
}
|
|
98
|
+
|
|
99
|
+
private _isTrustedKey(deviceKey: PublicKey) {
|
|
100
|
+
const deviceSet = this._params.trustedKeysProvider();
|
|
101
|
+
return deviceSet.has(deviceKey);
|
|
102
|
+
}
|
|
98
103
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { expect } from 'chai';
|
|
6
6
|
|
|
7
|
-
import { valueEncoding, MetadataStore, SpaceManager, AuthStatus } from '@dxos/echo-
|
|
7
|
+
import { valueEncoding, MetadataStore, SpaceManager, AuthStatus } from '@dxos/echo-pipeline';
|
|
8
8
|
import { FeedFactory, FeedStore } from '@dxos/feed-store';
|
|
9
9
|
import { Keyring } from '@dxos/keyring';
|
|
10
10
|
import { MemorySignalManager, MemorySignalManagerContext } from '@dxos/messaging';
|
|
@@ -46,11 +46,12 @@ describe('identity/identity-manager', () => {
|
|
|
46
46
|
feedStore,
|
|
47
47
|
networkManager
|
|
48
48
|
});
|
|
49
|
-
const identityManager = new IdentityManager(metadataStore, keyring, spaceManager);
|
|
49
|
+
const identityManager = new IdentityManager(metadataStore, keyring, feedStore, spaceManager);
|
|
50
50
|
|
|
51
51
|
return {
|
|
52
52
|
identityManager,
|
|
53
|
-
feedStore
|
|
53
|
+
feedStore,
|
|
54
|
+
keyring
|
|
54
55
|
};
|
|
55
56
|
};
|
|
56
57
|
|
|
@@ -90,23 +91,31 @@ describe('identity/identity-manager', () => {
|
|
|
90
91
|
|
|
91
92
|
const peer2 = await setupPeer({ signalContext });
|
|
92
93
|
|
|
94
|
+
const deviceKey = await peer2.keyring.createKey();
|
|
95
|
+
const controlFeedKey = await peer2.keyring.createKey();
|
|
96
|
+
const dataFeedKey = await peer2.keyring.createKey();
|
|
97
|
+
|
|
98
|
+
await identity1.controlPipeline.writer.write({
|
|
99
|
+
credential: {
|
|
100
|
+
credential: await identity1.getIdentityCredentialSigner().createCredential({
|
|
101
|
+
subject: deviceKey,
|
|
102
|
+
assertion: {
|
|
103
|
+
'@type': 'dxos.halo.credentials.AuthorizedDevice',
|
|
104
|
+
identityKey: identity1.identityKey,
|
|
105
|
+
deviceKey
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
93
111
|
// Identity2 is not yet ready at this point. Peer1 needs to admit peer2 device key and feed keys.
|
|
94
112
|
const identity2 = await peer2.identityManager.acceptIdentity({
|
|
95
113
|
identityKey: identity1.identityKey,
|
|
114
|
+
deviceKey,
|
|
96
115
|
haloSpaceKey: identity1.haloSpaceKey,
|
|
97
|
-
haloGenesisFeedKey: identity1.haloGenesisFeedKey
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
await identity1.controlPipeline.writer.write({
|
|
101
|
-
'@type': 'dxos.echo.feed.CredentialsMessage',
|
|
102
|
-
credential: await identity1.getIdentityCredentialSigner().createCredential({
|
|
103
|
-
subject: identity2.deviceKey,
|
|
104
|
-
assertion: {
|
|
105
|
-
'@type': 'dxos.halo.credentials.AuthorizedDevice',
|
|
106
|
-
identityKey: identity2.identityKey,
|
|
107
|
-
deviceKey: identity2.deviceKey
|
|
108
|
-
}
|
|
109
|
-
})
|
|
116
|
+
haloGenesisFeedKey: identity1.haloGenesisFeedKey,
|
|
117
|
+
controlFeedKey,
|
|
118
|
+
dataFeedKey
|
|
110
119
|
});
|
|
111
120
|
|
|
112
121
|
// TODO(dmaretskyi): We'd also need to admit device2's feeds otherwise messages from them won't be processed by the pipeline.
|
|
@@ -6,10 +6,12 @@ import assert from 'node:assert';
|
|
|
6
6
|
|
|
7
7
|
import { Event } from '@dxos/async';
|
|
8
8
|
import { createCredentialSignerWithKey, CredentialGenerator } from '@dxos/credentials';
|
|
9
|
-
import { MetadataStore, SpaceManager, SwarmIdentity } from '@dxos/echo-
|
|
9
|
+
import { MetadataStore, SpaceManager, SwarmIdentity } from '@dxos/echo-pipeline';
|
|
10
|
+
import { FeedStore } from '@dxos/feed-store';
|
|
10
11
|
import { Keyring } from '@dxos/keyring';
|
|
11
12
|
import { PublicKey } from '@dxos/keys';
|
|
12
13
|
import { log } from '@dxos/log';
|
|
14
|
+
import { FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
|
|
13
15
|
import { AdmittedFeed, IdentityRecord, SpaceRecord } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
14
16
|
import { deferFunction } from '@dxos/util';
|
|
15
17
|
|
|
@@ -24,8 +26,11 @@ interface ConstructSpaceParams {
|
|
|
24
26
|
|
|
25
27
|
export type JoinIdentityParams = {
|
|
26
28
|
identityKey: PublicKey;
|
|
29
|
+
deviceKey: PublicKey;
|
|
27
30
|
haloSpaceKey: PublicKey;
|
|
28
31
|
haloGenesisFeedKey: PublicKey;
|
|
32
|
+
controlFeedKey: PublicKey;
|
|
33
|
+
dataFeedKey: PublicKey;
|
|
29
34
|
};
|
|
30
35
|
|
|
31
36
|
export type CreateIdentityOptions = {
|
|
@@ -43,6 +48,7 @@ export class IdentityManager {
|
|
|
43
48
|
constructor(
|
|
44
49
|
private readonly _metadataStore: MetadataStore,
|
|
45
50
|
private readonly _keyring: Keyring,
|
|
51
|
+
private readonly _feedStore: FeedStore<FeedMessage>,
|
|
46
52
|
private readonly _spaceManager: SpaceManager
|
|
47
53
|
) {}
|
|
48
54
|
|
|
@@ -113,8 +119,7 @@ export class IdentityManager {
|
|
|
113
119
|
|
|
114
120
|
for (const credential of credentials) {
|
|
115
121
|
await identity.controlPipeline.writer.write({
|
|
116
|
-
|
|
117
|
-
credential
|
|
122
|
+
credential: { credential }
|
|
118
123
|
});
|
|
119
124
|
}
|
|
120
125
|
}
|
|
@@ -141,12 +146,12 @@ export class IdentityManager {
|
|
|
141
146
|
|
|
142
147
|
const identityRecord: IdentityRecord = {
|
|
143
148
|
identityKey: params.identityKey,
|
|
144
|
-
deviceKey:
|
|
149
|
+
deviceKey: params.deviceKey,
|
|
145
150
|
haloSpace: {
|
|
146
151
|
spaceKey: params.haloSpaceKey,
|
|
147
152
|
genesisFeedKey: params.haloGenesisFeedKey,
|
|
148
|
-
writeControlFeedKey:
|
|
149
|
-
writeDataFeedKey:
|
|
153
|
+
writeControlFeedKey: params.controlFeedKey,
|
|
154
|
+
writeDataFeedKey: params.dataFeedKey
|
|
150
155
|
}
|
|
151
156
|
};
|
|
152
157
|
const identity = await this._constructIdentity(identityRecord);
|
|
@@ -154,7 +159,9 @@ export class IdentityManager {
|
|
|
154
159
|
await identity.open();
|
|
155
160
|
this._identity = identity;
|
|
156
161
|
await this._metadataStore.setIdentityRecord(identityRecord);
|
|
162
|
+
await this._identity.ready();
|
|
157
163
|
this.stateUpdate.emit();
|
|
164
|
+
log('accepted identity', { identityKey: identity.identityKey, deviceKey: identity.deviceKey });
|
|
158
165
|
return identity;
|
|
159
166
|
}
|
|
160
167
|
|
|
@@ -162,6 +169,12 @@ export class IdentityManager {
|
|
|
162
169
|
assert(!this._identity);
|
|
163
170
|
log('constructing identity', { identityRecord });
|
|
164
171
|
|
|
172
|
+
// Must be created before the space so the feeds are writable.
|
|
173
|
+
const controlFeed = await this._feedStore.openFeed(identityRecord.haloSpace.writeControlFeedKey, {
|
|
174
|
+
writable: true
|
|
175
|
+
});
|
|
176
|
+
const dataFeed = await this._feedStore.openFeed(identityRecord.haloSpace.writeDataFeedKey, { writable: true });
|
|
177
|
+
|
|
165
178
|
const space = await this._constructSpace({
|
|
166
179
|
spaceRecord: identityRecord.haloSpace,
|
|
167
180
|
swarmIdentity: {
|
|
@@ -171,6 +184,9 @@ export class IdentityManager {
|
|
|
171
184
|
},
|
|
172
185
|
identityKey: identityRecord.identityKey
|
|
173
186
|
});
|
|
187
|
+
space.setControlFeed(controlFeed);
|
|
188
|
+
space.setDataFeed(dataFeed);
|
|
189
|
+
|
|
174
190
|
const identity: Identity = new Identity({
|
|
175
191
|
space,
|
|
176
192
|
signer: this._keyring,
|
|
@@ -186,9 +202,7 @@ export class IdentityManager {
|
|
|
186
202
|
return this._spaceManager.constructSpace({
|
|
187
203
|
metadata: {
|
|
188
204
|
key: spaceRecord.spaceKey,
|
|
189
|
-
genesisFeedKey: spaceRecord.genesisFeedKey
|
|
190
|
-
controlFeedKey: spaceRecord.writeControlFeedKey,
|
|
191
|
-
dataFeedKey: spaceRecord.writeDataFeedKey
|
|
205
|
+
genesisFeedKey: spaceRecord.genesisFeedKey
|
|
192
206
|
},
|
|
193
207
|
swarmIdentity,
|
|
194
208
|
onNetworkConnection: () => {}
|