@dxos/client-services 0.1.56-main.e47dfd1 → 0.1.56-main.e79d64a

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.
Files changed (95) hide show
  1. package/dist/lib/browser/{chunk-CSJSC47N.mjs → chunk-T32PP5QD.mjs} +1284 -625
  2. package/dist/lib/browser/chunk-T32PP5QD.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +70 -54
  4. package/dist/lib/browser/index.mjs.map +3 -3
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/packlets/testing/index.mjs +42 -48
  7. package/dist/lib/browser/packlets/testing/index.mjs.map +3 -3
  8. package/dist/lib/node/index.cjs +1439 -767
  9. package/dist/lib/node/index.cjs.map +4 -4
  10. package/dist/lib/node/meta.json +1 -1
  11. package/dist/lib/node/packlets/testing/index.cjs +1590 -936
  12. package/dist/lib/node/packlets/testing/index.cjs.map +4 -4
  13. package/dist/types/src/packlets/identity/identity-manager.d.ts +7 -1
  14. package/dist/types/src/packlets/identity/identity-manager.d.ts.map +1 -1
  15. package/dist/types/src/packlets/identity/identity-service.d.ts +7 -3
  16. package/dist/types/src/packlets/identity/identity-service.d.ts.map +1 -1
  17. package/dist/types/src/packlets/identity/identity.d.ts +3 -2
  18. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  19. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -1
  20. package/dist/types/src/packlets/invitations/invitation-extension.d.ts.map +1 -1
  21. package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -1
  22. package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -1
  23. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -1
  24. package/dist/types/src/packlets/logging/logging-service.d.ts +6 -2
  25. package/dist/types/src/packlets/logging/logging-service.d.ts.map +1 -1
  26. package/dist/types/src/packlets/services/client-rpc-server.d.ts.map +1 -1
  27. package/dist/types/src/packlets/services/diagnostics.d.ts +46 -0
  28. package/dist/types/src/packlets/services/diagnostics.d.ts.map +1 -0
  29. package/dist/types/src/packlets/services/index.d.ts +1 -0
  30. package/dist/types/src/packlets/services/index.d.ts.map +1 -1
  31. package/dist/types/src/packlets/services/platform.d.ts +16 -0
  32. package/dist/types/src/packlets/services/platform.d.ts.map +1 -0
  33. package/dist/types/src/packlets/services/service-context.d.ts +2 -1
  34. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  35. package/dist/types/src/packlets/services/service-host.d.ts +7 -3
  36. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  37. package/dist/types/src/packlets/services/util.d.ts +6 -0
  38. package/dist/types/src/packlets/services/util.d.ts.map +1 -0
  39. package/dist/types/src/packlets/spaces/data-space-manager.d.ts.map +1 -1
  40. package/dist/types/src/packlets/spaces/data-space.d.ts.map +1 -1
  41. package/dist/types/src/packlets/spaces/notarization-plugin.d.ts.map +1 -1
  42. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  43. package/dist/types/src/packlets/system/system-service.d.ts +12 -2
  44. package/dist/types/src/packlets/system/system-service.d.ts.map +1 -1
  45. package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
  46. package/dist/types/src/packlets/vault/iframe-host-runtime.d.ts.map +1 -1
  47. package/dist/types/src/packlets/vault/shell-runtime.d.ts.map +1 -1
  48. package/dist/types/src/packlets/vault/worker-runtime.d.ts.map +1 -1
  49. package/dist/types/src/packlets/vault/worker-session.d.ts.map +1 -1
  50. package/dist/types/src/version.d.ts +2 -0
  51. package/dist/types/src/version.d.ts.map +1 -0
  52. package/package.json +34 -33
  53. package/src/packlets/devices/devices-service.test.ts +2 -1
  54. package/src/packlets/identity/authenticator.test.ts +2 -2
  55. package/src/packlets/identity/identity-manager.test.ts +15 -3
  56. package/src/packlets/identity/identity-manager.ts +28 -8
  57. package/src/packlets/identity/identity-service.test.ts +17 -2
  58. package/src/packlets/identity/identity-service.ts +24 -16
  59. package/src/packlets/identity/identity.test.ts +7 -6
  60. package/src/packlets/identity/identity.ts +9 -5
  61. package/src/packlets/invitations/device-invitation-protocol.test.ts +2 -1
  62. package/src/packlets/invitations/device-invitation-protocol.ts +1 -2
  63. package/src/packlets/invitations/invitation-extension.ts +1 -2
  64. package/src/packlets/invitations/invitations-handler.ts +3 -2
  65. package/src/packlets/invitations/invitations-service.ts +1 -2
  66. package/src/packlets/invitations/space-invitation-protocol.ts +1 -2
  67. package/src/packlets/locks/node.ts +1 -1
  68. package/src/packlets/logging/logging-service.ts +17 -9
  69. package/src/packlets/network/network-service.test.ts +2 -1
  70. package/src/packlets/services/client-rpc-server.ts +4 -4
  71. package/src/packlets/services/diagnostics.ts +212 -0
  72. package/src/packlets/services/index.ts +1 -0
  73. package/src/packlets/services/platform.ts +48 -0
  74. package/src/packlets/services/service-context.test.ts +59 -0
  75. package/src/packlets/services/service-context.ts +21 -15
  76. package/src/packlets/services/service-host.test.ts +12 -11
  77. package/src/packlets/services/service-host.ts +39 -20
  78. package/src/packlets/services/service-registry.test.ts +3 -1
  79. package/src/packlets/services/util.ts +33 -0
  80. package/src/packlets/spaces/data-space-manager.test.ts +80 -22
  81. package/src/packlets/spaces/data-space-manager.ts +7 -4
  82. package/src/packlets/spaces/data-space.ts +17 -5
  83. package/src/packlets/spaces/notarization-plugin.ts +1 -2
  84. package/src/packlets/spaces/spaces-service.test.ts +2 -1
  85. package/src/packlets/spaces/spaces-service.ts +19 -13
  86. package/src/packlets/system/system-service.test.ts +1 -0
  87. package/src/packlets/system/system-service.ts +34 -2
  88. package/src/packlets/testing/invitation-utils.ts +1 -2
  89. package/src/packlets/testing/test-builder.ts +1 -1
  90. package/src/packlets/vault/iframe-host-runtime.ts +2 -1
  91. package/src/packlets/vault/shell-runtime.ts +1 -2
  92. package/src/packlets/vault/worker-runtime.ts +3 -2
  93. package/src/packlets/vault/worker-session.ts +7 -3
  94. package/src/version.ts +1 -0
  95. package/dist/lib/browser/chunk-CSJSC47N.mjs.map +0 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/client-services",
3
- "version": "0.1.56-main.e47dfd1",
3
+ "version": "0.1.56-main.e79d64a",
4
4
  "description": "DXOS client services implementation",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -21,41 +21,42 @@
21
21
  "src"
22
22
  ],
23
23
  "dependencies": {
24
- "tiny-invariant": "^1.3.1",
25
- "@dxos/async": "0.1.56-main.e47dfd1",
26
- "@dxos/client-protocol": "0.1.56-main.e47dfd1",
27
- "@dxos/codec-protobuf": "0.1.56-main.e47dfd1",
28
- "@dxos/config": "0.1.56-main.e47dfd1",
29
- "@dxos/context": "0.1.56-main.e47dfd1",
30
- "@dxos/credentials": "0.1.56-main.e47dfd1",
31
- "@dxos/crypto": "0.1.56-main.e47dfd1",
32
- "@dxos/debug": "0.1.56-main.e47dfd1",
33
- "@dxos/document-model": "0.1.56-main.e47dfd1",
34
- "@dxos/echo-db": "0.1.56-main.e47dfd1",
35
- "@dxos/echo-pipeline": "0.1.56-main.e47dfd1",
36
- "@dxos/errors": "0.1.56-main.e47dfd1",
37
- "@dxos/feed-store": "0.1.56-main.e47dfd1",
38
- "@dxos/keyring": "0.1.56-main.e47dfd1",
39
- "@dxos/keys": "0.1.56-main.e47dfd1",
40
- "@dxos/lock-file": "0.1.56-main.e47dfd1",
41
- "@dxos/log": "0.1.56-main.e47dfd1",
42
- "@dxos/messaging": "0.1.56-main.e47dfd1",
43
- "@dxos/model-factory": "0.1.56-main.e47dfd1",
44
- "@dxos/network-manager": "0.1.56-main.e47dfd1",
45
- "@dxos/node-std": "0.1.56-main.e47dfd1",
46
- "@dxos/protocols": "0.1.56-main.e47dfd1",
47
- "@dxos/random-access-storage": "0.1.56-main.e47dfd1",
48
- "@dxos/rpc": "0.1.56-main.e47dfd1",
49
- "@dxos/teleport": "0.1.56-main.e47dfd1",
50
- "@dxos/teleport-extension-gossip": "0.1.56-main.e47dfd1",
51
- "@dxos/teleport-extension-object-sync": "0.1.56-main.e47dfd1",
52
- "@dxos/text-model": "0.1.56-main.e47dfd1",
53
- "@dxos/timeframe": "0.1.56-main.e47dfd1",
54
- "@dxos/util": "0.1.56-main.e47dfd1"
24
+ "@dxos/async": "0.1.56-main.e79d64a",
25
+ "@dxos/client-protocol": "0.1.56-main.e79d64a",
26
+ "@dxos/codec-protobuf": "0.1.56-main.e79d64a",
27
+ "@dxos/config": "0.1.56-main.e79d64a",
28
+ "@dxos/context": "0.1.56-main.e79d64a",
29
+ "@dxos/credentials": "0.1.56-main.e79d64a",
30
+ "@dxos/crypto": "0.1.56-main.e79d64a",
31
+ "@dxos/debug": "0.1.56-main.e79d64a",
32
+ "@dxos/document-model": "0.1.56-main.e79d64a",
33
+ "@dxos/echo-db": "0.1.56-main.e79d64a",
34
+ "@dxos/echo-pipeline": "0.1.56-main.e79d64a",
35
+ "@dxos/errors": "0.1.56-main.e79d64a",
36
+ "@dxos/feed-store": "0.1.56-main.e79d64a",
37
+ "@dxos/invariant": "0.1.56-main.e79d64a",
38
+ "@dxos/keyring": "0.1.56-main.e79d64a",
39
+ "@dxos/keys": "0.1.56-main.e79d64a",
40
+ "@dxos/lock-file": "0.1.56-main.e79d64a",
41
+ "@dxos/log": "0.1.56-main.e79d64a",
42
+ "@dxos/messaging": "0.1.56-main.e79d64a",
43
+ "@dxos/model-factory": "0.1.56-main.e79d64a",
44
+ "@dxos/network-manager": "0.1.56-main.e79d64a",
45
+ "@dxos/node-std": "0.1.56-main.e79d64a",
46
+ "@dxos/protocols": "0.1.56-main.e79d64a",
47
+ "@dxos/random-access-storage": "0.1.56-main.e79d64a",
48
+ "@dxos/rpc": "0.1.56-main.e79d64a",
49
+ "@dxos/teleport": "0.1.56-main.e79d64a",
50
+ "@dxos/teleport-extension-gossip": "0.1.56-main.e79d64a",
51
+ "@dxos/teleport-extension-object-sync": "0.1.56-main.e79d64a",
52
+ "@dxos/text-model": "0.1.56-main.e79d64a",
53
+ "@dxos/timeframe": "0.1.56-main.e79d64a",
54
+ "@dxos/tracing": "0.1.56-main.e79d64a",
55
+ "@dxos/util": "0.1.56-main.e79d64a"
55
56
  },
56
57
  "devDependencies": {
57
58
  "@types/readable-stream": "^2.3.9",
58
- "@dxos/signal": "0.1.56-main.e47dfd1"
59
+ "@dxos/signal": "0.1.56-main.e79d64a"
59
60
  },
60
61
  "publishConfig": {
61
62
  "access": "public"
@@ -5,6 +5,7 @@
5
5
  import { expect } from 'chai';
6
6
 
7
7
  import { Trigger } from '@dxos/async';
8
+ import { Context } from '@dxos/context';
8
9
  import { DevicesService, Device } from '@dxos/protocols/proto/dxos/client/services';
9
10
  import { afterEach, afterTest, beforeEach, describe, test } from '@dxos/test';
10
11
 
@@ -18,7 +19,7 @@ describe('DevicesService', () => {
18
19
 
19
20
  beforeEach(async () => {
20
21
  serviceContext = createServiceContext();
21
- await serviceContext.open();
22
+ await serviceContext.open(new Context());
22
23
  devicesService = new DevicesServiceImpl(serviceContext.identityManager);
23
24
  });
24
25
 
@@ -3,10 +3,10 @@
3
3
  //
4
4
 
5
5
  import expect from 'expect';
6
- import assert from 'node:assert';
7
6
 
8
7
  import { Event } from '@dxos/async';
9
8
  import { createCredentialSignerWithKey } from '@dxos/credentials';
9
+ import { invariant } from '@dxos/invariant';
10
10
  import { Keyring } from '@dxos/keyring';
11
11
  import { PublicKey } from '@dxos/keys';
12
12
  import { describe, test } from '@dxos/test';
@@ -28,7 +28,7 @@ describe('identity/authenticator', () => {
28
28
 
29
29
  const nonce = new Uint8Array([2, 1, 3, 7]);
30
30
  const credential = await authProvider(nonce);
31
- assert(credential);
31
+ invariant(credential);
32
32
  expect(await authVerifier.verifier(nonce, credential)).toBeTruthy();
33
33
  }).onlyEnvironments('nodejs');
34
34
  });
@@ -4,6 +4,7 @@
4
4
 
5
5
  import { expect } from 'chai';
6
6
 
7
+ import { Context } from '@dxos/context';
7
8
  import { valueEncoding, MetadataStore, SpaceManager, AuthStatus, SnapshotStore } from '@dxos/echo-pipeline';
8
9
  import { FeedFactory, FeedStore } from '@dxos/feed-store';
9
10
  import { Keyring } from '@dxos/keyring';
@@ -64,7 +65,7 @@ describe('identity/identity-manager', () => {
64
65
 
65
66
  test('creates identity', async () => {
66
67
  const { identityManager } = await setupPeer();
67
- await identityManager.open();
68
+ await identityManager.open(new Context());
68
69
  afterTest(() => identityManager.close());
69
70
 
70
71
  const identity = await identityManager.createIdentity();
@@ -75,13 +76,13 @@ describe('identity/identity-manager', () => {
75
76
  const storage = createStorage({ type: StorageType.RAM });
76
77
 
77
78
  const peer1 = await setupPeer({ storage });
78
- await peer1.identityManager.open();
79
+ await peer1.identityManager.open(new Context());
79
80
  const identity1 = await peer1.identityManager.createIdentity();
80
81
  await peer1.identityManager.close();
81
82
  await peer1.feedStore.close();
82
83
 
83
84
  const peer2 = await setupPeer({ storage });
84
- await peer2.identityManager.open();
85
+ await peer2.identityManager.open(new Context());
85
86
 
86
87
  expect(peer2.identityManager.identity).to.exist;
87
88
  expect(peer2.identityManager.identity!.identityKey).to.deep.eq(identity1.identityKey);
@@ -90,6 +91,17 @@ describe('identity/identity-manager', () => {
90
91
  // TODO(dmaretskyi): Check that identity is "alive" (space is working and can write mutations).
91
92
  });
92
93
 
94
+ test('update profile', async () => {
95
+ const { identityManager } = await setupPeer();
96
+ await identityManager.open(new Context());
97
+ afterTest(() => identityManager.close());
98
+
99
+ const identity = await identityManager.createIdentity();
100
+ expect(identity.profileDocument?.displayName).to.be.undefined;
101
+ await identityManager.updateProfile({ displayName: 'Example' });
102
+ expect(identity.profileDocument?.displayName).to.equal('Example');
103
+ });
104
+
93
105
  test('admit another device', async () => {
94
106
  const signalContext = new MemorySignalManagerContext();
95
107
 
@@ -2,20 +2,21 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import invariant from 'tiny-invariant';
6
-
7
5
  import { Event } from '@dxos/async';
6
+ import { Context } from '@dxos/context';
8
7
  import { createCredentialSignerWithKey, CredentialGenerator } from '@dxos/credentials';
9
8
  import { MetadataStore, SpaceManager, SwarmIdentity } from '@dxos/echo-pipeline';
10
9
  import { FeedStore } from '@dxos/feed-store';
10
+ import { invariant } from '@dxos/invariant';
11
11
  import { Keyring } from '@dxos/keyring';
12
12
  import { PublicKey } from '@dxos/keys';
13
13
  import { log } from '@dxos/log';
14
14
  import { trace } from '@dxos/protocols';
15
15
  import { FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
16
16
  import { IdentityRecord, SpaceMetadata } from '@dxos/protocols/proto/dxos/echo/metadata';
17
- import { AdmittedFeed } from '@dxos/protocols/proto/dxos/halo/credentials';
17
+ import { AdmittedFeed, ProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
18
18
  import { Timeframe } from '@dxos/timeframe';
19
+ import { trace as Trace } from '@dxos/tracing';
19
20
  import { deferFunction } from '@dxos/util';
20
21
 
21
22
  import { createAuthProvider } from './authenticator';
@@ -47,6 +48,7 @@ export type CreateIdentityOptions = {
47
48
  };
48
49
 
49
50
  // TODO(dmaretskyi): Rename: represents the peer's state machine.
51
+ @Trace.resource()
50
52
  export class IdentityManager {
51
53
  readonly stateUpdate = new Event();
52
54
 
@@ -65,7 +67,8 @@ export class IdentityManager {
65
67
  return this._identity;
66
68
  }
67
69
 
68
- async open() {
70
+ @Trace.span()
71
+ async open(ctx: Context) {
69
72
  const traceId = PublicKey.random().toHex();
70
73
  log.trace('dxos.halo.identity-manager.open', trace.begin({ id: traceId }));
71
74
  await this._metadataStore.load();
@@ -74,7 +77,7 @@ export class IdentityManager {
74
77
  log('identity record', { identityRecord });
75
78
  if (identityRecord) {
76
79
  this._identity = await this._constructIdentity(identityRecord);
77
- await this._identity.open();
80
+ await this._identity.open(ctx);
78
81
  await this._identity.ready();
79
82
  log.trace('dxos.halo.identity', {
80
83
  identityKey: identityRecord.identityKey,
@@ -86,7 +89,7 @@ export class IdentityManager {
86
89
  }
87
90
 
88
91
  async close() {
89
- await this._identity?.close();
92
+ await this._identity?.close(new Context());
90
93
  }
91
94
 
92
95
  async createIdentity({ displayName }: CreateIdentityOptions = {}) {
@@ -106,7 +109,7 @@ export class IdentityManager {
106
109
  };
107
110
 
108
111
  const identity = await this._constructIdentity(identityRecord);
109
- await identity.open();
112
+ await identity.open(new Context());
110
113
 
111
114
  {
112
115
  const generator = new CredentialGenerator(this._keyring, identityRecord.identityKey, identityRecord.deviceKey);
@@ -176,7 +179,7 @@ export class IdentityManager {
176
179
  };
177
180
  const identity = await this._constructIdentity(identityRecord);
178
181
 
179
- await identity.open();
182
+ await identity.open(new Context());
180
183
  this._identity = identity;
181
184
  await this._metadataStore.setIdentityRecord(identityRecord);
182
185
  await this._identity.ready();
@@ -190,6 +193,23 @@ export class IdentityManager {
190
193
  return identity;
191
194
  }
192
195
 
196
+ /**
197
+ * Update the profile document of an existing identity.
198
+ */
199
+ async updateProfile(profile: ProfileDocument) {
200
+ invariant(this._identity, 'Identity not initialized.');
201
+ // TODO(wittjosiah): Use CredentialGenerator.
202
+ const credential = await this._identity.getIdentityCredentialSigner().createCredential({
203
+ subject: this._identity.identityKey,
204
+ assertion: {
205
+ '@type': 'dxos.halo.credentials.IdentityProfile',
206
+ profile,
207
+ },
208
+ });
209
+ const receipt = await this._identity.controlPipeline.writer.write({ credential: { credential } });
210
+ await this._identity.controlPipeline.state.waitUntilTimeframe(new Timeframe([[receipt.feedKey, receipt.seq]]));
211
+ }
212
+
193
213
  private async _constructIdentity(identityRecord: IdentityRecord) {
194
214
  invariant(!this._identity);
195
215
  log('constructing identity', { identityRecord });
@@ -6,6 +6,7 @@ import chai, { expect } from 'chai';
6
6
  import chaiAsPromised from 'chai-as-promised';
7
7
 
8
8
  import { Trigger } from '@dxos/async';
9
+ import { Context } from '@dxos/context';
9
10
  import { PublicKey } from '@dxos/keys';
10
11
  import { Identity, IdentityService } from '@dxos/protocols/proto/dxos/client/services';
11
12
  import { afterEach, afterTest, beforeEach, describe, test } from '@dxos/test';
@@ -22,8 +23,12 @@ describe('IdentityService', () => {
22
23
 
23
24
  beforeEach(async () => {
24
25
  serviceContext = createServiceContext();
25
- await serviceContext.open();
26
- identityService = new IdentityServiceImpl(serviceContext);
26
+ await serviceContext.open(new Context());
27
+ identityService = new IdentityServiceImpl(
28
+ (options) => serviceContext.createIdentity(options),
29
+ serviceContext.identityManager,
30
+ serviceContext.keyring,
31
+ );
27
32
  });
28
33
 
29
34
  afterEach(async () => {
@@ -54,6 +59,16 @@ describe('IdentityService', () => {
54
59
 
55
60
  describe.skip('recoverIdentity', () => {});
56
61
 
62
+ describe('updateProfile', () => {
63
+ test('updates profile', async () => {
64
+ const identity = await identityService.createIdentity({});
65
+ expect(identity.profile?.displayName).to.be.undefined;
66
+
67
+ const updatedIdentity = await identityService.updateProfile({ displayName: 'Example' });
68
+ expect(updatedIdentity.profile?.displayName).to.equal('Example');
69
+ });
70
+ });
71
+
57
72
  describe('queryIdentity', () => {
58
73
  test('returns undefined if no identity is available', async () => {
59
74
  const query = identityService.queryIdentity();
@@ -2,11 +2,11 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import invariant from 'tiny-invariant';
6
-
7
5
  import { Stream } from '@dxos/codec-protobuf';
8
6
  import { signPresentation } from '@dxos/credentials';
9
7
  import { todo } from '@dxos/debug';
8
+ import { invariant } from '@dxos/invariant';
9
+ import { Keyring } from '@dxos/keyring';
10
10
  import {
11
11
  Identity,
12
12
  IdentityService,
@@ -16,15 +16,17 @@ import {
16
16
  } from '@dxos/protocols/proto/dxos/client/services';
17
17
  import { Presentation, ProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
18
18
 
19
- import { ServiceContext } from '../services';
19
+ import { CreateIdentityOptions, IdentityManager } from './identity-manager';
20
20
 
21
21
  export class IdentityServiceImpl implements IdentityService {
22
- // TODO(wittjosiah): Remove dependency on service context.
23
- constructor(private readonly _serviceContext: ServiceContext) {}
22
+ constructor(
23
+ private readonly _createIdentity: (params?: CreateIdentityOptions) => Promise<Identity>,
24
+ private readonly _identityManager: IdentityManager,
25
+ private readonly _keyring: Keyring,
26
+ ) {}
24
27
 
25
28
  async createIdentity(request: ProfileDocument): Promise<Identity> {
26
- await this._serviceContext.createIdentity(request);
27
-
29
+ await this._createIdentity(request);
28
30
  return this._getIdentity()!;
29
31
  }
30
32
 
@@ -37,30 +39,36 @@ export class IdentityServiceImpl implements IdentityService {
37
39
  const emitNext = () => next({ identity: this._getIdentity() });
38
40
 
39
41
  emitNext();
40
- return this._serviceContext.identityManager.stateUpdate.on(emitNext);
42
+ return this._identityManager.stateUpdate.on(emitNext);
41
43
  });
42
44
  }
43
45
 
44
46
  private _getIdentity(): Identity | undefined {
45
- if (!this._serviceContext.identityManager.identity) {
47
+ if (!this._identityManager.identity) {
46
48
  return undefined;
47
49
  }
48
50
 
49
51
  return {
50
- identityKey: this._serviceContext.identityManager.identity.identityKey,
51
- spaceKey: this._serviceContext.identityManager.identity.space.key,
52
- profile: this._serviceContext.identityManager.identity.profileDocument,
52
+ identityKey: this._identityManager.identity.identityKey,
53
+ spaceKey: this._identityManager.identity.space.key,
54
+ profile: this._identityManager.identity.profileDocument,
53
55
  };
54
56
  }
55
57
 
58
+ async updateProfile(profile: ProfileDocument): Promise<Identity> {
59
+ invariant(this._identityManager.identity, 'Identity not initialized.');
60
+ await this._identityManager.updateProfile(profile);
61
+ return this._getIdentity()!;
62
+ }
63
+
56
64
  async signPresentation({ presentation, nonce }: SignPresentationRequest): Promise<Presentation> {
57
- invariant(this._serviceContext.identityManager.identity, 'Identity not initialized.');
65
+ invariant(this._identityManager.identity, 'Identity not initialized.');
58
66
 
59
67
  return await signPresentation({
60
68
  presentation,
61
- signer: this._serviceContext.keyring,
62
- signerKey: this._serviceContext.identityManager.identity.deviceKey,
63
- chain: this._serviceContext.identityManager.identity.deviceCredentialChain,
69
+ signer: this._keyring,
70
+ signerKey: this._identityManager.identity.deviceKey,
71
+ chain: this._identityManager.identity.deviceCredentialChain,
64
72
  nonce,
65
73
  });
66
74
  }
@@ -4,6 +4,7 @@
4
4
 
5
5
  import expect from 'expect';
6
6
 
7
+ import { Context } from '@dxos/context';
7
8
  import { CredentialGenerator, verifyCredential } from '@dxos/credentials';
8
9
  import {
9
10
  MetadataStore,
@@ -106,8 +107,8 @@ describe('identity/identity', () => {
106
107
  space,
107
108
  });
108
109
 
109
- await identity.open();
110
- afterTest(() => identity.close());
110
+ await identity.open(new Context());
111
+ afterTest(() => identity.close(new Context()));
111
112
 
112
113
  //
113
114
  // Identity genesis
@@ -219,8 +220,8 @@ describe('identity/identity', () => {
219
220
  space,
220
221
  }));
221
222
 
222
- await identity.open();
223
- afterTest(() => identity.close());
223
+ await identity.open(new Context());
224
+ afterTest(() => identity.close(new Context()));
224
225
 
225
226
  //
226
227
  // Identity genesis
@@ -310,8 +311,8 @@ describe('identity/identity', () => {
310
311
  space,
311
312
  }));
312
313
 
313
- await identity.open();
314
- afterTest(() => identity.close());
314
+ await identity.open(new Context());
315
+ afterTest(() => identity.close(new Context()));
315
316
  }
316
317
 
317
318
  //
@@ -2,10 +2,9 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import invariant from 'tiny-invariant';
6
-
7
5
  import { Event } from '@dxos/async';
8
6
  import { AUTH_TIMEOUT, LOAD_CONTROL_FEEDS_TIMEOUT } from '@dxos/client-protocol';
7
+ import { Context } from '@dxos/context';
9
8
  import {
10
9
  DeviceStateMachine,
11
10
  CredentialSigner,
@@ -17,11 +16,13 @@ import { Signer } from '@dxos/crypto';
17
16
  import { failUndefined } from '@dxos/debug';
18
17
  import { Space } from '@dxos/echo-pipeline';
19
18
  import { writeMessages } from '@dxos/feed-store';
19
+ import { invariant } from '@dxos/invariant';
20
20
  import { PublicKey } from '@dxos/keys';
21
21
  import { log } from '@dxos/log';
22
22
  import { FeedMessage } from '@dxos/protocols/proto/dxos/echo/feed';
23
23
  import { AdmittedFeed, ProfileDocument } from '@dxos/protocols/proto/dxos/halo/credentials';
24
24
  import { DeviceAdmissionRequest } from '@dxos/protocols/proto/dxos/halo/invitations';
25
+ import { trace } from '@dxos/tracing';
25
26
  import { ComplexSet } from '@dxos/util';
26
27
 
27
28
  import { TrustedKeySetAuthVerifier } from './authenticator';
@@ -36,6 +37,7 @@ export type IdentityParams = {
36
37
  /**
37
38
  * Agent identity manager, which includes the agent's Halo space.
38
39
  */
40
+ @trace.resource()
39
41
  export class Identity {
40
42
  public readonly space: Space;
41
43
  private readonly _signer: Signer;
@@ -77,13 +79,15 @@ export class Identity {
77
79
  return this._deviceStateMachine.authorizedDeviceKeys;
78
80
  }
79
81
 
80
- async open() {
82
+ @trace.span()
83
+ async open(ctx: Context) {
81
84
  await this.space.spaceState.addCredentialProcessor(this._deviceStateMachine);
82
85
  await this.space.spaceState.addCredentialProcessor(this._profileStateMachine);
83
- await this.space.open();
86
+ await this.space.open(ctx);
84
87
  }
85
88
 
86
- async close() {
89
+ @trace.span()
90
+ async close(ctx: Context) {
87
91
  await this.authVerifier.close();
88
92
  await this.space.spaceState.removeCredentialProcessor(this._profileStateMachine);
89
93
  await this.space.spaceState.removeCredentialProcessor(this._deviceStateMachine);
@@ -5,6 +5,7 @@
5
5
  import { expect } from 'chai';
6
6
 
7
7
  import { asyncChain } from '@dxos/async';
8
+ import { Context } from '@dxos/context';
8
9
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
9
10
  import { describe, test, afterTest } from '@dxos/test';
10
11
 
@@ -19,7 +20,7 @@ const closeAfterTest = async (peer: ServiceContext) => {
19
20
  describe('services/device', () => {
20
21
  test('creates identity', async () => {
21
22
  const peer = createServiceContext();
22
- await peer.open();
23
+ await peer.open(new Context());
23
24
  afterTest(() => peer.close());
24
25
 
25
26
  const identity = await peer.createIdentity();
@@ -2,8 +2,7 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import invariant from 'tiny-invariant';
6
-
5
+ import { invariant } from '@dxos/invariant';
7
6
  import { Keyring } from '@dxos/keyring';
8
7
  import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
9
8
  import { AdmissionRequest, AdmissionResponse, IntroductionRequest } from '@dxos/protocols/proto/dxos/halo/invitations';
@@ -2,11 +2,10 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import invariant from 'tiny-invariant';
6
-
7
5
  import { Trigger } from '@dxos/async';
8
6
  import { cancelWithContext, Context } from '@dxos/context';
9
7
  import { InvalidInvitationExtensionRoleError } from '@dxos/errors';
8
+ import { invariant } from '@dxos/invariant';
10
9
  import { PublicKey } from '@dxos/keys';
11
10
  import { log } from '@dxos/log';
12
11
  import { schema, trace } from '@dxos/protocols';
@@ -2,8 +2,6 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import invariant from 'tiny-invariant';
6
-
7
5
  import { PushStream, scheduleTask, TimeoutError, Trigger } from '@dxos/async';
8
6
  import {
9
7
  AuthenticatingInvitationObservable,
@@ -14,6 +12,7 @@ import {
14
12
  import { Context } from '@dxos/context';
15
13
  import { generatePasscode } from '@dxos/credentials';
16
14
  import { InvalidInvitationExtensionRoleError } from '@dxos/errors';
15
+ import { invariant } from '@dxos/invariant';
17
16
  import { PublicKey } from '@dxos/keys';
18
17
  import { log } from '@dxos/log';
19
18
  import { createTeleportProtocolFactory, NetworkManager, StarTopology, SwarmConnection } from '@dxos/network-manager';
@@ -187,6 +186,7 @@ export class InvitationsHandler {
187
186
  teleport.addExtension('dxos.halo.invitations', createExtension());
188
187
  }),
189
188
  topology: new StarTopology(topic),
189
+ label: 'invitation host',
190
190
  });
191
191
  ctx.onDispose(() => swarmConnection.close());
192
192
 
@@ -363,6 +363,7 @@ export class InvitationsHandler {
363
363
  teleport.addExtension('dxos.halo.invitations', createExtension());
364
364
  }),
365
365
  topology: new StarTopology(topic),
366
+ label: 'invitation guest',
366
367
  });
367
368
  ctx.onDispose(() => swarmConnection.close());
368
369
 
@@ -2,11 +2,10 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import invariant from 'tiny-invariant';
6
-
7
5
  import { Event } from '@dxos/async';
8
6
  import { AuthenticatingInvitationObservable, CancellableInvitationObservable } from '@dxos/client-protocol';
9
7
  import { Stream } from '@dxos/codec-protobuf';
8
+ import { invariant } from '@dxos/invariant';
10
9
  import { log } from '@dxos/log';
11
10
  import {
12
11
  AuthenticationRequest,
@@ -2,10 +2,9 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import invariant from 'tiny-invariant';
6
-
7
5
  import { createAdmissionCredentials, getCredentialAssertion } from '@dxos/credentials';
8
6
  import { writeMessages } from '@dxos/feed-store';
7
+ import { invariant } from '@dxos/invariant';
9
8
  import { Keyring } from '@dxos/keyring';
10
9
  import { PublicKey } from '@dxos/keys';
11
10
  import { log } from '@dxos/log';
@@ -3,8 +3,8 @@
3
3
  //
4
4
 
5
5
  import { FileHandle } from 'node:fs/promises';
6
- import invariant from 'tiny-invariant';
7
6
 
7
+ import { invariant } from '@dxos/invariant';
8
8
  import { LockFile } from '@dxos/lock-file';
9
9
  import { log, logInfo } from '@dxos/log';
10
10
 
@@ -13,6 +13,7 @@ import {
13
13
  ControlMetricsRequest,
14
14
  ControlMetricsResponse,
15
15
  QueryMetricsRequest,
16
+ QueryMetricsResponse,
16
17
  } from '@dxos/protocols/proto/dxos/client/services';
17
18
  import { jsonify, numericalValues, tracer } from '@dxos/util';
18
19
 
@@ -21,6 +22,7 @@ import { jsonify, numericalValues, tracer } from '@dxos/util';
21
22
  */
22
23
  export class LoggingServiceImpl implements LoggingService {
23
24
  private readonly _logs = new Event<NaturalLogEntry>();
25
+ private readonly _started = new Date();
24
26
 
25
27
  async open() {
26
28
  log.runtimeConfig.processors.push(this._logProcessor);
@@ -45,11 +47,14 @@ export class LoggingServiceImpl implements LoggingService {
45
47
  return { recording: tracer.recording };
46
48
  }
47
49
 
48
- queryMetrics({ interval }: QueryMetricsRequest): Stream<Metrics> {
50
+ /**
51
+ * @deprecated (Move to diagnostics).
52
+ */
53
+ queryMetrics({ interval = 5_000 }: QueryMetricsRequest): Stream<QueryMetricsResponse> {
49
54
  // TODO(burdon): Map all traces; how to bind to reducer/metrics shape (e.g., numericalValues)?
50
- const createNumericalValues = (key: string) => {
51
- const consume = tracer.get(key) ?? [];
52
- return { key, stats: numericalValues(consume, 'duration') };
55
+ const getNumericalValues = (key: string) => {
56
+ const events = tracer.get(key) ?? [];
57
+ return { key, stats: numericalValues(events, 'duration') };
53
58
  };
54
59
 
55
60
  return new Stream(({ next }) => {
@@ -57,16 +62,19 @@ export class LoggingServiceImpl implements LoggingService {
57
62
  const metrics: Metrics = {
58
63
  timestamp: new Date(),
59
64
  values: [
60
- createNumericalValues('dxos.echo.pipeline.control'),
61
- createNumericalValues('dxos.echo.pipeline.data'),
62
- ],
65
+ getNumericalValues('dxos.echo.pipeline.control'),
66
+ getNumericalValues('dxos.echo.pipeline.data'),
67
+ ].filter(Boolean) as Metrics.KeyPair[],
63
68
  };
64
69
 
65
- next(metrics);
70
+ next({
71
+ timestamp: new Date(),
72
+ metrics,
73
+ });
66
74
  };
67
75
 
68
76
  update();
69
- const i = setInterval(update, interval);
77
+ const i = setInterval(update, Math.max(interval, 1_000));
70
78
  return () => {
71
79
  clearInterval(i);
72
80
  };