@dxos/client-services 0.6.12-main.5cc132e → 0.6.12-main.78ddbdf
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-7FTR2DGP.mjs → chunk-XSFLJVDP.mjs} +5154 -5061
- package/dist/lib/browser/chunk-XSFLJVDP.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +3 -3
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +4 -5
- package/dist/lib/browser/testing/index.mjs.map +2 -2
- package/dist/lib/node/{chunk-KUHUPLSZ.cjs → chunk-F3WGFGEN.cjs} +4980 -4887
- package/dist/lib/node/chunk-F3WGFGEN.cjs.map +7 -0
- package/dist/lib/node/index.cjs +46 -46
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +11 -12
- package/dist/lib/node/testing/index.cjs.map +2 -2
- package/dist/lib/node-esm/{chunk-QGQGMTAW.mjs → chunk-3HDLTAT2.mjs} +5142 -5047
- package/dist/lib/node-esm/chunk-3HDLTAT2.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +4 -3
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +5 -5
- package/dist/lib/node-esm/testing/index.mjs.map +2 -2
- package/dist/types/src/packlets/identity/identity-manager.d.ts +19 -7
- package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
- package/dist/types/src/packlets/identity/identity.d.ts +7 -1
- package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
- package/dist/types/src/packlets/invitations/invitation-host-extension.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-context.d.ts +3 -4
- package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
- package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/data-space-manager.d.ts +1 -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 +1 -2
- package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts +1 -0
- package/dist/types/src/packlets/spaces/edge-feed-replicator.d.ts.map +1 -1
- package/dist/types/src/packlets/spaces/edge-feed-replicator.test.d.ts +2 -0
- package/dist/types/src/packlets/spaces/edge-feed-replicator.test.d.ts.map +1 -0
- 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/testing/test-builder.d.ts +1 -2
- 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/package.json +39 -38
- package/src/packlets/identity/identity-manager.test.ts +1 -1
- package/src/packlets/identity/identity-manager.ts +35 -19
- package/src/packlets/identity/identity.test.ts +126 -236
- package/src/packlets/identity/identity.ts +38 -8
- package/src/packlets/invitations/invitation-host-extension.ts +0 -3
- package/src/packlets/invitations/invitations-handler.ts +1 -1
- package/src/packlets/services/service-context.ts +24 -12
- package/src/packlets/services/service-host.ts +2 -2
- package/src/packlets/spaces/data-space-manager.ts +4 -1
- package/src/packlets/spaces/data-space.ts +7 -2
- package/src/packlets/spaces/edge-feed-replicator.test.ts +244 -0
- package/src/packlets/spaces/edge-feed-replicator.ts +59 -21
- package/src/packlets/spaces/epoch-migrations.ts +2 -2
- package/src/packlets/testing/test-builder.ts +1 -2
- package/src/packlets/worker/worker-runtime.ts +2 -2
- package/src/version.ts +1 -1
- package/dist/lib/browser/chunk-7FTR2DGP.mjs.map +0 -7
- package/dist/lib/node/chunk-KUHUPLSZ.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-QGQGMTAW.mjs.map +0 -7
- package/dist/types/src/packlets/services/automerge-host.test.d.ts +0 -2
- package/dist/types/src/packlets/services/automerge-host.test.d.ts.map +0 -1
- package/src/packlets/services/automerge-host.test.ts +0 -62
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/client-services",
|
|
3
|
-
"version": "0.6.12-main.
|
|
3
|
+
"version": "0.6.12-main.78ddbdf",
|
|
4
4
|
"description": "DXOS client services implementation",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -47,47 +47,48 @@
|
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"cbor-x": "^1.5.4",
|
|
49
49
|
"platform": "^1.3.6",
|
|
50
|
-
"@dxos/async": "0.6.12-main.
|
|
51
|
-
"@dxos/
|
|
52
|
-
"@dxos/
|
|
53
|
-
"@dxos/
|
|
54
|
-
"@dxos/
|
|
55
|
-
"@dxos/context": "0.6.12-main.
|
|
56
|
-
"@dxos/crypto": "0.6.12-main.
|
|
57
|
-
"@dxos/credentials": "0.6.12-main.
|
|
58
|
-
"@dxos/debug": "0.6.12-main.
|
|
59
|
-
"@dxos/echo-db": "0.6.12-main.
|
|
60
|
-
"@dxos/echo-
|
|
61
|
-
"@dxos/echo-
|
|
62
|
-
"@dxos/
|
|
63
|
-
"@dxos/
|
|
64
|
-
"@dxos/
|
|
65
|
-
"@dxos/
|
|
66
|
-
"@dxos/
|
|
67
|
-
"@dxos/
|
|
68
|
-
"@dxos/
|
|
69
|
-
"@dxos/
|
|
70
|
-
"@dxos/
|
|
71
|
-
"@dxos/
|
|
72
|
-
"@dxos/messaging": "0.6.12-main.
|
|
73
|
-
"@dxos/
|
|
74
|
-
"@dxos/
|
|
75
|
-
"@dxos/
|
|
76
|
-
"@dxos/
|
|
77
|
-
"@dxos/teleport": "0.6.12-main.
|
|
78
|
-
"@dxos/rpc": "0.6.12-main.
|
|
79
|
-
"@dxos/teleport-extension-gossip": "0.6.12-main.
|
|
80
|
-
"@dxos/
|
|
81
|
-
"@dxos/
|
|
82
|
-
"@dxos/
|
|
83
|
-
"@dxos/util": "0.6.12-main.
|
|
84
|
-
"@dxos/websocket-rpc": "0.6.12-main.
|
|
50
|
+
"@dxos/async": "0.6.12-main.78ddbdf",
|
|
51
|
+
"@dxos/client-protocol": "0.6.12-main.78ddbdf",
|
|
52
|
+
"@dxos/config": "0.6.12-main.78ddbdf",
|
|
53
|
+
"@dxos/codec-protobuf": "0.6.12-main.78ddbdf",
|
|
54
|
+
"@dxos/automerge": "0.6.12-main.78ddbdf",
|
|
55
|
+
"@dxos/context": "0.6.12-main.78ddbdf",
|
|
56
|
+
"@dxos/crypto": "0.6.12-main.78ddbdf",
|
|
57
|
+
"@dxos/credentials": "0.6.12-main.78ddbdf",
|
|
58
|
+
"@dxos/debug": "0.6.12-main.78ddbdf",
|
|
59
|
+
"@dxos/echo-db": "0.6.12-main.78ddbdf",
|
|
60
|
+
"@dxos/echo-pipeline": "0.6.12-main.78ddbdf",
|
|
61
|
+
"@dxos/echo-protocol": "0.6.12-main.78ddbdf",
|
|
62
|
+
"@dxos/echo-schema": "0.6.12-main.78ddbdf",
|
|
63
|
+
"@dxos/feed-store": "0.6.12-main.78ddbdf",
|
|
64
|
+
"@dxos/indexing": "0.6.12-main.78ddbdf",
|
|
65
|
+
"@dxos/edge-client": "0.6.12-main.78ddbdf",
|
|
66
|
+
"@dxos/invariant": "0.6.12-main.78ddbdf",
|
|
67
|
+
"@dxos/keyring": "0.6.12-main.78ddbdf",
|
|
68
|
+
"@dxos/keys": "0.6.12-main.78ddbdf",
|
|
69
|
+
"@dxos/lock-file": "0.6.12-main.78ddbdf",
|
|
70
|
+
"@dxos/log": "0.6.12-main.78ddbdf",
|
|
71
|
+
"@dxos/kv-store": "0.6.12-main.78ddbdf",
|
|
72
|
+
"@dxos/messaging": "0.6.12-main.78ddbdf",
|
|
73
|
+
"@dxos/network-manager": "0.6.12-main.78ddbdf",
|
|
74
|
+
"@dxos/node-std": "0.6.12-main.78ddbdf",
|
|
75
|
+
"@dxos/random-access-storage": "0.6.12-main.78ddbdf",
|
|
76
|
+
"@dxos/protocols": "0.6.12-main.78ddbdf",
|
|
77
|
+
"@dxos/teleport": "0.6.12-main.78ddbdf",
|
|
78
|
+
"@dxos/rpc": "0.6.12-main.78ddbdf",
|
|
79
|
+
"@dxos/teleport-extension-gossip": "0.6.12-main.78ddbdf",
|
|
80
|
+
"@dxos/timeframe": "0.6.12-main.78ddbdf",
|
|
81
|
+
"@dxos/tracing": "0.6.12-main.78ddbdf",
|
|
82
|
+
"@dxos/teleport-extension-object-sync": "0.6.12-main.78ddbdf",
|
|
83
|
+
"@dxos/util": "0.6.12-main.78ddbdf",
|
|
84
|
+
"@dxos/websocket-rpc": "0.6.12-main.78ddbdf"
|
|
85
85
|
},
|
|
86
86
|
"devDependencies": {
|
|
87
87
|
"@types/platform": "^1.3.4",
|
|
88
88
|
"@types/readable-stream": "^2.3.9",
|
|
89
|
-
"
|
|
90
|
-
"@dxos/
|
|
89
|
+
"get-port-please": "^3.1.1",
|
|
90
|
+
"@dxos/signal": "0.6.12-main.78ddbdf",
|
|
91
|
+
"@dxos/test-utils": "0.6.12-main.78ddbdf"
|
|
91
92
|
},
|
|
92
93
|
"publishConfig": {
|
|
93
94
|
"access": "public"
|
|
@@ -50,7 +50,7 @@ describe('identity/identity-manager', () => {
|
|
|
50
50
|
blobStore,
|
|
51
51
|
metadataStore,
|
|
52
52
|
});
|
|
53
|
-
const identityManager = new IdentityManager(metadataStore, keyring, feedStore, spaceManager);
|
|
53
|
+
const identityManager = new IdentityManager({ metadataStore, keyring, feedStore, spaceManager });
|
|
54
54
|
|
|
55
55
|
return {
|
|
56
56
|
metadataStore,
|
|
@@ -7,6 +7,7 @@ import { Event } from '@dxos/async';
|
|
|
7
7
|
import { Context } from '@dxos/context';
|
|
8
8
|
import { createCredentialSignerWithKey, CredentialGenerator } from '@dxos/credentials';
|
|
9
9
|
import { type MetadataStore, type SpaceManager, type SwarmIdentity } from '@dxos/echo-pipeline';
|
|
10
|
+
import { type EdgeConnection } from '@dxos/edge-client';
|
|
10
11
|
import { type FeedStore } from '@dxos/feed-store';
|
|
11
12
|
import { invariant } from '@dxos/invariant';
|
|
12
13
|
import { type Keyring } from '@dxos/keyring';
|
|
@@ -14,6 +15,7 @@ import { PublicKey } from '@dxos/keys';
|
|
|
14
15
|
import { log } from '@dxos/log';
|
|
15
16
|
import { trace } from '@dxos/protocols';
|
|
16
17
|
import { Device, DeviceKind } from '@dxos/protocols/proto/dxos/client/services';
|
|
18
|
+
import { type Runtime } from '@dxos/protocols/proto/dxos/config';
|
|
17
19
|
import { type FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
|
|
18
20
|
import { type IdentityRecord, type SpaceMetadata } from '@dxos/protocols/proto/dxos/echo/metadata';
|
|
19
21
|
import {
|
|
@@ -63,9 +65,20 @@ export type CreateIdentityOptions = {
|
|
|
63
65
|
deviceProfile?: DeviceProfileDocument;
|
|
64
66
|
};
|
|
65
67
|
|
|
66
|
-
export type
|
|
68
|
+
export type IdentityManagerCallbacks = {
|
|
69
|
+
onIdentityConstruction?: (identity: Identity) => void;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export type IdentityManagerParams = {
|
|
73
|
+
metadataStore: MetadataStore;
|
|
74
|
+
keyring: Keyring;
|
|
75
|
+
feedStore: FeedStore<FeedMessage>;
|
|
76
|
+
spaceManager: SpaceManager;
|
|
77
|
+
edgeConnection?: EdgeConnection;
|
|
78
|
+
edgeFeatures?: Runtime.Client.EdgeFeatures;
|
|
67
79
|
devicePresenceAnnounceInterval?: number;
|
|
68
80
|
devicePresenceOfflineTimeout?: number;
|
|
81
|
+
callbacks?: IdentityManagerCallbacks;
|
|
69
82
|
};
|
|
70
83
|
|
|
71
84
|
// TODO(dmaretskyi): Rename: represents the peer's state machine.
|
|
@@ -73,28 +86,29 @@ export type IdentityManagerRuntimeParams = {
|
|
|
73
86
|
export class IdentityManager {
|
|
74
87
|
readonly stateUpdate = new Event();
|
|
75
88
|
|
|
76
|
-
private
|
|
89
|
+
private readonly _metadataStore: MetadataStore;
|
|
90
|
+
private readonly _keyring: Keyring;
|
|
91
|
+
private readonly _feedStore: FeedStore<FeedMessage>;
|
|
92
|
+
private readonly _spaceManager: SpaceManager;
|
|
77
93
|
private readonly _devicePresenceAnnounceInterval: number;
|
|
78
94
|
private readonly _devicePresenceOfflineTimeout: number;
|
|
95
|
+
private readonly _edgeConnection: EdgeConnection | undefined;
|
|
96
|
+
private readonly _edgeFeatures: Runtime.Client.EdgeFeatures | undefined;
|
|
97
|
+
private readonly _callbacks: IdentityManagerCallbacks | undefined;
|
|
98
|
+
|
|
99
|
+
private _identity?: Identity;
|
|
79
100
|
|
|
80
|
-
// TODO(burdon): IdentityManagerParams.
|
|
81
101
|
// TODO(dmaretskyi): Perhaps this should take/generate the peerKey outside of an initialized identity.
|
|
82
|
-
constructor(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
params
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const {
|
|
93
|
-
devicePresenceAnnounceInterval = DEVICE_PRESENCE_ANNOUNCE_INTERVAL,
|
|
94
|
-
devicePresenceOfflineTimeout = DEVICE_PRESENCE_OFFLINE_TIMEOUT,
|
|
95
|
-
} = params ?? {};
|
|
96
|
-
this._devicePresenceAnnounceInterval = devicePresenceAnnounceInterval;
|
|
97
|
-
this._devicePresenceOfflineTimeout = devicePresenceOfflineTimeout;
|
|
102
|
+
constructor(params: IdentityManagerParams) {
|
|
103
|
+
this._metadataStore = params.metadataStore;
|
|
104
|
+
this._keyring = params.keyring;
|
|
105
|
+
this._feedStore = params.feedStore;
|
|
106
|
+
this._spaceManager = params.spaceManager;
|
|
107
|
+
this._edgeConnection = params.edgeConnection;
|
|
108
|
+
this._edgeFeatures = params.edgeFeatures;
|
|
109
|
+
this._devicePresenceAnnounceInterval = params.devicePresenceAnnounceInterval ?? DEVICE_PRESENCE_ANNOUNCE_INTERVAL;
|
|
110
|
+
this._devicePresenceOfflineTimeout = params.devicePresenceOfflineTimeout ?? DEVICE_PRESENCE_OFFLINE_TIMEOUT;
|
|
111
|
+
this._callbacks = params.callbacks;
|
|
98
112
|
}
|
|
99
113
|
|
|
100
114
|
get identity() {
|
|
@@ -360,6 +374,8 @@ export class IdentityManager {
|
|
|
360
374
|
signer: this._keyring,
|
|
361
375
|
identityKey: identityRecord.identityKey,
|
|
362
376
|
deviceKey: identityRecord.deviceKey,
|
|
377
|
+
edgeConnection: this._edgeConnection,
|
|
378
|
+
edgeFeatures: this._edgeFeatures,
|
|
363
379
|
});
|
|
364
380
|
log('done', { identityKey: identityRecord.identityKey });
|
|
365
381
|
this._callbacks?.onIdentityConstruction?.(identity);
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { onTestFinished, describe, expect, test } from 'vitest';
|
|
6
6
|
|
|
7
|
+
import { Event } from '@dxos/async';
|
|
7
8
|
import { Context } from '@dxos/context';
|
|
8
9
|
import { CredentialGenerator, verifyCredential } from '@dxos/credentials';
|
|
9
10
|
import {
|
|
@@ -15,7 +16,9 @@ import {
|
|
|
15
16
|
SpaceProtocol,
|
|
16
17
|
valueEncoding,
|
|
17
18
|
} from '@dxos/echo-pipeline';
|
|
19
|
+
import { type EdgeConnection, type MessageListener } from '@dxos/edge-client';
|
|
18
20
|
import { FeedFactory, FeedStore } from '@dxos/feed-store';
|
|
21
|
+
import { type FeedWrapper } from '@dxos/feed-store';
|
|
19
22
|
import { Keyring } from '@dxos/keyring';
|
|
20
23
|
import { type PublicKey } from '@dxos/keys';
|
|
21
24
|
import { MemorySignalManager, MemorySignalManagerContext } from '@dxos/messaging';
|
|
@@ -41,16 +44,108 @@ const createStores = () => {
|
|
|
41
44
|
|
|
42
45
|
describe('identity/identity', () => {
|
|
43
46
|
test('create', async () => {
|
|
47
|
+
const setup = await setupIdentity();
|
|
48
|
+
|
|
49
|
+
await writeGenesisCredential(setup);
|
|
50
|
+
|
|
51
|
+
// Wait for identity to be ready.
|
|
52
|
+
await setup.identity.ready();
|
|
53
|
+
const identitySigner = setup.identity.getIdentityCredentialSigner();
|
|
54
|
+
const credential = await identitySigner.createCredential({
|
|
55
|
+
subject: setup.identityKey,
|
|
56
|
+
assertion: {
|
|
57
|
+
'@type': 'dxos.halo.credentials.IdentityProfile',
|
|
58
|
+
profile: {
|
|
59
|
+
displayName: 'Alice',
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
expect(credential.issuer).toEqual(setup.identityKey);
|
|
65
|
+
expect(await verifyCredential(credential)).toEqual({ kind: 'pass' });
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('two devices', async () => {
|
|
69
|
+
const signalContext = new MemorySignalManagerContext();
|
|
70
|
+
|
|
71
|
+
const owner = await setupIdentity({ signalContext });
|
|
72
|
+
await writeGenesisCredential(owner);
|
|
73
|
+
await owner.identity.ready();
|
|
74
|
+
|
|
75
|
+
const secondDevice = (
|
|
76
|
+
await setupIdentity({
|
|
77
|
+
signalContext,
|
|
78
|
+
spaceKey: owner.spaceKey,
|
|
79
|
+
identityKey: owner.identityKey,
|
|
80
|
+
genesisFeedKey: owner.controlFeed.key,
|
|
81
|
+
})
|
|
82
|
+
).identity;
|
|
83
|
+
|
|
84
|
+
//
|
|
85
|
+
// Second device admission
|
|
86
|
+
//
|
|
87
|
+
{
|
|
88
|
+
const signer = owner.identity.getIdentityCredentialSigner();
|
|
89
|
+
void owner.identity.controlPipeline.writer.write({
|
|
90
|
+
credential: {
|
|
91
|
+
credential: await signer.createCredential({
|
|
92
|
+
subject: secondDevice.deviceKey,
|
|
93
|
+
assertion: {
|
|
94
|
+
'@type': 'dxos.halo.credentials.AuthorizedDevice',
|
|
95
|
+
identityKey: owner.identityKey,
|
|
96
|
+
deviceKey: secondDevice.deviceKey,
|
|
97
|
+
},
|
|
98
|
+
}),
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
await secondDevice.ready();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
expect(Array.from(owner.identity.authorizedDeviceKeys.keys())).toEqual([owner.deviceKey, secondDevice.deviceKey]);
|
|
106
|
+
expect(Array.from(secondDevice.authorizedDeviceKeys.keys())).toEqual([owner.deviceKey, secondDevice.deviceKey]);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('edge feed replicator', async () => {
|
|
110
|
+
let replicationStarted = false;
|
|
111
|
+
const connectedEvent = new Event();
|
|
112
|
+
const setup = await setupIdentity({
|
|
113
|
+
edgeConnection: {
|
|
114
|
+
connected: connectedEvent,
|
|
115
|
+
open: async () => {},
|
|
116
|
+
close: async () => {},
|
|
117
|
+
addListener: (_: MessageListener): (() => void) => {
|
|
118
|
+
return () => {};
|
|
119
|
+
},
|
|
120
|
+
send: async (_) => {
|
|
121
|
+
replicationStarted = true;
|
|
122
|
+
},
|
|
123
|
+
} as EdgeConnection,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
await writeGenesisCredential(setup);
|
|
127
|
+
connectedEvent.emit();
|
|
128
|
+
|
|
129
|
+
await expect.poll(() => replicationStarted).toBeTruthy();
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const setupIdentity = async (args?: {
|
|
133
|
+
signalContext?: MemorySignalManagerContext;
|
|
134
|
+
spaceKey?: PublicKey;
|
|
135
|
+
identityKey?: PublicKey;
|
|
136
|
+
genesisFeedKey?: PublicKey;
|
|
137
|
+
edgeConnection?: EdgeConnection;
|
|
138
|
+
}): Promise<TestIdentitySetup> => {
|
|
44
139
|
const { storage, metadataStore, blobStore } = createStores();
|
|
45
140
|
|
|
46
141
|
const keyring = new Keyring();
|
|
47
|
-
const identityKey = await keyring.createKey();
|
|
48
142
|
const deviceKey = await keyring.createKey();
|
|
49
|
-
const
|
|
143
|
+
const identityKey = args?.identityKey ?? (await keyring.createKey());
|
|
144
|
+
const spaceKey = args?.spaceKey ?? (await keyring.createKey());
|
|
50
145
|
|
|
51
146
|
const feedStore = new FeedStore<FeedMessage>({
|
|
52
147
|
factory: new FeedFactory<FeedMessage>({
|
|
53
|
-
root: storage.createDirectory(
|
|
148
|
+
root: storage.createDirectory(),
|
|
54
149
|
signer: keyring,
|
|
55
150
|
hypercore: {
|
|
56
151
|
valueEncoding,
|
|
@@ -76,7 +171,7 @@ describe('identity/identity', () => {
|
|
|
76
171
|
},
|
|
77
172
|
blobStore,
|
|
78
173
|
networkManager: new SwarmNetworkManager({
|
|
79
|
-
signalManager: new MemorySignalManager(new MemorySignalManagerContext()),
|
|
174
|
+
signalManager: new MemorySignalManager(args?.signalContext ?? new MemorySignalManagerContext()),
|
|
80
175
|
transportFactory: MemoryTransportFactory,
|
|
81
176
|
}),
|
|
82
177
|
});
|
|
@@ -86,7 +181,7 @@ describe('identity/identity', () => {
|
|
|
86
181
|
id: await createIdFromSpaceKey(spaceKey),
|
|
87
182
|
spaceKey,
|
|
88
183
|
protocol,
|
|
89
|
-
genesisFeed: controlFeed,
|
|
184
|
+
genesisFeed: args?.genesisFeedKey ? await feedStore.openFeed(args.genesisFeedKey) : controlFeed,
|
|
90
185
|
feedProvider: (feedKey) => feedStore.openFeed(feedKey),
|
|
91
186
|
memberKey: identityKey,
|
|
92
187
|
metadataStore,
|
|
@@ -102,242 +197,37 @@ describe('identity/identity', () => {
|
|
|
102
197
|
identityKey,
|
|
103
198
|
deviceKey,
|
|
104
199
|
space,
|
|
200
|
+
edgeFeatures: args?.edgeConnection && { feedReplicator: true },
|
|
201
|
+
edgeConnection: args?.edgeConnection,
|
|
105
202
|
});
|
|
106
203
|
|
|
107
204
|
await identity.open(new Context());
|
|
108
205
|
onTestFinished(() => identity.close(new Context()));
|
|
206
|
+
return { identity, identityKey, keyring, deviceKey, controlFeed, spaceKey, dataFeed };
|
|
207
|
+
};
|
|
109
208
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
for (const credential of credentials) {
|
|
122
|
-
await identity.controlPipeline.writer.write({
|
|
123
|
-
credential: { credential },
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Wait for identity to be ready.
|
|
129
|
-
await identity.ready();
|
|
130
|
-
const identitySigner = identity.getIdentityCredentialSigner();
|
|
131
|
-
const credential = await identitySigner.createCredential({
|
|
132
|
-
subject: identityKey,
|
|
133
|
-
assertion: {
|
|
134
|
-
'@type': 'dxos.halo.credentials.IdentityProfile',
|
|
135
|
-
profile: {
|
|
136
|
-
displayName: 'Alice',
|
|
137
|
-
},
|
|
138
|
-
},
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
expect(credential.issuer).toEqual(identityKey);
|
|
142
|
-
expect(await verifyCredential(credential)).toEqual({ kind: 'pass' });
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
test('two devices', async () => {
|
|
146
|
-
const signalContext = new MemorySignalManagerContext();
|
|
147
|
-
|
|
148
|
-
let spaceKey: PublicKey;
|
|
149
|
-
let identityKey: PublicKey;
|
|
150
|
-
let genesisFeedKey: PublicKey;
|
|
151
|
-
let identity1: Identity;
|
|
152
|
-
let identity2: Identity;
|
|
153
|
-
|
|
154
|
-
//
|
|
155
|
-
// First device
|
|
156
|
-
//
|
|
157
|
-
{
|
|
158
|
-
const { storage, metadataStore, blobStore } = createStores();
|
|
159
|
-
|
|
160
|
-
const keyring = new Keyring();
|
|
161
|
-
identityKey = await keyring.createKey();
|
|
162
|
-
const deviceKey = await keyring.createKey();
|
|
163
|
-
spaceKey = await keyring.createKey();
|
|
164
|
-
|
|
165
|
-
const feedStore = new FeedStore<FeedMessage>({
|
|
166
|
-
factory: new FeedFactory<FeedMessage>({
|
|
167
|
-
root: storage.createDirectory(),
|
|
168
|
-
signer: keyring,
|
|
169
|
-
hypercore: {
|
|
170
|
-
valueEncoding,
|
|
171
|
-
},
|
|
172
|
-
}),
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
const createFeed = async () => {
|
|
176
|
-
const feedKey = await keyring.createKey();
|
|
177
|
-
return feedStore.openFeed(feedKey, { writable: true });
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
const controlFeed = await createFeed();
|
|
181
|
-
genesisFeedKey = controlFeed.key;
|
|
182
|
-
|
|
183
|
-
const dataFeed = await createFeed();
|
|
184
|
-
|
|
185
|
-
const protocol = new SpaceProtocol({
|
|
186
|
-
topic: spaceKey,
|
|
187
|
-
swarmIdentity: {
|
|
188
|
-
peerKey: deviceKey,
|
|
189
|
-
identityKey,
|
|
190
|
-
credentialProvider: MOCK_AUTH_PROVIDER, // createHaloAuthProvider(createCredentialSignerWithKey(keyring, device_key)),
|
|
191
|
-
credentialAuthenticator: MOCK_AUTH_VERIFIER, // createHaloAuthVerifier(() => identity.authorizedDeviceKeys),
|
|
192
|
-
},
|
|
193
|
-
blobStore,
|
|
194
|
-
networkManager: new SwarmNetworkManager({
|
|
195
|
-
signalManager: new MemorySignalManager(signalContext),
|
|
196
|
-
transportFactory: MemoryTransportFactory,
|
|
197
|
-
}),
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
await metadataStore.setIdentityRecord({ haloSpace: { key: spaceKey }, identityKey, deviceKey });
|
|
201
|
-
const space = new Space({
|
|
202
|
-
id: await createIdFromSpaceKey(spaceKey),
|
|
203
|
-
spaceKey,
|
|
204
|
-
protocol,
|
|
205
|
-
genesisFeed: controlFeed,
|
|
206
|
-
feedProvider: (feedKey) => feedStore.openFeed(feedKey),
|
|
207
|
-
memberKey: identityKey,
|
|
208
|
-
metadataStore,
|
|
209
|
-
onDelegatedInvitationStatusChange: async () => {},
|
|
210
|
-
onMemberRolesChanged: async () => {},
|
|
211
|
-
});
|
|
212
|
-
await space.setControlFeed(controlFeed);
|
|
213
|
-
await space.setDataFeed(dataFeed);
|
|
214
|
-
|
|
215
|
-
const identity = (identity1 = new Identity({
|
|
216
|
-
signer: keyring,
|
|
217
|
-
identityKey,
|
|
218
|
-
deviceKey,
|
|
219
|
-
space,
|
|
220
|
-
}));
|
|
221
|
-
|
|
222
|
-
await identity.open(new Context());
|
|
223
|
-
onTestFinished(() => identity.close(new Context()));
|
|
224
|
-
|
|
225
|
-
//
|
|
226
|
-
// Identity genesis
|
|
227
|
-
//
|
|
228
|
-
{
|
|
229
|
-
const generator = new CredentialGenerator(keyring, identityKey, deviceKey);
|
|
230
|
-
const credentials = [
|
|
231
|
-
...(await generator.createSpaceGenesis(spaceKey, controlFeed.key)),
|
|
232
|
-
await generator.createDeviceAuthorization(deviceKey),
|
|
233
|
-
await generator.createFeedAdmission(spaceKey, dataFeed.key, AdmittedFeed.Designation.DATA),
|
|
234
|
-
];
|
|
235
|
-
|
|
236
|
-
for (const credential of credentials) {
|
|
237
|
-
await identity.controlPipeline.writer.write({
|
|
238
|
-
credential: { credential },
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// Wait for identity to be ready.
|
|
244
|
-
await identity.ready();
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
//
|
|
248
|
-
// Second device
|
|
249
|
-
//
|
|
250
|
-
{
|
|
251
|
-
const { storage, metadataStore, blobStore } = createStores();
|
|
252
|
-
|
|
253
|
-
const keyring = new Keyring();
|
|
254
|
-
const deviceKey = await keyring.createKey();
|
|
255
|
-
|
|
256
|
-
const feedStore = new FeedStore<FeedMessage>({
|
|
257
|
-
factory: new FeedFactory<FeedMessage>({
|
|
258
|
-
root: storage.createDirectory(),
|
|
259
|
-
signer: keyring,
|
|
260
|
-
hypercore: {
|
|
261
|
-
valueEncoding,
|
|
262
|
-
},
|
|
263
|
-
}),
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
const createFeed = async () => {
|
|
267
|
-
const feedKey = await keyring.createKey();
|
|
268
|
-
return feedStore.openFeed(feedKey, { writable: true });
|
|
269
|
-
};
|
|
270
|
-
|
|
271
|
-
const controlFeed = await createFeed();
|
|
272
|
-
const dataFeed = await createFeed();
|
|
273
|
-
|
|
274
|
-
const protocol = new SpaceProtocol({
|
|
275
|
-
topic: spaceKey,
|
|
276
|
-
swarmIdentity: {
|
|
277
|
-
peerKey: deviceKey,
|
|
278
|
-
identityKey,
|
|
279
|
-
credentialProvider: MOCK_AUTH_PROVIDER, // createHaloAuthProvider(createCredentialSignerWithKey(keyring, device_key)),
|
|
280
|
-
credentialAuthenticator: MOCK_AUTH_VERIFIER, // createHaloAuthVerifier(() => identity.authorizedDeviceKeys),
|
|
281
|
-
},
|
|
282
|
-
blobStore,
|
|
283
|
-
networkManager: new SwarmNetworkManager({
|
|
284
|
-
signalManager: new MemorySignalManager(signalContext),
|
|
285
|
-
transportFactory: MemoryTransportFactory,
|
|
286
|
-
}),
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
await metadataStore.setIdentityRecord({
|
|
290
|
-
haloSpace: { key: spaceKey },
|
|
291
|
-
identityKey: identity1.identityKey,
|
|
292
|
-
deviceKey,
|
|
293
|
-
});
|
|
294
|
-
const space = new Space({
|
|
295
|
-
id: await createIdFromSpaceKey(spaceKey),
|
|
296
|
-
spaceKey,
|
|
297
|
-
protocol,
|
|
298
|
-
genesisFeed: await feedStore.openFeed(genesisFeedKey),
|
|
299
|
-
feedProvider: (feedKey) => feedStore.openFeed(feedKey),
|
|
300
|
-
memberKey: identityKey,
|
|
301
|
-
metadataStore,
|
|
302
|
-
onDelegatedInvitationStatusChange: async () => {},
|
|
303
|
-
onMemberRolesChanged: async () => {},
|
|
209
|
+
const writeGenesisCredential = async (setup: TestIdentitySetup) => {
|
|
210
|
+
const generator = new CredentialGenerator(setup.keyring, setup.identityKey, setup.deviceKey);
|
|
211
|
+
const credentials = [
|
|
212
|
+
...(await generator.createSpaceGenesis(setup.spaceKey, setup.controlFeed.key)),
|
|
213
|
+
await generator.createDeviceAuthorization(setup.deviceKey),
|
|
214
|
+
await generator.createFeedAdmission(setup.spaceKey, setup.dataFeed.key, AdmittedFeed.Designation.DATA),
|
|
215
|
+
];
|
|
216
|
+
|
|
217
|
+
for (const credential of credentials) {
|
|
218
|
+
await setup.identity.controlPipeline.writer.write({
|
|
219
|
+
credential: { credential },
|
|
304
220
|
});
|
|
305
|
-
await space.setControlFeed(controlFeed);
|
|
306
|
-
await space.setDataFeed(dataFeed);
|
|
307
|
-
|
|
308
|
-
const identity = (identity2 = new Identity({
|
|
309
|
-
signer: keyring,
|
|
310
|
-
identityKey: identity1.identityKey,
|
|
311
|
-
deviceKey,
|
|
312
|
-
space,
|
|
313
|
-
}));
|
|
314
|
-
|
|
315
|
-
await identity.open(new Context());
|
|
316
|
-
onTestFinished(() => identity.close(new Context()));
|
|
317
221
|
}
|
|
318
|
-
|
|
319
|
-
//
|
|
320
|
-
// Second device admission
|
|
321
|
-
//
|
|
322
|
-
{
|
|
323
|
-
const signer = identity1.getIdentityCredentialSigner();
|
|
324
|
-
void identity1.controlPipeline.writer.write({
|
|
325
|
-
credential: {
|
|
326
|
-
credential: await signer.createCredential({
|
|
327
|
-
subject: identity2.deviceKey,
|
|
328
|
-
assertion: {
|
|
329
|
-
'@type': 'dxos.halo.credentials.AuthorizedDevice',
|
|
330
|
-
identityKey: identity1.identityKey,
|
|
331
|
-
deviceKey: identity2.deviceKey,
|
|
332
|
-
},
|
|
333
|
-
}),
|
|
334
|
-
},
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
await identity2.ready();
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
expect(Array.from(identity1.authorizedDeviceKeys.keys())).toEqual([identity1.deviceKey, identity2.deviceKey]);
|
|
341
|
-
expect(Array.from(identity2.authorizedDeviceKeys.keys())).toEqual([identity1.deviceKey, identity2.deviceKey]);
|
|
342
|
-
});
|
|
222
|
+
};
|
|
343
223
|
});
|
|
224
|
+
|
|
225
|
+
type TestIdentitySetup = {
|
|
226
|
+
identity: Identity;
|
|
227
|
+
keyring: Keyring;
|
|
228
|
+
identityKey: PublicKey;
|
|
229
|
+
deviceKey: PublicKey;
|
|
230
|
+
spaceKey: PublicKey;
|
|
231
|
+
controlFeed: FeedWrapper<FeedMessage>;
|
|
232
|
+
dataFeed: FeedWrapper<FeedMessage>;
|
|
233
|
+
};
|