@dxos/echo-db 2.33.2 → 2.33.3-dev.5c4af82a
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/src/echo.test.js +10 -10
- package/dist/src/echo.test.js.map +1 -1
- package/dist/src/halo/halo.d.ts +1 -0
- package/dist/src/halo/halo.d.ts.map +1 -1
- package/dist/src/halo/halo.js +10 -1
- package/dist/src/halo/halo.js.map +1 -1
- package/dist/src/halo/identity-manager.d.ts +0 -1
- package/dist/src/halo/identity-manager.d.ts.map +1 -1
- package/dist/src/halo/identity-manager.js +11 -11
- package/dist/src/halo/identity-manager.js.map +1 -1
- package/dist/src/halo/identity.d.ts +15 -11
- package/dist/src/halo/identity.d.ts.map +1 -1
- package/dist/src/halo/identity.js +17 -20
- package/dist/src/halo/identity.js.map +1 -1
- package/dist/src/invitations/offline-invitation-claimer.d.ts.map +1 -1
- package/dist/src/invitations/offline-invitation-claimer.js +1 -3
- package/dist/src/invitations/offline-invitation-claimer.js.map +1 -1
- package/dist/src/parties/party-factory.d.ts.map +1 -1
- package/dist/src/parties/party-factory.js +1 -10
- package/dist/src/parties/party-factory.js.map +1 -1
- package/dist/src/parties/party-manager.d.ts.map +1 -1
- package/dist/src/parties/party-manager.js +2 -1
- package/dist/src/parties/party-manager.js.map +1 -1
- package/dist/src/protocol/credentials-signer.d.ts +4 -4
- package/dist/src/protocol/credentials-signer.d.ts.map +1 -1
- package/dist/src/protocol/credentials-signer.js +8 -8
- package/dist/src/protocol/credentials-signer.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +17 -17
- package/src/echo.test.ts +10 -10
- package/src/halo/halo.ts +8 -1
- package/src/halo/identity-manager.ts +13 -14
- package/src/halo/identity.ts +32 -35
- package/src/invitations/offline-invitation-claimer.ts +3 -4
- package/src/parties/party-factory.ts +1 -8
- package/src/parties/party-manager.ts +2 -1
- package/src/protocol/credentials-signer.ts +9 -9
package/src/halo/halo.ts
CHANGED
|
@@ -46,6 +46,8 @@ export class HALO {
|
|
|
46
46
|
private readonly _keyring: Keyring;
|
|
47
47
|
private readonly _identityManager: IdentityManager;
|
|
48
48
|
|
|
49
|
+
private _isOpen = false;
|
|
50
|
+
|
|
49
51
|
constructor ({
|
|
50
52
|
keyring,
|
|
51
53
|
networkManager,
|
|
@@ -85,7 +87,7 @@ export class HALO {
|
|
|
85
87
|
* Whether the current identity manager has been initialized.
|
|
86
88
|
*/
|
|
87
89
|
get isInitialized (): boolean {
|
|
88
|
-
return this.
|
|
90
|
+
return this._isOpen;
|
|
89
91
|
}
|
|
90
92
|
|
|
91
93
|
/**
|
|
@@ -129,6 +131,7 @@ export class HALO {
|
|
|
129
131
|
*
|
|
130
132
|
* Loads the saved identity from disk. Is called by client.
|
|
131
133
|
*/
|
|
134
|
+
@synchronized
|
|
132
135
|
async open (onProgressCallback?: ((progress: OpenProgress) => void) | undefined) {
|
|
133
136
|
// TODO(burdon): Replace with events.
|
|
134
137
|
onProgressCallback?.({ haloOpened: false });
|
|
@@ -137,12 +140,16 @@ export class HALO {
|
|
|
137
140
|
await this._identityManager.loadFromStorage();
|
|
138
141
|
|
|
139
142
|
onProgressCallback?.({ haloOpened: true });
|
|
143
|
+
|
|
144
|
+
this._isOpen = true;
|
|
140
145
|
}
|
|
141
146
|
|
|
142
147
|
/**
|
|
143
148
|
* Closes HALO. Automatically called when client is destroyed.
|
|
144
149
|
*/
|
|
150
|
+
@synchronized
|
|
145
151
|
async close () {
|
|
152
|
+
this._isOpen = false;
|
|
146
153
|
await this._identityManager.close();
|
|
147
154
|
}
|
|
148
155
|
|
|
@@ -7,6 +7,7 @@ import debug from 'debug';
|
|
|
7
7
|
|
|
8
8
|
import { Event, synchronized, waitForCondition } from '@dxos/async';
|
|
9
9
|
import { Filter, KeyRecord, Keyring, KeyType, SecretProvider } from '@dxos/credentials';
|
|
10
|
+
import { failUndefined } from '@dxos/debug';
|
|
10
11
|
|
|
11
12
|
import { InvitationDescriptor } from '../invitations';
|
|
12
13
|
import { MetadataStore } from '../pipeline';
|
|
@@ -34,25 +35,23 @@ export class IdentityManager {
|
|
|
34
35
|
return this._identity;
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
get initialized (): boolean {
|
|
38
|
-
return this._identity !== undefined &&
|
|
39
|
-
!!this._identity.halo &&
|
|
40
|
-
this._identity.halo.isOpen &&
|
|
41
|
-
!!this._identity.halo!.memberKeys.length &&
|
|
42
|
-
!!this._identity.halo!.identityGenesis &&
|
|
43
|
-
!!this._identity.deviceKeyChain;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
38
|
private async _initialize (halo: HaloParty) {
|
|
47
39
|
assert(halo.isOpen, 'HALO must be open.');
|
|
48
40
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
//
|
|
52
|
-
|
|
41
|
+
// Wait for the minimum set of keys and messages we need for proper function:
|
|
42
|
+
//
|
|
43
|
+
// - KeyAdmit message for the current device so we can build the device KeyChain.
|
|
44
|
+
// - Identity genesis so it can be copied into newly joined parties.
|
|
45
|
+
//
|
|
46
|
+
const deviceKey = this._keyring.findKey(Keyring.signingFilter({ type: KeyType.DEVICE })) ?? failUndefined();
|
|
47
|
+
await waitForCondition(() =>
|
|
48
|
+
halo.processor.isMemberKey(deviceKey.publicKey) &&
|
|
49
|
+
halo.identityGenesis
|
|
50
|
+
);
|
|
53
51
|
|
|
54
|
-
|
|
52
|
+
this._identity = new Identity(this._keyring, halo);
|
|
55
53
|
this.ready.emit();
|
|
54
|
+
log('HALO initialized.');
|
|
56
55
|
}
|
|
57
56
|
|
|
58
57
|
async close () {
|
package/src/halo/identity.ts
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
// Copyright 2021 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import assert from 'assert';
|
|
5
6
|
import debug from 'debug';
|
|
6
7
|
|
|
7
|
-
import { Filter, KeyChain, KeyRecord, Keyring, KeyType, Signer } from '@dxos/credentials';
|
|
8
|
-
import {
|
|
8
|
+
import { Filter, KeyChain, KeyRecord, Keyring, KeyType, SignedMessage, Signer } from '@dxos/credentials';
|
|
9
|
+
import { failUndefined } from '@dxos/debug';
|
|
9
10
|
|
|
10
|
-
import { IdentityNotInitializedError } from '../errors';
|
|
11
11
|
import { CredentialsSigner } from '../protocol/credentials-signer';
|
|
12
12
|
import { ContactManager } from './contact-manager';
|
|
13
13
|
import { HaloParty } from './halo-party';
|
|
@@ -21,9 +21,9 @@ const log = debug('dxos:echo-db:identity');
|
|
|
21
21
|
* Acts as a read-only view into IdentityManager.
|
|
22
22
|
*/
|
|
23
23
|
export class Identity {
|
|
24
|
-
private _identityKey
|
|
25
|
-
private _deviceKey
|
|
26
|
-
private _deviceKeyChain
|
|
24
|
+
private readonly _identityKey: KeyRecord;
|
|
25
|
+
private readonly _deviceKey: KeyRecord;
|
|
26
|
+
private readonly _deviceKeyChain: KeyChain;
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* @param _halo HALO party. Must be open.
|
|
@@ -31,54 +31,51 @@ export class Identity {
|
|
|
31
31
|
constructor (
|
|
32
32
|
private readonly _keyring: Keyring,
|
|
33
33
|
private readonly _halo: HaloParty
|
|
34
|
-
) {
|
|
34
|
+
) {
|
|
35
|
+
this._identityKey = this._keyring.findKey(Filter.matches({ type: KeyType.IDENTITY, own: true, trusted: true })) ?? failUndefined();
|
|
36
|
+
this._deviceKey = this._keyring.findKey(Keyring.signingFilter({ type: KeyType.DEVICE })) ?? failUndefined();
|
|
37
|
+
this._deviceKeyChain = getDeviceKeyChainFromHalo(this._halo, this.deviceKey);
|
|
38
|
+
assert(this._halo.identityGenesis);
|
|
39
|
+
}
|
|
35
40
|
|
|
36
41
|
get signer (): Signer {
|
|
37
42
|
return this._keyring;
|
|
38
43
|
}
|
|
39
44
|
|
|
40
|
-
get identityKey (): KeyRecord
|
|
41
|
-
if (!this._identityKey) {
|
|
42
|
-
this._identityKey = this._keyring.findKey(Filter.matches({ type: KeyType.IDENTITY, own: true, trusted: true }));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
+
get identityKey (): KeyRecord {
|
|
45
46
|
return this._identityKey;
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
get deviceKey (): KeyRecord
|
|
49
|
-
if (!this._deviceKey) {
|
|
50
|
-
this._deviceKey = this._keyring.findKey(Keyring.signingFilter({ type: KeyType.DEVICE }));
|
|
51
|
-
}
|
|
52
|
-
|
|
49
|
+
get deviceKey (): KeyRecord {
|
|
53
50
|
return this._deviceKey;
|
|
54
51
|
}
|
|
55
52
|
|
|
56
|
-
get deviceKeyChain (): KeyChain
|
|
57
|
-
if (!this._deviceKeyChain) {
|
|
58
|
-
this._deviceKeyChain = this.deviceKey && this._halo ? getDeviceKeyChainFromHalo(this._halo, this.deviceKey) : undefined;
|
|
59
|
-
}
|
|
60
|
-
|
|
53
|
+
get deviceKeyChain (): KeyChain {
|
|
61
54
|
return this._deviceKeyChain;
|
|
62
55
|
}
|
|
63
56
|
|
|
64
|
-
get preferences (): Preferences
|
|
65
|
-
return this._halo
|
|
57
|
+
get preferences (): Preferences {
|
|
58
|
+
return this._halo.preferences;
|
|
66
59
|
}
|
|
67
60
|
|
|
68
|
-
get contacts (): ContactManager
|
|
69
|
-
return this._halo
|
|
61
|
+
get contacts (): ContactManager {
|
|
62
|
+
return this._halo.contacts;
|
|
70
63
|
}
|
|
71
64
|
|
|
72
65
|
get displayName (): string | undefined {
|
|
73
66
|
return this.identityInfo?.signed.payload.displayName;
|
|
74
67
|
}
|
|
75
68
|
|
|
76
|
-
|
|
77
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Contains profile username.
|
|
71
|
+
* Can be missing if the username wasn't provided when profile was created.
|
|
72
|
+
*/
|
|
73
|
+
get identityInfo (): SignedMessage | undefined {
|
|
74
|
+
return this._halo.identityInfo;
|
|
78
75
|
}
|
|
79
76
|
|
|
80
|
-
get identityGenesis () {
|
|
81
|
-
return this._halo
|
|
77
|
+
get identityGenesis (): SignedMessage {
|
|
78
|
+
return this._halo.identityGenesis ?? failUndefined();
|
|
82
79
|
}
|
|
83
80
|
|
|
84
81
|
/**
|
|
@@ -95,9 +92,9 @@ export class Identity {
|
|
|
95
92
|
createCredentialsSigner (): CredentialsSigner {
|
|
96
93
|
return new CredentialsSigner(
|
|
97
94
|
this._keyring,
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
95
|
+
this.identityKey,
|
|
96
|
+
this.deviceKey,
|
|
97
|
+
this.deviceKeyChain
|
|
101
98
|
);
|
|
102
99
|
}
|
|
103
100
|
}
|
|
@@ -112,7 +109,7 @@ function getDeviceKeyChainFromHalo (halo: HaloParty, deviceKey: KeyRecord) {
|
|
|
112
109
|
halo.feedKeys
|
|
113
110
|
);
|
|
114
111
|
} catch (err: any) {
|
|
115
|
-
log('Unable to locate device KeyChain:', err);
|
|
116
|
-
|
|
112
|
+
log('Unable to locate device KeyChain:', err);
|
|
113
|
+
throw err;
|
|
117
114
|
}
|
|
118
115
|
}
|
|
@@ -21,10 +21,9 @@ import {
|
|
|
21
21
|
codec
|
|
22
22
|
} from '@dxos/credentials';
|
|
23
23
|
import { keyToBuffer, keyToString, PublicKey, randomBytes } from '@dxos/crypto';
|
|
24
|
-
import { raise } from '@dxos/debug';
|
|
25
24
|
import { FullyConnectedTopology, NetworkManager } from '@dxos/network-manager';
|
|
26
25
|
|
|
27
|
-
import {
|
|
26
|
+
import { InvalidInvitationError } from '../errors';
|
|
28
27
|
import { Identity } from '../halo';
|
|
29
28
|
import { greetingProtocolProvider } from './greeting-protocol-provider';
|
|
30
29
|
import { GreetingState } from './greeting-responder';
|
|
@@ -179,8 +178,8 @@ export class OfflineInvitationClaimer {
|
|
|
179
178
|
createAuthMessage(
|
|
180
179
|
identity.signer,
|
|
181
180
|
info!.id.value,
|
|
182
|
-
identity.identityKey
|
|
183
|
-
identity.deviceKeyChain
|
|
181
|
+
identity.identityKey,
|
|
182
|
+
identity.deviceKeyChain,
|
|
184
183
|
undefined,
|
|
185
184
|
info!.authNonce.value)
|
|
186
185
|
));
|
|
@@ -52,8 +52,6 @@ export class PartyFactory {
|
|
|
52
52
|
@timed(5_000)
|
|
53
53
|
async createParty (): Promise<DataParty> {
|
|
54
54
|
const identity = this._identityProvider() ?? raise(new IdentityNotInitializedError());
|
|
55
|
-
assert(identity.identityGenesis, 'HALO not initialized.');
|
|
56
|
-
assert(identity.deviceKeyChain, 'Device KeyChain not initialized.');
|
|
57
55
|
assert(!this._options.readOnly, 'PartyFactory is read-only.');
|
|
58
56
|
|
|
59
57
|
const partyKey = await identity.keyring.createKeyRecord({ type: KeyType.PARTY });
|
|
@@ -138,7 +136,6 @@ export class PartyFactory {
|
|
|
138
136
|
);
|
|
139
137
|
|
|
140
138
|
await party.open();
|
|
141
|
-
assert(identity.identityKey, 'No identity key.');
|
|
142
139
|
const isHalo = identity.identityKey.publicKey.equals(partyKey);
|
|
143
140
|
const signingKey = isHalo ? identity.deviceKey : identity.deviceKeyChain;
|
|
144
141
|
assert(signingKey, 'No device key or keychain.');
|
|
@@ -213,7 +210,7 @@ export class PartyFactory {
|
|
|
213
210
|
async (partyKey, nonce) => [createDataPartyAdmissionMessages(
|
|
214
211
|
identity.createCredentialsSigner(),
|
|
215
212
|
partyKey,
|
|
216
|
-
identity.identityGenesis
|
|
213
|
+
identity.identityGenesis,
|
|
217
214
|
nonce
|
|
218
215
|
)]
|
|
219
216
|
);
|
|
@@ -223,8 +220,6 @@ export class PartyFactory {
|
|
|
223
220
|
const party = await this.addParty(partyKey, hints);
|
|
224
221
|
await initiator.destroy();
|
|
225
222
|
if (!haloInvitation) {
|
|
226
|
-
assert(identity.deviceKeyChain);
|
|
227
|
-
|
|
228
223
|
// Copy our signed IdentityInfo into the new Party.
|
|
229
224
|
const infoMessage = identity.identityInfo;
|
|
230
225
|
if (infoMessage) {
|
|
@@ -244,8 +239,6 @@ export class PartyFactory {
|
|
|
244
239
|
const identity = this._identityProvider() ?? raise(new IdentityNotInitializedError());
|
|
245
240
|
|
|
246
241
|
assert(!this._options.readOnly, 'PartyFactory is read-only');
|
|
247
|
-
assert(identity.identityGenesis, 'IdentityGenesis must exist');
|
|
248
|
-
assert(identity.deviceKeyChain, 'Device KeyChain must exist');
|
|
249
242
|
|
|
250
243
|
const partyKey = await identity.keyring.createKeyRecord({ type: KeyType.PARTY });
|
|
251
244
|
const party = await this.constructParty(partyKey.publicKey);
|
|
@@ -74,10 +74,11 @@ export class PartyManager {
|
|
|
74
74
|
|
|
75
75
|
let partyKeys = this._metadataStore.parties.map(party => party.key).filter(boolGuard);
|
|
76
76
|
|
|
77
|
+
// Identity may be undefined, for example, on the first start.
|
|
77
78
|
const identity = this._identityProvider();
|
|
78
79
|
|
|
79
80
|
// TODO(telackey): Does it make any sense to load other parties if we don't have an HALO?
|
|
80
|
-
if (identity
|
|
81
|
+
if (identity) {
|
|
81
82
|
partyKeys = partyKeys.filter(partyKey => !partyKey.equals(identity.identityKey!.publicKey));
|
|
82
83
|
}
|
|
83
84
|
|
|
@@ -19,17 +19,17 @@ export class CredentialsSigner {
|
|
|
19
19
|
|
|
20
20
|
return new CredentialsSigner(
|
|
21
21
|
keyring,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
identityKey,
|
|
23
|
+
deviceKey,
|
|
24
|
+
deviceKey
|
|
25
25
|
);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
constructor (
|
|
29
29
|
private readonly _signer: Signer,
|
|
30
|
-
private readonly
|
|
31
|
-
private readonly
|
|
32
|
-
private readonly
|
|
30
|
+
private readonly _identityKey: KeyRecord,
|
|
31
|
+
private readonly _deviceKey: KeyRecord,
|
|
32
|
+
private readonly _signingKeys: KeyRecord | KeyChain
|
|
33
33
|
) {}
|
|
34
34
|
|
|
35
35
|
get signer (): Signer {
|
|
@@ -37,11 +37,11 @@ export class CredentialsSigner {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
getIdentityKey (): KeyRecord {
|
|
40
|
-
return this.
|
|
40
|
+
return this._identityKey;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
getDeviceKey (): KeyRecord {
|
|
44
|
-
return this.
|
|
44
|
+
return this._deviceKey;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/**
|
|
@@ -55,6 +55,6 @@ export class CredentialsSigner {
|
|
|
55
55
|
* Devices need to sign with their keyChain including the device key admission credential in the signature.
|
|
56
56
|
*/
|
|
57
57
|
getDeviceSigningKeys (): KeyRecord | KeyChain {
|
|
58
|
-
return this.
|
|
58
|
+
return this._signingKeys;
|
|
59
59
|
}
|
|
60
60
|
}
|