chainlesschain 0.161.12 → 0.162.1

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 (145) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/.build-hash +1 -1
  3. package/src/assets/web-panel/assets/{AIOps-B1dwBvzW.js → AIOps-5A54O3wF.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-DfR4oLvh.js → ActionButton-epuY2GkZ.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-D3ZYGXjr.js → Analytics-CIdxw7T5.js} +1 -1
  6. package/src/assets/web-panel/assets/{AppLayout-CsmOoh-7.js → AppLayout-xR6YUHsS.js} +2 -2
  7. package/src/assets/web-panel/assets/{Audit-B4gwDm63.js → Audit-D95nRcdZ.js} +1 -1
  8. package/src/assets/web-panel/assets/{Backup-T42uSArV.js → Backup-Cmw7ZTJD.js} +1 -1
  9. package/src/assets/web-panel/assets/{BaseInput-CFi52nMs.js → BaseInput-DgCEAL_E.js} +1 -1
  10. package/src/assets/web-panel/assets/{Chat-D7Vvok1V.js → Chat-DAQAzZsA.js} +1 -1
  11. package/src/assets/web-panel/assets/{Checkbox-Dwaflpww.js → Checkbox-GRxUANnE.js} +1 -1
  12. package/src/assets/web-panel/assets/{Codegen-BIqx3G0b.js → Codegen--6KIDt1W.js} +1 -1
  13. package/src/assets/web-panel/assets/{Col-DzIUYUNu.js → Col-3s6dxuMx.js} +1 -1
  14. package/src/assets/web-panel/assets/{Community-DKePtzhk.js → Community-D60pkEBz.js} +1 -1
  15. package/src/assets/web-panel/assets/{Compact-CirVV9Wq.js → Compact-CQR4QsWP.js} +1 -1
  16. package/src/assets/web-panel/assets/{Compliance-CrXOr0sy.js → Compliance-KySNEhMK.js} +1 -1
  17. package/src/assets/web-panel/assets/{Cowork-BEBP6Tht.js → Cowork-Yrrf_Vuu.js} +1 -1
  18. package/src/assets/web-panel/assets/{Cron-k7nNUuqh.js → Cron-DSuuSKIQ.js} +1 -1
  19. package/src/assets/web-panel/assets/{Crosschain-CBnX0Dhq.js → Crosschain-Dub0G9i4.js} +1 -1
  20. package/src/assets/web-panel/assets/{DID-B48FszWS.js → DID-CbpCGV51.js} +1 -1
  21. package/src/assets/web-panel/assets/{Dashboard-Pb3qfFpp.js → Dashboard-D29e0y01.js} +2 -2
  22. package/src/assets/web-panel/assets/{Dropdown-pUHy4CQ2.js → Dropdown-DZY7X5v2.js} +1 -1
  23. package/src/assets/web-panel/assets/{Federation-CT0Qs-kR.js → Federation-dmrLzzMB.js} +1 -1
  24. package/src/assets/web-panel/assets/{FormItemContext-CbJJp5BR.js → FormItemContext-EopsCGez.js} +1 -1
  25. package/src/assets/web-panel/assets/{Git-B3mGNLQe.js → Git-D3mb4RhK.js} +1 -1
  26. package/src/assets/web-panel/assets/{Governance-BKf4733q.js → Governance-8v034-Nr.js} +1 -1
  27. package/src/assets/web-panel/assets/{Inference-DZjU541G.js → Inference-Ddl-HQwQ.js} +1 -1
  28. package/src/assets/web-panel/assets/{KnowledgeGraph-C8L-7Dd1.js → KnowledgeGraph-DrRruyud.js} +1 -1
  29. package/src/assets/web-panel/assets/{Logs-CwDwOiKv.js → Logs-Bsu6lYQe.js} +1 -1
  30. package/src/assets/web-panel/assets/{Marketplace-C2YWWU0M.js → Marketplace-Iyf2Xc23.js} +1 -1
  31. package/src/assets/web-panel/assets/{McpTools-dIbkOypF.js → McpTools-ljVE1lIN.js} +1 -1
  32. package/src/assets/web-panel/assets/{Memory-7eF8WzcY.js → Memory-Ca48TtDU.js} +1 -1
  33. package/src/assets/web-panel/assets/{MobileBridge-C74GHLbX.js → MobileBridge-DZ3Ar6da.js} +1 -1
  34. package/src/assets/web-panel/assets/{Mtc-CSEDo5Fo.js → Mtc-CRjBnVAT.js} +1 -1
  35. package/src/assets/web-panel/assets/{MtcAudit-DiJXxOrB.js → MtcAudit-CEC2eKez.js} +1 -1
  36. package/src/assets/web-panel/assets/Multisig-BHoQvNeL.js +7 -0
  37. package/src/assets/web-panel/assets/Multisig-kwPDnXnl.css +1 -0
  38. package/src/assets/web-panel/assets/{NLProgramming-DjF-gIUw.js → NLProgramming-9e5hIFvL.js} +1 -1
  39. package/src/assets/web-panel/assets/{Notes-BUE5CvMO.js → Notes-BEhZRadw.js} +1 -1
  40. package/src/assets/web-panel/assets/{NotificationSettings-Dfbrobje.js → NotificationSettings-CzPbT9UE.js} +1 -1
  41. package/src/assets/web-panel/assets/{Organization-C6YvqjQB.js → Organization-CvFg4VAr.js} +1 -1
  42. package/src/assets/web-panel/assets/{Overflow-BvHNhdMR.js → Overflow-Cm7ISeJl.js} +1 -1
  43. package/src/assets/web-panel/assets/{P2P-BO0hQHFS.js → P2P-BWN-wdfH.js} +1 -1
  44. package/src/assets/web-panel/assets/{Permissions-CCPlrJeP.js → Permissions-C4vKkP_t.js} +1 -1
  45. package/src/assets/web-panel/assets/{Pipeline-DTCL3FjJ.js → Pipeline-DQCShDeT.js} +1 -1
  46. package/src/assets/web-panel/assets/{Privacy-08DYgOe_.js → Privacy-Nc7LlSr3.js} +1 -1
  47. package/src/assets/web-panel/assets/{ProjectInit-B7j-Z8sa.js → ProjectInit-DDkqXAED.js} +1 -1
  48. package/src/assets/web-panel/assets/{ProjectSettings-CFqLhV1w.js → ProjectSettings-ia6GQr6A.js} +1 -1
  49. package/src/assets/web-panel/assets/{Projects-BPlpx2UN.js → Projects-CNqXa5XY.js} +1 -1
  50. package/src/assets/web-panel/assets/{Providers-BCBPbVbF.js → Providers-EwarbUb8.js} +1 -1
  51. package/src/assets/web-panel/assets/{QuickAsk-C8Job6zl.js → QuickAsk-BAHQBw0d.js} +1 -1
  52. package/src/assets/web-panel/assets/{Recommend-DOV_Aje-.js → Recommend-Ccgu6elV.js} +1 -1
  53. package/src/assets/web-panel/assets/{Reputation-DOgK_dIK.js → Reputation-ai0gRNpj.js} +1 -1
  54. package/src/assets/web-panel/assets/{Row-8jdU1xYg.js → Row-BWLfAhHC.js} +1 -1
  55. package/src/assets/web-panel/assets/{RssFeed-B289OgNZ.js → RssFeed-CnuRtiQH.js} +1 -1
  56. package/src/assets/web-panel/assets/{Search-cr0AndFE.js → Search-Da0CvI_2.js} +1 -1
  57. package/src/assets/web-panel/assets/{Security-w4diykaE.js → Security-DEFeOeUv.js} +1 -1
  58. package/src/assets/web-panel/assets/{Services-dTxAI5cG.js → Services-CsfvCqCH.js} +1 -1
  59. package/src/assets/web-panel/assets/{Skeleton-B3FiUiRo.js → Skeleton-DlRaGj_n.js} +1 -1
  60. package/src/assets/web-panel/assets/{Skills-DgtBTAFC.js → Skills-fjlZrsYq.js} +1 -1
  61. package/src/assets/web-panel/assets/{Sla-B4Y6bvbL.js → Sla-DNSDuEt2.js} +1 -1
  62. package/src/assets/web-panel/assets/{SpeechSettings-C8FEvArc.js → SpeechSettings-Bj0t-JCf.js} +1 -1
  63. package/src/assets/web-panel/assets/{SyncSettings-CHvV5L0m.js → SyncSettings-uO7Gy-BB.js} +1 -1
  64. package/src/assets/web-panel/assets/{Tasks-B4Py5ORS.js → Tasks-BSjsO-m8.js} +1 -1
  65. package/src/assets/web-panel/assets/{Templates-MeTyXM5u.js → Templates-B03SSuXn.js} +1 -1
  66. package/src/assets/web-panel/assets/{Tenant-Doiz7wyQ.js → Tenant-CTCPIBzq.js} +1 -1
  67. package/src/assets/web-panel/assets/{Terminal-DSEAdwWN.js → Terminal-CQZcdArx.js} +1 -1
  68. package/src/assets/web-panel/assets/{Tokens-BBrtaEKt.js → Tokens-CsNJIdNl.js} +1 -1
  69. package/src/assets/web-panel/assets/{Trigger-nPvjho27.js → Trigger-kYPQmm6P.js} +1 -1
  70. package/src/assets/web-panel/assets/{Trust-BFwPyS_6.js → Trust-mt-MiBeI.js} +1 -1
  71. package/src/assets/web-panel/assets/{UkeySign-DFsHoY1J.js → UkeySign-DBi8jgXw.js} +1 -1
  72. package/src/assets/web-panel/assets/{VideoEditing-FkSKqHE9.js → VideoEditing-CINSMEf5.js} +1 -1
  73. package/src/assets/web-panel/assets/{Wallet-AXo-_4-w.js → Wallet-DCVMgW0U.js} +1 -1
  74. package/src/assets/web-panel/assets/{WebAuthn-DoScnQ-4.js → WebAuthn-C9OjbTBs.js} +1 -1
  75. package/src/assets/web-panel/assets/{WorkflowEditor-IEMfIax-.js → WorkflowEditor-LM1HJs-S.js} +1 -1
  76. package/src/assets/web-panel/assets/{chat-pc1ciH6T.js → chat-Dz68Ixdp.js} +1 -1
  77. package/src/assets/web-panel/assets/{colors-CjkIkB0e.js → colors-qf63Eax9.js} +1 -1
  78. package/src/assets/web-panel/assets/{compact-item-CQZnkP5p.js → compact-item-r4YWRFGQ.js} +1 -1
  79. package/src/assets/web-panel/assets/{createContext-B1McGnV-.js → createContext-C8Lwrn-C.js} +1 -1
  80. package/src/assets/web-panel/assets/{hasIn-CbkA6peP.js → hasIn-DsPi2kPP.js} +1 -1
  81. package/src/assets/web-panel/assets/{index-B8r6OBuk.js → index-1xqIvVM5.js} +1 -1
  82. package/src/assets/web-panel/assets/{index-Dn7SHV2e.js → index-5nOMJaLt.js} +1 -1
  83. package/src/assets/web-panel/assets/{index-ChCCGHwz.js → index-B0KxtBNy.js} +1 -1
  84. package/src/assets/web-panel/assets/index-B3blziag.js +1 -0
  85. package/src/assets/web-panel/assets/{index-CGke5qZp.js → index-B8gs4g1v.js} +1 -1
  86. package/src/assets/web-panel/assets/{index-DHpwwlmv.js → index-BFV6aAoX.js} +1 -1
  87. package/src/assets/web-panel/assets/{index-DWq64zmv.js → index-BKEl9Ahm.js} +1 -1
  88. package/src/assets/web-panel/assets/{index-NRWBOo4F.js → index-BfdIkZnT.js} +1 -1
  89. package/src/assets/web-panel/assets/{index-fqI1KnP_.js → index-BjPHuhxG.js} +1 -1
  90. package/src/assets/web-panel/assets/{index-DHtiecyM.js → index-BtCSUUKm.js} +1 -1
  91. package/src/assets/web-panel/assets/{index-DjxVsyn_.js → index-BxNXO95B.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-DGb36exe.js → index-Bz1O2KhE.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-DcSe5y5O.js → index-BzzFMBIM.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-uWvLy_3T.js → index-C2OFaKmx.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-BTyhXFDW.js → index-C3VVwJcn.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-C052wi94.js → index-C8SY0_S8.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-wwQ_ZkWN.js → index-CCCX2ZSH.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-DPzT5L14.js → index-CEbbycgJ.js} +3 -3
  99. package/src/assets/web-panel/assets/{index-CzZ3LxPK.js → index-CINVudo7.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-CKwkP66s.js → index-CKRXnUTD.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-D4rhVRSV.js → index-CSCb-EY9.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-DMjPzhsp.js → index-CY5X4uXO.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-5c4JzwY3.js → index-CqmyLTa_.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CEENN81t.js → index-Cw48kkkH.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-C0Lj7Yl0.js → index-D0mFFS7Y.js} +1 -1
  106. package/src/assets/web-panel/assets/index-D1XYuPHf.js +1 -0
  107. package/src/assets/web-panel/assets/{index-CKledOCh.js → index-D2BR3WQ-.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-DsChgzu2.js → index-D4XgKgOF.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-C5mpCgak.js → index-DBpVVgRI.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-Bs-romIz.js → index-DGXVjiyF.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-BNLeseG1.js → index-DQSweK5-.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-CJr12ypE.js → index-DXBc_lyR.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-CFCQl1hk.js → index-DycrmZ_r.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-Di5tuS0d.js → index-I55BAmVG.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-CJbqE5Sw.js → index-LQYz2tRO.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-DYAWIXFt.js → index-cTFVNgoS.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-Dzfj71tf.js → index-qLyVEtRM.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-DJWYN-AT.js → index-qcVx0s-M.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-DjM0jsm1.js → index-wVpfPJXE.js} +1 -1
  120. package/src/assets/web-panel/assets/{initDefaultProps-BTloFqyf.js → initDefaultProps-CAgx2aHm.js} +1 -1
  121. package/src/assets/web-panel/assets/{motion-44iMBc1o.js → motion-DFuREFOd.js} +1 -1
  122. package/src/assets/web-panel/assets/{move-CyWQI5eW.js → move-DfcQIXuy.js} +1 -1
  123. package/src/assets/web-panel/assets/{omit-CXfJtuFy.js → omit-BFZV2hmZ.js} +1 -1
  124. package/src/assets/web-panel/assets/{pickAttrs-ANFpSZes.js → pickAttrs-D98WQSur.js} +1 -1
  125. package/src/assets/web-panel/assets/{placementArrow-CigX-url.js → placementArrow-BlP2AN9q.js} +1 -1
  126. package/src/assets/web-panel/assets/{responsiveObserve-Ch48RA0m.js → responsiveObserve-DuI2xGQd.js} +1 -1
  127. package/src/assets/web-panel/assets/{slide-BEz3LORF.js → slide-DSvqah_S.js} +1 -1
  128. package/src/assets/web-panel/assets/{statusUtils-D9EniG8V.js → statusUtils-B-96ZLWF.js} +1 -1
  129. package/src/assets/web-panel/assets/{styleChecker-C1IvuY3L.js → styleChecker-Br0YrCOO.js} +1 -1
  130. package/src/assets/web-panel/assets/{useFlexGapSupport-C92oHeXB.js → useFlexGapSupport-BD4Xr9XU.js} +1 -1
  131. package/src/assets/web-panel/assets/{useFs-CJhvFpgB.js → useFs-Ch5L3BnA.js} +1 -1
  132. package/src/assets/web-panel/assets/{vnode-BPkyunN_.js → vnode-BQi3uWRC.js} +1 -1
  133. package/src/assets/web-panel/assets/{zoom-B6Ipb64r.js → zoom-DaW-jbu7.js} +1 -1
  134. package/src/assets/web-panel/index.html +1 -1
  135. package/src/commands/crosschain.js +403 -1
  136. package/src/commands/pair.js +291 -0
  137. package/src/index.js +2 -0
  138. package/src/lib/cross-chain-mtc.js +275 -6
  139. package/src/lib/cross-chain.js +48 -2
  140. package/src/lib/lan-pairing-preflight.js +425 -0
  141. package/src/lib/lan-pairing-tokens.js +264 -0
  142. package/src/assets/web-panel/assets/Multisig-D-IuEDLa.css +0 -1
  143. package/src/assets/web-panel/assets/Multisig-FZTU5ri6.js +0 -1
  144. package/src/assets/web-panel/assets/index-BXfePRef.js +0 -1
  145. package/src/assets/web-panel/assets/index-Dc4fj_Ys.js +0 -1
@@ -0,0 +1,264 @@
1
+ /**
2
+ * #21 A.1 PR2 — Pairing token issuer + persistent store.
3
+ *
4
+ * Pre-generates pairing tokens compatible with the existing Electron
5
+ * `device-pairing-handler.js` QR data format. Use case: SSH-only Linux
6
+ * dev box / CI runner where the user wants to:
7
+ *
8
+ * 1. SSH into the box and run `cc pair token generate --did did:cc:foo`
9
+ * 2. Copy/paste the 6-digit code or scan ASCII QR
10
+ * 3. Use it on mobile / Electron client to complete pairing
11
+ *
12
+ * PR2 ships only token issuance + management. The actual signaling
13
+ * server that listens for mobile→PC confirmation stays in Electron's
14
+ * path (or future PR3 for a headless signaling server).
15
+ *
16
+ * Storage: `~/.chainlesschain/pairing-tokens.json` — simple JSON list of
17
+ * `{ code, did, expiresAtMs, createdAtMs, deviceInfo, status }`.
18
+ * Status: "pending" / "consumed" / "revoked" / "expired".
19
+ *
20
+ * Compatibility: token QR shape matches what `device-pairing-handler.js`
21
+ * `handleQRCodeScan()` expects:
22
+ * { type: "device-pairing", code: "######",
23
+ * did: "did:cc:...", deviceInfo: { ... }, timestamp: <ms> }
24
+ *
25
+ * Spike doc: docs/design/A1_Linux_Native_Pairing_spike.md §2 PR2
26
+ *
27
+ * @module lib/lan-pairing-tokens
28
+ * @version 0.1.0 (#21 A.1 PR2)
29
+ */
30
+
31
+ import fs from "node:fs";
32
+ import path from "node:path";
33
+ import os from "node:os";
34
+ import crypto from "node:crypto";
35
+ import { getHomeDir } from "./paths.js";
36
+
37
+ /** Token lifetime — mirrors device-pairing-handler.js pairingTimeout (5 min). */
38
+ const DEFAULT_TTL_MS = 5 * 60 * 1000;
39
+
40
+ /** Token QR type — must match device-pairing-handler.js validation. */
41
+ const QR_TYPE = "device-pairing";
42
+
43
+ const STATUS = Object.freeze({
44
+ PENDING: "pending",
45
+ CONSUMED: "consumed",
46
+ REVOKED: "revoked",
47
+ EXPIRED: "expired",
48
+ });
49
+
50
+ /**
51
+ * Path to the token store file. Caller may override for tests.
52
+ */
53
+ export function defaultTokenStorePath() {
54
+ return path.join(getHomeDir(), "pairing-tokens.json");
55
+ }
56
+
57
+ /**
58
+ * Generate a 6-digit pairing code. Uses crypto.randomInt for unbiased
59
+ * uniform distribution (Math.random would be acceptable too but crypto
60
+ * is cheap on this size).
61
+ */
62
+ export function generatePairingCode() {
63
+ // 100000 inclusive, 1000000 exclusive → always 6 digits no leading zero loss.
64
+ return String(crypto.randomInt(100000, 1000000));
65
+ }
66
+
67
+ /**
68
+ * Build a token's QR data payload that matches the Electron handler's
69
+ * expected shape (handleQRCodeScan in device-pairing-handler.js).
70
+ *
71
+ * @param {{ did: string, deviceInfo?: object }} input
72
+ * @returns {{ code, qrData, expiresAtMs, createdAtMs, status }}
73
+ */
74
+ export function buildToken({ did, deviceInfo } = {}) {
75
+ if (typeof did !== "string" || !did) {
76
+ const e = new Error("buildToken: did required");
77
+ e.code = "INVALID_ARGS";
78
+ throw e;
79
+ }
80
+ const now = Date.now();
81
+ const code = generatePairingCode();
82
+ const qrData = {
83
+ type: QR_TYPE,
84
+ code,
85
+ did,
86
+ deviceInfo: deviceInfo || {
87
+ deviceId: `cli-${os.hostname() || "unknown"}-${now}`,
88
+ name: os.hostname() || "ChainlessChain CLI",
89
+ platform: os.platform(),
90
+ version: process.env.npm_package_version || "0.1.0",
91
+ },
92
+ timestamp: now,
93
+ };
94
+ return {
95
+ code,
96
+ qrData,
97
+ expiresAtMs: now + DEFAULT_TTL_MS,
98
+ createdAtMs: now,
99
+ status: STATUS.PENDING,
100
+ };
101
+ }
102
+
103
+ /**
104
+ * Read the token store. Returns `{ schema, tokens: [...] }`. Creates
105
+ * an empty store if file doesn't exist. Tolerates malformed JSON by
106
+ * returning an empty store + caller can choose to log.
107
+ *
108
+ * @param {string} [filePath]
109
+ * @returns {{ schema: string, tokens: Array }}
110
+ */
111
+ export function readTokens(filePath = defaultTokenStorePath()) {
112
+ if (!fs.existsSync(filePath)) {
113
+ return { schema: "cc-pairing-tokens/v1", tokens: [] };
114
+ }
115
+ try {
116
+ const raw = fs.readFileSync(filePath, "utf-8");
117
+ const parsed = JSON.parse(raw);
118
+ if (parsed && typeof parsed === "object" && Array.isArray(parsed.tokens)) {
119
+ return {
120
+ schema: parsed.schema || "cc-pairing-tokens/v1",
121
+ tokens: parsed.tokens,
122
+ };
123
+ }
124
+ return { schema: "cc-pairing-tokens/v1", tokens: [] };
125
+ } catch (_err) {
126
+ // Malformed → return empty (don't crash CLI; user can `revoke --all`).
127
+ return { schema: "cc-pairing-tokens/v1", tokens: [] };
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Atomically write the token store. Creates parent dir if missing.
133
+ *
134
+ * @param {{ schema?: string, tokens: Array }} state
135
+ * @param {string} [filePath]
136
+ */
137
+ export function writeTokens(state, filePath = defaultTokenStorePath()) {
138
+ const dir = path.dirname(filePath);
139
+ if (!fs.existsSync(dir)) {
140
+ fs.mkdirSync(dir, { recursive: true });
141
+ }
142
+ const toWrite = {
143
+ schema: state.schema || "cc-pairing-tokens/v1",
144
+ tokens: state.tokens || [],
145
+ };
146
+ // Write to temp + rename for atomicity (avoid partial reads).
147
+ const tmp = filePath + ".tmp";
148
+ fs.writeFileSync(tmp, JSON.stringify(toWrite, null, 2), "utf-8");
149
+ fs.renameSync(tmp, filePath);
150
+ }
151
+
152
+ /**
153
+ * Append a new token to the store. Mark prior pending tokens for the
154
+ * same DID as REVOKED (one-active-token-per-DID invariant — prevents
155
+ * stale codes leaking into mobile scans).
156
+ *
157
+ * @param {{ did, deviceInfo? }} input
158
+ * @param {string} [filePath]
159
+ * @returns {object} the newly-stored token (with status PENDING)
160
+ */
161
+ export function addToken(input, filePath = defaultTokenStorePath()) {
162
+ const token = buildToken(input);
163
+ const state = readTokens(filePath);
164
+ // Invalidate prior pending tokens for the same DID.
165
+ state.tokens = state.tokens.map((t) => {
166
+ if (t.qrData?.did === input.did && t.status === STATUS.PENDING) {
167
+ return { ...t, status: STATUS.REVOKED, revokedAtMs: Date.now() };
168
+ }
169
+ return t;
170
+ });
171
+ state.tokens.push(token);
172
+ writeTokens(state, filePath);
173
+ return token;
174
+ }
175
+
176
+ /**
177
+ * Mark expired tokens. Returns the count touched. Caller can run this
178
+ * before `list` to keep status accurate.
179
+ */
180
+ export function sweepExpired(filePath = defaultTokenStorePath()) {
181
+ const state = readTokens(filePath);
182
+ const now = Date.now();
183
+ let touched = 0;
184
+ state.tokens = state.tokens.map((t) => {
185
+ if (t.status === STATUS.PENDING && t.expiresAtMs <= now) {
186
+ touched += 1;
187
+ return { ...t, status: STATUS.EXPIRED, expiredAtMs: now };
188
+ }
189
+ return t;
190
+ });
191
+ if (touched > 0) writeTokens(state, filePath);
192
+ return touched;
193
+ }
194
+
195
+ /**
196
+ * List tokens. Optional filter by status. Tokens returned newest-first.
197
+ */
198
+ export function listTokens(
199
+ { status, did } = {},
200
+ filePath = defaultTokenStorePath(),
201
+ ) {
202
+ sweepExpired(filePath);
203
+ const state = readTokens(filePath);
204
+ let tokens = state.tokens;
205
+ if (status) tokens = tokens.filter((t) => t.status === status);
206
+ if (did) tokens = tokens.filter((t) => t.qrData?.did === did);
207
+ return tokens
208
+ .slice()
209
+ .sort((a, b) => (b.createdAtMs || 0) - (a.createdAtMs || 0));
210
+ }
211
+
212
+ /**
213
+ * Look up a token by 6-digit code. Returns null when not found.
214
+ */
215
+ export function findToken(code, filePath = defaultTokenStorePath()) {
216
+ if (typeof code !== "string" || !code) return null;
217
+ sweepExpired(filePath);
218
+ const state = readTokens(filePath);
219
+ return state.tokens.find((t) => t.code === code) || null;
220
+ }
221
+
222
+ /**
223
+ * Revoke a token by code. Idempotent — returns `{revoked: false}` when
224
+ * not found or already non-pending.
225
+ */
226
+ export function revokeToken(code, filePath = defaultTokenStorePath()) {
227
+ const state = readTokens(filePath);
228
+ const i = state.tokens.findIndex((t) => t.code === code);
229
+ if (i < 0) return { revoked: false, reason: "not_found" };
230
+ const t = state.tokens[i];
231
+ if (t.status !== STATUS.PENDING) {
232
+ return { revoked: false, reason: `not_pending(${t.status})` };
233
+ }
234
+ state.tokens[i] = {
235
+ ...t,
236
+ status: STATUS.REVOKED,
237
+ revokedAtMs: Date.now(),
238
+ };
239
+ writeTokens(state, filePath);
240
+ return { revoked: true, token: state.tokens[i] };
241
+ }
242
+
243
+ /**
244
+ * Mark a token as consumed. Caller (e.g. signaling listener in PR3) calls
245
+ * this after the mobile successfully connects.
246
+ */
247
+ export function markConsumed(code, filePath = defaultTokenStorePath()) {
248
+ const state = readTokens(filePath);
249
+ const i = state.tokens.findIndex((t) => t.code === code);
250
+ if (i < 0) return { consumed: false, reason: "not_found" };
251
+ const t = state.tokens[i];
252
+ if (t.status !== STATUS.PENDING) {
253
+ return { consumed: false, reason: `not_pending(${t.status})` };
254
+ }
255
+ state.tokens[i] = {
256
+ ...t,
257
+ status: STATUS.CONSUMED,
258
+ consumedAtMs: Date.now(),
259
+ };
260
+ writeTokens(state, filePath);
261
+ return { consumed: true, token: state.tokens[i] };
262
+ }
263
+
264
+ export { STATUS, QR_TYPE, DEFAULT_TTL_MS };
@@ -1 +0,0 @@
1
- .page-title[data-v-14541f7e]{font-size:22px;font-weight:600;margin:0;color:var(--text-primary)}.page-sub[data-v-14541f7e]{font-size:13px;color:var(--text-secondary);margin:4px 0 0}.filter-bar[data-v-14541f7e]{display:flex;align-items:center;margin-bottom:16px}.multisig-row[data-v-14541f7e]{cursor:pointer}.multisig-row[data-v-14541f7e]:hover{background:var(--bg-hover, rgba(22, 119, 255, .05))}
@@ -1 +0,0 @@
1
- import{o as _e,M as O,R as y,c as a,N as t,K as i,r as k,L as p,O as s,u as b,P as r,Q as c,_ as ye,a1 as F,S as x,F as ve,Y as ge,f as Y}from"./vendor-M5lGV-wr.js";import{_ as be,u as ke,d as m}from"./index-DPzT5L14.js";import{u as xe}from"./useShellMode-CgR0wCYM.js";import{R as we,x as G,l as he,aE as Ce,f as X,d as ze,c as Me}from"./icons-NT6gy8Ee.js";import Se from"./index-CEENN81t.js";import"./KeyCode-D63Tfrq7.js";import"./omit-CXfJtuFy.js";import"./pickAttrs-ANFpSZes.js";import"./initDefaultProps-BTloFqyf.js";import"./motion-44iMBc1o.js";import"./raf-Deuc0E8-.js";import"./index-DcSe5y5O.js";import"./index-BTyhXFDW.js";import"./isVisible-C7tPsqfj.js";import"./useState-CSzR8F8O.js";import"./devWarning-CNIS3FrJ.js";import"./warning-Pq00owYb.js";import"./compact-item-CQZnkP5p.js";import"./createContext-B1McGnV-.js";import"./Compact-CirVV9Wq.js";import"./_getTag-BVc6NQ_K.js";import"./styleChecker-C1IvuY3L.js";import"./zoom-B6Ipb64r.js";import"./ActionButton-DfR4oLvh.js";import"./vnode-BPkyunN_.js";const $e={style:{display:"flex","align-items":"center","justify-content":"space-between","margin-bottom":"24px"}},De={class:"filter-bar"},Ae={key:0,style:{"font-size":"12px"}},Ie={style:{margin:"0 0 8px 0"}},Le={style:{"margin-left":"8px",color:"var(--text-secondary)"}},Oe={style:{"margin-top":"8px"}},je={style:{cursor:"pointer",color:"var(--text-secondary)"}},Fe={key:0},Ne={style:{margin:"0","max-height":"240px",overflow:"auto","font-size":"12px"}},Te={style:{margin:"16px 0 8px 0"}},Pe={style:{"font-size":"12px"}},Be={__name:"Multisig",setup(Ee){const N=ke(),{isEmbedded:Z}=xe();async function w(l,e,d,f=8e3){if(Z){const _=await N.sendRaw({type:l,...e},f);if(!_?.ok){const g=_?.error;throw new Error(typeof g=="string"?g:g?.message||`${l} failed`)}return _.result}return N.executeJson(d,f)}const D=k(!1),A=k([]),j=k([]),T=k("proposals"),I=k(""),L=k(""),h=k(!1),n=k(null),ee=[{title:"ID",key:"id",width:200},{title:"Domain",dataIndex:"domain",width:220},{title:"状态",key:"state",width:110},{title:"阈值",key:"sigs",width:80},{title:"创建",key:"createdAt",width:140},{title:"过期",key:"expiresAt",width:140},{title:"操作",key:"actions",width:240,fixed:"right"}],te=[{title:"DID",dataIndex:"did"},{title:"Alg",dataIndex:"alg",width:200}],$=Y(()=>{const l={pending:0,reached:0,consumed:0,cancelled:0,expired:0};for(const e of A.value)l[e.state]!==void 0&&(l[e.state]+=1);return l}),ae=Y(()=>A.value.filter(l=>!(I.value&&l.state!==I.value||L.value&&!l.domain.toLowerCase().includes(L.value.toLowerCase()))));function P(l){switch(l){case"pending":return"gold";case"reached":return"cyan";case"consumed":return"green";case"cancelled":return"default";case"expired":return"red";default:return"default"}}function B(l){const e=l-Date.now(),d=Math.abs(e)/6e4;if(d<60)return e>0?`${Math.round(d)} 分钟后`:`${Math.round(d)} 分钟前`;const f=d/60;if(f<24)return e>0?`${Math.round(f)} 小时后`:`${Math.round(f)} 小时前`;const _=f/24;return e>0?`${Math.round(_)} 天后`:`${Math.round(_)} 天前`}async function C(){D.value=!0;try{const[l,e]=await Promise.all([w("multisig.list",{limit:500},"multisig list --limit 500 --json",1e4).catch(()=>[]),Promise.all(["marketplace.purchase","did.rotate","crosschain.outbound"].map(async d=>{try{const f=await w("multisig.policy.show",{domain:d},`multisig policy show ${d} --json`,8e3);return{domain:d,policy:f,updatedAtMs:Date.now()}}catch{return null}})).then(d=>d.filter(Boolean))]);A.value=Array.isArray(l)?l:[],j.value=Array.isArray(e)?e:[]}catch(l){m.error("加载失败: "+(l.message||l))}finally{D.value=!1}}async function E(l){try{const e=await w("multisig.show",{proposalId:l.id},`multisig show ${l.id} --json`,8e3);n.value=e,h.value=!0}catch(e){m.error("加载详情失败: "+(e.message||e))}}function le(l){return{onClick:()=>E(l)}}async function R(l){Se.confirm({title:`取消提案 ${l.id.slice(0,12)}…?`,content:"已签名的成员需要重新发起新提案。此操作不可撤销。",okText:"取消提案",okType:"danger",cancelText:"保持",onOk:async()=>{try{const e=await w("multisig.cancel",{proposalId:l.id,reason:"web-shell"},`multisig cancel ${l.id} --reason web-shell --json`,8e3);e.ok?(m.success("提案已取消"),h.value=!1,await C()):m.error("取消失败: "+e.reason)}catch(e){m.error(e.message||String(e))}}})}async function K(l){try{const e=await w("marketplace.consume",{proposalId:l.id},`marketplace consume ${l.id} --json`,1e4);e.status==="consumed"?(m.success(`订单 ${e.order.itemId} 已执行 (¥${(e.order.amountFen/100).toFixed(2)})`),h.value=!1,await C()):m.error("执行失败: "+(e.reason||JSON.stringify(e)))}catch(e){m.error(e.message||String(e))}}async function oe(l){try{const e=await w("multisig.finalize",{proposalId:l.id},`multisig finalize ${l.id} --json`,8e3);e.ok?(m.success("提案已 finalize"),h.value=!1,await C()):m.error("Finalize 失败: "+e.reason)}catch(e){m.error(e.message||String(e))}}async function se(){try{const l=await w("multisig.sweep",{},"multisig sweep --json",8e3);l.expired===0?m.info("无过期提案"):(m.success(`已标记 ${l.expired} 条提案为过期`),await C())}catch(l){m.error(l.message||String(l))}}return _e(C),(l,e)=>{const d=i("a-button"),f=i("a-space"),_=i("a-statistic"),g=i("a-card"),z=i("a-col"),ne=i("a-row"),M=i("a-radio-button"),re=i("a-radio-group"),ie=i("a-input-search"),S=i("a-tag"),U=i("a-tooltip"),q=i("a-table"),J=i("a-tab-pane"),ue=i("a-empty"),v=i("a-descriptions-item"),V=i("a-descriptions"),Q=i("a-list-item"),W=i("a-list"),de=i("a-tabs"),pe=i("a-list-item-meta"),ce=i("a-divider"),me=i("a-alert"),fe=i("a-drawer");return p(),O("div",null,[y("div",$e,[e[9]||(e[9]=y("div",null,[y("h2",{class:"page-title"},"M-of-N 多签"),y("p",{class:"page-sub"},"marketplace.purchase 大额、DID 关键操作、跨链桥 outbound 的联合签名审批")],-1)),a(f,null,{default:t(()=>[a(d,{loading:D.value,onClick:C},{icon:t(()=>[a(b(we))]),default:t(()=>[e[7]||(e[7]=s(" 刷新 ",-1))]),_:1},8,["loading"]),a(d,{onClick:se},{icon:t(()=>[a(b(G))]),default:t(()=>[e[8]||(e[8]=s(" 扫过期 ",-1))]),_:1})]),_:1})]),a(ne,{gutter:[16,16],style:{"margin-bottom":"20px"}},{default:t(()=>[a(z,{xs:12,sm:8,lg:4},{default:t(()=>[a(g,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:t(()=>[a(_,{title:"总提案",value:A.value.length,"value-style":{color:"#1677ff",fontSize:"20px"}},{prefix:t(()=>[a(b(he))]),_:1},8,["value"])]),_:1})]),_:1}),a(z,{xs:12,sm:8,lg:4},{default:t(()=>[a(g,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:t(()=>[a(_,{title:"待签",value:$.value.pending,"value-style":{color:"#faad14",fontSize:"20px"}},{prefix:t(()=>[a(b(G))]),_:1},8,["value"])]),_:1})]),_:1}),a(z,{xs:12,sm:8,lg:4},{default:t(()=>[a(g,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:t(()=>[a(_,{title:"已达阈值",value:$.value.reached,"value-style":{color:"#13c2c2",fontSize:"20px"}},{prefix:t(()=>[a(b(Ce))]),_:1},8,["value"])]),_:1})]),_:1}),a(z,{xs:12,sm:8,lg:4},{default:t(()=>[a(g,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:t(()=>[a(_,{title:"已执行",value:$.value.consumed,"value-style":{color:"#52c41a",fontSize:"20px"}},{prefix:t(()=>[a(b(X))]),_:1},8,["value"])]),_:1})]),_:1}),a(z,{xs:12,sm:8,lg:4},{default:t(()=>[a(g,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:t(()=>[a(_,{title:"已取消",value:$.value.cancelled,"value-style":{color:"#8c8c8c",fontSize:"20px"}},{prefix:t(()=>[a(b(ze))]),_:1},8,["value"])]),_:1})]),_:1}),a(z,{xs:12,sm:8,lg:4},{default:t(()=>[a(g,{style:{background:"var(--bg-card)","border-color":"var(--border-color)"}},{default:t(()=>[a(_,{title:"已过期",value:$.value.expired,"value-style":{color:"#ff4d4f",fontSize:"20px"}},{prefix:t(()=>[a(b(Me))]),_:1},8,["value"])]),_:1})]),_:1})]),_:1}),a(de,{activeKey:T.value,"onUpdate:activeKey":e[2]||(e[2]=o=>T.value=o)},{default:t(()=>[a(J,{key:"proposals",tab:"提案列表"},{default:t(()=>[y("div",De,[a(re,{value:I.value,"onUpdate:value":e[0]||(e[0]=o=>I.value=o),size:"small","button-style":"solid"},{default:t(()=>[a(M,{value:""},{default:t(()=>[...e[10]||(e[10]=[s("全部",-1)])]),_:1}),a(M,{value:"pending"},{default:t(()=>[...e[11]||(e[11]=[s("待签",-1)])]),_:1}),a(M,{value:"reached"},{default:t(()=>[...e[12]||(e[12]=[s("已达阈值",-1)])]),_:1}),a(M,{value:"consumed"},{default:t(()=>[...e[13]||(e[13]=[s("已执行",-1)])]),_:1}),a(M,{value:"cancelled"},{default:t(()=>[...e[14]||(e[14]=[s("已取消",-1)])]),_:1}),a(M,{value:"expired"},{default:t(()=>[...e[15]||(e[15]=[s("已过期",-1)])]),_:1})]),_:1},8,["value"]),a(ie,{value:L.value,"onUpdate:value":e[1]||(e[1]=o=>L.value=o),placeholder:"按 domain 过滤 (marketplace.purchase 等)","allow-clear":"",style:{"max-width":"360px","margin-left":"12px"}},null,8,["value"])]),a(q,{columns:ee,"data-source":ae.value,loading:D.value,pagination:{pageSize:20,showSizeChanger:!0,pageSizeOptions:["10","20","50","100"]},"row-key":"id",size:"middle",onRowClick:le,"row-class-name":()=>"multisig-row"},{bodyCell:t(({column:o,record:u})=>[o.key==="id"?(p(),O("code",Ae,r(u.id.slice(0,16))+"…",1)):o.key==="state"?(p(),c(S,{key:1,color:P(u.state)},{default:t(()=>[s(r(u.state),1)]),_:2},1032,["color"])):o.key==="sigs"?(p(),c(S,{key:2,color:u.n===u.m?"cyan":"default"},{default:t(()=>[s(r(u.m)+"/"+r(u.n),1)]),_:2},1032,["color"])):o.key==="createdAt"?(p(),c(U,{key:3,title:new Date(u.createdAtMs).toLocaleString()},{default:t(()=>[s(r(B(u.createdAtMs)),1)]),_:2},1032,["title"])):o.key==="expiresAt"?(p(),c(U,{key:4,title:new Date(u.expiresAtMs).toLocaleString()},{default:t(()=>[y("span",{style:ye({color:u.expiresAtMs<Date.now()?"#ff4d4f":"inherit"})},r(B(u.expiresAtMs)),5)]),_:2},1032,["title"])):o.key==="actions"?(p(),c(f,{key:5,size:"small"},{default:t(()=>[a(d,{size:"small",onClick:F(H=>E(u),["stop"])},{default:t(()=>[...e[16]||(e[16]=[s("详情",-1)])]),_:1},8,["onClick"]),u.state==="pending"||u.state==="reached"?(p(),c(d,{key:0,size:"small",danger:"",onClick:F(H=>R(u),["stop"])},{default:t(()=>[...e[17]||(e[17]=[s("取消",-1)])]),_:1},8,["onClick"])):x("",!0),u.state==="reached"&&u.domain==="marketplace.purchase"?(p(),c(d,{key:1,size:"small",type:"primary",onClick:F(H=>K(u),["stop"])},{default:t(()=>[...e[18]||(e[18]=[s("执行购买",-1)])]),_:1},8,["onClick"])):x("",!0)]),_:2},1024)):x("",!0)]),_:1},8,["data-source","loading"])]),_:1}),a(J,{key:"policies",tab:"域策略"},{default:t(()=>[j.value.length===0?(p(),c(ue,{key:0,description:"暂无域策略 — 用 CLI 配置: cc multisig policy set <domain> --m <M> --members <json>"})):(p(),c(W,{key:1,"data-source":j.value,"item-layout":"vertical"},{renderItem:t(({item:o})=>[a(Q,null,{default:t(()=>[a(g,null,{default:t(()=>[y("h4",Ie,[a(S,{color:"purple"},{default:t(()=>[s(r(o.domain),1)]),_:2},1024),y("span",Le,[s(r(o.policy.m)+"-of-"+r(o.policy.members.length)+" ",1),o.policy.requirePqc?(p(),c(S,{key:0,color:"orange",style:{"margin-left":"8px"}},{default:t(()=>[...e[19]||(e[19]=[s("requirePQC",-1)])]),_:1})):x("",!0)])]),a(V,{size:"small",column:2},{default:t(()=>[a(v,{label:"阈值 M"},{default:t(()=>[s(r(o.policy.m),1)]),_:2},1024),a(v,{label:"成员数 N"},{default:t(()=>[s(r(o.policy.members.length),1)]),_:2},1024),a(v,{label:"算法"},{default:t(()=>[(p(!0),O(ve,null,ge(o.policy.algorithms||[],u=>(p(),c(S,{key:u,size:"small"},{default:t(()=>[s(r(u),1)]),_:2},1024))),128))]),_:2},1024),a(v,{label:"默认有效期"},{default:t(()=>[s(r(Math.round((o.policy.defaultExpiryMs||864e5)/1e3/60/60))+"h ",1)]),_:2},1024)]),_:2},1024),y("details",Oe,[y("summary",je,"展开成员列表 ("+r(o.policy.members.length)+")",1),a(q,{columns:te,"data-source":o.policy.members,pagination:!1,size:"small","row-key":"did",style:{"margin-top":"8px"}},null,8,["data-source"])])]),_:2},1024)]),_:2},1024)]),_:1},8,["data-source"]))]),_:1})]),_:1},8,["activeKey"]),a(fe,{open:h.value,"onUpdate:open":e[6]||(e[6]=o=>h.value=o),title:n.value?`提案 ${n.value.proposal.id}`:"提案详情",width:"640","destroy-on-close":""},{default:t(()=>[n.value?(p(),O("div",Fe,[a(V,{column:1,bordered:"",size:"small"},{default:t(()=>[a(v,{label:"Domain"},{default:t(()=>[s(r(n.value.proposal.domain),1)]),_:1}),a(v,{label:"状态"},{default:t(()=>[a(S,{color:P(n.value.proposal.state)},{default:t(()=>[s(r(n.value.proposal.state),1)]),_:1},8,["color"])]),_:1}),a(v,{label:"阈值"},{default:t(()=>[s(r(n.value.proposal.thresholdM)+"-of-"+r(n.value.proposal.memberSet.length),1)]),_:1}),a(v,{label:"已签 / 需签"},{default:t(()=>[s(r(n.value.signatures.length)+" / "+r(n.value.proposal.thresholdM),1)]),_:1}),a(v,{label:"发起方"},{default:t(()=>[s(r(n.value.proposal.initiatorDid),1)]),_:1}),a(v,{label:"创建时间"},{default:t(()=>[s(r(new Date(n.value.proposal.createdAtMs).toLocaleString()),1)]),_:1}),a(v,{label:"过期时间"},{default:t(()=>[s(r(new Date(n.value.proposal.expiresAtMs).toLocaleString()),1)]),_:1}),a(v,{label:"Payload"},{default:t(()=>[y("pre",Ne,r(n.value.proposal.payload?JSON.stringify(n.value.proposal.payload,null,2):n.value.proposal.payloadJcs),1)]),_:1})]),_:1}),y("h4",Te,"签名列表 ("+r(n.value.signatures.length)+")",1),a(W,{"data-source":n.value.signatures,size:"small"},{renderItem:t(({item:o})=>[a(Q,null,{default:t(()=>[a(pe,null,{title:t(()=>[a(b(X),{style:{color:"#52c41a","margin-right":"6px"}}),y("code",Pe,r(o.signerDid),1)]),description:t(()=>[s(r(o.alg)+" — "+r(new Date(o.signedAtMs).toLocaleString()),1)]),_:2},1024)]),_:2},1024)]),_:1},8,["data-source"]),a(ce),a(me,{message:"签名 / 执行操作需通过 CLI 提供私钥",description:"Web shell 不直接持有私钥(v1.3 接 Unified KeyStore)。本面板用于查看提案状态,操作请用:cc multisig sign / cancel,或 cc marketplace consume。",type:"info","show-icon":"",style:{"margin-bottom":"12px"}}),a(f,null,{default:t(()=>[n.value.proposal.state==="pending"||n.value.proposal.state==="reached"?(p(),c(d,{key:0,danger:"",onClick:e[3]||(e[3]=o=>R(n.value.proposal))},{default:t(()=>[...e[20]||(e[20]=[s("取消提案",-1)])]),_:1})):x("",!0),n.value.proposal.state==="reached"&&n.value.proposal.domain==="marketplace.purchase"?(p(),c(d,{key:1,type:"primary",onClick:e[4]||(e[4]=o=>K(n.value.proposal))},{default:t(()=>[...e[21]||(e[21]=[s("执行购买 (cc marketplace consume)",-1)])]),_:1})):x("",!0),n.value.proposal.state==="reached"&&n.value.proposal.domain!=="marketplace.purchase"?(p(),c(d,{key:2,type:"primary",onClick:e[5]||(e[5]=o=>oe(n.value.proposal))},{default:t(()=>[...e[22]||(e[22]=[s("finalize (cc multisig finalize)",-1)])]),_:1})):x("",!0)]),_:1})])):x("",!0)]),_:1},8,["open","title"])])}}},ct=be(Be,[["__scopeId","data-v-14541f7e"]]);export{ct as default};
@@ -1 +0,0 @@
1
- import{C as o}from"./Col-DzIUYUNu.js";import{S as t}from"./index-DPzT5L14.js";import"./index-D4rhVRSV.js";import"./vendor-M5lGV-wr.js";import"./icons-NT6gy8Ee.js";const s=t(o);export{s as default};
@@ -1 +0,0 @@
1
- import{A as o}from"./Row-8jdU1xYg.js";import{S as t}from"./index-DPzT5L14.js";import"./responsiveObserve-Ch48RA0m.js";import"./vendor-M5lGV-wr.js";import"./useFlexGapSupport-C92oHeXB.js";import"./styleChecker-C1IvuY3L.js";import"./index-D4rhVRSV.js";import"./icons-NT6gy8Ee.js";const l=t(o);export{l as default};