@bcts/frost-hubert 1.0.0-beta.1 → 1.0.0-beta.2

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 (110) hide show
  1. package/dist/bin/frost.cjs +16 -16
  2. package/dist/bin/frost.cjs.map +1 -1
  3. package/dist/bin/frost.mjs +16 -16
  4. package/dist/bin/frost.mjs.map +1 -1
  5. package/dist/cmd/index.cjs +3 -3
  6. package/dist/cmd/index.mjs +3 -3
  7. package/dist/{cmd-CCVhHzG7.cjs → cmd-Cd5Bmjy8.cjs} +26 -26
  8. package/dist/{cmd-DNsHd19v.mjs.map → cmd-Cd5Bmjy8.cjs.map} +1 -1
  9. package/dist/{cmd-DNsHd19v.mjs → cmd-ChW3eHA8.mjs} +20 -20
  10. package/dist/{cmd-CCVhHzG7.cjs.map → cmd-ChW3eHA8.mjs.map} +1 -1
  11. package/dist/{common-DNrD_-EI.mjs → common--IfAHVkl.mjs} +2 -2
  12. package/dist/{common-DNrD_-EI.mjs.map → common--IfAHVkl.mjs.map} +1 -1
  13. package/dist/{common-CnvAUC2b.cjs → common-3msAx7hO.cjs} +3 -3
  14. package/dist/{common-CnvAUC2b.cjs.map → common-3msAx7hO.cjs.map} +1 -1
  15. package/dist/{common-Cf1UvJaP.mjs → common-4spC1kNw.mjs} +2 -2
  16. package/dist/{common-Cf1UvJaP.mjs.map → common-4spC1kNw.mjs.map} +1 -1
  17. package/dist/{common-7-BOgaTt.cjs → common-CeTqMwj0.cjs} +2 -2
  18. package/dist/{common-7-BOgaTt.cjs.map → common-CeTqMwj0.cjs.map} +1 -1
  19. package/dist/dkg/index.cjs.map +1 -1
  20. package/dist/dkg/index.mjs.map +1 -1
  21. package/dist/{finalize-BpC0rz93.mjs → finalize-BAwtGCQW.mjs} +4 -4
  22. package/dist/{finalize-BpC0rz93.mjs.map → finalize-BAwtGCQW.mjs.map} +1 -1
  23. package/dist/{finalize-Cb0obTSo.cjs → finalize-BUUNWqKC.cjs} +7 -7
  24. package/dist/{finalize-Cb0obTSo.cjs.map → finalize-BUUNWqKC.cjs.map} +1 -1
  25. package/dist/{finalize-DtRxHZ7H.mjs → finalize-Bm5RZIox.mjs} +3 -3
  26. package/dist/{finalize-DtRxHZ7H.mjs.map → finalize-Bm5RZIox.mjs.map} +1 -1
  27. package/dist/{finalize-T83Ko8nG.mjs → finalize-CELJsR4C.mjs} +4 -4
  28. package/dist/{finalize-T83Ko8nG.mjs.map → finalize-CELJsR4C.mjs.map} +1 -1
  29. package/dist/{finalize-DQ0VGUHO.cjs → finalize-D091kTVy.cjs} +7 -7
  30. package/dist/{finalize-DQ0VGUHO.cjs.map → finalize-D091kTVy.cjs.map} +1 -1
  31. package/dist/{finalize-DHEnKobp.cjs → finalize-SzzTi9BL.cjs} +6 -6
  32. package/dist/{finalize-DHEnKobp.cjs.map → finalize-SzzTi9BL.cjs.map} +1 -1
  33. package/dist/frost/index.cjs +2 -2
  34. package/dist/frost/index.cjs.map +1 -1
  35. package/dist/frost/index.d.cts.map +1 -1
  36. package/dist/frost/index.d.mts.map +1 -1
  37. package/dist/frost/index.mjs +1 -1
  38. package/dist/frost/index.mjs.map +1 -1
  39. package/dist/index-BErX9AZF.d.cts.map +1 -1
  40. package/dist/index-BaUVw4b1.d.mts.map +1 -1
  41. package/dist/index-CD50Qtgw.d.cts.map +1 -1
  42. package/dist/index-CD50Qtgw.d.mts.map +1 -1
  43. package/dist/index-Drklne-Y.d.mts.map +1 -1
  44. package/dist/index-gkmZzEuD.d.cts.map +1 -1
  45. package/dist/index.cjs +3 -3
  46. package/dist/index.d.cts.map +1 -1
  47. package/dist/index.d.mts.map +1 -1
  48. package/dist/index.mjs +3 -3
  49. package/dist/{invite-BLwtexAu.cjs → invite-5sYctfsS.cjs} +6 -6
  50. package/dist/{invite-BLwtexAu.cjs.map → invite-5sYctfsS.cjs.map} +1 -1
  51. package/dist/{invite-D8mQSnFz.mjs → invite-DNlTkwzM.mjs} +4 -4
  52. package/dist/{invite-D8mQSnFz.mjs.map → invite-DNlTkwzM.mjs.map} +1 -1
  53. package/dist/{invite-1tzg0B0P.cjs → invite-T3L4N2m0.cjs} +7 -7
  54. package/dist/{invite-1tzg0B0P.cjs.map → invite-T3L4N2m0.cjs.map} +1 -1
  55. package/dist/{invite-Be2v2SVc.mjs → invite-vRv9LMEE.mjs} +3 -3
  56. package/dist/{invite-Be2v2SVc.mjs.map → invite-vRv9LMEE.mjs.map} +1 -1
  57. package/dist/parallel-PZiwHZT8.mjs.map +1 -1
  58. package/dist/parallel-szwYx-bi.cjs.map +1 -1
  59. package/dist/proposed-participant-BvHNnpcZ.cjs.map +1 -1
  60. package/dist/proposed-participant-Detb823_.mjs.map +1 -1
  61. package/dist/{receive-g8EhZF2Y.mjs → receive-Bzn87ahI.mjs} +4 -4
  62. package/dist/{receive-g8EhZF2Y.mjs.map → receive-Bzn87ahI.mjs.map} +1 -1
  63. package/dist/{receive-dkSCSGpl.mjs → receive-C2Dwb_FQ.mjs} +4 -4
  64. package/dist/{receive-dkSCSGpl.mjs.map → receive-C2Dwb_FQ.mjs.map} +1 -1
  65. package/dist/{receive-D_r4Mryr.cjs → receive-Coqg6eFx.cjs} +7 -7
  66. package/dist/{receive-D_r4Mryr.cjs.map → receive-Coqg6eFx.cjs.map} +1 -1
  67. package/dist/{receive-BR-knnGv.cjs → receive-DZARudBa.cjs} +7 -7
  68. package/dist/{receive-BR-knnGv.cjs.map → receive-DZARudBa.cjs.map} +1 -1
  69. package/dist/registry/index.cjs +3 -3
  70. package/dist/registry/index.cjs.map +1 -1
  71. package/dist/registry/index.mjs.map +1 -1
  72. package/dist/{registry-CkIbA7nt.cjs → registry-D-rFKk9R.cjs} +5 -5
  73. package/dist/{registry-CkIbA7nt.cjs.map → registry-D-rFKk9R.cjs.map} +1 -1
  74. package/dist/{registry-DGjs4qDK.mjs → registry-ycylEdoc.mjs} +2 -2
  75. package/dist/{registry-DGjs4qDK.mjs.map → registry-ycylEdoc.mjs.map} +1 -1
  76. package/dist/{round1-D8t7EzIo.mjs → round1-BRgDPU4Y.mjs} +4 -4
  77. package/dist/{round1-D8t7EzIo.mjs.map → round1-BRgDPU4Y.mjs.map} +1 -1
  78. package/dist/{round1-CXkXoVQU.cjs → round1-BwNBKLYm.cjs} +8 -8
  79. package/dist/{round1-CXkXoVQU.cjs.map → round1-BwNBKLYm.cjs.map} +1 -1
  80. package/dist/{round1-9FAqFvL5.cjs → round1-C1IlXH-9.cjs} +6 -6
  81. package/dist/{round1-9FAqFvL5.cjs.map → round1-C1IlXH-9.cjs.map} +1 -1
  82. package/dist/{round1-DriPu15x.cjs → round1-CEbz7cnL.cjs} +8 -8
  83. package/dist/{round1-DriPu15x.cjs.map → round1-CEbz7cnL.cjs.map} +1 -1
  84. package/dist/{round1-B8haiMM8.mjs → round1-DL4N2QJ5.mjs} +5 -5
  85. package/dist/{round1-B8haiMM8.mjs.map → round1-DL4N2QJ5.mjs.map} +1 -1
  86. package/dist/{round1-BOIE1E4O.mjs → round1-DSaOFCar.mjs} +3 -3
  87. package/dist/{round1-BOIE1E4O.mjs.map → round1-DSaOFCar.mjs.map} +1 -1
  88. package/dist/{round1-Y2kcVwnR.mjs → round1-_fHip4H1.mjs} +5 -5
  89. package/dist/{round1-Y2kcVwnR.mjs.map → round1-_fHip4H1.mjs.map} +1 -1
  90. package/dist/{round1-Bq0vweyQ.cjs → round1-ek-G6qVi.cjs} +7 -7
  91. package/dist/{round1-Bq0vweyQ.cjs.map → round1-ek-G6qVi.cjs.map} +1 -1
  92. package/dist/{round2-Dk_w97nl.cjs → round2-BD_0N7Ab.cjs} +6 -6
  93. package/dist/{round2-Dk_w97nl.cjs.map → round2-BD_0N7Ab.cjs.map} +1 -1
  94. package/dist/{round2-Z2JhMwxc.mjs → round2-BLOgZeAo.mjs} +4 -4
  95. package/dist/{round2-Z2JhMwxc.mjs.map → round2-BLOgZeAo.mjs.map} +1 -1
  96. package/dist/{round2-BHQKVJFo.cjs → round2-C684Nir0.cjs} +7 -7
  97. package/dist/{round2-BHQKVJFo.cjs.map → round2-C684Nir0.cjs.map} +1 -1
  98. package/dist/{round2-mF6UlkT-.mjs → round2-CU-yTXHT.mjs} +4 -4
  99. package/dist/{round2-mF6UlkT-.mjs.map → round2-CU-yTXHT.mjs.map} +1 -1
  100. package/dist/{round2-BfetYacV.mjs → round2-Cq2SD6F8.mjs} +3 -3
  101. package/dist/{round2-BfetYacV.mjs.map → round2-Cq2SD6F8.mjs.map} +1 -1
  102. package/dist/{round2-AMDYMUIg.cjs → round2-D8l1PUm5.cjs} +7 -7
  103. package/dist/{round2-AMDYMUIg.cjs.map → round2-D8l1PUm5.cjs.map} +1 -1
  104. package/dist/{round2-CvrmylN1.cjs → round2-DhdFarwY.cjs} +7 -7
  105. package/dist/{round2-CvrmylN1.cjs.map → round2-DhdFarwY.cjs.map} +1 -1
  106. package/dist/{round2-Cf5CJc_8.mjs → round2-DmQvJDVj.mjs} +4 -4
  107. package/dist/{round2-Cf5CJc_8.mjs.map → round2-DmQvJDVj.mjs.map} +1 -1
  108. package/package.json +16 -16
  109. /package/dist/{chunk-DakpK96I.cjs → rolldown-runtime-DakpK96I.cjs} +0 -0
  110. /package/dist/{chunk-z9aeyW2b.mjs → rolldown-runtime-z9aeyW2b.mjs} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;;;;;iBAkCsB,YAAA,CAAA,GAAgB,OAAO"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;;;;;iBAkCsB,YAAA,IAAgB,OAAO"}
package/dist/index.mjs CHANGED
@@ -1,11 +1,11 @@
1
1
  import { n as compareXidBytes, t as DkgProposedParticipant } from "./proposed-participant-Detb823_.mjs";
2
2
  import { DkgInvitation, DkgInvite, accepted, declined } from "./dkg/index.mjs";
3
3
  import { AddOutcome, ContributionPaths, GroupOutcome, GroupParticipant, GroupRecord, OwnerOutcome, OwnerRecord, ParticipantRecord, PendingRequests, Registry, resolveRegistryPath } from "./registry/index.mjs";
4
- import { c as parseAridUr, h as signingKeyFromVerifying, n as isVerbose, r as setVerbose, t as groupStateDir } from "./common-Cf1UvJaP.mjs";
4
+ import { c as parseAridUr, h as signingKeyFromVerifying, n as isVerbose, r as setVerbose, t as groupStateDir } from "./common-4spC1kNw.mjs";
5
5
  import { n as putWithIndicator, t as getWithIndicator } from "./busy-BlU8_pS2.mjs";
6
6
  import { a as directionEmoji, c as fetchStatusPending, d as fetchStatusTimeout, f as parallelFetch, i as buildFetchRequests, l as fetchStatusRejected, m as parallelSend, n as DEFAULT_TIMEOUT_SECONDS, o as emptyCollectionResult, p as parallelFetchConfigWithTimeout, r as Direction, s as fetchStatusError, t as CollectionResult, u as fetchStatusSuccess } from "./parallel-PZiwHZT8.mjs";
7
- import { i as createStorageClient, t as registry_exports } from "./registry-DGjs4qDK.mjs";
8
- import { n as dkg_exports, r as checkAridExists, t as sign_exports } from "./cmd-DNsHd19v.mjs";
7
+ import { i as createStorageClient, t as registry_exports } from "./registry-ycylEdoc.mjs";
8
+ import { n as dkg_exports, r as checkAridExists, t as sign_exports } from "./cmd-ChW3eHA8.mjs";
9
9
  import { t as frost_exports } from "./frost/index.mjs";
10
10
  //#region src/index.ts
11
11
  /**
@@ -1,13 +1,13 @@
1
- const require_chunk = require("./chunk-DakpK96I.cjs");
1
+ const require_rolldown_runtime = require("./rolldown-runtime-DakpK96I.cjs");
2
2
  const require_dkg_index = require("./dkg/index.cjs");
3
3
  const require_registry_index = require("./registry/index.cjs");
4
- const require_common = require("./common-CnvAUC2b.cjs");
4
+ const require_common = require("./common-3msAx7hO.cjs");
5
5
  const require_busy = require("./busy-B_h0bNAJ.cjs");
6
6
  let _bcts_components = require("@bcts/components");
7
7
  let node_fs = require("node:fs");
8
- node_fs = require_chunk.__toESM(node_fs, 1);
8
+ node_fs = require_rolldown_runtime.__toESM(node_fs, 1);
9
9
  let node_path = require("node:path");
10
- node_path = require_chunk.__toESM(node_path, 1);
10
+ node_path = require_rolldown_runtime.__toESM(node_path, 1);
11
11
  //#region src/cmd/dkg/coordinator/invite.ts
12
12
  /**
13
13
  * Copyright © 2023-2026 Blockchain Commons, LLC
@@ -20,7 +20,7 @@ node_path = require_chunk.__toESM(node_path, 1);
20
20
  *
21
21
  * @module
22
22
  */
23
- var invite_exports = /* @__PURE__ */ require_chunk.__exportAll({ invite: () => invite });
23
+ var invite_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({ invite: () => invite });
24
24
  /**
25
25
  * Build the DKG invite with validation.
26
26
  *
@@ -106,4 +106,4 @@ Object.defineProperty(exports, "invite_exports", {
106
106
  }
107
107
  });
108
108
 
109
- //# sourceMappingURL=invite-BLwtexAu.cjs.map
109
+ //# sourceMappingURL=invite-5sYctfsS.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"invite-BLwtexAu.cjs","names":["resolveParticipants","ARID","PendingRequests","resolveOwnerXidDocument","DkgInvite","resolveRegistryPath","Registry","putWithIndicator","GroupParticipant","GroupRecord","dkgStateDir","path"],"sources":["../src/cmd/dkg/coordinator/invite.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * DKG coordinator invite command.\n *\n * Port of cmd/dkg/coordinator/invite.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID, type XID } from \"@bcts/components\";\n\nimport { DkgInvite } from \"../../../dkg/index.js\";\nimport {\n GroupParticipant,\n GroupRecord,\n PendingRequests,\n Registry,\n resolveRegistryPath,\n} from \"../../../registry/index.js\";\nimport { putWithIndicator } from \"../../busy.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { dkgStateDir, resolveOwnerXidDocument, resolveParticipants } from \"../common.js\";\n\n/**\n * Options for the DKG invite command.\n */\nexport interface DkgInviteOptions {\n registryPath?: string;\n minSigners?: number;\n charter: string;\n validDays: number;\n participantNames: string[];\n verbose?: boolean;\n}\n\n/**\n * Result of the DKG invite command.\n */\nexport interface DkgInviteResult {\n groupId: ARID;\n requestId: ARID;\n envelopeUr: string;\n}\n\n/**\n * Internal data structure for building an invite.\n *\n * Port of `InviteData` struct from cmd/dkg/coordinator/invite.rs lines 122-126.\n */\ninterface InviteData {\n invite: DkgInvite;\n participantXids: XID[];\n pendingRequests: PendingRequests;\n}\n\n/**\n * Build the DKG invite with validation.\n *\n * Port of `build_invite()` from cmd/dkg/coordinator/invite.rs lines 128-181.\n */\nfunction buildInvite(\n registry: Registry,\n minSignersArg: number | undefined,\n charter: string,\n participantNames: string[],\n validDays: number,\n): InviteData {\n // Resolve participants using the common utility\n const resolved = resolveParticipants(registry, participantNames);\n const participantDocs: string[] = resolved.map(([, record]) => record.xidDocumentUr());\n const participantXids: XID[] = resolved.map(([xid]) => xid);\n\n // These are the ARIDs where participants will post their invite responses\n const collectFromArids: ARID[] = participantDocs.map(() => ARID.new());\n\n // Build pending_requests: coordinator will collect invite responses from these ARIDs\n const pendingRequests = new PendingRequests();\n for (let i = 0; i < participantXids.length; i++) {\n pendingRequests.addCollectOnly(participantXids[i], collectFromArids[i]);\n }\n\n // Validate participant count\n const participantCount = participantDocs.length;\n if (participantCount < 2) {\n throw new Error(\"At least two participants are required for a DKG invite\");\n }\n\n // Validate and default minSigners\n const minSigners = minSignersArg ?? participantCount;\n if (minSigners < 2) {\n throw new Error(\"--min-signers must be at least 2\");\n }\n if (minSigners > participantCount) {\n throw new Error(\"--min-signers cannot exceed participant count\");\n }\n\n // Get sender (registry owner)\n // The coordinator's invite always identifies the registry owner as\n // the sender. (Rust reads `registry.owner()` directly here too —\n // see `cmd/dkg/coordinator/invite.rs:74-77`.)\n const sender = resolveOwnerXidDocument(registry);\n\n // Calculate dates\n const now = new Date();\n const validUntil = new Date(Date.now() + validDays * 24 * 60 * 60 * 1000);\n\n // Create the invite\n const invite = DkgInvite.create(\n ARID.new(), // requestId\n sender,\n ARID.new(), // groupId\n now,\n validUntil,\n minSigners,\n charter,\n participantDocs,\n collectFromArids,\n );\n\n return { invite, participantXids, pendingRequests };\n}\n\n/**\n * Execute the DKG invite command.\n *\n * Port of `invite()` from cmd/dkg/coordinator/invite.rs.\n */\nexport async function invite(\n client: StorageClient,\n options: DkgInviteOptions,\n cwd: string,\n): Promise<DkgInviteResult> {\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n // Build the invite with validation\n const inviteData = buildInvite(\n registry,\n options.minSigners,\n options.charter,\n options.participantNames,\n options.validDays,\n );\n\n const { invite: dkgInvite, participantXids, pendingRequests } = inviteData;\n const groupId = dkgInvite.groupId();\n const requestId = dkgInvite.requestId();\n\n // Create sealed envelope\n const envelope = dkgInvite.toEnvelope();\n\n // Send to storage\n const startArid = ARID.new();\n await putWithIndicator(\n client,\n startArid,\n envelope,\n \"Sending DKG invite\",\n options.verbose ?? false,\n );\n\n // Save group record to registry\n const owner = registry.owner();\n if (!owner) {\n throw new Error(\"Registry owner is required to issue invites\");\n }\n\n const coordinator = new GroupParticipant(owner.xid());\n const groupParticipants = participantXids.map((xid) => new GroupParticipant(xid));\n\n const groupRecord = new GroupRecord(\n options.charter,\n dkgInvite.minSigners(),\n coordinator,\n groupParticipants,\n );\n\n // Track pending requests\n groupRecord.setPendingRequests(pendingRequests);\n\n // Use recordGroup() for proper merge behavior\n registry.recordGroup(groupId, groupRecord);\n registry.save(registryPath);\n\n // Save invite state\n const stateDir = dkgStateDir(registryPath, groupId.hex());\n fs.mkdirSync(stateDir, { recursive: true });\n\n const inviteState: {\n group: string;\n request_id: string;\n start_arid: string;\n valid_until: string;\n participants: { xid: string; response_arid: string }[];\n } = {\n group: groupId.urString(),\n request_id: requestId.urString(),\n start_arid: startArid.urString(),\n valid_until: dkgInvite.validUntil().toISOString(),\n participants: dkgInvite.participants().map((p) => ({\n xid: p.xid().urString(),\n response_arid: p.responseArid().urString(),\n })),\n };\n\n fs.writeFileSync(path.join(stateDir, \"invite.json\"), JSON.stringify(inviteState, null, 2));\n\n if (options.verbose === true) {\n console.log(`Group ID: ${groupId.urString()}`);\n console.log(`Start ARID: ${startArid.urString()}`);\n }\n\n return {\n groupId,\n requestId,\n envelopeUr: envelope.urString(),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"invite-5sYctfsS.cjs","names":["resolveParticipants","ARID","PendingRequests","resolveOwnerXidDocument","DkgInvite","resolveRegistryPath","Registry","putWithIndicator","GroupParticipant","GroupRecord","dkgStateDir","path"],"sources":["../src/cmd/dkg/coordinator/invite.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * DKG coordinator invite command.\n *\n * Port of cmd/dkg/coordinator/invite.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID, type XID } from \"@bcts/components\";\n\nimport { DkgInvite } from \"../../../dkg/index.js\";\nimport {\n GroupParticipant,\n GroupRecord,\n PendingRequests,\n Registry,\n resolveRegistryPath,\n} from \"../../../registry/index.js\";\nimport { putWithIndicator } from \"../../busy.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { dkgStateDir, resolveOwnerXidDocument, resolveParticipants } from \"../common.js\";\n\n/**\n * Options for the DKG invite command.\n */\nexport interface DkgInviteOptions {\n registryPath?: string;\n minSigners?: number;\n charter: string;\n validDays: number;\n participantNames: string[];\n verbose?: boolean;\n}\n\n/**\n * Result of the DKG invite command.\n */\nexport interface DkgInviteResult {\n groupId: ARID;\n requestId: ARID;\n envelopeUr: string;\n}\n\n/**\n * Internal data structure for building an invite.\n *\n * Port of `InviteData` struct from cmd/dkg/coordinator/invite.rs lines 122-126.\n */\ninterface InviteData {\n invite: DkgInvite;\n participantXids: XID[];\n pendingRequests: PendingRequests;\n}\n\n/**\n * Build the DKG invite with validation.\n *\n * Port of `build_invite()` from cmd/dkg/coordinator/invite.rs lines 128-181.\n */\nfunction buildInvite(\n registry: Registry,\n minSignersArg: number | undefined,\n charter: string,\n participantNames: string[],\n validDays: number,\n): InviteData {\n // Resolve participants using the common utility\n const resolved = resolveParticipants(registry, participantNames);\n const participantDocs: string[] = resolved.map(([, record]) => record.xidDocumentUr());\n const participantXids: XID[] = resolved.map(([xid]) => xid);\n\n // These are the ARIDs where participants will post their invite responses\n const collectFromArids: ARID[] = participantDocs.map(() => ARID.new());\n\n // Build pending_requests: coordinator will collect invite responses from these ARIDs\n const pendingRequests = new PendingRequests();\n for (let i = 0; i < participantXids.length; i++) {\n pendingRequests.addCollectOnly(participantXids[i], collectFromArids[i]);\n }\n\n // Validate participant count\n const participantCount = participantDocs.length;\n if (participantCount < 2) {\n throw new Error(\"At least two participants are required for a DKG invite\");\n }\n\n // Validate and default minSigners\n const minSigners = minSignersArg ?? participantCount;\n if (minSigners < 2) {\n throw new Error(\"--min-signers must be at least 2\");\n }\n if (minSigners > participantCount) {\n throw new Error(\"--min-signers cannot exceed participant count\");\n }\n\n // Get sender (registry owner)\n // The coordinator's invite always identifies the registry owner as\n // the sender. (Rust reads `registry.owner()` directly here too —\n // see `cmd/dkg/coordinator/invite.rs:74-77`.)\n const sender = resolveOwnerXidDocument(registry);\n\n // Calculate dates\n const now = new Date();\n const validUntil = new Date(Date.now() + validDays * 24 * 60 * 60 * 1000);\n\n // Create the invite\n const invite = DkgInvite.create(\n ARID.new(), // requestId\n sender,\n ARID.new(), // groupId\n now,\n validUntil,\n minSigners,\n charter,\n participantDocs,\n collectFromArids,\n );\n\n return { invite, participantXids, pendingRequests };\n}\n\n/**\n * Execute the DKG invite command.\n *\n * Port of `invite()` from cmd/dkg/coordinator/invite.rs.\n */\nexport async function invite(\n client: StorageClient,\n options: DkgInviteOptions,\n cwd: string,\n): Promise<DkgInviteResult> {\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n // Build the invite with validation\n const inviteData = buildInvite(\n registry,\n options.minSigners,\n options.charter,\n options.participantNames,\n options.validDays,\n );\n\n const { invite: dkgInvite, participantXids, pendingRequests } = inviteData;\n const groupId = dkgInvite.groupId();\n const requestId = dkgInvite.requestId();\n\n // Create sealed envelope\n const envelope = dkgInvite.toEnvelope();\n\n // Send to storage\n const startArid = ARID.new();\n await putWithIndicator(\n client,\n startArid,\n envelope,\n \"Sending DKG invite\",\n options.verbose ?? false,\n );\n\n // Save group record to registry\n const owner = registry.owner();\n if (!owner) {\n throw new Error(\"Registry owner is required to issue invites\");\n }\n\n const coordinator = new GroupParticipant(owner.xid());\n const groupParticipants = participantXids.map((xid) => new GroupParticipant(xid));\n\n const groupRecord = new GroupRecord(\n options.charter,\n dkgInvite.minSigners(),\n coordinator,\n groupParticipants,\n );\n\n // Track pending requests\n groupRecord.setPendingRequests(pendingRequests);\n\n // Use recordGroup() for proper merge behavior\n registry.recordGroup(groupId, groupRecord);\n registry.save(registryPath);\n\n // Save invite state\n const stateDir = dkgStateDir(registryPath, groupId.hex());\n fs.mkdirSync(stateDir, { recursive: true });\n\n const inviteState: {\n group: string;\n request_id: string;\n start_arid: string;\n valid_until: string;\n participants: { xid: string; response_arid: string }[];\n } = {\n group: groupId.urString(),\n request_id: requestId.urString(),\n start_arid: startArid.urString(),\n valid_until: dkgInvite.validUntil().toISOString(),\n participants: dkgInvite.participants().map((p) => ({\n xid: p.xid().urString(),\n response_arid: p.responseArid().urString(),\n })),\n };\n\n fs.writeFileSync(path.join(stateDir, \"invite.json\"), JSON.stringify(inviteState, null, 2));\n\n if (options.verbose === true) {\n console.log(`Group ID: ${groupId.urString()}`);\n console.log(`Start ARID: ${startArid.urString()}`);\n }\n\n return {\n groupId,\n requestId,\n envelopeUr: envelope.urString(),\n };\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
- import { t as __exportAll } from "./chunk-z9aeyW2b.mjs";
1
+ import { t as __exportAll } from "./rolldown-runtime-z9aeyW2b.mjs";
2
2
  import { Registry, resolveRegistryPath } from "./registry/index.mjs";
3
- import { c as parseAridUr } from "./common-Cf1UvJaP.mjs";
3
+ import { c as parseAridUr } from "./common-4spC1kNw.mjs";
4
4
  import { n as putWithIndicator } from "./busy-BlU8_pS2.mjs";
5
- import { n as signingStateDir } from "./common-DNrD_-EI.mjs";
5
+ import { n as signingStateDir } from "./common--IfAHVkl.mjs";
6
6
  import { ARID } from "@bcts/components";
7
7
  import { CborDate } from "@bcts/dcbor";
8
8
  import { Envelope } from "@bcts/envelope";
@@ -216,4 +216,4 @@ async function invite(client, options, cwd) {
216
216
  //#endregion
217
217
  export { invite as a, persistSessionState as c, gatherRecipientDocuments as i, validateCoordinator as l, buildSignInviteRequest as n, invite_exports as o, createSessionArids as r, loadEnvelopeFromPath as s, buildSessionStateJson as t };
218
218
 
219
- //# sourceMappingURL=invite-D8mQSnFz.mjs.map
219
+ //# sourceMappingURL=invite-DNlTkwzM.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"invite-D8mQSnFz.mjs","names":[],"sources":["../src/cmd/sign/coordinator/invite.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * Sign coordinator invite command.\n *\n * Port of cmd/sign/coordinator/invite.rs from frost-hubert-rust.\n *\n * @module\n */\n\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-argument */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID } from \"@bcts/components\";\nimport { CborDate } from \"@bcts/dcbor\";\nimport { Envelope } from \"@bcts/envelope\";\nimport { SealedRequest } from \"@bcts/gstp\";\nimport { type XIDDocument } from \"@bcts/xid\";\n\nimport {\n Registry,\n resolveRegistryPath,\n type GroupRecord,\n type GroupParticipant,\n type OwnerRecord,\n} from \"../../../registry/index.js\";\nimport { putWithIndicator } from \"../../busy.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { parseAridUr } from \"../../dkg/common.js\";\nimport { signingStateDir } from \"../common.js\";\n\n// -----------------------------------------------------------------------------\n// Session ARID management\n// -----------------------------------------------------------------------------\n\n/**\n * Session ARIDs for tracking the signing session.\n *\n * Port of `struct SessionArids` from cmd/sign/coordinator/invite.rs lines 151-156.\n */\nexport interface SessionArids {\n sessionId: ARID;\n startArid: ARID;\n commitArids: Map<string, ARID>; // Map<XID.urString(), ARID>\n shareArids: Map<string, ARID>; // Map<XID.urString(), ARID>\n}\n\n/**\n * Create new session ARIDs for all participants.\n *\n * Port of `SessionArids::new()` from cmd/sign/coordinator/invite.rs lines 158-173.\n */\nexport function createSessionArids(participants: GroupParticipant[]): SessionArids {\n const commitArids = new Map<string, ARID>();\n const shareArids = new Map<string, ARID>();\n\n for (const participant of participants) {\n const xidKey = participant.xid().urString();\n commitArids.set(xidKey, ARID.new());\n shareArids.set(xidKey, ARID.new());\n }\n\n return {\n sessionId: ARID.new(),\n startArid: ARID.new(),\n commitArids,\n shareArids,\n };\n}\n\n// -----------------------------------------------------------------------------\n// Validation\n// -----------------------------------------------------------------------------\n\n/**\n * Validate that the owner is the coordinator of the group.\n *\n * Port of `validate_coordinator()` from cmd/sign/coordinator/invite.rs lines 179-192.\n */\nexport function validateCoordinator(groupRecord: GroupRecord, owner: OwnerRecord): void {\n if (groupRecord.coordinator().xid().urString() !== owner.xid().urString()) {\n throw new Error(\n `Only the coordinator can start signing. Coordinator: ${groupRecord.coordinator().xid().urString()}, Owner: ${owner.xid().urString()}`,\n );\n }\n}\n\n// -----------------------------------------------------------------------------\n// Participant document gathering\n// -----------------------------------------------------------------------------\n\n/**\n * Gather XIDDocuments for all participants from the registry.\n *\n * Port of `gather_recipient_documents()` from cmd/sign/coordinator/invite.rs lines 198-222.\n */\nexport function gatherRecipientDocuments(\n participants: GroupParticipant[],\n owner: OwnerRecord,\n registry: Registry,\n): XIDDocument[] {\n const recipientDocs: XIDDocument[] = [];\n\n for (const participant of participants) {\n const xid = participant.xid();\n if (xid.urString() === owner.xid().urString()) {\n recipientDocs.push(owner.xidDocument());\n } else {\n const record = registry.participant(xid);\n if (record === undefined) {\n throw new Error(`Participant ${xid.urString()} not found in registry`);\n }\n recipientDocs.push(record.xidDocument());\n }\n }\n\n return recipientDocs;\n}\n\n// -----------------------------------------------------------------------------\n// Request building\n// -----------------------------------------------------------------------------\n\n/**\n * Context for building the sign invite request.\n *\n * Port of `struct SignInviteContext` from cmd/sign/coordinator/invite.rs lines 228-237.\n */\nexport interface SignInviteContext {\n arids: SessionArids;\n groupId: ARID;\n targetEnvelope: Envelope;\n groupRecord: GroupRecord;\n owner: OwnerRecord;\n registry: Registry;\n participants: GroupParticipant[];\n validUntil: Date;\n}\n\n/**\n * Build the sign invite request.\n *\n * Port of `build_sign_invite_request()` from cmd/sign/coordinator/invite.rs lines 239-284.\n */\nexport function buildSignInviteRequest(ctx: SignInviteContext): SealedRequest {\n let request = SealedRequest.new(\"signInvite\", ctx.arids.sessionId, ctx.owner.xidDocument())\n .withParameter(\"group\", ctx.groupId)\n .withParameter(\"session\", ctx.arids.sessionId)\n .withParameter(\"target\", ctx.targetEnvelope)\n .withParameter(\"minSigners\", ctx.groupRecord.minSigners())\n .withDate(new Date())\n .withParameter(\"validUntil\", CborDate.fromDatetime(ctx.validUntil));\n\n for (const participant of ctx.participants) {\n const xid = participant.xid();\n const xidKey = xid.urString();\n\n // Get participant document\n let participantDoc: XIDDocument;\n if (xidKey === ctx.owner.xid().urString()) {\n participantDoc = ctx.owner.xidDocument();\n } else {\n const record = ctx.registry.participant(xid);\n if (record === undefined) {\n throw new Error(\"Participant not found in registry\");\n }\n participantDoc = record.xidDocument();\n }\n\n // Get encryption key\n const encryptionKey = participantDoc.encryptionKey();\n if (encryptionKey === undefined) {\n throw new Error(\"Participant XID document has no encryption key\");\n }\n\n // Get commit ARID for this participant\n const responseArid = ctx.arids.commitArids.get(xidKey);\n if (responseArid === undefined) {\n throw new Error(\"commit ARID not found for participant\");\n }\n\n // Encrypt response ARID to participant\n // @ts-expect-error TS2339 - API mismatch: toEnvelope/encryptToRecipient methods\n const encryptedResponseArid = responseArid.toEnvelope().encryptToRecipient(encryptionKey);\n\n // Build participant entry envelope\n const participantEntry = Envelope.new(xid).addAssertion(\"response_arid\", encryptedResponseArid);\n\n request = request.withParameter(\"participant\", participantEntry);\n }\n\n return request;\n}\n\n// -----------------------------------------------------------------------------\n// State persistence\n// -----------------------------------------------------------------------------\n\n/**\n * Build the session state JSON for persistence.\n *\n * Port of `build_session_state_json()` from cmd/sign/coordinator/invite.rs lines 290-346.\n */\nexport function buildSessionStateJson(\n arids: SessionArids,\n groupId: ARID,\n groupRecord: GroupRecord,\n participants: GroupParticipant[],\n targetEnvelope: Envelope,\n): Record<string, unknown> {\n const participantsMap: Record<string, unknown> = {};\n\n for (const participant of participants) {\n const xid = participant.xid();\n const xidKey = xid.urString();\n\n const commitArid = arids.commitArids.get(xidKey);\n const shareArid = arids.shareArids.get(xidKey);\n\n if (commitArid === undefined || shareArid === undefined) {\n throw new Error(\"ARID not found for participant\");\n }\n\n participantsMap[xidKey] = {\n commit_arid: commitArid.urString(),\n share_arid: shareArid.urString(),\n };\n }\n\n return {\n session_id: arids.sessionId.urString(),\n start_arid: arids.startArid.urString(),\n group: groupId.urString(),\n min_signers: groupRecord.minSigners(),\n participants: participantsMap,\n target: targetEnvelope.urString(),\n };\n}\n\n/**\n * Persist the session state to disk.\n *\n * Port of `persist_session_state()` from cmd/sign/coordinator/invite.rs lines 348-356.\n */\nexport function persistSessionState(signingDir: string, stateJson: Record<string, unknown>): void {\n fs.mkdirSync(signingDir, { recursive: true });\n const startStatePath = path.join(signingDir, \"start.json\");\n fs.writeFileSync(startStatePath, JSON.stringify(stateJson, null, 2));\n}\n\n// -----------------------------------------------------------------------------\n// File loading\n// -----------------------------------------------------------------------------\n\n/**\n * Load an envelope from a file path.\n *\n * Port of `load_envelope_from_path()` from cmd/sign/coordinator/invite.rs lines 385-392.\n */\nexport function loadEnvelopeFromPath(filePath: string): Envelope {\n if (!fs.existsSync(filePath)) {\n throw new Error(`Failed to read target envelope from ${filePath}`);\n }\n\n const data = fs.readFileSync(filePath, \"utf-8\");\n const trimmed = data.trim();\n\n try {\n return Envelope.fromURString(trimmed);\n } catch (e) {\n throw new Error(`Failed to load target envelope from ${filePath}: ${String(e)}`, { cause: e });\n }\n}\n\n// -----------------------------------------------------------------------------\n// Options and Result types\n// -----------------------------------------------------------------------------\n\n/**\n * Options for the sign invite command.\n */\nexport interface SignInviteOptions {\n registryPath?: string;\n groupId: string;\n targetFile: string;\n validDays?: number;\n verbose?: boolean;\n preview?: boolean;\n}\n\n/**\n * Result of the sign invite command.\n */\nexport interface SignInviteResult {\n sessionId: string;\n startArid: string;\n}\n\n// -----------------------------------------------------------------------------\n// Main invite function\n// -----------------------------------------------------------------------------\n\n/**\n * Execute the sign coordinator invite command.\n *\n * Invites participants to sign a target envelope.\n *\n * Port of `CommandArgs::exec()` from cmd/sign/coordinator/invite.rs lines 44-144.\n */\nexport async function invite(\n client: StorageClient | undefined,\n options: SignInviteOptions,\n cwd: string,\n): Promise<SignInviteResult> {\n // Validate preview mode\n if (client !== undefined && options.preview === true) {\n throw new Error(\"--preview cannot be used with Hubert storage options\");\n }\n\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (owner === undefined) {\n throw new Error(\"Registry owner is required\");\n }\n\n const groupId = parseAridUr(options.groupId);\n const groupRecord = registry.group(groupId);\n\n if (groupRecord === undefined) {\n throw new Error(`Group ${options.groupId} not found in registry`);\n }\n\n // Validate sender is coordinator\n validateCoordinator(groupRecord, owner);\n\n // Load target envelope\n const targetPath = path.resolve(cwd, options.targetFile);\n const targetEnvelope = loadEnvelopeFromPath(targetPath);\n\n // Get participants\n const participants = groupRecord.participants();\n\n // Gather recipient documents\n const recipientDocs = gatherRecipientDocuments(participants, owner, registry);\n\n // Get signer keys\n const signerKeys = owner.xidDocument().inceptionPrivateKeys();\n if (signerKeys === undefined) {\n throw new Error(\"Coordinator XID document has no signing keys\");\n }\n\n // Generate session ARIDs\n const sessionArids = createSessionArids(participants);\n\n // Calculate valid until date (default 1 hour)\n const validDays = options.validDays ?? 1 / 24; // 1 hour default\n const validUntil = new Date(Date.now() + validDays * 24 * 60 * 60 * 1000);\n\n // Build request context\n const ctx: SignInviteContext = {\n arids: sessionArids,\n groupId,\n targetEnvelope,\n groupRecord,\n owner,\n registry,\n participants,\n validUntil,\n };\n\n // Build request\n const request = buildSignInviteRequest(ctx);\n\n // Build state for persistence\n const stateJson = buildSessionStateJson(\n sessionArids,\n groupId,\n groupRecord,\n participants,\n targetEnvelope,\n );\n\n // Build envelope for recipients\n const recipientRefs = recipientDocs;\n const sealedEnvelope = request.toEnvelopeForRecipients(validUntil, signerKeys, recipientRefs);\n\n // Handle preview mode\n if (options.preview === true) {\n const unsealed = request.toEnvelope(undefined, signerKeys, undefined);\n console.log(unsealed.urString());\n return {\n sessionId: sessionArids.sessionId.urString(),\n startArid: sessionArids.startArid.urString(),\n };\n }\n\n // Persist state\n const signingDir = signingStateDir(registryPath, groupId.hex(), sessionArids.sessionId.hex());\n persistSessionState(signingDir, stateJson);\n\n // Post to Hubert storage\n if (client === undefined) {\n throw new Error(\"Hubert storage is required for sign start\");\n }\n\n await putWithIndicator(\n client,\n sessionArids.startArid,\n sealedEnvelope,\n \"Signing invite\",\n options.verbose ?? false,\n );\n\n if (options.verbose === true) {\n console.log(`Session ID: ${sessionArids.sessionId.urString()}`);\n console.log(`Start ARID: ${sessionArids.startArid.urString()}`);\n }\n\n // Output the start ARID\n console.log(sessionArids.startArid.urString());\n\n return {\n sessionId: sessionArids.sessionId.urString(),\n startArid: sessionArids.startArid.urString(),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"invite-DNlTkwzM.mjs","names":[],"sources":["../src/cmd/sign/coordinator/invite.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * Sign coordinator invite command.\n *\n * Port of cmd/sign/coordinator/invite.rs from frost-hubert-rust.\n *\n * @module\n */\n\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-argument */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID } from \"@bcts/components\";\nimport { CborDate } from \"@bcts/dcbor\";\nimport { Envelope } from \"@bcts/envelope\";\nimport { SealedRequest } from \"@bcts/gstp\";\nimport { type XIDDocument } from \"@bcts/xid\";\n\nimport {\n Registry,\n resolveRegistryPath,\n type GroupRecord,\n type GroupParticipant,\n type OwnerRecord,\n} from \"../../../registry/index.js\";\nimport { putWithIndicator } from \"../../busy.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { parseAridUr } from \"../../dkg/common.js\";\nimport { signingStateDir } from \"../common.js\";\n\n// -----------------------------------------------------------------------------\n// Session ARID management\n// -----------------------------------------------------------------------------\n\n/**\n * Session ARIDs for tracking the signing session.\n *\n * Port of `struct SessionArids` from cmd/sign/coordinator/invite.rs lines 151-156.\n */\nexport interface SessionArids {\n sessionId: ARID;\n startArid: ARID;\n commitArids: Map<string, ARID>; // Map<XID.urString(), ARID>\n shareArids: Map<string, ARID>; // Map<XID.urString(), ARID>\n}\n\n/**\n * Create new session ARIDs for all participants.\n *\n * Port of `SessionArids::new()` from cmd/sign/coordinator/invite.rs lines 158-173.\n */\nexport function createSessionArids(participants: GroupParticipant[]): SessionArids {\n const commitArids = new Map<string, ARID>();\n const shareArids = new Map<string, ARID>();\n\n for (const participant of participants) {\n const xidKey = participant.xid().urString();\n commitArids.set(xidKey, ARID.new());\n shareArids.set(xidKey, ARID.new());\n }\n\n return {\n sessionId: ARID.new(),\n startArid: ARID.new(),\n commitArids,\n shareArids,\n };\n}\n\n// -----------------------------------------------------------------------------\n// Validation\n// -----------------------------------------------------------------------------\n\n/**\n * Validate that the owner is the coordinator of the group.\n *\n * Port of `validate_coordinator()` from cmd/sign/coordinator/invite.rs lines 179-192.\n */\nexport function validateCoordinator(groupRecord: GroupRecord, owner: OwnerRecord): void {\n if (groupRecord.coordinator().xid().urString() !== owner.xid().urString()) {\n throw new Error(\n `Only the coordinator can start signing. Coordinator: ${groupRecord.coordinator().xid().urString()}, Owner: ${owner.xid().urString()}`,\n );\n }\n}\n\n// -----------------------------------------------------------------------------\n// Participant document gathering\n// -----------------------------------------------------------------------------\n\n/**\n * Gather XIDDocuments for all participants from the registry.\n *\n * Port of `gather_recipient_documents()` from cmd/sign/coordinator/invite.rs lines 198-222.\n */\nexport function gatherRecipientDocuments(\n participants: GroupParticipant[],\n owner: OwnerRecord,\n registry: Registry,\n): XIDDocument[] {\n const recipientDocs: XIDDocument[] = [];\n\n for (const participant of participants) {\n const xid = participant.xid();\n if (xid.urString() === owner.xid().urString()) {\n recipientDocs.push(owner.xidDocument());\n } else {\n const record = registry.participant(xid);\n if (record === undefined) {\n throw new Error(`Participant ${xid.urString()} not found in registry`);\n }\n recipientDocs.push(record.xidDocument());\n }\n }\n\n return recipientDocs;\n}\n\n// -----------------------------------------------------------------------------\n// Request building\n// -----------------------------------------------------------------------------\n\n/**\n * Context for building the sign invite request.\n *\n * Port of `struct SignInviteContext` from cmd/sign/coordinator/invite.rs lines 228-237.\n */\nexport interface SignInviteContext {\n arids: SessionArids;\n groupId: ARID;\n targetEnvelope: Envelope;\n groupRecord: GroupRecord;\n owner: OwnerRecord;\n registry: Registry;\n participants: GroupParticipant[];\n validUntil: Date;\n}\n\n/**\n * Build the sign invite request.\n *\n * Port of `build_sign_invite_request()` from cmd/sign/coordinator/invite.rs lines 239-284.\n */\nexport function buildSignInviteRequest(ctx: SignInviteContext): SealedRequest {\n let request = SealedRequest.new(\"signInvite\", ctx.arids.sessionId, ctx.owner.xidDocument())\n .withParameter(\"group\", ctx.groupId)\n .withParameter(\"session\", ctx.arids.sessionId)\n .withParameter(\"target\", ctx.targetEnvelope)\n .withParameter(\"minSigners\", ctx.groupRecord.minSigners())\n .withDate(new Date())\n .withParameter(\"validUntil\", CborDate.fromDatetime(ctx.validUntil));\n\n for (const participant of ctx.participants) {\n const xid = participant.xid();\n const xidKey = xid.urString();\n\n // Get participant document\n let participantDoc: XIDDocument;\n if (xidKey === ctx.owner.xid().urString()) {\n participantDoc = ctx.owner.xidDocument();\n } else {\n const record = ctx.registry.participant(xid);\n if (record === undefined) {\n throw new Error(\"Participant not found in registry\");\n }\n participantDoc = record.xidDocument();\n }\n\n // Get encryption key\n const encryptionKey = participantDoc.encryptionKey();\n if (encryptionKey === undefined) {\n throw new Error(\"Participant XID document has no encryption key\");\n }\n\n // Get commit ARID for this participant\n const responseArid = ctx.arids.commitArids.get(xidKey);\n if (responseArid === undefined) {\n throw new Error(\"commit ARID not found for participant\");\n }\n\n // Encrypt response ARID to participant\n // @ts-expect-error TS2339 - API mismatch: toEnvelope/encryptToRecipient methods\n const encryptedResponseArid = responseArid.toEnvelope().encryptToRecipient(encryptionKey);\n\n // Build participant entry envelope\n const participantEntry = Envelope.new(xid).addAssertion(\"response_arid\", encryptedResponseArid);\n\n request = request.withParameter(\"participant\", participantEntry);\n }\n\n return request;\n}\n\n// -----------------------------------------------------------------------------\n// State persistence\n// -----------------------------------------------------------------------------\n\n/**\n * Build the session state JSON for persistence.\n *\n * Port of `build_session_state_json()` from cmd/sign/coordinator/invite.rs lines 290-346.\n */\nexport function buildSessionStateJson(\n arids: SessionArids,\n groupId: ARID,\n groupRecord: GroupRecord,\n participants: GroupParticipant[],\n targetEnvelope: Envelope,\n): Record<string, unknown> {\n const participantsMap: Record<string, unknown> = {};\n\n for (const participant of participants) {\n const xid = participant.xid();\n const xidKey = xid.urString();\n\n const commitArid = arids.commitArids.get(xidKey);\n const shareArid = arids.shareArids.get(xidKey);\n\n if (commitArid === undefined || shareArid === undefined) {\n throw new Error(\"ARID not found for participant\");\n }\n\n participantsMap[xidKey] = {\n commit_arid: commitArid.urString(),\n share_arid: shareArid.urString(),\n };\n }\n\n return {\n session_id: arids.sessionId.urString(),\n start_arid: arids.startArid.urString(),\n group: groupId.urString(),\n min_signers: groupRecord.minSigners(),\n participants: participantsMap,\n target: targetEnvelope.urString(),\n };\n}\n\n/**\n * Persist the session state to disk.\n *\n * Port of `persist_session_state()` from cmd/sign/coordinator/invite.rs lines 348-356.\n */\nexport function persistSessionState(signingDir: string, stateJson: Record<string, unknown>): void {\n fs.mkdirSync(signingDir, { recursive: true });\n const startStatePath = path.join(signingDir, \"start.json\");\n fs.writeFileSync(startStatePath, JSON.stringify(stateJson, null, 2));\n}\n\n// -----------------------------------------------------------------------------\n// File loading\n// -----------------------------------------------------------------------------\n\n/**\n * Load an envelope from a file path.\n *\n * Port of `load_envelope_from_path()` from cmd/sign/coordinator/invite.rs lines 385-392.\n */\nexport function loadEnvelopeFromPath(filePath: string): Envelope {\n if (!fs.existsSync(filePath)) {\n throw new Error(`Failed to read target envelope from ${filePath}`);\n }\n\n const data = fs.readFileSync(filePath, \"utf-8\");\n const trimmed = data.trim();\n\n try {\n return Envelope.fromURString(trimmed);\n } catch (e) {\n throw new Error(`Failed to load target envelope from ${filePath}: ${String(e)}`, { cause: e });\n }\n}\n\n// -----------------------------------------------------------------------------\n// Options and Result types\n// -----------------------------------------------------------------------------\n\n/**\n * Options for the sign invite command.\n */\nexport interface SignInviteOptions {\n registryPath?: string;\n groupId: string;\n targetFile: string;\n validDays?: number;\n verbose?: boolean;\n preview?: boolean;\n}\n\n/**\n * Result of the sign invite command.\n */\nexport interface SignInviteResult {\n sessionId: string;\n startArid: string;\n}\n\n// -----------------------------------------------------------------------------\n// Main invite function\n// -----------------------------------------------------------------------------\n\n/**\n * Execute the sign coordinator invite command.\n *\n * Invites participants to sign a target envelope.\n *\n * Port of `CommandArgs::exec()` from cmd/sign/coordinator/invite.rs lines 44-144.\n */\nexport async function invite(\n client: StorageClient | undefined,\n options: SignInviteOptions,\n cwd: string,\n): Promise<SignInviteResult> {\n // Validate preview mode\n if (client !== undefined && options.preview === true) {\n throw new Error(\"--preview cannot be used with Hubert storage options\");\n }\n\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (owner === undefined) {\n throw new Error(\"Registry owner is required\");\n }\n\n const groupId = parseAridUr(options.groupId);\n const groupRecord = registry.group(groupId);\n\n if (groupRecord === undefined) {\n throw new Error(`Group ${options.groupId} not found in registry`);\n }\n\n // Validate sender is coordinator\n validateCoordinator(groupRecord, owner);\n\n // Load target envelope\n const targetPath = path.resolve(cwd, options.targetFile);\n const targetEnvelope = loadEnvelopeFromPath(targetPath);\n\n // Get participants\n const participants = groupRecord.participants();\n\n // Gather recipient documents\n const recipientDocs = gatherRecipientDocuments(participants, owner, registry);\n\n // Get signer keys\n const signerKeys = owner.xidDocument().inceptionPrivateKeys();\n if (signerKeys === undefined) {\n throw new Error(\"Coordinator XID document has no signing keys\");\n }\n\n // Generate session ARIDs\n const sessionArids = createSessionArids(participants);\n\n // Calculate valid until date (default 1 hour)\n const validDays = options.validDays ?? 1 / 24; // 1 hour default\n const validUntil = new Date(Date.now() + validDays * 24 * 60 * 60 * 1000);\n\n // Build request context\n const ctx: SignInviteContext = {\n arids: sessionArids,\n groupId,\n targetEnvelope,\n groupRecord,\n owner,\n registry,\n participants,\n validUntil,\n };\n\n // Build request\n const request = buildSignInviteRequest(ctx);\n\n // Build state for persistence\n const stateJson = buildSessionStateJson(\n sessionArids,\n groupId,\n groupRecord,\n participants,\n targetEnvelope,\n );\n\n // Build envelope for recipients\n const recipientRefs = recipientDocs;\n const sealedEnvelope = request.toEnvelopeForRecipients(validUntil, signerKeys, recipientRefs);\n\n // Handle preview mode\n if (options.preview === true) {\n const unsealed = request.toEnvelope(undefined, signerKeys, undefined);\n console.log(unsealed.urString());\n return {\n sessionId: sessionArids.sessionId.urString(),\n startArid: sessionArids.startArid.urString(),\n };\n }\n\n // Persist state\n const signingDir = signingStateDir(registryPath, groupId.hex(), sessionArids.sessionId.hex());\n persistSessionState(signingDir, stateJson);\n\n // Post to Hubert storage\n if (client === undefined) {\n throw new Error(\"Hubert storage is required for sign start\");\n }\n\n await putWithIndicator(\n client,\n sessionArids.startArid,\n sealedEnvelope,\n \"Signing invite\",\n options.verbose ?? false,\n );\n\n if (options.verbose === true) {\n console.log(`Session ID: ${sessionArids.sessionId.urString()}`);\n console.log(`Start ARID: ${sessionArids.startArid.urString()}`);\n }\n\n // Output the start ARID\n console.log(sessionArids.startArid.urString());\n\n return {\n sessionId: sessionArids.sessionId.urString(),\n startArid: sessionArids.startArid.urString(),\n };\n}\n"],"mappings":"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"}
@@ -1,16 +1,16 @@
1
- const require_chunk = require("./chunk-DakpK96I.cjs");
1
+ const require_rolldown_runtime = require("./rolldown-runtime-DakpK96I.cjs");
2
2
  const require_registry_index = require("./registry/index.cjs");
3
- const require_common = require("./common-CnvAUC2b.cjs");
3
+ const require_common = require("./common-3msAx7hO.cjs");
4
4
  const require_busy = require("./busy-B_h0bNAJ.cjs");
5
- const require_common$1 = require("./common-7-BOgaTt.cjs");
5
+ const require_common$1 = require("./common-CeTqMwj0.cjs");
6
6
  let _bcts_components = require("@bcts/components");
7
7
  let _bcts_dcbor = require("@bcts/dcbor");
8
8
  let _bcts_envelope = require("@bcts/envelope");
9
9
  let _bcts_gstp = require("@bcts/gstp");
10
10
  let node_fs = require("node:fs");
11
- node_fs = require_chunk.__toESM(node_fs, 1);
11
+ node_fs = require_rolldown_runtime.__toESM(node_fs, 1);
12
12
  let node_path = require("node:path");
13
- node_path = require_chunk.__toESM(node_path, 1);
13
+ node_path = require_rolldown_runtime.__toESM(node_path, 1);
14
14
  //#region src/cmd/sign/coordinator/invite.ts
15
15
  /**
16
16
  * Copyright © 2023-2026 Blockchain Commons, LLC
@@ -23,7 +23,7 @@ node_path = require_chunk.__toESM(node_path, 1);
23
23
  *
24
24
  * @module
25
25
  */
26
- var invite_exports = /* @__PURE__ */ require_chunk.__exportAll({
26
+ var invite_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
27
27
  buildSessionStateJson: () => buildSessionStateJson,
28
28
  buildSignInviteRequest: () => buildSignInviteRequest,
29
29
  createSessionArids: () => createSessionArids,
@@ -271,4 +271,4 @@ Object.defineProperty(exports, "validateCoordinator", {
271
271
  }
272
272
  });
273
273
 
274
- //# sourceMappingURL=invite-1tzg0B0P.cjs.map
274
+ //# sourceMappingURL=invite-T3L4N2m0.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"invite-1tzg0B0P.cjs","names":["ARID","SealedRequest","CborDate","Envelope","path","fs","resolveRegistryPath","Registry","parseAridUr","signingStateDir","putWithIndicator"],"sources":["../src/cmd/sign/coordinator/invite.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * Sign coordinator invite command.\n *\n * Port of cmd/sign/coordinator/invite.rs from frost-hubert-rust.\n *\n * @module\n */\n\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-argument */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID } from \"@bcts/components\";\nimport { CborDate } from \"@bcts/dcbor\";\nimport { Envelope } from \"@bcts/envelope\";\nimport { SealedRequest } from \"@bcts/gstp\";\nimport { type XIDDocument } from \"@bcts/xid\";\n\nimport {\n Registry,\n resolveRegistryPath,\n type GroupRecord,\n type GroupParticipant,\n type OwnerRecord,\n} from \"../../../registry/index.js\";\nimport { putWithIndicator } from \"../../busy.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { parseAridUr } from \"../../dkg/common.js\";\nimport { signingStateDir } from \"../common.js\";\n\n// -----------------------------------------------------------------------------\n// Session ARID management\n// -----------------------------------------------------------------------------\n\n/**\n * Session ARIDs for tracking the signing session.\n *\n * Port of `struct SessionArids` from cmd/sign/coordinator/invite.rs lines 151-156.\n */\nexport interface SessionArids {\n sessionId: ARID;\n startArid: ARID;\n commitArids: Map<string, ARID>; // Map<XID.urString(), ARID>\n shareArids: Map<string, ARID>; // Map<XID.urString(), ARID>\n}\n\n/**\n * Create new session ARIDs for all participants.\n *\n * Port of `SessionArids::new()` from cmd/sign/coordinator/invite.rs lines 158-173.\n */\nexport function createSessionArids(participants: GroupParticipant[]): SessionArids {\n const commitArids = new Map<string, ARID>();\n const shareArids = new Map<string, ARID>();\n\n for (const participant of participants) {\n const xidKey = participant.xid().urString();\n commitArids.set(xidKey, ARID.new());\n shareArids.set(xidKey, ARID.new());\n }\n\n return {\n sessionId: ARID.new(),\n startArid: ARID.new(),\n commitArids,\n shareArids,\n };\n}\n\n// -----------------------------------------------------------------------------\n// Validation\n// -----------------------------------------------------------------------------\n\n/**\n * Validate that the owner is the coordinator of the group.\n *\n * Port of `validate_coordinator()` from cmd/sign/coordinator/invite.rs lines 179-192.\n */\nexport function validateCoordinator(groupRecord: GroupRecord, owner: OwnerRecord): void {\n if (groupRecord.coordinator().xid().urString() !== owner.xid().urString()) {\n throw new Error(\n `Only the coordinator can start signing. Coordinator: ${groupRecord.coordinator().xid().urString()}, Owner: ${owner.xid().urString()}`,\n );\n }\n}\n\n// -----------------------------------------------------------------------------\n// Participant document gathering\n// -----------------------------------------------------------------------------\n\n/**\n * Gather XIDDocuments for all participants from the registry.\n *\n * Port of `gather_recipient_documents()` from cmd/sign/coordinator/invite.rs lines 198-222.\n */\nexport function gatherRecipientDocuments(\n participants: GroupParticipant[],\n owner: OwnerRecord,\n registry: Registry,\n): XIDDocument[] {\n const recipientDocs: XIDDocument[] = [];\n\n for (const participant of participants) {\n const xid = participant.xid();\n if (xid.urString() === owner.xid().urString()) {\n recipientDocs.push(owner.xidDocument());\n } else {\n const record = registry.participant(xid);\n if (record === undefined) {\n throw new Error(`Participant ${xid.urString()} not found in registry`);\n }\n recipientDocs.push(record.xidDocument());\n }\n }\n\n return recipientDocs;\n}\n\n// -----------------------------------------------------------------------------\n// Request building\n// -----------------------------------------------------------------------------\n\n/**\n * Context for building the sign invite request.\n *\n * Port of `struct SignInviteContext` from cmd/sign/coordinator/invite.rs lines 228-237.\n */\nexport interface SignInviteContext {\n arids: SessionArids;\n groupId: ARID;\n targetEnvelope: Envelope;\n groupRecord: GroupRecord;\n owner: OwnerRecord;\n registry: Registry;\n participants: GroupParticipant[];\n validUntil: Date;\n}\n\n/**\n * Build the sign invite request.\n *\n * Port of `build_sign_invite_request()` from cmd/sign/coordinator/invite.rs lines 239-284.\n */\nexport function buildSignInviteRequest(ctx: SignInviteContext): SealedRequest {\n let request = SealedRequest.new(\"signInvite\", ctx.arids.sessionId, ctx.owner.xidDocument())\n .withParameter(\"group\", ctx.groupId)\n .withParameter(\"session\", ctx.arids.sessionId)\n .withParameter(\"target\", ctx.targetEnvelope)\n .withParameter(\"minSigners\", ctx.groupRecord.minSigners())\n .withDate(new Date())\n .withParameter(\"validUntil\", CborDate.fromDatetime(ctx.validUntil));\n\n for (const participant of ctx.participants) {\n const xid = participant.xid();\n const xidKey = xid.urString();\n\n // Get participant document\n let participantDoc: XIDDocument;\n if (xidKey === ctx.owner.xid().urString()) {\n participantDoc = ctx.owner.xidDocument();\n } else {\n const record = ctx.registry.participant(xid);\n if (record === undefined) {\n throw new Error(\"Participant not found in registry\");\n }\n participantDoc = record.xidDocument();\n }\n\n // Get encryption key\n const encryptionKey = participantDoc.encryptionKey();\n if (encryptionKey === undefined) {\n throw new Error(\"Participant XID document has no encryption key\");\n }\n\n // Get commit ARID for this participant\n const responseArid = ctx.arids.commitArids.get(xidKey);\n if (responseArid === undefined) {\n throw new Error(\"commit ARID not found for participant\");\n }\n\n // Encrypt response ARID to participant\n // @ts-expect-error TS2339 - API mismatch: toEnvelope/encryptToRecipient methods\n const encryptedResponseArid = responseArid.toEnvelope().encryptToRecipient(encryptionKey);\n\n // Build participant entry envelope\n const participantEntry = Envelope.new(xid).addAssertion(\"response_arid\", encryptedResponseArid);\n\n request = request.withParameter(\"participant\", participantEntry);\n }\n\n return request;\n}\n\n// -----------------------------------------------------------------------------\n// State persistence\n// -----------------------------------------------------------------------------\n\n/**\n * Build the session state JSON for persistence.\n *\n * Port of `build_session_state_json()` from cmd/sign/coordinator/invite.rs lines 290-346.\n */\nexport function buildSessionStateJson(\n arids: SessionArids,\n groupId: ARID,\n groupRecord: GroupRecord,\n participants: GroupParticipant[],\n targetEnvelope: Envelope,\n): Record<string, unknown> {\n const participantsMap: Record<string, unknown> = {};\n\n for (const participant of participants) {\n const xid = participant.xid();\n const xidKey = xid.urString();\n\n const commitArid = arids.commitArids.get(xidKey);\n const shareArid = arids.shareArids.get(xidKey);\n\n if (commitArid === undefined || shareArid === undefined) {\n throw new Error(\"ARID not found for participant\");\n }\n\n participantsMap[xidKey] = {\n commit_arid: commitArid.urString(),\n share_arid: shareArid.urString(),\n };\n }\n\n return {\n session_id: arids.sessionId.urString(),\n start_arid: arids.startArid.urString(),\n group: groupId.urString(),\n min_signers: groupRecord.minSigners(),\n participants: participantsMap,\n target: targetEnvelope.urString(),\n };\n}\n\n/**\n * Persist the session state to disk.\n *\n * Port of `persist_session_state()` from cmd/sign/coordinator/invite.rs lines 348-356.\n */\nexport function persistSessionState(signingDir: string, stateJson: Record<string, unknown>): void {\n fs.mkdirSync(signingDir, { recursive: true });\n const startStatePath = path.join(signingDir, \"start.json\");\n fs.writeFileSync(startStatePath, JSON.stringify(stateJson, null, 2));\n}\n\n// -----------------------------------------------------------------------------\n// File loading\n// -----------------------------------------------------------------------------\n\n/**\n * Load an envelope from a file path.\n *\n * Port of `load_envelope_from_path()` from cmd/sign/coordinator/invite.rs lines 385-392.\n */\nexport function loadEnvelopeFromPath(filePath: string): Envelope {\n if (!fs.existsSync(filePath)) {\n throw new Error(`Failed to read target envelope from ${filePath}`);\n }\n\n const data = fs.readFileSync(filePath, \"utf-8\");\n const trimmed = data.trim();\n\n try {\n return Envelope.fromURString(trimmed);\n } catch (e) {\n throw new Error(`Failed to load target envelope from ${filePath}: ${String(e)}`, { cause: e });\n }\n}\n\n// -----------------------------------------------------------------------------\n// Options and Result types\n// -----------------------------------------------------------------------------\n\n/**\n * Options for the sign invite command.\n */\nexport interface SignInviteOptions {\n registryPath?: string;\n groupId: string;\n targetFile: string;\n validDays?: number;\n verbose?: boolean;\n preview?: boolean;\n}\n\n/**\n * Result of the sign invite command.\n */\nexport interface SignInviteResult {\n sessionId: string;\n startArid: string;\n}\n\n// -----------------------------------------------------------------------------\n// Main invite function\n// -----------------------------------------------------------------------------\n\n/**\n * Execute the sign coordinator invite command.\n *\n * Invites participants to sign a target envelope.\n *\n * Port of `CommandArgs::exec()` from cmd/sign/coordinator/invite.rs lines 44-144.\n */\nexport async function invite(\n client: StorageClient | undefined,\n options: SignInviteOptions,\n cwd: string,\n): Promise<SignInviteResult> {\n // Validate preview mode\n if (client !== undefined && options.preview === true) {\n throw new Error(\"--preview cannot be used with Hubert storage options\");\n }\n\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (owner === undefined) {\n throw new Error(\"Registry owner is required\");\n }\n\n const groupId = parseAridUr(options.groupId);\n const groupRecord = registry.group(groupId);\n\n if (groupRecord === undefined) {\n throw new Error(`Group ${options.groupId} not found in registry`);\n }\n\n // Validate sender is coordinator\n validateCoordinator(groupRecord, owner);\n\n // Load target envelope\n const targetPath = path.resolve(cwd, options.targetFile);\n const targetEnvelope = loadEnvelopeFromPath(targetPath);\n\n // Get participants\n const participants = groupRecord.participants();\n\n // Gather recipient documents\n const recipientDocs = gatherRecipientDocuments(participants, owner, registry);\n\n // Get signer keys\n const signerKeys = owner.xidDocument().inceptionPrivateKeys();\n if (signerKeys === undefined) {\n throw new Error(\"Coordinator XID document has no signing keys\");\n }\n\n // Generate session ARIDs\n const sessionArids = createSessionArids(participants);\n\n // Calculate valid until date (default 1 hour)\n const validDays = options.validDays ?? 1 / 24; // 1 hour default\n const validUntil = new Date(Date.now() + validDays * 24 * 60 * 60 * 1000);\n\n // Build request context\n const ctx: SignInviteContext = {\n arids: sessionArids,\n groupId,\n targetEnvelope,\n groupRecord,\n owner,\n registry,\n participants,\n validUntil,\n };\n\n // Build request\n const request = buildSignInviteRequest(ctx);\n\n // Build state for persistence\n const stateJson = buildSessionStateJson(\n sessionArids,\n groupId,\n groupRecord,\n participants,\n targetEnvelope,\n );\n\n // Build envelope for recipients\n const recipientRefs = recipientDocs;\n const sealedEnvelope = request.toEnvelopeForRecipients(validUntil, signerKeys, recipientRefs);\n\n // Handle preview mode\n if (options.preview === true) {\n const unsealed = request.toEnvelope(undefined, signerKeys, undefined);\n console.log(unsealed.urString());\n return {\n sessionId: sessionArids.sessionId.urString(),\n startArid: sessionArids.startArid.urString(),\n };\n }\n\n // Persist state\n const signingDir = signingStateDir(registryPath, groupId.hex(), sessionArids.sessionId.hex());\n persistSessionState(signingDir, stateJson);\n\n // Post to Hubert storage\n if (client === undefined) {\n throw new Error(\"Hubert storage is required for sign start\");\n }\n\n await putWithIndicator(\n client,\n sessionArids.startArid,\n sealedEnvelope,\n \"Signing invite\",\n options.verbose ?? false,\n );\n\n if (options.verbose === true) {\n console.log(`Session ID: ${sessionArids.sessionId.urString()}`);\n console.log(`Start ARID: ${sessionArids.startArid.urString()}`);\n }\n\n // Output the start ARID\n console.log(sessionArids.startArid.urString());\n\n return {\n sessionId: sessionArids.sessionId.urString(),\n startArid: sessionArids.startArid.urString(),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"invite-T3L4N2m0.cjs","names":["ARID","SealedRequest","CborDate","Envelope","path","fs","resolveRegistryPath","Registry","parseAridUr","signingStateDir","putWithIndicator"],"sources":["../src/cmd/sign/coordinator/invite.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * Sign coordinator invite command.\n *\n * Port of cmd/sign/coordinator/invite.rs from frost-hubert-rust.\n *\n * @module\n */\n\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-argument */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID } from \"@bcts/components\";\nimport { CborDate } from \"@bcts/dcbor\";\nimport { Envelope } from \"@bcts/envelope\";\nimport { SealedRequest } from \"@bcts/gstp\";\nimport { type XIDDocument } from \"@bcts/xid\";\n\nimport {\n Registry,\n resolveRegistryPath,\n type GroupRecord,\n type GroupParticipant,\n type OwnerRecord,\n} from \"../../../registry/index.js\";\nimport { putWithIndicator } from \"../../busy.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { parseAridUr } from \"../../dkg/common.js\";\nimport { signingStateDir } from \"../common.js\";\n\n// -----------------------------------------------------------------------------\n// Session ARID management\n// -----------------------------------------------------------------------------\n\n/**\n * Session ARIDs for tracking the signing session.\n *\n * Port of `struct SessionArids` from cmd/sign/coordinator/invite.rs lines 151-156.\n */\nexport interface SessionArids {\n sessionId: ARID;\n startArid: ARID;\n commitArids: Map<string, ARID>; // Map<XID.urString(), ARID>\n shareArids: Map<string, ARID>; // Map<XID.urString(), ARID>\n}\n\n/**\n * Create new session ARIDs for all participants.\n *\n * Port of `SessionArids::new()` from cmd/sign/coordinator/invite.rs lines 158-173.\n */\nexport function createSessionArids(participants: GroupParticipant[]): SessionArids {\n const commitArids = new Map<string, ARID>();\n const shareArids = new Map<string, ARID>();\n\n for (const participant of participants) {\n const xidKey = participant.xid().urString();\n commitArids.set(xidKey, ARID.new());\n shareArids.set(xidKey, ARID.new());\n }\n\n return {\n sessionId: ARID.new(),\n startArid: ARID.new(),\n commitArids,\n shareArids,\n };\n}\n\n// -----------------------------------------------------------------------------\n// Validation\n// -----------------------------------------------------------------------------\n\n/**\n * Validate that the owner is the coordinator of the group.\n *\n * Port of `validate_coordinator()` from cmd/sign/coordinator/invite.rs lines 179-192.\n */\nexport function validateCoordinator(groupRecord: GroupRecord, owner: OwnerRecord): void {\n if (groupRecord.coordinator().xid().urString() !== owner.xid().urString()) {\n throw new Error(\n `Only the coordinator can start signing. Coordinator: ${groupRecord.coordinator().xid().urString()}, Owner: ${owner.xid().urString()}`,\n );\n }\n}\n\n// -----------------------------------------------------------------------------\n// Participant document gathering\n// -----------------------------------------------------------------------------\n\n/**\n * Gather XIDDocuments for all participants from the registry.\n *\n * Port of `gather_recipient_documents()` from cmd/sign/coordinator/invite.rs lines 198-222.\n */\nexport function gatherRecipientDocuments(\n participants: GroupParticipant[],\n owner: OwnerRecord,\n registry: Registry,\n): XIDDocument[] {\n const recipientDocs: XIDDocument[] = [];\n\n for (const participant of participants) {\n const xid = participant.xid();\n if (xid.urString() === owner.xid().urString()) {\n recipientDocs.push(owner.xidDocument());\n } else {\n const record = registry.participant(xid);\n if (record === undefined) {\n throw new Error(`Participant ${xid.urString()} not found in registry`);\n }\n recipientDocs.push(record.xidDocument());\n }\n }\n\n return recipientDocs;\n}\n\n// -----------------------------------------------------------------------------\n// Request building\n// -----------------------------------------------------------------------------\n\n/**\n * Context for building the sign invite request.\n *\n * Port of `struct SignInviteContext` from cmd/sign/coordinator/invite.rs lines 228-237.\n */\nexport interface SignInviteContext {\n arids: SessionArids;\n groupId: ARID;\n targetEnvelope: Envelope;\n groupRecord: GroupRecord;\n owner: OwnerRecord;\n registry: Registry;\n participants: GroupParticipant[];\n validUntil: Date;\n}\n\n/**\n * Build the sign invite request.\n *\n * Port of `build_sign_invite_request()` from cmd/sign/coordinator/invite.rs lines 239-284.\n */\nexport function buildSignInviteRequest(ctx: SignInviteContext): SealedRequest {\n let request = SealedRequest.new(\"signInvite\", ctx.arids.sessionId, ctx.owner.xidDocument())\n .withParameter(\"group\", ctx.groupId)\n .withParameter(\"session\", ctx.arids.sessionId)\n .withParameter(\"target\", ctx.targetEnvelope)\n .withParameter(\"minSigners\", ctx.groupRecord.minSigners())\n .withDate(new Date())\n .withParameter(\"validUntil\", CborDate.fromDatetime(ctx.validUntil));\n\n for (const participant of ctx.participants) {\n const xid = participant.xid();\n const xidKey = xid.urString();\n\n // Get participant document\n let participantDoc: XIDDocument;\n if (xidKey === ctx.owner.xid().urString()) {\n participantDoc = ctx.owner.xidDocument();\n } else {\n const record = ctx.registry.participant(xid);\n if (record === undefined) {\n throw new Error(\"Participant not found in registry\");\n }\n participantDoc = record.xidDocument();\n }\n\n // Get encryption key\n const encryptionKey = participantDoc.encryptionKey();\n if (encryptionKey === undefined) {\n throw new Error(\"Participant XID document has no encryption key\");\n }\n\n // Get commit ARID for this participant\n const responseArid = ctx.arids.commitArids.get(xidKey);\n if (responseArid === undefined) {\n throw new Error(\"commit ARID not found for participant\");\n }\n\n // Encrypt response ARID to participant\n // @ts-expect-error TS2339 - API mismatch: toEnvelope/encryptToRecipient methods\n const encryptedResponseArid = responseArid.toEnvelope().encryptToRecipient(encryptionKey);\n\n // Build participant entry envelope\n const participantEntry = Envelope.new(xid).addAssertion(\"response_arid\", encryptedResponseArid);\n\n request = request.withParameter(\"participant\", participantEntry);\n }\n\n return request;\n}\n\n// -----------------------------------------------------------------------------\n// State persistence\n// -----------------------------------------------------------------------------\n\n/**\n * Build the session state JSON for persistence.\n *\n * Port of `build_session_state_json()` from cmd/sign/coordinator/invite.rs lines 290-346.\n */\nexport function buildSessionStateJson(\n arids: SessionArids,\n groupId: ARID,\n groupRecord: GroupRecord,\n participants: GroupParticipant[],\n targetEnvelope: Envelope,\n): Record<string, unknown> {\n const participantsMap: Record<string, unknown> = {};\n\n for (const participant of participants) {\n const xid = participant.xid();\n const xidKey = xid.urString();\n\n const commitArid = arids.commitArids.get(xidKey);\n const shareArid = arids.shareArids.get(xidKey);\n\n if (commitArid === undefined || shareArid === undefined) {\n throw new Error(\"ARID not found for participant\");\n }\n\n participantsMap[xidKey] = {\n commit_arid: commitArid.urString(),\n share_arid: shareArid.urString(),\n };\n }\n\n return {\n session_id: arids.sessionId.urString(),\n start_arid: arids.startArid.urString(),\n group: groupId.urString(),\n min_signers: groupRecord.minSigners(),\n participants: participantsMap,\n target: targetEnvelope.urString(),\n };\n}\n\n/**\n * Persist the session state to disk.\n *\n * Port of `persist_session_state()` from cmd/sign/coordinator/invite.rs lines 348-356.\n */\nexport function persistSessionState(signingDir: string, stateJson: Record<string, unknown>): void {\n fs.mkdirSync(signingDir, { recursive: true });\n const startStatePath = path.join(signingDir, \"start.json\");\n fs.writeFileSync(startStatePath, JSON.stringify(stateJson, null, 2));\n}\n\n// -----------------------------------------------------------------------------\n// File loading\n// -----------------------------------------------------------------------------\n\n/**\n * Load an envelope from a file path.\n *\n * Port of `load_envelope_from_path()` from cmd/sign/coordinator/invite.rs lines 385-392.\n */\nexport function loadEnvelopeFromPath(filePath: string): Envelope {\n if (!fs.existsSync(filePath)) {\n throw new Error(`Failed to read target envelope from ${filePath}`);\n }\n\n const data = fs.readFileSync(filePath, \"utf-8\");\n const trimmed = data.trim();\n\n try {\n return Envelope.fromURString(trimmed);\n } catch (e) {\n throw new Error(`Failed to load target envelope from ${filePath}: ${String(e)}`, { cause: e });\n }\n}\n\n// -----------------------------------------------------------------------------\n// Options and Result types\n// -----------------------------------------------------------------------------\n\n/**\n * Options for the sign invite command.\n */\nexport interface SignInviteOptions {\n registryPath?: string;\n groupId: string;\n targetFile: string;\n validDays?: number;\n verbose?: boolean;\n preview?: boolean;\n}\n\n/**\n * Result of the sign invite command.\n */\nexport interface SignInviteResult {\n sessionId: string;\n startArid: string;\n}\n\n// -----------------------------------------------------------------------------\n// Main invite function\n// -----------------------------------------------------------------------------\n\n/**\n * Execute the sign coordinator invite command.\n *\n * Invites participants to sign a target envelope.\n *\n * Port of `CommandArgs::exec()` from cmd/sign/coordinator/invite.rs lines 44-144.\n */\nexport async function invite(\n client: StorageClient | undefined,\n options: SignInviteOptions,\n cwd: string,\n): Promise<SignInviteResult> {\n // Validate preview mode\n if (client !== undefined && options.preview === true) {\n throw new Error(\"--preview cannot be used with Hubert storage options\");\n }\n\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (owner === undefined) {\n throw new Error(\"Registry owner is required\");\n }\n\n const groupId = parseAridUr(options.groupId);\n const groupRecord = registry.group(groupId);\n\n if (groupRecord === undefined) {\n throw new Error(`Group ${options.groupId} not found in registry`);\n }\n\n // Validate sender is coordinator\n validateCoordinator(groupRecord, owner);\n\n // Load target envelope\n const targetPath = path.resolve(cwd, options.targetFile);\n const targetEnvelope = loadEnvelopeFromPath(targetPath);\n\n // Get participants\n const participants = groupRecord.participants();\n\n // Gather recipient documents\n const recipientDocs = gatherRecipientDocuments(participants, owner, registry);\n\n // Get signer keys\n const signerKeys = owner.xidDocument().inceptionPrivateKeys();\n if (signerKeys === undefined) {\n throw new Error(\"Coordinator XID document has no signing keys\");\n }\n\n // Generate session ARIDs\n const sessionArids = createSessionArids(participants);\n\n // Calculate valid until date (default 1 hour)\n const validDays = options.validDays ?? 1 / 24; // 1 hour default\n const validUntil = new Date(Date.now() + validDays * 24 * 60 * 60 * 1000);\n\n // Build request context\n const ctx: SignInviteContext = {\n arids: sessionArids,\n groupId,\n targetEnvelope,\n groupRecord,\n owner,\n registry,\n participants,\n validUntil,\n };\n\n // Build request\n const request = buildSignInviteRequest(ctx);\n\n // Build state for persistence\n const stateJson = buildSessionStateJson(\n sessionArids,\n groupId,\n groupRecord,\n participants,\n targetEnvelope,\n );\n\n // Build envelope for recipients\n const recipientRefs = recipientDocs;\n const sealedEnvelope = request.toEnvelopeForRecipients(validUntil, signerKeys, recipientRefs);\n\n // Handle preview mode\n if (options.preview === true) {\n const unsealed = request.toEnvelope(undefined, signerKeys, undefined);\n console.log(unsealed.urString());\n return {\n sessionId: sessionArids.sessionId.urString(),\n startArid: sessionArids.startArid.urString(),\n };\n }\n\n // Persist state\n const signingDir = signingStateDir(registryPath, groupId.hex(), sessionArids.sessionId.hex());\n persistSessionState(signingDir, stateJson);\n\n // Post to Hubert storage\n if (client === undefined) {\n throw new Error(\"Hubert storage is required for sign start\");\n }\n\n await putWithIndicator(\n client,\n sessionArids.startArid,\n sealedEnvelope,\n \"Signing invite\",\n options.verbose ?? false,\n );\n\n if (options.verbose === true) {\n console.log(`Session ID: ${sessionArids.sessionId.urString()}`);\n console.log(`Start ARID: ${sessionArids.startArid.urString()}`);\n }\n\n // Output the start ARID\n console.log(sessionArids.startArid.urString());\n\n return {\n sessionId: sessionArids.sessionId.urString(),\n startArid: sessionArids.startArid.urString(),\n };\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import { t as __exportAll } from "./chunk-z9aeyW2b.mjs";
1
+ import { t as __exportAll } from "./rolldown-runtime-z9aeyW2b.mjs";
2
2
  import { DkgInvite } from "./dkg/index.mjs";
3
3
  import { GroupParticipant, GroupRecord, PendingRequests, Registry, resolveRegistryPath } from "./registry/index.mjs";
4
- import { a as dkgStateDir, d as resolveOwnerXidDocument, f as resolveParticipants } from "./common-Cf1UvJaP.mjs";
4
+ import { a as dkgStateDir, d as resolveOwnerXidDocument, f as resolveParticipants } from "./common-4spC1kNw.mjs";
5
5
  import { n as putWithIndicator } from "./busy-BlU8_pS2.mjs";
6
6
  import { ARID } from "@bcts/components";
7
7
  import * as fs from "node:fs";
@@ -93,4 +93,4 @@ async function invite(client, options, cwd) {
93
93
  //#endregion
94
94
  export { invite_exports as n, invite as t };
95
95
 
96
- //# sourceMappingURL=invite-Be2v2SVc.mjs.map
96
+ //# sourceMappingURL=invite-vRv9LMEE.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"invite-Be2v2SVc.mjs","names":[],"sources":["../src/cmd/dkg/coordinator/invite.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * DKG coordinator invite command.\n *\n * Port of cmd/dkg/coordinator/invite.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID, type XID } from \"@bcts/components\";\n\nimport { DkgInvite } from \"../../../dkg/index.js\";\nimport {\n GroupParticipant,\n GroupRecord,\n PendingRequests,\n Registry,\n resolveRegistryPath,\n} from \"../../../registry/index.js\";\nimport { putWithIndicator } from \"../../busy.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { dkgStateDir, resolveOwnerXidDocument, resolveParticipants } from \"../common.js\";\n\n/**\n * Options for the DKG invite command.\n */\nexport interface DkgInviteOptions {\n registryPath?: string;\n minSigners?: number;\n charter: string;\n validDays: number;\n participantNames: string[];\n verbose?: boolean;\n}\n\n/**\n * Result of the DKG invite command.\n */\nexport interface DkgInviteResult {\n groupId: ARID;\n requestId: ARID;\n envelopeUr: string;\n}\n\n/**\n * Internal data structure for building an invite.\n *\n * Port of `InviteData` struct from cmd/dkg/coordinator/invite.rs lines 122-126.\n */\ninterface InviteData {\n invite: DkgInvite;\n participantXids: XID[];\n pendingRequests: PendingRequests;\n}\n\n/**\n * Build the DKG invite with validation.\n *\n * Port of `build_invite()` from cmd/dkg/coordinator/invite.rs lines 128-181.\n */\nfunction buildInvite(\n registry: Registry,\n minSignersArg: number | undefined,\n charter: string,\n participantNames: string[],\n validDays: number,\n): InviteData {\n // Resolve participants using the common utility\n const resolved = resolveParticipants(registry, participantNames);\n const participantDocs: string[] = resolved.map(([, record]) => record.xidDocumentUr());\n const participantXids: XID[] = resolved.map(([xid]) => xid);\n\n // These are the ARIDs where participants will post their invite responses\n const collectFromArids: ARID[] = participantDocs.map(() => ARID.new());\n\n // Build pending_requests: coordinator will collect invite responses from these ARIDs\n const pendingRequests = new PendingRequests();\n for (let i = 0; i < participantXids.length; i++) {\n pendingRequests.addCollectOnly(participantXids[i], collectFromArids[i]);\n }\n\n // Validate participant count\n const participantCount = participantDocs.length;\n if (participantCount < 2) {\n throw new Error(\"At least two participants are required for a DKG invite\");\n }\n\n // Validate and default minSigners\n const minSigners = minSignersArg ?? participantCount;\n if (minSigners < 2) {\n throw new Error(\"--min-signers must be at least 2\");\n }\n if (minSigners > participantCount) {\n throw new Error(\"--min-signers cannot exceed participant count\");\n }\n\n // Get sender (registry owner)\n // The coordinator's invite always identifies the registry owner as\n // the sender. (Rust reads `registry.owner()` directly here too —\n // see `cmd/dkg/coordinator/invite.rs:74-77`.)\n const sender = resolveOwnerXidDocument(registry);\n\n // Calculate dates\n const now = new Date();\n const validUntil = new Date(Date.now() + validDays * 24 * 60 * 60 * 1000);\n\n // Create the invite\n const invite = DkgInvite.create(\n ARID.new(), // requestId\n sender,\n ARID.new(), // groupId\n now,\n validUntil,\n minSigners,\n charter,\n participantDocs,\n collectFromArids,\n );\n\n return { invite, participantXids, pendingRequests };\n}\n\n/**\n * Execute the DKG invite command.\n *\n * Port of `invite()` from cmd/dkg/coordinator/invite.rs.\n */\nexport async function invite(\n client: StorageClient,\n options: DkgInviteOptions,\n cwd: string,\n): Promise<DkgInviteResult> {\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n // Build the invite with validation\n const inviteData = buildInvite(\n registry,\n options.minSigners,\n options.charter,\n options.participantNames,\n options.validDays,\n );\n\n const { invite: dkgInvite, participantXids, pendingRequests } = inviteData;\n const groupId = dkgInvite.groupId();\n const requestId = dkgInvite.requestId();\n\n // Create sealed envelope\n const envelope = dkgInvite.toEnvelope();\n\n // Send to storage\n const startArid = ARID.new();\n await putWithIndicator(\n client,\n startArid,\n envelope,\n \"Sending DKG invite\",\n options.verbose ?? false,\n );\n\n // Save group record to registry\n const owner = registry.owner();\n if (!owner) {\n throw new Error(\"Registry owner is required to issue invites\");\n }\n\n const coordinator = new GroupParticipant(owner.xid());\n const groupParticipants = participantXids.map((xid) => new GroupParticipant(xid));\n\n const groupRecord = new GroupRecord(\n options.charter,\n dkgInvite.minSigners(),\n coordinator,\n groupParticipants,\n );\n\n // Track pending requests\n groupRecord.setPendingRequests(pendingRequests);\n\n // Use recordGroup() for proper merge behavior\n registry.recordGroup(groupId, groupRecord);\n registry.save(registryPath);\n\n // Save invite state\n const stateDir = dkgStateDir(registryPath, groupId.hex());\n fs.mkdirSync(stateDir, { recursive: true });\n\n const inviteState: {\n group: string;\n request_id: string;\n start_arid: string;\n valid_until: string;\n participants: { xid: string; response_arid: string }[];\n } = {\n group: groupId.urString(),\n request_id: requestId.urString(),\n start_arid: startArid.urString(),\n valid_until: dkgInvite.validUntil().toISOString(),\n participants: dkgInvite.participants().map((p) => ({\n xid: p.xid().urString(),\n response_arid: p.responseArid().urString(),\n })),\n };\n\n fs.writeFileSync(path.join(stateDir, \"invite.json\"), JSON.stringify(inviteState, null, 2));\n\n if (options.verbose === true) {\n console.log(`Group ID: ${groupId.urString()}`);\n console.log(`Start ARID: ${startArid.urString()}`);\n }\n\n return {\n groupId,\n requestId,\n envelopeUr: envelope.urString(),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAkEA,SAAS,YACP,UACA,eACA,SACA,kBACA,WACY;CAEZ,MAAM,WAAW,oBAAoB,UAAU,gBAAgB;CAC/D,MAAM,kBAA4B,SAAS,KAAK,GAAG,YAAY,OAAO,cAAc,CAAC;CACrF,MAAM,kBAAyB,SAAS,KAAK,CAAC,SAAS,GAAG;CAG1D,MAAM,mBAA2B,gBAAgB,UAAU,KAAK,IAAI,CAAC;CAGrE,MAAM,kBAAkB,IAAI,gBAAgB;CAC5C,KAAK,IAAI,IAAI,GAAG,IAAI,gBAAgB,QAAQ,KAC1C,gBAAgB,eAAe,gBAAgB,IAAI,iBAAiB,EAAE;CAIxE,MAAM,mBAAmB,gBAAgB;CACzC,IAAI,mBAAmB,GACrB,MAAM,IAAI,MAAM,yDAAyD;CAI3E,MAAM,aAAa,iBAAiB;CACpC,IAAI,aAAa,GACf,MAAM,IAAI,MAAM,kCAAkC;CAEpD,IAAI,aAAa,kBACf,MAAM,IAAI,MAAM,+CAA+C;CAOjE,MAAM,SAAS,wBAAwB,QAAQ;CAG/C,MAAM,sBAAM,IAAI,KAAK;CACrB,MAAM,aAAa,IAAI,KAAK,KAAK,IAAI,IAAI,YAAY,KAAK,KAAK,KAAK,GAAI;CAexE,OAAO;EAAE,QAZM,UAAU,OACvB,KAAK,IAAI,GACT,QACA,KAAK,IAAI,GACT,KACA,YACA,YACA,SACA,iBACA,gBAGY;EAAG;EAAiB;CAAgB;AACpD;;;;;;AAOA,eAAsB,OACpB,QACA,SACA,KAC0B;CAC1B,MAAM,eAAe,oBAAoB,QAAQ,cAAc,GAAG;CAClE,MAAM,WAAW,SAAS,KAAK,YAAY;CAW3C,MAAM,EAAE,QAAQ,WAAW,iBAAiB,oBARzB,YACjB,UACA,QAAQ,YACR,QAAQ,SACR,QAAQ,kBACR,QAAQ,SAG+D;CACzE,MAAM,UAAU,UAAU,QAAQ;CAClC,MAAM,YAAY,UAAU,UAAU;CAGtC,MAAM,WAAW,UAAU,WAAW;CAGtC,MAAM,YAAY,KAAK,IAAI;CAC3B,MAAM,iBACJ,QACA,WACA,UACA,sBACA,QAAQ,WAAW,KACrB;CAGA,MAAM,QAAQ,SAAS,MAAM;CAC7B,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,6CAA6C;CAG/D,MAAM,cAAc,IAAI,iBAAiB,MAAM,IAAI,CAAC;CACpD,MAAM,oBAAoB,gBAAgB,KAAK,QAAQ,IAAI,iBAAiB,GAAG,CAAC;CAEhF,MAAM,cAAc,IAAI,YACtB,QAAQ,SACR,UAAU,WAAW,GACrB,aACA,iBACF;CAGA,YAAY,mBAAmB,eAAe;CAG9C,SAAS,YAAY,SAAS,WAAW;CACzC,SAAS,KAAK,YAAY;CAG1B,MAAM,WAAW,YAAY,cAAc,QAAQ,IAAI,CAAC;CACxD,GAAG,UAAU,UAAU,EAAE,WAAW,KAAK,CAAC;CAE1C,MAAM,cAMF;EACF,OAAO,QAAQ,SAAS;EACxB,YAAY,UAAU,SAAS;EAC/B,YAAY,UAAU,SAAS;EAC/B,aAAa,UAAU,WAAW,EAAE,YAAY;EAChD,cAAc,UAAU,aAAa,EAAE,KAAK,OAAO;GACjD,KAAK,EAAE,IAAI,EAAE,SAAS;GACtB,eAAe,EAAE,aAAa,EAAE,SAAS;EAC3C,EAAE;CACJ;CAEA,GAAG,cAAc,KAAK,KAAK,UAAU,aAAa,GAAG,KAAK,UAAU,aAAa,MAAM,CAAC,CAAC;CAEzF,IAAI,QAAQ,YAAY,MAAM;EAC5B,QAAQ,IAAI,aAAa,QAAQ,SAAS,GAAG;EAC7C,QAAQ,IAAI,eAAe,UAAU,SAAS,GAAG;CACnD;CAEA,OAAO;EACL;EACA;EACA,YAAY,SAAS,SAAS;CAChC;AACF"}
1
+ {"version":3,"file":"invite-vRv9LMEE.mjs","names":[],"sources":["../src/cmd/dkg/coordinator/invite.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * DKG coordinator invite command.\n *\n * Port of cmd/dkg/coordinator/invite.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID, type XID } from \"@bcts/components\";\n\nimport { DkgInvite } from \"../../../dkg/index.js\";\nimport {\n GroupParticipant,\n GroupRecord,\n PendingRequests,\n Registry,\n resolveRegistryPath,\n} from \"../../../registry/index.js\";\nimport { putWithIndicator } from \"../../busy.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { dkgStateDir, resolveOwnerXidDocument, resolveParticipants } from \"../common.js\";\n\n/**\n * Options for the DKG invite command.\n */\nexport interface DkgInviteOptions {\n registryPath?: string;\n minSigners?: number;\n charter: string;\n validDays: number;\n participantNames: string[];\n verbose?: boolean;\n}\n\n/**\n * Result of the DKG invite command.\n */\nexport interface DkgInviteResult {\n groupId: ARID;\n requestId: ARID;\n envelopeUr: string;\n}\n\n/**\n * Internal data structure for building an invite.\n *\n * Port of `InviteData` struct from cmd/dkg/coordinator/invite.rs lines 122-126.\n */\ninterface InviteData {\n invite: DkgInvite;\n participantXids: XID[];\n pendingRequests: PendingRequests;\n}\n\n/**\n * Build the DKG invite with validation.\n *\n * Port of `build_invite()` from cmd/dkg/coordinator/invite.rs lines 128-181.\n */\nfunction buildInvite(\n registry: Registry,\n minSignersArg: number | undefined,\n charter: string,\n participantNames: string[],\n validDays: number,\n): InviteData {\n // Resolve participants using the common utility\n const resolved = resolveParticipants(registry, participantNames);\n const participantDocs: string[] = resolved.map(([, record]) => record.xidDocumentUr());\n const participantXids: XID[] = resolved.map(([xid]) => xid);\n\n // These are the ARIDs where participants will post their invite responses\n const collectFromArids: ARID[] = participantDocs.map(() => ARID.new());\n\n // Build pending_requests: coordinator will collect invite responses from these ARIDs\n const pendingRequests = new PendingRequests();\n for (let i = 0; i < participantXids.length; i++) {\n pendingRequests.addCollectOnly(participantXids[i], collectFromArids[i]);\n }\n\n // Validate participant count\n const participantCount = participantDocs.length;\n if (participantCount < 2) {\n throw new Error(\"At least two participants are required for a DKG invite\");\n }\n\n // Validate and default minSigners\n const minSigners = minSignersArg ?? participantCount;\n if (minSigners < 2) {\n throw new Error(\"--min-signers must be at least 2\");\n }\n if (minSigners > participantCount) {\n throw new Error(\"--min-signers cannot exceed participant count\");\n }\n\n // Get sender (registry owner)\n // The coordinator's invite always identifies the registry owner as\n // the sender. (Rust reads `registry.owner()` directly here too —\n // see `cmd/dkg/coordinator/invite.rs:74-77`.)\n const sender = resolveOwnerXidDocument(registry);\n\n // Calculate dates\n const now = new Date();\n const validUntil = new Date(Date.now() + validDays * 24 * 60 * 60 * 1000);\n\n // Create the invite\n const invite = DkgInvite.create(\n ARID.new(), // requestId\n sender,\n ARID.new(), // groupId\n now,\n validUntil,\n minSigners,\n charter,\n participantDocs,\n collectFromArids,\n );\n\n return { invite, participantXids, pendingRequests };\n}\n\n/**\n * Execute the DKG invite command.\n *\n * Port of `invite()` from cmd/dkg/coordinator/invite.rs.\n */\nexport async function invite(\n client: StorageClient,\n options: DkgInviteOptions,\n cwd: string,\n): Promise<DkgInviteResult> {\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n // Build the invite with validation\n const inviteData = buildInvite(\n registry,\n options.minSigners,\n options.charter,\n options.participantNames,\n options.validDays,\n );\n\n const { invite: dkgInvite, participantXids, pendingRequests } = inviteData;\n const groupId = dkgInvite.groupId();\n const requestId = dkgInvite.requestId();\n\n // Create sealed envelope\n const envelope = dkgInvite.toEnvelope();\n\n // Send to storage\n const startArid = ARID.new();\n await putWithIndicator(\n client,\n startArid,\n envelope,\n \"Sending DKG invite\",\n options.verbose ?? false,\n );\n\n // Save group record to registry\n const owner = registry.owner();\n if (!owner) {\n throw new Error(\"Registry owner is required to issue invites\");\n }\n\n const coordinator = new GroupParticipant(owner.xid());\n const groupParticipants = participantXids.map((xid) => new GroupParticipant(xid));\n\n const groupRecord = new GroupRecord(\n options.charter,\n dkgInvite.minSigners(),\n coordinator,\n groupParticipants,\n );\n\n // Track pending requests\n groupRecord.setPendingRequests(pendingRequests);\n\n // Use recordGroup() for proper merge behavior\n registry.recordGroup(groupId, groupRecord);\n registry.save(registryPath);\n\n // Save invite state\n const stateDir = dkgStateDir(registryPath, groupId.hex());\n fs.mkdirSync(stateDir, { recursive: true });\n\n const inviteState: {\n group: string;\n request_id: string;\n start_arid: string;\n valid_until: string;\n participants: { xid: string; response_arid: string }[];\n } = {\n group: groupId.urString(),\n request_id: requestId.urString(),\n start_arid: startArid.urString(),\n valid_until: dkgInvite.validUntil().toISOString(),\n participants: dkgInvite.participants().map((p) => ({\n xid: p.xid().urString(),\n response_arid: p.responseArid().urString(),\n })),\n };\n\n fs.writeFileSync(path.join(stateDir, \"invite.json\"), JSON.stringify(inviteState, null, 2));\n\n if (options.verbose === true) {\n console.log(`Group ID: ${groupId.urString()}`);\n console.log(`Start ARID: ${startArid.urString()}`);\n }\n\n return {\n groupId,\n requestId,\n envelopeUr: envelope.urString(),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAkEA,SAAS,YACP,UACA,eACA,SACA,kBACA,WACY;CAEZ,MAAM,WAAW,oBAAoB,UAAU,gBAAgB;CAC/D,MAAM,kBAA4B,SAAS,KAAK,GAAG,YAAY,OAAO,cAAc,CAAC;CACrF,MAAM,kBAAyB,SAAS,KAAK,CAAC,SAAS,GAAG;CAG1D,MAAM,mBAA2B,gBAAgB,UAAU,KAAK,IAAI,CAAC;CAGrE,MAAM,kBAAkB,IAAI,gBAAgB;CAC5C,KAAK,IAAI,IAAI,GAAG,IAAI,gBAAgB,QAAQ,KAC1C,gBAAgB,eAAe,gBAAgB,IAAI,iBAAiB,EAAE;CAIxE,MAAM,mBAAmB,gBAAgB;CACzC,IAAI,mBAAmB,GACrB,MAAM,IAAI,MAAM,yDAAyD;CAI3E,MAAM,aAAa,iBAAiB;CACpC,IAAI,aAAa,GACf,MAAM,IAAI,MAAM,kCAAkC;CAEpD,IAAI,aAAa,kBACf,MAAM,IAAI,MAAM,+CAA+C;CAOjE,MAAM,SAAS,wBAAwB,QAAQ;CAG/C,MAAM,sBAAM,IAAI,KAAK;CACrB,MAAM,aAAa,IAAI,KAAK,KAAK,IAAI,IAAI,YAAY,KAAK,KAAK,KAAK,GAAI;CAexE,OAAO;EAAE,QAZM,UAAU,OACvB,KAAK,IAAI,GACT,QACA,KAAK,IAAI,GACT,KACA,YACA,YACA,SACA,iBACA,gBAGY;EAAG;EAAiB;CAAgB;AACpD;;;;;;AAOA,eAAsB,OACpB,QACA,SACA,KAC0B;CAC1B,MAAM,eAAe,oBAAoB,QAAQ,cAAc,GAAG;CAClE,MAAM,WAAW,SAAS,KAAK,YAAY;CAW3C,MAAM,EAAE,QAAQ,WAAW,iBAAiB,oBARzB,YACjB,UACA,QAAQ,YACR,QAAQ,SACR,QAAQ,kBACR,QAAQ,SAG+D;CACzE,MAAM,UAAU,UAAU,QAAQ;CAClC,MAAM,YAAY,UAAU,UAAU;CAGtC,MAAM,WAAW,UAAU,WAAW;CAGtC,MAAM,YAAY,KAAK,IAAI;CAC3B,MAAM,iBACJ,QACA,WACA,UACA,sBACA,QAAQ,WAAW,KACrB;CAGA,MAAM,QAAQ,SAAS,MAAM;CAC7B,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,6CAA6C;CAG/D,MAAM,cAAc,IAAI,iBAAiB,MAAM,IAAI,CAAC;CACpD,MAAM,oBAAoB,gBAAgB,KAAK,QAAQ,IAAI,iBAAiB,GAAG,CAAC;CAEhF,MAAM,cAAc,IAAI,YACtB,QAAQ,SACR,UAAU,WAAW,GACrB,aACA,iBACF;CAGA,YAAY,mBAAmB,eAAe;CAG9C,SAAS,YAAY,SAAS,WAAW;CACzC,SAAS,KAAK,YAAY;CAG1B,MAAM,WAAW,YAAY,cAAc,QAAQ,IAAI,CAAC;CACxD,GAAG,UAAU,UAAU,EAAE,WAAW,KAAK,CAAC;CAE1C,MAAM,cAMF;EACF,OAAO,QAAQ,SAAS;EACxB,YAAY,UAAU,SAAS;EAC/B,YAAY,UAAU,SAAS;EAC/B,aAAa,UAAU,WAAW,CAAC,CAAC,YAAY;EAChD,cAAc,UAAU,aAAa,CAAC,CAAC,KAAK,OAAO;GACjD,KAAK,EAAE,IAAI,CAAC,CAAC,SAAS;GACtB,eAAe,EAAE,aAAa,CAAC,CAAC,SAAS;EAC3C,EAAE;CACJ;CAEA,GAAG,cAAc,KAAK,KAAK,UAAU,aAAa,GAAG,KAAK,UAAU,aAAa,MAAM,CAAC,CAAC;CAEzF,IAAI,QAAQ,YAAY,MAAM;EAC5B,QAAQ,IAAI,aAAa,QAAQ,SAAS,GAAG;EAC7C,QAAQ,IAAI,eAAe,UAAU,SAAS,GAAG;CACnD;CAEA,OAAO;EACL;EACA;EACA,YAAY,SAAS,SAAS;CAChC;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"parallel-PZiwHZT8.mjs","names":[],"sources":["../src/cmd/parallel.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * Parallel fetch and send utilities for coordinator commands.\n *\n * This module provides utilities for fetching responses from multiple\n * participants in parallel with progress display.\n *\n * Port of cmd/parallel.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport { type ARID, type XID } from \"@bcts/components\";\nimport { type Envelope } from \"@bcts/envelope\";\n\nimport { type StorageClient } from \"./storage.js\";\n\n/**\n * Status of a participant's response fetch.\n *\n * Port of `enum FetchStatus` from cmd/parallel.rs.\n */\nexport type FetchStatus =\n | { type: \"Pending\" }\n | { type: \"Success\"; envelope: Envelope }\n | { type: \"Rejected\"; reason: string }\n | { type: \"Error\"; error: string }\n | { type: \"Timeout\" };\n\n/**\n * Create a Pending status.\n */\nexport function fetchStatusPending(): FetchStatus {\n return { type: \"Pending\" };\n}\n\n/**\n * Create a Success status.\n */\nexport function fetchStatusSuccess(envelope: Envelope): FetchStatus {\n return { type: \"Success\", envelope };\n}\n\n/**\n * Create a Rejected status.\n */\nexport function fetchStatusRejected(reason: string): FetchStatus {\n return { type: \"Rejected\", reason };\n}\n\n/**\n * Create an Error status.\n */\nexport function fetchStatusError(error: string): FetchStatus {\n return { type: \"Error\", error };\n}\n\n/**\n * Create a Timeout status.\n */\nexport function fetchStatusTimeout(): FetchStatus {\n return { type: \"Timeout\" };\n}\n\n/**\n * Direction of the operation (get or put).\n *\n * Port of `enum Direction` from cmd/parallel.rs.\n */\nexport enum Direction {\n /** Downloading from storage */\n Get = \"Get\",\n /** Uploading to storage */\n Put = \"Put\",\n}\n\n/**\n * Get the emoji for a direction.\n *\n * Port of `Direction::emoji()` from cmd/parallel.rs.\n */\nexport function directionEmoji(direction: Direction): string {\n switch (direction) {\n case Direction.Get:\n return \"⬇️\";\n case Direction.Put:\n return \"⬆️\";\n }\n}\n\n/**\n * Configuration for parallel fetch operations.\n *\n * Port of `struct ParallelFetchConfig` from cmd/parallel.rs.\n */\nexport interface ParallelFetchConfig {\n /** Maximum time to wait for all responses (in seconds) */\n timeoutSeconds?: number | undefined;\n /** Whether to show verbose output */\n verbose?: boolean | undefined;\n}\n\n/**\n * Default timeout in seconds (10 minutes).\n */\nexport const DEFAULT_TIMEOUT_SECONDS = 600;\n\n/**\n * Create a config with the specified timeout.\n */\nexport function parallelFetchConfigWithTimeout(timeoutSeconds?: number): ParallelFetchConfig {\n return { timeoutSeconds };\n}\n\n/**\n * Result of collecting responses from multiple participants.\n *\n * Port of `struct CollectionResult` from cmd/parallel.rs.\n */\nexport class CollectionResult<T> {\n /** Successful responses as [XID, T] tuples */\n successes: [XID, T][];\n /** Participants who explicitly rejected as [XID, reason] tuples */\n rejections: [XID, string][];\n /** Participants with network/parsing errors as [XID, error] tuples */\n errors: [XID, string][];\n /** Participants who timed out */\n timeouts: XID[];\n\n constructor() {\n this.successes = [];\n this.rejections = [];\n this.errors = [];\n this.timeouts = [];\n }\n\n /**\n * Check if enough responses were received to proceed.\n *\n * Port of `CollectionResult::can_proceed()` from cmd/parallel.rs.\n */\n canProceed(minRequired: number): boolean {\n return this.successes.length >= minRequired;\n }\n\n /**\n * Total number of participants.\n *\n * Port of `CollectionResult::total()` from cmd/parallel.rs.\n */\n total(): number {\n return (\n this.successes.length + this.rejections.length + this.errors.length + this.timeouts.length\n );\n }\n\n /**\n * Check if all responses succeeded.\n *\n * Port of `CollectionResult::all_succeeded()` from cmd/parallel.rs.\n */\n allSucceeded(): boolean {\n return this.rejections.length === 0 && this.errors.length === 0 && this.timeouts.length === 0;\n }\n}\n\n/**\n * Create an empty collection result.\n */\nexport function emptyCollectionResult<T>(): CollectionResult<T> {\n return new CollectionResult<T>();\n}\n\n/**\n * Helper to build request tuples from pending requests and registry.\n *\n * Port of `build_fetch_requests()` from cmd/parallel.rs.\n */\nexport function buildFetchRequests(\n pending: Iterable<[XID, ARID]>,\n getName: (xid: XID) => string,\n): [XID, ARID, string][] {\n const requests: [XID, ARID, string][] = [];\n for (const [xid, arid] of pending) {\n const name = getName(xid);\n requests.push([xid, arid, name]);\n }\n return requests;\n}\n\n/**\n * Simple progress output for non-interactive terminals.\n */\nfunction logProgress(\n direction: Direction,\n name: string,\n status: \"success\" | \"error\" | \"timeout\",\n message?: string,\n): void {\n const emoji = directionEmoji(direction);\n switch (status) {\n case \"success\":\n console.error(`${emoji} ✅ ${name}`);\n break;\n case \"error\":\n console.error(`${emoji} ❌ ${name}: ${message ?? \"Error\"}`);\n break;\n case \"timeout\":\n console.error(`${emoji} ❌ ${name}: Timeout`);\n break;\n }\n}\n\n/**\n * Fetch messages from multiple ARIDs in parallel.\n *\n * Port of `parallel_fetch()` from cmd/parallel.rs.\n */\nexport async function parallelFetch<T>(\n client: StorageClient,\n requests: [XID, ARID, string][],\n validate: (envelope: Envelope, xid: XID) => T | { rejected: string },\n config: ParallelFetchConfig,\n): Promise<CollectionResult<T>> {\n const result = new CollectionResult<T>();\n const timeoutSeconds = config.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS;\n\n if (config.verbose === true) {\n console.error(`Waiting for ${requests.length} responses...`);\n }\n\n const promises = requests.map(async ([xid, arid, name]) => {\n try {\n const envelope = await client.get(arid, timeoutSeconds);\n\n if (!envelope) {\n result.timeouts.push(xid);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"timeout\");\n }\n return;\n }\n\n const parsed = validate(envelope, xid);\n\n if (parsed !== null && typeof parsed === \"object\" && \"rejected\" in parsed) {\n result.rejections.push([xid, parsed.rejected]);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"error\", parsed.rejected);\n }\n } else {\n result.successes.push([xid, parsed]);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"success\");\n }\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n if (errorMessage.includes(\"Timeout\") || errorMessage.includes(\"timeout\")) {\n result.timeouts.push(xid);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"timeout\");\n }\n } else {\n result.errors.push([xid, `${name}: ${errorMessage}`]);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"error\", errorMessage);\n }\n }\n }\n });\n\n await Promise.all(promises);\n\n if (config.verbose === true) {\n console.error(`Collected ${result.successes.length} responses`);\n if (result.rejections.length > 0) {\n console.error(` ${result.rejections.length} rejections`);\n }\n if (result.errors.length > 0) {\n console.error(` ${result.errors.length} errors`);\n }\n if (result.timeouts.length > 0) {\n console.error(` ${result.timeouts.length} timeouts`);\n }\n }\n\n return result;\n}\n\n/**\n * Send messages to multiple ARIDs in parallel.\n *\n * Port of `parallel_send()` from cmd/parallel.rs.\n */\nexport async function parallelSend(\n client: StorageClient,\n messages: [XID, ARID, Envelope, string][],\n verbose?: boolean,\n): Promise<[XID, Error | null][]> {\n const results: [XID, Error | null][] = [];\n\n if (verbose === true) {\n console.error(`Sending to ${messages.length} participants...`);\n }\n\n const promises = messages.map(async ([xid, arid, envelope, name]) => {\n try {\n await client.put(arid, envelope);\n results.push([xid, null]);\n if (verbose === true) {\n logProgress(Direction.Put, name, \"success\");\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n results.push([xid, err]);\n if (verbose === true) {\n logProgress(Direction.Put, name, \"error\", err.message);\n }\n }\n });\n\n await Promise.all(promises);\n\n if (verbose === true) {\n const successes = results.filter(([_, err]) => err === null).length;\n const failures = results.length - successes;\n console.error(`Sent ${successes} messages`);\n if (failures > 0) {\n console.error(` ${failures} failed`);\n }\n }\n\n return results;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"parallel-PZiwHZT8.mjs","names":[],"sources":["../src/cmd/parallel.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * Parallel fetch and send utilities for coordinator commands.\n *\n * This module provides utilities for fetching responses from multiple\n * participants in parallel with progress display.\n *\n * Port of cmd/parallel.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport { type ARID, type XID } from \"@bcts/components\";\nimport { type Envelope } from \"@bcts/envelope\";\n\nimport { type StorageClient } from \"./storage.js\";\n\n/**\n * Status of a participant's response fetch.\n *\n * Port of `enum FetchStatus` from cmd/parallel.rs.\n */\nexport type FetchStatus =\n | { type: \"Pending\" }\n | { type: \"Success\"; envelope: Envelope }\n | { type: \"Rejected\"; reason: string }\n | { type: \"Error\"; error: string }\n | { type: \"Timeout\" };\n\n/**\n * Create a Pending status.\n */\nexport function fetchStatusPending(): FetchStatus {\n return { type: \"Pending\" };\n}\n\n/**\n * Create a Success status.\n */\nexport function fetchStatusSuccess(envelope: Envelope): FetchStatus {\n return { type: \"Success\", envelope };\n}\n\n/**\n * Create a Rejected status.\n */\nexport function fetchStatusRejected(reason: string): FetchStatus {\n return { type: \"Rejected\", reason };\n}\n\n/**\n * Create an Error status.\n */\nexport function fetchStatusError(error: string): FetchStatus {\n return { type: \"Error\", error };\n}\n\n/**\n * Create a Timeout status.\n */\nexport function fetchStatusTimeout(): FetchStatus {\n return { type: \"Timeout\" };\n}\n\n/**\n * Direction of the operation (get or put).\n *\n * Port of `enum Direction` from cmd/parallel.rs.\n */\nexport enum Direction {\n /** Downloading from storage */\n Get = \"Get\",\n /** Uploading to storage */\n Put = \"Put\",\n}\n\n/**\n * Get the emoji for a direction.\n *\n * Port of `Direction::emoji()` from cmd/parallel.rs.\n */\nexport function directionEmoji(direction: Direction): string {\n switch (direction) {\n case Direction.Get:\n return \"⬇️\";\n case Direction.Put:\n return \"⬆️\";\n }\n}\n\n/**\n * Configuration for parallel fetch operations.\n *\n * Port of `struct ParallelFetchConfig` from cmd/parallel.rs.\n */\nexport interface ParallelFetchConfig {\n /** Maximum time to wait for all responses (in seconds) */\n timeoutSeconds?: number | undefined;\n /** Whether to show verbose output */\n verbose?: boolean | undefined;\n}\n\n/**\n * Default timeout in seconds (10 minutes).\n */\nexport const DEFAULT_TIMEOUT_SECONDS = 600;\n\n/**\n * Create a config with the specified timeout.\n */\nexport function parallelFetchConfigWithTimeout(timeoutSeconds?: number): ParallelFetchConfig {\n return { timeoutSeconds };\n}\n\n/**\n * Result of collecting responses from multiple participants.\n *\n * Port of `struct CollectionResult` from cmd/parallel.rs.\n */\nexport class CollectionResult<T> {\n /** Successful responses as [XID, T] tuples */\n successes: [XID, T][];\n /** Participants who explicitly rejected as [XID, reason] tuples */\n rejections: [XID, string][];\n /** Participants with network/parsing errors as [XID, error] tuples */\n errors: [XID, string][];\n /** Participants who timed out */\n timeouts: XID[];\n\n constructor() {\n this.successes = [];\n this.rejections = [];\n this.errors = [];\n this.timeouts = [];\n }\n\n /**\n * Check if enough responses were received to proceed.\n *\n * Port of `CollectionResult::can_proceed()` from cmd/parallel.rs.\n */\n canProceed(minRequired: number): boolean {\n return this.successes.length >= minRequired;\n }\n\n /**\n * Total number of participants.\n *\n * Port of `CollectionResult::total()` from cmd/parallel.rs.\n */\n total(): number {\n return (\n this.successes.length + this.rejections.length + this.errors.length + this.timeouts.length\n );\n }\n\n /**\n * Check if all responses succeeded.\n *\n * Port of `CollectionResult::all_succeeded()` from cmd/parallel.rs.\n */\n allSucceeded(): boolean {\n return this.rejections.length === 0 && this.errors.length === 0 && this.timeouts.length === 0;\n }\n}\n\n/**\n * Create an empty collection result.\n */\nexport function emptyCollectionResult<T>(): CollectionResult<T> {\n return new CollectionResult<T>();\n}\n\n/**\n * Helper to build request tuples from pending requests and registry.\n *\n * Port of `build_fetch_requests()` from cmd/parallel.rs.\n */\nexport function buildFetchRequests(\n pending: Iterable<[XID, ARID]>,\n getName: (xid: XID) => string,\n): [XID, ARID, string][] {\n const requests: [XID, ARID, string][] = [];\n for (const [xid, arid] of pending) {\n const name = getName(xid);\n requests.push([xid, arid, name]);\n }\n return requests;\n}\n\n/**\n * Simple progress output for non-interactive terminals.\n */\nfunction logProgress(\n direction: Direction,\n name: string,\n status: \"success\" | \"error\" | \"timeout\",\n message?: string,\n): void {\n const emoji = directionEmoji(direction);\n switch (status) {\n case \"success\":\n console.error(`${emoji} ✅ ${name}`);\n break;\n case \"error\":\n console.error(`${emoji} ❌ ${name}: ${message ?? \"Error\"}`);\n break;\n case \"timeout\":\n console.error(`${emoji} ❌ ${name}: Timeout`);\n break;\n }\n}\n\n/**\n * Fetch messages from multiple ARIDs in parallel.\n *\n * Port of `parallel_fetch()` from cmd/parallel.rs.\n */\nexport async function parallelFetch<T>(\n client: StorageClient,\n requests: [XID, ARID, string][],\n validate: (envelope: Envelope, xid: XID) => T | { rejected: string },\n config: ParallelFetchConfig,\n): Promise<CollectionResult<T>> {\n const result = new CollectionResult<T>();\n const timeoutSeconds = config.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS;\n\n if (config.verbose === true) {\n console.error(`Waiting for ${requests.length} responses...`);\n }\n\n const promises = requests.map(async ([xid, arid, name]) => {\n try {\n const envelope = await client.get(arid, timeoutSeconds);\n\n if (!envelope) {\n result.timeouts.push(xid);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"timeout\");\n }\n return;\n }\n\n const parsed = validate(envelope, xid);\n\n if (parsed !== null && typeof parsed === \"object\" && \"rejected\" in parsed) {\n result.rejections.push([xid, parsed.rejected]);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"error\", parsed.rejected);\n }\n } else {\n result.successes.push([xid, parsed]);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"success\");\n }\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n if (errorMessage.includes(\"Timeout\") || errorMessage.includes(\"timeout\")) {\n result.timeouts.push(xid);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"timeout\");\n }\n } else {\n result.errors.push([xid, `${name}: ${errorMessage}`]);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"error\", errorMessage);\n }\n }\n }\n });\n\n await Promise.all(promises);\n\n if (config.verbose === true) {\n console.error(`Collected ${result.successes.length} responses`);\n if (result.rejections.length > 0) {\n console.error(` ${result.rejections.length} rejections`);\n }\n if (result.errors.length > 0) {\n console.error(` ${result.errors.length} errors`);\n }\n if (result.timeouts.length > 0) {\n console.error(` ${result.timeouts.length} timeouts`);\n }\n }\n\n return result;\n}\n\n/**\n * Send messages to multiple ARIDs in parallel.\n *\n * Port of `parallel_send()` from cmd/parallel.rs.\n */\nexport async function parallelSend(\n client: StorageClient,\n messages: [XID, ARID, Envelope, string][],\n verbose?: boolean,\n): Promise<[XID, Error | null][]> {\n const results: [XID, Error | null][] = [];\n\n if (verbose === true) {\n console.error(`Sending to ${messages.length} participants...`);\n }\n\n const promises = messages.map(async ([xid, arid, envelope, name]) => {\n try {\n await client.put(arid, envelope);\n results.push([xid, null]);\n if (verbose === true) {\n logProgress(Direction.Put, name, \"success\");\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n results.push([xid, err]);\n if (verbose === true) {\n logProgress(Direction.Put, name, \"error\", err.message);\n }\n }\n });\n\n await Promise.all(promises);\n\n if (verbose === true) {\n const successes = results.filter(([_, err]) => err === null).length;\n const failures = results.length - successes;\n console.error(`Sent ${successes} messages`);\n if (failures > 0) {\n console.error(` ${failures} failed`);\n }\n }\n\n return results;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"parallel-szwYx-bi.cjs","names":[],"sources":["../src/cmd/parallel.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * Parallel fetch and send utilities for coordinator commands.\n *\n * This module provides utilities for fetching responses from multiple\n * participants in parallel with progress display.\n *\n * Port of cmd/parallel.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport { type ARID, type XID } from \"@bcts/components\";\nimport { type Envelope } from \"@bcts/envelope\";\n\nimport { type StorageClient } from \"./storage.js\";\n\n/**\n * Status of a participant's response fetch.\n *\n * Port of `enum FetchStatus` from cmd/parallel.rs.\n */\nexport type FetchStatus =\n | { type: \"Pending\" }\n | { type: \"Success\"; envelope: Envelope }\n | { type: \"Rejected\"; reason: string }\n | { type: \"Error\"; error: string }\n | { type: \"Timeout\" };\n\n/**\n * Create a Pending status.\n */\nexport function fetchStatusPending(): FetchStatus {\n return { type: \"Pending\" };\n}\n\n/**\n * Create a Success status.\n */\nexport function fetchStatusSuccess(envelope: Envelope): FetchStatus {\n return { type: \"Success\", envelope };\n}\n\n/**\n * Create a Rejected status.\n */\nexport function fetchStatusRejected(reason: string): FetchStatus {\n return { type: \"Rejected\", reason };\n}\n\n/**\n * Create an Error status.\n */\nexport function fetchStatusError(error: string): FetchStatus {\n return { type: \"Error\", error };\n}\n\n/**\n * Create a Timeout status.\n */\nexport function fetchStatusTimeout(): FetchStatus {\n return { type: \"Timeout\" };\n}\n\n/**\n * Direction of the operation (get or put).\n *\n * Port of `enum Direction` from cmd/parallel.rs.\n */\nexport enum Direction {\n /** Downloading from storage */\n Get = \"Get\",\n /** Uploading to storage */\n Put = \"Put\",\n}\n\n/**\n * Get the emoji for a direction.\n *\n * Port of `Direction::emoji()` from cmd/parallel.rs.\n */\nexport function directionEmoji(direction: Direction): string {\n switch (direction) {\n case Direction.Get:\n return \"⬇️\";\n case Direction.Put:\n return \"⬆️\";\n }\n}\n\n/**\n * Configuration for parallel fetch operations.\n *\n * Port of `struct ParallelFetchConfig` from cmd/parallel.rs.\n */\nexport interface ParallelFetchConfig {\n /** Maximum time to wait for all responses (in seconds) */\n timeoutSeconds?: number | undefined;\n /** Whether to show verbose output */\n verbose?: boolean | undefined;\n}\n\n/**\n * Default timeout in seconds (10 minutes).\n */\nexport const DEFAULT_TIMEOUT_SECONDS = 600;\n\n/**\n * Create a config with the specified timeout.\n */\nexport function parallelFetchConfigWithTimeout(timeoutSeconds?: number): ParallelFetchConfig {\n return { timeoutSeconds };\n}\n\n/**\n * Result of collecting responses from multiple participants.\n *\n * Port of `struct CollectionResult` from cmd/parallel.rs.\n */\nexport class CollectionResult<T> {\n /** Successful responses as [XID, T] tuples */\n successes: [XID, T][];\n /** Participants who explicitly rejected as [XID, reason] tuples */\n rejections: [XID, string][];\n /** Participants with network/parsing errors as [XID, error] tuples */\n errors: [XID, string][];\n /** Participants who timed out */\n timeouts: XID[];\n\n constructor() {\n this.successes = [];\n this.rejections = [];\n this.errors = [];\n this.timeouts = [];\n }\n\n /**\n * Check if enough responses were received to proceed.\n *\n * Port of `CollectionResult::can_proceed()` from cmd/parallel.rs.\n */\n canProceed(minRequired: number): boolean {\n return this.successes.length >= minRequired;\n }\n\n /**\n * Total number of participants.\n *\n * Port of `CollectionResult::total()` from cmd/parallel.rs.\n */\n total(): number {\n return (\n this.successes.length + this.rejections.length + this.errors.length + this.timeouts.length\n );\n }\n\n /**\n * Check if all responses succeeded.\n *\n * Port of `CollectionResult::all_succeeded()` from cmd/parallel.rs.\n */\n allSucceeded(): boolean {\n return this.rejections.length === 0 && this.errors.length === 0 && this.timeouts.length === 0;\n }\n}\n\n/**\n * Create an empty collection result.\n */\nexport function emptyCollectionResult<T>(): CollectionResult<T> {\n return new CollectionResult<T>();\n}\n\n/**\n * Helper to build request tuples from pending requests and registry.\n *\n * Port of `build_fetch_requests()` from cmd/parallel.rs.\n */\nexport function buildFetchRequests(\n pending: Iterable<[XID, ARID]>,\n getName: (xid: XID) => string,\n): [XID, ARID, string][] {\n const requests: [XID, ARID, string][] = [];\n for (const [xid, arid] of pending) {\n const name = getName(xid);\n requests.push([xid, arid, name]);\n }\n return requests;\n}\n\n/**\n * Simple progress output for non-interactive terminals.\n */\nfunction logProgress(\n direction: Direction,\n name: string,\n status: \"success\" | \"error\" | \"timeout\",\n message?: string,\n): void {\n const emoji = directionEmoji(direction);\n switch (status) {\n case \"success\":\n console.error(`${emoji} ✅ ${name}`);\n break;\n case \"error\":\n console.error(`${emoji} ❌ ${name}: ${message ?? \"Error\"}`);\n break;\n case \"timeout\":\n console.error(`${emoji} ❌ ${name}: Timeout`);\n break;\n }\n}\n\n/**\n * Fetch messages from multiple ARIDs in parallel.\n *\n * Port of `parallel_fetch()` from cmd/parallel.rs.\n */\nexport async function parallelFetch<T>(\n client: StorageClient,\n requests: [XID, ARID, string][],\n validate: (envelope: Envelope, xid: XID) => T | { rejected: string },\n config: ParallelFetchConfig,\n): Promise<CollectionResult<T>> {\n const result = new CollectionResult<T>();\n const timeoutSeconds = config.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS;\n\n if (config.verbose === true) {\n console.error(`Waiting for ${requests.length} responses...`);\n }\n\n const promises = requests.map(async ([xid, arid, name]) => {\n try {\n const envelope = await client.get(arid, timeoutSeconds);\n\n if (!envelope) {\n result.timeouts.push(xid);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"timeout\");\n }\n return;\n }\n\n const parsed = validate(envelope, xid);\n\n if (parsed !== null && typeof parsed === \"object\" && \"rejected\" in parsed) {\n result.rejections.push([xid, parsed.rejected]);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"error\", parsed.rejected);\n }\n } else {\n result.successes.push([xid, parsed]);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"success\");\n }\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n if (errorMessage.includes(\"Timeout\") || errorMessage.includes(\"timeout\")) {\n result.timeouts.push(xid);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"timeout\");\n }\n } else {\n result.errors.push([xid, `${name}: ${errorMessage}`]);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"error\", errorMessage);\n }\n }\n }\n });\n\n await Promise.all(promises);\n\n if (config.verbose === true) {\n console.error(`Collected ${result.successes.length} responses`);\n if (result.rejections.length > 0) {\n console.error(` ${result.rejections.length} rejections`);\n }\n if (result.errors.length > 0) {\n console.error(` ${result.errors.length} errors`);\n }\n if (result.timeouts.length > 0) {\n console.error(` ${result.timeouts.length} timeouts`);\n }\n }\n\n return result;\n}\n\n/**\n * Send messages to multiple ARIDs in parallel.\n *\n * Port of `parallel_send()` from cmd/parallel.rs.\n */\nexport async function parallelSend(\n client: StorageClient,\n messages: [XID, ARID, Envelope, string][],\n verbose?: boolean,\n): Promise<[XID, Error | null][]> {\n const results: [XID, Error | null][] = [];\n\n if (verbose === true) {\n console.error(`Sending to ${messages.length} participants...`);\n }\n\n const promises = messages.map(async ([xid, arid, envelope, name]) => {\n try {\n await client.put(arid, envelope);\n results.push([xid, null]);\n if (verbose === true) {\n logProgress(Direction.Put, name, \"success\");\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n results.push([xid, err]);\n if (verbose === true) {\n logProgress(Direction.Put, name, \"error\", err.message);\n }\n }\n });\n\n await Promise.all(promises);\n\n if (verbose === true) {\n const successes = results.filter(([_, err]) => err === null).length;\n const failures = results.length - successes;\n console.error(`Sent ${successes} messages`);\n if (failures > 0) {\n console.error(` ${failures} failed`);\n }\n }\n\n return results;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"parallel-szwYx-bi.cjs","names":[],"sources":["../src/cmd/parallel.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * Parallel fetch and send utilities for coordinator commands.\n *\n * This module provides utilities for fetching responses from multiple\n * participants in parallel with progress display.\n *\n * Port of cmd/parallel.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport { type ARID, type XID } from \"@bcts/components\";\nimport { type Envelope } from \"@bcts/envelope\";\n\nimport { type StorageClient } from \"./storage.js\";\n\n/**\n * Status of a participant's response fetch.\n *\n * Port of `enum FetchStatus` from cmd/parallel.rs.\n */\nexport type FetchStatus =\n | { type: \"Pending\" }\n | { type: \"Success\"; envelope: Envelope }\n | { type: \"Rejected\"; reason: string }\n | { type: \"Error\"; error: string }\n | { type: \"Timeout\" };\n\n/**\n * Create a Pending status.\n */\nexport function fetchStatusPending(): FetchStatus {\n return { type: \"Pending\" };\n}\n\n/**\n * Create a Success status.\n */\nexport function fetchStatusSuccess(envelope: Envelope): FetchStatus {\n return { type: \"Success\", envelope };\n}\n\n/**\n * Create a Rejected status.\n */\nexport function fetchStatusRejected(reason: string): FetchStatus {\n return { type: \"Rejected\", reason };\n}\n\n/**\n * Create an Error status.\n */\nexport function fetchStatusError(error: string): FetchStatus {\n return { type: \"Error\", error };\n}\n\n/**\n * Create a Timeout status.\n */\nexport function fetchStatusTimeout(): FetchStatus {\n return { type: \"Timeout\" };\n}\n\n/**\n * Direction of the operation (get or put).\n *\n * Port of `enum Direction` from cmd/parallel.rs.\n */\nexport enum Direction {\n /** Downloading from storage */\n Get = \"Get\",\n /** Uploading to storage */\n Put = \"Put\",\n}\n\n/**\n * Get the emoji for a direction.\n *\n * Port of `Direction::emoji()` from cmd/parallel.rs.\n */\nexport function directionEmoji(direction: Direction): string {\n switch (direction) {\n case Direction.Get:\n return \"⬇️\";\n case Direction.Put:\n return \"⬆️\";\n }\n}\n\n/**\n * Configuration for parallel fetch operations.\n *\n * Port of `struct ParallelFetchConfig` from cmd/parallel.rs.\n */\nexport interface ParallelFetchConfig {\n /** Maximum time to wait for all responses (in seconds) */\n timeoutSeconds?: number | undefined;\n /** Whether to show verbose output */\n verbose?: boolean | undefined;\n}\n\n/**\n * Default timeout in seconds (10 minutes).\n */\nexport const DEFAULT_TIMEOUT_SECONDS = 600;\n\n/**\n * Create a config with the specified timeout.\n */\nexport function parallelFetchConfigWithTimeout(timeoutSeconds?: number): ParallelFetchConfig {\n return { timeoutSeconds };\n}\n\n/**\n * Result of collecting responses from multiple participants.\n *\n * Port of `struct CollectionResult` from cmd/parallel.rs.\n */\nexport class CollectionResult<T> {\n /** Successful responses as [XID, T] tuples */\n successes: [XID, T][];\n /** Participants who explicitly rejected as [XID, reason] tuples */\n rejections: [XID, string][];\n /** Participants with network/parsing errors as [XID, error] tuples */\n errors: [XID, string][];\n /** Participants who timed out */\n timeouts: XID[];\n\n constructor() {\n this.successes = [];\n this.rejections = [];\n this.errors = [];\n this.timeouts = [];\n }\n\n /**\n * Check if enough responses were received to proceed.\n *\n * Port of `CollectionResult::can_proceed()` from cmd/parallel.rs.\n */\n canProceed(minRequired: number): boolean {\n return this.successes.length >= minRequired;\n }\n\n /**\n * Total number of participants.\n *\n * Port of `CollectionResult::total()` from cmd/parallel.rs.\n */\n total(): number {\n return (\n this.successes.length + this.rejections.length + this.errors.length + this.timeouts.length\n );\n }\n\n /**\n * Check if all responses succeeded.\n *\n * Port of `CollectionResult::all_succeeded()` from cmd/parallel.rs.\n */\n allSucceeded(): boolean {\n return this.rejections.length === 0 && this.errors.length === 0 && this.timeouts.length === 0;\n }\n}\n\n/**\n * Create an empty collection result.\n */\nexport function emptyCollectionResult<T>(): CollectionResult<T> {\n return new CollectionResult<T>();\n}\n\n/**\n * Helper to build request tuples from pending requests and registry.\n *\n * Port of `build_fetch_requests()` from cmd/parallel.rs.\n */\nexport function buildFetchRequests(\n pending: Iterable<[XID, ARID]>,\n getName: (xid: XID) => string,\n): [XID, ARID, string][] {\n const requests: [XID, ARID, string][] = [];\n for (const [xid, arid] of pending) {\n const name = getName(xid);\n requests.push([xid, arid, name]);\n }\n return requests;\n}\n\n/**\n * Simple progress output for non-interactive terminals.\n */\nfunction logProgress(\n direction: Direction,\n name: string,\n status: \"success\" | \"error\" | \"timeout\",\n message?: string,\n): void {\n const emoji = directionEmoji(direction);\n switch (status) {\n case \"success\":\n console.error(`${emoji} ✅ ${name}`);\n break;\n case \"error\":\n console.error(`${emoji} ❌ ${name}: ${message ?? \"Error\"}`);\n break;\n case \"timeout\":\n console.error(`${emoji} ❌ ${name}: Timeout`);\n break;\n }\n}\n\n/**\n * Fetch messages from multiple ARIDs in parallel.\n *\n * Port of `parallel_fetch()` from cmd/parallel.rs.\n */\nexport async function parallelFetch<T>(\n client: StorageClient,\n requests: [XID, ARID, string][],\n validate: (envelope: Envelope, xid: XID) => T | { rejected: string },\n config: ParallelFetchConfig,\n): Promise<CollectionResult<T>> {\n const result = new CollectionResult<T>();\n const timeoutSeconds = config.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS;\n\n if (config.verbose === true) {\n console.error(`Waiting for ${requests.length} responses...`);\n }\n\n const promises = requests.map(async ([xid, arid, name]) => {\n try {\n const envelope = await client.get(arid, timeoutSeconds);\n\n if (!envelope) {\n result.timeouts.push(xid);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"timeout\");\n }\n return;\n }\n\n const parsed = validate(envelope, xid);\n\n if (parsed !== null && typeof parsed === \"object\" && \"rejected\" in parsed) {\n result.rejections.push([xid, parsed.rejected]);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"error\", parsed.rejected);\n }\n } else {\n result.successes.push([xid, parsed]);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"success\");\n }\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n if (errorMessage.includes(\"Timeout\") || errorMessage.includes(\"timeout\")) {\n result.timeouts.push(xid);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"timeout\");\n }\n } else {\n result.errors.push([xid, `${name}: ${errorMessage}`]);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"error\", errorMessage);\n }\n }\n }\n });\n\n await Promise.all(promises);\n\n if (config.verbose === true) {\n console.error(`Collected ${result.successes.length} responses`);\n if (result.rejections.length > 0) {\n console.error(` ${result.rejections.length} rejections`);\n }\n if (result.errors.length > 0) {\n console.error(` ${result.errors.length} errors`);\n }\n if (result.timeouts.length > 0) {\n console.error(` ${result.timeouts.length} timeouts`);\n }\n }\n\n return result;\n}\n\n/**\n * Send messages to multiple ARIDs in parallel.\n *\n * Port of `parallel_send()` from cmd/parallel.rs.\n */\nexport async function parallelSend(\n client: StorageClient,\n messages: [XID, ARID, Envelope, string][],\n verbose?: boolean,\n): Promise<[XID, Error | null][]> {\n const results: [XID, Error | null][] = [];\n\n if (verbose === true) {\n console.error(`Sending to ${messages.length} participants...`);\n }\n\n const promises = messages.map(async ([xid, arid, envelope, name]) => {\n try {\n await client.put(arid, envelope);\n results.push([xid, null]);\n if (verbose === true) {\n logProgress(Direction.Put, name, \"success\");\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n results.push([xid, err]);\n if (verbose === true) {\n logProgress(Direction.Put, name, \"error\", err.message);\n }\n }\n });\n\n await Promise.all(promises);\n\n if (verbose === true) {\n const successes = results.filter(([_, err]) => err === null).length;\n const failures = results.length - successes;\n console.error(`Sent ${successes} messages`);\n if (failures > 0) {\n console.error(` ${failures} failed`);\n }\n }\n\n return results;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"proposed-participant-BvHNnpcZ.cjs","names":["UR","Envelope","XIDDocument","XIDVerifySignature"],"sources":["../src/dkg/proposed-participant.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * DKG Proposed Participant.\n *\n * Port of dkg/proposed_participant.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport { type ARID, type XID } from \"@bcts/components\";\nimport { Envelope } from \"@bcts/envelope\";\nimport { UR } from \"@bcts/uniform-resources\";\nimport { XIDDocument, XIDVerifySignature } from \"@bcts/xid\";\n\n/**\n * A proposed participant in a DKG session.\n *\n * Port of `struct DkgProposedParticipant` from proposed_participant.rs lines 8-13.\n */\nexport class DkgProposedParticipant {\n private readonly _urString: string;\n private readonly _envelope: Envelope;\n private readonly _document: XIDDocument;\n private readonly _responseArid: ARID;\n\n private constructor(\n urString: string,\n envelope: Envelope,\n document: XIDDocument,\n responseArid: ARID,\n ) {\n this._urString = urString;\n this._envelope = envelope;\n this._document = document;\n this._responseArid = responseArid;\n }\n\n /**\n * Create a new DkgProposedParticipant from a UR string and response ARID.\n *\n * Port of `DkgProposedParticipant::new()` from proposed_participant.rs lines 22-26.\n */\n static create(urString: string, responseArid: ARID): DkgProposedParticipant {\n const [envelope, document] = parseXidEnvelope(urString);\n return new DkgProposedParticipant(urString, envelope, document, responseArid);\n }\n\n /**\n * Get the XID of this participant.\n *\n * Port of `DkgProposedParticipant::xid()` from proposed_participant.rs line 28.\n */\n xid(): XID {\n return this._document.xid();\n }\n\n /**\n * Get the XID document of this participant.\n *\n * Port of `DkgProposedParticipant::xid_document()` from proposed_participant.rs line 30.\n */\n xidDocument(): XIDDocument {\n return this._document;\n }\n\n /**\n * Get the UR string of the XID document.\n *\n * Port of `DkgProposedParticipant::xid_document_ur()` from proposed_participant.rs line 32.\n */\n xidDocumentUr(): string {\n return this._urString;\n }\n\n /**\n * Get the envelope containing the XID document.\n *\n * Port of `DkgProposedParticipant::xid_document_envelope()` from proposed_participant.rs line 34.\n */\n xidDocumentEnvelope(): Envelope {\n return this._envelope;\n }\n\n /**\n * Get the response ARID for this participant.\n *\n * Port of `DkgProposedParticipant::response_arid()` from proposed_participant.rs line 36.\n */\n responseArid(): ARID {\n return this._responseArid;\n }\n\n /**\n * Compare participants by XID for sorting.\n *\n * Mirrors Rust `PartialOrd::partial_cmp` which uses\n * `self.xid().cmp(&other.xid())` — i.e. the underlying 32-byte XID\n * data is compared lexicographically (`Vec<u8>` ordering). The\n * earlier port used `xid.toString().localeCompare(...)`, which (a)\n * compares the UR-encoded base32-ish string, not the bytes, and (b)\n * is locale-aware. Sorting on UR strings differs from the byte\n * order whenever the underlying bytes contain values ≥ 0x80, so\n * Rust and TS would assign different FROST identifiers to the same\n * participant set — producing different secret shares.\n */\n compareTo(other: DkgProposedParticipant): number {\n return compareXidBytes(this.xid().toData(), other.xid().toData());\n }\n}\n\n/**\n * Lexicographic byte compare matching Rust's `Vec<u8>::cmp` /\n * `XID::cmp`. Exported so the cmd-tree call sites (round1 / finalize)\n * can use the same comparator when they sort deduplicated XID lists.\n *\n * `XID` is exactly 32 bytes so this only ever compares two equal-length\n * inputs; the length-tiebreak branch mirrors the generic `Ord` impl on\n * `Vec<u8>` and is included for correctness if ever applied to other\n * byte sequences.\n *\n * @internal\n */\nexport function compareXidBytes(a: Uint8Array, b: Uint8Array): number {\n const minLen = Math.min(a.length, b.length);\n for (let i = 0; i < minLen; i++) {\n if (a[i] !== b[i]) return a[i] < b[i] ? -1 : 1;\n }\n if (a.length !== b.length) return a.length < b.length ? -1 : 1;\n return 0;\n}\n\n/**\n * Parse a XID envelope from a UR string.\n *\n * Port of `parse_xid_envelope()` from proposed_participant.rs lines 39-60.\n */\nfunction parseXidEnvelope(input: string): [Envelope, XIDDocument] {\n const trimmed = input.trim();\n if (trimmed.length === 0) {\n throw new Error(\"XID document is required\");\n }\n\n const ur = UR.fromURString(trimmed);\n const urType = ur.urTypeStr();\n if (urType !== \"xid\" && urType !== \"envelope\") {\n throw new Error(`Expected a ur:xid document, found ur:${urType}`);\n }\n\n const envelopeCbor = ur.cbor();\n // Try tagged CBOR first, then untagged\n let envelope: Envelope;\n try {\n envelope = Envelope.fromTaggedCbor(envelopeCbor);\n } catch {\n envelope = Envelope.fromUntaggedCbor(envelopeCbor);\n }\n\n const document = XIDDocument.fromEnvelope(envelope, undefined, XIDVerifySignature.Inception);\n\n return [envelope, document];\n}\n"],"mappings":";;;;;;;;;AAsBA,IAAa,yBAAb,MAAa,uBAAuB;CAClC;CACA;CACA;CACA;CAEA,YACE,UACA,UACA,UACA,cACA;EACA,KAAK,YAAY;EACjB,KAAK,YAAY;EACjB,KAAK,YAAY;EACjB,KAAK,gBAAgB;CACvB;;;;;;CAOA,OAAO,OAAO,UAAkB,cAA4C;EAC1E,MAAM,CAAC,UAAU,YAAY,iBAAiB,QAAQ;EACtD,OAAO,IAAI,uBAAuB,UAAU,UAAU,UAAU,YAAY;CAC9E;;;;;;CAOA,MAAW;EACT,OAAO,KAAK,UAAU,IAAI;CAC5B;;;;;;CAOA,cAA2B;EACzB,OAAO,KAAK;CACd;;;;;;CAOA,gBAAwB;EACtB,OAAO,KAAK;CACd;;;;;;CAOA,sBAAgC;EAC9B,OAAO,KAAK;CACd;;;;;;CAOA,eAAqB;EACnB,OAAO,KAAK;CACd;;;;;;;;;;;;;;CAeA,UAAU,OAAuC;EAC/C,OAAO,gBAAgB,KAAK,IAAI,EAAE,OAAO,GAAG,MAAM,IAAI,EAAE,OAAO,CAAC;CAClE;AACF;;;;;;;;;;;;;AAcA,SAAgB,gBAAgB,GAAe,GAAuB;CACpE,MAAM,SAAS,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM;CAC1C,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,KAC1B,IAAI,EAAE,OAAO,EAAE,IAAI,OAAO,EAAE,KAAK,EAAE,KAAK,KAAK;CAE/C,IAAI,EAAE,WAAW,EAAE,QAAQ,OAAO,EAAE,SAAS,EAAE,SAAS,KAAK;CAC7D,OAAO;AACT;;;;;;AAOA,SAAS,iBAAiB,OAAwC;CAChE,MAAM,UAAU,MAAM,KAAK;CAC3B,IAAI,QAAQ,WAAW,GACrB,MAAM,IAAI,MAAM,0BAA0B;CAG5C,MAAM,KAAKA,wBAAAA,GAAG,aAAa,OAAO;CAClC,MAAM,SAAS,GAAG,UAAU;CAC5B,IAAI,WAAW,SAAS,WAAW,YACjC,MAAM,IAAI,MAAM,wCAAwC,QAAQ;CAGlE,MAAM,eAAe,GAAG,KAAK;CAE7B,IAAI;CACJ,IAAI;EACF,WAAWC,eAAAA,SAAS,eAAe,YAAY;CACjD,QAAQ;EACN,WAAWA,eAAAA,SAAS,iBAAiB,YAAY;CACnD;CAEA,MAAM,WAAWC,UAAAA,YAAY,aAAa,UAAU,KAAA,GAAWC,UAAAA,mBAAmB,SAAS;CAE3F,OAAO,CAAC,UAAU,QAAQ;AAC5B"}
1
+ {"version":3,"file":"proposed-participant-BvHNnpcZ.cjs","names":["UR","Envelope","XIDDocument","XIDVerifySignature"],"sources":["../src/dkg/proposed-participant.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * DKG Proposed Participant.\n *\n * Port of dkg/proposed_participant.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport { type ARID, type XID } from \"@bcts/components\";\nimport { Envelope } from \"@bcts/envelope\";\nimport { UR } from \"@bcts/uniform-resources\";\nimport { XIDDocument, XIDVerifySignature } from \"@bcts/xid\";\n\n/**\n * A proposed participant in a DKG session.\n *\n * Port of `struct DkgProposedParticipant` from proposed_participant.rs lines 8-13.\n */\nexport class DkgProposedParticipant {\n private readonly _urString: string;\n private readonly _envelope: Envelope;\n private readonly _document: XIDDocument;\n private readonly _responseArid: ARID;\n\n private constructor(\n urString: string,\n envelope: Envelope,\n document: XIDDocument,\n responseArid: ARID,\n ) {\n this._urString = urString;\n this._envelope = envelope;\n this._document = document;\n this._responseArid = responseArid;\n }\n\n /**\n * Create a new DkgProposedParticipant from a UR string and response ARID.\n *\n * Port of `DkgProposedParticipant::new()` from proposed_participant.rs lines 22-26.\n */\n static create(urString: string, responseArid: ARID): DkgProposedParticipant {\n const [envelope, document] = parseXidEnvelope(urString);\n return new DkgProposedParticipant(urString, envelope, document, responseArid);\n }\n\n /**\n * Get the XID of this participant.\n *\n * Port of `DkgProposedParticipant::xid()` from proposed_participant.rs line 28.\n */\n xid(): XID {\n return this._document.xid();\n }\n\n /**\n * Get the XID document of this participant.\n *\n * Port of `DkgProposedParticipant::xid_document()` from proposed_participant.rs line 30.\n */\n xidDocument(): XIDDocument {\n return this._document;\n }\n\n /**\n * Get the UR string of the XID document.\n *\n * Port of `DkgProposedParticipant::xid_document_ur()` from proposed_participant.rs line 32.\n */\n xidDocumentUr(): string {\n return this._urString;\n }\n\n /**\n * Get the envelope containing the XID document.\n *\n * Port of `DkgProposedParticipant::xid_document_envelope()` from proposed_participant.rs line 34.\n */\n xidDocumentEnvelope(): Envelope {\n return this._envelope;\n }\n\n /**\n * Get the response ARID for this participant.\n *\n * Port of `DkgProposedParticipant::response_arid()` from proposed_participant.rs line 36.\n */\n responseArid(): ARID {\n return this._responseArid;\n }\n\n /**\n * Compare participants by XID for sorting.\n *\n * Mirrors Rust `PartialOrd::partial_cmp` which uses\n * `self.xid().cmp(&other.xid())` — i.e. the underlying 32-byte XID\n * data is compared lexicographically (`Vec<u8>` ordering). The\n * earlier port used `xid.toString().localeCompare(...)`, which (a)\n * compares the UR-encoded base32-ish string, not the bytes, and (b)\n * is locale-aware. Sorting on UR strings differs from the byte\n * order whenever the underlying bytes contain values ≥ 0x80, so\n * Rust and TS would assign different FROST identifiers to the same\n * participant set — producing different secret shares.\n */\n compareTo(other: DkgProposedParticipant): number {\n return compareXidBytes(this.xid().toData(), other.xid().toData());\n }\n}\n\n/**\n * Lexicographic byte compare matching Rust's `Vec<u8>::cmp` /\n * `XID::cmp`. Exported so the cmd-tree call sites (round1 / finalize)\n * can use the same comparator when they sort deduplicated XID lists.\n *\n * `XID` is exactly 32 bytes so this only ever compares two equal-length\n * inputs; the length-tiebreak branch mirrors the generic `Ord` impl on\n * `Vec<u8>` and is included for correctness if ever applied to other\n * byte sequences.\n *\n * @internal\n */\nexport function compareXidBytes(a: Uint8Array, b: Uint8Array): number {\n const minLen = Math.min(a.length, b.length);\n for (let i = 0; i < minLen; i++) {\n if (a[i] !== b[i]) return a[i] < b[i] ? -1 : 1;\n }\n if (a.length !== b.length) return a.length < b.length ? -1 : 1;\n return 0;\n}\n\n/**\n * Parse a XID envelope from a UR string.\n *\n * Port of `parse_xid_envelope()` from proposed_participant.rs lines 39-60.\n */\nfunction parseXidEnvelope(input: string): [Envelope, XIDDocument] {\n const trimmed = input.trim();\n if (trimmed.length === 0) {\n throw new Error(\"XID document is required\");\n }\n\n const ur = UR.fromURString(trimmed);\n const urType = ur.urTypeStr();\n if (urType !== \"xid\" && urType !== \"envelope\") {\n throw new Error(`Expected a ur:xid document, found ur:${urType}`);\n }\n\n const envelopeCbor = ur.cbor();\n // Try tagged CBOR first, then untagged\n let envelope: Envelope;\n try {\n envelope = Envelope.fromTaggedCbor(envelopeCbor);\n } catch {\n envelope = Envelope.fromUntaggedCbor(envelopeCbor);\n }\n\n const document = XIDDocument.fromEnvelope(envelope, undefined, XIDVerifySignature.Inception);\n\n return [envelope, document];\n}\n"],"mappings":";;;;;;;;;AAsBA,IAAa,yBAAb,MAAa,uBAAuB;CAClC;CACA;CACA;CACA;CAEA,YACE,UACA,UACA,UACA,cACA;EACA,KAAK,YAAY;EACjB,KAAK,YAAY;EACjB,KAAK,YAAY;EACjB,KAAK,gBAAgB;CACvB;;;;;;CAOA,OAAO,OAAO,UAAkB,cAA4C;EAC1E,MAAM,CAAC,UAAU,YAAY,iBAAiB,QAAQ;EACtD,OAAO,IAAI,uBAAuB,UAAU,UAAU,UAAU,YAAY;CAC9E;;;;;;CAOA,MAAW;EACT,OAAO,KAAK,UAAU,IAAI;CAC5B;;;;;;CAOA,cAA2B;EACzB,OAAO,KAAK;CACd;;;;;;CAOA,gBAAwB;EACtB,OAAO,KAAK;CACd;;;;;;CAOA,sBAAgC;EAC9B,OAAO,KAAK;CACd;;;;;;CAOA,eAAqB;EACnB,OAAO,KAAK;CACd;;;;;;;;;;;;;;CAeA,UAAU,OAAuC;EAC/C,OAAO,gBAAgB,KAAK,IAAI,CAAC,CAAC,OAAO,GAAG,MAAM,IAAI,CAAC,CAAC,OAAO,CAAC;CAClE;AACF;;;;;;;;;;;;;AAcA,SAAgB,gBAAgB,GAAe,GAAuB;CACpE,MAAM,SAAS,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM;CAC1C,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,KAC1B,IAAI,EAAE,OAAO,EAAE,IAAI,OAAO,EAAE,KAAK,EAAE,KAAK,KAAK;CAE/C,IAAI,EAAE,WAAW,EAAE,QAAQ,OAAO,EAAE,SAAS,EAAE,SAAS,KAAK;CAC7D,OAAO;AACT;;;;;;AAOA,SAAS,iBAAiB,OAAwC;CAChE,MAAM,UAAU,MAAM,KAAK;CAC3B,IAAI,QAAQ,WAAW,GACrB,MAAM,IAAI,MAAM,0BAA0B;CAG5C,MAAM,KAAKA,wBAAAA,GAAG,aAAa,OAAO;CAClC,MAAM,SAAS,GAAG,UAAU;CAC5B,IAAI,WAAW,SAAS,WAAW,YACjC,MAAM,IAAI,MAAM,wCAAwC,QAAQ;CAGlE,MAAM,eAAe,GAAG,KAAK;CAE7B,IAAI;CACJ,IAAI;EACF,WAAWC,eAAAA,SAAS,eAAe,YAAY;CACjD,QAAQ;EACN,WAAWA,eAAAA,SAAS,iBAAiB,YAAY;CACnD;CAEA,MAAM,WAAWC,UAAAA,YAAY,aAAa,UAAU,KAAA,GAAWC,UAAAA,mBAAmB,SAAS;CAE3F,OAAO,CAAC,UAAU,QAAQ;AAC5B"}