chainlesschain 0.161.8 → 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 (148) hide show
  1. package/package.json +2 -1
  2. package/src/assets/web-panel/.build-hash +1 -1
  3. package/src/assets/web-panel/assets/{AIOps-Uls1XIO4.js → AIOps-Cbnj25uU.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-BpVrefl1.js → ActionButton-DY69UkxV.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-Z1Rgg9PA.js → Analytics-DUzoL75H.js} +2 -2
  6. package/src/assets/web-panel/assets/AppLayout-DATUppSv.js +1 -0
  7. package/src/assets/web-panel/assets/{AppLayout-P7jhSfLy.css → AppLayout-qr7ghxW7.css} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-Co6yYgmX.js → Audit-CFJh6huz.js} +1 -1
  9. package/src/assets/web-panel/assets/{Backup-1IZDB3QD.js → Backup-CMTir4tV.js} +1 -1
  10. package/src/assets/web-panel/assets/{BaseInput-LYB_wIZP.js → BaseInput-BaWXBDdp.js} +1 -1
  11. package/src/assets/web-panel/assets/{Chat-D-6LDWGl.js → Chat-DjToexEx.js} +3 -3
  12. package/src/assets/web-panel/assets/{Checkbox-dLnnw7OE.js → Checkbox-DJnhKXhi.js} +1 -1
  13. package/src/assets/web-panel/assets/{Codegen-Wh6xypMx.js → Codegen-CgsgvRJX.js} +1 -1
  14. package/src/assets/web-panel/assets/{Col-BT8lkjSw.js → Col-MvMGDJAB.js} +1 -1
  15. package/src/assets/web-panel/assets/{Community-CdAeMHde.js → Community-q26VGOGu.js} +1 -1
  16. package/src/assets/web-panel/assets/{Compact-VsImrjgV.js → Compact-DyLYzWoX.js} +1 -1
  17. package/src/assets/web-panel/assets/{Compliance-PScuVx8d.js → Compliance-D_TF9eBc.js} +1 -1
  18. package/src/assets/web-panel/assets/{Cowork-qB8hRW0r.js → Cowork-B9bg988c.js} +3 -3
  19. package/src/assets/web-panel/assets/{Cron-CuSjuE-h.js → Cron-6k9vTFfd.js} +2 -2
  20. package/src/assets/web-panel/assets/{Crosschain-BqIRd8bv.js → Crosschain-B7fk2aHi.js} +1 -1
  21. package/src/assets/web-panel/assets/{DID-BT5BJ0DF.js → DID-XhCfTFm2.js} +2 -2
  22. package/src/assets/web-panel/assets/{Dashboard-BX-06zEm.js → Dashboard-Bqk7vtZM.js} +2 -2
  23. package/src/assets/web-panel/assets/{Dropdown-Pjo3G3Vf.js → Dropdown-CDOOZGv7.js} +1 -1
  24. package/src/assets/web-panel/assets/{Federation-BbnYcYhr.js → Federation-NajN4oRO.js} +1 -1
  25. package/src/assets/web-panel/assets/{FormItemContext-C3hf4K1_.js → FormItemContext-DgMHYlMB.js} +1 -1
  26. package/src/assets/web-panel/assets/{Git-Cmw6_HXW.js → Git-CZC5n1Zu.js} +2 -2
  27. package/src/assets/web-panel/assets/{Governance-BFBvB2G6.js → Governance-Br131eUW.js} +1 -1
  28. package/src/assets/web-panel/assets/{Inference-BBdX3YjM.js → Inference-BHlUfcT-.js} +1 -1
  29. package/src/assets/web-panel/assets/{KnowledgeGraph-BC-bcvNY.js → KnowledgeGraph-CByROhg-.js} +1 -1
  30. package/src/assets/web-panel/assets/{Logs-B9DuqFeW.js → Logs-D8Ghzk4B.js} +1 -1
  31. package/src/assets/web-panel/assets/{Marketplace-Bff1ja4R.js → Marketplace-CnjHPFm7.js} +1 -1
  32. package/src/assets/web-panel/assets/{McpTools-DnWqjtkb.js → McpTools-C_vszCBU.js} +1 -1
  33. package/src/assets/web-panel/assets/{Memory-C6YXBuM7.js → Memory-Cl5c_8In.js} +2 -2
  34. package/src/assets/web-panel/assets/MobileBridge-DkkMCDx9.css +1 -0
  35. package/src/assets/web-panel/assets/MobileBridge-K3KwwCKl.js +3 -0
  36. package/src/assets/web-panel/assets/{Mtc-r-J4WRfp.js → Mtc-NfZ8xzyu.js} +4 -4
  37. package/src/assets/web-panel/assets/{MtcAudit-DFqXLHn6.js → MtcAudit-BkktYSXj.js} +1 -1
  38. package/src/assets/web-panel/assets/Multisig-BLRYDn7_.css +1 -0
  39. package/src/assets/web-panel/assets/Multisig-qP51bs1T.js +1 -0
  40. package/src/assets/web-panel/assets/{NLProgramming-s5CrjYto.js → NLProgramming-BhFRuXyi.js} +1 -1
  41. package/src/assets/web-panel/assets/{Notes-TAbnvDCd.js → Notes-BpcAFy8i.js} +3 -3
  42. package/src/assets/web-panel/assets/{NotificationSettings-BZIKI219.js → NotificationSettings-DKNtYYeo.js} +1 -1
  43. package/src/assets/web-panel/assets/{Organization-BXbSljYa.js → Organization-C61VwQEW.js} +4 -4
  44. package/src/assets/web-panel/assets/{Overflow-O2RWHZxH.js → Overflow-WBloac1x.js} +1 -1
  45. package/src/assets/web-panel/assets/{P2P-B8jBZLh6.js → P2P-DGm7EvDg.js} +2 -2
  46. package/src/assets/web-panel/assets/{Permissions-Cexi8Jr6.js → Permissions-KFPtoOV6.js} +2 -2
  47. package/src/assets/web-panel/assets/{Pipeline-BwIBnNzj.js → Pipeline-CFjFtzZT.js} +1 -1
  48. package/src/assets/web-panel/assets/{Privacy-D-LOR9um.js → Privacy-T_Kewe_f.js} +1 -1
  49. package/src/assets/web-panel/assets/{ProjectSettings-DZ_fdRRJ.js → ProjectSettings-BQl8qTPQ.js} +1 -1
  50. package/src/assets/web-panel/assets/{Projects-Bis42Cb6.js → Projects-xGNn4Ov9.js} +2 -2
  51. package/src/assets/web-panel/assets/{Providers-DH6hY4Gx.js → Providers-ByuUztXe.js} +1 -1
  52. package/src/assets/web-panel/assets/{QuickAsk-Ur0bUXHK.js → QuickAsk-BwSXmXvL.js} +1 -1
  53. package/src/assets/web-panel/assets/{Recommend-CLDQjSf6.js → Recommend-Cp433_5Z.js} +1 -1
  54. package/src/assets/web-panel/assets/{Reputation-StG-zGil.js → Reputation-DE_JSjyi.js} +1 -1
  55. package/src/assets/web-panel/assets/{Row-DAWA1cwa.js → Row-DI36Fic1.js} +1 -1
  56. package/src/assets/web-panel/assets/{RssFeed-rb2CP-IS.js → RssFeed-DswpSUiI.js} +3 -3
  57. package/src/assets/web-panel/assets/{Search-Y9qsWaAE.js → Search-Crs2UKhh.js} +1 -1
  58. package/src/assets/web-panel/assets/{Security-BanZDWBe.js → Security-W8ViXXbq.js} +3 -3
  59. package/src/assets/web-panel/assets/{Services-DFOMZwqJ.js → Services-BIQdyLJM.js} +2 -2
  60. package/src/assets/web-panel/assets/{Skeleton-Cy48VmyC.js → Skeleton-DDiOevKX.js} +1 -1
  61. package/src/assets/web-panel/assets/{Skills-BqdkGRyO.js → Skills-v-Vw_jGa.js} +1 -1
  62. package/src/assets/web-panel/assets/{Sla-B8lXq9rJ.js → Sla-B-ULmz5m.js} +1 -1
  63. package/src/assets/web-panel/assets/{SpeechSettings-CmIkYpWT.js → SpeechSettings--8IIPHri.js} +1 -1
  64. package/src/assets/web-panel/assets/{SyncSettings-tZDaJZ0S.js → SyncSettings-D0QiEwJn.js} +1 -1
  65. package/src/assets/web-panel/assets/{Tasks-DxBlrylF.js → Tasks-BNSR9FlM.js} +1 -1
  66. package/src/assets/web-panel/assets/{Templates-ByshgJtu.js → Templates-CFVkaS-d.js} +1 -1
  67. package/src/assets/web-panel/assets/{Tenant-DCpEpRf1.js → Tenant-quU-tldS.js} +1 -1
  68. package/src/assets/web-panel/assets/{Tokens-BIUug_M_.js → Tokens-DTqFjS4k.js} +1 -1
  69. package/src/assets/web-panel/assets/{Trigger-DY4iT_Sv.js → Trigger-ZWVirxhN.js} +1 -1
  70. package/src/assets/web-panel/assets/{Trust-fAtm0ohe.js → Trust-DmaYf5tg.js} +1 -1
  71. package/src/assets/web-panel/assets/{UkeySign-CwbV_ITc.js → UkeySign-BeYyXtZW.js} +1 -1
  72. package/src/assets/web-panel/assets/{VideoEditing-CBJ5dw8E.js → VideoEditing-CRdDwD9C.js} +1 -1
  73. package/src/assets/web-panel/assets/{Wallet-B1fyWeNC.js → Wallet-H-38f7Pv.js} +4 -4
  74. package/src/assets/web-panel/assets/{WebAuthn-by6IZMeB.js → WebAuthn-CCQVzZ0W.js} +4 -4
  75. package/src/assets/web-panel/assets/{WorkflowEditor-DZkBKsSU.js → WorkflowEditor-B1RFE2oN.js} +1 -1
  76. package/src/assets/web-panel/assets/{chat-CKAWhBMH.js → chat-Z4UoBAeF.js} +1 -1
  77. package/src/assets/web-panel/assets/{colors-DgRS7Mb2.js → colors-AecMhEAZ.js} +1 -1
  78. package/src/assets/web-panel/assets/{compact-item-CQUZCSRU.js → compact-item-Dfhm05kA.js} +1 -1
  79. package/src/assets/web-panel/assets/{createContext-DgOciZHM.js → createContext-C7gBVuRm.js} +1 -1
  80. package/src/assets/web-panel/assets/{hasIn-DEXVOypF.js → hasIn-DQarK3iI.js} +1 -1
  81. package/src/assets/web-panel/assets/icons-B2mcO3YM.js +57 -0
  82. package/src/assets/web-panel/assets/{index-DjQzFo-O.js → index-1d6L3YWV.js} +1 -1
  83. package/src/assets/web-panel/assets/{index-jLpDpunJ.js → index-5I_kEh5L.js} +1 -1
  84. package/src/assets/web-panel/assets/{index-BjpS0vcp.js → index-5P_X26-m.js} +1 -1
  85. package/src/assets/web-panel/assets/{index-nMw96bEM.js → index-78eTUfD9.js} +1 -1
  86. package/src/assets/web-panel/assets/{index-BYrBEkTv.js → index-B1XdBIuG.js} +1 -1
  87. package/src/assets/web-panel/assets/{index-BQDGHgXQ.js → index-B52lOAOU.js} +1 -1
  88. package/src/assets/web-panel/assets/{index-Bo43zHIV.js → index-BLYMiBRw.js} +1 -1
  89. package/src/assets/web-panel/assets/{index-D8S-7oDQ.js → index-BxjOmfVA.js} +9 -9
  90. package/src/assets/web-panel/assets/{index-D2PDzVV6.js → index-C-4d1ug2.js} +1 -1
  91. package/src/assets/web-panel/assets/{index-D1dIizuf.js → index-C0kyGID6.js} +1 -1
  92. package/src/assets/web-panel/assets/{index-CS3fI6_d.js → index-C7nHW5ZW.js} +1 -1
  93. package/src/assets/web-panel/assets/{index-Ce57JGJq.js → index-CCUfW7hO.js} +1 -1
  94. package/src/assets/web-panel/assets/{index-nIXYg_tf.js → index-CFR1Scu8.js} +1 -1
  95. package/src/assets/web-panel/assets/{index-hfGZzUzb.js → index-CS7_x1br.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-1EDbawpk.js → index-Ch9ExDNs.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-CEt0RfAY.js → index-CiVezMja.js} +1 -1
  98. package/src/assets/web-panel/assets/index-Cp5G30tN.js +1 -0
  99. package/src/assets/web-panel/assets/index-CuPmKar9.js +1 -0
  100. package/src/assets/web-panel/assets/{index-CCuIY7Ff.js → index-CxDBoEkf.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-B-g1My7q.js → index-Cy_80Fj7.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-CH5YkJC9.js → index-D3Pxfwcc.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-_Oe8Zr99.js → index-D4_1yL1c.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-HE37tYPs.js → index-D841tepe.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-ZOpqRGzA.js → index-DWbRHjgk.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-DkBSIb9k.js → index-DX4CKtlL.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-wPVZuwWm.js → index-DdtxWGjo.js} +2 -2
  108. package/src/assets/web-panel/assets/{index-DW_-28b4.js → index-DfA9S79c.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-CetlLBjh.js → index-DfAZSzZc.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-B1USa9q3.js → index-Dkh_4r1F.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-DBRA1wFF.js → index-DtrMx44i.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-BEnMJ3rw.js → index-Dy2fLm3i.js} +1 -1
  113. package/src/assets/web-panel/assets/index-L6kKxFAO.js +21 -0
  114. package/src/assets/web-panel/assets/{index-DpL-43E_.js → index-OqY41c_z.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-D3tqZAdL.js → index-QgJGoGAK.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-o6vVX9C_.js → index-YJxjR7t9.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-CQepaPId.js → index-aHqD7CZz.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-bRI-SvZ-.js → index-d0Iy6r2J.js} +1 -1
  119. package/src/assets/web-panel/assets/index-eoNKQdFC.js +1 -0
  120. package/src/assets/web-panel/assets/{index-BMx0R9Vw.js → index-nqKLHlmq.js} +1 -1
  121. package/src/assets/web-panel/assets/{initDefaultProps-BSTz5E8D.js → initDefaultProps-CDOGbz6v.js} +1 -1
  122. package/src/assets/web-panel/assets/{markdown-xjUYbPSW.js → markdown-CsiA8-E5.js} +1 -1
  123. package/src/assets/web-panel/assets/{markdown-vYH_ziAO.js → markdown-Yo_c6Krv.js} +1 -1
  124. package/src/assets/web-panel/assets/{motion-B10pjDA-.js → motion-ChIpIzUN.js} +1 -1
  125. package/src/assets/web-panel/assets/{move-B_PFOXXn.js → move-DbH3dyN8.js} +1 -1
  126. package/src/assets/web-panel/assets/{omit-Bf31gUOR.js → omit-BJ1K-IDI.js} +1 -1
  127. package/src/assets/web-panel/assets/{pickAttrs-CTOOvnV9.js → pickAttrs-B0q7EpvV.js} +1 -1
  128. package/src/assets/web-panel/assets/{placementArrow-DfXqIy1B.js → placementArrow-D7XkOUjs.js} +1 -1
  129. package/src/assets/web-panel/assets/{responsiveObserve-BonUzZVT.js → responsiveObserve-efcdE4ju.js} +1 -1
  130. package/src/assets/web-panel/assets/{slide-DtkoQrl3.js → slide-BgAktMzM.js} +1 -1
  131. package/src/assets/web-panel/assets/{statusUtils-BJlmtjwo.js → statusUtils-CV83LVbI.js} +1 -1
  132. package/src/assets/web-panel/assets/{styleChecker-CoQ2DFN_.js → styleChecker-D1npYi6G.js} +1 -1
  133. package/src/assets/web-panel/assets/{useFlexGapSupport-BD9H_ICR.js → useFlexGapSupport-DTH3yXTD.js} +1 -1
  134. package/src/assets/web-panel/assets/{useFs-DNCH6P7V.js → useFs-BEvSw9aX.js} +1 -1
  135. package/src/assets/web-panel/assets/{vnode-CAFNU-3N.js → vnode-Duw65sZ1.js} +1 -1
  136. package/src/assets/web-panel/assets/{zoom-Beg44Pk9.js → zoom-CLMtA8PG.js} +1 -1
  137. package/src/assets/web-panel/index.html +2 -2
  138. package/src/commands/marketplace.js +286 -0
  139. package/src/commands/multisig.js +471 -0
  140. package/src/commands/p2p.js +114 -7
  141. package/src/index.js +2 -0
  142. package/src/lib/multisig-runtime.js +160 -0
  143. package/src/lib/p2p-manager.js +96 -2
  144. package/src/assets/web-panel/assets/AppLayout-GvY1b95g.js +0 -1
  145. package/src/assets/web-panel/assets/icons-B2G69bhT.js +0 -57
  146. package/src/assets/web-panel/assets/index-DLnvncqr.js +0 -1
  147. package/src/assets/web-panel/assets/index-DsmrJv8Y.js +0 -21
  148. package/src/assets/web-panel/assets/index-Rvjbak1o.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 ===