@dxos/client-services 0.1.5 → 0.1.7

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 (164) hide show
  1. package/LICENSE +5 -18
  2. package/README.md +14 -10
  3. package/README.yml +5 -0
  4. package/dist/src/packlets/deprecated/profile.d.ts +2 -5
  5. package/dist/src/packlets/deprecated/profile.d.ts.map +1 -1
  6. package/dist/src/packlets/deprecated/profile.js +1 -73
  7. package/dist/src/packlets/deprecated/profile.js.map +1 -1
  8. package/dist/src/packlets/deprecated/system.d.ts +4 -0
  9. package/dist/src/packlets/deprecated/system.d.ts.map +1 -1
  10. package/dist/src/packlets/deprecated/system.js +6 -0
  11. package/dist/src/packlets/deprecated/system.js.map +1 -1
  12. package/dist/src/packlets/deprecated/tracing.d.ts +1 -1
  13. package/dist/src/packlets/deprecated/tracing.js +1 -1
  14. package/dist/src/packlets/devtools/devtools.d.ts +3 -0
  15. package/dist/src/packlets/devtools/devtools.d.ts.map +1 -1
  16. package/dist/src/packlets/devtools/devtools.js +3 -1
  17. package/dist/src/packlets/devtools/devtools.js.map +1 -1
  18. package/dist/src/packlets/devtools/feeds.d.ts.map +1 -1
  19. package/dist/src/packlets/devtools/feeds.js +5 -3
  20. package/dist/src/packlets/devtools/feeds.js.map +1 -1
  21. package/dist/src/packlets/identity/devices-service-impl.d.ts.map +1 -1
  22. package/dist/src/packlets/identity/devices-service-impl.js.map +1 -1
  23. package/dist/src/packlets/identity/identity-manager.d.ts +2 -2
  24. package/dist/src/packlets/identity/identity-manager.d.ts.map +1 -1
  25. package/dist/src/packlets/identity/identity-manager.js +44 -43
  26. package/dist/src/packlets/identity/identity-manager.js.map +1 -1
  27. package/dist/src/packlets/identity/identity.d.ts +3 -0
  28. package/dist/src/packlets/identity/identity.d.ts.map +1 -1
  29. package/dist/src/packlets/identity/identity.js +51 -1
  30. package/dist/src/packlets/identity/identity.js.map +1 -1
  31. package/dist/src/packlets/invitations/halo-invitations-handler.d.ts +23 -0
  32. package/dist/src/packlets/invitations/halo-invitations-handler.d.ts.map +1 -0
  33. package/dist/src/packlets/invitations/halo-invitations-handler.js +231 -0
  34. package/dist/src/packlets/invitations/halo-invitations-handler.js.map +1 -0
  35. package/dist/src/packlets/invitations/halo-invitations-handler.test.d.ts +2 -0
  36. package/dist/src/packlets/invitations/halo-invitations-handler.test.d.ts.map +1 -0
  37. package/dist/src/packlets/invitations/halo-invitations-handler.test.js +69 -0
  38. package/dist/src/packlets/invitations/halo-invitations-handler.test.js.map +1 -0
  39. package/dist/src/packlets/invitations/halo-invitations-proxy.d.ts +8 -0
  40. package/dist/src/packlets/invitations/halo-invitations-proxy.d.ts.map +1 -0
  41. package/dist/src/packlets/invitations/halo-invitations-proxy.js +17 -0
  42. package/dist/src/packlets/invitations/halo-invitations-proxy.js.map +1 -0
  43. package/dist/src/packlets/invitations/halo-invitations-service.d.ts +13 -0
  44. package/dist/src/packlets/invitations/halo-invitations-service.d.ts.map +1 -0
  45. package/dist/src/packlets/invitations/halo-invitations-service.js +20 -0
  46. package/dist/src/packlets/invitations/halo-invitations-service.js.map +1 -0
  47. package/dist/src/packlets/invitations/halo-invitations-service.test.d.ts +2 -0
  48. package/dist/src/packlets/invitations/halo-invitations-service.test.d.ts.map +1 -0
  49. package/dist/src/packlets/invitations/halo-invitations-service.test.js +83 -0
  50. package/dist/src/packlets/invitations/halo-invitations-service.test.js.map +1 -0
  51. package/dist/src/packlets/invitations/index.d.ts +5 -1
  52. package/dist/src/packlets/invitations/index.d.ts.map +1 -1
  53. package/dist/src/packlets/invitations/index.js +5 -1
  54. package/dist/src/packlets/invitations/index.js.map +1 -1
  55. package/dist/src/packlets/invitations/invitations-handler.d.ts +48 -0
  56. package/dist/src/packlets/invitations/invitations-handler.d.ts.map +1 -0
  57. package/dist/src/packlets/invitations/invitations-handler.js +18 -0
  58. package/dist/src/packlets/invitations/invitations-handler.js.map +1 -0
  59. package/dist/src/packlets/invitations/invitations-proxy.d.ts +11 -7
  60. package/dist/src/packlets/invitations/invitations-proxy.d.ts.map +1 -1
  61. package/dist/src/packlets/invitations/invitations-proxy.js +5 -10
  62. package/dist/src/packlets/invitations/invitations-proxy.js.map +1 -1
  63. package/dist/src/packlets/invitations/invitations-service.d.ts +25 -0
  64. package/dist/src/packlets/invitations/invitations-service.d.ts.map +1 -0
  65. package/dist/src/packlets/invitations/invitations-service.js +174 -0
  66. package/dist/src/packlets/invitations/invitations-service.js.map +1 -0
  67. package/dist/src/packlets/invitations/invitations.d.ts +10 -42
  68. package/dist/src/packlets/invitations/invitations.d.ts.map +1 -1
  69. package/dist/src/packlets/invitations/invitations.js +5 -2
  70. package/dist/src/packlets/invitations/invitations.js.map +1 -1
  71. package/dist/src/packlets/invitations/space-invitations-handler.d.ts +6 -6
  72. package/dist/src/packlets/invitations/space-invitations-handler.d.ts.map +1 -1
  73. package/dist/src/packlets/invitations/space-invitations-handler.js +18 -19
  74. package/dist/src/packlets/invitations/space-invitations-handler.js.map +1 -1
  75. package/dist/src/packlets/invitations/space-invitations-handler.test.js +5 -5
  76. package/dist/src/packlets/invitations/space-invitations-handler.test.js.map +1 -1
  77. package/dist/src/packlets/invitations/space-invitations-proxy.d.ts +1 -1
  78. package/dist/src/packlets/invitations/space-invitations-proxy.d.ts.map +1 -1
  79. package/dist/src/packlets/invitations/space-invitations-proxy.js +2 -2
  80. package/dist/src/packlets/invitations/space-invitations-proxy.js.map +1 -1
  81. package/dist/src/packlets/invitations/space-invitations-service.d.ts +8 -14
  82. package/dist/src/packlets/invitations/space-invitations-service.d.ts.map +1 -1
  83. package/dist/src/packlets/invitations/space-invitations-service.js +11 -169
  84. package/dist/src/packlets/invitations/space-invitations-service.js.map +1 -1
  85. package/dist/src/packlets/invitations/space-invitations-service.test.js +4 -4
  86. package/dist/src/packlets/invitations/space-invitations-service.test.js.map +1 -1
  87. package/dist/src/packlets/services/service-context.d.ts +2 -2
  88. package/dist/src/packlets/services/service-context.d.ts.map +1 -1
  89. package/dist/src/packlets/services/service-context.js +8 -8
  90. package/dist/src/packlets/services/service-context.js.map +1 -1
  91. package/dist/src/packlets/services/service-definitions.d.ts +5 -4
  92. package/dist/src/packlets/services/service-definitions.d.ts.map +1 -1
  93. package/dist/src/packlets/services/service-definitions.js +6 -4
  94. package/dist/src/packlets/services/service-definitions.js.map +1 -1
  95. package/dist/src/packlets/services/service-host.d.ts.map +1 -1
  96. package/dist/src/packlets/services/service-host.js +10 -8
  97. package/dist/src/packlets/services/service-host.js.map +1 -1
  98. package/dist/src/packlets/services/service-proxy.js +1 -1
  99. package/dist/src/packlets/services/service-registry.test.js +2 -2
  100. package/dist/src/packlets/services/service-registry.test.js.map +1 -1
  101. package/dist/src/packlets/vault/iframe-runtime.d.ts +5 -4
  102. package/dist/src/packlets/vault/iframe-runtime.d.ts.map +1 -1
  103. package/dist/src/packlets/vault/iframe-runtime.js +4 -12
  104. package/dist/src/packlets/vault/iframe-runtime.js.map +1 -1
  105. package/dist/src/packlets/vault/worker-runtime.d.ts +4 -3
  106. package/dist/src/packlets/vault/worker-runtime.d.ts.map +1 -1
  107. package/dist/src/packlets/vault/worker-runtime.js +29 -24
  108. package/dist/src/packlets/vault/worker-runtime.js.map +1 -1
  109. package/dist/src/packlets/vault/worker-session.d.ts +5 -2
  110. package/dist/src/packlets/vault/worker-session.d.ts.map +1 -1
  111. package/dist/src/packlets/vault/worker-session.js +23 -10
  112. package/dist/src/packlets/vault/worker-session.js.map +1 -1
  113. package/package.json +26 -26
  114. package/src/packlets/deprecated/profile.ts +2 -84
  115. package/src/packlets/deprecated/system.ts +7 -0
  116. package/src/packlets/deprecated/tracing.ts +1 -1
  117. package/src/packlets/devtools/devtools.ts +3 -1
  118. package/src/packlets/devtools/feeds.ts +5 -3
  119. package/src/packlets/identity/devices-service-impl.ts +0 -1
  120. package/src/packlets/identity/identity-manager.ts +50 -49
  121. package/src/packlets/identity/identity.ts +58 -1
  122. package/src/packlets/invitations/halo-invitations-handler.test.ts +79 -0
  123. package/src/packlets/invitations/halo-invitations-handler.ts +255 -0
  124. package/src/packlets/invitations/halo-invitations-proxy.ts +14 -0
  125. package/src/packlets/invitations/halo-invitations-service.test.ts +96 -0
  126. package/src/packlets/invitations/halo-invitations-service.ts +24 -0
  127. package/src/packlets/invitations/index.ts +5 -1
  128. package/src/packlets/invitations/invitations-handler.ts +59 -0
  129. package/src/packlets/invitations/invitations-proxy.ts +15 -13
  130. package/src/packlets/invitations/invitations-service.ts +184 -0
  131. package/src/packlets/invitations/invitations.ts +14 -46
  132. package/src/packlets/invitations/space-invitations-handler.test.ts +6 -6
  133. package/src/packlets/invitations/space-invitations-handler.ts +16 -16
  134. package/src/packlets/invitations/space-invitations-proxy.ts +2 -2
  135. package/src/packlets/invitations/space-invitations-service.test.ts +13 -13
  136. package/src/packlets/invitations/space-invitations-service.ts +16 -177
  137. package/src/packlets/services/service-context.ts +6 -6
  138. package/src/packlets/services/service-definitions.ts +20 -10
  139. package/src/packlets/services/service-host.ts +15 -7
  140. package/src/packlets/services/service-proxy.ts +1 -1
  141. package/src/packlets/services/service-registry.test.ts +5 -5
  142. package/src/packlets/vault/iframe-runtime.ts +8 -15
  143. package/src/packlets/vault/worker-runtime.ts +36 -30
  144. package/src/packlets/vault/worker-session.ts +20 -6
  145. package/dist/src/packlets/invitations/halo-invitations.d.ts +0 -23
  146. package/dist/src/packlets/invitations/halo-invitations.d.ts.map +0 -1
  147. package/dist/src/packlets/invitations/halo-invitations.js +0 -154
  148. package/dist/src/packlets/invitations/halo-invitations.js.map +0 -1
  149. package/dist/src/packlets/invitations/halo-invitations.test.d.ts +0 -2
  150. package/dist/src/packlets/invitations/halo-invitations.test.d.ts.map +0 -1
  151. package/dist/src/packlets/invitations/halo-invitations.test.js +0 -34
  152. package/dist/src/packlets/invitations/halo-invitations.test.js.map +0 -1
  153. package/dist/src/packlets/services/iframe-service-proxy.d.ts +0 -23
  154. package/dist/src/packlets/services/iframe-service-proxy.d.ts.map +0 -1
  155. package/dist/src/packlets/services/iframe-service-proxy.js +0 -53
  156. package/dist/src/packlets/services/iframe-service-proxy.js.map +0 -1
  157. package/dist/src/packlets/services/service-host.test.d.ts +0 -2
  158. package/dist/src/packlets/services/service-host.test.d.ts.map +0 -1
  159. package/dist/src/packlets/services/service-host.test.js +0 -68
  160. package/dist/src/packlets/services/service-host.test.js.map +0 -1
  161. package/src/packlets/invitations/halo-invitations.test.ts +0 -40
  162. package/src/packlets/invitations/halo-invitations.ts +0 -164
  163. package/src/packlets/services/iframe-service-proxy.ts +0 -71
  164. package/src/packlets/services/service-host.test.ts +0 -76
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@dxos/client-services",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
+ "description": "DXOS client services implementation",
4
5
  "homepage": "https://dxos.org",
5
6
  "bugs": "https://github.com/dxos/dxos/issues",
6
7
  "license": "MIT",
@@ -15,29 +16,28 @@
15
16
  "src"
16
17
  ],
17
18
  "dependencies": {
18
- "@dxos/async": "0.1.5",
19
- "@dxos/codec-protobuf": "0.1.5",
20
- "@dxos/config": "0.1.5",
21
- "@dxos/credentials": "0.1.5",
22
- "@dxos/crypto": "0.1.5",
23
- "@dxos/debug": "0.1.5",
24
- "@dxos/echo-db": "0.1.5",
25
- "@dxos/feed-store": "0.1.5",
26
- "@dxos/keyring": "0.1.5",
27
- "@dxos/keys": "0.1.5",
28
- "@dxos/log": "0.1.5",
29
- "@dxos/messaging": "0.1.5",
30
- "@dxos/model-factory": "0.1.5",
31
- "@dxos/network-manager": "0.1.5",
32
- "@dxos/object-model": "0.1.5",
33
- "@dxos/protocol-plugin-rpc": "0.1.5",
34
- "@dxos/protocols": "0.1.5",
35
- "@dxos/random-access-storage": "0.1.5",
36
- "@dxos/rpc": "0.1.5",
37
- "@dxos/rpc-tunnel": "0.1.5",
38
- "@dxos/text-model": "0.1.5",
39
- "@dxos/timeframe": "0.1.5",
40
- "@dxos/util": "0.1.5",
19
+ "@dxos/async": "0.1.7",
20
+ "@dxos/codec-protobuf": "0.1.7",
21
+ "@dxos/config": "0.1.7",
22
+ "@dxos/credentials": "0.1.7",
23
+ "@dxos/crypto": "0.1.7",
24
+ "@dxos/debug": "0.1.7",
25
+ "@dxos/echo-db": "0.1.7",
26
+ "@dxos/feed-store": "0.1.7",
27
+ "@dxos/keyring": "0.1.7",
28
+ "@dxos/keys": "0.1.7",
29
+ "@dxos/log": "0.1.7",
30
+ "@dxos/messaging": "0.1.7",
31
+ "@dxos/model-factory": "0.1.7",
32
+ "@dxos/network-manager": "0.1.7",
33
+ "@dxos/object-model": "0.1.7",
34
+ "@dxos/protocol-plugin-rpc": "0.1.7",
35
+ "@dxos/protocols": "0.1.7",
36
+ "@dxos/random-access-storage": "0.1.7",
37
+ "@dxos/rpc": "0.1.7",
38
+ "@dxos/text-model": "0.1.7",
39
+ "@dxos/timeframe": "0.1.7",
40
+ "@dxos/util": "0.1.7",
41
41
  "abstract-leveldown": "~7.0.0",
42
42
  "assert": "^2.0.0",
43
43
  "base-x": "~3.0.9",
@@ -46,8 +46,8 @@
46
46
  "memdown": "^5.1.0"
47
47
  },
48
48
  "devDependencies": {
49
- "@dxos/signal": "0.1.5",
50
- "@dxos/testutils": "0.1.5",
49
+ "@dxos/signal": "0.1.7",
50
+ "@dxos/testutils": "0.1.7",
51
51
  "@types/level-js": "~4.0.1",
52
52
  "@types/memdown": "^3.0.0",
53
53
  "@types/readable-stream": "^2.3.9"
@@ -2,31 +2,22 @@
2
2
  // Copyright 2022 DXOS.org
3
3
  //
4
4
 
5
- import assert from 'node:assert';
6
- import { v4 } from 'uuid';
7
-
8
- import { latch } from '@dxos/async';
9
5
  import { Stream } from '@dxos/codec-protobuf';
10
- import { generatePasscode } from '@dxos/credentials';
11
6
  import { todo } from '@dxos/debug';
12
7
  import {
13
- AuthenticateInvitationRequest,
14
8
  CreateProfileRequest,
15
- InvitationRequest,
16
- InvitationState,
17
9
  Profile,
18
10
  ProfileService,
19
11
  RecoverProfileRequest,
20
- RedeemedInvitation,
21
12
  SubscribeProfileResponse
22
13
  } from '@dxos/protocols/proto/dxos/client';
23
- import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
24
14
 
25
15
  import { ServiceContext } from '../services';
26
- import { InviteeInvitation, InviteeInvitations } from './invitations';
16
+ import { InviteeInvitations } from './invitations';
27
17
 
28
18
  /**
29
19
  * Profile service implementation.
20
+ * @deprecated
30
21
  */
31
22
  export class ProfileServiceImpl implements ProfileService {
32
23
  private inviteeInvitations: InviteeInvitations = new Map();
@@ -65,77 +56,4 @@ export class ProfileServiceImpl implements ProfileService {
65
56
  // assert(profile, 'Recovering profile failed.');
66
57
  // return profile;
67
58
  }
68
-
69
- createInvitation(): Stream<InvitationRequest> {
70
- return new Stream(({ next, close }) => {
71
- setTimeout(async () => {
72
- const authenticationCode = generatePasscode();
73
- // TODO(burdon): Not used.
74
- // const secretProvider = async () => {
75
- // next({ descriptor: invitation.toProto(), state: InvitationState.CONNECTED });
76
- // return Buffer.from(secret);
77
- // };
78
-
79
- const invitation = await this.context.haloInvitations.createInvitation({
80
- onFinish: () => {
81
- next({ state: InvitationState.SUCCESS });
82
- close();
83
- }
84
- });
85
- invitation.authenticationCode = authenticationCode;
86
-
87
- next({
88
- state: InvitationState.WAITING_FOR_CONNECTION,
89
- descriptor: invitation
90
- });
91
- });
92
- });
93
- }
94
-
95
- acceptInvitation(invitation: Invitation): Stream<RedeemedInvitation> {
96
- return new Stream(({ next, close }) => {
97
- const id = v4();
98
- const [, secretTrigger] = latch();
99
- const inviteeInvitation: InviteeInvitation = { secretTrigger };
100
-
101
- // Secret will be provided separately (in AuthenticateInvitation).
102
- // Process will continue when `secretLatch` resolves, triggered by `secretTrigger`.
103
- // const secretProvider: SecretProvider = async () => {
104
- // await secretLatch;
105
- // const secret = inviteeInvitation.secret;
106
- // if (!secret) {
107
- // throw new Error('Secret not provided.');
108
- // }
109
- // return Buffer.from(secret);
110
- // };
111
-
112
- // Joining process is kicked off, and will await authentication with a secret.
113
- const haloSpacePromise = this.context.haloInvitations.acceptInvitation(invitation);
114
- this.inviteeInvitations.set(id, inviteeInvitation);
115
- next({ id, state: InvitationState.CONNECTED });
116
-
117
- haloSpacePromise
118
- .then((identity) => {
119
- next({
120
- id,
121
- state: InvitationState.SUCCESS,
122
- spaceKey: identity.identityKey
123
- });
124
- })
125
- .catch((err) => {
126
- next({ id, state: InvitationState.ERROR, error: String(err) });
127
- });
128
- });
129
- }
130
-
131
- async authenticateInvitation(request: AuthenticateInvitationRequest) {
132
- assert(request.processId, 'Process ID is missing.');
133
- const invitation = this.inviteeInvitations.get(request.processId);
134
- assert(invitation, 'Invitation not found.');
135
- assert(request.secret, 'Secret not provided.');
136
-
137
- // Supply the secret, and move the internal invitation process by triggering the secretTrigger.
138
- invitation.secret = request.secret;
139
- invitation.secretTrigger?.();
140
- }
141
59
  }
@@ -6,9 +6,16 @@ import { Config } from '@dxos/config';
6
6
  import { todo } from '@dxos/debug';
7
7
  import { SystemService } from '@dxos/protocols/proto/dxos/client';
8
8
 
9
+ /**
10
+ * @deprecated
11
+ */
9
12
  export class SystemServiceImpl implements SystemService {
10
13
  constructor(private readonly _config: Config) {}
11
14
 
15
+ async initSession() {
16
+ // Ok.
17
+ }
18
+
12
19
  async getConfig(request: void) {
13
20
  return this._config.values;
14
21
  }
@@ -6,7 +6,7 @@ import { Config } from '@dxos/config';
6
6
  import { TracingService } from '@dxos/protocols/proto/dxos/devtools/host';
7
7
 
8
8
  /**
9
- *
9
+ * @deprecated
10
10
  */
11
11
  export class TracingServiceImpl implements TracingService {
12
12
  constructor(private readonly _config: Config) {}
@@ -42,7 +42,6 @@ import { subscribeToFeedBlocks, subscribeToFeeds } from './feeds';
42
42
  import { subscribeToNetworkStatus, subscribeToSignalTrace, subscribeToSwarmInfo } from './network';
43
43
  import { subscribeToSpaces } from './spaces';
44
44
 
45
- // TODO(burdon): Remove?
46
45
  export class DevtoolsHostEvents {
47
46
  readonly ready = new AsyncEvent();
48
47
  }
@@ -53,6 +52,9 @@ export type DevtoolsServiceParams = {
53
52
  context: ServiceContext;
54
53
  };
55
54
 
55
+ /**
56
+ * @deprecated
57
+ */
56
58
  export class DevtoolsServiceImpl implements DevtoolsHost {
57
59
  constructor(private readonly params: DevtoolsServiceParams) {}
58
60
 
@@ -84,12 +84,14 @@ export const subscribeToFeedBlocks = (
84
84
  };
85
85
 
86
86
  feed.on('append', update);
87
- subscriptions.add(feed.off('append', update));
87
+ subscriptions.add(() => feed.off('append', update));
88
88
 
89
89
  feed.on('truncate', update);
90
- subscriptions.add(feed.off('truncate', update));
90
+ subscriptions.add(() => feed.off('truncate', update));
91
91
  await update();
92
92
  });
93
93
 
94
- return () => {};
94
+ return () => {
95
+ subscriptions.clear();
96
+ };
95
97
  });
@@ -31,7 +31,6 @@ export class DevicesServiceImpl implements DevicesService {
31
31
  };
32
32
 
33
33
  const dispose = new EventSubscriptions();
34
-
35
34
  dispose.add(
36
35
  this._identityManager.stateUpdate.on(() => {
37
36
  update();
@@ -74,54 +74,6 @@ export class IdentityManager {
74
74
  await this._identity?.close();
75
75
  }
76
76
 
77
- private async _constructIdentity(identityRecord: IdentityRecord) {
78
- assert(!this._identity);
79
- log('constructing identity', { identityRecord });
80
-
81
- const space = await this._constructSpace({
82
- spaceRecord: identityRecord.haloSpace,
83
- swarmIdentity: {
84
- peerKey: identityRecord.deviceKey,
85
- credentialProvider: MOCK_AUTH_PROVIDER,
86
- credentialAuthenticator: MOCK_AUTH_VERIFIER
87
- }
88
- });
89
-
90
- log('done', { identityKey: identityRecord.identityKey });
91
- return new Identity({
92
- space,
93
- signer: this._keyring,
94
- identityKey: identityRecord.identityKey,
95
- deviceKey: identityRecord.deviceKey
96
- });
97
- }
98
-
99
- private async _constructSpace({ spaceRecord, swarmIdentity }: ConstructSpaceParams) {
100
- const controlFeed = await this._feedStore.openFeed(spaceRecord.writeControlFeedKey, { writable: true });
101
- const dataFeed = await this._feedStore.openFeed(spaceRecord.writeDataFeedKey, { writable: true });
102
-
103
- // The genesis feed will be the same as the control feed if the space was created by the local agent.
104
- // NOTE: Must be initialized after writable feeds so that it is in a writable state.
105
- const genesisFeed = await this._feedStore.openFeed(spaceRecord.genesisFeedKey);
106
-
107
- const protocol = new SpaceProtocol({
108
- topic: spaceRecord.spaceKey,
109
- identity: swarmIdentity,
110
- networkManager: this._networkManager
111
- });
112
-
113
- return new Space({
114
- spaceKey: spaceRecord.spaceKey,
115
- protocol,
116
- genesisFeed,
117
- controlFeed,
118
- dataFeed,
119
- feedProvider: (feedKey) => this._feedStore.openFeed(feedKey),
120
- databaseFactory: async ({ databaseBackend }) =>
121
- new Database(this._modelFactory, databaseBackend, swarmIdentity.peerKey)
122
- });
123
- }
124
-
125
77
  async createIdentity() {
126
78
  assert(!this._identity, 'Identity already exists.');
127
79
  log('creating identity...');
@@ -169,6 +121,7 @@ export class IdentityManager {
169
121
  }
170
122
  }
171
123
 
124
+ // TODO(burdon): ???
172
125
  // await this._keyring.deleteKey(identityRecord.identity_key);
173
126
  // await this._keyring.deleteKey(identityRecord.halo_space.space_key);
174
127
 
@@ -177,7 +130,7 @@ export class IdentityManager {
177
130
  await this._identity.ready();
178
131
  this.stateUpdate.emit();
179
132
 
180
- log('created identity', { identityKey: identity.identityKey });
133
+ log('created identity', { identityKey: identity.identityKey, deviceKey: identity.deviceKey });
181
134
  return identity;
182
135
  }
183
136
 
@@ -204,4 +157,52 @@ export class IdentityManager {
204
157
  this.stateUpdate.emit();
205
158
  return identity;
206
159
  }
160
+
161
+ private async _constructIdentity(identityRecord: IdentityRecord) {
162
+ assert(!this._identity);
163
+ log('constructing identity', { identityRecord });
164
+
165
+ const space = await this._constructSpace({
166
+ spaceRecord: identityRecord.haloSpace,
167
+ swarmIdentity: {
168
+ peerKey: identityRecord.deviceKey,
169
+ credentialProvider: MOCK_AUTH_PROVIDER,
170
+ credentialAuthenticator: MOCK_AUTH_VERIFIER
171
+ }
172
+ });
173
+
174
+ log('done', { identityKey: identityRecord.identityKey });
175
+ return new Identity({
176
+ space,
177
+ signer: this._keyring,
178
+ identityKey: identityRecord.identityKey,
179
+ deviceKey: identityRecord.deviceKey
180
+ });
181
+ }
182
+
183
+ private async _constructSpace({ spaceRecord, swarmIdentity }: ConstructSpaceParams) {
184
+ const controlFeed = await this._feedStore.openFeed(spaceRecord.writeControlFeedKey, { writable: true });
185
+ const dataFeed = await this._feedStore.openFeed(spaceRecord.writeDataFeedKey, { writable: true });
186
+
187
+ // The genesis feed will be the same as the control feed if the space was created by the local agent.
188
+ // NOTE: Must be initialized after writable feeds so that it is in a writable state.
189
+ const genesisFeed = await this._feedStore.openFeed(spaceRecord.genesisFeedKey);
190
+
191
+ const protocol = new SpaceProtocol({
192
+ topic: spaceRecord.spaceKey,
193
+ identity: swarmIdentity,
194
+ networkManager: this._networkManager
195
+ });
196
+
197
+ return new Space({
198
+ spaceKey: spaceRecord.spaceKey,
199
+ protocol,
200
+ genesisFeed,
201
+ controlFeed,
202
+ dataFeed,
203
+ feedProvider: (feedKey) => this._feedStore.openFeed(feedKey),
204
+ databaseFactory: async ({ databaseBackend }) =>
205
+ new Database(this._modelFactory, databaseBackend, swarmIdentity.peerKey)
206
+ });
207
+ }
207
208
  }
@@ -14,7 +14,12 @@ import {
14
14
  import { Signer } from '@dxos/crypto';
15
15
  import { failUndefined } from '@dxos/debug';
16
16
  import { Database, Space } from '@dxos/echo-db';
17
+ import { writeMessages } from '@dxos/feed-store';
17
18
  import { PublicKey } from '@dxos/keys';
19
+ import { log } from '@dxos/log';
20
+ import { TypedMessage } from '@dxos/protocols';
21
+ import { AdmittedFeed } from '@dxos/protocols/proto/dxos/halo/credentials';
22
+ import { HaloAdmissionCredentials } from '@dxos/protocols/proto/dxos/halo/invitations';
18
23
  import { ComplexSet } from '@dxos/util';
19
24
 
20
25
  export type IdentityParams = {
@@ -46,7 +51,7 @@ export class Identity {
46
51
 
47
52
  this._deviceStateMachine = new DeviceStateMachine(this.identityKey, this.deviceKey);
48
53
 
49
- // Save device key chain credential when processed by the space state machine.
54
+ // Save device keychain credential when processed by the space state machine.
50
55
  this._space.onCredentialProcessed.set(async (credential) => {
51
56
  await this._deviceStateMachine.process(credential);
52
57
  this.stateUpdate.emit();
@@ -91,6 +96,14 @@ export class Identity {
91
96
  return this._space.database ?? failUndefined();
92
97
  }
93
98
 
99
+ getAdmissionCredentials(): HaloAdmissionCredentials {
100
+ return {
101
+ deviceKey: this.deviceKey,
102
+ controlFeedKey: this._space.controlFeedKey,
103
+ dataFeedKey: this._space.dataFeedKey
104
+ };
105
+ }
106
+
94
107
  /**
95
108
  * Issues credentials as identity.
96
109
  * Requires identity to be ready.
@@ -110,4 +123,48 @@ export class Identity {
110
123
  getDeviceCredentialSigner(): CredentialSigner {
111
124
  return createCredentialSignerWithKey(this._signer, this.deviceKey);
112
125
  }
126
+
127
+ async admitDevice({ deviceKey, controlFeedKey, dataFeedKey }: HaloAdmissionCredentials) {
128
+ log('Admitting device:', {
129
+ identityKey: this.identityKey,
130
+ hostDevice: this.deviceKey,
131
+ deviceKey,
132
+ controlFeedKey,
133
+ dataFeedKey
134
+ });
135
+ const signer = this.getIdentityCredentialSigner();
136
+ await writeMessages(
137
+ this.controlPipeline.writer,
138
+ [
139
+ await signer.createCredential({
140
+ subject: deviceKey,
141
+ assertion: {
142
+ '@type': 'dxos.halo.credentials.AuthorizedDevice',
143
+ identityKey: this.identityKey,
144
+ deviceKey
145
+ }
146
+ }),
147
+ await signer.createCredential({
148
+ subject: controlFeedKey,
149
+ assertion: {
150
+ '@type': 'dxos.halo.credentials.AdmittedFeed',
151
+ spaceKey: this.haloSpaceKey,
152
+ deviceKey,
153
+ identityKey: this.identityKey,
154
+ designation: AdmittedFeed.Designation.CONTROL
155
+ }
156
+ }),
157
+ await signer.createCredential({
158
+ subject: dataFeedKey,
159
+ assertion: {
160
+ '@type': 'dxos.halo.credentials.AdmittedFeed',
161
+ spaceKey: this.haloSpaceKey,
162
+ deviceKey,
163
+ identityKey: this.identityKey,
164
+ designation: AdmittedFeed.Designation.DATA
165
+ }
166
+ })
167
+ ].map((credential): TypedMessage => ({ '@type': 'dxos.echo.feed.CredentialsMessage', credential }))
168
+ );
169
+ }
113
170
  }
@@ -0,0 +1,79 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ import assert from 'assert';
6
+ import { expect } from 'chai';
7
+
8
+ import { asyncChain, Trigger } from '@dxos/async';
9
+ import { raise } from '@dxos/debug';
10
+ import { PublicKey } from '@dxos/keys';
11
+ import { Invitation } from '@dxos/protocols/proto/dxos/client/services';
12
+ import { afterTest } from '@dxos/testutils';
13
+
14
+ import { ServiceContext } from '../services';
15
+ import { createPeers, createServiceContext } from '../testing';
16
+
17
+ const closeAfterTest = async (peer: ServiceContext) => {
18
+ afterTest(() => peer.close());
19
+ return peer;
20
+ };
21
+
22
+ describe('services/halo', function () {
23
+ it('creates identity', async function () {
24
+ const peer = createServiceContext();
25
+ await peer.open();
26
+ afterTest(() => peer.close());
27
+
28
+ const identity = await peer.createIdentity();
29
+ expect(identity).not.to.be.undefined;
30
+ });
31
+
32
+ it('creates and accepts invitation', async function () {
33
+ const [host, guest] = await asyncChain<ServiceContext>([closeAfterTest])(createPeers(2));
34
+
35
+ const identity1 = await host.createIdentity();
36
+ expect(host.identityManager.identity).to.eq(identity1);
37
+
38
+ const observable1 = await host.haloInvitations.createInvitation();
39
+
40
+ const complete1 = new Trigger<PublicKey>();
41
+ const complete2 = new Trigger<PublicKey>();
42
+
43
+ const authenticationCode = new Trigger<string>();
44
+
45
+ observable1.subscribe({
46
+ onConnecting: async (invitation1: Invitation) => {
47
+ const observable2 = guest.haloInvitations!.acceptInvitation(invitation1);
48
+ observable2.subscribe({
49
+ onConnecting: async () => {},
50
+ onConnected: async (invitation2: Invitation) => {
51
+ expect(invitation1.swarmKey).to.eq(invitation2.swarmKey);
52
+ },
53
+ onAuthenticating: async () => {
54
+ await observable2.authenticate(await authenticationCode.wait());
55
+ },
56
+ onSuccess: (invitation: Invitation) => {
57
+ complete2.wake(invitation.identityKey!);
58
+ },
59
+ onCancelled: () => raise(new Error()),
60
+ onTimeout: (err: Error) => raise(new Error(err.message)),
61
+ onError: (err: Error) => raise(new Error(err.message))
62
+ });
63
+ },
64
+ onConnected: (invitation: Invitation) => {
65
+ assert(invitation.authenticationCode);
66
+ authenticationCode.wake(invitation.authenticationCode);
67
+ },
68
+ onSuccess: (invitation: Invitation) => {
69
+ complete1.wake(host.identityManager.identity!.identityKey);
70
+ },
71
+ onCancelled: () => raise(new Error()),
72
+ onTimeout: (err: Error) => raise(new Error(err.message)),
73
+ onError: (err: Error) => raise(new Error(err.message))
74
+ });
75
+
76
+ const [identityKey1, identityKey2] = await Promise.all([complete1.wait(), complete2.wait()]);
77
+ expect(identityKey1).to.deep.eq(identityKey2);
78
+ });
79
+ });