@awiki/dsh-plugin 0.3.12 → 0.3.16

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 (66) hide show
  1. package/README.md +24 -2
  2. package/README.zh.md +12 -2
  3. package/cordis.patch.yml +1 -0
  4. package/lib/client.js +997 -122
  5. package/lib/client.js.map +1 -1
  6. package/lib/index.js +203 -46
  7. package/lib/provider.js +2 -1
  8. package/lib/{sdk-adapter-DFDY7Hih.mjs → sdk-adapter-DGcTiEZz.mjs} +91 -7
  9. package/lib/typert.host.js +349 -68
  10. package/lib/typert.remote-client.d.ts +9 -1
  11. package/lib/typert.remote-client.d.ts.map +1 -1
  12. package/lib/typert.remote-client.js +349 -68
  13. package/lib/types/client/AwikiDeviceJoinReminder.d.ts.map +1 -1
  14. package/lib/types/client/AwikiDeviceJoinReminder.js +1 -1
  15. package/lib/types/client/AwikiDeviceJoinReminder.js.map +1 -1
  16. package/lib/types/client/AwikiDevices.d.ts +5 -1
  17. package/lib/types/client/AwikiDevices.d.ts.map +1 -1
  18. package/lib/types/client/AwikiDevices.js +2 -1
  19. package/lib/types/client/AwikiDevices.js.map +1 -1
  20. package/lib/types/client/AwikiIdentityAccess.d.ts.map +1 -1
  21. package/lib/types/client/AwikiIdentityAccess.js +72 -24
  22. package/lib/types/client/AwikiIdentityAccess.js.map +1 -1
  23. package/lib/types/client/AwikiIdentityServices.d.ts +9 -0
  24. package/lib/types/client/AwikiIdentityServices.d.ts.map +1 -0
  25. package/lib/types/client/AwikiIdentityServices.js +66 -0
  26. package/lib/types/client/AwikiIdentityServices.js.map +1 -0
  27. package/lib/types/client/AwikiOverlay.js +1 -1
  28. package/lib/types/client/AwikiOverlay.js.map +1 -1
  29. package/lib/types/client/AwikiSettingsSection.js +1 -1
  30. package/lib/types/client/AwikiSettingsSection.js.map +1 -1
  31. package/lib/types/client/controller.d.ts +8 -0
  32. package/lib/types/client/controller.d.ts.map +1 -1
  33. package/lib/types/client/controller.js +20 -2
  34. package/lib/types/client/controller.js.map +1 -1
  35. package/lib/types/client/index.d.ts.map +1 -1
  36. package/lib/types/client/index.js +8 -0
  37. package/lib/types/client/index.js.map +1 -1
  38. package/lib/types/client/slots.d.ts +3 -1
  39. package/lib/types/client/slots.d.ts.map +1 -1
  40. package/lib/types/index.d.ts +7 -1
  41. package/lib/types/index.d.ts.map +1 -1
  42. package/lib/types/index.js +134 -34
  43. package/lib/types/index.js.map +1 -1
  44. package/lib/types/package-version.generated.d.ts +2 -2
  45. package/lib/types/package-version.generated.d.ts.map +1 -1
  46. package/lib/types/package-version.generated.js +2 -2
  47. package/lib/types/package-version.generated.js.map +1 -1
  48. package/lib/types/provider-api.d.ts +17 -1
  49. package/lib/types/provider-api.d.ts.map +1 -1
  50. package/lib/types/provider.d.ts.map +1 -1
  51. package/lib/types/provider.js +1 -0
  52. package/lib/types/provider.js.map +1 -1
  53. package/lib/types/registration-policy.d.ts +1 -1
  54. package/lib/types/registration-policy.d.ts.map +1 -1
  55. package/lib/types/registration-policy.js +1 -1
  56. package/lib/types/registration-policy.js.map +1 -1
  57. package/lib/types/sdk-adapter.d.ts +17 -1
  58. package/lib/types/sdk-adapter.d.ts.map +1 -1
  59. package/lib/types/sdk-adapter.js +83 -4
  60. package/lib/types/sdk-adapter.js.map +1 -1
  61. package/lib/types/types.d.ts +60 -1
  62. package/lib/types/types.d.ts.map +1 -1
  63. package/lib/types/types.js.map +1 -1
  64. package/lib/types/update-policy.d.ts +2 -2
  65. package/lib/types/update-policy.d.ts.map +1 -1
  66. package/package.json +35 -31
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as fencedMailRecoveryObservability, i as failedMailRecoveryObservability, o as successfulMailRecoveryObservability, r as downloadedAttachment, s as isMessageTarget, t as AwikiSdkError } from "./sdk-adapter-DFDY7Hih.mjs";
1
+ import { a as fencedMailRecoveryObservability, i as failedMailRecoveryObservability, o as successfulMailRecoveryObservability, r as downloadedAttachment, s as isMessageTarget, t as AwikiSdkError } from "./sdk-adapter-DGcTiEZz.mjs";
2
2
  import "@deepseek-ai/cordis";
3
3
  import { createHash, randomUUID, timingSafeEqual } from "node:crypto";
4
4
  import { homedir } from "node:os";
@@ -3571,8 +3571,8 @@ function checkInstallation(requirements, installed) {
3571
3571
  //#endregion
3572
3572
  //#region lib/types/package-version.generated.js
3573
3573
  /** Generated from package.json by scripts/sync-package-versions.mjs. */
3574
- const DSH_AWIKI_PACKAGE_VERSION = "0.3.12";
3575
- const DSH_AWIKI_MODEL_PROXY_PACKAGE_VERSION = "0.1.7";
3574
+ const DSH_AWIKI_PACKAGE_VERSION = "0.3.16";
3575
+ const DSH_AWIKI_MODEL_PROXY_PACKAGE_VERSION = "0.1.11";
3576
3576
  //#endregion
3577
3577
  //#region lib/types/update-policy.js
3578
3578
  /** Tenant-scoped DSH AWiki plugin update policy and verified cache. */
@@ -3979,6 +3979,7 @@ const Config = z.object({
3979
3979
  messageServiceDid: z.string().default(DEFAULT_AWIKI_MESSAGE_SERVICE_DID),
3980
3980
  allowedAttachmentOrigins: z.array(z.string()).default([]),
3981
3981
  allowInsecureLoopbackForTesting: z.boolean().default(false),
3982
+ caBundle: z.string(),
3982
3983
  stateRoot: z.string(),
3983
3984
  attachmentMaxBytes: z.number().default(DEFAULT_ATTACHMENT_MAX_BYTES),
3984
3985
  mailAttachmentMaxCount: z.number().default(10),
@@ -4198,6 +4199,7 @@ function resolveConfig(ctx, config) {
4198
4199
  messageServiceDid: serviceDid(config.messageServiceDid ?? DEFAULT_AWIKI_MESSAGE_SERVICE_DID),
4199
4200
  allowedAttachmentOrigins: attachmentOrigins(config.allowedAttachmentOrigins, messageServicePublicUrl, allowInsecureLoopbackForTesting),
4200
4201
  allowInsecureLoopbackForTesting,
4202
+ ...config.caBundle === void 0 ? {} : { caBundle: config.caBundle },
4201
4203
  stateRoot,
4202
4204
  attachmentMaxBytes,
4203
4205
  mailAttachmentMaxCount,
@@ -4333,12 +4335,7 @@ function normalizeRecoveryPrepareRequest(request) {
4333
4335
  };
4334
4336
  }
4335
4337
  const IDENTITY_ACCESS_RESPONSE_MAX_BYTES = 65536;
4336
- const DID_URI = /^did:[a-z0-9]+:(?:[A-Za-z0-9._-]|%[0-9A-Fa-f]{2})+(?::(?:[A-Za-z0-9._-]|%[0-9A-Fa-f]{2})+)*$/u;
4337
- const DID_URI_MAX_CHARACTERS = 2048;
4338
4338
  const SERVER_INFO_RESPONSE_MAX_BYTES = 65536;
4339
- function isBoundedDidUri(value) {
4340
- return typeof value === "string" && value.length <= DID_URI_MAX_CHARACTERS && DID_URI.test(value);
4341
- }
4342
4339
  /** Read one untrusted discovery response without buffering beyond the fixed Host limit. */
4343
4340
  async function readBoundedResponseText(response, maxBytes) {
4344
4341
  const declaredLength = response.headers.get("content-length");
@@ -4566,8 +4563,12 @@ let AwikiService = (() => {
4566
4563
  let _getDeviceJoinStatus_decorators;
4567
4564
  let _cancelDeviceJoin_decorators;
4568
4565
  let _refreshDeviceManagement_decorators;
4566
+ let _getIdentityServices_decorators;
4567
+ let _updateIdentityServices_decorators;
4568
+ let _resumeIdentityServicesUpdate_decorators;
4569
4569
  let _startDeviceJoinVerification_decorators;
4570
4570
  let _approveDeviceJoin_decorators;
4571
+ let _retryDeviceManagement_decorators;
4571
4572
  let _rejectDeviceJoin_decorators;
4572
4573
  let _revokeDevice_decorators;
4573
4574
  let _prepareRootTransfer_decorators;
@@ -4631,8 +4632,12 @@ let AwikiService = (() => {
4631
4632
  _getDeviceJoinStatus_decorators = [Remote];
4632
4633
  _cancelDeviceJoin_decorators = [Remote];
4633
4634
  _refreshDeviceManagement_decorators = [Remote];
4635
+ _getIdentityServices_decorators = [Remote];
4636
+ _updateIdentityServices_decorators = [Remote];
4637
+ _resumeIdentityServicesUpdate_decorators = [Remote];
4634
4638
  _startDeviceJoinVerification_decorators = [Remote];
4635
4639
  _approveDeviceJoin_decorators = [Remote];
4640
+ _retryDeviceManagement_decorators = [Remote];
4636
4641
  _rejectDeviceJoin_decorators = [Remote];
4637
4642
  _revokeDevice_decorators = [Remote];
4638
4643
  _prepareRootTransfer_decorators = [Remote];
@@ -4893,6 +4898,39 @@ let AwikiService = (() => {
4893
4898
  },
4894
4899
  metadata: _metadata
4895
4900
  }, null, _instanceExtraInitializers);
4901
+ __esDecorate(this, null, _getIdentityServices_decorators, {
4902
+ kind: "method",
4903
+ name: "getIdentityServices",
4904
+ static: false,
4905
+ private: false,
4906
+ access: {
4907
+ has: (obj) => "getIdentityServices" in obj,
4908
+ get: (obj) => obj.getIdentityServices
4909
+ },
4910
+ metadata: _metadata
4911
+ }, null, _instanceExtraInitializers);
4912
+ __esDecorate(this, null, _updateIdentityServices_decorators, {
4913
+ kind: "method",
4914
+ name: "updateIdentityServices",
4915
+ static: false,
4916
+ private: false,
4917
+ access: {
4918
+ has: (obj) => "updateIdentityServices" in obj,
4919
+ get: (obj) => obj.updateIdentityServices
4920
+ },
4921
+ metadata: _metadata
4922
+ }, null, _instanceExtraInitializers);
4923
+ __esDecorate(this, null, _resumeIdentityServicesUpdate_decorators, {
4924
+ kind: "method",
4925
+ name: "resumeIdentityServicesUpdate",
4926
+ static: false,
4927
+ private: false,
4928
+ access: {
4929
+ has: (obj) => "resumeIdentityServicesUpdate" in obj,
4930
+ get: (obj) => obj.resumeIdentityServicesUpdate
4931
+ },
4932
+ metadata: _metadata
4933
+ }, null, _instanceExtraInitializers);
4896
4934
  __esDecorate(this, null, _startDeviceJoinVerification_decorators, {
4897
4935
  kind: "method",
4898
4936
  name: "startDeviceJoinVerification",
@@ -4915,6 +4953,17 @@ let AwikiService = (() => {
4915
4953
  },
4916
4954
  metadata: _metadata
4917
4955
  }, null, _instanceExtraInitializers);
4956
+ __esDecorate(this, null, _retryDeviceManagement_decorators, {
4957
+ kind: "method",
4958
+ name: "retryDeviceManagement",
4959
+ static: false,
4960
+ private: false,
4961
+ access: {
4962
+ has: (obj) => "retryDeviceManagement" in obj,
4963
+ get: (obj) => obj.retryDeviceManagement
4964
+ },
4965
+ metadata: _metadata
4966
+ }, null, _instanceExtraInitializers);
4918
4967
  __esDecorate(this, null, _rejectDeviceJoin_decorators, {
4919
4968
  kind: "method",
4920
4969
  name: "rejectDeviceJoin",
@@ -5535,6 +5584,7 @@ let AwikiService = (() => {
5535
5584
  allowedAttachmentOrigins: tenant.storageLayout === "legacy-base" ? this.resolved.allowedAttachmentOrigins : [messageServicePublicOrigin],
5536
5585
  attachmentMaxBytes: this.resolved.attachmentMaxBytes,
5537
5586
  allowInsecureLoopbackForTesting: this.resolved.allowInsecureLoopbackForTesting,
5587
+ ...this.resolved.caBundle === void 0 ? {} : { caBundle: this.resolved.caBundle },
5538
5588
  stateRoot: this.ensureTenantRegistry().stateRoot(tenant)
5539
5589
  };
5540
5590
  }
@@ -6053,70 +6103,87 @@ let AwikiService = (() => {
6053
6103
  ok: false,
6054
6104
  error: failure("invalid-request")
6055
6105
  };
6056
- const endpoint = new URL(`/.well-known/handle/${encodeURIComponent(target.localPart)}`, options.userServiceUrl);
6106
+ if (request.inviteCode !== void 0 && (typeof request.inviteCode !== "string" || request.inviteCode.length > 512) || request.phone !== void 0 && (typeof request.phone !== "string" || request.phone.length > 64)) return {
6107
+ ok: false,
6108
+ error: failure("invalid-request")
6109
+ };
6110
+ const endpoint = new URL("/user-service/v1/handle/rpc", options.userServiceUrl);
6057
6111
  const abort = new AbortController();
6058
6112
  const timeout = setTimeout(() => {
6059
6113
  abort.abort();
6060
6114
  }, 1e4);
6061
- let response;
6062
6115
  try {
6063
- response = await fetch(endpoint, {
6064
- method: "GET",
6116
+ const response = await fetch(endpoint, {
6117
+ method: "POST",
6065
6118
  headers: {
6066
6119
  accept: "application/json",
6120
+ "content-type": "application/json",
6067
6121
  "cache-control": "no-store"
6068
6122
  },
6123
+ body: JSON.stringify({
6124
+ jsonrpc: "2.0",
6125
+ id: "registration-check",
6126
+ method: "registration_check",
6127
+ params: {
6128
+ handle: target.localPart,
6129
+ domain: options.userServiceDomain,
6130
+ check_invite: request.inviteCode !== void 0,
6131
+ ...request.inviteCode === void 0 ? {} : { invite_code: request.inviteCode },
6132
+ ...request.phone === void 0 ? {} : { phone: request.phone }
6133
+ }
6134
+ }),
6069
6135
  cache: "no-store",
6070
6136
  redirect: "error",
6071
6137
  signal: abort.signal
6072
6138
  });
6073
- } catch {
6074
- return {
6139
+ if (!response.ok) return {
6075
6140
  ok: false,
6076
- error: failure("network")
6141
+ error: failure("remote")
6077
6142
  };
6078
- } finally {
6079
- clearTimeout(timeout);
6080
- }
6081
- if (response.status === 404) return {
6082
- ok: true,
6083
- value: {
6084
- status: "available",
6085
- fullHandle: target.fullHandle
6086
- }
6087
- };
6088
- if (!response.ok && response.status !== 410) return {
6089
- ok: false,
6090
- error: failure("remote")
6091
- };
6092
- try {
6093
6143
  const text = await readBoundedResponseText(response, IDENTITY_ACCESS_RESPONSE_MAX_BYTES);
6094
6144
  if (text === void 0) return {
6095
6145
  ok: false,
6096
6146
  error: failure("remote")
6097
6147
  };
6098
- const value = JSON.parse(text);
6099
- if (typeof value !== "object" || value === null) return {
6100
- ok: false,
6101
- error: failure("remote")
6102
- };
6103
- const binding = value;
6104
- if (binding.handle !== target.fullHandle || !isBoundedDidUri(binding.did) || typeof binding.status !== "string" || binding.status.length === 0 || response.status === 410 && binding.status !== "revoked") return {
6148
+ let envelope;
6149
+ try {
6150
+ envelope = JSON.parse(text);
6151
+ } catch {
6152
+ return {
6153
+ ok: false,
6154
+ error: failure("remote")
6155
+ };
6156
+ }
6157
+ const value = envelope?.result;
6158
+ if (envelope?.jsonrpc !== "2.0" || envelope.id !== "registration-check" || envelope.error !== void 0 && envelope.error !== null || value?.full_handle !== target.fullHandle || ![
6159
+ "register",
6160
+ "existing",
6161
+ "unavailable"
6162
+ ].includes(value.decision) || typeof value.invite_required !== "boolean" || ![
6163
+ "not_required",
6164
+ "required",
6165
+ "valid",
6166
+ "invalid"
6167
+ ].includes(value.invite_status) || value.decision === "existing" && value.invite_required || !value.invite_required && value.invite_status !== "not_required" || value.invite_required && value.invite_status === "not_required") return {
6105
6168
  ok: false,
6106
6169
  error: failure("remote")
6107
6170
  };
6108
6171
  return {
6109
6172
  ok: true,
6110
6173
  value: {
6111
- status: "existing",
6112
- fullHandle: target.fullHandle
6174
+ status: value.decision === "register" ? "available" : value.decision,
6175
+ fullHandle: target.fullHandle,
6176
+ inviteRequired: value.invite_required,
6177
+ inviteStatus: value.invite_status
6113
6178
  }
6114
6179
  };
6115
6180
  } catch {
6116
6181
  return {
6117
6182
  ok: false,
6118
- error: failure("remote")
6183
+ error: failure("network")
6119
6184
  };
6185
+ } finally {
6186
+ clearTimeout(timeout);
6120
6187
  }
6121
6188
  }
6122
6189
  async sendRegistrationOtp(request) {
@@ -6158,7 +6225,8 @@ let AwikiService = (() => {
6158
6225
  continuationId: result.value.continuationId,
6159
6226
  fullHandle: result.value.fullHandle,
6160
6227
  mode: result.value.mode,
6161
- requiresUserPresence: result.value.requiresUserPresence
6228
+ requiresUserPresence: result.value.requiresUserPresence,
6229
+ ...result.value.methodCapabilities === void 0 ? {} : { methodCapabilities: result.value.methodCapabilities }
6162
6230
  };
6163
6231
  return {
6164
6232
  ok: true,
@@ -6166,7 +6234,8 @@ let AwikiService = (() => {
6166
6234
  status: "join-required",
6167
6235
  fullHandle: result.value.fullHandle,
6168
6236
  mode: result.value.mode,
6169
- requiresUserPresence: result.value.requiresUserPresence
6237
+ requiresUserPresence: result.value.requiresUserPresence,
6238
+ ...result.value.methodCapabilities === void 0 ? {} : { methodCapabilities: result.value.methodCapabilities }
6170
6239
  }
6171
6240
  };
6172
6241
  }
@@ -6241,6 +6310,10 @@ let AwikiService = (() => {
6241
6310
  return this.run(async (client) => {
6242
6311
  const joining = await this.selectDeviceJoinSession(client) !== null;
6243
6312
  const recoveries = await client.listPendingRecoveries();
6313
+ const pendingRegistrations = await client.pendingIdentityRegistrations();
6314
+ const creationMethods = await client.identityCreationMethods().catch(() => []);
6315
+ const identity = await client.getIdentity();
6316
+ const capabilities = identity === null ? void 0 : await client.identityMethodCapabilities(identity.did);
6244
6317
  const domain = this.activeClientOptions?.userServiceDomain;
6245
6318
  const choice = this.pendingDeviceJoin;
6246
6319
  return {
@@ -6248,9 +6321,13 @@ let AwikiService = (() => {
6248
6321
  status: "join-required",
6249
6322
  fullHandle: choice.fullHandle,
6250
6323
  mode: choice.mode,
6251
- requiresUserPresence: choice.requiresUserPresence
6324
+ requiresUserPresence: choice.requiresUserPresence,
6325
+ ...choice.methodCapabilities === void 0 ? {} : { methodCapabilities: choice.methodCapabilities }
6252
6326
  },
6253
6327
  joining,
6328
+ creationMethods,
6329
+ pendingRegistrations,
6330
+ ...capabilities === void 0 ? {} : { methodCapabilities: capabilities },
6254
6331
  recoveries: recoveries.filter((value) => domain !== void 0 && value.fullHandle.slice(value.fullHandle.indexOf(".") + 1) === domain)
6255
6332
  };
6256
6333
  }, { allowSignedOut: true });
@@ -6287,6 +6364,48 @@ let AwikiService = (() => {
6287
6364
  refreshDeviceManagement() {
6288
6365
  return this.run((client) => this.deviceManagementSnapshot(client));
6289
6366
  }
6367
+ getIdentityServices() {
6368
+ return this.run((client) => client.getIdentityServices());
6369
+ }
6370
+ updateIdentityServices(request) {
6371
+ if (request === null || !Array.isArray(request.services)) return Promise.resolve({
6372
+ ok: false,
6373
+ error: failure("invalid-request")
6374
+ });
6375
+ return this.run(async (client) => {
6376
+ const did = await this.requireIdentityServicesManager(client);
6377
+ if (request.did !== did) throw Object.assign(/* @__PURE__ */ new Error("identity changed"), {
6378
+ name: "AwikiSdkError",
6379
+ code: "conflict"
6380
+ });
6381
+ if ((await client.getIdentityServices()).pending) throw Object.assign(/* @__PURE__ */ new Error("pending service update"), {
6382
+ name: "AwikiSdkError",
6383
+ code: "conflict"
6384
+ });
6385
+ await client.updateIdentityServices(request);
6386
+ return client.getIdentityServices();
6387
+ });
6388
+ }
6389
+ resumeIdentityServicesUpdate(request) {
6390
+ return this.run(async (client) => {
6391
+ const did = await this.requireIdentityServicesManager(client);
6392
+ if (request?.did !== did) throw Object.assign(/* @__PURE__ */ new Error("identity changed"), {
6393
+ name: "AwikiSdkError",
6394
+ code: "conflict"
6395
+ });
6396
+ await client.resumeIdentityServicesUpdate();
6397
+ return client.getIdentityServices();
6398
+ });
6399
+ }
6400
+ async requireIdentityServicesManager(client) {
6401
+ await this.requireDeviceManager(client);
6402
+ const identity = await client.getIdentity();
6403
+ if (identity === null || !(await client.identityMethodCapabilities(identity.did)).servicesUpdate) throw Object.assign(/* @__PURE__ */ new Error("service update unavailable"), {
6404
+ name: "AwikiSdkError",
6405
+ code: "forbidden"
6406
+ });
6407
+ return identity.did;
6408
+ }
6290
6409
  async startDeviceJoinVerification(request) {
6291
6410
  const joinSessionId = this.requestSessions.get(request?.requestRef);
6292
6411
  if (joinSessionId === void 0) return {
@@ -6362,6 +6481,23 @@ let AwikiService = (() => {
6362
6481
  });
6363
6482
  return result.ok ? this.publicAdminJoinProgress(request.requestRef, result.value) : result;
6364
6483
  }
6484
+ async retryDeviceManagement(request) {
6485
+ const deviceId = this.deviceIds.get(request?.deviceRef);
6486
+ if (deviceId === void 0) return {
6487
+ ok: false,
6488
+ error: failure("invalid-request")
6489
+ };
6490
+ return this.run(async (client) => {
6491
+ await this.requireDeviceManager(client);
6492
+ const task = (await client.deviceJoinManagementStatus()).find((value) => value.recipientDeviceId === deviceId);
6493
+ if (task === void 0 || task.phase !== "failed" || ["root_transfer.delivery_expired", "root_transfer.delivery_invalidated"].includes(task.failureCode ?? "")) throw Object.assign(/* @__PURE__ */ new Error("management retry unavailable"), {
6494
+ name: "AwikiSdkError",
6495
+ code: "forbidden"
6496
+ });
6497
+ await client.retryDeviceJoinManagement(task.joinSessionId);
6498
+ return null;
6499
+ });
6500
+ }
6365
6501
  async rejectDeviceJoin(request) {
6366
6502
  const joinSessionId = this.requestSessions.get(request?.requestRef);
6367
6503
  if (joinSessionId === void 0 || request.reason !== "user_rejected" && request.reason !== "sas_mismatch") return {
@@ -7207,6 +7343,10 @@ let AwikiService = (() => {
7207
7343
  name: "AwikiSdkError",
7208
7344
  code: "not-registered"
7209
7345
  });
7346
+ if (!(await client.identityMethodCapabilities(identity.did)).rootTransfer) throw Object.assign(/* @__PURE__ */ new Error("root transfer unavailable"), {
7347
+ name: "AwikiSdkError",
7348
+ code: "forbidden"
7349
+ });
7210
7350
  const target = (await client.getDeviceRegistry()).find((device) => device.deviceId === deviceId);
7211
7351
  if (target === void 0 || target.isCurrent || target.status !== "active" || target.role !== "member" || target.managementReady) throw Object.assign(/* @__PURE__ */ new Error("root transfer recipient unavailable"), {
7212
7352
  name: "AwikiSdkError",
@@ -7233,6 +7373,9 @@ let AwikiService = (() => {
7233
7373
  async deviceManagementSnapshot(client) {
7234
7374
  await client.syncDeviceManagement();
7235
7375
  const current = await client.getCurrentDeviceSummary();
7376
+ const currentIdentity = await client.getIdentity();
7377
+ const capabilities = currentIdentity === null ? void 0 : await client.identityMethodCapabilities(currentIdentity.did);
7378
+ const rootTransferSupported = capabilities?.rootTransfer === true && client.trustedUserPresenceSupported;
7236
7379
  if (!current.canManage || current.role !== "admin" || current.readiness !== "admin_ready") {
7237
7380
  this.requestRefs.clear();
7238
7381
  this.requestSessions.clear();
@@ -7241,7 +7384,8 @@ let AwikiService = (() => {
7241
7384
  this.rootTransfers.clear();
7242
7385
  return {
7243
7386
  canManage: false,
7244
- rootTransferSupported: client.trustedUserPresenceSupported,
7387
+ rootTransferSupported,
7388
+ ...capabilities === void 0 ? {} : { methodCapabilities: capabilities },
7245
7389
  ...current.role === void 0 ? {} : { role: current.role },
7246
7390
  readiness: current.readiness,
7247
7391
  devices: [],
@@ -7250,6 +7394,7 @@ let AwikiService = (() => {
7250
7394
  }
7251
7395
  const requests = await client.listLocalDeviceJoinRequests();
7252
7396
  await Promise.all(requests.filter((request) => request.claimedByCurrentDevice).map((request) => client.getLocalDeviceJoinVerificationProgress(request.joinSessionId).catch(() => void 0)));
7397
+ const management = await client.deviceJoinManagementStatus();
7253
7398
  const devices = await client.getDeviceRegistry();
7254
7399
  const identity = await client.getIdentity();
7255
7400
  const joinedAtByDeviceId = /* @__PURE__ */ new Map();
@@ -7260,10 +7405,22 @@ let AwikiService = (() => {
7260
7405
  const initialDeviceJoinedAt = identity === null ? void 0 : new Date(identity.registeredAt).toISOString();
7261
7406
  return {
7262
7407
  canManage: true,
7263
- rootTransferSupported: client.trustedUserPresenceSupported,
7408
+ rootTransferSupported,
7409
+ ...capabilities === void 0 ? {} : { methodCapabilities: capabilities },
7264
7410
  role: "admin",
7265
7411
  readiness: "admin_ready",
7266
- devices: devices.filter((device) => device.status === "active").map((device) => this.publicDevice(device, joinedAtByDeviceId.get(device.deviceId) ?? (device.isCurrent ? initialDeviceJoinedAt : void 0))),
7412
+ devices: devices.filter((device) => device.status === "active").map((device) => {
7413
+ const task = management.find((value) => value.recipientDeviceId === device.deviceId);
7414
+ const phase = task?.phase === "failed" ? "failed" : task?.phase === "management_registered" ? "complete" : task?.phase === "waiting_for_recipient" ? "waiting" : "pending";
7415
+ return {
7416
+ ...this.publicDevice(device, joinedAtByDeviceId.get(device.deviceId) ?? (device.isCurrent ? initialDeviceJoinedAt : void 0)),
7417
+ ...task === void 0 ? {} : { provisioning: {
7418
+ phase,
7419
+ attempts: task.attempts,
7420
+ ...["root_transfer.delivery_expired", "root_transfer.delivery_invalidated"].includes(task.failureCode ?? "") ? { requiresRejoin: true } : {}
7421
+ } }
7422
+ };
7423
+ }),
7267
7424
  requests: requests.map((request) => ({
7268
7425
  requestRef: this.requestRef(request.joinSessionId),
7269
7426
  candidateKeyFingerprint: request.candidateKeyFingerprint,
package/lib/provider.js CHANGED
@@ -1,4 +1,4 @@
1
- import { n as RustSdkAdapter } from "./sdk-adapter-DFDY7Hih.mjs";
1
+ import { n as RustSdkAdapter } from "./sdk-adapter-DGcTiEZz.mjs";
2
2
  import { setTimeout } from "node:timers/promises";
3
3
  import { openImCoreNodeClient } from "@awiki/im-core-node";
4
4
  import { AnpIdentityPluginError } from "@agent-network-protocol/dsh-anp-identity";
@@ -57,6 +57,7 @@ async function apply(ctx) {
57
57
  const unregister = ctx.awiki.registerClientFactory((options) => {
58
58
  const openOptions = {
59
59
  stateRoot: options.stateRoot,
60
+ ...options.caBundle === void 0 ? {} : { caBundle: options.caBundle },
60
61
  serviceBaseUrl: options.userServiceUrl,
61
62
  didDomain: options.userServiceDomain,
62
63
  userServiceEndpoint: options.userServiceUrl,
@@ -117,6 +117,30 @@ function fencedMailRecoveryObservability(currentPrincipalMatchesRecovery, reques
117
117
  /** Rust IM Core adapter that copies native values into Host-owned public DTOs. */
118
118
  const GROUP_LOOKUP_LIMIT = 100;
119
119
  const MAX_GROUP_LOOKUP_PAGES = 20;
120
+ function methodCapabilities(value) {
121
+ return {
122
+ method: value.method,
123
+ handleRecovery: boolean(value.handleRecovery),
124
+ rootImport: boolean(value.rootImport),
125
+ rootTransfer: boolean(value.rootTransfer),
126
+ servicesUpdate: boolean(value.servicesUpdate)
127
+ };
128
+ }
129
+ function publicDocumentService(raw) {
130
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) fail("invalid-request");
131
+ const value = raw;
132
+ if (typeof value.id !== "string" || typeof value.type !== "string" || typeof value.serviceEndpoint !== "string") fail("invalid-request");
133
+ if (value.serviceDid !== void 0 && typeof value.serviceDid !== "string") fail("invalid-request");
134
+ for (const field of ["profiles", "securityProfiles"]) if (value[field] !== void 0 && (!Array.isArray(value[field]) || !value[field].every((item) => typeof item === "string"))) fail("invalid-request");
135
+ return {
136
+ id: value.id,
137
+ type: value.type,
138
+ serviceEndpoint: value.serviceEndpoint,
139
+ ...value.serviceDid === void 0 ? {} : { serviceDid: value.serviceDid },
140
+ ...value.profiles === void 0 ? {} : { profiles: [...value.profiles] },
141
+ ...value.securityProfiles === void 0 ? {} : { securityProfiles: [...value.securityProfiles] }
142
+ };
143
+ }
120
144
  const RUST_FAILURE_CODES = {
121
145
  invalid_input: "invalid-request",
122
146
  invalid_state_root: "invalid-request",
@@ -479,6 +503,7 @@ var RustSdkAdapter = class {
479
503
  onIdentity;
480
504
  trustedUserPresenceSupported = process.platform === "darwin" && process.arch === "x64";
481
505
  client;
506
+ approvalManagement = /* @__PURE__ */ new Map();
482
507
  refreshingDisplayPeers = /* @__PURE__ */ new Set();
483
508
  scheduleDisplayRefresh(client, peers) {
484
509
  if (this.disposal !== void 0) return;
@@ -801,6 +826,48 @@ var RustSdkAdapter = class {
801
826
  return result;
802
827
  });
803
828
  }
829
+ identityCreationMethods() {
830
+ return this.run(async (client) => [...await client.identityCreationMethods()]);
831
+ }
832
+ pendingIdentityRegistrations() {
833
+ return this.run(async (client) => (await client.pendingIdentityRegistrations()).map((value) => ({
834
+ did: value.did,
835
+ fullHandle: value.fullHandle,
836
+ method: value.method,
837
+ displayName: value.displayName,
838
+ verificationKind: value.verificationKind,
839
+ phase: value.phase
840
+ })));
841
+ }
842
+ identityMethodCapabilities(did) {
843
+ return this.run(async (client) => methodCapabilities(await client.identityMethodCapabilities(did)));
844
+ }
845
+ getIdentityServices() {
846
+ return this.run(async (client) => {
847
+ const currentIdentity = await client.getDefaultIdentity();
848
+ if (currentIdentity === null) fail("not-registered");
849
+ const capabilities = await client.identityMethodCapabilities(currentIdentity.did);
850
+ const current = await client.getCurrentDeviceSummary();
851
+ const document = await client.identityDocument();
852
+ if (document.id !== currentIdentity.did || !Array.isArray(document.service)) fail("remote");
853
+ return {
854
+ did: currentIdentity.did,
855
+ canManage: capabilities.servicesUpdate && current.canManage && current.role === "admin" && current.readiness === "admin_ready",
856
+ pending: await client.identityServicesUpdatePending(),
857
+ services: document.service.map(publicDocumentService)
858
+ };
859
+ });
860
+ }
861
+ updateIdentityServices(request) {
862
+ return this.run(async (client) => {
863
+ await client.updateIdentityServices(request.services.map(publicDocumentService));
864
+ });
865
+ }
866
+ resumeIdentityServicesUpdate() {
867
+ return this.run(async (client) => {
868
+ await client.resumeIdentityServicesUpdate();
869
+ });
870
+ }
804
871
  sendRegistrationOtp(request) {
805
872
  return this.run(async (client) => {
806
873
  const value = await client.requestRegistrationOtp(request);
@@ -826,7 +893,8 @@ var RustSdkAdapter = class {
826
893
  continuationId: required(value.existingHandle.continuationId),
827
894
  fullHandle: required(value.existingHandle.fullHandle),
828
895
  mode: value.existingHandle.mode === "handle_recovery_rebind" ? "handle-recovery-rebind" : "ordinary",
829
- requiresUserPresence: boolean(value.existingHandle.requiresUserPresence)
896
+ requiresUserPresence: boolean(value.existingHandle.requiresUserPresence),
897
+ methodCapabilities: methodCapabilities(await client.identityMethodCapabilities(value.existingHandle.expectedDid))
830
898
  };
831
899
  });
832
900
  }
@@ -899,17 +967,33 @@ var RustSdkAdapter = class {
899
967
  }
900
968
  prepareDeviceJoinApproval(joinSessionId) {
901
969
  return this.run(async (client) => {
902
- return { approvalHandle: required((await client.prepareDeviceJoinApproval({
970
+ const identity = await client.getDefaultIdentity();
971
+ if (identity === null) fail("not-registered");
972
+ const capabilities = await client.identityMethodCapabilities(identity.did);
973
+ const value = await client.prepareDeviceJoinApproval({
903
974
  joinSessionId,
904
975
  sasConfirmed: true
905
- })).approvalHandle) };
976
+ });
977
+ this.approvalManagement.set(value.approvalHandle, capabilities.rootTransfer);
978
+ return { approvalHandle: required(value.approvalHandle) };
906
979
  });
907
980
  }
981
+ deviceJoinManagementStatus() {
982
+ return this.run((client) => client.deviceJoinManagementStatus());
983
+ }
984
+ retryDeviceJoinManagement(joinSessionId) {
985
+ return this.run((client) => client.retryDeviceJoinManagement({ joinSessionId }));
986
+ }
908
987
  confirmDeviceJoinApproval(approvalHandle) {
909
- return this.run(async (client) => adminJoinProgress(await client.confirmDeviceJoinApproval({
910
- approvalHandle,
911
- userPresenceConfirmed: true
912
- })));
988
+ return this.run(async (client) => {
989
+ const request = {
990
+ approvalHandle,
991
+ userPresenceConfirmed: true
992
+ };
993
+ const result = this.approvalManagement.get(approvalHandle) === false ? await client.confirmDeviceJoinApproval(request) : await client.confirmDeviceJoinWithManagement(request);
994
+ this.approvalManagement.delete(approvalHandle);
995
+ return adminJoinProgress(result);
996
+ });
913
997
  }
914
998
  rejectDeviceJoin(joinSessionId, reason) {
915
999
  return this.run(async (client) => adminJoinProgress(await client.rejectDeviceJoin({