chainlesschain 0.161.7 → 0.161.9

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 (149) hide show
  1. package/bin/chainlesschain.js +0 -0
  2. package/package.json +2 -1
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AIOps-C06IYJkC.js → AIOps-Cbnj25uU.js} +1 -1
  5. package/src/assets/web-panel/assets/{ActionButton-Cq4f1js5.js → ActionButton-DY69UkxV.js} +1 -1
  6. package/src/assets/web-panel/assets/{Analytics-DyJsowHu.js → Analytics-DUzoL75H.js} +2 -2
  7. package/src/assets/web-panel/assets/AppLayout-DATUppSv.js +1 -0
  8. package/src/assets/web-panel/assets/{AppLayout-P7jhSfLy.css → AppLayout-qr7ghxW7.css} +1 -1
  9. package/src/assets/web-panel/assets/{Audit-C7y4wGzh.js → Audit-CFJh6huz.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-BxkJJwr5.js → Backup-CMTir4tV.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-BraWNP3N.js → BaseInput-BaWXBDdp.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-BhZPLetb.js → Chat-DjToexEx.js} +3 -3
  13. package/src/assets/web-panel/assets/{Checkbox-DuDAToKQ.js → Checkbox-DJnhKXhi.js} +1 -1
  14. package/src/assets/web-panel/assets/{Codegen-DWHT3ZCT.js → Codegen-CgsgvRJX.js} +1 -1
  15. package/src/assets/web-panel/assets/{Col-rZ1FbPeP.js → Col-MvMGDJAB.js} +1 -1
  16. package/src/assets/web-panel/assets/{Community-BHefT_qI.js → Community-q26VGOGu.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compact-D68vLPVh.js → Compact-DyLYzWoX.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compliance-cxmKFzWJ.js → Compliance-D_TF9eBc.js} +1 -1
  19. package/src/assets/web-panel/assets/{Cowork-Dzt1uT50.js → Cowork-B9bg988c.js} +3 -3
  20. package/src/assets/web-panel/assets/{Cron-oWxj9K9p.js → Cron-6k9vTFfd.js} +2 -2
  21. package/src/assets/web-panel/assets/{Crosschain-C9UdRkm2.js → Crosschain-B7fk2aHi.js} +1 -1
  22. package/src/assets/web-panel/assets/{DID-D5WEHKMO.js → DID-XhCfTFm2.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dashboard-dP1_OGh-.js → Dashboard-Bqk7vtZM.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dropdown-C55GjQPR.js → Dropdown-CDOOZGv7.js} +1 -1
  25. package/src/assets/web-panel/assets/{Federation-oJxrz7TD.js → Federation-NajN4oRO.js} +1 -1
  26. package/src/assets/web-panel/assets/{FormItemContext-CeLP5Pvz.js → FormItemContext-DgMHYlMB.js} +1 -1
  27. package/src/assets/web-panel/assets/{Git-CWs6CrRt.js → Git-CZC5n1Zu.js} +2 -2
  28. package/src/assets/web-panel/assets/{Governance-wo9Gz6OK.js → Governance-Br131eUW.js} +1 -1
  29. package/src/assets/web-panel/assets/{Inference-75Ob1OAF.js → Inference-BHlUfcT-.js} +1 -1
  30. package/src/assets/web-panel/assets/{KnowledgeGraph-DNw3Xz30.js → KnowledgeGraph-CByROhg-.js} +1 -1
  31. package/src/assets/web-panel/assets/{Logs-Bo7_f07I.js → Logs-D8Ghzk4B.js} +1 -1
  32. package/src/assets/web-panel/assets/{Marketplace-Dm0yQkoQ.js → Marketplace-CnjHPFm7.js} +1 -1
  33. package/src/assets/web-panel/assets/{McpTools-oh6SZgBB.js → McpTools-C_vszCBU.js} +1 -1
  34. package/src/assets/web-panel/assets/{Memory-DANDCrzX.js → Memory-Cl5c_8In.js} +2 -2
  35. package/src/assets/web-panel/assets/MobileBridge-DkkMCDx9.css +1 -0
  36. package/src/assets/web-panel/assets/MobileBridge-K3KwwCKl.js +3 -0
  37. package/src/assets/web-panel/assets/{Mtc-4D52E6FP.js → Mtc-NfZ8xzyu.js} +4 -4
  38. package/src/assets/web-panel/assets/{MtcAudit-BmlorrLr.js → MtcAudit-BkktYSXj.js} +1 -1
  39. package/src/assets/web-panel/assets/Multisig-BLRYDn7_.css +1 -0
  40. package/src/assets/web-panel/assets/Multisig-qP51bs1T.js +1 -0
  41. package/src/assets/web-panel/assets/{NLProgramming-DolGSSOm.js → NLProgramming-BhFRuXyi.js} +1 -1
  42. package/src/assets/web-panel/assets/{Notes-BTyTq1Qk.js → Notes-BpcAFy8i.js} +3 -3
  43. package/src/assets/web-panel/assets/{NotificationSettings-Db1AaWp_.js → NotificationSettings-DKNtYYeo.js} +1 -1
  44. package/src/assets/web-panel/assets/{Organization-DC4RfB2j.js → Organization-C61VwQEW.js} +4 -4
  45. package/src/assets/web-panel/assets/{Overflow-cYKtW74T.js → Overflow-WBloac1x.js} +1 -1
  46. package/src/assets/web-panel/assets/{P2P-CY5dBoF-.js → P2P-DGm7EvDg.js} +2 -2
  47. package/src/assets/web-panel/assets/{Permissions-B-U6t8Wf.js → Permissions-KFPtoOV6.js} +2 -2
  48. package/src/assets/web-panel/assets/{Pipeline-a2pkdq6t.js → Pipeline-CFjFtzZT.js} +1 -1
  49. package/src/assets/web-panel/assets/{Privacy-ClgLdkPP.js → Privacy-T_Kewe_f.js} +1 -1
  50. package/src/assets/web-panel/assets/{ProjectSettings-D4Fi9bEQ.js → ProjectSettings-BQl8qTPQ.js} +1 -1
  51. package/src/assets/web-panel/assets/{Projects-BiSWtWMm.js → Projects-xGNn4Ov9.js} +2 -2
  52. package/src/assets/web-panel/assets/{Providers-ydpAao66.js → Providers-ByuUztXe.js} +1 -1
  53. package/src/assets/web-panel/assets/{QuickAsk-Bg955QRg.js → QuickAsk-BwSXmXvL.js} +1 -1
  54. package/src/assets/web-panel/assets/{Recommend-BqynHnTn.js → Recommend-Cp433_5Z.js} +1 -1
  55. package/src/assets/web-panel/assets/{Reputation-B8xfdWQt.js → Reputation-DE_JSjyi.js} +1 -1
  56. package/src/assets/web-panel/assets/{Row-D4zoYiqD.js → Row-DI36Fic1.js} +1 -1
  57. package/src/assets/web-panel/assets/{RssFeed-BI0FPtP6.js → RssFeed-DswpSUiI.js} +3 -3
  58. package/src/assets/web-panel/assets/{Search-BG975ISr.js → Search-Crs2UKhh.js} +1 -1
  59. package/src/assets/web-panel/assets/{Security-BObRR-p6.js → Security-W8ViXXbq.js} +3 -3
  60. package/src/assets/web-panel/assets/{Services-B2TScn1O.js → Services-BIQdyLJM.js} +2 -2
  61. package/src/assets/web-panel/assets/{Skeleton-PYzlv5Fw.js → Skeleton-DDiOevKX.js} +1 -1
  62. package/src/assets/web-panel/assets/{Skills-DbsTF84K.js → Skills-v-Vw_jGa.js} +1 -1
  63. package/src/assets/web-panel/assets/{Sla-D8q9j9bo.js → Sla-B-ULmz5m.js} +1 -1
  64. package/src/assets/web-panel/assets/{SpeechSettings-CjjNbmVH.js → SpeechSettings--8IIPHri.js} +1 -1
  65. package/src/assets/web-panel/assets/{SyncSettings-UEp5lB2T.js → SyncSettings-D0QiEwJn.js} +1 -1
  66. package/src/assets/web-panel/assets/{Tasks-CoCW4gWI.js → Tasks-BNSR9FlM.js} +1 -1
  67. package/src/assets/web-panel/assets/{Templates-hd7UB-8K.js → Templates-CFVkaS-d.js} +1 -1
  68. package/src/assets/web-panel/assets/{Tenant-CqebAGfR.js → Tenant-quU-tldS.js} +1 -1
  69. package/src/assets/web-panel/assets/{Tokens-9b0DDm86.js → Tokens-DTqFjS4k.js} +1 -1
  70. package/src/assets/web-panel/assets/{Trigger-CG_ZXii2.js → Trigger-ZWVirxhN.js} +1 -1
  71. package/src/assets/web-panel/assets/{Trust-CoCtornh.js → Trust-DmaYf5tg.js} +1 -1
  72. package/src/assets/web-panel/assets/{UkeySign-mBEc6SBj.js → UkeySign-BeYyXtZW.js} +1 -1
  73. package/src/assets/web-panel/assets/{VideoEditing-41j-ZZYu.js → VideoEditing-CRdDwD9C.js} +1 -1
  74. package/src/assets/web-panel/assets/{Wallet-DX4iBaEj.js → Wallet-H-38f7Pv.js} +4 -4
  75. package/src/assets/web-panel/assets/{WebAuthn-9BlQYiNI.js → WebAuthn-CCQVzZ0W.js} +4 -4
  76. package/src/assets/web-panel/assets/{WorkflowEditor-BVm3icIg.js → WorkflowEditor-B1RFE2oN.js} +1 -1
  77. package/src/assets/web-panel/assets/{chat-D98zBL7S.js → chat-Z4UoBAeF.js} +1 -1
  78. package/src/assets/web-panel/assets/{colors-ARL9W9UC.js → colors-AecMhEAZ.js} +1 -1
  79. package/src/assets/web-panel/assets/{compact-item-MYI7UP_X.js → compact-item-Dfhm05kA.js} +1 -1
  80. package/src/assets/web-panel/assets/{createContext-BddTmM7g.js → createContext-C7gBVuRm.js} +1 -1
  81. package/src/assets/web-panel/assets/{hasIn-2OsB0OBj.js → hasIn-DQarK3iI.js} +1 -1
  82. package/src/assets/web-panel/assets/icons-B2mcO3YM.js +57 -0
  83. package/src/assets/web-panel/assets/{index-kNDK9K4y.js → index-1d6L3YWV.js} +1 -1
  84. package/src/assets/web-panel/assets/{index-CXMgUcC_.js → index-5I_kEh5L.js} +1 -1
  85. package/src/assets/web-panel/assets/{index-BA8yc-bG.js → index-5P_X26-m.js} +1 -1
  86. package/src/assets/web-panel/assets/{index-tSE1B4ri.js → index-78eTUfD9.js} +1 -1
  87. package/src/assets/web-panel/assets/{index-BIpkHBFo.js → index-B1XdBIuG.js} +1 -1
  88. package/src/assets/web-panel/assets/{index-BNjLDXWZ.js → index-B52lOAOU.js} +1 -1
  89. package/src/assets/web-panel/assets/{index-CndUS0Yo.js → index-BLYMiBRw.js} +1 -1
  90. package/src/assets/web-panel/assets/{index-BKl1SKpb.js → index-BxjOmfVA.js} +9 -9
  91. package/src/assets/web-panel/assets/{index-awm9n2jp.js → index-C-4d1ug2.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-CtCi5cvq.js → index-C0kyGID6.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-TepTGolv.js → index-C7nHW5ZW.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-DK71wnJK.js → index-CCUfW7hO.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-N9X-UOF0.js → index-CFR1Scu8.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-DpAOSmby.js → index-CS7_x1br.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-B7XKJHg8.js → index-Ch9ExDNs.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-B5UMIkIp.js → index-CiVezMja.js} +1 -1
  99. package/src/assets/web-panel/assets/index-Cp5G30tN.js +1 -0
  100. package/src/assets/web-panel/assets/index-CuPmKar9.js +1 -0
  101. package/src/assets/web-panel/assets/{index-CuoiTv71.js → index-CxDBoEkf.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-BhgLJAQi.js → index-Cy_80Fj7.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-DVB0ott1.js → index-D3Pxfwcc.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-DnL-YqLO.js → index-D4_1yL1c.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-N8eKGGPN.js → index-D841tepe.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-hP2fDMJo.js → index-DWbRHjgk.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-D2lcW3-z.js → index-DX4CKtlL.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-BP5G8FRT.js → index-DdtxWGjo.js} +2 -2
  109. package/src/assets/web-panel/assets/{index-BO0TQWkU.js → index-DfA9S79c.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-BYbgYr7r.js → index-DfAZSzZc.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-C5qBLUjM.js → index-Dkh_4r1F.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-BSKiudeY.js → index-DtrMx44i.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-GxbpL_A7.js → index-Dy2fLm3i.js} +1 -1
  114. package/src/assets/web-panel/assets/index-L6kKxFAO.js +21 -0
  115. package/src/assets/web-panel/assets/{index-DqCyINtK.js → index-OqY41c_z.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-CISWdYQV.js → index-QgJGoGAK.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-Bc-fiOB-.js → index-YJxjR7t9.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-CHfRLYw8.js → index-aHqD7CZz.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-BYKZplcs.js → index-d0Iy6r2J.js} +1 -1
  120. package/src/assets/web-panel/assets/index-eoNKQdFC.js +1 -0
  121. package/src/assets/web-panel/assets/{index-Dz5ro_F6.js → index-nqKLHlmq.js} +1 -1
  122. package/src/assets/web-panel/assets/{initDefaultProps-CJbHV9hH.js → initDefaultProps-CDOGbz6v.js} +1 -1
  123. package/src/assets/web-panel/assets/{markdown-xjUYbPSW.js → markdown-CsiA8-E5.js} +1 -1
  124. package/src/assets/web-panel/assets/{markdown-vYH_ziAO.js → markdown-Yo_c6Krv.js} +1 -1
  125. package/src/assets/web-panel/assets/{motion-BTVrWA7N.js → motion-ChIpIzUN.js} +1 -1
  126. package/src/assets/web-panel/assets/{move-CRIIhWv7.js → move-DbH3dyN8.js} +1 -1
  127. package/src/assets/web-panel/assets/{omit-CDcQHhGi.js → omit-BJ1K-IDI.js} +1 -1
  128. package/src/assets/web-panel/assets/{pickAttrs-Dplb8z8U.js → pickAttrs-B0q7EpvV.js} +1 -1
  129. package/src/assets/web-panel/assets/{placementArrow-CP1cLg6P.js → placementArrow-D7XkOUjs.js} +1 -1
  130. package/src/assets/web-panel/assets/{responsiveObserve-PFMAIMDu.js → responsiveObserve-efcdE4ju.js} +1 -1
  131. package/src/assets/web-panel/assets/{slide-_CVxhTa3.js → slide-BgAktMzM.js} +1 -1
  132. package/src/assets/web-panel/assets/{statusUtils-6j8grlgm.js → statusUtils-CV83LVbI.js} +1 -1
  133. package/src/assets/web-panel/assets/{styleChecker-BbC7i8Sl.js → styleChecker-D1npYi6G.js} +1 -1
  134. package/src/assets/web-panel/assets/{useFlexGapSupport-Ctha7v2w.js → useFlexGapSupport-DTH3yXTD.js} +1 -1
  135. package/src/assets/web-panel/assets/{useFs-CeTUZIh2.js → useFs-BEvSw9aX.js} +1 -1
  136. package/src/assets/web-panel/assets/{vnode-kefkre4N.js → vnode-Duw65sZ1.js} +1 -1
  137. package/src/assets/web-panel/assets/{zoom-CZjCXV_O.js → zoom-CLMtA8PG.js} +1 -1
  138. package/src/assets/web-panel/index.html +2 -2
  139. package/src/commands/marketplace.js +286 -0
  140. package/src/commands/multisig.js +471 -0
  141. package/src/commands/p2p.js +114 -7
  142. package/src/index.js +2 -0
  143. package/src/lib/multisig-runtime.js +160 -0
  144. package/src/lib/p2p-manager.js +96 -2
  145. package/src/assets/web-panel/assets/AppLayout-DSFSWtOZ.js +0 -1
  146. package/src/assets/web-panel/assets/icons-B2G69bhT.js +0 -57
  147. package/src/assets/web-panel/assets/index-BNXp47dX.js +0 -21
  148. package/src/assets/web-panel/assets/index-G5xmB5Af.js +0 -1
  149. package/src/assets/web-panel/assets/index-qbPE-_18.js +0 -1
@@ -34,6 +34,17 @@ import {
34
34
  setInvocationStatus,
35
35
  getMarketplaceStatsV2,
36
36
  } from "../lib/skill-marketplace.js";
37
+ import {
38
+ openMultisigManager,
39
+ defaultMultisigDbPath,
40
+ defaultMultisigLogPath,
41
+ readSecretKey,
42
+ } from "../lib/multisig-runtime.js";
43
+
44
+ // v1.2 m-of-n Phase 2 — marketplace.purchase 大额触发阈值。设计文档 §1 写的
45
+ // "商品 price ≥ ¥1000"。fen = ¥ × 100。可由命令行 --threshold-fen 覆盖(测试用)。
46
+ export const LARGE_PURCHASE_THRESHOLD_FEN = 100_000;
47
+ const MULTISIG_DOMAIN = "marketplace.purchase";
37
48
 
38
49
  function _dbFromCtx(ctx) {
39
50
  if (!ctx.db) {
@@ -579,6 +590,281 @@ export function registerMarketplaceCommand(program) {
579
590
  process.exit(1);
580
591
  }
581
592
  });
593
+
594
+ /* ── v1.2 m-of-n Phase 2: marketplace.purchase mediator ─────── */
595
+
596
+ mp.command("purchase <itemId>")
597
+ .description(
598
+ "Initiate a purchase. Large orders (≥ threshold) route through M-of-N multisig.",
599
+ )
600
+ .requiredOption("--amount-fen <n>", "Order amount in fen (¥ × 100)", (v) =>
601
+ parseInt(v, 10),
602
+ )
603
+ .requiredOption("--buyer <did>", "Buyer DID (multisig initiator)")
604
+ .option("--alg <alg>", "Initiator signing alg", "Ed25519")
605
+ .option("--key <hex|path>", "Initiator secret key hex / file")
606
+ .option(
607
+ "--threshold-fen <n>",
608
+ `Override large-order threshold (default ${LARGE_PURCHASE_THRESHOLD_FEN})`,
609
+ (v) => parseInt(v, 10),
610
+ )
611
+ .option("--item-name <name>", "Optional item display name")
612
+ .option("--db <path>", "Multisig DB path", defaultMultisigDbPath())
613
+ .option("--log <path>", "Governance log path", defaultMultisigLogPath())
614
+ .option("--json", "Output JSON")
615
+ .action(async (itemId, options) => {
616
+ try {
617
+ const threshold = options.thresholdFen ?? LARGE_PURCHASE_THRESHOLD_FEN;
618
+ const amountFen = options.amountFen;
619
+ if (!Number.isFinite(amountFen) || amountFen <= 0) {
620
+ logger.error("--amount-fen must be positive integer");
621
+ process.exit(2);
622
+ }
623
+ const requiresMultisig = amountFen >= threshold;
624
+
625
+ if (!requiresMultisig) {
626
+ // Below threshold: direct path. No real payment processor in CLI scope
627
+ // — emit a "purchased" record. Phase 2 doesn't aim to wire a real
628
+ // payment gateway; it aims to gate large orders through multisig.
629
+ if (options.json) {
630
+ console.log(
631
+ JSON.stringify(
632
+ {
633
+ status: "purchased",
634
+ itemId,
635
+ amountFen,
636
+ buyer: options.buyer,
637
+ path: "direct",
638
+ },
639
+ null,
640
+ 2,
641
+ ),
642
+ );
643
+ } else {
644
+ logger.log(
645
+ chalk.green(
646
+ `✓ Purchase executed (direct, below ¥${(threshold / 100).toFixed(2)} threshold)`,
647
+ ),
648
+ );
649
+ logger.log(` itemId: ${itemId}`);
650
+ logger.log(` amount: ¥${(amountFen / 100).toFixed(2)}`);
651
+ }
652
+ return;
653
+ }
654
+
655
+ // Above threshold: route through multisig.
656
+ const { store, mgr, close } = await openMultisigManager(
657
+ options.db,
658
+ options.log,
659
+ );
660
+ try {
661
+ const policy = store.getPolicy(MULTISIG_DOMAIN);
662
+ if (!policy) {
663
+ const msg = `No multisig policy for domain "${MULTISIG_DOMAIN}" — cannot route ¥${(amountFen / 100).toFixed(2)} (≥ threshold). Run: cc multisig policy set ${MULTISIG_DOMAIN} --m <M> --members <json>`;
664
+ if (options.json) {
665
+ console.log(
666
+ JSON.stringify(
667
+ {
668
+ status: "blocked",
669
+ reason: "no_policy",
670
+ itemId,
671
+ amountFen,
672
+ path: "multisig",
673
+ },
674
+ null,
675
+ 2,
676
+ ),
677
+ );
678
+ } else {
679
+ logger.error(chalk.red(`✗ ${msg}`));
680
+ }
681
+ process.exit(2);
682
+ }
683
+ const secretKey = readSecretKey(options.key);
684
+ const result = mgr.propose({
685
+ domain: MULTISIG_DOMAIN,
686
+ payload: {
687
+ itemId,
688
+ amountFen,
689
+ buyer: options.buyer,
690
+ itemName: options.itemName || null,
691
+ },
692
+ policy,
693
+ initiator: {
694
+ did: options.buyer,
695
+ alg: options.alg,
696
+ secretKey,
697
+ },
698
+ });
699
+ if (options.json) {
700
+ console.log(
701
+ JSON.stringify(
702
+ {
703
+ status: "needs_co_sign",
704
+ path: "multisig",
705
+ proposalId: result.proposal.id,
706
+ reachedThreshold: result.reachedThreshold,
707
+ requiredSigs: policy.m,
708
+ itemId,
709
+ amountFen,
710
+ },
711
+ null,
712
+ 2,
713
+ ),
714
+ );
715
+ } else {
716
+ logger.log(
717
+ chalk.cyan(
718
+ `↪ Routed through multisig (¥${(amountFen / 100).toFixed(2)} ≥ ¥${(threshold / 100).toFixed(2)} threshold)`,
719
+ ),
720
+ );
721
+ logger.log(` proposalId: ${result.proposal.id}`);
722
+ logger.log(
723
+ ` needs ${policy.m} of ${policy.members.length} signatures`,
724
+ );
725
+ if (result.reachedThreshold) {
726
+ logger.log(
727
+ chalk.green(
728
+ " ✓ threshold reached on first signature — run: cc marketplace consume",
729
+ ),
730
+ );
731
+ } else {
732
+ logger.log(
733
+ ` next: co-signers run: cc multisig sign ${result.proposal.id}`,
734
+ );
735
+ }
736
+ }
737
+ } finally {
738
+ close();
739
+ }
740
+ } catch (err) {
741
+ logger.error(`Purchase failed: ${err.message}`);
742
+ process.exit(1);
743
+ }
744
+ });
745
+
746
+ mp.command("consume <proposalId>")
747
+ .description(
748
+ "Execute a multisig-gated purchase after threshold reached (marks proposal consumed)",
749
+ )
750
+ .option("--db <path>", "Multisig DB path", defaultMultisigDbPath())
751
+ .option("--log <path>", "Governance log path", defaultMultisigLogPath())
752
+ .option("--json", "Output JSON")
753
+ .action(async (proposalId, options) => {
754
+ try {
755
+ const { mgr, close } = await openMultisigManager(
756
+ options.db,
757
+ options.log,
758
+ );
759
+ try {
760
+ const got = mgr.get(proposalId);
761
+ if (!got) {
762
+ if (options.json) {
763
+ console.log(
764
+ JSON.stringify(
765
+ { status: "error", reason: "proposal_not_found" },
766
+ null,
767
+ 2,
768
+ ),
769
+ );
770
+ } else {
771
+ logger.error(chalk.red(`No proposal: ${proposalId}`));
772
+ }
773
+ process.exit(2);
774
+ }
775
+ if (got.proposal.domain !== MULTISIG_DOMAIN) {
776
+ if (options.json) {
777
+ console.log(
778
+ JSON.stringify(
779
+ {
780
+ status: "error",
781
+ reason: "wrong_domain",
782
+ expected: MULTISIG_DOMAIN,
783
+ actual: got.proposal.domain,
784
+ },
785
+ null,
786
+ 2,
787
+ ),
788
+ );
789
+ } else {
790
+ logger.error(
791
+ chalk.red(
792
+ `Proposal domain "${got.proposal.domain}" is not "${MULTISIG_DOMAIN}" — use cc multisig finalize instead.`,
793
+ ),
794
+ );
795
+ }
796
+ process.exit(2);
797
+ }
798
+ if (got.proposal.state !== "reached") {
799
+ if (options.json) {
800
+ console.log(
801
+ JSON.stringify(
802
+ {
803
+ status: "error",
804
+ reason: `proposal_state_${got.proposal.state}`,
805
+ },
806
+ null,
807
+ 2,
808
+ ),
809
+ );
810
+ } else {
811
+ logger.error(
812
+ chalk.red(
813
+ `Proposal state is "${got.proposal.state}", need "reached" — sign more before consume.`,
814
+ ),
815
+ );
816
+ }
817
+ process.exit(2);
818
+ }
819
+
820
+ // Execute purchase from proposal payload (CLI stub — Phase 2 doesn't
821
+ // ship a real payment processor). Just print the order, then finalize.
822
+ const order = JSON.parse(got.proposal.payloadJcs);
823
+ const finalizeRes = mgr.finalize(proposalId);
824
+ if (!finalizeRes.ok) {
825
+ if (options.json) {
826
+ console.log(
827
+ JSON.stringify(
828
+ { status: "error", reason: finalizeRes.reason },
829
+ null,
830
+ 2,
831
+ ),
832
+ );
833
+ } else {
834
+ logger.error(chalk.red(`Finalize failed: ${finalizeRes.reason}`));
835
+ }
836
+ process.exit(1);
837
+ }
838
+ if (options.json) {
839
+ console.log(
840
+ JSON.stringify(
841
+ {
842
+ status: "consumed",
843
+ proposalId,
844
+ order,
845
+ },
846
+ null,
847
+ 2,
848
+ ),
849
+ );
850
+ } else {
851
+ logger.log(
852
+ chalk.green(
853
+ `✓ Purchase consumed — order ${order.itemId} for ¥${(order.amountFen / 100).toFixed(2)}`,
854
+ ),
855
+ );
856
+ logger.log(` buyer: ${order.buyer}`);
857
+ if (order.itemName) logger.log(` item: ${order.itemName}`);
858
+ logger.log(` proposalId: ${proposalId}`);
859
+ }
860
+ } finally {
861
+ close();
862
+ }
863
+ } catch (err) {
864
+ logger.error(`Consume failed: ${err.message}`);
865
+ process.exit(1);
866
+ }
867
+ });
582
868
  }
583
869
 
584
870
  // === Iter16 V2 governance overlay ===