@dxos/client-services 0.1.35 → 0.1.36-next.ef27157

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 (87) hide show
  1. package/dist/lib/browser/{chunk-H5IXSSI7.mjs → chunk-OINEQJWM.mjs} +783 -924
  2. package/dist/lib/browser/chunk-OINEQJWM.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +9 -11
  4. package/dist/lib/browser/meta.json +1 -1
  5. package/dist/lib/browser/packlets/testing/index.mjs +212 -74
  6. package/dist/lib/browser/packlets/testing/index.mjs.map +3 -3
  7. package/dist/lib/node/index.cjs +897 -1039
  8. package/dist/lib/node/index.cjs.map +4 -4
  9. package/dist/lib/node/meta.json +1 -1
  10. package/dist/lib/node/packlets/testing/index.cjs +1057 -1061
  11. package/dist/lib/node/packlets/testing/index.cjs.map +4 -4
  12. package/dist/types/src/packlets/identity/identity.d.ts +3 -3
  13. package/dist/types/src/packlets/identity/identity.d.ts.map +1 -1
  14. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts +18 -0
  15. package/dist/types/src/packlets/invitations/device-invitation-protocol.d.ts.map +1 -0
  16. package/dist/types/src/packlets/invitations/device-invitation-protocol.test.d.ts +2 -0
  17. package/dist/types/src/packlets/invitations/device-invitation-protocol.test.d.ts.map +1 -0
  18. package/dist/types/src/packlets/invitations/index.d.ts +4 -4
  19. package/dist/types/src/packlets/invitations/index.d.ts.map +1 -1
  20. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts +12 -0
  21. package/dist/types/src/packlets/invitations/invitation-protocol.d.ts.map +1 -0
  22. package/dist/types/src/packlets/invitations/invitations-handler.d.ts +38 -0
  23. package/dist/types/src/packlets/invitations/invitations-handler.d.ts.map +1 -0
  24. package/dist/types/src/packlets/invitations/invitations-service.d.ts +13 -15
  25. package/dist/types/src/packlets/invitations/invitations-service.d.ts.map +1 -1
  26. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts +22 -0
  27. package/dist/types/src/packlets/invitations/space-invitation-protocol.d.ts.map +1 -0
  28. package/dist/types/src/packlets/invitations/space-invitation-protocol.test.d.ts +2 -0
  29. package/dist/types/src/packlets/invitations/space-invitation-protocol.test.d.ts.map +1 -0
  30. package/dist/types/src/packlets/services/service-context.d.ts +6 -4
  31. package/dist/types/src/packlets/services/service-context.d.ts.map +1 -1
  32. package/dist/types/src/packlets/services/service-host.d.ts.map +1 -1
  33. package/dist/types/src/packlets/spaces/spaces-service.d.ts.map +1 -1
  34. package/dist/types/src/packlets/testing/invitation-utils.d.ts +31 -2
  35. package/dist/types/src/packlets/testing/invitation-utils.d.ts.map +1 -1
  36. package/dist/types/src/packlets/testing/test-builder.d.ts.map +1 -1
  37. package/dist/types/src/packlets/tests/invitations.test.d.ts +2 -0
  38. package/dist/types/src/packlets/tests/invitations.test.d.ts.map +1 -0
  39. package/dist/types/src/packlets/vault/worker-runtime.d.ts +2 -0
  40. package/dist/types/src/packlets/vault/worker-runtime.d.ts.map +1 -1
  41. package/package.json +30 -30
  42. package/src/packlets/identity/identity.ts +3 -3
  43. package/src/packlets/invitations/{device-invitations-handler.test.ts → device-invitation-protocol.test.ts} +3 -3
  44. package/src/packlets/invitations/device-invitation-protocol.ts +83 -0
  45. package/src/packlets/invitations/index.ts +4 -4
  46. package/src/packlets/invitations/invitation-protocol.ts +21 -0
  47. package/src/packlets/invitations/invitations-handler.ts +462 -0
  48. package/src/packlets/invitations/invitations-service.ts +127 -104
  49. package/src/packlets/invitations/space-invitation-protocol.test.ts +221 -0
  50. package/src/packlets/invitations/space-invitation-protocol.ts +117 -0
  51. package/src/packlets/services/service-context.test.ts +11 -4
  52. package/src/packlets/services/service-context.ts +34 -17
  53. package/src/packlets/services/service-host.ts +4 -12
  54. package/src/packlets/services/service-registry.test.ts +23 -25
  55. package/src/packlets/spaces/spaces-service.ts +7 -2
  56. package/src/packlets/testing/invitation-utils.ts +219 -31
  57. package/src/packlets/testing/test-builder.ts +30 -19
  58. package/src/packlets/tests/client-services.test.ts +33 -76
  59. package/src/packlets/tests/halo-profile.test.ts +2 -28
  60. package/src/packlets/tests/invitations.test.ts +389 -0
  61. package/src/packlets/tests/spaces-invitations.test.ts +12 -30
  62. package/src/packlets/tests/spaces.test.ts +6 -28
  63. package/src/packlets/vault/worker-runtime.ts +4 -0
  64. package/dist/lib/browser/chunk-H5IXSSI7.mjs.map +0 -7
  65. package/dist/types/src/packlets/invitations/device-invitations-handler.d.ts +0 -30
  66. package/dist/types/src/packlets/invitations/device-invitations-handler.d.ts.map +0 -1
  67. package/dist/types/src/packlets/invitations/device-invitations-handler.test.d.ts +0 -2
  68. package/dist/types/src/packlets/invitations/device-invitations-handler.test.d.ts.map +0 -1
  69. package/dist/types/src/packlets/invitations/device-invitations-service.d.ts +0 -13
  70. package/dist/types/src/packlets/invitations/device-invitations-service.d.ts.map +0 -1
  71. package/dist/types/src/packlets/invitations/device-invitations-service.test.d.ts +0 -2
  72. package/dist/types/src/packlets/invitations/device-invitations-service.test.d.ts.map +0 -1
  73. package/dist/types/src/packlets/invitations/space-invitations-handler.d.ts +0 -26
  74. package/dist/types/src/packlets/invitations/space-invitations-handler.d.ts.map +0 -1
  75. package/dist/types/src/packlets/invitations/space-invitations-handler.test.d.ts +0 -2
  76. package/dist/types/src/packlets/invitations/space-invitations-handler.test.d.ts.map +0 -1
  77. package/dist/types/src/packlets/invitations/space-invitations-service.d.ts +0 -16
  78. package/dist/types/src/packlets/invitations/space-invitations-service.d.ts.map +0 -1
  79. package/dist/types/src/packlets/invitations/space-invitations-service.test.d.ts +0 -2
  80. package/dist/types/src/packlets/invitations/space-invitations-service.test.d.ts.map +0 -1
  81. package/src/packlets/invitations/device-invitations-handler.ts +0 -370
  82. package/src/packlets/invitations/device-invitations-service.test.ts +0 -96
  83. package/src/packlets/invitations/device-invitations-service.ts +0 -24
  84. package/src/packlets/invitations/space-invitations-handler.test.ts +0 -246
  85. package/src/packlets/invitations/space-invitations-handler.ts +0 -463
  86. package/src/packlets/invitations/space-invitations-service.test.ts +0 -129
  87. package/src/packlets/invitations/space-invitations-service.ts +0 -35
@@ -861,696 +861,176 @@ var IdentityServiceImpl = class {
861
861
  }
862
862
  };
863
863
 
864
- // packages/sdk/client-services/src/packlets/invitations/device-invitations-handler.ts
864
+ // packages/sdk/client-services/src/packlets/invitations/device-invitation-protocol.ts
865
865
  import assert4 from "@dxos/node-std/assert";
866
- import { scheduleTask, sleep, Trigger as Trigger2 } from "@dxos/async";
867
- import { AbstractInvitationsHandler, AuthenticatingInvitationProvider, AUTHENTICATION_CODE_LENGTH, InvitationObservableProvider, INVITATION_TIMEOUT, ON_CLOSE_DELAY } from "@dxos/client";
868
- import { Context as Context3 } from "@dxos/context";
869
- import { generatePasscode } from "@dxos/credentials";
870
- import { PublicKey as PublicKey4 } from "@dxos/keys";
871
- import { log as log4 } from "@dxos/log";
872
- import { createTeleportProtocolFactory, StarTopology } from "@dxos/network-manager";
873
- import { schema as schema2 } from "@dxos/protocols";
874
866
  import { Invitation } from "@dxos/protocols/proto/dxos/client/services";
875
- import { AuthenticationResponse } from "@dxos/protocols/proto/dxos/halo/invitations";
876
- import { RpcExtension } from "@dxos/teleport";
877
- var DeviceInvitationsHandler = class extends AbstractInvitationsHandler {
878
- // prettier-ignore
879
- constructor(_params) {
880
- super(_params.networkManager);
881
- this._params = _params;
867
+ var DeviceInvitationProtocol = class {
868
+ constructor(_keyring, _getIdentity, _acceptIdentity) {
869
+ this._keyring = _keyring;
870
+ this._getIdentity = _getIdentity;
871
+ this._acceptIdentity = _acceptIdentity;
882
872
  }
883
- /**
884
- * Creates an invitation and listens for a join request from the invited (guest) peer.
885
- */
886
- createInvitation(context, options) {
887
- const { type, timeout = INVITATION_TIMEOUT, swarmKey } = options != null ? options : {};
888
- assert4(type !== Invitation.Type.OFFLINE);
889
- const identity = this._params.getIdentity();
890
- const invitation = {
891
- type,
892
- invitationId: PublicKey4.random().toHex(),
893
- swarmKey: swarmKey != null ? swarmKey : PublicKey4.random(),
894
- authenticationCode: generatePasscode(AUTHENTICATION_CODE_LENGTH)
895
- };
896
- const ctx = new Context3({
897
- onError: (err) => {
898
- void ctx.dispose();
899
- observable.callback.onError(err);
900
- }
901
- });
902
- const observable = new InvitationObservableProvider(async () => {
903
- await ctx.dispose();
904
- });
905
- let authenticationCode;
906
- const complete = new Trigger2();
907
- const createExtension = () => new HostHaloInvitationExtension({
908
- requestAdmission: async () => {
909
- var _a, _b;
910
- log4("responding with admission offer", {
911
- host: identity.deviceKey
912
- }, {
913
- file: "device-invitations-handler.ts",
914
- line: 92,
915
- scope: this,
916
- callSite: (f, a) => f(...a)
917
- });
918
- (_b = (_a = observable.callback).onAuthenticating) == null ? void 0 : _b.call(_a, invitation);
919
- return {
920
- identityKey: identity.identityKey,
921
- haloSpaceKey: identity.haloSpaceKey,
922
- genesisFeedKey: identity.haloGenesisFeedKey,
923
- controlTimeframe: identity.controlPipeline.state.timeframe
924
- };
925
- },
926
- authenticate: async ({ authenticationCode: code }) => {
927
- log4("received authentication request", {
928
- authenticationCode: code
929
- }, {
930
- file: "device-invitations-handler.ts",
931
- line: 107,
932
- scope: this,
933
- callSite: (f, a) => f(...a)
934
- });
935
- authenticationCode = code;
936
- return {
937
- status: AuthenticationResponse.Status.OK
938
- };
939
- },
940
- // TODO(burdon): Not used: controlFeedKey, dataFeedKey.
941
- presentAdmissionCredentials: async (credentials) => {
942
- try {
943
- if (invitation.type !== Invitation.Type.INTERACTIVE_TESTING) {
944
- if (invitation.authenticationCode === void 0 || invitation.authenticationCode !== authenticationCode) {
945
- throw new Error(`invalid authentication code: ${authenticationCode}`);
946
- }
947
- }
948
- log4("writing guest credentials", {
949
- host: identity.deviceKey,
950
- guest: credentials.deviceKey
951
- }, {
952
- file: "device-invitations-handler.ts",
953
- line: 122,
954
- scope: this,
955
- callSite: (f, a) => f(...a)
956
- });
957
- await identity.admitDevice(credentials);
958
- complete.wake(credentials.deviceKey);
959
- } catch (err) {
960
- observable.callback.onError(err);
961
- throw err;
962
- }
963
- },
964
- onOpen: () => {
965
- scheduleTask(ctx, async () => {
966
- var _a, _b;
967
- try {
968
- log4("connected", {
969
- host: identity.deviceKey
970
- }, {
971
- file: "device-invitations-handler.ts",
972
- line: 138,
973
- scope: this,
974
- callSite: (f, a) => f(...a)
975
- });
976
- (_b = (_a = observable.callback).onConnected) == null ? void 0 : _b.call(_a, invitation);
977
- const deviceKey = await complete.wait({
978
- timeout
979
- });
980
- log4("admitted guest", {
981
- host: identity.deviceKey,
982
- guest: deviceKey
983
- }, {
984
- file: "device-invitations-handler.ts",
985
- line: 141,
986
- scope: this,
987
- callSite: (f, a) => f(...a)
988
- });
989
- observable.callback.onSuccess(invitation);
990
- } catch (err) {
991
- if (!observable.cancelled) {
992
- log4.error("failed", err, {
993
- file: "device-invitations-handler.ts",
994
- line: 145,
995
- scope: this,
996
- callSite: (f, a) => f(...a)
997
- });
998
- observable.callback.onError(err);
999
- }
1000
- } finally {
1001
- await sleep(ON_CLOSE_DELAY);
1002
- await ctx.dispose();
1003
- }
1004
- });
1005
- }
1006
- });
1007
- scheduleTask(ctx, async () => {
1008
- var _a, _b;
1009
- const topic = invitation.swarmKey;
1010
- const swarmConnection = await this._networkManager.joinSwarm({
1011
- topic,
1012
- peerId: topic,
1013
- protocolProvider: createTeleportProtocolFactory(async (teleport) => {
1014
- teleport.addExtension("dxos.halo.invitations", createExtension());
1015
- }),
1016
- topology: new StarTopology(topic)
1017
- });
1018
- ctx.onDispose(() => swarmConnection.close());
1019
- (_b = (_a = observable.callback).onConnecting) == null ? void 0 : _b.call(_a, invitation);
1020
- });
1021
- return observable;
873
+ toJSON() {
874
+ return {};
1022
875
  }
1023
- /**
1024
- * Waits for the host peer (inviter) to accept our join request.
1025
- * The local guest peer (invitee) then sends the local halo invitation to the host,
1026
- * which then writes the guest's credentials to the halo.
1027
- */
1028
- acceptInvitation(invitation, options) {
1029
- const { timeout = INVITATION_TIMEOUT } = options != null ? options : {};
1030
- const ctx = new Context3({
1031
- onError: (err) => {
1032
- void ctx.dispose();
1033
- observable.callback.onError(err);
1034
- }
1035
- });
1036
- const authenticated = new Trigger2();
1037
- const observable = new AuthenticatingInvitationProvider({
1038
- onCancel: async () => {
1039
- await ctx.dispose();
1040
- },
1041
- // TODO(burdon): Consider retry.
1042
- onAuthenticate: async (code) => {
1043
- authenticated.wake(code);
1044
- }
1045
- });
1046
- let connectionCount = 0;
1047
- const complete = new Trigger2();
1048
- const createExtension = () => {
1049
- const extension = new GuestHaloInvitationExtension({
1050
- onOpen: () => {
1051
- scheduleTask(ctx, async () => {
1052
- var _a, _b, _c, _d;
1053
- try {
1054
- if (++connectionCount > 1) {
1055
- throw new Error(`multiple connections detected: ${connectionCount}`);
1056
- }
1057
- log4("connected", {}, {
1058
- file: "device-invitations-handler.ts",
1059
- line: 216,
1060
- scope: this,
1061
- callSite: (f, a) => f(...a)
1062
- });
1063
- (_b = (_a = observable.callback).onConnected) == null ? void 0 : _b.call(_a, invitation);
1064
- log4("sending admission request", {}, {
1065
- file: "device-invitations-handler.ts",
1066
- line: 220,
1067
- scope: this,
1068
- callSite: (f, a) => f(...a)
1069
- });
1070
- const { identityKey, haloSpaceKey, genesisFeedKey, controlTimeframe } = await extension.rpc.HaloHostService.requestAdmission();
1071
- if (invitation.type === void 0 || invitation.type === Invitation.Type.INTERACTIVE) {
1072
- log4("guest waiting for authentication code...", {}, {
1073
- file: "device-invitations-handler.ts",
1074
- line: 227,
1075
- scope: this,
1076
- callSite: (f, a) => f(...a)
1077
- });
1078
- (_d = (_c = observable.callback).onAuthenticating) == null ? void 0 : _d.call(_c, invitation);
1079
- const authenticationCode = await authenticated.wait({
1080
- timeout
1081
- });
1082
- log4("sending authentication request", {}, {
1083
- file: "device-invitations-handler.ts",
1084
- line: 230,
1085
- scope: this,
1086
- callSite: (f, a) => f(...a)
1087
- });
1088
- await extension.rpc.HaloHostService.authenticate({
1089
- authenticationCode
1090
- });
1091
- }
1092
- const deviceKey = await this._params.keyring.createKey();
1093
- const controlFeedKey = await this._params.keyring.createKey();
1094
- const dataFeedKey = await this._params.keyring.createKey();
1095
- log4("presenting admission credentials", {
1096
- identityKey,
1097
- deviceKey,
1098
- controlFeedKey,
1099
- dataFeedKey
1100
- }, {
1101
- file: "device-invitations-handler.ts",
1102
- line: 239,
1103
- scope: this,
1104
- callSite: (f, a) => f(...a)
1105
- });
1106
- await extension.rpc.HaloHostService.presentAdmissionCredentials({
1107
- deviceKey,
1108
- controlFeedKey,
1109
- dataFeedKey
1110
- });
1111
- const identity = await this._params.acceptIdentity({
1112
- identityKey,
1113
- deviceKey,
1114
- haloSpaceKey,
1115
- haloGenesisFeedKey: genesisFeedKey,
1116
- controlFeedKey,
1117
- dataFeedKey,
1118
- controlTimeframe
1119
- });
1120
- log4("admitted by host", {
1121
- guest: identity.deviceKey,
1122
- identityKey
1123
- }, {
1124
- file: "device-invitations-handler.ts",
1125
- line: 259,
1126
- scope: this,
1127
- callSite: (f, a) => f(...a)
1128
- });
1129
- complete.wake(identityKey);
1130
- } catch (err) {
1131
- if (!observable.cancelled) {
1132
- log4.warn("auth failed", err, {
1133
- file: "device-invitations-handler.ts",
1134
- line: 263,
1135
- scope: this,
1136
- callSite: (f, a) => f(...a)
1137
- });
1138
- observable.callback.onError(err);
1139
- }
1140
- } finally {
1141
- await ctx.dispose();
1142
- }
1143
- });
1144
- }
1145
- });
1146
- return extension;
876
+ getInvitationContext() {
877
+ return {
878
+ kind: Invitation.Kind.DEVICE
1147
879
  };
1148
- scheduleTask(ctx, async () => {
1149
- var _a, _b;
1150
- assert4(invitation.swarmKey);
1151
- const topic = invitation.swarmKey;
1152
- const swarmConnection = await this._networkManager.joinSwarm({
1153
- topic,
1154
- peerId: PublicKey4.random(),
1155
- protocolProvider: createTeleportProtocolFactory(async (teleport) => {
1156
- teleport.addExtension("dxos.halo.invitations", createExtension());
1157
- }),
1158
- topology: new StarTopology(topic)
1159
- });
1160
- ctx.onDispose(() => swarmConnection.close());
1161
- (_b = (_a = observable.callback).onConnecting) == null ? void 0 : _b.call(_a, invitation);
1162
- invitation.identityKey = await complete.wait();
1163
- observable.callback.onSuccess(invitation);
1164
- await ctx.dispose();
1165
- });
1166
- return observable;
1167
- }
1168
- };
1169
- var HostHaloInvitationExtension = class extends RpcExtension {
1170
- constructor(_callbacks) {
1171
- super({
1172
- exposed: {
1173
- HaloHostService: schema2.getService("dxos.halo.invitations.HaloHostService")
1174
- }
1175
- });
1176
- this._callbacks = _callbacks;
1177
880
  }
1178
- async getHandlers() {
881
+ async admit(request) {
882
+ assert4(request.device);
883
+ const identity = this._getIdentity();
884
+ await identity.admitDevice(request.device);
1179
885
  return {
1180
- // TODO(dmaretskyi): For now this is just forwarding the data to callbacks since we don't have session-specific logic.
1181
- // Perhaps in the future we will have more complex logic here.
1182
- HaloHostService: {
1183
- requestAdmission: async () => {
1184
- return this._callbacks.requestAdmission();
1185
- },
1186
- authenticate: async (credentials) => {
1187
- return this._callbacks.authenticate(credentials);
1188
- },
1189
- // TODO(burdon): Not used: controlFeedKey, dataFeedKey.
1190
- presentAdmissionCredentials: async (credentials) => {
1191
- return this._callbacks.presentAdmissionCredentials(credentials);
1192
- }
886
+ device: {
887
+ identityKey: identity.identityKey,
888
+ haloSpaceKey: identity.haloSpaceKey,
889
+ genesisFeedKey: identity.haloGenesisFeedKey,
890
+ controlTimeframe: identity.controlPipeline.state.timeframe
1193
891
  }
1194
892
  };
1195
893
  }
1196
- async onOpen(context) {
1197
- await super.onOpen(context);
1198
- this._callbacks.onOpen();
1199
- }
1200
- };
1201
- var GuestHaloInvitationExtension = class extends RpcExtension {
1202
- constructor(_callbacks) {
1203
- super({
1204
- requested: {
1205
- HaloHostService: schema2.getService("dxos.halo.invitations.HaloHostService")
1206
- }
1207
- });
1208
- this._callbacks = _callbacks;
1209
- }
1210
- async getHandlers() {
894
+ createIntroduction() {
1211
895
  return {};
1212
896
  }
1213
- async onOpen(context) {
1214
- await super.onOpen(context);
1215
- this._callbacks.onOpen();
1216
- }
1217
- };
1218
-
1219
- // packages/sdk/client-services/src/packlets/invitations/invitations-service.ts
1220
- import assert5 from "@dxos/node-std/assert";
1221
- import { Stream as Stream7 } from "@dxos/codec-protobuf";
1222
- import { log as log5 } from "@dxos/log";
1223
- import { Invitation as Invitation2 } from "@dxos/protocols/proto/dxos/client/services";
1224
- var AbstractInvitationsService = class {
1225
- // prettier-ignore
1226
- constructor(_identityManager, _getInvitationsHandler) {
1227
- this._identityManager = _identityManager;
1228
- this._getInvitationsHandler = _getInvitationsHandler;
1229
- this._createInvitations = /* @__PURE__ */ new Map();
1230
- this._acceptInvitations = /* @__PURE__ */ new Map();
1231
- }
1232
- // TODO(burdon): Guest/host label.
1233
- getLoggingContext() {
1234
- var _a;
897
+ async createAdmissionRequest() {
898
+ const deviceKey = await this._keyring.createKey();
899
+ const controlFeedKey = await this._keyring.createKey();
900
+ const dataFeedKey = await this._keyring.createKey();
1235
901
  return {
1236
- deviceKey: (_a = this._identityManager.identity) == null ? void 0 : _a.deviceKey
902
+ device: {
903
+ deviceKey,
904
+ controlFeedKey,
905
+ dataFeedKey
906
+ }
1237
907
  };
1238
908
  }
1239
- createInvitation(invitation) {
1240
- return new Stream7(({ next, close }) => {
1241
- const invitationsHandler = this._getInvitationsHandler();
1242
- const context = this.getContext(invitation);
1243
- log5("stream opened", this.getLoggingContext(), {
1244
- file: "invitations-service.ts",
1245
- line: 48,
1246
- scope: this,
1247
- callSite: (f, a) => f(...a)
1248
- });
1249
- let invitationId;
1250
- const { type, swarmKey, authMethod } = invitation;
1251
- const observable = invitationsHandler.createInvitation(context, {
1252
- type,
1253
- swarmKey,
1254
- authMethod
1255
- });
1256
- observable.subscribe({
1257
- onConnecting: (invitation2) => {
1258
- assert5(invitation2.invitationId);
1259
- invitationId = invitation2.invitationId;
1260
- this._createInvitations.set(invitation2.invitationId, observable);
1261
- invitation2.state = Invitation2.State.CONNECTING;
1262
- next(invitation2);
1263
- },
1264
- onConnected: (invitation2) => {
1265
- assert5(invitation2.invitationId);
1266
- invitation2.state = Invitation2.State.CONNECTED;
1267
- next(invitation2);
1268
- },
1269
- onAuthenticating: (invitation2) => {
1270
- assert5(invitation2.invitationId);
1271
- invitation2.state = Invitation2.State.AUTHENTICATING;
1272
- next(invitation2);
1273
- },
1274
- onSuccess: (invitation2) => {
1275
- assert5(invitation2.invitationId);
1276
- invitation2.state = Invitation2.State.SUCCESS;
1277
- next(invitation2);
1278
- close();
1279
- },
1280
- onCancelled: () => {
1281
- assert5(invitationId);
1282
- invitation.invitationId = invitationId;
1283
- invitation.state = Invitation2.State.CANCELLED;
1284
- next(invitation);
1285
- close();
1286
- },
1287
- onTimeout: (err) => {
1288
- invitation.state = Invitation2.State.TIMEOUT;
1289
- close(err);
1290
- },
1291
- onError: (err) => {
1292
- invitation.state = Invitation2.State.ERROR;
1293
- close(err);
1294
- }
1295
- });
1296
- return (err) => {
1297
- const context2 = this.getLoggingContext();
1298
- if (err) {
1299
- log5.warn("stream closed", {
1300
- ...context2,
1301
- err
1302
- }, {
1303
- file: "invitations-service.ts",
1304
- line: 97,
1305
- scope: this,
1306
- callSite: (f, a) => f(...a)
1307
- });
1308
- } else {
1309
- log5("stream closed", context2, {
1310
- file: "invitations-service.ts",
1311
- line: 99,
1312
- scope: this,
1313
- callSite: (f, a) => f(...a)
1314
- });
1315
- }
1316
- this._createInvitations.delete(invitation.invitationId);
1317
- };
1318
- });
1319
- }
1320
- acceptInvitation(invitation, options) {
1321
- return new Stream7(({ next, close }) => {
1322
- log5("stream opened", this.getLoggingContext(), {
1323
- file: "invitations-service.ts",
1324
- line: 109,
1325
- scope: this,
1326
- callSite: (f, a) => f(...a)
1327
- });
1328
- const invitationsHandler = this._getInvitationsHandler();
1329
- let invitationId;
1330
- const observable = invitationsHandler.acceptInvitation(invitation, options);
1331
- observable.subscribe({
1332
- onConnecting: (invitation2) => {
1333
- assert5(invitation2.invitationId);
1334
- invitationId = invitation2.invitationId;
1335
- this._acceptInvitations.set(invitation2.invitationId, observable);
1336
- invitation2.state = Invitation2.State.CONNECTING;
1337
- next(invitation2);
1338
- },
1339
- onConnected: (invitation2) => {
1340
- assert5(invitation2.invitationId);
1341
- invitation2.state = Invitation2.State.CONNECTED;
1342
- next(invitation2);
1343
- },
1344
- onAuthenticating: (invitation2) => {
1345
- assert5(invitation2.invitationId);
1346
- invitation2.state = Invitation2.State.AUTHENTICATING;
1347
- next(invitation2);
1348
- },
1349
- onSuccess: (invitation2) => {
1350
- invitation2.state = Invitation2.State.SUCCESS;
1351
- next(invitation2);
1352
- close();
1353
- },
1354
- onCancelled: () => {
1355
- assert5(invitationId);
1356
- invitation.invitationId = invitationId;
1357
- invitation.state = Invitation2.State.CANCELLED;
1358
- next(invitation);
1359
- close();
1360
- },
1361
- onTimeout: (err) => {
1362
- invitation.state = Invitation2.State.TIMEOUT;
1363
- close(err);
1364
- },
1365
- onError: (err) => {
1366
- invitation.state = Invitation2.State.ERROR;
1367
- close(err);
1368
- }
1369
- });
1370
- return (err) => {
1371
- const context = this.getLoggingContext();
1372
- if (err) {
1373
- log5.warn("stream closed", {
1374
- ...context,
1375
- err
1376
- }, {
1377
- file: "invitations-service.ts",
1378
- line: 157,
1379
- scope: this,
1380
- callSite: (f, a) => f(...a)
1381
- });
1382
- } else {
1383
- log5("stream closed", context, {
1384
- file: "invitations-service.ts",
1385
- line: 159,
1386
- scope: this,
1387
- callSite: (f, a) => f(...a)
1388
- });
1389
- }
1390
- this._acceptInvitations.delete(invitation.invitationId);
1391
- };
1392
- });
1393
- }
1394
- async authenticate({ invitationId, authenticationCode }) {
1395
- log5("authenticating...", {}, {
1396
- file: "invitations-service.ts",
1397
- line: 168,
1398
- scope: this,
1399
- callSite: (f, a) => f(...a)
1400
- });
1401
- assert5(invitationId);
1402
- const observable = this._acceptInvitations.get(invitationId);
1403
- if (!observable) {
1404
- log5.warn("invalid invitation", {
1405
- invitationId
1406
- }, {
1407
- file: "invitations-service.ts",
1408
- line: 172,
1409
- scope: this,
1410
- callSite: (f, a) => f(...a)
1411
- });
1412
- } else {
1413
- await observable.authenticate(authenticationCode);
1414
- }
1415
- }
1416
- async cancelInvitation(invitation) {
1417
- var _a;
1418
- log5("cancelling...", {}, {
1419
- file: "invitations-service.ts",
1420
- line: 179,
1421
- scope: this,
1422
- callSite: (f, a) => f(...a)
909
+ async accept(response, request) {
910
+ assert4(response.device);
911
+ const { identityKey, haloSpaceKey, genesisFeedKey, controlTimeframe } = response.device;
912
+ assert4(request.device);
913
+ const { deviceKey, controlFeedKey, dataFeedKey } = request.device;
914
+ await this._acceptIdentity({
915
+ identityKey,
916
+ deviceKey,
917
+ haloSpaceKey,
918
+ haloGenesisFeedKey: genesisFeedKey,
919
+ controlFeedKey,
920
+ dataFeedKey,
921
+ controlTimeframe
1423
922
  });
1424
- assert5(invitation.invitationId);
1425
- const observable = (_a = this._createInvitations.get(invitation.invitationId)) != null ? _a : this._acceptInvitations.get(invitation.invitationId);
1426
- if (!observable) {
1427
- log5.warn("invalid invitation", {
1428
- invitationId: invitation.invitationId
1429
- }, {
1430
- file: "invitations-service.ts",
1431
- line: 184,
1432
- scope: this,
1433
- callSite: (f, a) => f(...a)
1434
- });
1435
- } else {
1436
- await (observable == null ? void 0 : observable.cancel());
1437
- }
1438
- }
1439
- };
1440
-
1441
- // packages/sdk/client-services/src/packlets/invitations/device-invitations-service.ts
1442
- var DeviceInvitationsServiceImpl = class extends AbstractInvitationsService {
1443
- // prettier-ignore
1444
- constructor(identityManager, invitationsHandler) {
1445
- super(identityManager, () => invitationsHandler);
1446
- this.invitationsHandler = invitationsHandler;
1447
- }
1448
- getContext(invitation) {
923
+ return {
924
+ identityKey
925
+ };
1449
926
  }
1450
927
  };
1451
928
 
1452
- // packages/sdk/client-services/src/packlets/invitations/space-invitations-handler.ts
1453
- import assert6 from "@dxos/node-std/assert";
1454
- import { scheduleTask as scheduleTask2, sleep as sleep2, Trigger as Trigger3 } from "@dxos/async";
1455
- import { AuthenticatingInvitationProvider as AuthenticatingInvitationProvider2, AUTHENTICATION_CODE_LENGTH as AUTHENTICATION_CODE_LENGTH2, InvitationObservableProvider as InvitationObservableProvider2, INVITATION_TIMEOUT as INVITATION_TIMEOUT2, ON_CLOSE_DELAY as ON_CLOSE_DELAY2, AbstractInvitationsHandler as AbstractInvitationsHandler2 } from "@dxos/client";
1456
- import { Context as Context4 } from "@dxos/context";
1457
- import { createAdmissionCredentials, generatePasscode as generatePasscode2, getCredentialAssertion } from "@dxos/credentials";
1458
- import { writeMessages as writeMessages2 } from "@dxos/feed-store";
1459
- import { PublicKey as PublicKey5 } from "@dxos/keys";
1460
- import { log as log6 } from "@dxos/log";
1461
- import { createTeleportProtocolFactory as createTeleportProtocolFactory2, StarTopology as StarTopology2 } from "@dxos/network-manager";
1462
- import { schema as schema3 } from "@dxos/protocols";
1463
- import { Invitation as Invitation3 } from "@dxos/protocols/proto/dxos/client/services";
1464
- import { AuthenticationResponse as AuthenticationResponse2, AuthMethod } from "@dxos/protocols/proto/dxos/halo/invitations";
1465
- import { RpcExtension as RpcExtension2 } from "@dxos/teleport";
929
+ // packages/sdk/client-services/src/packlets/invitations/invitations-handler.ts
930
+ import assert5 from "@dxos/node-std/assert";
931
+ import { PushStream, scheduleTask, sleep, TimeoutError, Trigger as Trigger2 } from "@dxos/async";
932
+ import { AUTHENTICATION_CODE_LENGTH, CancellableInvitationObservable, INVITATION_TIMEOUT, ON_CLOSE_DELAY, AuthenticatingInvitationObservable } from "@dxos/client";
933
+ import { Context as Context3 } from "@dxos/context";
934
+ import { generatePasscode } from "@dxos/credentials";
935
+ import { PublicKey as PublicKey4 } from "@dxos/keys";
936
+ import { log as log4 } from "@dxos/log";
937
+ import { createTeleportProtocolFactory, StarTopology } from "@dxos/network-manager";
938
+ import { schema as schema2 } from "@dxos/protocols";
939
+ import { Invitation as Invitation2 } from "@dxos/protocols/proto/dxos/client/services";
940
+ import { AuthenticationResponse } from "@dxos/protocols/proto/dxos/halo/invitations";
941
+ import { RpcExtension } from "@dxos/teleport";
1466
942
  var MAX_OTP_ATTEMPTS = 3;
1467
- var SpaceInvitationsHandler = class extends AbstractInvitationsHandler2 {
1468
- constructor(networkManager, _spaceManager, _signingContext, _keyring) {
1469
- super(networkManager);
1470
- this._spaceManager = _spaceManager;
1471
- this._signingContext = _signingContext;
1472
- this._keyring = _keyring;
943
+ var InvitationsHandler = class {
944
+ constructor(_networkManager) {
945
+ this._networkManager = _networkManager;
1473
946
  }
1474
- /**
1475
- * Creates an invitation and listens for a join request from the invited (guest) peer.
1476
- */
1477
- createInvitation(space, options) {
947
+ createInvitation(protocol, options) {
1478
948
  var _a;
1479
- let swarmConnection;
1480
- const { type, timeout = INVITATION_TIMEOUT2, swarmKey } = options != null ? options : {};
1481
- assert6(type !== Invitation3.Type.OFFLINE);
1482
- assert6(space);
949
+ const { invitationId = PublicKey4.random().toHex(), type = Invitation2.Type.INTERACTIVE, authMethod = Invitation2.AuthMethod.SHARED_SECRET, state = Invitation2.State.INIT, timeout = INVITATION_TIMEOUT, swarmKey = PublicKey4.random() } = options != null ? options : {};
950
+ const authCode = (_a = options == null ? void 0 : options.authCode) != null ? _a : authMethod === Invitation2.AuthMethod.SHARED_SECRET ? generatePasscode(AUTHENTICATION_CODE_LENGTH) : void 0;
951
+ assert5(protocol);
1483
952
  const invitation = {
953
+ invitationId,
1484
954
  type,
1485
- invitationId: PublicKey5.random().toHex(),
1486
- swarmKey: swarmKey != null ? swarmKey : PublicKey5.random(),
1487
- spaceKey: space.key,
1488
- authMethod: (_a = options == null ? void 0 : options.authMethod) != null ? _a : AuthMethod.SHARED_SECRET,
1489
- authenticationCode: generatePasscode2(AUTHENTICATION_CODE_LENGTH2)
1490
- // TODO(dmaretskyi): Don't generate if authMethod === NONE .
955
+ authMethod,
956
+ state,
957
+ swarmKey,
958
+ authCode,
959
+ timeout,
960
+ ...protocol.getInvitationContext()
1491
961
  };
1492
- const ctx = new Context4({
962
+ const stream = new PushStream();
963
+ const ctx = new Context3({
1493
964
  onError: (err) => {
1494
965
  void ctx.dispose();
1495
- observable.callback.onError(err);
966
+ stream.error(err);
1496
967
  }
1497
968
  });
1498
- const observable = new InvitationObservableProvider2(async () => {
1499
- await (swarmConnection == null ? void 0 : swarmConnection.close());
969
+ ctx.onDispose(() => {
970
+ log4("complete", {
971
+ ...protocol.toJSON()
972
+ }, {
973
+ file: "invitations-handler.ts",
974
+ line: 102,
975
+ scope: this,
976
+ callSite: (f, a) => f(...a)
977
+ });
978
+ stream.complete();
1500
979
  });
1501
- let authenticationPassed = false;
1502
- let authenticationRetry = 0;
1503
980
  const createExtension = () => {
1504
- const complete = new Trigger3();
981
+ const success = new Trigger2();
1505
982
  let guestProfile;
1506
- const hostInvitationExtension = new HostSpaceInvitationExtension({
983
+ let authenticationPassed = false;
984
+ let authenticationRetry = 0;
985
+ const extension = new InvitationHostExtension({
1507
986
  introduce: async ({ profile }) => {
1508
- var _a2, _b;
1509
- log6("guest introduced itself", {
987
+ log4("guest introduced itself", {
1510
988
  guestProfile: profile,
1511
- host: this._signingContext.deviceKey,
1512
- spaceKey: space.key
989
+ ...protocol.toJSON()
1513
990
  }, {
1514
- file: "space-invitations-handler.ts",
1515
- line: 101,
991
+ file: "invitations-handler.ts",
992
+ line: 115,
1516
993
  scope: this,
1517
994
  callSite: (f, a) => f(...a)
1518
995
  });
1519
996
  guestProfile = profile;
1520
- (_b = (_a2 = observable.callback).onAuthenticating) == null ? void 0 : _b.call(_a2, invitation);
997
+ stream.next({
998
+ ...invitation,
999
+ state: Invitation2.State.READY_FOR_AUTHENTICATION
1000
+ });
1521
1001
  return {
1522
- spaceKey: type === Invitation3.Type.INTERACTIVE_TESTING || type === Invitation3.Type.MULTIUSE_TESTING ? space.key : void 0,
1523
- authMethod: invitation.authMethod
1002
+ spaceKey: authMethod === Invitation2.AuthMethod.NONE ? protocol.getInvitationContext().spaceKey : void 0,
1003
+ authMethod
1524
1004
  };
1525
1005
  },
1526
- authenticate: async ({ authenticationCode: code }) => {
1527
- log6("received authentication request", {
1528
- authenticationCode: code
1006
+ authenticate: async ({ authCode: code }) => {
1007
+ log4("received authentication request", {
1008
+ authCode: code
1529
1009
  }, {
1530
- file: "space-invitations-handler.ts",
1531
- line: 123,
1010
+ file: "invitations-handler.ts",
1011
+ line: 134,
1532
1012
  scope: this,
1533
1013
  callSite: (f, a) => f(...a)
1534
1014
  });
1535
- let status = AuthenticationResponse2.Status.OK;
1015
+ let status = AuthenticationResponse.Status.OK;
1536
1016
  switch (invitation.authMethod) {
1537
- case AuthMethod.NONE: {
1538
- log6("authentication not required", {}, {
1539
- file: "space-invitations-handler.ts",
1540
- line: 128,
1017
+ case Invitation2.AuthMethod.NONE: {
1018
+ log4("authentication not required", {}, {
1019
+ file: "invitations-handler.ts",
1020
+ line: 139,
1541
1021
  scope: this,
1542
1022
  callSite: (f, a) => f(...a)
1543
1023
  });
1544
1024
  return {
1545
- status: AuthenticationResponse2.Status.OK
1025
+ status: AuthenticationResponse.Status.OK
1546
1026
  };
1547
1027
  }
1548
- case AuthMethod.SHARED_SECRET: {
1549
- if (invitation.authenticationCode) {
1028
+ case Invitation2.AuthMethod.SHARED_SECRET: {
1029
+ if (invitation.authCode) {
1550
1030
  if (authenticationRetry++ > MAX_OTP_ATTEMPTS) {
1551
- status = AuthenticationResponse2.Status.INVALID_OPT_ATTEMPTS;
1552
- } else if (code !== invitation.authenticationCode) {
1553
- status = AuthenticationResponse2.Status.INVALID_OTP;
1031
+ status = AuthenticationResponse.Status.INVALID_OPT_ATTEMPTS;
1032
+ } else if (code !== invitation.authCode) {
1033
+ status = AuthenticationResponse.Status.INVALID_OTP;
1554
1034
  } else {
1555
1035
  authenticationPassed = true;
1556
1036
  }
@@ -1558,15 +1038,15 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler2 {
1558
1038
  break;
1559
1039
  }
1560
1040
  default: {
1561
- log6.error("invalid authentication method", {
1041
+ log4.error("invalid authentication method", {
1562
1042
  authMethod: invitation.authMethod
1563
1043
  }, {
1564
- file: "space-invitations-handler.ts",
1565
- line: 144,
1044
+ file: "invitations-handler.ts",
1045
+ line: 157,
1566
1046
  scope: this,
1567
1047
  callSite: (f, a) => f(...a)
1568
1048
  });
1569
- status = AuthenticationResponse2.Status.INTERNAL_ERROR;
1049
+ status = AuthenticationResponse.Status.INTERNAL_ERROR;
1570
1050
  break;
1571
1051
  }
1572
1052
  }
@@ -1574,159 +1054,196 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler2 {
1574
1054
  status
1575
1055
  };
1576
1056
  },
1577
- requestAdmission: async ({ identityKey, deviceKey, controlFeedKey, dataFeedKey }) => {
1578
- var _a2;
1057
+ admit: async (admissionRequest) => {
1058
+ var _a2, _b, _c;
1579
1059
  try {
1580
1060
  if (isAuthenticationRequired(invitation) && !authenticationPassed) {
1581
1061
  throw new Error("Not authenticated");
1582
1062
  }
1583
- log6("writing guest credentials", {
1584
- host: this._signingContext.deviceKey,
1585
- guest: deviceKey
1586
- }, {
1587
- file: "space-invitations-handler.ts",
1588
- line: 160,
1589
- scope: this,
1590
- callSite: (f, a) => f(...a)
1591
- });
1592
- const credentials = await createAdmissionCredentials(this._signingContext.credentialSigner, identityKey, space.key, space.inner.genesisFeedKey, guestProfile);
1593
- assert6(credentials[0].credential);
1594
- const spaceMemberCredential = credentials[0].credential.credential;
1595
- assert6(getCredentialAssertion(spaceMemberCredential)["@type"] === "dxos.halo.credentials.SpaceMember");
1596
- await writeMessages2(space.inner.controlPipeline.writer, credentials);
1597
- complete.wake(deviceKey);
1598
- return {
1599
- credential: spaceMemberCredential,
1600
- controlTimeframe: space.inner.controlPipeline.state.timeframe,
1601
- dataTimeframe: (_a2 = space.dataPipeline.pipelineState) == null ? void 0 : _a2.timeframe
1602
- };
1063
+ const deviceKey = (_c = (_a2 = admissionRequest.device) == null ? void 0 : _a2.deviceKey) != null ? _c : (_b = admissionRequest.space) == null ? void 0 : _b.deviceKey;
1064
+ assert5(deviceKey);
1065
+ const admissionResponse = await protocol.admit(admissionRequest, guestProfile);
1066
+ success.wake(deviceKey);
1067
+ return admissionResponse;
1603
1068
  } catch (err) {
1604
- observable.callback.onError(err);
1069
+ stream.error(err);
1605
1070
  throw err;
1606
1071
  }
1607
1072
  },
1608
1073
  onOpen: () => {
1609
- scheduleTask2(ctx, async () => {
1610
- var _a2, _b;
1074
+ scheduleTask(ctx, async () => {
1611
1075
  try {
1612
- log6("connected", {
1613
- host: this._signingContext.deviceKey
1076
+ log4("connected", {
1077
+ ...protocol.toJSON()
1614
1078
  }, {
1615
- file: "space-invitations-handler.ts",
1616
- line: 195,
1079
+ file: "invitations-handler.ts",
1080
+ line: 191,
1617
1081
  scope: this,
1618
1082
  callSite: (f, a) => f(...a)
1619
1083
  });
1620
- (_b = (_a2 = observable.callback).onConnected) == null ? void 0 : _b.call(_a2, invitation);
1621
- const deviceKey = await complete.wait({
1084
+ stream.next({
1085
+ ...invitation,
1086
+ state: Invitation2.State.CONNECTED
1087
+ });
1088
+ const deviceKey = await success.wait({
1622
1089
  timeout
1623
1090
  });
1624
- log6("admitted guest", {
1625
- host: this._signingContext.deviceKey,
1626
- guest: deviceKey
1091
+ log4("admitted guest", {
1092
+ guest: deviceKey,
1093
+ ...protocol.toJSON()
1627
1094
  }, {
1628
- file: "space-invitations-handler.ts",
1629
- line: 198,
1095
+ file: "invitations-handler.ts",
1096
+ line: 194,
1630
1097
  scope: this,
1631
1098
  callSite: (f, a) => f(...a)
1632
1099
  });
1633
- observable.callback.onSuccess(invitation);
1100
+ stream.next({
1101
+ ...invitation,
1102
+ state: Invitation2.State.SUCCESS
1103
+ });
1634
1104
  } catch (err) {
1635
- if (!observable.cancelled) {
1636
- log6.error("failed", err, {
1637
- file: "space-invitations-handler.ts",
1638
- line: 202,
1105
+ if (err instanceof TimeoutError) {
1106
+ log4("timeout", {
1107
+ ...protocol.toJSON()
1108
+ }, {
1109
+ file: "invitations-handler.ts",
1110
+ line: 198,
1111
+ scope: this,
1112
+ callSite: (f, a) => f(...a)
1113
+ });
1114
+ stream.next({
1115
+ ...invitation,
1116
+ state: Invitation2.State.TIMEOUT
1117
+ });
1118
+ } else {
1119
+ log4.error("failed", err, {
1120
+ file: "invitations-handler.ts",
1121
+ line: 201,
1639
1122
  scope: this,
1640
1123
  callSite: (f, a) => f(...a)
1641
1124
  });
1642
- observable.callback.onError(err);
1125
+ stream.error(err);
1643
1126
  }
1644
1127
  } finally {
1645
- if (type !== Invitation3.Type.MULTIUSE_TESTING) {
1646
- await sleep2(ON_CLOSE_DELAY2);
1128
+ if (type !== Invitation2.Type.MULTIUSE) {
1129
+ await sleep(ON_CLOSE_DELAY);
1647
1130
  await ctx.dispose();
1648
1131
  }
1649
1132
  }
1650
1133
  });
1651
1134
  }
1652
1135
  });
1653
- return hostInvitationExtension;
1136
+ return extension;
1654
1137
  };
1655
- scheduleTask2(ctx, async () => {
1656
- var _a2, _b;
1138
+ scheduleTask(ctx, async () => {
1657
1139
  const topic = invitation.swarmKey;
1658
- const swarmConnection2 = await this._networkManager.joinSwarm({
1140
+ const swarmConnection = await this._networkManager.joinSwarm({
1659
1141
  topic,
1660
1142
  peerId: topic,
1661
- protocolProvider: createTeleportProtocolFactory2(async (teleport) => {
1143
+ protocolProvider: createTeleportProtocolFactory(async (teleport) => {
1662
1144
  teleport.addExtension("dxos.halo.invitations", createExtension());
1663
1145
  }),
1664
- topology: new StarTopology2(topic)
1146
+ topology: new StarTopology(topic)
1147
+ });
1148
+ ctx.onDispose(() => swarmConnection.close());
1149
+ stream.next({
1150
+ ...invitation,
1151
+ state: Invitation2.State.CONNECTING
1665
1152
  });
1666
- ctx.onDispose(() => swarmConnection2.close());
1667
- (_b = (_a2 = observable.callback).onConnecting) == null ? void 0 : _b.call(_a2, invitation);
1153
+ });
1154
+ const observable = new CancellableInvitationObservable({
1155
+ initialInvitation: invitation,
1156
+ subscriber: stream.observable,
1157
+ onCancel: async () => {
1158
+ stream.next({
1159
+ ...invitation,
1160
+ state: Invitation2.State.CANCELLED
1161
+ });
1162
+ await ctx.dispose();
1163
+ }
1668
1164
  });
1669
1165
  return observable;
1670
1166
  }
1671
- /**
1672
- * Waits for the host peer (inviter) to accept our join request.
1673
- * The local guest peer (invitee) then sends the local space invitation to the host,
1674
- * which then writes the guest's credentials to the space.
1675
- */
1676
- acceptInvitation(invitation, options) {
1677
- const { timeout = INVITATION_TIMEOUT2 } = options != null ? options : {};
1678
- const ctx = new Context4({
1167
+ acceptInvitation(protocol, invitation) {
1168
+ const { timeout = INVITATION_TIMEOUT } = invitation;
1169
+ assert5(protocol);
1170
+ const authenticated = new Trigger2();
1171
+ const stream = new PushStream();
1172
+ const ctx = new Context3({
1679
1173
  onError: (err) => {
1680
- void ctx.dispose();
1681
- observable.callback.onError(err);
1682
- }
1683
- });
1684
- const authenticated = new Trigger3();
1685
- const observable = new AuthenticatingInvitationProvider2({
1686
- onCancel: async () => {
1687
- await ctx.dispose();
1688
- },
1689
- onAuthenticate: async (code) => {
1690
- authenticated.wake(code);
1174
+ if (err instanceof TimeoutError) {
1175
+ log4("timeout", {
1176
+ ...protocol.toJSON()
1177
+ }, {
1178
+ file: "invitations-handler.ts",
1179
+ line: 255,
1180
+ scope: this,
1181
+ callSite: (f, a) => f(...a)
1182
+ });
1183
+ stream.next({
1184
+ ...invitation,
1185
+ state: Invitation2.State.TIMEOUT
1186
+ });
1187
+ } else {
1188
+ log4.warn("auth failed", err, {
1189
+ file: "invitations-handler.ts",
1190
+ line: 258,
1191
+ scope: this,
1192
+ callSite: (f, a) => f(...a)
1193
+ });
1194
+ stream.error(err);
1195
+ }
1196
+ void ctx.dispose();
1691
1197
  }
1692
1198
  });
1693
- let connectionCount = 0;
1694
- const complete = new Trigger3();
1199
+ ctx.onDispose(() => {
1200
+ log4("complete", {
1201
+ ...protocol.toJSON()
1202
+ }, {
1203
+ file: "invitations-handler.ts",
1204
+ line: 266,
1205
+ scope: this,
1206
+ callSite: (f, a) => f(...a)
1207
+ });
1208
+ stream.complete();
1209
+ });
1695
1210
  const createExtension = () => {
1696
- const extension = new GuestSpaceInvitationExtension({
1211
+ let connectionCount = 0;
1212
+ const extension = new InvitationGuestExtension({
1697
1213
  onOpen: () => {
1698
- scheduleTask2(ctx, async () => {
1699
- var _a, _b, _c, _d, _e, _f;
1214
+ scheduleTask(ctx, async () => {
1700
1215
  try {
1701
1216
  if (++connectionCount > 1) {
1702
1217
  throw new Error(`multiple connections detected: ${connectionCount}`);
1703
1218
  }
1704
- log6("connected", {
1705
- guest: this._signingContext.deviceKey
1219
+ scheduleTask(ctx, () => ctx.raise(new TimeoutError(timeout)), timeout);
1220
+ log4("connected", {
1221
+ ...protocol.toJSON()
1706
1222
  }, {
1707
- file: "space-invitations-handler.ts",
1708
- line: 275,
1223
+ file: "invitations-handler.ts",
1224
+ line: 284,
1709
1225
  scope: this,
1710
1226
  callSite: (f, a) => f(...a)
1711
1227
  });
1712
- (_b = (_a = observable.callback).onConnected) == null ? void 0 : _b.call(_a, invitation);
1713
- log6("introduce", {
1714
- guest: this._signingContext.deviceKey
1228
+ stream.next({
1229
+ ...invitation,
1230
+ state: Invitation2.State.CONNECTED
1231
+ });
1232
+ log4("introduce", {
1233
+ ...protocol.toJSON()
1715
1234
  }, {
1716
- file: "space-invitations-handler.ts",
1717
- line: 279,
1235
+ file: "invitations-handler.ts",
1236
+ line: 288,
1718
1237
  scope: this,
1719
1238
  callSite: (f, a) => f(...a)
1720
1239
  });
1721
- const introductionResponse = await extension.rpc.SpaceHostService.introduce({
1722
- profile: this._signingContext.profile
1723
- });
1724
- log6("introduce response", {
1725
- guest: this._signingContext.deviceKey,
1240
+ const introductionResponse = await extension.rpc.InvitationHostService.introduce(protocol.createIntroduction());
1241
+ log4("introduce response", {
1242
+ ...protocol.toJSON(),
1726
1243
  response: introductionResponse
1727
1244
  }, {
1728
- file: "space-invitations-handler.ts",
1729
- line: 283,
1245
+ file: "invitations-handler.ts",
1246
+ line: 292,
1730
1247
  scope: this,
1731
1248
  callSite: (f, a) => f(...a)
1732
1249
  });
@@ -1735,39 +1252,45 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler2 {
1735
1252
  invitation.spaceKey = introductionResponse.spaceKey;
1736
1253
  }
1737
1254
  if (isAuthenticationRequired(invitation)) {
1738
- (_d = (_c = observable.callback).onAuthenticating) == null ? void 0 : _d.call(_c, invitation);
1739
1255
  for (let attempt = 1; attempt <= MAX_OTP_ATTEMPTS; attempt++) {
1740
- log6("guest waiting for authentication code...", {}, {
1741
- file: "space-invitations-handler.ts",
1742
- line: 297,
1256
+ log4("guest waiting for authentication code...", {}, {
1257
+ file: "invitations-handler.ts",
1258
+ line: 301,
1743
1259
  scope: this,
1744
1260
  callSite: (f, a) => f(...a)
1745
1261
  });
1746
- (_f = (_e = observable.callback).onAuthenticating) == null ? void 0 : _f.call(_e, invitation);
1747
- const authenticationCode = await authenticated.wait({
1262
+ stream.next({
1263
+ ...invitation,
1264
+ state: Invitation2.State.READY_FOR_AUTHENTICATION
1265
+ });
1266
+ const authCode = await authenticated.wait({
1748
1267
  timeout
1749
1268
  });
1750
- log6("sending authentication request", {}, {
1751
- file: "space-invitations-handler.ts",
1752
- line: 301,
1269
+ log4("sending authentication request", {}, {
1270
+ file: "invitations-handler.ts",
1271
+ line: 305,
1753
1272
  scope: this,
1754
1273
  callSite: (f, a) => f(...a)
1755
1274
  });
1756
- const response = await extension.rpc.SpaceHostService.authenticate({
1757
- authenticationCode
1275
+ stream.next({
1276
+ ...invitation,
1277
+ state: Invitation2.State.AUTHENTICATING
1278
+ });
1279
+ const response = await extension.rpc.InvitationHostService.authenticate({
1280
+ authCode
1758
1281
  });
1759
- if (response.status === void 0 || response.status === AuthenticationResponse2.Status.OK) {
1282
+ if (response.status === void 0 || response.status === AuthenticationResponse.Status.OK) {
1760
1283
  break;
1761
1284
  }
1762
- if (response.status === AuthenticationResponse2.Status.INVALID_OTP) {
1285
+ if (response.status === AuthenticationResponse.Status.INVALID_OTP) {
1763
1286
  if (attempt === MAX_OTP_ATTEMPTS) {
1764
1287
  throw new Error(`Maximum retry attempts: ${MAX_OTP_ATTEMPTS}`);
1765
1288
  } else {
1766
- log6("retrying invalid code", {
1289
+ log4("retrying invalid code", {
1767
1290
  attempt
1768
1291
  }, {
1769
- file: "space-invitations-handler.ts",
1770
- line: 311,
1292
+ file: "invitations-handler.ts",
1293
+ line: 316,
1771
1294
  scope: this,
1772
1295
  callSite: (f, a) => f(...a)
1773
1296
  });
@@ -1775,52 +1298,58 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler2 {
1775
1298
  }
1776
1299
  }
1777
1300
  }
1301
+ } else {
1302
+ stream.next({
1303
+ ...invitation,
1304
+ state: Invitation2.State.READY_FOR_AUTHENTICATION
1305
+ });
1778
1306
  }
1779
- const controlFeedKey = await this._keyring.createKey();
1780
- const dataFeedKey = await this._keyring.createKey();
1781
- log6("request admission", {
1782
- guest: this._signingContext.deviceKey
1307
+ log4("request admission", {
1308
+ ...protocol.toJSON()
1783
1309
  }, {
1784
- file: "space-invitations-handler.ts",
1785
- line: 322,
1310
+ file: "invitations-handler.ts",
1311
+ line: 327,
1786
1312
  scope: this,
1787
1313
  callSite: (f, a) => f(...a)
1788
1314
  });
1789
- const { credential, controlTimeframe, dataTimeframe } = await extension.rpc.SpaceHostService.requestAdmission({
1790
- identityKey: this._signingContext.identityKey,
1791
- deviceKey: this._signingContext.deviceKey,
1792
- controlFeedKey,
1793
- dataFeedKey
1794
- });
1795
- const assertion = getCredentialAssertion(credential);
1796
- assert6(assertion["@type"] === "dxos.halo.credentials.SpaceMember", "Invalid credential");
1797
- assert6(credential.subject.id.equals(this._signingContext.identityKey));
1798
- const space = await this._spaceManager.acceptSpace({
1799
- spaceKey: assertion.spaceKey,
1800
- genesisFeedKey: assertion.genesisFeedKey,
1801
- controlTimeframe,
1802
- dataTimeframe
1803
- });
1804
- await this._signingContext.recordCredential(credential);
1805
- log6("admitted by host", {
1806
- guest: this._signingContext.deviceKey,
1807
- spaceKey: space.key
1315
+ const admissionRequest = await protocol.createAdmissionRequest();
1316
+ const admissionResponse = await extension.rpc.InvitationHostService.admit(admissionRequest);
1317
+ const result = await protocol.accept(admissionResponse, admissionRequest);
1318
+ log4("admitted by host", {
1319
+ ...protocol.toJSON()
1808
1320
  }, {
1809
- file: "space-invitations-handler.ts",
1810
- line: 347,
1321
+ file: "invitations-handler.ts",
1322
+ line: 335,
1811
1323
  scope: this,
1812
1324
  callSite: (f, a) => f(...a)
1813
1325
  });
1814
- complete.wake();
1326
+ stream.next({
1327
+ ...invitation,
1328
+ ...result,
1329
+ state: Invitation2.State.SUCCESS
1330
+ });
1815
1331
  } catch (err) {
1816
- if (!observable.cancelled) {
1817
- log6.warn("auth failed", err, {
1818
- file: "space-invitations-handler.ts",
1819
- line: 351,
1332
+ if (err instanceof TimeoutError) {
1333
+ log4("timeout", {
1334
+ ...protocol.toJSON()
1335
+ }, {
1336
+ file: "invitations-handler.ts",
1337
+ line: 339,
1338
+ scope: this,
1339
+ callSite: (f, a) => f(...a)
1340
+ });
1341
+ stream.next({
1342
+ ...invitation,
1343
+ state: Invitation2.State.TIMEOUT
1344
+ });
1345
+ } else {
1346
+ log4.warn("auth failed", err, {
1347
+ file: "invitations-handler.ts",
1348
+ line: 342,
1820
1349
  scope: this,
1821
1350
  callSite: (f, a) => f(...a)
1822
1351
  });
1823
- observable.callback.onError(err);
1352
+ stream.error(err);
1824
1353
  }
1825
1354
  } finally {
1826
1355
  await ctx.dispose();
@@ -1830,33 +1359,46 @@ var SpaceInvitationsHandler = class extends AbstractInvitationsHandler2 {
1830
1359
  });
1831
1360
  return extension;
1832
1361
  };
1833
- scheduleTask2(ctx, async () => {
1834
- var _a, _b;
1835
- assert6(invitation.swarmKey);
1362
+ scheduleTask(ctx, async () => {
1363
+ assert5(invitation.swarmKey);
1836
1364
  const topic = invitation.swarmKey;
1837
1365
  const swarmConnection = await this._networkManager.joinSwarm({
1838
1366
  topic,
1839
- peerId: PublicKey5.random(),
1840
- protocolProvider: createTeleportProtocolFactory2(async (teleport) => {
1367
+ peerId: PublicKey4.random(),
1368
+ protocolProvider: createTeleportProtocolFactory(async (teleport) => {
1841
1369
  teleport.addExtension("dxos.halo.invitations", createExtension());
1842
1370
  }),
1843
- topology: new StarTopology2(topic)
1371
+ topology: new StarTopology(topic)
1844
1372
  });
1845
1373
  ctx.onDispose(() => swarmConnection.close());
1846
- (_b = (_a = observable.callback).onConnecting) == null ? void 0 : _b.call(_a, invitation);
1847
- await complete.wait();
1848
- observable.callback.onSuccess(invitation);
1849
- await ctx.dispose();
1374
+ stream.next({
1375
+ ...invitation,
1376
+ state: Invitation2.State.CONNECTING
1377
+ });
1378
+ });
1379
+ const observable = new AuthenticatingInvitationObservable({
1380
+ initialInvitation: invitation,
1381
+ subscriber: stream.observable,
1382
+ onCancel: async () => {
1383
+ stream.next({
1384
+ ...invitation,
1385
+ state: Invitation2.State.CANCELLED
1386
+ });
1387
+ await ctx.dispose();
1388
+ },
1389
+ onAuthenticate: async (code) => {
1390
+ authenticated.wake(code);
1391
+ }
1850
1392
  });
1851
1393
  return observable;
1852
1394
  }
1853
1395
  };
1854
- var isAuthenticationRequired = (invitation) => invitation.authMethod !== AuthMethod.NONE && invitation.type !== Invitation3.Type.INTERACTIVE_TESTING && invitation.type !== Invitation3.Type.MULTIUSE_TESTING;
1855
- var HostSpaceInvitationExtension = class extends RpcExtension2 {
1396
+ var isAuthenticationRequired = (invitation) => invitation.authMethod !== Invitation2.AuthMethod.NONE;
1397
+ var InvitationHostExtension = class extends RpcExtension {
1856
1398
  constructor(_callbacks) {
1857
1399
  super({
1858
1400
  exposed: {
1859
- SpaceHostService: schema3.getService("dxos.halo.invitations.SpaceHostService")
1401
+ InvitationHostService: schema2.getService("dxos.halo.invitations.InvitationHostService")
1860
1402
  }
1861
1403
  });
1862
1404
  this._callbacks = _callbacks;
@@ -1865,15 +1407,15 @@ var HostSpaceInvitationExtension = class extends RpcExtension2 {
1865
1407
  return {
1866
1408
  // TODO(dmaretskyi): For now this is just forwarding the data to callbacks since we don't have session-specific logic.
1867
1409
  // Perhaps in the future we will have more complex logic here.
1868
- SpaceHostService: {
1869
- introduce: async (params) => {
1870
- return this._callbacks.introduce(params);
1410
+ InvitationHostService: {
1411
+ introduce: async (request) => {
1412
+ return this._callbacks.introduce(request);
1871
1413
  },
1872
- authenticate: async (credentials) => {
1873
- return this._callbacks.authenticate(credentials);
1414
+ authenticate: async (request) => {
1415
+ return this._callbacks.authenticate(request);
1874
1416
  },
1875
- requestAdmission: async (credentials) => {
1876
- return this._callbacks.requestAdmission(credentials);
1417
+ admit: async (request) => {
1418
+ return this._callbacks.admit(request);
1877
1419
  }
1878
1420
  }
1879
1421
  };
@@ -1883,11 +1425,11 @@ var HostSpaceInvitationExtension = class extends RpcExtension2 {
1883
1425
  this._callbacks.onOpen();
1884
1426
  }
1885
1427
  };
1886
- var GuestSpaceInvitationExtension = class extends RpcExtension2 {
1428
+ var InvitationGuestExtension = class extends RpcExtension {
1887
1429
  constructor(_callbacks) {
1888
1430
  super({
1889
1431
  requested: {
1890
- SpaceHostService: schema3.getService("dxos.halo.invitations.SpaceHostService")
1432
+ InvitationHostService: schema2.getService("dxos.halo.invitations.InvitationHostService")
1891
1433
  }
1892
1434
  });
1893
1435
  this._callbacks = _callbacks;
@@ -1901,21 +1443,333 @@ var GuestSpaceInvitationExtension = class extends RpcExtension2 {
1901
1443
  }
1902
1444
  };
1903
1445
 
1904
- // packages/sdk/client-services/src/packlets/invitations/space-invitations-service.ts
1446
+ // packages/sdk/client-services/src/packlets/invitations/invitations-service.ts
1447
+ import assert6 from "@dxos/node-std/assert";
1448
+ import { Stream as Stream7 } from "@dxos/codec-protobuf";
1449
+ import { log as log5 } from "@dxos/log";
1450
+ import { Invitation as Invitation3 } from "@dxos/protocols/proto/dxos/client/services";
1451
+ var InvitationsServiceImpl = class {
1452
+ constructor(_invitationsHandler, _getHandler) {
1453
+ this._invitationsHandler = _invitationsHandler;
1454
+ this._getHandler = _getHandler;
1455
+ this._createInvitations = /* @__PURE__ */ new Map();
1456
+ this._acceptInvitations = /* @__PURE__ */ new Map();
1457
+ }
1458
+ // TODO(burdon): Guest/host label.
1459
+ getLoggingContext() {
1460
+ return {};
1461
+ }
1462
+ createInvitation(invitation) {
1463
+ return new Stream7(({ next, close }) => {
1464
+ const handler = this._getHandler(invitation);
1465
+ log5("stream opened", this.getLoggingContext(), {
1466
+ file: "invitations-service.ts",
1467
+ line: 37,
1468
+ scope: this,
1469
+ callSite: (f, a) => f(...a)
1470
+ });
1471
+ let invitationId;
1472
+ const observable = this._invitationsHandler.createInvitation(handler, invitation);
1473
+ observable.subscribe((invitation2) => {
1474
+ switch (invitation2.state) {
1475
+ case Invitation3.State.CONNECTING: {
1476
+ assert6(invitation2.invitationId);
1477
+ invitationId = invitation2.invitationId;
1478
+ this._createInvitations.set(invitation2.invitationId, observable);
1479
+ invitation2.state = Invitation3.State.CONNECTING;
1480
+ next(invitation2);
1481
+ break;
1482
+ }
1483
+ case Invitation3.State.CONNECTED: {
1484
+ assert6(invitation2.invitationId);
1485
+ invitation2.state = Invitation3.State.CONNECTED;
1486
+ next(invitation2);
1487
+ break;
1488
+ }
1489
+ case Invitation3.State.READY_FOR_AUTHENTICATION: {
1490
+ assert6(invitation2.invitationId);
1491
+ invitation2.state = Invitation3.State.READY_FOR_AUTHENTICATION;
1492
+ next(invitation2);
1493
+ break;
1494
+ }
1495
+ case Invitation3.State.AUTHENTICATING: {
1496
+ assert6(invitation2.invitationId);
1497
+ invitation2.state = Invitation3.State.AUTHENTICATING;
1498
+ next(invitation2);
1499
+ break;
1500
+ }
1501
+ case Invitation3.State.SUCCESS: {
1502
+ assert6(invitation2.invitationId);
1503
+ invitation2.state = Invitation3.State.SUCCESS;
1504
+ next(invitation2);
1505
+ break;
1506
+ }
1507
+ case Invitation3.State.CANCELLED: {
1508
+ assert6(invitationId);
1509
+ invitation2.invitationId = invitationId;
1510
+ invitation2.state = Invitation3.State.CANCELLED;
1511
+ next(invitation2);
1512
+ break;
1513
+ }
1514
+ case Invitation3.State.TIMEOUT: {
1515
+ assert6(invitationId);
1516
+ invitation2.invitationId = invitationId;
1517
+ invitation2.state = Invitation3.State.TIMEOUT;
1518
+ next(invitation2);
1519
+ break;
1520
+ }
1521
+ }
1522
+ }, (err) => {
1523
+ close(err);
1524
+ }, () => {
1525
+ close();
1526
+ });
1527
+ return (err) => {
1528
+ const context = this.getLoggingContext();
1529
+ if (err) {
1530
+ log5.warn("stream closed", {
1531
+ ...context,
1532
+ err
1533
+ }, {
1534
+ file: "invitations-service.ts",
1535
+ line: 103,
1536
+ scope: this,
1537
+ callSite: (f, a) => f(...a)
1538
+ });
1539
+ } else {
1540
+ log5("stream closed", context, {
1541
+ file: "invitations-service.ts",
1542
+ line: 105,
1543
+ scope: this,
1544
+ callSite: (f, a) => f(...a)
1545
+ });
1546
+ }
1547
+ this._createInvitations.delete(invitation.invitationId);
1548
+ };
1549
+ });
1550
+ }
1551
+ acceptInvitation(invitation) {
1552
+ return new Stream7(({ next, close }) => {
1553
+ log5("stream opened", this.getLoggingContext(), {
1554
+ file: "invitations-service.ts",
1555
+ line: 115,
1556
+ scope: this,
1557
+ callSite: (f, a) => f(...a)
1558
+ });
1559
+ const handler = this._getHandler(invitation);
1560
+ let invitationId;
1561
+ const observable = this._invitationsHandler.acceptInvitation(handler, invitation);
1562
+ observable.subscribe((invitation2) => {
1563
+ switch (invitation2.state) {
1564
+ case Invitation3.State.CONNECTING: {
1565
+ assert6(invitation2.invitationId);
1566
+ invitationId = invitation2.invitationId;
1567
+ this._acceptInvitations.set(invitation2.invitationId, observable);
1568
+ invitation2.state = Invitation3.State.CONNECTING;
1569
+ next(invitation2);
1570
+ break;
1571
+ }
1572
+ case Invitation3.State.CONNECTED: {
1573
+ assert6(invitation2.invitationId);
1574
+ invitation2.state = Invitation3.State.CONNECTED;
1575
+ next(invitation2);
1576
+ break;
1577
+ }
1578
+ case Invitation3.State.READY_FOR_AUTHENTICATION: {
1579
+ assert6(invitation2.invitationId);
1580
+ invitation2.state = Invitation3.State.READY_FOR_AUTHENTICATION;
1581
+ next(invitation2);
1582
+ break;
1583
+ }
1584
+ case Invitation3.State.AUTHENTICATING: {
1585
+ assert6(invitation2.invitationId);
1586
+ invitation2.state = Invitation3.State.AUTHENTICATING;
1587
+ next(invitation2);
1588
+ break;
1589
+ }
1590
+ case Invitation3.State.SUCCESS: {
1591
+ invitation2.state = Invitation3.State.SUCCESS;
1592
+ next(invitation2);
1593
+ break;
1594
+ }
1595
+ case Invitation3.State.CANCELLED: {
1596
+ assert6(invitationId);
1597
+ invitation2.invitationId = invitationId;
1598
+ invitation2.state = Invitation3.State.CANCELLED;
1599
+ next(invitation2);
1600
+ break;
1601
+ }
1602
+ case Invitation3.State.TIMEOUT: {
1603
+ assert6(invitationId);
1604
+ invitation2.invitationId = invitationId;
1605
+ invitation2.state = Invitation3.State.TIMEOUT;
1606
+ next(invitation2);
1607
+ break;
1608
+ }
1609
+ }
1610
+ }, (err) => {
1611
+ close(err);
1612
+ }, () => {
1613
+ close();
1614
+ });
1615
+ return (err) => {
1616
+ const context = this.getLoggingContext();
1617
+ if (err) {
1618
+ log5.warn("stream closed", {
1619
+ ...context,
1620
+ err
1621
+ }, {
1622
+ file: "invitations-service.ts",
1623
+ line: 181,
1624
+ scope: this,
1625
+ callSite: (f, a) => f(...a)
1626
+ });
1627
+ } else {
1628
+ log5("stream closed", context, {
1629
+ file: "invitations-service.ts",
1630
+ line: 183,
1631
+ scope: this,
1632
+ callSite: (f, a) => f(...a)
1633
+ });
1634
+ }
1635
+ this._acceptInvitations.delete(invitation.invitationId);
1636
+ };
1637
+ });
1638
+ }
1639
+ async authenticate({ invitationId, authCode }) {
1640
+ log5("authenticating...", {}, {
1641
+ file: "invitations-service.ts",
1642
+ line: 192,
1643
+ scope: this,
1644
+ callSite: (f, a) => f(...a)
1645
+ });
1646
+ assert6(invitationId);
1647
+ const observable = this._acceptInvitations.get(invitationId);
1648
+ if (!observable) {
1649
+ log5.warn("invalid invitation", {
1650
+ invitationId
1651
+ }, {
1652
+ file: "invitations-service.ts",
1653
+ line: 196,
1654
+ scope: this,
1655
+ callSite: (f, a) => f(...a)
1656
+ });
1657
+ } else {
1658
+ await observable.authenticate(authCode);
1659
+ }
1660
+ }
1661
+ async cancelInvitation({ invitationId }) {
1662
+ var _a;
1663
+ log5("cancelling...", {}, {
1664
+ file: "invitations-service.ts",
1665
+ line: 203,
1666
+ scope: this,
1667
+ callSite: (f, a) => f(...a)
1668
+ });
1669
+ assert6(invitationId);
1670
+ const observable = (_a = this._createInvitations.get(invitationId)) != null ? _a : this._acceptInvitations.get(invitationId);
1671
+ if (!observable) {
1672
+ log5.warn("invalid invitation", {
1673
+ invitationId
1674
+ }, {
1675
+ file: "invitations-service.ts",
1676
+ line: 207,
1677
+ scope: this,
1678
+ callSite: (f, a) => f(...a)
1679
+ });
1680
+ } else {
1681
+ await (observable == null ? void 0 : observable.cancel());
1682
+ }
1683
+ }
1684
+ };
1685
+
1686
+ // packages/sdk/client-services/src/packlets/invitations/space-invitation-protocol.ts
1905
1687
  import assert7 from "@dxos/node-std/assert";
1906
- var SpaceInvitationsServiceImpl = class extends AbstractInvitationsService {
1907
- // prettier-ignore
1908
- constructor(identityManager, invitationsHandler, _getSpaceManager) {
1909
- super(identityManager, invitationsHandler);
1910
- this.invitationsHandler = invitationsHandler;
1911
- this._getSpaceManager = _getSpaceManager;
1912
- }
1913
- getContext(invitation) {
1914
- assert7(invitation.spaceKey);
1915
- const spaceManager = this._getSpaceManager();
1916
- const space = spaceManager.spaces.get(invitation.spaceKey);
1688
+ import { createAdmissionCredentials, getCredentialAssertion } from "@dxos/credentials";
1689
+ import { writeMessages as writeMessages2 } from "@dxos/feed-store";
1690
+ import { log as log6 } from "@dxos/log";
1691
+ import { Invitation as Invitation4 } from "@dxos/protocols/proto/dxos/client/services";
1692
+ var SpaceInvitationProtocol = class {
1693
+ constructor(_spaceManager, _signingContext, _keyring, _spaceKey) {
1694
+ this._spaceManager = _spaceManager;
1695
+ this._signingContext = _signingContext;
1696
+ this._keyring = _keyring;
1697
+ this._spaceKey = _spaceKey;
1698
+ }
1699
+ toJSON() {
1700
+ return {
1701
+ deviceKey: this._signingContext.deviceKey,
1702
+ spaceKey: this._spaceKey
1703
+ };
1704
+ }
1705
+ getInvitationContext() {
1706
+ return {
1707
+ kind: Invitation4.Kind.SPACE,
1708
+ spaceKey: this._spaceKey
1709
+ };
1710
+ }
1711
+ async admit(request, guestProfile) {
1712
+ var _a;
1713
+ assert7(this._spaceKey);
1714
+ const space = await this._spaceManager.spaces.get(this._spaceKey);
1917
1715
  assert7(space);
1918
- return space;
1716
+ assert7(request.space);
1717
+ const { identityKey, deviceKey } = request.space;
1718
+ log6("writing guest credentials", {
1719
+ host: this._signingContext.deviceKey,
1720
+ guest: deviceKey
1721
+ }, {
1722
+ file: "space-invitation-protocol.ts",
1723
+ line: 51,
1724
+ scope: this,
1725
+ callSite: (f, a) => f(...a)
1726
+ });
1727
+ const credentials = await createAdmissionCredentials(this._signingContext.credentialSigner, identityKey, space.key, space.inner.genesisFeedKey, guestProfile);
1728
+ assert7(credentials[0].credential);
1729
+ const spaceMemberCredential = credentials[0].credential.credential;
1730
+ assert7(getCredentialAssertion(spaceMemberCredential)["@type"] === "dxos.halo.credentials.SpaceMember");
1731
+ await writeMessages2(space.inner.controlPipeline.writer, credentials);
1732
+ return {
1733
+ space: {
1734
+ credential: spaceMemberCredential,
1735
+ controlTimeframe: space.inner.controlPipeline.state.timeframe,
1736
+ dataTimeframe: (_a = space.dataPipeline.pipelineState) == null ? void 0 : _a.timeframe
1737
+ }
1738
+ };
1739
+ }
1740
+ createIntroduction() {
1741
+ return {
1742
+ profile: this._signingContext.profile
1743
+ };
1744
+ }
1745
+ async createAdmissionRequest() {
1746
+ const controlFeedKey = await this._keyring.createKey();
1747
+ const dataFeedKey = await this._keyring.createKey();
1748
+ return {
1749
+ space: {
1750
+ identityKey: this._signingContext.identityKey,
1751
+ deviceKey: this._signingContext.deviceKey,
1752
+ controlFeedKey,
1753
+ dataFeedKey
1754
+ }
1755
+ };
1756
+ }
1757
+ async accept(response) {
1758
+ assert7(response.space);
1759
+ const { credential, controlTimeframe, dataTimeframe } = response.space;
1760
+ const assertion = getCredentialAssertion(credential);
1761
+ assert7(assertion["@type"] === "dxos.halo.credentials.SpaceMember", "Invalid credential");
1762
+ assert7(credential.subject.id.equals(this._signingContext.identityKey));
1763
+ await this._spaceManager.acceptSpace({
1764
+ spaceKey: assertion.spaceKey,
1765
+ genesisFeedKey: assertion.genesisFeedKey,
1766
+ controlTimeframe,
1767
+ dataTimeframe
1768
+ });
1769
+ await this._signingContext.recordCredential(credential);
1770
+ return {
1771
+ spaceKey: assertion.spaceKey
1772
+ };
1919
1773
  }
1920
1774
  };
1921
1775
 
@@ -2054,17 +1908,16 @@ var MemoryShellRuntime = class {
2054
1908
  };
2055
1909
 
2056
1910
  // packages/sdk/client-services/src/packlets/vault/iframe-host-runtime.ts
2057
- import { Trigger as Trigger9 } from "@dxos/async";
1911
+ import { Trigger as Trigger8 } from "@dxos/async";
2058
1912
  import { log as log17, logInfo as logInfo3 } from "@dxos/log";
2059
1913
  import { MemorySignalManager as MemorySignalManager3, MemorySignalManagerContext as MemorySignalManagerContext3, WebsocketSignalManager as WebsocketSignalManager3 } from "@dxos/messaging";
2060
1914
  import { createWebRTCTransportFactory as createWebRTCTransportFactory2, NetworkManager as NetworkManager3 } from "@dxos/network-manager";
2061
1915
  import { getAsyncValue } from "@dxos/util";
2062
1916
 
2063
1917
  // packages/sdk/client-services/src/packlets/services/service-host.ts
2064
- import assert12 from "@dxos/node-std/assert";
1918
+ import assert13 from "@dxos/node-std/assert";
2065
1919
  import { Event as Event7 } from "@dxos/async";
2066
- import { clientServiceBundle, createDefaultModelFactory, PublicKey as PublicKey10 } from "@dxos/client";
2067
- import { raise as raise3 } from "@dxos/debug";
1920
+ import { clientServiceBundle, createDefaultModelFactory, PublicKey as PublicKey9 } from "@dxos/client";
2068
1921
  import { DataServiceImpl } from "@dxos/echo-pipeline";
2069
1922
  import { log as log15 } from "@dxos/log";
2070
1923
  import { trace as trace3 } from "@dxos/protocols";
@@ -2156,45 +2009,45 @@ var NetworkServiceImpl = class {
2156
2009
  import assert10 from "@dxos/node-std/assert";
2157
2010
  import { Event as Event6, synchronized, trackLeaks as trackLeaks2 } from "@dxos/async";
2158
2011
  import { SpaceState as SpaceState2 } from "@dxos/client";
2159
- import { cancelWithContext, Context as Context7 } from "@dxos/context";
2012
+ import { cancelWithContext, Context as Context6 } from "@dxos/context";
2160
2013
  import { getCredentialAssertion as getCredentialAssertion2 } from "@dxos/credentials";
2161
2014
  import { SnapshotManager, spaceGenesis } from "@dxos/echo-pipeline";
2162
- import { PublicKey as PublicKey8 } from "@dxos/keys";
2015
+ import { PublicKey as PublicKey7 } from "@dxos/keys";
2163
2016
  import { log as log9 } from "@dxos/log";
2164
2017
  import { Gossip, Presence } from "@dxos/teleport-extension-gossip";
2165
2018
  import { ComplexMap as ComplexMap3, deferFunction as deferFunction2 } from "@dxos/util";
2166
2019
 
2167
2020
  // packages/sdk/client-services/src/packlets/spaces/data-space.ts
2168
- import { Event as Event5, scheduleTask as scheduleTask4, trackLeaks } from "@dxos/async";
2021
+ import { Event as Event5, scheduleTask as scheduleTask3, trackLeaks } from "@dxos/async";
2169
2022
  import { SpaceState } from "@dxos/client";
2170
- import { Context as Context6 } from "@dxos/context";
2023
+ import { Context as Context5 } from "@dxos/context";
2171
2024
  import { timed } from "@dxos/debug";
2172
2025
  import { createMappedFeedWriter, DataPipeline } from "@dxos/echo-pipeline";
2173
2026
  import { CancelledError, SystemError } from "@dxos/errors";
2174
- import { PublicKey as PublicKey7 } from "@dxos/keys";
2027
+ import { PublicKey as PublicKey6 } from "@dxos/keys";
2175
2028
  import { log as log8 } from "@dxos/log";
2176
2029
  import { AdmittedFeed as AdmittedFeed3 } from "@dxos/protocols/proto/dxos/halo/credentials";
2177
2030
  import { ComplexSet as ComplexSet2 } from "@dxos/util";
2178
2031
 
2179
2032
  // packages/sdk/client-services/src/packlets/spaces/notarization-plugin.ts
2180
2033
  import assert9 from "@dxos/node-std/assert";
2181
- import { DeferredTask, Event as Event4, scheduleTask as scheduleTask3, sleep as sleep3, TimeoutError, Trigger as Trigger4 } from "@dxos/async";
2182
- import { Context as Context5, rejectOnDispose } from "@dxos/context";
2183
- import { PublicKey as PublicKey6 } from "@dxos/keys";
2034
+ import { DeferredTask, Event as Event4, scheduleTask as scheduleTask2, sleep as sleep2, TimeoutError as TimeoutError2, Trigger as Trigger3 } from "@dxos/async";
2035
+ import { Context as Context4, rejectOnDispose } from "@dxos/context";
2036
+ import { PublicKey as PublicKey5 } from "@dxos/keys";
2184
2037
  import { log as log7 } from "@dxos/log";
2185
- import { schema as schema4 } from "@dxos/protocols";
2186
- import { RpcExtension as RpcExtension3 } from "@dxos/teleport";
2038
+ import { schema as schema3 } from "@dxos/protocols";
2039
+ import { RpcExtension as RpcExtension2 } from "@dxos/teleport";
2187
2040
  import { ComplexMap as ComplexMap2, ComplexSet, entry } from "@dxos/util";
2188
2041
  var DEFAULT_RETRY_TIMEOUT = 1e3;
2189
2042
  var DEFAULT_SUCCESS_DELAY = 1e3;
2190
2043
  var DEFAULT_NOTARIZE_TIMEOUT = 1e4;
2191
2044
  var NotarizationPlugin = class {
2192
2045
  constructor() {
2193
- this._ctx = new Context5();
2046
+ this._ctx = new Context4();
2194
2047
  this._extensionOpened = new Event4();
2195
2048
  this._extensions = /* @__PURE__ */ new Set();
2196
- this._processedCredentials = new ComplexSet(PublicKey6.hash);
2197
- this._processCredentialsTriggers = new ComplexMap2(PublicKey6.hash);
2049
+ this._processedCredentials = new ComplexSet(PublicKey5.hash);
2050
+ this._processCredentialsTriggers = new ComplexMap2(PublicKey5.hash);
2198
2051
  }
2199
2052
  async open() {
2200
2053
  }
@@ -2214,7 +2067,7 @@ var NotarizationPlugin = class {
2214
2067
  callSite: (f, a) => f(...a)
2215
2068
  });
2216
2069
  assert9(credentials.every((credential) => credential.id), "Credentials must have an id");
2217
- const errors = new Trigger4();
2070
+ const errors = new Trigger3();
2218
2071
  const ctx = this._ctx.derive({
2219
2072
  onError: (err) => {
2220
2073
  log7.warn("Notarization error", {
@@ -2231,7 +2084,7 @@ var NotarizationPlugin = class {
2231
2084
  });
2232
2085
  opCtx == null ? void 0 : opCtx.onDispose(() => ctx.dispose());
2233
2086
  if (timeout !== 0) {
2234
- scheduleTask3(ctx, () => {
2087
+ scheduleTask2(ctx, () => {
2235
2088
  log7.warn("Notarization timeout", {
2236
2089
  timeout,
2237
2090
  peers: Array.from(this._extensions).map((extension) => extension.remotePeerId)
@@ -2242,7 +2095,7 @@ var NotarizationPlugin = class {
2242
2095
  callSite: (f, a) => f(...a)
2243
2096
  });
2244
2097
  void ctx.dispose();
2245
- errors.throw(new TimeoutError(timeout, "Notarization timed out"));
2098
+ errors.throw(new TimeoutError2(timeout, "Notarization timed out"));
2246
2099
  }, timeout);
2247
2100
  }
2248
2101
  const allNotarized = Promise.all(credentials.map((credential) => this._waitUntilProcessed(credential.id)));
@@ -2265,7 +2118,7 @@ var NotarizationPlugin = class {
2265
2118
  callSite: (f, a) => f(...a)
2266
2119
  });
2267
2120
  peersTried.clear();
2268
- scheduleTask3(ctx, () => notarizeTask.schedule(), retryTimeout);
2121
+ scheduleTask2(ctx, () => notarizeTask.schedule(), retryTimeout);
2269
2122
  return;
2270
2123
  }
2271
2124
  peersTried.add(peer);
@@ -2287,7 +2140,7 @@ var NotarizationPlugin = class {
2287
2140
  scope: this,
2288
2141
  callSite: (f, a) => f(...a)
2289
2142
  });
2290
- await sleep3(successDelay);
2143
+ await sleep2(successDelay);
2291
2144
  } catch (err) {
2292
2145
  log7.warn("error notarizing (recoverable)", err, {
2293
2146
  file: "notarization-plugin.ts",
@@ -2336,7 +2189,7 @@ var NotarizationPlugin = class {
2336
2189
  if (this._processedCredentials.has(id)) {
2337
2190
  return;
2338
2191
  }
2339
- await entry(this._processCredentialsTriggers, id).orInsert(new Trigger4()).value.wait();
2192
+ await entry(this._processCredentialsTriggers, id).orInsert(new Trigger3()).value.wait();
2340
2193
  }
2341
2194
  /**
2342
2195
  * Requests from other peers to notarize credentials.
@@ -2384,14 +2237,14 @@ var NotarizationPlugin = class {
2384
2237
  return extension;
2385
2238
  }
2386
2239
  };
2387
- var NotarizationTeleportExtension = class extends RpcExtension3 {
2240
+ var NotarizationTeleportExtension = class extends RpcExtension2 {
2388
2241
  constructor(_params) {
2389
2242
  super({
2390
2243
  requested: {
2391
- NotarizationService: schema4.getService("dxos.mesh.teleport.notarization.NotarizationService")
2244
+ NotarizationService: schema3.getService("dxos.mesh.teleport.notarization.NotarizationService")
2392
2245
  },
2393
2246
  exposed: {
2394
- NotarizationService: schema4.getService("dxos.mesh.teleport.notarization.NotarizationService")
2247
+ NotarizationService: schema3.getService("dxos.mesh.teleport.notarization.NotarizationService")
2395
2248
  }
2396
2249
  });
2397
2250
  this._params = _params;
@@ -2429,7 +2282,7 @@ var __decorate = function(decorators, target, key, desc) {
2429
2282
  var AUTH_TIMEOUT2 = 3e4;
2430
2283
  var DataSpace = class DataSpace2 {
2431
2284
  constructor(params) {
2432
- this._ctx = new Context6();
2285
+ this._ctx = new Context5();
2433
2286
  this._state = SpaceState.CLOSED;
2434
2287
  this.stateUpdate = new Event5();
2435
2288
  var _a;
@@ -2452,7 +2305,7 @@ var DataSpace = class DataSpace2 {
2452
2305
  snapshotId: params.snapshotId
2453
2306
  });
2454
2307
  this.authVerifier = new TrustedKeySetAuthVerifier({
2455
- trustedKeysProvider: () => new ComplexSet2(PublicKey7.hash, Array.from(this._inner.spaceState.members.keys())),
2308
+ trustedKeysProvider: () => new ComplexSet2(PublicKey6.hash, Array.from(this._inner.spaceState.members.keys())),
2456
2309
  update: this._inner.stateUpdate,
2457
2310
  authTimeout: AUTH_TIMEOUT2
2458
2311
  });
@@ -2506,7 +2359,7 @@ var DataSpace = class DataSpace2 {
2506
2359
  * Initialize the data pipeline in a separate task.
2507
2360
  */
2508
2361
  initializeDataPipelineAsync() {
2509
- scheduleTask4(this._ctx, async () => {
2362
+ scheduleTask3(this._ctx, async () => {
2510
2363
  try {
2511
2364
  await this.initializeDataPipeline();
2512
2365
  } catch (err) {
@@ -2653,9 +2506,9 @@ var DataSpaceManager = class DataSpaceManager2 {
2653
2506
  this._modelFactory = _modelFactory;
2654
2507
  this._feedStore = _feedStore;
2655
2508
  this._snapshotStore = _snapshotStore;
2656
- this._ctx = new Context7();
2509
+ this._ctx = new Context6();
2657
2510
  this.updated = new Event6();
2658
- this._spaces = new ComplexMap3(PublicKey8.hash);
2511
+ this._spaces = new ComplexMap3(PublicKey7.hash);
2659
2512
  this._isOpen = false;
2660
2513
  }
2661
2514
  // TODO(burdon): Remove.
@@ -2883,7 +2736,7 @@ DataSpaceManager = __decorate2([
2883
2736
  ], DataSpaceManager);
2884
2737
 
2885
2738
  // packages/sdk/client-services/src/packlets/spaces/spaces-service.ts
2886
- import { EventSubscriptions as EventSubscriptions3, scheduleTask as scheduleTask5 } from "@dxos/async";
2739
+ import { EventSubscriptions as EventSubscriptions3, scheduleTask as scheduleTask4 } from "@dxos/async";
2887
2740
  import { Stream as Stream10 } from "@dxos/codec-protobuf";
2888
2741
  import { raise, todo as todo2 } from "@dxos/debug";
2889
2742
  import { SpaceNotFoundError } from "@dxos/echo-pipeline";
@@ -2926,7 +2779,7 @@ var SpacesServiceImpl = class {
2926
2779
  spaces
2927
2780
  });
2928
2781
  };
2929
- scheduleTask5(ctx, async () => {
2782
+ scheduleTask4(ctx, async () => {
2930
2783
  const dataSpaceManager = await this._getDataSpaceManager();
2931
2784
  const subscriptions = new EventSubscriptions3();
2932
2785
  ctx.onDispose(() => subscriptions.clear());
@@ -2963,7 +2816,7 @@ var SpacesServiceImpl = class {
2963
2816
  }
2964
2817
  subscribeMessages({ spaceKey, channel }) {
2965
2818
  return new Stream10(({ ctx, next }) => {
2966
- scheduleTask5(ctx, async () => {
2819
+ scheduleTask4(ctx, async () => {
2967
2820
  var _a;
2968
2821
  const dataSpaceManager = await this._getDataSpaceManager();
2969
2822
  const space = (_a = dataSpaceManager.spaces.get(spaceKey)) != null ? _a : raise(new SpaceNotFoundError(spaceKey));
@@ -2984,7 +2837,7 @@ var SpacesServiceImpl = class {
2984
2837
  }
2985
2838
  });
2986
2839
  ctx.onDispose(() => processor.close());
2987
- scheduleTask5(ctx, () => processor.open());
2840
+ scheduleTask4(ctx, () => processor.open());
2988
2841
  });
2989
2842
  }
2990
2843
  async writeCredentials({ spaceKey, credentials }) {
@@ -2999,18 +2852,22 @@ var SpacesServiceImpl = class {
2999
2852
  }
3000
2853
  }
3001
2854
  _transformSpace(space) {
3002
- var _a, _b;
2855
+ var _a, _b, _c, _d, _e;
3003
2856
  return {
3004
2857
  spaceKey: space.key,
3005
2858
  state: space.state,
3006
2859
  pipeline: {
3007
- targetControlTimeframe: space.inner.controlPipeline.state.targetTimeframe,
2860
+ controlFeeds: space.inner.controlPipeline.state.feeds.map((feed) => feed.key),
3008
2861
  currentControlTimeframe: space.inner.controlPipeline.state.timeframe,
3009
- currentDataTimeframe: (_a = space.dataPipeline.pipelineState) == null ? void 0 : _a.timeframe,
3010
- targetDataTimeframe: (_b = space.dataPipeline.pipelineState) == null ? void 0 : _b.targetTimeframe
2862
+ targetControlTimeframe: space.inner.controlPipeline.state.targetTimeframe,
2863
+ totalControlTimeframe: space.inner.controlPipeline.state.endTimeframe,
2864
+ dataFeeds: (_b = (_a = space.dataPipeline.pipelineState) == null ? void 0 : _a.feeds.map((feed) => feed.key)) != null ? _b : [],
2865
+ currentDataTimeframe: (_c = space.dataPipeline.pipelineState) == null ? void 0 : _c.timeframe,
2866
+ targetDataTimeframe: (_d = space.dataPipeline.pipelineState) == null ? void 0 : _d.targetTimeframe,
2867
+ totalDataTimeframe: (_e = space.dataPipeline.pipelineState) == null ? void 0 : _e.endTimeframe
3011
2868
  },
3012
2869
  members: Array.from(space.inner.spaceState.members.values()).map((member) => {
3013
- var _a2, _b2, _c;
2870
+ var _a2, _b2, _c2;
3014
2871
  return {
3015
2872
  identity: {
3016
2873
  identityKey: member.key,
@@ -3018,7 +2875,7 @@ var SpacesServiceImpl = class {
3018
2875
  displayName: (_b2 = (_a2 = member.assertion.profile) == null ? void 0 : _a2.displayName) != null ? _b2 : humanize(member.key)
3019
2876
  }
3020
2877
  },
3021
- presence: ((_c = this._identityManager.identity) == null ? void 0 : _c.identityKey.equals(member.key)) || space.presence.getPeersOnline().filter(({ identityKey }) => identityKey.equals(member.key)).length > 0 ? SpaceMember.PresenceState.ONLINE : SpaceMember.PresenceState.OFFLINE
2878
+ presence: ((_c2 = this._identityManager.identity) == null ? void 0 : _c2.identityKey.equals(member.key)) || space.presence.getPeersOnline().filter(({ identityKey }) => identityKey.equals(member.key)).length > 0 ? SpaceMember.PresenceState.ONLINE : SpaceMember.PresenceState.OFFLINE
3022
2879
  };
3023
2880
  })
3024
2881
  };
@@ -3114,7 +2971,7 @@ var IFrameProxyRuntime = class {
3114
2971
  };
3115
2972
 
3116
2973
  // packages/sdk/client-services/src/packlets/vault/vault-resource-lock.ts
3117
- import { asyncTimeout, Trigger as Trigger5 } from "@dxos/async";
2974
+ import { asyncTimeout, Trigger as Trigger4 } from "@dxos/async";
3118
2975
  import { log as log11, logInfo } from "@dxos/log";
3119
2976
  var __decorate3 = function(decorators, target, key, desc) {
3120
2977
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -3133,7 +2990,7 @@ var Message;
3133
2990
  var VaultResourceLock = class {
3134
2991
  constructor({ lockKey, onAcquire, onRelease }) {
3135
2992
  this._broadcastChannel = new BroadcastChannel("vault-resource-lock");
3136
- this._releaseTrigger = new Trigger5();
2993
+ this._releaseTrigger = new Trigger4();
3137
2994
  this._lockKey = lockKey;
3138
2995
  this._onAcquire = onAcquire;
3139
2996
  this._onRelease = onRelease;
@@ -3193,14 +3050,14 @@ var VaultResourceLock = class {
3193
3050
  scope: this,
3194
3051
  callSite: (f, a) => f(...a)
3195
3052
  });
3196
- const acquired = new Trigger5();
3053
+ const acquired = new Trigger4();
3197
3054
  void navigator.locks.request(this._lockKey, {
3198
3055
  steal
3199
3056
  }, async () => {
3200
3057
  var _a, _b;
3201
3058
  await ((_a = this._onAcquire) == null ? void 0 : _a.call(this));
3202
3059
  acquired.wake();
3203
- this._releaseTrigger = new Trigger5();
3060
+ this._releaseTrigger = new Trigger4();
3204
3061
  await this._releaseTrigger.wait();
3205
3062
  log11("releasing lock...", {}, {
3206
3063
  file: "vault-resource-lock.ts",
@@ -3235,14 +3092,14 @@ __decorate3([
3235
3092
  ], VaultResourceLock.prototype, "lockKey", null);
3236
3093
 
3237
3094
  // packages/sdk/client-services/src/packlets/vault/worker-runtime.ts
3238
- import { Trigger as Trigger7 } from "@dxos/async";
3095
+ import { Trigger as Trigger6 } from "@dxos/async";
3239
3096
  import { log as log13 } from "@dxos/log";
3240
3097
  import { MemorySignalManager, MemorySignalManagerContext, WebsocketSignalManager } from "@dxos/messaging";
3241
3098
  import { NetworkManager, WebRTCTransportProxyFactory } from "@dxos/network-manager";
3242
3099
 
3243
3100
  // packages/sdk/client-services/src/packlets/vault/worker-session.ts
3244
3101
  import assert11 from "@dxos/node-std/assert";
3245
- import { asyncTimeout as asyncTimeout2, Trigger as Trigger6 } from "@dxos/async";
3102
+ import { asyncTimeout as asyncTimeout2, Trigger as Trigger5 } from "@dxos/async";
3246
3103
  import { iframeServiceBundle as iframeServiceBundle2, workerServiceBundle as workerServiceBundle2 } from "@dxos/client";
3247
3104
  import { log as log12, logInfo as logInfo2 } from "@dxos/log";
3248
3105
  import { createProtoRpcPeer as createProtoRpcPeer3 } from "@dxos/rpc";
@@ -3316,7 +3173,7 @@ var WorkerSession = class {
3316
3173
  constructor({ serviceHost, systemPort, appPort, shellPort, readySignal, options = {
3317
3174
  heartbeatInterval: 1e3
3318
3175
  } }) {
3319
- this._startTrigger = new Trigger6();
3176
+ this._startTrigger = new Trigger5();
3320
3177
  this.onClose = new Callback();
3321
3178
  assert11(options);
3322
3179
  assert11(serviceHost);
@@ -3471,14 +3328,17 @@ var WorkerRuntime = class {
3471
3328
  constructor(_configProvider) {
3472
3329
  this._configProvider = _configProvider;
3473
3330
  this._transportFactory = new WebRTCTransportProxyFactory();
3474
- this._ready = new Trigger7();
3331
+ this._ready = new Trigger6();
3475
3332
  this.sessions = /* @__PURE__ */ new Set();
3476
3333
  this._clientServices = new ClientServicesHost();
3477
3334
  }
3335
+ get host() {
3336
+ return this._clientServices;
3337
+ }
3478
3338
  async start() {
3479
3339
  log13("starting...", {}, {
3480
3340
  file: "worker-runtime.ts",
3481
- line: 44,
3341
+ line: 48,
3482
3342
  scope: this,
3483
3343
  callSite: (f, a) => f(...a)
3484
3344
  });
@@ -3499,7 +3359,7 @@ var WorkerRuntime = class {
3499
3359
  this._ready.wake(void 0);
3500
3360
  log13("started", {}, {
3501
3361
  file: "worker-runtime.ts",
3502
- line: 61,
3362
+ line: 65,
3503
3363
  scope: this,
3504
3364
  callSite: (f, a) => f(...a)
3505
3365
  });
@@ -3507,7 +3367,7 @@ var WorkerRuntime = class {
3507
3367
  this._ready.wake(err);
3508
3368
  log13.catch(err, {}, {
3509
3369
  file: "worker-runtime.ts",
3510
- line: 64,
3370
+ line: 68,
3511
3371
  scope: this,
3512
3372
  callSite: (f, a) => f(...a)
3513
3373
  });
@@ -3557,13 +3417,15 @@ var WorkerRuntime = class {
3557
3417
  };
3558
3418
 
3559
3419
  // packages/sdk/client-services/src/packlets/services/service-context.ts
3560
- import { Trigger as Trigger8 } from "@dxos/async";
3420
+ import assert12 from "@dxos/node-std/assert";
3421
+ import { Trigger as Trigger7 } from "@dxos/async";
3422
+ import { Invitation as Invitation5 } from "@dxos/client";
3561
3423
  import { getCredentialAssertion as getCredentialAssertion3 } from "@dxos/credentials";
3562
3424
  import { failUndefined as failUndefined2 } from "@dxos/debug";
3563
3425
  import { valueEncoding, MetadataStore, SpaceManager, DataServiceSubscriptions, SnapshotStore } from "@dxos/echo-pipeline";
3564
3426
  import { FeedFactory, FeedStore } from "@dxos/feed-store";
3565
3427
  import { Keyring } from "@dxos/keyring";
3566
- import { PublicKey as PublicKey9 } from "@dxos/keys";
3428
+ import { PublicKey as PublicKey8 } from "@dxos/keys";
3567
3429
  import { log as log14 } from "@dxos/log";
3568
3430
  import { trace as trace2 } from "@dxos/protocols";
3569
3431
  var ServiceContext = class {
@@ -3572,9 +3434,10 @@ var ServiceContext = class {
3572
3434
  this.storage = storage;
3573
3435
  this.networkManager = networkManager;
3574
3436
  this.modelFactory = modelFactory;
3575
- this.initialized = new Trigger8();
3437
+ this.initialized = new Trigger7();
3576
3438
  this.dataServiceSubscriptions = new DataServiceSubscriptions();
3577
- this._instanceId = PublicKey9.random().toHex();
3439
+ this._handlerFactories = /* @__PURE__ */ new Map();
3440
+ this._instanceId = PublicKey8.random().toHex();
3578
3441
  this.metadataStore = new MetadataStore(storage.createDirectory("metadata"));
3579
3442
  this.snapshotStore = new SnapshotStore(storage.createDirectory("snapshots"));
3580
3443
  this.keyring = new Keyring(storage.createDirectory("keyring"));
@@ -3592,28 +3455,24 @@ var ServiceContext = class {
3592
3455
  networkManager: this.networkManager
3593
3456
  });
3594
3457
  this.identityManager = new IdentityManager(this.metadataStore, this.keyring, this.feedStore, this.spaceManager);
3595
- this.deviceInvitations = new DeviceInvitationsHandler({
3596
- networkManager: this.networkManager,
3597
- getIdentity: () => {
3598
- var _a;
3599
- return (_a = this.identityManager.identity) != null ? _a : failUndefined2();
3600
- },
3601
- acceptIdentity: this._acceptIdentity.bind(this),
3602
- keyring: this.keyring
3603
- });
3458
+ this.invitations = new InvitationsHandler(this.networkManager);
3459
+ this._handlerFactories.set(Invitation5.Kind.DEVICE, () => new DeviceInvitationProtocol(this.keyring, () => {
3460
+ var _a;
3461
+ return (_a = this.identityManager.identity) != null ? _a : failUndefined2();
3462
+ }, this._acceptIdentity.bind(this)));
3604
3463
  }
3605
3464
  async open() {
3606
3465
  log14.trace("dxos.sdk.client-services", trace2.begin({
3607
3466
  id: this._instanceId
3608
3467
  }), {
3609
3468
  file: "service-context.ts",
3610
- line: 98,
3469
+ line: 111,
3611
3470
  scope: this,
3612
3471
  callSite: (f, a) => f(...a)
3613
3472
  });
3614
3473
  log14("opening...", {}, {
3615
3474
  file: "service-context.ts",
3616
- line: 100,
3475
+ line: 113,
3617
3476
  scope: this,
3618
3477
  callSite: (f, a) => f(...a)
3619
3478
  });
@@ -3625,7 +3484,7 @@ var ServiceContext = class {
3625
3484
  }
3626
3485
  log14("opened", {}, {
3627
3486
  file: "service-context.ts",
3628
- line: 107,
3487
+ line: 120,
3629
3488
  scope: this,
3630
3489
  callSite: (f, a) => f(...a)
3631
3490
  });
@@ -3634,7 +3493,7 @@ var ServiceContext = class {
3634
3493
  var _a, _b;
3635
3494
  log14("closing...", {}, {
3636
3495
  file: "service-context.ts",
3637
- line: 111,
3496
+ line: 124,
3638
3497
  scope: this,
3639
3498
  callSite: (f, a) => f(...a)
3640
3499
  });
@@ -3647,7 +3506,7 @@ var ServiceContext = class {
3647
3506
  this.dataServiceSubscriptions.clear();
3648
3507
  log14("closed", {}, {
3649
3508
  file: "service-context.ts",
3650
- line: 119,
3509
+ line: 132,
3651
3510
  scope: this,
3652
3511
  callSite: (f, a) => f(...a)
3653
3512
  });
@@ -3655,7 +3514,7 @@ var ServiceContext = class {
3655
3514
  id: this._instanceId
3656
3515
  }), {
3657
3516
  file: "service-context.ts",
3658
- line: 121,
3517
+ line: 134,
3659
3518
  scope: this,
3660
3519
  callSite: (f, a) => f(...a)
3661
3520
  });
@@ -3663,7 +3522,7 @@ var ServiceContext = class {
3663
3522
  async reset() {
3664
3523
  log14("resetting...", {}, {
3665
3524
  file: "service-context.ts",
3666
- line: 125,
3525
+ line: 138,
3667
3526
  scope: this,
3668
3527
  callSite: (f, a) => f(...a)
3669
3528
  });
@@ -3671,7 +3530,7 @@ var ServiceContext = class {
3671
3530
  await this.storage.reset();
3672
3531
  log14("reset", {}, {
3673
3532
  file: "service-context.ts",
3674
- line: 128,
3533
+ line: 141,
3675
3534
  scope: this,
3676
3535
  callSite: (f, a) => f(...a)
3677
3536
  });
@@ -3681,6 +3540,11 @@ var ServiceContext = class {
3681
3540
  await this._initialize();
3682
3541
  return identity;
3683
3542
  }
3543
+ getInvitationHandler(invitation) {
3544
+ const factory = this._handlerFactories.get(invitation.kind);
3545
+ assert12(factory, `Unknown invitation kind: ${invitation.kind}`);
3546
+ return factory(invitation);
3547
+ }
3684
3548
  async _acceptIdentity(params) {
3685
3549
  const identity = await this.identityManager.acceptIdentity(params);
3686
3550
  await this._initialize();
@@ -3691,7 +3555,7 @@ var ServiceContext = class {
3691
3555
  var _a;
3692
3556
  log14("initializing spaces...", {}, {
3693
3557
  file: "service-context.ts",
3694
- line: 147,
3558
+ line: 166,
3695
3559
  scope: this,
3696
3560
  callSite: (f, a) => f(...a)
3697
3561
  });
@@ -3711,7 +3575,10 @@ var ServiceContext = class {
3711
3575
  };
3712
3576
  this.dataSpaceManager = new DataSpaceManager(this.spaceManager, this.metadataStore, this.dataServiceSubscriptions, this.keyring, signingContext, this.modelFactory, this.feedStore, this.snapshotStore);
3713
3577
  await this.dataSpaceManager.open();
3714
- this.spaceInvitations = new SpaceInvitationsHandler(this.networkManager, this.dataSpaceManager, signingContext, this.keyring);
3578
+ this._handlerFactories.set(Invitation5.Kind.SPACE, (invitation) => {
3579
+ assert12(this.dataSpaceManager, "dataSpaceManager not initialized yet");
3580
+ return new SpaceInvitationProtocol(this.dataSpaceManager, signingContext, this.keyring, invitation.spaceKey);
3581
+ });
3715
3582
  this.initialized.wake();
3716
3583
  this._deviceSpaceSync = identity.space.spaceState.registerProcessor({
3717
3584
  process: async (credential) => {
@@ -3727,7 +3594,7 @@ var ServiceContext = class {
3727
3594
  details: assertion
3728
3595
  }, {
3729
3596
  file: "service-context.ts",
3730
- line: 190,
3597
+ line: 207,
3731
3598
  scope: this,
3732
3599
  callSite: (f, a) => f(...a)
3733
3600
  });
@@ -3738,7 +3605,7 @@ var ServiceContext = class {
3738
3605
  details: assertion
3739
3606
  }, {
3740
3607
  file: "service-context.ts",
3741
- line: 194,
3608
+ line: 211,
3742
3609
  scope: this,
3743
3610
  callSite: (f, a) => f(...a)
3744
3611
  });
@@ -3749,7 +3616,7 @@ var ServiceContext = class {
3749
3616
  details: assertion
3750
3617
  }, {
3751
3618
  file: "service-context.ts",
3752
- line: 199,
3619
+ line: 216,
3753
3620
  scope: this,
3754
3621
  callSite: (f, a) => f(...a)
3755
3622
  });
@@ -3760,7 +3627,7 @@ var ServiceContext = class {
3760
3627
  } catch (err) {
3761
3628
  log14.catch(err, {}, {
3762
3629
  file: "service-context.ts",
3763
- line: 205,
3630
+ line: 222,
3764
3631
  scope: this,
3765
3632
  callSite: (f, a) => f(...a)
3766
3633
  });
@@ -3809,7 +3676,7 @@ var ClientServicesHost = class {
3809
3676
  this._statusUpdate = new Event7();
3810
3677
  this._opening = false;
3811
3678
  this._open = false;
3812
- this._instanceId = PublicKey10.random().toHex();
3679
+ this._instanceId = PublicKey9.random().toHex();
3813
3680
  this._storage = storage;
3814
3681
  this._modelFactory = modelFactory;
3815
3682
  if (config) {
@@ -3838,7 +3705,7 @@ var ClientServicesHost = class {
3838
3705
  }
3839
3706
  },
3840
3707
  onReset: async () => {
3841
- assert12(this._serviceContext, "service host is closed");
3708
+ assert13(this._serviceContext, "service host is closed");
3842
3709
  await this._serviceContext.reset();
3843
3710
  }
3844
3711
  });
@@ -3864,16 +3731,16 @@ var ClientServicesHost = class {
3864
3731
  * Can only be called once.
3865
3732
  */
3866
3733
  initialize({ config, networkManager }) {
3867
- assert12(!this._open, "service host is open");
3734
+ assert13(!this._open, "service host is open");
3868
3735
  if (config) {
3869
- assert12(!this._config, "config already set");
3736
+ assert13(!this._config, "config already set");
3870
3737
  this._config = config;
3871
3738
  if (!this._storage) {
3872
3739
  this._storage = createStorageObjects(config.get("runtime.client.storage", {})).storage;
3873
3740
  }
3874
3741
  }
3875
3742
  if (networkManager) {
3876
- assert12(!this._networkManager, "network manager already set");
3743
+ assert13(!this._networkManager, "network manager already set");
3877
3744
  this._networkManager = networkManager;
3878
3745
  }
3879
3746
  }
@@ -3886,19 +3753,19 @@ var ClientServicesHost = class {
3886
3753
  id: this._instanceId
3887
3754
  }), {
3888
3755
  file: "service-host.ts",
3889
- line: 168,
3756
+ line: 167,
3890
3757
  scope: this,
3891
3758
  callSite: (f, a) => f(...a)
3892
3759
  });
3893
- assert12(this._config, "config not set");
3894
- assert12(this._storage, "storage not set");
3895
- assert12(this._networkManager, "network manager not set");
3760
+ assert13(this._config, "config not set");
3761
+ assert13(this._storage, "storage not set");
3762
+ assert13(this._networkManager, "network manager not set");
3896
3763
  this._opening = true;
3897
3764
  log15("opening...", {
3898
3765
  lockKey: (_a = this._resourceLock) == null ? void 0 : _a.lockKey
3899
3766
  }, {
3900
3767
  file: "service-host.ts",
3901
- line: 175,
3768
+ line: 174,
3902
3769
  scope: this,
3903
3770
  callSite: (f, a) => f(...a)
3904
3771
  });
@@ -3907,15 +3774,8 @@ var ClientServicesHost = class {
3907
3774
  this._serviceRegistry.setServices({
3908
3775
  SystemService: this._systemService,
3909
3776
  IdentityService: new IdentityServiceImpl(this._serviceContext),
3777
+ InvitationsService: new InvitationsServiceImpl(this._serviceContext.invitations, (invitation) => this._serviceContext.getInvitationHandler(invitation)),
3910
3778
  DevicesService: new DevicesServiceImpl(this._serviceContext.identityManager),
3911
- DeviceInvitationsService: new DeviceInvitationsServiceImpl(this._serviceContext.identityManager, this._serviceContext.deviceInvitations),
3912
- SpaceInvitationsService: new SpaceInvitationsServiceImpl(this._serviceContext.identityManager, () => {
3913
- var _a2;
3914
- return (_a2 = this._serviceContext.spaceInvitations) != null ? _a2 : raise3(new Error("SpaceInvitations not initialized"));
3915
- }, () => {
3916
- var _a2;
3917
- return (_a2 = this._serviceContext.dataSpaceManager) != null ? _a2 : raise3(new Error("SpaceManager not initialized"));
3918
- }),
3919
3779
  SpacesService: new SpacesServiceImpl(this._serviceContext.identityManager, this._serviceContext.spaceManager, this._serviceContext.dataServiceSubscriptions, async () => {
3920
3780
  await this._serviceContext.initialized.wait();
3921
3781
  return this._serviceContext.dataSpaceManager;
@@ -3939,7 +3799,7 @@ var ClientServicesHost = class {
3939
3799
  deviceKey
3940
3800
  }, {
3941
3801
  file: "service-host.ts",
3942
- line: 229,
3802
+ line: 221,
3943
3803
  scope: this,
3944
3804
  callSite: (f, a) => f(...a)
3945
3805
  });
@@ -3954,7 +3814,7 @@ var ClientServicesHost = class {
3954
3814
  deviceKey
3955
3815
  }, {
3956
3816
  file: "service-host.ts",
3957
- line: 238,
3817
+ line: 230,
3958
3818
  scope: this,
3959
3819
  callSite: (f, a) => f(...a)
3960
3820
  });
@@ -3968,7 +3828,7 @@ var ClientServicesHost = class {
3968
3828
  deviceKey
3969
3829
  }, {
3970
3830
  file: "service-host.ts",
3971
- line: 243,
3831
+ line: 235,
3972
3832
  scope: this,
3973
3833
  callSite: (f, a) => f(...a)
3974
3834
  });
@@ -3976,7 +3836,7 @@ var ClientServicesHost = class {
3976
3836
  id: this._instanceId
3977
3837
  }), {
3978
3838
  file: "service-host.ts",
3979
- line: 245,
3839
+ line: 237,
3980
3840
  scope: this,
3981
3841
  callSite: (f, a) => f(...a)
3982
3842
  });
@@ -4057,7 +3917,7 @@ var LOCK_KEY = "DXOS_RESOURCE_LOCK";
4057
3917
  var IFrameHostRuntime = class {
4058
3918
  constructor({ configProvider, appPort, shellPort }) {
4059
3919
  this._transportFactory = createWebRTCTransportFactory2();
4060
- this._ready = new Trigger9();
3920
+ this._ready = new Trigger8();
4061
3921
  this._configProvider = configProvider;
4062
3922
  this._appPort = appPort;
4063
3923
  this._shellPort = shellPort;
@@ -4179,11 +4039,10 @@ export {
4179
4039
  Identity,
4180
4040
  IdentityManager,
4181
4041
  IdentityServiceImpl,
4182
- DeviceInvitationsHandler,
4183
- AbstractInvitationsService,
4184
- DeviceInvitationsServiceImpl,
4185
- SpaceInvitationsHandler,
4186
- SpaceInvitationsServiceImpl,
4042
+ DeviceInvitationProtocol,
4043
+ InvitationsHandler,
4044
+ InvitationsServiceImpl,
4045
+ SpaceInvitationProtocol,
4187
4046
  createStorageObjects,
4188
4047
  ShellRuntimeImpl,
4189
4048
  MemoryShellRuntime,
@@ -4198,4 +4057,4 @@ export {
4198
4057
  LocalClientServices,
4199
4058
  fromHost
4200
4059
  };
4201
- //# sourceMappingURL=chunk-H5IXSSI7.mjs.map
4060
+ //# sourceMappingURL=chunk-OINEQJWM.mjs.map