@yalehwang/cloudpit 2.0.0 → 3.0.0

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 (690) hide show
  1. package/README.md +1 -1
  2. package/dist/api-docs.html +3 -3
  3. package/dist/assets/{abnfDiagram-N423BO3Z-D5yLnMt9.js → abnfDiagram-N423BO3Z-D7Xt05gV.js} +1 -1
  4. package/dist/assets/{abnfDiagram-N423BO3Z-bTHtQIhR.js → abnfDiagram-N423BO3Z-dmPRRPEm.js} +1 -1
  5. package/dist/assets/{arc-1DmrBEyG.js → arc-B7W3R5qH.js} +1 -1
  6. package/dist/assets/{arc-BlGK--01.js → arc-BHMlIcaQ.js} +1 -1
  7. package/dist/assets/{architectureDiagram-T3A2C74G--lzbKBn9.js → architectureDiagram-T3A2C74G-CUUpAoN0.js} +1 -1
  8. package/dist/assets/{architectureDiagram-T3A2C74G-7lKNAbUU.js → architectureDiagram-T3A2C74G-DpXhbHxu.js} +1 -1
  9. package/dist/assets/{blockDiagram-VBNYF7ZC-17cdO9zs.js → blockDiagram-VBNYF7ZC-Bf0yfNxj.js} +1 -1
  10. package/dist/assets/{blockDiagram-VBNYF7ZC-BPavJfDj.js → blockDiagram-VBNYF7ZC-Cki9AOhc.js} +1 -1
  11. package/dist/assets/{c4Diagram-5PPSVZJV-Bm1-2w3b.js → c4Diagram-5PPSVZJV-DK2RqNDO.js} +1 -1
  12. package/dist/assets/{c4Diagram-5PPSVZJV-aHvFL3Wb.js → c4Diagram-5PPSVZJV-DyhTF0e5.js} +1 -1
  13. package/dist/assets/channel-DTLMNzbH.js +1 -0
  14. package/dist/assets/channel-DiqxUuPf.js +1 -0
  15. package/dist/assets/{chunk-2GRJ4B5K-D7WqZewM.js → chunk-2GRJ4B5K-BYtByJbf.js} +1 -1
  16. package/dist/assets/{chunk-2GRJ4B5K-DbwzBiPF.js → chunk-2GRJ4B5K-CksFgocc.js} +1 -1
  17. package/dist/assets/{chunk-2Q5K7J3B-DdCr89uy.js → chunk-2Q5K7J3B-D2kQa5TZ.js} +1 -1
  18. package/dist/assets/{chunk-2Q5K7J3B-TFd0ECKO.js → chunk-2Q5K7J3B-NSSX86FA.js} +1 -1
  19. package/dist/assets/{chunk-5RXB4S5H-BdhRBpEi.js → chunk-5RXB4S5H-DNNYC8_t.js} +1 -1
  20. package/dist/assets/{chunk-5RXB4S5H-D0SQ3nIe.js → chunk-5RXB4S5H-Rx0YaqNI.js} +1 -1
  21. package/dist/assets/{chunk-5VM5RSS4-B9Lv3cWR.js → chunk-5VM5RSS4-B1k4I4CX.js} +1 -1
  22. package/dist/assets/{chunk-5VM5RSS4-DioqTIvB.js → chunk-5VM5RSS4-CsvQj3QC.js} +1 -1
  23. package/dist/assets/{chunk-6Q2QTUOP-09bwlcIv.js → chunk-6Q2QTUOP-48-dEgAs.js} +1 -1
  24. package/dist/assets/{chunk-6Q2QTUOP-JuhPJZZL.js → chunk-6Q2QTUOP-DCMSW5_0.js} +1 -1
  25. package/dist/assets/{chunk-GF5L2VYU-C6f2SgCw.js → chunk-GF5L2VYU-CGyvOsdN.js} +1 -1
  26. package/dist/assets/{chunk-GF5L2VYU-DzD9aOyp.js → chunk-GF5L2VYU-YXe113hp.js} +1 -1
  27. package/dist/assets/{chunk-JWPE2WC7-BggnWNZv.js → chunk-JWPE2WC7-BT7vCW4x.js} +1 -1
  28. package/dist/assets/{chunk-JWPE2WC7-Dte_Ax9K.js → chunk-JWPE2WC7-D2K1Oywq.js} +1 -1
  29. package/dist/assets/{chunk-KBJHAD2P-9TCQV92m.js → chunk-KBJHAD2P-CQZWamtE.js} +1 -1
  30. package/dist/assets/{chunk-KBJHAD2P-DDnJp7kJ.js → chunk-KBJHAD2P-gpEwZrNy.js} +1 -1
  31. package/dist/assets/{chunk-RYQCIY6F-CE2Y4D_h.js → chunk-RYQCIY6F-BI0fMtjY.js} +1 -1
  32. package/dist/assets/{chunk-RYQCIY6F-DsgFSTNw.js → chunk-RYQCIY6F-vguRdb4F.js} +1 -1
  33. package/dist/assets/{chunk-XXDRQBXY-B1FIfsqq.js → chunk-XXDRQBXY-B99qH1_w.js} +1 -1
  34. package/dist/assets/{chunk-XXDRQBXY-B4YfaqTO.js → chunk-XXDRQBXY-DZLJnbBB.js} +1 -1
  35. package/dist/assets/classDiagram-JCYQIIEL-BaV-s6x8.js +1 -0
  36. package/dist/assets/classDiagram-JCYQIIEL-D4M03B4L.js +1 -0
  37. package/dist/assets/classDiagram-v2-OCEON4UE-BaV-s6x8.js +1 -0
  38. package/dist/assets/classDiagram-v2-OCEON4UE-D4M03B4L.js +1 -0
  39. package/dist/assets/{cose-bilkent-JH36ORCC-C1AG5Pib.js → cose-bilkent-JH36ORCC-EsVnz-E6.js} +1 -1
  40. package/dist/assets/{cose-bilkent-JH36ORCC-lMwWDibI.js → cose-bilkent-JH36ORCC-VI2OjCIx.js} +1 -1
  41. package/dist/assets/{cynefin-VYW2F7L2-BlabniRL.js → cynefin-VYW2F7L2-BVYg0ixs.js} +1 -1
  42. package/dist/assets/{cynefin-VYW2F7L2-W-c-z4IW.js → cynefin-VYW2F7L2-BnHmA5I2.js} +1 -1
  43. package/dist/assets/{cynefinDiagram-MW4NZA55-BtTep_pq.js → cynefinDiagram-MW4NZA55-B-OCRLIw.js} +1 -1
  44. package/dist/assets/{cynefinDiagram-MW4NZA55-Due6EIPh.js → cynefinDiagram-MW4NZA55-ItLlzjDR.js} +1 -1
  45. package/dist/assets/{dagre-VZM6K2ZE-CWLaFfdt.js → dagre-VZM6K2ZE-DkVDkAWJ.js} +1 -1
  46. package/dist/assets/{dagre-VZM6K2ZE-DZldvqiQ.js → dagre-VZM6K2ZE-bYR4z8-Z.js} +1 -1
  47. package/dist/assets/{diagram-7IWD3JNH-RnmUHYwN.js → diagram-7IWD3JNH-DjXMue67.js} +1 -1
  48. package/dist/assets/{diagram-7IWD3JNH-Di-7-nSA.js → diagram-7IWD3JNH-FNEXlm5k.js} +1 -1
  49. package/dist/assets/{diagram-B4RE2ZJO-Wybyn8fw.js → diagram-B4RE2ZJO-73NYiO_P.js} +1 -1
  50. package/dist/assets/{diagram-B4RE2ZJO-mrK79C2E.js → diagram-B4RE2ZJO-dB4QHq0D.js} +1 -1
  51. package/dist/assets/{diagram-LBJQPF4R-JY6FqSFu.js → diagram-LBJQPF4R-DyKT610O.js} +1 -1
  52. package/dist/assets/{diagram-LBJQPF4R-sWhu2VLy.js → diagram-LBJQPF4R-rMgmnjvd.js} +1 -1
  53. package/dist/assets/{diagram-Q27KOJAE-BJ4T0WGp.js → diagram-Q27KOJAE-BvsfmmQt.js} +1 -1
  54. package/dist/assets/{diagram-Q27KOJAE-DyGT9KhB.js → diagram-Q27KOJAE-c6DEjLQX.js} +1 -1
  55. package/dist/assets/{diagram-UB23O5K3-oXFJAndB.js → diagram-UB23O5K3-BMo2VXVb.js} +1 -1
  56. package/dist/assets/{diagram-UB23O5K3-tTd8qwEM.js → diagram-UB23O5K3-DRMKefnZ.js} +1 -1
  57. package/dist/assets/{ebnfDiagram-BXEA7PRR-DV67cBe6.js → ebnfDiagram-BXEA7PRR-BrOAekWh.js} +1 -1
  58. package/dist/assets/{ebnfDiagram-BXEA7PRR-OQGm8tPs.js → ebnfDiagram-BXEA7PRR-YmQkylwV.js} +1 -1
  59. package/dist/assets/{elk-BRx4gEGg.js → elk-Hz3WRESK.js} +1 -1
  60. package/dist/assets/{elk-CdAQJ-NA.js → elk-tPSZwRVB.js} +1 -1
  61. package/dist/assets/{erDiagram-JOGREHBK-BhD2xZ2I.js → erDiagram-JOGREHBK-BlaZnoQi.js} +1 -1
  62. package/dist/assets/{erDiagram-JOGREHBK-BqP8DqqW.js → erDiagram-JOGREHBK-CRCfRUXt.js} +1 -1
  63. package/dist/assets/{flowDiagram-UKHOOZJN-B4AjZxPJ.js → flowDiagram-UKHOOZJN-DQ1gbjxo.js} +1 -1
  64. package/dist/assets/{flowDiagram-UKHOOZJN-CP_1WsW4.js → flowDiagram-UKHOOZJN-Dinlbmds.js} +1 -1
  65. package/dist/assets/{ganttDiagram-PKOTCBZU-BMk6nngr.js → ganttDiagram-PKOTCBZU-CMGpcBZO.js} +1 -1
  66. package/dist/assets/{ganttDiagram-PKOTCBZU-B_ce39Ld.js → ganttDiagram-PKOTCBZU-Eh94zuPI.js} +1 -1
  67. package/dist/assets/{gitGraphDiagram-DS77QQ5N-CnZA42iA.js → gitGraphDiagram-DS77QQ5N-Bp8xIZbk.js} +1 -1
  68. package/dist/assets/{gitGraphDiagram-DS77QQ5N-DqEz_iTn.js → gitGraphDiagram-DS77QQ5N-Cu-b4YNw.js} +1 -1
  69. package/dist/assets/index-51e8fagd.css +32 -0
  70. package/dist/assets/{index-D5nLH7qP.js → index-CQE9C6k6.js} +356 -356
  71. package/dist/assets/{index-CqyOGerp.js → index-S8ow0XfK.js} +356 -356
  72. package/dist/assets/{infoDiagram-6WML65LV-BQf7m4X4.js → infoDiagram-6WML65LV-CClEEtTq.js} +1 -1
  73. package/dist/assets/{infoDiagram-6WML65LV-Dntf4YFM.js → infoDiagram-6WML65LV-QmHeojgl.js} +1 -1
  74. package/dist/assets/{ishikawaDiagram-WSZJBQD7-BDjsldAI.js → ishikawaDiagram-WSZJBQD7-BemSj9lN.js} +1 -1
  75. package/dist/assets/{ishikawaDiagram-WSZJBQD7-BqXpJeoL.js → ishikawaDiagram-WSZJBQD7-nw48g1vr.js} +1 -1
  76. package/dist/assets/{journeyDiagram-NVQOT4AX-CBcFzP2M.js → journeyDiagram-NVQOT4AX-DeNtO6OU.js} +1 -1
  77. package/dist/assets/{journeyDiagram-NVQOT4AX-DoWKjgKd.js → journeyDiagram-NVQOT4AX-q1lCfOYn.js} +1 -1
  78. package/dist/assets/{kanban-definition-27J2QSJJ-9bspl7j-.js → kanban-definition-27J2QSJJ-Bzhu6hql.js} +1 -1
  79. package/dist/assets/{kanban-definition-27J2QSJJ-Cjxa-Fbb.js → kanban-definition-27J2QSJJ-VfvD33YG.js} +1 -1
  80. package/dist/assets/{linear-YogAXmU_.js → linear-C0Kwu3Yp.js} +1 -1
  81. package/dist/assets/{linear-lIhI5Y8l.js → linear-CbM_4-fP.js} +1 -1
  82. package/dist/assets/{mermaid.core-2Spxcrg7.js → mermaid.core-G2huIsXn.js} +5 -5
  83. package/dist/assets/{mermaid.core-BxxInCBm.js → mermaid.core-fvTQFUX1.js} +5 -5
  84. package/dist/assets/{mindmap-definition-FAOFIHXS-DblO5EG4.js → mindmap-definition-FAOFIHXS-BONvuyvz.js} +1 -1
  85. package/dist/assets/{mindmap-definition-FAOFIHXS-_nlvJ9VK.js → mindmap-definition-FAOFIHXS-BzYawGKQ.js} +1 -1
  86. package/dist/assets/{pegDiagram-VL7TDLO6-BBJFPAZG.js → pegDiagram-VL7TDLO6-Df2HAKGH.js} +1 -1
  87. package/dist/assets/{pegDiagram-VL7TDLO6-DhRH7YRf.js → pegDiagram-VL7TDLO6-DnMwBHn_.js} +1 -1
  88. package/dist/assets/{pieDiagram-7S7Q4E2Y-4Qy7Nk4U.js → pieDiagram-7S7Q4E2Y-Cd3-a-dM.js} +1 -1
  89. package/dist/assets/{pieDiagram-7S7Q4E2Y-BUtdeYBT.js → pieDiagram-7S7Q4E2Y-LV6TOhOD.js} +1 -1
  90. package/dist/assets/{quadrantDiagram-CIZ2JOQS-BUoIDY1r.js → quadrantDiagram-CIZ2JOQS-8VOnA3FV.js} +1 -1
  91. package/dist/assets/{quadrantDiagram-CIZ2JOQS-D90kdHA1.js → quadrantDiagram-CIZ2JOQS-CnwxFPxh.js} +1 -1
  92. package/dist/assets/{railroadDiagram-AXF67PYL-CJf9--tj.js → railroadDiagram-AXF67PYL-CXBFj3Iu.js} +1 -1
  93. package/dist/assets/{railroadDiagram-AXF67PYL-D3S1oliC.js → railroadDiagram-AXF67PYL-DLoAPcsb.js} +1 -1
  94. package/dist/assets/{requirementDiagram-LRYGKXZP-C04jhjS6.js → requirementDiagram-LRYGKXZP-LrVlZXSz.js} +1 -1
  95. package/dist/assets/{requirementDiagram-LRYGKXZP-cQaGai5h.js → requirementDiagram-LRYGKXZP-pakITowN.js} +1 -1
  96. package/dist/assets/{sankeyDiagram-W5VNT64P-AT4cTVbY.js → sankeyDiagram-W5VNT64P-BIQQ8A1I.js} +1 -1
  97. package/dist/assets/{sankeyDiagram-W5VNT64P-DfFUdqYO.js → sankeyDiagram-W5VNT64P-C6QWOxNM.js} +1 -1
  98. package/dist/assets/{sequenceDiagram-SI44F4Z6-DbjhG030.js → sequenceDiagram-SI44F4Z6-CpHBe2CG.js} +1 -1
  99. package/dist/assets/{sequenceDiagram-SI44F4Z6-DKjdupix.js → sequenceDiagram-SI44F4Z6-cnLxaxcV.js} +1 -1
  100. package/dist/assets/{sizeCapture-X5ZJPWSS-CCcKLP8m.js → sizeCapture-X5ZJPWSS-3g-1onHD.js} +1 -1
  101. package/dist/assets/{sizeCapture-X5ZJPWSS-DGxRWxeo.js → sizeCapture-X5ZJPWSS-4U6b3PSL.js} +1 -1
  102. package/dist/assets/{stateDiagram-OKZ733FA-D7wGCNb7.js → stateDiagram-OKZ733FA-CFwVDdlY.js} +1 -1
  103. package/dist/assets/{stateDiagram-OKZ733FA-qdMAailp.js → stateDiagram-OKZ733FA-CKVGJcM2.js} +1 -1
  104. package/dist/assets/{stateDiagram-v2-UEYNNEHI-BbmmtA9w.js → stateDiagram-v2-UEYNNEHI-Dnbk8ftm.js} +1 -1
  105. package/dist/assets/{stateDiagram-v2-UEYNNEHI-Diz_hFvh.js → stateDiagram-v2-UEYNNEHI-rlA-woxH.js} +1 -1
  106. package/dist/assets/{swimlanes-SLNWSIFB-CZgIPz6I.js → swimlanes-SLNWSIFB-DCwz8-mf.js} +2 -2
  107. package/dist/assets/{swimlanes-SLNWSIFB-B16H-6OU.js → swimlanes-SLNWSIFB-M9Oumwnl.js} +2 -2
  108. package/dist/assets/swimlanesDiagram-ULZ7WXOC-CTtTyW6-.js +8 -0
  109. package/dist/assets/swimlanesDiagram-ULZ7WXOC-Caohx6WZ.js +8 -0
  110. package/dist/assets/{timeline-definition-Z64GVDOM-7r7OVlrT.js → timeline-definition-Z64GVDOM-BVmfjoWH.js} +1 -1
  111. package/dist/assets/{timeline-definition-Z64GVDOM-nhnkS_wy.js → timeline-definition-Z64GVDOM-DyXvto1l.js} +1 -1
  112. package/dist/assets/{vennDiagram-T6HMQDX7-B1piFYrz.js → vennDiagram-T6HMQDX7-CNe6zorb.js} +1 -1
  113. package/dist/assets/{vennDiagram-T6HMQDX7-x8SJTFhK.js → vennDiagram-T6HMQDX7-DyzOWKx3.js} +1 -1
  114. package/dist/assets/{wardleyDiagram-T6FBY63Y-BdD4GExj.js → wardleyDiagram-T6FBY63Y-D5YvMVwa.js} +1 -1
  115. package/dist/assets/{wardleyDiagram-T6FBY63Y-C90xqNVS.js → wardleyDiagram-T6FBY63Y-DXo8BCrA.js} +1 -1
  116. package/dist/assets/{xychartDiagram-ELKLHX3M--Ndoz0Cq.js → xychartDiagram-ELKLHX3M-CIBffVxC.js} +1 -1
  117. package/dist/assets/{xychartDiagram-ELKLHX3M-BAKns-7o.js → xychartDiagram-ELKLHX3M-XlsWelDb.js} +1 -1
  118. package/dist/build-info.json +2 -2
  119. package/dist/convert-icons.md +10 -46
  120. package/dist/favicon.png +0 -0
  121. package/dist/favicon.svg +1 -9
  122. package/dist/generate-icons.js +67 -47
  123. package/dist/icons/icon-128x128.png +0 -0
  124. package/dist/icons/icon-144x144.png +0 -0
  125. package/dist/icons/icon-152x152.png +0 -0
  126. package/dist/icons/icon-192x192.png +0 -0
  127. package/dist/icons/icon-384x384.png +0 -0
  128. package/dist/icons/icon-512x512.png +0 -0
  129. package/dist/icons/icon-72x72.png +0 -0
  130. package/dist/icons/icon-96x96.png +0 -0
  131. package/dist/index.html +2 -2
  132. package/dist/logo-128.png +0 -0
  133. package/dist/logo-256.png +0 -0
  134. package/dist/logo-32.png +0 -0
  135. package/dist/logo-512.png +0 -0
  136. package/dist/logo-64.png +0 -0
  137. package/dist/logo-source.png +0 -0
  138. package/dist/logo.svg +1 -17
  139. package/dist/sw.js +7 -9
  140. package/dist-server/build-info.json +2 -2
  141. package/dist-server/server/load-env.js +12 -4
  142. package/dist-server/server/load-env.js.map +1 -1
  143. package/dist-server/server/modules/browser-use/browser-use.service.js +33 -11
  144. package/dist-server/server/modules/browser-use/browser-use.service.js.map +1 -1
  145. package/dist-server/server/modules/browser-use/index.js +4 -4
  146. package/dist-server/server/modules/browser-use/index.js.map +1 -1
  147. package/dist-server/server/modules/browser-use/mcp-server-names.js +6 -4
  148. package/dist-server/server/modules/browser-use/mcp-server-names.js.map +1 -1
  149. package/dist-server/server/modules/browser-use/tests/browser-use.service.test.js +49 -1
  150. package/dist-server/server/modules/browser-use/tests/browser-use.service.test.js.map +1 -1
  151. package/dist-server/server/modules/cli/asset-migration-files.js +74 -0
  152. package/dist-server/server/modules/cli/asset-migration-files.js.map +1 -0
  153. package/dist-server/server/modules/cli/asset-migration-report.js +80 -0
  154. package/dist-server/server/modules/cli/asset-migration-report.js.map +1 -0
  155. package/dist-server/server/modules/cli/asset-migration-store.js +153 -0
  156. package/dist-server/server/modules/cli/asset-migration-store.js.map +1 -0
  157. package/dist-server/server/modules/cli/asset-migration.service.js +161 -0
  158. package/dist-server/server/modules/cli/asset-migration.service.js.map +1 -0
  159. package/dist-server/server/modules/cli/browser-use-mcp.js +9 -4
  160. package/dist-server/server/modules/cli/browser-use-mcp.js.map +1 -1
  161. package/dist-server/server/modules/cli/cli.module.js +21 -1
  162. package/dist-server/server/modules/cli/cli.module.js.map +1 -1
  163. package/dist-server/server/modules/cli/cli.service.js +6 -1
  164. package/dist-server/server/modules/cli/cli.service.js.map +1 -1
  165. package/dist-server/server/modules/cli/tests/asset-migration.service.test.js +275 -0
  166. package/dist-server/server/modules/cli/tests/asset-migration.service.test.js.map +1 -0
  167. package/dist-server/server/modules/cli/tests/browser-use-mcp-entry.test.js +157 -0
  168. package/dist-server/server/modules/cli/tests/browser-use-mcp-entry.test.js.map +1 -1
  169. package/dist-server/server/modules/cli/tests/cli-environment-bootstrap.test.js +1 -0
  170. package/dist-server/server/modules/cli/tests/cli-environment-bootstrap.test.js.map +1 -1
  171. package/dist-server/server/modules/cli/tests/cli.service.test.js +6 -1
  172. package/dist-server/server/modules/cli/tests/cli.service.test.js.map +1 -1
  173. package/dist-server/server/modules/cockpit/cockpit-brief-prompt.js +1 -1
  174. package/dist-server/server/modules/cockpit/cockpit-card-actions.js +19 -3
  175. package/dist-server/server/modules/cockpit/cockpit-card-actions.js.map +1 -1
  176. package/dist-server/server/modules/cockpit/cockpit-card-feedback-store.js +94 -9
  177. package/dist-server/server/modules/cockpit/cockpit-card-feedback-store.js.map +1 -1
  178. package/dist-server/server/modules/cockpit/cockpit-card-registry.js +1 -1
  179. package/dist-server/server/modules/cockpit/cockpit-fleet-card-projection.js +3 -0
  180. package/dist-server/server/modules/cockpit/cockpit-fleet-card-projection.js.map +1 -1
  181. package/dist-server/server/modules/cockpit/cockpit-knowledge-reading.js +16 -0
  182. package/dist-server/server/modules/cockpit/cockpit-knowledge-reading.js.map +1 -1
  183. package/dist-server/server/modules/cockpit/cockpit.module.js +1 -1
  184. package/dist-server/server/modules/cockpit/tests/cockpit-card-feedback.test.js +96 -1
  185. package/dist-server/server/modules/cockpit/tests/cockpit-card-feedback.test.js.map +1 -1
  186. package/dist-server/server/modules/cockpit/tests/cockpit-fleet-card-provider.test.js +2 -2
  187. package/dist-server/server/modules/cockpit/tests/cockpit-knowledge-decision-handoff.test.js +169 -3
  188. package/dist-server/server/modules/cockpit/tests/cockpit-knowledge-decision-handoff.test.js.map +1 -1
  189. package/dist-server/server/modules/context-events/context-event-writer.js +5 -5
  190. package/dist-server/server/modules/context-events/context-events.module.js +2 -2
  191. package/dist-server/server/modules/context-events/session-ask-stream-reader.js +1 -1
  192. package/dist-server/server/modules/context-events/session-blocked-events.js +3 -3
  193. package/dist-server/server/modules/context-events/tests/session-ask-event-writer.test.js +1 -1
  194. package/dist-server/server/modules/context-events/tests/session-blocked-events.test.js +3 -3
  195. package/dist-server/server/modules/context-events/tests/session-run-events.test.js +1 -1
  196. package/dist-server/server/modules/database/migrations.js +23 -1
  197. package/dist-server/server/modules/database/migrations.js.map +1 -1
  198. package/dist-server/server/modules/database/repositories/sessions.db.js +25 -4
  199. package/dist-server/server/modules/database/repositories/sessions.db.js.map +1 -1
  200. package/dist-server/server/modules/database/repositories/voice-user-identifiers.db.js +1 -1
  201. package/dist-server/server/modules/database/schema.js +16 -2
  202. package/dist-server/server/modules/database/schema.js.map +1 -1
  203. package/dist-server/server/modules/database/tests/migrations-ensure-columns.test.js +2 -0
  204. package/dist-server/server/modules/database/tests/migrations-ensure-columns.test.js.map +1 -1
  205. package/dist-server/server/modules/database/tests/sessions-provider-mapping.test.js +2 -2
  206. package/dist-server/server/modules/debug-agent/tests/debug-agent-permission-popup.test.js +2 -2
  207. package/dist-server/server/modules/liaison/liaison-deliver.service.js +3 -3
  208. package/dist-server/server/modules/liaison/liaison.module.js +1 -1
  209. package/dist-server/server/modules/mcp-gateway/mcp-gateway.auth.js +3 -2
  210. package/dist-server/server/modules/mcp-gateway/mcp-gateway.auth.js.map +1 -1
  211. package/dist-server/server/modules/mcp-gateway/mcp-self-target.js +2 -2
  212. package/dist-server/server/modules/mcp-gateway/mcp-session-send.js +7 -0
  213. package/dist-server/server/modules/mcp-gateway/mcp-session-send.js.map +1 -1
  214. package/dist-server/server/modules/mcp-gateway/mcp-tool-annotations.js +4 -4
  215. package/dist-server/server/modules/mcp-gateway/oauth-metadata.gate.js +4 -2
  216. package/dist-server/server/modules/mcp-gateway/oauth-metadata.gate.js.map +1 -1
  217. package/dist-server/server/modules/mcp-gateway/tests/knowledge-effective-config-proof.test.js +1 -1
  218. package/dist-server/server/modules/mcp-gateway/tests/knowledge-peer-correlation-proof.test.js +2 -2
  219. package/dist-server/server/modules/mcp-gateway/tests/mcp-approvals.test.js +3 -2
  220. package/dist-server/server/modules/mcp-gateway/tests/mcp-approvals.test.js.map +1 -1
  221. package/dist-server/server/modules/mcp-gateway/tests/mcp-audit-route.test.js +1 -1
  222. package/dist-server/server/modules/mcp-gateway/tests/mcp-audit.test.js +4 -4
  223. package/dist-server/server/modules/mcp-gateway/tests/mcp-auth.test.js +3 -1
  224. package/dist-server/server/modules/mcp-gateway/tests/mcp-auth.test.js.map +1 -1
  225. package/dist-server/server/modules/mcp-gateway/tests/mcp-cancel-queued.test.js +3 -2
  226. package/dist-server/server/modules/mcp-gateway/tests/mcp-cancel-queued.test.js.map +1 -1
  227. package/dist-server/server/modules/mcp-gateway/tests/mcp-cockpit-tools.test.js +7 -3
  228. package/dist-server/server/modules/mcp-gateway/tests/mcp-cockpit-tools.test.js.map +1 -1
  229. package/dist-server/server/modules/mcp-gateway/tests/mcp-correlation-id.test.js +8 -8
  230. package/dist-server/server/modules/mcp-gateway/tests/mcp-draft.test.js +3 -2
  231. package/dist-server/server/modules/mcp-gateway/tests/mcp-draft.test.js.map +1 -1
  232. package/dist-server/server/modules/mcp-gateway/tests/mcp-english-only.test.js +1 -1
  233. package/dist-server/server/modules/mcp-gateway/tests/mcp-gateway-wiring.test.js +2 -2
  234. package/dist-server/server/modules/mcp-gateway/tests/mcp-insufficient-scope.test.js +1 -1
  235. package/dist-server/server/modules/mcp-gateway/tests/mcp-insufficient-scope.test.js.map +1 -1
  236. package/dist-server/server/modules/mcp-gateway/tests/mcp-knowledge-facts.test.js +1 -1
  237. package/dist-server/server/modules/mcp-gateway/tests/mcp-not-found-semantics.test.js +1 -1
  238. package/dist-server/server/modules/mcp-gateway/tests/mcp-not-found-semantics.test.js.map +1 -1
  239. package/dist-server/server/modules/mcp-gateway/tests/mcp-oauth-challenge.test.js +3 -2
  240. package/dist-server/server/modules/mcp-gateway/tests/mcp-oauth-challenge.test.js.map +1 -1
  241. package/dist-server/server/modules/mcp-gateway/tests/mcp-overview.test.js +2 -2
  242. package/dist-server/server/modules/mcp-gateway/tests/mcp-pending-interaction.test.js +2 -2
  243. package/dist-server/server/modules/mcp-gateway/tests/mcp-read-tools.test.js +3 -3
  244. package/dist-server/server/modules/mcp-gateway/tests/mcp-read-tools.test.js.map +1 -1
  245. package/dist-server/server/modules/mcp-gateway/tests/mcp-run-get.test.js +1 -1
  246. package/dist-server/server/modules/mcp-gateway/tests/mcp-self-target.test.js +1 -1
  247. package/dist-server/server/modules/mcp-gateway/tests/mcp-self-target.test.js.map +1 -1
  248. package/dist-server/server/modules/mcp-gateway/tests/mcp-session-background.test.js +2 -2
  249. package/dist-server/server/modules/mcp-gateway/tests/mcp-session-background.test.js.map +1 -1
  250. package/dist-server/server/modules/mcp-gateway/tests/mcp-session-host-control.test.js +1 -1
  251. package/dist-server/server/modules/mcp-gateway/tests/mcp-session-host-control.test.js.map +1 -1
  252. package/dist-server/server/modules/mcp-gateway/tests/mcp-session-lifecycle.test.js +1 -1
  253. package/dist-server/server/modules/mcp-gateway/tests/mcp-session-lifecycle.test.js.map +1 -1
  254. package/dist-server/server/modules/mcp-gateway/tests/mcp-session-reconfigure.test.js +2 -2
  255. package/dist-server/server/modules/mcp-gateway/tests/mcp-session-reconfigure.test.js.map +1 -1
  256. package/dist-server/server/modules/mcp-gateway/tests/mcp-session-search-pruning.test.js +1 -1
  257. package/dist-server/server/modules/mcp-gateway/tests/mcp-session-search.test.js +1 -1
  258. package/dist-server/server/modules/mcp-gateway/tests/mcp-session-send.test.js +2 -2
  259. package/dist-server/server/modules/mcp-gateway/tests/mcp-session-send.test.js.map +1 -1
  260. package/dist-server/server/modules/mcp-gateway/tests/mcp-ui-last-opened.test.js +1 -1
  261. package/dist-server/server/modules/mcp-gateway/tests/mcp-usage-stats.test.js +1 -1
  262. package/dist-server/server/modules/mcp-gateway/tests/mcp-usage-stats.test.js.map +1 -1
  263. package/dist-server/server/modules/mcp-gateway/tests/mcp-write-notification.test.js +2 -2
  264. package/dist-server/server/modules/mcp-gateway/tests/mcp-write-notification.test.js.map +1 -1
  265. package/dist-server/server/modules/mcp-gateway/tests/oauth-flow.e2e.test.js +3 -3
  266. package/dist-server/server/modules/notifications/services/notification-orchestrator.service.js +1 -1
  267. package/dist-server/server/modules/oauth/access-tokens.service.js +8 -8
  268. package/dist-server/server/modules/oauth/oauth-consent.service.js +20 -15
  269. package/dist-server/server/modules/oauth/oauth-consent.service.js.map +1 -1
  270. package/dist-server/server/modules/oauth/tests/access-token-scopes.test.js +54 -34
  271. package/dist-server/server/modules/oauth/tests/access-token-scopes.test.js.map +1 -1
  272. package/dist-server/server/modules/oauth/tests/access-tokens.service.test.js +35 -14
  273. package/dist-server/server/modules/oauth/tests/access-tokens.service.test.js.map +1 -1
  274. package/dist-server/server/modules/oauth/tests/oauth-consent-page.test.js +27 -22
  275. package/dist-server/server/modules/oauth/tests/oauth-consent-page.test.js.map +1 -1
  276. package/dist-server/server/modules/oauth/tests/oauth-consent-ratelimit.test.js +2 -2
  277. package/dist-server/server/modules/oauth/tests/token-info.routes.test.js +2 -2
  278. package/dist-server/server/modules/oauth/tests/token-info.routes.test.js.map +1 -1
  279. package/dist-server/server/modules/observation/blind-spots.js +1 -1
  280. package/dist-server/server/modules/observation/observation-store.js +50 -17
  281. package/dist-server/server/modules/observation/observation-store.js.map +1 -1
  282. package/dist-server/server/modules/observation/observation-uri.js +31 -19
  283. package/dist-server/server/modules/observation/observation-uri.js.map +1 -1
  284. package/dist-server/server/modules/observation/observation.routes.js +1 -1
  285. package/dist-server/server/modules/observation/project-truth.js +1 -1
  286. package/dist-server/server/modules/observation/session-ask-decision-answer.js +2 -1
  287. package/dist-server/server/modules/observation/session-ask-decision-answer.js.map +1 -1
  288. package/dist-server/server/modules/observation/session-digest-llm.js +7 -1
  289. package/dist-server/server/modules/observation/session-digest-llm.js.map +1 -1
  290. package/dist-server/server/modules/observation/session-digest.js +39 -5
  291. package/dist-server/server/modules/observation/session-digest.js.map +1 -1
  292. package/dist-server/server/modules/observation/tests/architecture-delta.test.js +1 -1
  293. package/dist-server/server/modules/observation/tests/observation-routes.test.js +9 -0
  294. package/dist-server/server/modules/observation/tests/observation-routes.test.js.map +1 -1
  295. package/dist-server/server/modules/observation/tests/observation-store.test.js +38 -0
  296. package/dist-server/server/modules/observation/tests/observation-store.test.js.map +1 -1
  297. package/dist-server/server/modules/observation/tests/project-truth.test.js +2 -2
  298. package/dist-server/server/modules/observation/tests/session-ask-decision-digest.test.js +150 -0
  299. package/dist-server/server/modules/observation/tests/session-ask-decision-digest.test.js.map +1 -1
  300. package/dist-server/server/modules/observation/tests/session-digest.test.js +24 -1
  301. package/dist-server/server/modules/observation/tests/session-digest.test.js.map +1 -1
  302. package/dist-server/server/modules/providers/index.js +9 -0
  303. package/dist-server/server/modules/providers/index.js.map +1 -1
  304. package/dist-server/server/modules/providers/list/claude/claude-host-driver.provider.js +1 -1
  305. package/dist-server/server/modules/providers/list/codex/codex-app-server.client.js +22 -3
  306. package/dist-server/server/modules/providers/list/codex/codex-app-server.client.js.map +1 -1
  307. package/dist-server/server/modules/providers/list/codex/codex-app-server.connection.js +1 -1
  308. package/dist-server/server/modules/providers/list/codex/codex-host-driver.contract.js +11 -9
  309. package/dist-server/server/modules/providers/list/codex/codex-host-driver.contract.js.map +1 -1
  310. package/dist-server/server/modules/providers/list/codex/codex-host-driver.provider.js +15 -1
  311. package/dist-server/server/modules/providers/list/codex/codex-host-driver.provider.js.map +1 -1
  312. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js +14 -3
  313. package/dist-server/server/modules/providers/list/codex/codex-models.provider.js.map +1 -1
  314. package/dist-server/server/modules/providers/list/codex/codex-provider-injection.js +248 -0
  315. package/dist-server/server/modules/providers/list/codex/codex-provider-injection.js.map +1 -0
  316. package/dist-server/server/modules/providers/list/codex/codex-resident-provider-launch.js +37 -0
  317. package/dist-server/server/modules/providers/list/codex/codex-resident-provider-launch.js.map +1 -0
  318. package/dist-server/server/modules/providers/list/codex/codex-runtime.provider.js +19 -1
  319. package/dist-server/server/modules/providers/list/codex/codex-runtime.provider.js.map +1 -1
  320. package/dist-server/server/modules/providers/list/cursor/cursor-models.provider.js +1 -1
  321. package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js +1 -1
  322. package/dist-server/server/modules/providers/provider.routes.js +23 -2
  323. package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
  324. package/dist-server/server/modules/providers/services/provider-models.service.js +136 -106
  325. package/dist-server/server/modules/providers/services/provider-models.service.js.map +1 -1
  326. package/dist-server/server/modules/providers/services/provider-runtime.service.js +3 -0
  327. package/dist-server/server/modules/providers/services/provider-runtime.service.js.map +1 -1
  328. package/dist-server/server/modules/providers/services/session-model-resolver.js +106 -0
  329. package/dist-server/server/modules/providers/services/session-model-resolver.js.map +1 -0
  330. package/dist-server/server/modules/providers/services/session-provider-binding.js +89 -0
  331. package/dist-server/server/modules/providers/services/session-provider-binding.js.map +1 -0
  332. package/dist-server/server/modules/providers/services/sessions.service.js +5 -1
  333. package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -1
  334. package/dist-server/server/modules/providers/tests/claude-resident-addressable.test.js +2 -2
  335. package/dist-server/server/modules/providers/tests/claude-session-name-authority.test.js +4 -4
  336. package/dist-server/server/modules/providers/tests/codex-app-server-protocol.test.js +1 -1
  337. package/dist-server/server/modules/providers/tests/codex-host-driver-persistent.test.js +2 -2
  338. package/dist-server/server/modules/providers/tests/codex-provider-model-binding.test.js +270 -0
  339. package/dist-server/server/modules/providers/tests/codex-provider-model-binding.test.js.map +1 -0
  340. package/dist-server/server/modules/providers/tests/codex-resident-provider-injection.test.js +484 -0
  341. package/dist-server/server/modules/providers/tests/codex-resident-provider-injection.test.js.map +1 -0
  342. package/dist-server/server/modules/providers/tests/codex-runtime-provider-injection.test.js +228 -0
  343. package/dist-server/server/modules/providers/tests/codex-runtime-provider-injection.test.js.map +1 -0
  344. package/dist-server/server/modules/providers/tests/codex-session-provider-binding.test.js +306 -0
  345. package/dist-server/server/modules/providers/tests/codex-session-provider-binding.test.js.map +1 -0
  346. package/dist-server/server/modules/providers/tests/codex-sessions.test.js +1 -1
  347. package/dist-server/server/modules/providers/tests/opencode-sessions.test.js +2 -2
  348. package/dist-server/server/modules/providers/tests/provider-models.service.test.js +15 -0
  349. package/dist-server/server/modules/providers/tests/provider-models.service.test.js.map +1 -1
  350. package/dist-server/server/modules/providers/tests/provider.routes.test.js +1 -1
  351. package/dist-server/server/modules/quay/index.js +1 -1
  352. package/dist-server/server/modules/quay/quay-fleet-cli.js +1 -1
  353. package/dist-server/server/modules/quay/quay-fleet-locator.js +2 -2
  354. package/dist-server/server/modules/quay/quay-fleet-project-id.js +7 -7
  355. package/dist-server/server/modules/quay/quay-fleet-registry.js +3 -3
  356. package/dist-server/server/modules/quay/quay-suite-fanin-reader.js +1 -1
  357. package/dist-server/server/modules/quay/quay-uri-resolve.js +6 -6
  358. package/dist-server/server/modules/quay/quay.module.js +3 -3
  359. package/dist-server/server/modules/quay/quay.routes.js +1 -1
  360. package/dist-server/server/modules/quay/quay.service.js +4 -4
  361. package/dist-server/server/modules/quay/tests/contracts/fleet-cli-contracts.test.js +3 -3
  362. package/dist-server/server/modules/quay/tests/contracts/shapes.js +9 -9
  363. package/dist-server/server/modules/quay/tests/quay-fleet-locator.test.js +1 -1
  364. package/dist-server/server/modules/quay/tests/quay-fleet-project-id.test.js +4 -4
  365. package/dist-server/server/modules/quay/tests/quay-uri-resolve.test.js +10 -10
  366. package/dist-server/server/modules/session-hosts/tests/resident-server-restart.test.js +1 -1
  367. package/dist-server/server/modules/settings/codex-mcp-gateway.settings.js +1 -1
  368. package/dist-server/server/modules/settings/codex-model-providers.schema.js +349 -0
  369. package/dist-server/server/modules/settings/codex-model-providers.schema.js.map +1 -0
  370. package/dist-server/server/modules/settings/codex-model-providers.service.js +199 -0
  371. package/dist-server/server/modules/settings/codex-model-providers.service.js.map +1 -0
  372. package/dist-server/server/modules/settings/codex-model-providers.settings.js +547 -0
  373. package/dist-server/server/modules/settings/codex-model-providers.settings.js.map +1 -0
  374. package/dist-server/server/modules/settings/codex-model-providers.store.js +200 -0
  375. package/dist-server/server/modules/settings/codex-model-providers.store.js.map +1 -0
  376. package/dist-server/server/modules/settings/index.js +10 -0
  377. package/dist-server/server/modules/settings/index.js.map +1 -1
  378. package/dist-server/server/modules/settings/server-settings-file.js +28 -32
  379. package/dist-server/server/modules/settings/server-settings-file.js.map +1 -1
  380. package/dist-server/server/modules/settings/server-settings.js +2 -2
  381. package/dist-server/server/modules/settings/server-settings.js.map +1 -1
  382. package/dist-server/server/modules/settings/settings.module.js +35 -0
  383. package/dist-server/server/modules/settings/settings.module.js.map +1 -1
  384. package/dist-server/server/modules/settings/settings.routes.js +42 -0
  385. package/dist-server/server/modules/settings/settings.routes.js.map +1 -1
  386. package/dist-server/server/modules/settings/settings.service.js +8 -21
  387. package/dist-server/server/modules/settings/settings.service.js.map +1 -1
  388. package/dist-server/server/modules/settings/tests/cockpit-session-start-settings.routes.test.js +1 -0
  389. package/dist-server/server/modules/settings/tests/cockpit-session-start-settings.routes.test.js.map +1 -1
  390. package/dist-server/server/modules/settings/tests/codex-model-providers-settings.test.js +336 -0
  391. package/dist-server/server/modules/settings/tests/codex-model-providers-settings.test.js.map +1 -0
  392. package/dist-server/server/modules/settings/tests/codex-provider-advanced.test.js +466 -0
  393. package/dist-server/server/modules/settings/tests/codex-provider-advanced.test.js.map +1 -0
  394. package/dist-server/server/modules/settings/tests/codex-provider-import.test.js +475 -0
  395. package/dist-server/server/modules/settings/tests/codex-provider-import.test.js.map +1 -0
  396. package/dist-server/server/modules/voice/tests/voice-lexicon.test.js +9 -9
  397. package/dist-server/server/modules/voice/tests/voice-lexicon.test.js.map +1 -1
  398. package/dist-server/server/modules/voice/voice-lexicon.js +1 -1
  399. package/dist-server/server/modules/websocket/services/chat-control.service.js +21 -1
  400. package/dist-server/server/modules/websocket/services/chat-control.service.js.map +1 -1
  401. package/dist-server/server/modules/websocket/services/chat-websocket.service.js +25 -1
  402. package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -1
  403. package/dist-server/server/modules/websocket/tests/chat-background-task.test.js +18 -1
  404. package/dist-server/server/modules/websocket/tests/chat-background-task.test.js.map +1 -1
  405. package/dist-server/server/modules/websocket/tests/chat-stop-task.test.js +18 -1
  406. package/dist-server/server/modules/websocket/tests/chat-stop-task.test.js.map +1 -1
  407. package/dist-server/server/modules/worktrees/services/worktree-list.service.js +1 -1
  408. package/dist-server/server/modules/worktrees/services/worktree-open.service.js +1 -1
  409. package/dist-server/server/modules/worktrees/services/worktree-remove.service.js +1 -1
  410. package/dist-server/server/shared/brand.js +18 -20
  411. package/dist-server/server/shared/brand.js.map +1 -1
  412. package/dist-server/server/shared/data-root-migration.js +3 -2
  413. package/dist-server/server/shared/data-root-migration.js.map +1 -1
  414. package/dist-server/server/shared/data-root.js +54 -59
  415. package/dist-server/server/shared/data-root.js.map +1 -1
  416. package/dist-server/server/shared/mcp-contract/types.js +20 -15
  417. package/dist-server/server/shared/mcp-contract/types.js.map +1 -1
  418. package/dist-server/server/shared/ports/codex-provider-registry.port.js +66 -0
  419. package/dist-server/server/shared/ports/codex-provider-registry.port.js.map +1 -0
  420. package/dist-server/server/shared/settings-file.js +120 -6
  421. package/dist-server/server/shared/settings-file.js.map +1 -1
  422. package/dist-server/server/shared/tests/cloudpit-brand-env.test.js +76 -34
  423. package/dist-server/server/shared/tests/cloudpit-brand-env.test.js.map +1 -1
  424. package/dist-server/server/shared/tests/cloudpit-data-root.test.js +35 -18
  425. package/dist-server/server/shared/tests/cloudpit-data-root.test.js.map +1 -1
  426. package/dist-server/server/shared/tests/cloudpit-goal-exit-gate.test.js +153 -17
  427. package/dist-server/server/shared/tests/cloudpit-goal-exit-gate.test.js.map +1 -1
  428. package/dist-server/server/shared/tests/cloudpit-runtime-flip.test.js +116 -114
  429. package/dist-server/server/shared/tests/cloudpit-runtime-flip.test.js.map +1 -1
  430. package/dist-server/server/shared/tests/frontend-import-cycle-budget.test.js +9 -1
  431. package/dist-server/server/shared/tests/frontend-import-cycle-budget.test.js.map +1 -1
  432. package/dist-server/server/shared/tests/quay-test-script.test.js +40 -6
  433. package/dist-server/server/shared/tests/quay-test-script.test.js.map +1 -1
  434. package/dist-server/server/shared/tests/settings-file.test.js +58 -2
  435. package/dist-server/server/shared/tests/settings-file.test.js.map +1 -1
  436. package/dist-server/server/shared/types.js.map +1 -1
  437. package/dist-server/server/shared/utils.js +1 -1
  438. package/electron/appIdMigration.js +467 -0
  439. package/electron/assets/logo-macos.icns +0 -0
  440. package/electron/assets/logo-macos.png +0 -0
  441. package/electron/assets/logo-windows.ico +0 -0
  442. package/electron/brandEnv.js +64 -0
  443. package/electron/cloud.js +3 -3
  444. package/electron/desktopNotifications.js +1 -1
  445. package/electron/launcher/index.html +1 -1
  446. package/electron/localServer.js +41 -7
  447. package/electron/main.js +33 -15
  448. package/electron/scripts/generate-macos-icon.js +34 -28
  449. package/electron/scripts/generate-windows-icon.js +66 -0
  450. package/electron/serverInstaller.js +20 -11
  451. package/electron/tests/cloudpit-appid-migration.test.mjs +514 -0
  452. package/electron/tests/cloudpit-brand-env-wiring.test.mjs +324 -0
  453. package/electron/tests/cloudpit-desktop-identity.test.mjs +42 -19
  454. package/electron/tests/cloudpit-runtime-identity-surfaces.test.mjs +10 -4
  455. package/electron/tests/cloudpit-userdata-migration.test.mjs +18 -5
  456. package/electron/userDataMigration.js +3 -0
  457. package/package.json +7 -6
  458. package/public/api-docs.html +3 -3
  459. package/scripts/brand-allowlist-check.mjs +233 -12
  460. package/scripts/brand-allowlist-check.test.mjs +270 -1
  461. package/scripts/cloudpit-distribution-check.mjs +57 -23
  462. package/scripts/cloudpit-distribution-check.test.mjs +42 -9
  463. package/scripts/codex-protocol-smoke.mjs +1 -1
  464. package/scripts/isolated-instance.sh +1 -1
  465. package/scripts/mcp-smoke.mjs +2 -2
  466. package/scripts/release/tests/fork-release-workflows.test.mjs +45 -0
  467. package/scripts/release/tests/server-installer-bundle-url.test.mjs +57 -9
  468. package/scripts/restart-when-idle.sh +1 -1
  469. package/scripts/shadow-prediction-report.mjs +1 -1
  470. package/scripts/suite-duration-baseline.tsv +45 -0
  471. package/scripts/ui-scenario.mjs +195 -0
  472. package/scripts/ui-scenarios/codex-provider-import.json +63 -0
  473. package/scripts/ui-scenarios/codex-provider-settings.json +77 -0
  474. package/scripts/voice-capture-process-check.false-forms.test.mjs +1 -1
  475. package/scripts/voice-phase0-report.test.mjs +1 -1
  476. package/server/load-env.ts +15 -4
  477. package/server/modules/browser-use/browser-use.service.ts +45 -14
  478. package/server/modules/browser-use/index.ts +3 -4
  479. package/server/modules/browser-use/mcp-server-names.ts +6 -5
  480. package/server/modules/browser-use/tests/browser-use.service.test.ts +63 -1
  481. package/server/modules/cli/asset-migration-files.ts +96 -0
  482. package/server/modules/cli/asset-migration-report.ts +123 -0
  483. package/server/modules/cli/asset-migration-store.ts +228 -0
  484. package/server/modules/cli/asset-migration.service.ts +236 -0
  485. package/server/modules/cli/browser-use-mcp.ts +9 -4
  486. package/server/modules/cli/cli.module.ts +21 -1
  487. package/server/modules/cli/cli.service.ts +14 -1
  488. package/server/modules/cli/tests/asset-migration.service.test.ts +349 -0
  489. package/server/modules/cli/tests/browser-use-mcp-entry.test.ts +202 -0
  490. package/server/modules/cli/tests/cli-environment-bootstrap.test.ts +1 -0
  491. package/server/modules/cli/tests/cli.service.test.ts +6 -1
  492. package/server/modules/cockpit/cockpit-brief-prompt.ts +1 -1
  493. package/server/modules/cockpit/cockpit-card-actions.ts +20 -3
  494. package/server/modules/cockpit/cockpit-card-feedback-store.ts +104 -9
  495. package/server/modules/cockpit/cockpit-card-registry.ts +2 -2
  496. package/server/modules/cockpit/cockpit-fleet-card-projection.ts +3 -0
  497. package/server/modules/cockpit/cockpit-fleet-executor.ts +1 -1
  498. package/server/modules/cockpit/cockpit-knowledge-reading.ts +17 -0
  499. package/server/modules/cockpit/cockpit.module.ts +2 -2
  500. package/server/modules/cockpit/cockpit.reducer.ts +1 -1
  501. package/server/modules/cockpit/tests/cockpit-card-feedback.test.ts +116 -1
  502. package/server/modules/cockpit/tests/cockpit-fleet-card-provider.test.ts +2 -2
  503. package/server/modules/cockpit/tests/cockpit-knowledge-decision-handoff.test.ts +205 -3
  504. package/server/modules/context-events/context-event-writer.ts +6 -6
  505. package/server/modules/context-events/context-events.module.ts +2 -2
  506. package/server/modules/context-events/session-ask-stream-reader.ts +1 -1
  507. package/server/modules/context-events/session-blocked-events.ts +3 -3
  508. package/server/modules/context-events/tests/session-ask-event-writer.test.ts +1 -1
  509. package/server/modules/context-events/tests/session-blocked-events.test.ts +3 -3
  510. package/server/modules/context-events/tests/session-run-events.test.ts +1 -1
  511. package/server/modules/database/migrations.ts +24 -1
  512. package/server/modules/database/repositories/sessions.db.ts +41 -4
  513. package/server/modules/database/repositories/voice-user-identifiers.db.ts +1 -1
  514. package/server/modules/database/schema.ts +16 -2
  515. package/server/modules/database/tests/migrations-ensure-columns.test.ts +2 -0
  516. package/server/modules/database/tests/sessions-provider-mapping.test.ts +2 -2
  517. package/server/modules/debug-agent/tests/debug-agent-permission-popup.test.ts +2 -2
  518. package/server/modules/liaison/liaison-deliver.service.ts +4 -4
  519. package/server/modules/liaison/liaison.module.ts +1 -1
  520. package/server/modules/mcp-gateway/mcp-gateway.auth.ts +3 -2
  521. package/server/modules/mcp-gateway/mcp-self-target.ts +2 -2
  522. package/server/modules/mcp-gateway/mcp-session-send.ts +21 -2
  523. package/server/modules/mcp-gateway/mcp-tool-annotations.ts +4 -4
  524. package/server/modules/mcp-gateway/oauth-metadata.gate.ts +4 -5
  525. package/server/modules/mcp-gateway/tests/knowledge-effective-config-proof.test.ts +1 -1
  526. package/server/modules/mcp-gateway/tests/knowledge-peer-correlation-proof.test.ts +2 -2
  527. package/server/modules/mcp-gateway/tests/mcp-approvals.test.ts +3 -2
  528. package/server/modules/mcp-gateway/tests/mcp-audit-route.test.ts +1 -1
  529. package/server/modules/mcp-gateway/tests/mcp-audit.test.ts +4 -4
  530. package/server/modules/mcp-gateway/tests/mcp-auth.test.ts +3 -1
  531. package/server/modules/mcp-gateway/tests/mcp-cancel-queued.test.ts +3 -2
  532. package/server/modules/mcp-gateway/tests/mcp-cockpit-tools.test.ts +7 -3
  533. package/server/modules/mcp-gateway/tests/mcp-correlation-id.test.ts +8 -8
  534. package/server/modules/mcp-gateway/tests/mcp-draft.test.ts +3 -2
  535. package/server/modules/mcp-gateway/tests/mcp-english-only.test.ts +1 -1
  536. package/server/modules/mcp-gateway/tests/mcp-gateway-wiring.test.ts +2 -2
  537. package/server/modules/mcp-gateway/tests/mcp-insufficient-scope.test.ts +1 -1
  538. package/server/modules/mcp-gateway/tests/mcp-knowledge-facts.test.ts +1 -1
  539. package/server/modules/mcp-gateway/tests/mcp-not-found-semantics.test.ts +1 -1
  540. package/server/modules/mcp-gateway/tests/mcp-oauth-challenge.test.ts +3 -2
  541. package/server/modules/mcp-gateway/tests/mcp-overview.test.ts +2 -2
  542. package/server/modules/mcp-gateway/tests/mcp-pending-interaction.test.ts +2 -2
  543. package/server/modules/mcp-gateway/tests/mcp-read-tools.test.ts +3 -3
  544. package/server/modules/mcp-gateway/tests/mcp-run-get.test.ts +1 -1
  545. package/server/modules/mcp-gateway/tests/mcp-self-target.test.ts +1 -1
  546. package/server/modules/mcp-gateway/tests/mcp-session-background.test.ts +2 -2
  547. package/server/modules/mcp-gateway/tests/mcp-session-host-control.test.ts +1 -1
  548. package/server/modules/mcp-gateway/tests/mcp-session-lifecycle.test.ts +1 -1
  549. package/server/modules/mcp-gateway/tests/mcp-session-reconfigure.test.ts +2 -2
  550. package/server/modules/mcp-gateway/tests/mcp-session-search-pruning.test.ts +1 -1
  551. package/server/modules/mcp-gateway/tests/mcp-session-search.test.ts +1 -1
  552. package/server/modules/mcp-gateway/tests/mcp-session-send.test.ts +2 -2
  553. package/server/modules/mcp-gateway/tests/mcp-ui-last-opened.test.ts +1 -1
  554. package/server/modules/mcp-gateway/tests/mcp-usage-stats.test.ts +1 -1
  555. package/server/modules/mcp-gateway/tests/mcp-write-notification.test.ts +2 -2
  556. package/server/modules/mcp-gateway/tests/oauth-flow.e2e.test.ts +3 -3
  557. package/server/modules/notifications/services/notification-orchestrator.service.js +1 -1
  558. package/server/modules/oauth/access-tokens.service.ts +8 -8
  559. package/server/modules/oauth/oauth-consent.service.ts +20 -15
  560. package/server/modules/oauth/tests/access-token-scopes.test.ts +55 -34
  561. package/server/modules/oauth/tests/access-tokens.service.test.ts +50 -14
  562. package/server/modules/oauth/tests/oauth-consent-page.test.ts +29 -21
  563. package/server/modules/oauth/tests/oauth-consent-ratelimit.test.ts +2 -2
  564. package/server/modules/oauth/tests/token-info.routes.test.ts +2 -2
  565. package/server/modules/observation/architecture-delta.producer.ts +1 -1
  566. package/server/modules/observation/blind-spots.ts +1 -1
  567. package/server/modules/observation/observation-store.ts +54 -16
  568. package/server/modules/observation/observation-uri.ts +34 -21
  569. package/server/modules/observation/observation.routes.ts +1 -1
  570. package/server/modules/observation/project-truth.ts +3 -3
  571. package/server/modules/observation/session-ask-decision-answer.ts +2 -1
  572. package/server/modules/observation/session-digest-llm.ts +7 -1
  573. package/server/modules/observation/session-digest.ts +39 -5
  574. package/server/modules/observation/tests/architecture-delta.test.ts +1 -1
  575. package/server/modules/observation/tests/observation-routes.test.ts +13 -0
  576. package/server/modules/observation/tests/observation-store.test.ts +58 -0
  577. package/server/modules/observation/tests/project-truth.test.ts +2 -2
  578. package/server/modules/observation/tests/session-ask-decision-digest.test.ts +189 -0
  579. package/server/modules/observation/tests/session-digest.test.ts +43 -0
  580. package/server/modules/providers/index.ts +13 -0
  581. package/server/modules/providers/list/claude/claude-host-driver.provider.ts +1 -1
  582. package/server/modules/providers/list/codex/codex-app-server.client.ts +37 -5
  583. package/server/modules/providers/list/codex/codex-app-server.connection.ts +1 -1
  584. package/server/modules/providers/list/codex/codex-host-driver.contract.ts +18 -9
  585. package/server/modules/providers/list/codex/codex-host-driver.provider.ts +15 -1
  586. package/server/modules/providers/list/codex/codex-models.provider.ts +16 -3
  587. package/server/modules/providers/list/codex/codex-provider-injection.ts +323 -0
  588. package/server/modules/providers/list/codex/codex-resident-provider-launch.ts +71 -0
  589. package/server/modules/providers/list/codex/codex-runtime.provider.ts +20 -1
  590. package/server/modules/providers/list/cursor/cursor-models.provider.ts +1 -1
  591. package/server/modules/providers/list/opencode/opencode-models.provider.ts +1 -1
  592. package/server/modules/providers/provider.routes.ts +23 -2
  593. package/server/modules/providers/services/provider-models.service.ts +187 -124
  594. package/server/modules/providers/services/provider-runtime.service.ts +3 -0
  595. package/server/modules/providers/services/session-model-resolver.ts +180 -0
  596. package/server/modules/providers/services/session-provider-binding.ts +176 -0
  597. package/server/modules/providers/services/sessions.service.ts +5 -1
  598. package/server/modules/providers/tests/claude-resident-addressable.test.ts +2 -2
  599. package/server/modules/providers/tests/claude-session-name-authority.test.ts +4 -4
  600. package/server/modules/providers/tests/codex-app-server-protocol.test.ts +1 -1
  601. package/server/modules/providers/tests/codex-host-driver-persistent.test.ts +2 -2
  602. package/server/modules/providers/tests/codex-provider-model-binding.test.ts +345 -0
  603. package/server/modules/providers/tests/codex-resident-provider-injection.test.ts +561 -0
  604. package/server/modules/providers/tests/codex-runtime-provider-injection.test.ts +269 -0
  605. package/server/modules/providers/tests/codex-session-provider-binding.test.ts +386 -0
  606. package/server/modules/providers/tests/codex-sessions.test.ts +1 -1
  607. package/server/modules/providers/tests/opencode-sessions.test.ts +2 -2
  608. package/server/modules/providers/tests/provider-models.service.test.ts +15 -0
  609. package/server/modules/providers/tests/provider.routes.test.ts +1 -1
  610. package/server/modules/quay/index.ts +1 -1
  611. package/server/modules/quay/quay-dispatch-carrier.ts +1 -1
  612. package/server/modules/quay/quay-fleet-cli.ts +1 -1
  613. package/server/modules/quay/quay-fleet-locator.ts +2 -2
  614. package/server/modules/quay/quay-fleet-project-id.ts +14 -14
  615. package/server/modules/quay/quay-fleet-registry.ts +8 -8
  616. package/server/modules/quay/quay-suite-fanin-reader.ts +1 -1
  617. package/server/modules/quay/quay-uri-resolve.ts +8 -8
  618. package/server/modules/quay/quay.module.ts +3 -3
  619. package/server/modules/quay/quay.routes.ts +1 -1
  620. package/server/modules/quay/quay.service.ts +6 -6
  621. package/server/modules/quay/session-task-chain.service.ts +1 -1
  622. package/server/modules/quay/tests/contracts/fleet-cli-contracts.test.ts +3 -3
  623. package/server/modules/quay/tests/contracts/shapes.ts +10 -10
  624. package/server/modules/quay/tests/quay-fleet-locator.test.ts +1 -1
  625. package/server/modules/quay/tests/quay-fleet-project-id.test.ts +6 -6
  626. package/server/modules/quay/tests/quay-uri-resolve.test.ts +10 -10
  627. package/server/modules/session-hosts/tests/resident-server-restart.test.ts +1 -1
  628. package/server/modules/settings/codex-mcp-gateway.settings.ts +1 -1
  629. package/server/modules/settings/codex-model-providers.schema.ts +460 -0
  630. package/server/modules/settings/codex-model-providers.service.ts +235 -0
  631. package/server/modules/settings/codex-model-providers.settings.ts +713 -0
  632. package/server/modules/settings/codex-model-providers.store.ts +244 -0
  633. package/server/modules/settings/index.ts +18 -0
  634. package/server/modules/settings/server-settings-file.ts +29 -41
  635. package/server/modules/settings/server-settings.ts +2 -3
  636. package/server/modules/settings/settings.module.ts +41 -0
  637. package/server/modules/settings/settings.routes.ts +37 -0
  638. package/server/modules/settings/settings.service.ts +21 -26
  639. package/server/modules/settings/tests/cockpit-session-start-settings.routes.test.ts +1 -0
  640. package/server/modules/settings/tests/codex-model-providers-settings.test.ts +413 -0
  641. package/server/modules/settings/tests/codex-provider-advanced.test.ts +540 -0
  642. package/server/modules/settings/tests/codex-provider-import.test.ts +621 -0
  643. package/server/modules/voice/tests/voice-lexicon.test.ts +10 -10
  644. package/server/modules/voice/voice-lexicon.ts +1 -1
  645. package/server/modules/websocket/services/chat-control.service.ts +35 -2
  646. package/server/modules/websocket/services/chat-websocket.service.ts +25 -1
  647. package/server/modules/websocket/tests/chat-background-task.test.ts +17 -1
  648. package/server/modules/websocket/tests/chat-stop-task.test.ts +17 -1
  649. package/server/modules/worktrees/services/worktree-list.service.ts +1 -1
  650. package/server/modules/worktrees/services/worktree-open.service.ts +1 -1
  651. package/server/modules/worktrees/services/worktree-remove.service.ts +1 -1
  652. package/server/shared/brand.ts +24 -38
  653. package/server/shared/data-root-migration.ts +3 -2
  654. package/server/shared/data-root.ts +73 -79
  655. package/server/shared/interfaces.ts +1 -1
  656. package/server/shared/mcp-contract/types.ts +20 -15
  657. package/server/shared/ports/codex-provider-registry.port.ts +133 -0
  658. package/server/shared/ports/session-blocked-events.port.ts +1 -1
  659. package/server/shared/ports/session-run-events.port.ts +2 -2
  660. package/server/shared/settings-file.ts +167 -6
  661. package/server/shared/tests/architecture-ratchet.baseline.json +15 -15
  662. package/server/shared/tests/cloudpit-brand-env.test.ts +106 -36
  663. package/server/shared/tests/cloudpit-data-root.test.ts +42 -18
  664. package/server/shared/tests/cloudpit-goal-exit-gate.baseline.json +6 -2
  665. package/server/shared/tests/cloudpit-goal-exit-gate.test.ts +179 -17
  666. package/server/shared/tests/cloudpit-runtime-flip.test.ts +162 -123
  667. package/server/shared/tests/frontend-import-cycle-budget.baseline.json +8 -6
  668. package/server/shared/tests/frontend-import-cycle-budget.test.ts +9 -1
  669. package/server/shared/tests/quay-test-script.test.ts +40 -6
  670. package/server/shared/tests/settings-file.test.ts +83 -1
  671. package/server/shared/types.ts +121 -8
  672. package/server/shared/utils.ts +1 -1
  673. package/dist/assets/channel-D7XqNTJC.js +0 -1
  674. package/dist/assets/channel-sbQyI1an.js +0 -1
  675. package/dist/assets/classDiagram-JCYQIIEL-DHudi-zH.js +0 -1
  676. package/dist/assets/classDiagram-JCYQIIEL-DV7ybJJG.js +0 -1
  677. package/dist/assets/classDiagram-v2-OCEON4UE-DHudi-zH.js +0 -1
  678. package/dist/assets/classDiagram-v2-OCEON4UE-DV7ybJJG.js +0 -1
  679. package/dist/assets/index-BsACp0s2.css +0 -32
  680. package/dist/assets/swimlanesDiagram-ULZ7WXOC-CNMNp6YA.js +0 -8
  681. package/dist/assets/swimlanesDiagram-ULZ7WXOC-DOjtDEUW.js +0 -8
  682. package/dist/icons/icon-128x128.svg +0 -12
  683. package/dist/icons/icon-144x144.svg +0 -12
  684. package/dist/icons/icon-152x152.svg +0 -12
  685. package/dist/icons/icon-192x192.svg +0 -12
  686. package/dist/icons/icon-384x384.svg +0 -12
  687. package/dist/icons/icon-512x512.svg +0 -12
  688. package/dist/icons/icon-72x72.svg +0 -12
  689. package/dist/icons/icon-96x96.svg +0 -12
  690. package/dist/icons/icon-template.svg +0 -12
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Filesystem I/O for the project-owned Codex provider settings file and its per-provider
3
+ * secret files.
4
+ *
5
+ * WHY A FILE OF ITS OWN. `codex.settings.json` is the project's one writable surface for
6
+ * upstream Codex providers. The schema and validation live in
7
+ * `codex-model-providers.settings.ts`; this sibling owns only the bytes: resolving the
8
+ * path, hashing the content version a concurrent editor must send back, the atomic replace,
9
+ * and the `600` token files. Splitting the concern keeps both files under the module
10
+ * standard's line ceiling and lets a criterion drive the file layer without a route.
11
+ *
12
+ * THE PROJECT FILE IS THE ONLY WRITE TARGET. A user `~/.codex/config.toml` is never written:
13
+ * it is read-only compatibility, and an import binds into this project file instead.
14
+ *
15
+ * SECRETS NEVER ENTER THE JSON. `tokenFile` is a path. `readTokenSecret` is the only reader
16
+ * and its value is handed to a caller in memory; `writeTokenSecret` exists so the settings
17
+ * API can accept a secret without persisting it in the document. Every write here creates the
18
+ * file (or replaces it) with mode `600`.
19
+ */
20
+ import { createHash } from 'node:crypto';
21
+ import { readFileSync, statSync } from 'node:fs';
22
+ import os from 'node:os';
23
+ import path from 'node:path';
24
+
25
+ import {
26
+ expandHome,
27
+ resolveSettingsPath,
28
+ writeSettingsFileAtomically,
29
+ } from '@/shared/settings-file.js';
30
+ import { AppError, errorMessage, isRecord } from '@/shared/utils.js';
31
+
32
+ /** The only environment entry: it names the project Codex settings file. */
33
+ export const CODEX_SETTINGS_PATH_ENV = 'CODEX_SETTINGS_PATH';
34
+
35
+ /** The deployment's default location; a development checkout points the env entry at `config/`. */
36
+ export function defaultCodexSettingsPath(homeDir: string): string {
37
+ return path.join(homeDir, '.config', 'cloudpit', 'codex.settings.json');
38
+ }
39
+
40
+ /** The file this process reads and writes. `explicit` is true when an operator named it. */
41
+ export type CodexSettingsFileTarget = {
42
+ path: string;
43
+ explicit: boolean;
44
+ };
45
+
46
+ /**
47
+ * Resolves the Codex settings file: an explicit path, then `CODEX_SETTINGS_PATH`, then the
48
+ * shipped location. Consumers: the settings module (the production source) and the criterion.
49
+ */
50
+ export function resolveCodexSettingsFileTarget(
51
+ options: {
52
+ settingsPath?: string | null;
53
+ env?: Record<string, string | undefined>;
54
+ homeDir?: string | undefined;
55
+ } = {},
56
+ ): CodexSettingsFileTarget {
57
+ const homeDir = options.homeDir ?? os.homedir();
58
+ const { filePath, explicit } = resolveSettingsPath({
59
+ settingsPath: options.settingsPath,
60
+ env: options.env ?? process.env,
61
+ envVar: CODEX_SETTINGS_PATH_ENV,
62
+ homeDir,
63
+ defaultPath: defaultCodexSettingsPath,
64
+ });
65
+ return { path: filePath ?? defaultCodexSettingsPath(homeDir), explicit };
66
+ }
67
+
68
+ /** The version reported for a file that does not exist yet (a first write creates it). */
69
+ export const MISSING_CODEX_SETTINGS_VERSION = 'missing';
70
+
71
+ /** One raw read: the parsed document, its content hash, and whether the file was present. */
72
+ export type CodexSettingsDocumentReading = {
73
+ document: Record<string, unknown>;
74
+ version: string;
75
+ exists: boolean;
76
+ };
77
+
78
+ /** A content hash, so a stale editor can be told the file moved under it. */
79
+ function versionOf(text: string): string {
80
+ return createHash('sha256').update(text).digest('hex');
81
+ }
82
+
83
+ /**
84
+ * Reads the project file. A missing file is the ordinary "no providers yet" state; an
85
+ * unreadable or malformed one is a visible error, never silently treated as empty.
86
+ *
87
+ * Consumers: `codex-model-providers.settings.ts` (read, resolve and the version check).
88
+ */
89
+ export function readCodexSettingsDocument(filePath: string): CodexSettingsDocumentReading {
90
+ let text: string;
91
+ try {
92
+ text = readFileSync(filePath, 'utf8');
93
+ } catch (failure) {
94
+ if ((failure as NodeJS.ErrnoException | null)?.code === 'ENOENT') {
95
+ return { document: {}, version: MISSING_CODEX_SETTINGS_VERSION, exists: false };
96
+ }
97
+ throw new AppError(`could not read ${filePath}: ${errorMessage(failure)}`, {
98
+ code: 'CODEX_SETTINGS_READ_FAILED',
99
+ statusCode: 500,
100
+ });
101
+ }
102
+
103
+ let parsed: unknown;
104
+ try {
105
+ parsed = JSON.parse(text);
106
+ } catch (failure) {
107
+ throw new AppError(`${filePath} is not valid JSON: ${errorMessage(failure)}`, {
108
+ code: 'CODEX_SETTINGS_INVALID_JSON',
109
+ statusCode: 500,
110
+ });
111
+ }
112
+ if (!isRecord(parsed)) {
113
+ throw new AppError(`${filePath} must contain a JSON object`, {
114
+ code: 'CODEX_SETTINGS_INVALID_JSON',
115
+ statusCode: 500,
116
+ });
117
+ }
118
+ return { document: parsed, version: versionOf(text), exists: true };
119
+ }
120
+
121
+ /**
122
+ * Replaces the project file with `document` after proving the caller edited the version it
123
+ * read. The replace is atomic and always mode `600`, even when the previous file was wider,
124
+ * because this document describes credentials (paths and env names) and the task's contract
125
+ * is a 0600 project file.
126
+ *
127
+ * Consumers: `codex-model-providers.settings.ts`'s write path.
128
+ */
129
+ export function writeCodexSettingsDocument(
130
+ filePath: string,
131
+ document: Record<string, unknown>,
132
+ options: { expectedVersion: string; versionPath?: string | undefined },
133
+ ): { version: string } {
134
+ const sourcePath = options.versionPath ?? filePath;
135
+ const current = readCodexSettingsDocument(sourcePath);
136
+ if (current.version !== options.expectedVersion) {
137
+ throw new AppError('The Codex provider settings changed since they were read; reload and save again.', {
138
+ code: 'VERSION_CONFLICT',
139
+ statusCode: 409,
140
+ details: { expectedVersion: options.expectedVersion, currentVersion: current.version },
141
+ });
142
+ }
143
+
144
+ const serialized = `${JSON.stringify(document, null, 2)}\n`;
145
+ try {
146
+ writeSettingsFileAtomically(filePath, serialized, { mode: 0o600 });
147
+ } catch (failure) {
148
+ throw new AppError(`could not write ${filePath}: ${errorMessage(failure)}`, {
149
+ code: 'CODEX_SETTINGS_WRITE_FAILED',
150
+ statusCode: 500,
151
+ });
152
+ }
153
+ return { version: versionOf(serialized) };
154
+ }
155
+
156
+ /**
157
+ * Resolves a provider's secret path. An operator-written `tokenFile` wins (a leading `~` is
158
+ * expanded and a relative path is resolved against the settings file's directory); otherwise
159
+ * every provider gets its own file under `<settings dir>/codex.secrets/<id>.token`.
160
+ *
161
+ * Consumers: `codex-model-providers.settings.ts`'s read/resolve/write paths.
162
+ */
163
+ export function resolveCodexTokenFilePath(
164
+ settingsPath: string,
165
+ providerId: string,
166
+ rawTokenFile: string,
167
+ homeDir: string,
168
+ ): string {
169
+ const trimmed = rawTokenFile.trim();
170
+ if (trimmed !== '') {
171
+ const expanded = expandHome(trimmed, homeDir);
172
+ return path.isAbsolute(expanded)
173
+ ? expanded
174
+ : path.resolve(path.dirname(settingsPath), expanded);
175
+ }
176
+ return path.join(path.dirname(settingsPath), 'codex.secrets', `${providerId}.token`);
177
+ }
178
+
179
+ /** What one secret-file read observed: the value, or a line naming why it is unusable. */
180
+ export type CodexTokenSecretReading =
181
+ | { ok: true; secret: string }
182
+ | { ok: false; problem: string };
183
+
184
+ /**
185
+ * Reads one `600` token file. A missing or empty file is a readable "no secret" answer, not a
186
+ * throw: the runtime must be able to say why a provider cannot launch. The value never
187
+ * appears in the returned text.
188
+ *
189
+ * Consumers: `codex-model-providers.settings.ts`'s `read`/`resolve`.
190
+ */
191
+ export function readCodexTokenSecret(tokenFile: string): CodexTokenSecretReading {
192
+ let secret: string;
193
+ try {
194
+ secret = readFileSync(tokenFile, 'utf8').trim();
195
+ } catch (failure) {
196
+ const code = (failure as NodeJS.ErrnoException | null)?.code;
197
+ return {
198
+ ok: false,
199
+ problem: code === 'ENOENT'
200
+ ? `token file ${tokenFile} is missing`
201
+ : `could not read token file ${tokenFile}: ${errorMessage(failure)}`,
202
+ };
203
+ }
204
+ if (secret === '') {
205
+ return { ok: false, problem: `token file ${tokenFile} is empty` };
206
+ }
207
+ return { ok: true, secret };
208
+ }
209
+
210
+ /**
211
+ * Writes a secret into its token file, atomically and mode `600`. Used only when the settings
212
+ * API is handed a write-only `token`; the value is never placed in the project document.
213
+ *
214
+ * Consumers: `codex-model-providers.settings.ts`'s write path.
215
+ */
216
+ export function writeCodexTokenSecret(tokenFile: string, secret: string): void {
217
+ try {
218
+ writeSettingsFileAtomically(tokenFile, secret, { mode: 0o600 });
219
+ } catch (failure) {
220
+ throw new AppError(`could not write token file ${tokenFile}: ${errorMessage(failure)}`, {
221
+ code: 'CODEX_TOKEN_WRITE_FAILED',
222
+ statusCode: 500,
223
+ });
224
+ }
225
+ }
226
+
227
+ /**
228
+ * Reports (never throws) whether a token file is wider than `600`. The runtime tolerates a
229
+ * wide file — refusing it would turn a permissions typo into a dead provider — but the reading
230
+ * names the problem so an operator can fix it.
231
+ *
232
+ * Consumers: `codex-model-providers.settings.ts` (per-provider warnings).
233
+ */
234
+ export function tokenFileModeWarning(tokenFile: string): string | null {
235
+ try {
236
+ const mode = statSync(tokenFile).mode & 0o777;
237
+ if ((mode & 0o077) !== 0) {
238
+ return `token file ${tokenFile} has mode ${mode.toString(8)}; 600 is expected because it holds a secret`;
239
+ }
240
+ } catch {
241
+ // The read path already reports a missing file with its own, more useful message.
242
+ }
243
+ return null;
244
+ }
@@ -42,6 +42,24 @@ export type {
42
42
  ServerSettings,
43
43
  } from './server-settings.js';
44
44
  export type { CodexMcpGatewaySettings } from './codex-mcp-gateway.settings.js';
45
+ // createCodexModelProvidersSource / CodexModelProvidersSource: the project-owned Codex upstream
46
+ // provider registry (`~/.config/cloudpit/codex.settings.json`). The settings API writes through
47
+ // the one instance `settings.module.ts` owns; the resident/per-run Codex injection tasks create
48
+ // their own source over the same file and call `resolve(id)` AT SPAWN TIME (reads are uncached),
49
+ // so an edit reaches the next launch without a restart.
50
+ export {
51
+ createCodexModelProvidersSource,
52
+ type CodexModelProviderResolution,
53
+ type CodexModelProvidersSource,
54
+ type ResolvedCodexModelProvider,
55
+ } from './codex-model-providers.settings.js';
56
+ // The registry's own vocabulary, exported so a sibling task names the same reserved ids and the
57
+ // same one accepted wire dialect instead of restating them.
58
+ export {
59
+ CODEX_PROVIDER_WIRE_API,
60
+ RESERVED_CODEX_PROVIDER_IDS,
61
+ } from './codex-model-providers.schema.js';
62
+ export { CODEX_SETTINGS_PATH_ENV } from './codex-model-providers.store.js';
45
63
  // readCockpitSessionStartBoot / resolveServerSettingsFileTarget: the dual read/write target the
46
64
  // cockpit session-start settings use when the legacy file is the source. Exported so the
47
65
  // Cloudpit runtime criterion can drive the legacy-read → Cloudpit-write contract over a temp home.
@@ -21,22 +21,15 @@
21
21
  * top-level key and every other `cockpit`/`sessionStart` field, and committed by writing a
22
22
  * sibling temp file and renaming it over the target, so a reader never observes a half file.
23
23
  */
24
- import { createHash, randomUUID } from 'node:crypto';
25
- import {
26
- existsSync,
27
- mkdirSync,
28
- readFileSync,
29
- renameSync,
30
- rmSync,
31
- statSync,
32
- writeFileSync,
33
- } from 'node:fs';
24
+ import { createHash } from 'node:crypto';
25
+ import { existsSync, readFileSync } from 'node:fs';
34
26
  import { homedir } from 'node:os';
35
- import path from 'node:path';
36
27
 
37
28
  import {
38
29
  defaultServerSettingsPath as defaultServerSettingsPathForHome,
39
30
  legacyServerSettingsPath,
31
+ migrateLegacyServerSettingsFile,
32
+ writeSettingsFileAtomically,
40
33
  } from '@/shared/settings-file.js';
41
34
  import { AppError, errorMessage, isRecord } from '@/shared/utils.js';
42
35
 
@@ -67,10 +60,11 @@ export function defaultServerSettingsPath(): string {
67
60
  * Resolves the file the boot reader and the settings API share. Same order as
68
61
  * `loadServerSettings`: an explicit path > `SERVER_SETTINGS_PATH` > the shipped location.
69
62
  *
70
- * The shipped location is now `<home>/.config/cloudpit/server.settings.json`. When that file does
71
- * not exist yet but the legacy `<home>/.config/claudecodeui/server.settings.json` does, the READ
72
- * falls back to the legacy file while `writePath` stays on the Cloudpit default: an upgrade keeps
73
- * its effective configuration and the next save lands in the new tree, never back in the old one.
63
+ * The shipped location is `<home>/.config/cloudpit/server.settings.json`. v3.0 deleted the
64
+ * runtime read fallback to `<home>/.config/claudecodeui/server.settings.json`: on the first
65
+ * resolution the legacy file is COPIED to the Cloudpit path once (never overwriting an existing
66
+ * Cloudpit file), and every read afterwards uses only the Cloudpit file. `path` and `writePath`
67
+ * are therefore always the same for the default target, and a save lands in the new tree.
74
68
  *
75
69
  * Consumers: `server-settings.ts` (the boot read) and `settings.module.ts` (the API's target).
76
70
  */
@@ -78,7 +72,6 @@ export function resolveServerSettingsFileTarget(options: {
78
72
  settingsPath?: string | undefined;
79
73
  env?: Record<string, string | undefined>;
80
74
  defaultPath?: string | undefined;
81
- legacyDefaultPath?: string | undefined;
82
75
  homeDir?: string | undefined;
83
76
  exists?: ((filePath: string) => boolean) | undefined;
84
77
  } = {}): ServerSettingsFileTarget {
@@ -93,12 +86,19 @@ export function resolveServerSettingsFileTarget(options: {
93
86
  }
94
87
 
95
88
  const defaultPath = options.defaultPath ?? defaultServerSettingsPathForHome(homeDir);
96
- // An injected defaultPath without an injected legacy path is a hermetic caller: do not consult
97
- // the process HOME behind its back.
98
- const legacyDefaultPath = options.legacyDefaultPath
99
- ?? (options.defaultPath === undefined ? legacyServerSettingsPath(homeDir) : defaultPath);
100
- const path_ = exists(defaultPath) || !exists(legacyDefaultPath) ? defaultPath : legacyDefaultPath;
101
- return { path: path_, writePath: defaultPath, explicit: false };
89
+ // One-time upgrade aid: copy the pre-flip file into the Cloudpit tree when the latter is
90
+ // absent. The legacy file is never read again after this and is left on disk.
91
+ // An INJECTED defaultPath marks a hermetic caller (the criteria drive an arbitrary temp file);
92
+ // it must not consult the process HOME behind its back, so migration runs only for the shipped
93
+ // default derived from `homeDir`.
94
+ if (options.defaultPath === undefined) {
95
+ migrateLegacyServerSettingsFile({
96
+ legacyPath: legacyServerSettingsPath(homeDir),
97
+ targetPath: defaultPath,
98
+ exists,
99
+ });
100
+ }
101
+ return { path: defaultPath, writePath: defaultPath, explicit: false };
102
102
  }
103
103
 
104
104
  /**
@@ -293,30 +293,18 @@ function createSerialQueue(): { run<T>(operation: () => T): Promise<T> } {
293
293
 
294
294
  const cockpitSessionStartWrites = createSerialQueue();
295
295
 
296
- /** Writes a sibling temp file and renames it over the target, so no reader sees a half file. */
297
- function writeAtomically(filePath: string, contents: string, replacing: boolean): void {
298
- const directory = path.dirname(filePath);
299
- const temporary = path.join(
300
- directory,
301
- `.${path.basename(filePath)}.${process.pid}.${randomUUID()}.tmp`,
302
- );
296
+ /**
297
+ * Writes the document through the shared atomic replace, wrapping a filesystem failure in this
298
+ * module's own error code. An existing file keeps its mode; a new one is created `0600`.
299
+ */
300
+ function writeAtomically(filePath: string, contents: string): void {
303
301
  try {
304
- mkdirSync(directory, { recursive: true });
305
- const mode = replacing ? statSync(filePath).mode & 0o777 : 0o600;
306
- writeFileSync(temporary, contents, { encoding: 'utf8', mode });
307
- renameSync(temporary, filePath);
302
+ writeSettingsFileAtomically(filePath, contents);
308
303
  } catch (failure) {
309
304
  throw new AppError(`could not write ${filePath}: ${errorMessage(failure)}`, {
310
305
  code: 'SERVER_SETTINGS_WRITE_FAILED',
311
306
  statusCode: 500,
312
307
  });
313
- } finally {
314
- // The rename consumed the temp name on success; this removes it only after a failed write.
315
- try {
316
- rmSync(temporary, { force: true });
317
- } catch {
318
- // A leftover temp file is not a reason to hide the write's own error.
319
- }
320
308
  }
321
309
  }
322
310
 
@@ -377,7 +365,7 @@ export function writeCockpitSessionStart(
377
365
  document.cockpit = cockpit;
378
366
 
379
367
  const serialized = `${JSON.stringify(document, null, 2)}\n`;
380
- writeAtomically(filePath, serialized, existsSync(filePath));
368
+ writeAtomically(filePath, serialized);
381
369
  return { path: filePath, ...savedFieldsOf(document), version: versionOf(serialized) };
382
370
  });
383
371
  }
@@ -303,7 +303,6 @@ type ServerSettingsFileOptions = {
303
303
  settingsPath?: string | undefined;
304
304
  env?: Record<string, string | undefined>;
305
305
  defaultPath?: string | undefined;
306
- legacyDefaultPath?: string | undefined;
307
306
  homeDir?: string | undefined;
308
307
  exists?: ((filePath: string) => boolean) | undefined;
309
308
  };
@@ -312,8 +311,8 @@ export function loadServerSettings(options: ServerSettingsFileOptions = {}): Ser
312
311
  const target = resolveServerSettingsFileTarget(options);
313
312
  const reading = readServerSettings(options, target);
314
313
  // The ONE boot read becomes the "currently in effect" reading the settings API reports, so
315
- // the surface and the card `session.start` executor cannot disagree about this process;
316
- // `writePath` stays on the Cloudpit default even when the reading came from the legacy file.
314
+ // the surface and the card `session.start` executor cannot disagree about this process.
315
+ // v3.0 removed the legacy read fallback, so `path` and `writePath` are the same default file.
317
316
  recordCockpitSessionStartBoot(reading.path, reading.cockpit.sessionStart, target.writePath);
318
317
  return reading;
319
318
  }
@@ -1,3 +1,5 @@
1
+ import os from 'node:os';
2
+
1
3
  import {
2
4
  accessTokensDb,
3
5
  credentialsDb,
@@ -18,9 +20,15 @@ import {
18
20
  notifyUserIfEnabled,
19
21
  } from '@/modules/notifications/index.js';
20
22
  import { createAccessTokensService } from '@/modules/oauth/index.js';
23
+ import { installCodexProviderRegistryPort } from '@/shared/ports/codex-provider-registry.port.js';
21
24
 
22
25
  import { createSettingsRouter } from './settings.routes.js';
23
26
  import { createSettingsService } from './settings.service.js';
27
+ import { RESERVED_CODEX_PROVIDER_IDS } from './codex-model-providers.schema.js';
28
+ import {
29
+ createCodexModelProvidersSource,
30
+ readCodexUserProviderImports,
31
+ } from './codex-model-providers.settings.js';
24
32
  import { DEFAULT_COCKPIT_SESSION_START_MODEL } from './server-settings.js';
25
33
  import {
26
34
  readCockpitSessionStart,
@@ -31,6 +39,32 @@ import {
31
39
 
32
40
  const accessTokensService = createAccessTokensService({ now: () => new Date() });
33
41
 
42
+ /**
43
+ * The project-owned Codex provider registry. One instance owns the file path and the write
44
+ * queue; the settings API writes through it and the Codex injection tasks create their own
45
+ * source over the same file (reads are uncached, so both see the latest edit).
46
+ */
47
+ const codexModelProvidersSource = createCodexModelProvidersSource();
48
+
49
+ /**
50
+ * The providers module refuses a model entry's `codexProviderId` unless it names a provider this
51
+ * registry (or Codex's built-in list) knows. It reads that judgement through a shared port rather
52
+ * than importing this module: `providers -> settings` would close the `providers -> settings ->
53
+ * mcp-gateway -> providers` cycle AC-394 pins. Reads are uncached, so a provider saved through
54
+ * the settings API is visible to the very next model write.
55
+ *
56
+ * The same install carries `resolve`, the spawn-time lookup a per-run/resident Codex injection
57
+ * uses to read the endpoint and the token-file secret. It resolves against the live file on every
58
+ * call, so an edit reaches the next launch without a restart.
59
+ */
60
+ installCodexProviderRegistryPort({
61
+ read: () => ({
62
+ providers: codexModelProvidersSource.read().providers.map((provider) => ({ id: provider.id })),
63
+ reservedIds: RESERVED_CODEX_PROVIDER_IDS,
64
+ }),
65
+ resolve: (id) => codexModelProvidersSource.resolve(id),
66
+ });
67
+
34
68
  /**
35
69
  * The two files the cockpit settings page works with: the one THIS boot read, and the one a save
36
70
  * must write. They differ only when the boot read fell back to the legacy settings file — the
@@ -176,6 +210,13 @@ const settingsService = createSettingsService({
176
210
  return boot === null ? null : { model: boot.model, effort: boot.effort };
177
211
  },
178
212
  },
213
+ codexModelProviders: {
214
+ read: () => codexModelProvidersSource.read(),
215
+ write: (input) => codexModelProvidersSource.write(input),
216
+ // The composition root decides WHOSE profile is imported: this process's operator. The read
217
+ // is one-way (the user's TOML files are never written); the bind goes to the project source.
218
+ readUserImports: () => readCodexUserProviderImports({ homeDir: os.homedir(), env: process.env }),
219
+ },
179
220
  });
180
221
 
181
222
  /** Settings router assembled for the authenticated server mount. */
@@ -100,5 +100,42 @@ export function createSettingsRouter(
100
100
  };
101
101
  router.put('/cockpit/session-start', writeCockpitSessionStart(false));
102
102
  router.patch('/cockpit/session-start', writeCockpitSessionStart(true));
103
+
104
+ // The project-owned Codex upstream provider registry. GET reports each provider's fields and
105
+ // only whether its token file holds a secret (`tokenSet`); PUT is a full replacement guarded by
106
+ // the content hash it was based on (`expectedVersion` in the body, or `If-Match`), so a second
107
+ // editor's stale save is a 409 rather than a silent overwrite.
108
+ //
109
+ // The user-profile import lives at a sub-path: GET only READS the operator's `~/.codex` TOML
110
+ // blocks (never a secret value), and POST binds the named rows into the project file, carrying
111
+ // the same version proof as a save so a stale bind cannot overwrite a newer registry.
112
+ router.get('/codex/model-providers/import', respond(() => service.getCodexUserProviderImports()));
113
+ router.post('/codex/model-providers/import', async (req, res, next) => {
114
+ try {
115
+ const header = req.get('if-match');
116
+ const headerVersion = header === undefined
117
+ ? undefined
118
+ : header.replace(/^W\//, '').replace(/^"|"$/g, '');
119
+ const reading = await service.importCodexUserProviders({
120
+ body: req.body,
121
+ headerVersion,
122
+ });
123
+ res.status(200).set('ETag', `"${reading.version}"`).json(reading);
124
+ } catch (error) { next(error); }
125
+ });
126
+ router.get('/codex/model-providers', respond(() => service.getCodexModelProviders()));
127
+ router.put('/codex/model-providers', async (req, res, next) => {
128
+ try {
129
+ const header = req.get('if-match');
130
+ const headerVersion = header === undefined
131
+ ? undefined
132
+ : header.replace(/^W\//, '').replace(/^"|"$/g, '');
133
+ const reading = await service.updateCodexModelProviders({
134
+ body: req.body,
135
+ headerVersion,
136
+ });
137
+ res.status(200).set('ETag', `"${reading.version}"`).json(reading);
138
+ } catch (error) { next(error); }
139
+ });
103
140
  return router;
104
141
  }
@@ -1,7 +1,13 @@
1
1
  import type { McpAuditRouteEntry, McpGatewayGateReading } from '@/modules/mcp-gateway/index.js';
2
2
  import { normalizeAccessTokenScopes } from '@/modules/oauth/index.js';
3
+ import { readExpectedVersion } from '@/shared/settings-file.js';
3
4
  import { AppError } from '@/shared/utils.js';
4
5
 
6
+ import {
7
+ createCodexModelProvidersOperations,
8
+ type CodexModelProvidersPort,
9
+ } from './codex-model-providers.service.js';
10
+
5
11
  type NotificationPreferences = Record<string, unknown> & {
6
12
  channels?: Record<string, unknown> & { webPush?: boolean };
7
13
  };
@@ -133,7 +139,7 @@ type SettingsDependencies = {
133
139
  list(userId: number): StoredOAuthToken[];
134
140
  };
135
141
  /**
136
- * The read-only seams the Settings → API page's CloudCLI MCP block needs.
142
+ * The read-only seams the Settings → API page's Cloudpit MCP block needs.
137
143
  *
138
144
  * Optional so the existing service criteria keep constructing the dependency
139
145
  * object they always have; the module always supplies it (see
@@ -167,6 +173,14 @@ type SettingsDependencies = {
167
173
  * model with the shipped default, so this module never restates it.
168
174
  */
169
175
  cockpitSessionStart?: CockpitSessionStartPort;
176
+ /**
177
+ * The project-owned Codex provider registry (Settings → Agents → Codex).
178
+ *
179
+ * Optional so the existing service criteria keep constructing the dependency object they
180
+ * always have; `settings.module.ts` always supplies it. The operations live in a sibling
181
+ * file so this assembled service does not grow the registry's file and transport rules.
182
+ */
183
+ codexModelProviders?: CodexModelProvidersPort;
170
184
  };
171
185
 
172
186
  /** The only lifetimes a personal access token may request, in days. */
@@ -176,7 +190,7 @@ const ALLOWED_TOKEN_EXPIRY_DAYS: readonly number[] = [7, 30, 90];
176
190
  const DEFAULT_TOKEN_EXPIRY_DAYS = 30;
177
191
 
178
192
  /** Scopes applied when the caller omits them; the read scope is the required baseline. */
179
- const DEFAULT_TOKEN_SCOPES: readonly string[] = ['cloudcli:read'];
193
+ const DEFAULT_TOKEN_SCOPES: readonly string[] = ['cloudpit:read'];
180
194
 
181
195
  /**
182
196
  * Projects a stored row to the client-facing token shape. Written as an
@@ -298,31 +312,12 @@ function readCockpitSessionStartEffort(value: unknown): string {
298
312
  return value.trim();
299
313
  }
300
314
 
301
- /** The version the edit was based on: the body's `expectedVersion`, else the `If-Match` header. */
302
- function readCockpitSessionStartVersion(
303
- body: Record<string, unknown>,
304
- headerVersion: string | undefined,
305
- ): string {
306
- if (body.expectedVersion !== undefined && typeof body.expectedVersion !== 'string') {
307
- throw new AppError('expectedVersion must be a string', {
308
- code: 'INVALID_VERSION',
309
- statusCode: 400,
310
- });
311
- }
312
- const fromBody = typeof body.expectedVersion === 'string' ? body.expectedVersion.trim() : '';
313
- const version = fromBody || (headerVersion ?? '').trim();
314
- if (!version) {
315
- throw new AppError('expectedVersion is required to save', {
316
- code: 'VERSION_REQUIRED',
317
- statusCode: 400,
318
- });
319
- }
320
- return version;
321
- }
322
-
323
315
  /** Creates settings workflows with repositories and notification effects injected. */
324
316
  export function createSettingsService(dependencies: SettingsDependencies) {
325
317
  return {
318
+ // The Codex provider registry's two endpoints are a distinct file-backed concern; they are
319
+ // composed here so `settings.module.ts` still builds one service.
320
+ ...createCodexModelProvidersOperations(dependencies.codexModelProviders),
326
321
  listCredentials(userId: number, credentialType: string | null) {
327
322
  return { credentials: dependencies.credentials.list(userId, credentialType) };
328
323
  },
@@ -459,7 +454,7 @@ export function createSettingsService(dependencies: SettingsDependencies) {
459
454
  return { success: true };
460
455
  },
461
456
  /**
462
- * The Settings → API page's CloudCLI MCP block: whether the gateway is
457
+ * The Settings → API page's Cloudpit MCP block: whether the gateway is
463
458
  * enabled, the path it answers on, and the base url an MCP client should
464
459
  * dial. The gate is read through the mcp-gateway module (the single place
465
460
  * `MCP_ENABLED` is parsed) rather than re-derived here.
@@ -545,7 +540,7 @@ export function createSettingsService(dependencies: SettingsDependencies) {
545
540
  });
546
541
  }
547
542
 
548
- const expectedVersion = readCockpitSessionStartVersion(body, input.headerVersion);
543
+ const expectedVersion = readExpectedVersion(body, input.headerVersion);
549
544
  const saved = await port.write({
550
545
  model,
551
546
  effort: input.partial ? effort : (effort ?? ''),
@@ -318,6 +318,7 @@ test('AC1: real auth rejects anonymous and invalid callers; the GET is an allowl
318
318
  { label: 'non-string model', reply: await harness.put({ model: 42, expectedVersion: version }), code: 'INVALID_MODEL' },
319
319
  { label: 'non-string effort', reply: await harness.patch({ effort: 5, expectedVersion: version }), code: 'INVALID_EFFORT' },
320
320
  { label: 'missing version', reply: await harness.put({ model: 'x' }), code: 'VERSION_REQUIRED' },
321
+ { label: 'non-string version', reply: await harness.put({ model: 'x', expectedVersion: 42 }), code: 'INVALID_VERSION' },
321
322
  { label: 'PUT without a model', reply: await harness.put({ effort: 'high', expectedVersion: version }), code: 'MODEL_REQUIRED' },
322
323
  { label: 'empty PATCH', reply: await harness.patch({ expectedVersion: version }), code: 'NOTHING_TO_UPDATE' },
323
324
  ];