@runeya/runeya 2.0.51 → 2.0.53
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.
- package/agent/index.js +58 -17
- package/agent/index.js.map +1 -1
- package/agent-manager-RGDHYM64.js +7 -0
- package/{chunk-NVKGIBJN.js → chunk-EL75GG7O.js} +338 -117
- package/chunk-EL75GG7O.js.map +1 -0
- package/index.js +1 -1
- package/package.json +1 -1
- package/{src-R6JOPDNL.js → src-4GK5OK3K.js} +1012 -372
- package/src-4GK5OK3K.js.map +1 -0
- package/web/assets/AgentScalarChatInterface.vue-Cz4cGFw_.js +13 -0
- package/web/assets/AgentTerminalPage-ChRcIGvk.js +1 -0
- package/web/assets/AiChatPage-jeAEz3pL.js +1 -0
- package/web/assets/AppLayout-C8-7N9YJ.js +1 -0
- package/web/assets/{AppLayout-D1bdzemo.css → AppLayout-CDh-jiJ3.css} +1 -1
- package/web/assets/AuditPage-DfJlEoaI.js +1 -0
- package/web/assets/CloudAccountPage--6fr9upU.js +1 -0
- package/web/assets/CloudAccountPage-CI6Vvfrv.js +1 -0
- package/web/assets/CloudAccountPage-CVAMkCOF.css +1 -0
- package/web/assets/CloudMessagingPage-CWz2XG-O.js +2 -0
- package/web/assets/DashboardPage-Bkla6ZI9.js +1 -0
- package/web/assets/{EditorIcon-dUXSIPv3.js → EditorIcon-BYTcFJnr.js} +2 -2
- package/web/assets/EnvironmentForm-Tody7LuY.js +108 -0
- package/web/assets/EnvironmentFormPage-r_Hn2SiC.js +1 -0
- package/web/assets/EnvironmentListPage-BPQL4Fdp.js +1 -0
- package/web/assets/EnvironmentSelector-CsXJXDJE.js +1 -0
- package/web/assets/KanbanBoardPage-C2Cj_u1W.js +4 -0
- package/web/assets/KanbanBoardPage-ZIYuV1kG.css +1 -0
- package/web/assets/KanbanListPage-DG04Ci-t.js +1 -0
- package/web/assets/LaunchProjectPage-ZU10tRlq.js +1 -0
- package/web/assets/LaunchServicesPage-rLishQca.js +1 -0
- package/web/assets/LogViewer-DkR3A0v0.js +3 -0
- package/web/assets/{ProcessControls-t9skQ_zd.js → ProcessControls-Dkf-zJF8.js} +1 -1
- package/web/assets/ProcessDetailPage-vDdHOtno.js +1 -0
- package/web/assets/{ProcessMetrics-DL00NyoX.js → ProcessMetrics-BxwLdytO.js} +2 -2
- package/web/assets/ProjectDetailPage-Bu2gDzDU.js +1 -0
- package/web/assets/ProjectListPage-zlXxla_K.js +1 -0
- package/web/assets/RandomJobTestPage-DkxLX-Uy.js +2 -0
- package/web/assets/ScenarioEditorPage-Dlgug19y.js +14 -0
- package/web/assets/SendToChatDialog-BbMjL5KU.js +1 -0
- package/web/assets/ServiceControlsBar-D9mA1wIv.js +1 -0
- package/web/assets/ServiceDetailPage-CPtHs7te.js +2 -0
- package/web/assets/ServiceFormPage-D6zoG4d2.js +1 -0
- package/web/assets/SettingsPage-BL1cbj_d.js +2062 -0
- package/web/assets/{SettingsPage-C9WtnczY.css → SettingsPage-BY3dG-wn.css} +1 -1
- package/web/assets/UnlockPage-tTNE4QTc.js +1 -0
- package/web/assets/VariablesTable-C8UT5LGj.js +1 -0
- package/web/assets/VaultMigrationPage-ee6mGXkE.js +1 -0
- package/web/assets/VersionBadge-XGdKeJYP.js +1 -0
- package/web/assets/WikiPage-DBxWCk1C.js +1 -0
- package/web/assets/WikiView-CtMG-Mpi.js +1 -0
- package/web/assets/{add-scalar-classes-CEf8wgbL.js → add-scalar-classes-CjP6yoH9.js} +26 -26
- package/web/assets/auth-errors-C7Lmr_5E.js +1 -0
- package/web/assets/autocomplete-DLtfuYAg.js +422 -0
- package/web/assets/{basic-shape-diamond.svg-BxBPwaOm.js → basic-shape-diamond.svg-Dwn3EJf7.js} +1 -1
- package/web/assets/{basic-shape-hexagon.svg-Du908vLS.js → basic-shape-hexagon.svg-kpOvfzAi.js} +1 -1
- package/web/assets/{basic-shape-primary-circle-ellipse-round.svg-CfFm5Pl7.js → basic-shape-primary-circle-ellipse-round.svg-CZpeeE8h.js} +1 -1
- package/web/assets/{basic-shape-primary-square-rectangle.svg-CP0kG7Ut.js → basic-shape-primary-square-rectangle.svg-lIzT-3bQ.js} +1 -1
- package/web/assets/{basic-shape-shield.svg-DxTsLdrS.js → basic-shape-shield.svg-DB-n6Wmn.js} +1 -1
- package/web/assets/{browser-DV9-oWjy.js → browser-Dm_lNzZ-.js} +1 -1
- package/web/assets/{browser-BvCyKum4.js → browser-wjfUiObI.js} +1 -1
- package/web/assets/card-C3zlSqpG.js +32 -0
- package/web/assets/{checkbox-D5bej0ao.js → checkbox-lVXx5U1s.js} +3 -3
- package/web/assets/{chip-D8vO8NID.js → chip-Cc40pDDT.js} +2 -2
- package/web/assets/client-CN9LxBfq.js +24 -0
- package/web/assets/cloud-chat.store-CKtcP8mx.js +1 -0
- package/web/assets/{cloud-session-tALRHewK.js → cloud-session-luM5H14C.js} +1 -1
- package/web/assets/column-DlQNKY_S.js +907 -0
- package/web/assets/{computer-device-desktop-monitor.svg-82Glaw7U.js → computer-device-desktop-monitor.svg-B8fVLOqV.js} +1 -1
- package/web/assets/{computer-device-desktop.svg-BZb-XFcK.js → computer-device-desktop.svg-CKeybOQk.js} +1 -1
- package/web/assets/{computer-device-laptop.svg-BnptbmCn.js → computer-device-laptop.svg-C5xV7_Nt.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-android-samsung-back.svg-g23ZYYHm.js → computer-device-mobile-phone-android-samsung-back.svg-5CRKvrQx.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-android-samsung.svg-B5fBZlIN.js → computer-device-mobile-phone-android-samsung.svg-Da4aZrXd.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-iphone-x-back.svg-BsKZAUH_.js → computer-device-mobile-phone-iphone-x-back.svg-D9phyiQZ.js} +1 -1
- package/web/assets/{computer-device-mobile-phone-iphone-x.svg-GVv-OoXC.js → computer-device-mobile-phone-iphone-x.svg-V7yMTZCu.js} +1 -1
- package/web/assets/{computer-device-mobile-tablet-touch.svg-CpyRybCz.js → computer-device-mobile-tablet-touch.svg-CGMdXdex.js} +1 -1
- package/web/assets/{computer-device-mobile-tablet.svg-C_6zzbHC.js → computer-device-mobile-tablet.svg-66hlusLK.js} +1 -1
- package/web/assets/{computer-device-network-ethernet-cat6.svg-s_MRa0bJ.js → computer-device-network-ethernet-cat6.svg-BhuzmqfI.js} +1 -1
- package/web/assets/{computer-device-network-lan-www.svg-31TS3sqT.js → computer-device-network-lan-www.svg-BXLNIvQ6.js} +1 -1
- package/web/assets/{computer-device-network-wifi-connection.svg-BfBnT-iK.js → computer-device-network-wifi-connection.svg-CaVzq_6z.js} +1 -1
- package/web/assets/{computer-device-network-wifi-router.svg-BNQJ_FEI.js → computer-device-network-wifi-router.svg-DasSXsmT.js} +1 -1
- package/web/assets/{cssMode-IplHgA8x.js → cssMode-CokQPPhF.js} +1 -1
- package/web/assets/{divider-D-QC8_57.js → divider-3st3S0cz.js} +2 -2
- package/web/assets/{ecology-science-erlenmeyer-flask.svg-CKCEQFIq.js → ecology-science-erlenmeyer-flask.svg-0xfq6Yyi.js} +1 -1
- package/web/assets/{fieldset-DpQHSMKf.js → fieldset-CvZZBOcz.js} +2 -2
- package/web/assets/{freemarker2-DHUVsWtT.js → freemarker2-1YMoAedE.js} +1 -1
- package/web/assets/{handlebars-pE00Hjr_.js → handlebars-wAW8puhT.js} +1 -1
- package/web/assets/{html-DMtmtVNV.js → html-DdFlw76f.js} +1 -1
- package/web/assets/{htmlMode-DFeVLqUM.js → htmlMode-Cy1vm8Ag.js} +1 -1
- package/web/assets/{image-flash-lightning.svg-NAFI_e2J.js → image-flash-lightning.svg-COFAE0wR.js} +1 -1
- package/web/assets/{image-picture-flower.svg-B6ZUCTNS.js → image-picture-flower.svg-ezqcE4KS.js} +1 -1
- package/web/assets/{index-D7XqcLhE.css → index-CICxLkjp.css} +1 -1
- package/web/assets/{index-a1iwaPG1.js → index-Ccntdgfe.js} +290 -290
- package/web/assets/{interface-alert-exclamation-diamond.svg-CwHTxp3a.js → interface-alert-exclamation-diamond.svg-CHGW-cLp.js} +1 -1
- package/web/assets/{interface-alert-exclamation-triangle-warning.svg-Bi-1vcWG.js → interface-alert-exclamation-triangle-warning.svg-DvPTCqs0.js} +1 -1
- package/web/assets/{interface-alert-information-circle.svg-CQnbLMfS.js → interface-alert-information-circle.svg-jX4BkfAJ.js} +1 -1
- package/web/assets/{interface-award-crown.svg-CFtMz4dE.js → interface-award-crown.svg-DtuQ-cID.js} +1 -1
- package/web/assets/{interface-bookmark.svg-7SV2pxyN.js → interface-bookmark-tag.svg-CAFVyAoV.js} +1 -1
- package/web/assets/{interface-bookmark-tag.svg-DumdjnW1.js → interface-bookmark.svg-BneowIGx.js} +1 -1
- package/web/assets/{interface-calendar-date-one.svg-e7-h1b3y.js → interface-calendar-date-one.svg-CfpOGCx4.js} +1 -1
- package/web/assets/{interface-content-book-open-pages.svg-DwLQV4lf.js → interface-content-book-open-pages.svg-Cl1dxQ4s.js} +1 -1
- package/web/assets/{interface-content-book-page.svg-CAKDQ2x-.js → interface-content-book-page.svg-CEhybPQh.js} +1 -1
- package/web/assets/{interface-content-file.svg-DZEwGNLB.js → interface-content-file.svg-HK08zzYO.js} +1 -1
- package/web/assets/interface-content-folder.svg-BD3Sy4hk.js +1 -0
- package/web/assets/{interface-content-folder.svg-BnFYmNMO.js → interface-content-folder.svg-DuncK7Kw.js} +1 -1
- package/web/assets/{interface-copy-clipboard.svg-9UwhLON-.js → interface-copy-clipboard.svg-CHxj1VUB.js} +1 -1
- package/web/assets/{interface-edit-attachment.svg-C1_u9TNx.js → interface-edit-attachment.svg-DQ-TGp2N.js} +1 -1
- package/web/assets/{interface-edit-binocular.svg-DoQnsqHf.js → interface-edit-binocular.svg-CIUJcI__.js} +1 -1
- package/web/assets/{interface-edit-magic-wand.svg-C7wTd6JH.js → interface-edit-magic-wand.svg-Bn7wsTVd.js} +1 -1
- package/web/assets/{interface-edit-tool-paint-roller.svg-BZ4hqe-1.js → interface-edit-tool-paint-roller.svg-BLR1HoWs.js} +1 -1
- package/web/assets/{interface-edit-tool-pencil.svg-D1bysygW.js → interface-edit-tool-pencil.svg-DM3xZUtj.js} +1 -1
- package/web/assets/{interface-favorite-award.svg-0Thu2k9M.js → interface-favorite-award.svg-Bc8_APGD.js} +1 -1
- package/web/assets/{interface-favorite-flag.svg-DI4_vrUQ.js → interface-favorite-flag.svg-BBV01eyw.js} +1 -1
- package/web/assets/{interface-favorite-heart.svg-DpwKtPuU.js → interface-favorite-heart.svg-DpFl3KSk.js} +1 -1
- package/web/assets/{interface-favorite-star.svg-D-udxHVN.js → interface-favorite-star.svg-CaFUQ9jK.js} +1 -1
- package/web/assets/{interface-favorite-stars-sparkles.svg-Dc4Z9Mjg.js → interface-favorite-stars-sparkles.svg-19cy1b4g.js} +1 -1
- package/web/assets/{interface-hierarchy-flowchart.svg-vfERX-oc.js → interface-hierarchy-flowchart.svg-Btiu5TuK.js} +1 -1
- package/web/assets/{interface-home-house.svg-BY98XY-a.js → interface-home-house.svg-Bp4aVUgs.js} +1 -1
- package/web/assets/{interface-hyperlink.svg-8D6WX1Q9.js → interface-hyperlink.svg-Df34T3Eu.js} +1 -1
- package/web/assets/{interface-lighting-brightness.svg-DUoPpiwx.js → interface-lighting-brightness.svg-CBJnLIw7.js} +1 -1
- package/web/assets/{interface-lock-closed.svg-CzFKU_Z4.js → interface-lock-closed.svg-C082mEtr.js} +1 -1
- package/web/assets/{interface-lock-open-unlock.svg-BnrVx0lo.js → interface-lock-open-unlock.svg-ktQ_lN_X.js} +1 -1
- package/web/assets/{interface-login-key.svg-DAfv-MMA.js → interface-login-key.svg-1JZV_q3n.js} +1 -1
- package/web/assets/{interface-search.svg-Q2hCozQb.js → interface-search.svg-BWOepCe2.js} +1 -1
- package/web/assets/{interface-setting-cog.svg-Bvq0dvZR.js → interface-setting-cog.svg-Ck7-QPf8.js} +1 -1
- package/web/assets/{interface-share-megaphone-bullhorn.svg-fUmta8NQ.js → interface-share-megaphone-bullhorn.svg-B4XWLcvf.js} +1 -1
- package/web/assets/{interface-share-rocket.svg-BKSZkx2r.js → interface-share-rocket.svg-jsXjbfvo.js} +1 -1
- package/web/assets/{interface-share-satellite.svg-CB_uwNHS.js → interface-share-satellite.svg-DYc-pAdI.js} +1 -1
- package/web/assets/{interface-share-space-ship.svg-CcUB1z0B.js → interface-share-space-ship.svg-azKKMF8L.js} +1 -1
- package/web/assets/{interface-share.svg-Bug50vV0.js → interface-share.svg-k0lPxn1t.js} +1 -1
- package/web/assets/{interface-signal-square.svg-zg41vf79.js → interface-signal-square.svg-eCO4ev15.js} +1 -1
- package/web/assets/{interface-time-clock-circle.svg-a4omIVlV.js → interface-time-clock-circle.svg-C0Sm0_j9.js} +1 -1
- package/web/assets/{interface-time-hour-glass.svg-3zmzbQg_.js → interface-time-hour-glass.svg-hfRVIC1r.js} +1 -1
- package/web/assets/{interface-users-multiple.svg-BdPX2m6Y.js → interface-users-multiple.svg-Dm9UimfL.js} +1 -1
- package/web/assets/{interface-weather-moon.svg-D9_m-QTi.js → interface-weather-moon.svg-BhxFHPbN.js} +1 -1
- package/web/assets/{javascript-BJlgvmgy.js → javascript-_AR6wrF0.js} +1 -1
- package/web/assets/{jsonMode-D0zJGMKu.js → jsonMode-CYWBTJpV.js} +2 -2
- package/web/assets/{liquid-B0fONmvZ.js → liquid-Doe_Qoxn.js} +1 -1
- package/web/assets/{lspLanguageFeatures-CrwGD4mx.js → lspLanguageFeatures-TK5k9ahW.js} +2 -2
- package/web/assets/{mail-chat-bubble-square.svg-DZaD3FQ3.js → mail-chat-bubble-square.svg-CitsmxJ_.js} +1 -1
- package/web/assets/{mail-send-email-paper-airplane.svg-DkbRfjXY.js → mail-send-email-paper-airplane.svg-CYDMogt4.js} +1 -1
- package/web/assets/{mail-send-envelope.svg-5c8j8mB_.js → mail-send-envelope.svg-s-A4ytfv.js} +1 -1
- package/web/assets/{mdx-CKW2c2uF.js → mdx-CSf3fjQb.js} +1 -1
- package/web/assets/{message-DZ0RuJXv.js → message-5nViABpL.js} +2 -2
- package/web/assets/{minus-C_n6M3oC.js → minus-mDLJQeXY.js} +2 -2
- package/web/assets/modal-DcxJxueq.js +5 -0
- package/web/assets/modal-n2wMDd7F.js +1 -0
- package/web/assets/{money-cashier-receipt.svg-nNTup6TP.js → money-cashier-receipt.svg-B3w4dcvy.js} +1 -1
- package/web/assets/{money-currency-dollar-pay.svg-D6ct80fW.js → money-currency-dollar-pay.svg-By5pgatC.js} +1 -1
- package/web/assets/{money-graph-arrow-increase.svg-DrQ3RzKG.js → money-graph-arrow-increase.svg-JJK_oYl6.js} +1 -1
- package/web/assets/{money-graph-bar-chart-increase.svg-CgI8xnRe.js → money-graph-bar-chart-increase.svg-BMvEIVpy.js} +1 -1
- package/web/assets/multiselect-CqGmdE3J.js +251 -0
- package/web/assets/{nature-ecology-leaf.svg-SIUCD6fX.js → nature-ecology-leaf.svg-CGCHa8bD.js} +1 -1
- package/web/assets/{password-1NqZx53t.js → password-CSX8oB5M.js} +4 -4
- package/web/assets/{phone-telephone.svg-DuLAx6_w.js → phone-telephone.svg-CA8_wOQH.js} +1 -1
- package/web/assets/{plus-CP-dlA9U.js → plus-CGTKvVZ7.js} +6 -6
- package/web/assets/process.store-CTLjlYjT.js +1 -0
- package/web/assets/{programming-bug.svg-DzOMyrsK.js → programming-bug.svg-Cizii8p1.js} +1 -1
- package/web/assets/{programming-cloud.svg-CB7hznLf.js → programming-cloud.svg-pnwxJHaK.js} +1 -1
- package/web/assets/{programming-computer-database-server.svg-Vdd0DgKt.js → programming-computer-database-server.svg-CNt3Jbql.js} +1 -1
- package/web/assets/{programming-computer-database.svg-CEqheAaf.js → programming-computer-database.svg-ESSkZX3t.js} +1 -1
- package/web/assets/{programming-module-four-layout.svg-BdPzuTtB.js → programming-module-four-layout.svg-BGbJvE0O.js} +1 -1
- package/web/assets/{programming-module-three.svg-PwBqCXu4.js → programming-module-three.svg-D3gOTAlw.js} +1 -1
- package/web/assets/{programming-module.svg-DsBi6ejo.js → programming-module.svg-CSHFfsFS.js} +1 -1
- package/web/assets/{programming-script-code.svg-Broms4WV.js → programming-script-code.svg-DjFoDv0c.js} +1 -1
- package/web/assets/{python-DfCB9qU4.js → python-MEGp0q_z.js} +1 -1
- package/web/assets/{razor-BBh-Aao5.js → razor-CEazjH4x.js} +1 -1
- package/web/assets/router-BmJL8z_u.js +1 -0
- package/web/assets/settings-scope-BGuX4AI9.js +1 -0
- package/web/assets/settings.store-a49Jijfe.js +1 -0
- package/web/assets/{shopping-cart.svg-CKdnb6hR.js → shopping-cart.svg-Cu7M1oni.js} +1 -1
- package/web/assets/{shopping-gift-present.svg-DIxbK0pG.js → shopping-gift-present.svg-Cdnu9uAQ.js} +1 -1
- package/web/assets/{shopping-shipping-box-parcel-package.svg-C-9ntsF7.js → shopping-shipping-box-parcel-package.svg-C6BL6pCC.js} +1 -1
- package/web/assets/{src-C77fweBS.js → src-BKhMPhsU.js} +13 -13
- package/web/assets/src-DQvVUJe0.js +1 -0
- package/web/assets/{tabpanel-C0aUv4Tp.js → tabpanel-B9VkBnSU.js} +3 -3
- package/web/assets/{tag-new-circle.svg-D9mnL-uB.js → tag-new-circle.svg-BpXDXKC4.js} +1 -1
- package/web/assets/{travel-map-earth-globe.svg-B1pf_UKK.js → travel-map-earth-globe.svg-B_t8kO2f.js} +1 -1
- package/web/assets/trpc-B-qv_zm2.js +1 -0
- package/web/assets/{tsMode-CBiaVW1A.js → tsMode-lBRYpyez.js} +6 -6
- package/web/assets/{typescript-DSa5kNRs.js → typescript-DGOxNj9C.js} +1 -1
- package/web/assets/useAiChatDrawer-xv2HAiHA.js +1 -0
- package/web/assets/useCloudOrg-_Z_zfd63.js +1 -0
- package/web/assets/useProjectCatalog-CNbze2zg.js +1 -0
- package/web/assets/{xml-BYwyGk9G.js → xml-Cqgx2kWf.js} +1 -1
- package/web/assets/{yaml-Dl2OSYTO.js → yaml-CIs4cY7e.js} +1 -1
- package/web/index.html +2 -2
- package/agent-manager-KX5MSTAK.js +0 -7
- package/chunk-NVKGIBJN.js.map +0 -1
- package/src-R6JOPDNL.js.map +0 -1
- package/web/assets/AgentScalarChatInterface.vue-D53JSFzC.js +0 -13
- package/web/assets/AgentTerminalPage-zuXFRGB0.js +0 -1
- package/web/assets/AiChatPage-BjC9iQnH.js +0 -1
- package/web/assets/AppLayout-fVYVDGr-.js +0 -1
- package/web/assets/AuditPage-DvhG8fxh.js +0 -1
- package/web/assets/CloudAccountPage-CE3b0q5v.js +0 -1
- package/web/assets/CloudAccountPage-ChVg2wnJ.css +0 -1
- package/web/assets/CloudAccountPage-YkGuA0nb.js +0 -1
- package/web/assets/CloudMessagingPage-okqqdltV.js +0 -2
- package/web/assets/DashboardPage-CmZITjvU.js +0 -1
- package/web/assets/EnvironmentForm-_y5JoRHH.js +0 -108
- package/web/assets/EnvironmentFormPage-DYhDZdPj.js +0 -1
- package/web/assets/EnvironmentListPage-soh5FJDb.js +0 -1
- package/web/assets/EnvironmentSelector-CQNLsssr.js +0 -1
- package/web/assets/KanbanBoardPage-BvMPl2FW.css +0 -1
- package/web/assets/KanbanBoardPage-C3cG7v4z.js +0 -4
- package/web/assets/KanbanListPage-xyv-oiyq.js +0 -1
- package/web/assets/LaunchProjectPage-DKqMjh-V.js +0 -1
- package/web/assets/LaunchServicesPage-IhWdB_Gw.js +0 -1
- package/web/assets/LogViewer-ChElXmMu.js +0 -3
- package/web/assets/ProcessDetailPage-DFv0ESg1.js +0 -1
- package/web/assets/ProjectDetailPage-DEXvg1pg.js +0 -1
- package/web/assets/ProjectListPage-h0AQ_RCw.js +0 -1
- package/web/assets/RandomJobTestPage-Dp7A7Qgx.js +0 -2
- package/web/assets/ScenarioEditorPage-D0_VpZUT.js +0 -14
- package/web/assets/SendToChatDialog-BpJetpLA.js +0 -1
- package/web/assets/ServiceControlsBar-qiCaxnab.js +0 -1
- package/web/assets/ServiceDetailPage-BD8D0CuN.js +0 -2
- package/web/assets/ServiceFormPage-Dax40DkX.js +0 -1
- package/web/assets/SettingsPage-zriZbuPv.js +0 -2062
- package/web/assets/UnlockPage-BYtu3w_t.js +0 -1
- package/web/assets/VariablesTable-IvhXwdsn.js +0 -1
- package/web/assets/VaultMigrationPage-6Id4Fmeo.js +0 -1
- package/web/assets/VersionBadge-B-PtNx51.js +0 -1
- package/web/assets/WikiPage-DqqlIbM6.js +0 -1
- package/web/assets/WikiView-BZvgaTQp.js +0 -1
- package/web/assets/auth-errors-B510-08J.js +0 -1
- package/web/assets/autocomplete-DpSrZtZQ.js +0 -422
- package/web/assets/card-TJ-av0Pi.js +0 -32
- package/web/assets/client-D5eMRPpD.js +0 -24
- package/web/assets/cloud-chat.store-DzSz0QMb.js +0 -1
- package/web/assets/column-BAToyYIb.js +0 -907
- package/web/assets/interface-content-folder.svg-BF9F5qf2.js +0 -1
- package/web/assets/modal-C5SccGq4.js +0 -1
- package/web/assets/modal-CvqNyAvh.js +0 -5
- package/web/assets/multiselect-CSd05WUd.js +0 -251
- package/web/assets/process.store-B_vfVoW1.js +0 -1
- package/web/assets/router-CEOd6ZAd.js +0 -1
- package/web/assets/settings.store-BfNYjk_y.js +0 -1
- package/web/assets/src-CXyRAwtR.js +0 -1
- package/web/assets/trpc-BNJN8Syq.js +0 -1
- package/web/assets/useAiChatDrawer-DJh6hREC.js +0 -1
- package/web/assets/useCloudOrg-DYG5BAW1.js +0 -1
- package/web/assets/useProjectCatalog-Dyg12Vcr.js +0 -1
- /package/{agent-manager-KX5MSTAK.js.map → agent-manager-RGDHYM64.js.map} +0 -0
- /package/web/assets/{abap-DMmvWZUy.js → abap-DT2sAUGb.js} +0 -0
- /package/web/assets/{apex-D89PiTzU.js → apex-BqR8ejP0.js} +0 -0
- /package/web/assets/{azcli-ChnjTTA5.js → azcli-DK_jNPxf.js} +0 -0
- /package/web/assets/{bat-uLzQ_FhK.js → bat-BLmcleEN.js} +0 -0
- /package/web/assets/{bicep-CMOK7Q1v.js → bicep-DkR6Nnyy.js} +0 -0
- /package/web/assets/{cameligo-D1AyojFH.js → cameligo-DfT1QA_V.js} +0 -0
- /package/web/assets/{clojure-D9JoUgXn.js → clojure-BbsGZ_q_.js} +0 -0
- /package/web/assets/{coffee-D-5sSToL.js → coffee-CZQPrkXM.js} +0 -0
- /package/web/assets/{cpp-BqT_t_y9.js → cpp-CZLFjmrQ.js} +0 -0
- /package/web/assets/{csharp-CuToYI91.js → csharp-CljM85nx.js} +0 -0
- /package/web/assets/{csp-CffcxvlO.js → csp-B7ItwhrE.js} +0 -0
- /package/web/assets/{css-CUD0biQW.js → css-CIuVviKc.js} +0 -0
- /package/web/assets/{cypher-ByyWL_9U.js → cypher-Lk1MiloH.js} +0 -0
- /package/web/assets/{dart-B__ipcUn.js → dart-B83vLjrb.js} +0 -0
- /package/web/assets/{dockerfile-DS-_8bWw.js → dockerfile--LImnfYW.js} +0 -0
- /package/web/assets/{ecl-DWsNCBUj.js → ecl-C1mPHzto.js} +0 -0
- /package/web/assets/{elixir-OfjEy-3g.js → elixir-F7VkySYx.js} +0 -0
- /package/web/assets/{flow9-BPX22hxS.js → flow9-CyDLjcIP.js} +0 -0
- /package/web/assets/{fsharp-CVJcfIUn.js → fsharp-BtAy52j8.js} +0 -0
- /package/web/assets/{go-CfRHZ3yg.js → go-nAky3Nvu.js} +0 -0
- /package/web/assets/{graphql-BZaO3ttK.js → graphql-BFHB5AhE.js} +0 -0
- /package/web/assets/{hcl-BF9-qUku.js → hcl-DiNGWUmy.js} +0 -0
- /package/web/assets/{ini-BUvw6xhr.js → ini-D1Fg5XrG.js} +0 -0
- /package/web/assets/{java-BZ5BNd2x.js → java-C-10mSK7.js} +0 -0
- /package/web/assets/{julia-DN38cgYT.js → julia-Bqx3lIQk.js} +0 -0
- /package/web/assets/{kotlin-CjEJKT8q.js → kotlin-BBx7H7X0.js} +0 -0
- /package/web/assets/{less-DMEH_Nwq.js → less-BFHUOKEO.js} +0 -0
- /package/web/assets/{lexon-CKQUX8Ov.js → lexon-CZNaGS2_.js} +0 -0
- /package/web/assets/{lua-CuWjKLJ0.js → lua-iuAeZ15y.js} +0 -0
- /package/web/assets/{m3-CEp1bVrM.js → m3-Dotjo0U8.js} +0 -0
- /package/web/assets/{markdown-DxtQ_puq.js → markdown-B_31SQ_4.js} +0 -0
- /package/web/assets/{mips-Dx7qydpO.js → mips-Dp4rVQ6A.js} +0 -0
- /package/web/assets/{msdax-DpNCaSiO.js → msdax-DGvgi_My.js} +0 -0
- /package/web/assets/{mysql-C3xsBDPP.js → mysql-jqX2Izgu.js} +0 -0
- /package/web/assets/{objective-c-BbaVHCX1.js → objective-c-KWePe42v.js} +0 -0
- /package/web/assets/{pascal-sDju2faq.js → pascal-k9Augcc6.js} +0 -0
- /package/web/assets/{pascaligo-ChCdOH6b.js → pascaligo-CijZuMoC.js} +0 -0
- /package/web/assets/{perl-BCgLFj01.js → perl-CtKbbdqv.js} +0 -0
- /package/web/assets/{pgsql-DtKby69f.js → pgsql-IYBGBY8p.js} +0 -0
- /package/web/assets/{php-NYvR17Qb.js → php-CZgzKas5.js} +0 -0
- /package/web/assets/{pla-gSg-RBG0.js → pla-DxEUZCU5.js} +0 -0
- /package/web/assets/{postiats-BQxHyDfy.js → postiats-Cf9oispl.js} +0 -0
- /package/web/assets/{powerquery-DzDmbVZN.js → powerquery-Cyri2j7y.js} +0 -0
- /package/web/assets/{powershell-yy4Q5BEQ.js → powershell-CezsOW84.js} +0 -0
- /package/web/assets/{protobuf-B_hIk9q0.js → protobuf-BVSVLozM.js} +0 -0
- /package/web/assets/{pug-CdeEb1ft.js → pug-tdDHxxGI.js} +0 -0
- /package/web/assets/{qsharp-CiSquEgT.js → qsharp-BbxYBU73.js} +0 -0
- /package/web/assets/{r-D1Ocz1x4.js → r-CMiogh24.js} +0 -0
- /package/web/assets/{redis-D42Y12yz.js → redis-Be7YRs2n.js} +0 -0
- /package/web/assets/{redshift-CS62MYfG.js → redshift-BMtedC4Y.js} +0 -0
- /package/web/assets/{restructuredtext-CKFSMEXw.js → restructuredtext-BeqA_Nw7.js} +0 -0
- /package/web/assets/{ruby-C4gTaeU3.js → ruby-DQh1qjXf.js} +0 -0
- /package/web/assets/{rust-C_f2AiHQ.js → rust-Dtb7SJq9.js} +0 -0
- /package/web/assets/{sb-CdNdpP1r.js → sb-YjmuT7ii.js} +0 -0
- /package/web/assets/{scala-N4EWaFTL.js → scala-3ZhdCU1r.js} +0 -0
- /package/web/assets/{scheme-CttIARxx.js → scheme-Ck6PwJVN.js} +0 -0
- /package/web/assets/{scss-v0wtbxaE.js → scss-CdSZkceb.js} +0 -0
- /package/web/assets/{shell-BJdEWXbc.js → shell-D951-SzL.js} +0 -0
- /package/web/assets/{solidity-DKDa59zZ.js → solidity-BtE4jdUZ.js} +0 -0
- /package/web/assets/{sophia--Kw-vDpr.js → sophia-CPgh17t9.js} +0 -0
- /package/web/assets/{sparql-BI8jS9Pc.js → sparql-D5V7fRaF.js} +0 -0
- /package/web/assets/{sql-Dz6z--6O.js → sql-CIe64i2G.js} +0 -0
- /package/web/assets/{st-CT8D05gv.js → st-BUZL4NkZ.js} +0 -0
- /package/web/assets/{swift-Ayb3KzWx.js → swift-BGpAy-yZ.js} +0 -0
- /package/web/assets/{systemverilog-BtWJM9O5.js → systemverilog-CYBqw_20.js} +0 -0
- /package/web/assets/{tcl-BJvUWpbV.js → tcl-CqmcDc3_.js} +0 -0
- /package/web/assets/{twig-c3YaBCU6.js → twig-BWVIPIPE.js} +0 -0
- /package/web/assets/{typespec-gFCWLBoZ.js → typespec-mTM8EdlQ.js} +0 -0
- /package/web/assets/{uuid-B3B8HIK9.js → uuid-aTVnbu2y.js} +0 -0
- /package/web/assets/{vb-CVtfWXV2.js → vb-xvgQ7mYU.js} +0 -0
- /package/web/assets/{w3c-keyname-nn0G3QC2.js → w3c-keyname-CjzYiphr.js} +0 -0
- /package/web/assets/{wgsl-C_huaGQy.js → wgsl-C8m-CvBD.js} +0 -0
|
@@ -6,7 +6,7 @@ import { z as z21 } from "zod";
|
|
|
6
6
|
// ../server/src/services/agent-store.ts
|
|
7
7
|
import { randomUUID, randomBytes, createCipheriv, createDecipheriv } from "crypto";
|
|
8
8
|
import { readFile as readFile2, writeFile as writeFile2, rename, mkdir as mkdir2, chmod } from "fs/promises";
|
|
9
|
-
import { dirname } from "path";
|
|
9
|
+
import { dirname, join as join2 } from "path";
|
|
10
10
|
|
|
11
11
|
// ../server/src/services/vault-resolver.ts
|
|
12
12
|
import { join, sep } from "path";
|
|
@@ -89,6 +89,15 @@ function projectVaultRoot(orgId, projectId) {
|
|
|
89
89
|
assertSafeId("project", projectId);
|
|
90
90
|
return join(orgVaultRoot(orgId), "projects", projectId);
|
|
91
91
|
}
|
|
92
|
+
function orgIdOfRoot(root) {
|
|
93
|
+
const marker = join(machineRoot(), "orgs") + sep;
|
|
94
|
+
if (!root.startsWith(marker)) return null;
|
|
95
|
+
const [orgId] = root.slice(marker.length).split(sep);
|
|
96
|
+
return orgId && SAFE_ID.test(orgId) ? orgId : null;
|
|
97
|
+
}
|
|
98
|
+
function vaultIdOfRoot(root) {
|
|
99
|
+
return orgIdOfRoot(root) ?? void 0;
|
|
100
|
+
}
|
|
92
101
|
function vaultFor(target) {
|
|
93
102
|
if (!target.orgId) return { root: localVaultRoot() };
|
|
94
103
|
return { root: projectVaultRoot(target.orgId, target.id) };
|
|
@@ -118,6 +127,14 @@ async function readOrgClouds() {
|
|
|
118
127
|
}
|
|
119
128
|
return out;
|
|
120
129
|
}
|
|
130
|
+
async function listOrgVaults() {
|
|
131
|
+
const orgsDir = join(machineRoot(), "orgs");
|
|
132
|
+
try {
|
|
133
|
+
return (await readdir(orgsDir, { withFileTypes: true })).filter((e) => e.isDirectory() && SAFE_ID.test(e.name)).map((e) => e.name);
|
|
134
|
+
} catch {
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
121
138
|
async function listCloudVaults() {
|
|
122
139
|
const orgsDir = join(machineRoot(), "orgs");
|
|
123
140
|
const found = [];
|
|
@@ -187,6 +204,7 @@ import { createHash } from "crypto";
|
|
|
187
204
|
var KEY_SIZE_BYTES = 32;
|
|
188
205
|
var DEFAULT_VAULT = "\0default";
|
|
189
206
|
var keyring = /* @__PURE__ */ new Map();
|
|
207
|
+
var lockedVaults = /* @__PURE__ */ new Set();
|
|
190
208
|
var _ciMode = false;
|
|
191
209
|
var _pendingLegacyKey = null;
|
|
192
210
|
function isCiMode() {
|
|
@@ -223,16 +241,31 @@ function hasPendingLegacyKey() {
|
|
|
223
241
|
function setEncryptionKeyInMemory(key, vault = DEFAULT_VAULT) {
|
|
224
242
|
if (key.length !== KEY_SIZE_BYTES) throw new Error("Taille de cl\xE9 invalide");
|
|
225
243
|
keyring.set(vault, key);
|
|
244
|
+
lockedVaults.delete(vault);
|
|
226
245
|
}
|
|
227
246
|
function clearEncryptionKey(vault) {
|
|
228
|
-
if (vault === void 0)
|
|
229
|
-
|
|
247
|
+
if (vault === void 0) {
|
|
248
|
+
keyring.clear();
|
|
249
|
+
lockedVaults.clear();
|
|
250
|
+
} else {
|
|
251
|
+
keyring.delete(vault);
|
|
252
|
+
}
|
|
230
253
|
}
|
|
231
254
|
function hasEncryptionKey(vault = DEFAULT_VAULT) {
|
|
232
255
|
return keyring.has(vault);
|
|
233
256
|
}
|
|
234
257
|
function getEncryptionKey(vault = DEFAULT_VAULT) {
|
|
235
|
-
|
|
258
|
+
const own = keyring.get(vault);
|
|
259
|
+
if (own) return own;
|
|
260
|
+
if (vault === DEFAULT_VAULT || lockedVaults.has(vault)) return null;
|
|
261
|
+
return keyring.get(DEFAULT_VAULT) ?? null;
|
|
262
|
+
}
|
|
263
|
+
function markVaultLocked(vault) {
|
|
264
|
+
lockedVaults.add(vault);
|
|
265
|
+
keyring.delete(vault);
|
|
266
|
+
}
|
|
267
|
+
function clearVaultLock(vault) {
|
|
268
|
+
lockedVaults.delete(vault);
|
|
236
269
|
}
|
|
237
270
|
function deriveStableSecret(purpose, vault = DEFAULT_VAULT) {
|
|
238
271
|
const key = getEncryptionKey(vault);
|
|
@@ -250,8 +283,8 @@ async function setEncryptionKey(keyHex) {
|
|
|
250
283
|
// ../server/src/services/agent-store.ts
|
|
251
284
|
var FILENAME = "agents.json";
|
|
252
285
|
var ALGORITHM = "aes-256-gcm";
|
|
253
|
-
function encrypt(plaintext) {
|
|
254
|
-
const maybeKey = getEncryptionKey();
|
|
286
|
+
function encrypt(plaintext, vault) {
|
|
287
|
+
const maybeKey = getEncryptionKey(vault);
|
|
255
288
|
if (!maybeKey) {
|
|
256
289
|
throw new Error("Encryption key not loaded \u2014 please provide the key via setup UI");
|
|
257
290
|
}
|
|
@@ -263,11 +296,11 @@ function encrypt(plaintext) {
|
|
|
263
296
|
const authTag = cipher.getAuthTag().toString("hex");
|
|
264
297
|
return { encrypted: enc, iv: iv.toString("hex"), authTag };
|
|
265
298
|
}
|
|
266
|
-
function decrypt(encrypted, ivHex, authTagHex) {
|
|
299
|
+
function decrypt(encrypted, ivHex, authTagHex, vault) {
|
|
267
300
|
if (!/^[0-9a-f]+$/i.test(encrypted) || !/^[0-9a-f]+$/i.test(ivHex) || !/^[0-9a-f]+$/i.test(authTagHex)) {
|
|
268
301
|
throw new Error("Invalid hex string in encrypted agent data");
|
|
269
302
|
}
|
|
270
|
-
const maybeKey = getEncryptionKey();
|
|
303
|
+
const maybeKey = getEncryptionKey(vault);
|
|
271
304
|
if (!maybeKey) {
|
|
272
305
|
throw new Error("Encryption key not loaded \u2014 please provide the key via setup UI");
|
|
273
306
|
}
|
|
@@ -283,71 +316,129 @@ var AgentStore = class {
|
|
|
283
316
|
agents = /* @__PURE__ */ new Map();
|
|
284
317
|
passthroughEnv = {};
|
|
285
318
|
traefikConfigs = {};
|
|
319
|
+
/** Le propriétaire de chaque agent, d'après le coffre où il a été lu. */
|
|
320
|
+
owners = /* @__PURE__ */ new Map();
|
|
321
|
+
/**
|
|
322
|
+
* Tous les coffres rencontrés, y compris ceux devenus vides.
|
|
323
|
+
*
|
|
324
|
+
* Déduire cette liste des agents encore présents laisserait le dernier agent
|
|
325
|
+
* d'une organisation dans son fichier après suppression : plus personne pour
|
|
326
|
+
* désigner ce coffre, donc plus personne pour le réécrire.
|
|
327
|
+
*/
|
|
328
|
+
knownOwners = /* @__PURE__ */ new Set([null]);
|
|
286
329
|
loaded = false;
|
|
287
330
|
/**
|
|
288
|
-
*
|
|
289
|
-
*
|
|
331
|
+
* Le fichier d'un propriétaire donné.
|
|
332
|
+
*
|
|
333
|
+
* Pour la machine, il reste à côté de la clé qui l'ouvre (`keyedFilePath`) :
|
|
334
|
+
* lu sous une autre clé il se déchiffrerait en blancs, puis serait réécrit
|
|
335
|
+
* blanc. Pour une organisation, c'est son coffre — la clé, elle, répond
|
|
336
|
+
* toujours pour toute la machine.
|
|
290
337
|
*/
|
|
291
|
-
|
|
292
|
-
|
|
338
|
+
/** L'identifiant de clé d'un agent : son organisation, ou la machine. */
|
|
339
|
+
vaultOf(id) {
|
|
340
|
+
return this.owners.get(id) ?? void 0;
|
|
341
|
+
}
|
|
342
|
+
filePathFor(owner) {
|
|
343
|
+
if (owner === null) return keyedFilePath(FILENAME);
|
|
344
|
+
return Promise.resolve(join2(orgVaultRoot(owner), FILENAME));
|
|
293
345
|
}
|
|
294
346
|
/** Where older versions kept it — read only, so an older Runeya keeps working. */
|
|
295
347
|
getLegacyFilePath() {
|
|
296
348
|
return legacyMachineFilePath(FILENAME);
|
|
297
349
|
}
|
|
350
|
+
/** Ce qu'un fichier de coffre contient, ou null s'il n'y en a pas. */
|
|
351
|
+
async readOwnerFile(owner) {
|
|
352
|
+
const paths = owner === null ? [await this.filePathFor(null), this.getLegacyFilePath()] : [await this.filePathFor(owner)];
|
|
353
|
+
for (const path of paths) {
|
|
354
|
+
let raw;
|
|
355
|
+
try {
|
|
356
|
+
raw = await readFile2(path, "utf-8");
|
|
357
|
+
} catch {
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
try {
|
|
361
|
+
const data = JSON.parse(raw);
|
|
362
|
+
if (Array.isArray(data)) {
|
|
363
|
+
return { agents: data, passthroughEnv: {}, traefikConfigs: {} };
|
|
364
|
+
}
|
|
365
|
+
const fileData = data;
|
|
366
|
+
return {
|
|
367
|
+
agents: fileData.agents ?? [],
|
|
368
|
+
passthroughEnv: fileData.passthroughEnv ?? {},
|
|
369
|
+
traefikConfigs: fileData.traefikConfigs ?? {}
|
|
370
|
+
};
|
|
371
|
+
} catch {
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
298
376
|
/**
|
|
299
|
-
*
|
|
377
|
+
* Lire la machine puis chaque organisation présente sur ce disque.
|
|
300
378
|
*
|
|
301
|
-
*
|
|
302
|
-
*
|
|
379
|
+
* Les organisations sont relues du disque et non d'une liste tenue à part :
|
|
380
|
+
* un coffre qui existe est une organisation dont les agents comptent, et
|
|
381
|
+
* c'est déjà comme ça que la synchronisation décide de sa portée.
|
|
303
382
|
*/
|
|
304
|
-
async readFromDisk() {
|
|
305
|
-
try {
|
|
306
|
-
return await readFile2(await this.getFilePath(), "utf-8");
|
|
307
|
-
} catch {
|
|
308
|
-
return readFile2(this.getLegacyFilePath(), "utf-8");
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
async ensureDir() {
|
|
312
|
-
await mkdir2(dirname(await this.getFilePath()), { recursive: true });
|
|
313
|
-
}
|
|
314
383
|
async load() {
|
|
315
384
|
if (this.loaded) return;
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
const data =
|
|
319
|
-
if (
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
for (const a of fileData.agents) this.agents.set(a.id, a);
|
|
325
|
-
this.passthroughEnv = fileData.passthroughEnv ?? {};
|
|
326
|
-
this.traefikConfigs = fileData.traefikConfigs ?? {};
|
|
385
|
+
const owners = [null, ...await listOrgVaults()];
|
|
386
|
+
for (const owner of owners) {
|
|
387
|
+
const data = await this.readOwnerFile(owner);
|
|
388
|
+
if (!data) continue;
|
|
389
|
+
this.knownOwners.add(owner);
|
|
390
|
+
for (const a of data.agents) {
|
|
391
|
+
this.agents.set(a.id, a);
|
|
392
|
+
this.owners.set(a.id, owner);
|
|
327
393
|
}
|
|
328
|
-
|
|
394
|
+
Object.assign(this.passthroughEnv, data.passthroughEnv);
|
|
395
|
+
Object.assign(this.traefikConfigs, data.traefikConfigs);
|
|
329
396
|
}
|
|
330
397
|
this.loaded = true;
|
|
331
398
|
}
|
|
399
|
+
/**
|
|
400
|
+
* Réécrire chaque coffre concerné.
|
|
401
|
+
*
|
|
402
|
+
* Un agent emporte son `passthroughEnv` et sa configuration Traefik dans le
|
|
403
|
+
* fichier de son propriétaire : les laisser côté machine rendrait la portée
|
|
404
|
+
* mensongère — l'organisation partirait en laissant ses miettes derrière.
|
|
405
|
+
* Tous les coffres sont réécrits, y compris ceux devenus vides, sinon un
|
|
406
|
+
* agent déplacé subsisterait dans les deux.
|
|
407
|
+
*/
|
|
332
408
|
async save() {
|
|
333
|
-
|
|
334
|
-
const
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
409
|
+
const byOwner = /* @__PURE__ */ new Map();
|
|
410
|
+
for (const owner of this.knownOwners) byOwner.set(owner, []);
|
|
411
|
+
for (const agent of this.agents.values()) {
|
|
412
|
+
const owner = this.owners.get(agent.id) ?? null;
|
|
413
|
+
byOwner.set(owner, [...byOwner.get(owner) ?? [], agent]);
|
|
414
|
+
}
|
|
415
|
+
for (const [owner, agents] of byOwner) {
|
|
416
|
+
const ids = new Set(agents.map((a) => a.id));
|
|
417
|
+
const fileData = {
|
|
418
|
+
agents,
|
|
419
|
+
passthroughEnv: Object.fromEntries(
|
|
420
|
+
Object.entries(this.passthroughEnv).filter(([id]) => ids.has(id))
|
|
421
|
+
),
|
|
422
|
+
traefikConfigs: Object.fromEntries(
|
|
423
|
+
Object.entries(this.traefikConfigs).filter(([id]) => ids.has(id))
|
|
424
|
+
)
|
|
425
|
+
};
|
|
426
|
+
const filePath = await this.filePathFor(owner);
|
|
427
|
+
await mkdir2(dirname(filePath), { recursive: true });
|
|
428
|
+
const tmpPath = filePath + ".tmp";
|
|
429
|
+
await writeFile2(tmpPath, JSON.stringify(fileData, null, 2), "utf-8");
|
|
430
|
+
await rename(tmpPath, filePath);
|
|
431
|
+
await chmod(filePath, 384);
|
|
432
|
+
}
|
|
344
433
|
}
|
|
345
434
|
toAgentConfig(stored) {
|
|
346
435
|
return {
|
|
347
436
|
id: stored.id,
|
|
348
437
|
name: stored.name,
|
|
349
438
|
url: stored.url,
|
|
350
|
-
passphrase
|
|
439
|
+
// La passphrase est chiffrée par la clé du coffre où l'agent est rangé :
|
|
440
|
+
// celle de son organisation, ou celle de la machine.
|
|
441
|
+
passphrase: decrypt(stored.encrypted, stored.iv, stored.authTag, this.vaultOf(stored.id)),
|
|
351
442
|
passthroughEnv: this.passthroughEnv[stored.id] ?? []
|
|
352
443
|
};
|
|
353
444
|
}
|
|
@@ -367,10 +458,11 @@ var AgentStore = class {
|
|
|
367
458
|
if (!stored) return null;
|
|
368
459
|
return this.toAgentConfig(stored);
|
|
369
460
|
}
|
|
370
|
-
async register(name, url, passphrase) {
|
|
461
|
+
async register(name, url, passphrase, owner = null) {
|
|
371
462
|
await this.load();
|
|
372
463
|
const existing = Array.from(this.agents.values()).find((a) => a.url === url);
|
|
373
|
-
const
|
|
464
|
+
const vault = existing ? this.vaultOf(existing.id) : owner ?? void 0;
|
|
465
|
+
const { encrypted, iv, authTag } = encrypt(passphrase, vault);
|
|
374
466
|
if (existing) {
|
|
375
467
|
existing.name = name;
|
|
376
468
|
existing.encrypted = encrypted;
|
|
@@ -382,6 +474,8 @@ var AgentStore = class {
|
|
|
382
474
|
const id = randomUUID();
|
|
383
475
|
const stored = { id, name, url, encrypted, iv, authTag };
|
|
384
476
|
this.agents.set(id, stored);
|
|
477
|
+
this.owners.set(id, owner);
|
|
478
|
+
this.knownOwners.add(owner);
|
|
385
479
|
await this.save();
|
|
386
480
|
return { id, name, url, passphrase, passthroughEnv: [] };
|
|
387
481
|
}
|
|
@@ -389,6 +483,7 @@ var AgentStore = class {
|
|
|
389
483
|
await this.load();
|
|
390
484
|
if (!this.agents.has(id)) return false;
|
|
391
485
|
this.agents.delete(id);
|
|
486
|
+
this.owners.delete(id);
|
|
392
487
|
delete this.passthroughEnv[id];
|
|
393
488
|
delete this.traefikConfigs[id];
|
|
394
489
|
await this.save();
|
|
@@ -417,7 +512,7 @@ var AgentStore = class {
|
|
|
417
512
|
if (fields.name !== void 0) stored.name = fields.name;
|
|
418
513
|
if (fields.url !== void 0) stored.url = fields.url;
|
|
419
514
|
if (fields.passphrase !== void 0) {
|
|
420
|
-
const { encrypted, iv, authTag } = encrypt(fields.passphrase);
|
|
515
|
+
const { encrypted, iv, authTag } = encrypt(fields.passphrase, this.vaultOf(id));
|
|
421
516
|
stored.encrypted = encrypted;
|
|
422
517
|
stored.iv = iv;
|
|
423
518
|
stored.authTag = authTag;
|
|
@@ -440,7 +535,7 @@ var agentStore = new AgentStore();
|
|
|
440
535
|
// ../server/src/services/service-store.ts
|
|
441
536
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
442
537
|
import { readFile as readFile4, writeFile as writeFile4, rename as rename3, mkdir as mkdir4, chmod as chmod3, rm as rm2 } from "fs/promises";
|
|
443
|
-
import { join as
|
|
538
|
+
import { join as join4 } from "path";
|
|
444
539
|
|
|
445
540
|
// ../server/src/services/project-key.ts
|
|
446
541
|
function projectKey(ref) {
|
|
@@ -553,7 +648,7 @@ function isVaultConflicted(root) {
|
|
|
553
648
|
// ../server/src/services/environment-store.ts
|
|
554
649
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
555
650
|
import { readFile as readFile3, writeFile as writeFile3, rename as rename2, mkdir as mkdir3, chmod as chmod2, rm } from "fs/promises";
|
|
556
|
-
import { join as
|
|
651
|
+
import { join as join3 } from "path";
|
|
557
652
|
|
|
558
653
|
// ../server/src/services/crypto-helpers.ts
|
|
559
654
|
import { randomBytes as randomBytes2, createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2 } from "crypto";
|
|
@@ -579,8 +674,8 @@ function decryptValueWith(key, encrypted) {
|
|
|
579
674
|
dec += decipher.final("utf-8");
|
|
580
675
|
return dec;
|
|
581
676
|
}
|
|
582
|
-
function encryptValue(plaintext) {
|
|
583
|
-
const maybeKey = getEncryptionKey();
|
|
677
|
+
function encryptValue(plaintext, vault) {
|
|
678
|
+
const maybeKey = getEncryptionKey(vault);
|
|
584
679
|
if (!maybeKey) {
|
|
585
680
|
throw new Error("Encryption key not loaded \u2014 please provide the key via setup UI");
|
|
586
681
|
}
|
|
@@ -592,14 +687,14 @@ function encryptValue(plaintext) {
|
|
|
592
687
|
const authTag = cipher.getAuthTag().toString("hex");
|
|
593
688
|
return `${iv.toString("hex")}:${authTag}:${enc}`;
|
|
594
689
|
}
|
|
595
|
-
function decryptValue(encrypted) {
|
|
690
|
+
function decryptValue(encrypted, vault) {
|
|
596
691
|
const parts = encrypted.split(":");
|
|
597
692
|
if (parts.length !== 3) throw new Error("Invalid encrypted value format \u2014 expected iv:authTag:ciphertext");
|
|
598
693
|
const [ivHex, authTagHex, ciphertext] = parts;
|
|
599
694
|
if (!/^[0-9a-f]+$/i.test(ivHex) || !/^[0-9a-f]+$/i.test(authTagHex) || ciphertext !== "" && !/^[0-9a-f]+$/i.test(ciphertext)) {
|
|
600
695
|
throw new Error("Invalid hex in encrypted value \u2014 possible data corruption");
|
|
601
696
|
}
|
|
602
|
-
const maybeKey = getEncryptionKey();
|
|
697
|
+
const maybeKey = getEncryptionKey(vault);
|
|
603
698
|
if (!maybeKey) {
|
|
604
699
|
throw new Error("Encryption key not loaded \u2014 please provide the key via setup UI");
|
|
605
700
|
}
|
|
@@ -611,34 +706,34 @@ function decryptValue(encrypted) {
|
|
|
611
706
|
dec += decipher.final("utf-8");
|
|
612
707
|
return dec;
|
|
613
708
|
}
|
|
614
|
-
function stableEncryptValue(plaintext, existingEncrypted) {
|
|
709
|
+
function stableEncryptValue(plaintext, existingEncrypted, vault) {
|
|
615
710
|
if (existingEncrypted) {
|
|
616
711
|
try {
|
|
617
|
-
if (decryptValue(existingEncrypted) === plaintext) return existingEncrypted;
|
|
712
|
+
if (decryptValue(existingEncrypted, vault) === plaintext) return existingEncrypted;
|
|
618
713
|
} catch {
|
|
619
714
|
}
|
|
620
715
|
}
|
|
621
|
-
return encryptValue(plaintext);
|
|
716
|
+
return encryptValue(plaintext, vault);
|
|
622
717
|
}
|
|
623
|
-
function encryptVariableSlots(variables, existingEncrypted) {
|
|
718
|
+
function encryptVariableSlots(variables, existingEncrypted, vault) {
|
|
624
719
|
const result = {};
|
|
625
720
|
for (const [key, variable] of Object.entries(variables)) {
|
|
626
721
|
const slot = variable.value;
|
|
627
722
|
if (slot.isSecret && slot.value) {
|
|
628
|
-
result[key] = { ...variable, value: { ...slot, value: stableEncryptValue(slot.value, existingEncrypted?.[key]) } };
|
|
723
|
+
result[key] = { ...variable, value: { ...slot, value: stableEncryptValue(slot.value, existingEncrypted?.[key], vault) } };
|
|
629
724
|
} else {
|
|
630
725
|
result[key] = { ...variable, value: { ...slot } };
|
|
631
726
|
}
|
|
632
727
|
}
|
|
633
728
|
return result;
|
|
634
729
|
}
|
|
635
|
-
function decryptVariableSlots(variables, contextLabel, onFailure) {
|
|
730
|
+
function decryptVariableSlots(variables, contextLabel, onFailure, vault) {
|
|
636
731
|
const result = {};
|
|
637
732
|
for (const [key, variable] of Object.entries(variables)) {
|
|
638
733
|
const slot = variable.value;
|
|
639
734
|
if (slot.isSecret && slot.value) {
|
|
640
735
|
try {
|
|
641
|
-
result[key] = { ...variable, value: { ...slot, value: decryptValue(slot.value) } };
|
|
736
|
+
result[key] = { ...variable, value: { ...slot, value: decryptValue(slot.value, vault) } };
|
|
642
737
|
} catch (err) {
|
|
643
738
|
console.error(`[crypto-helpers] Failed to decrypt variable "${key}" for ${contextLabel}: ${err.message} \u2014 la valeur chiffr\xE9e est conserv\xE9e telle quelle sur le disque`);
|
|
644
739
|
onFailure?.(key);
|
|
@@ -1947,8 +2042,10 @@ var EnvironmentStore = class {
|
|
|
1947
2042
|
* belongs even before its project has been loaded.
|
|
1948
2043
|
*/
|
|
1949
2044
|
roots = /* @__PURE__ */ new Map();
|
|
2045
|
+
/** L'organisation d'où vient un environnement reçu du cloud — voir `vaultOf`. */
|
|
2046
|
+
remoteOrgs = /* @__PURE__ */ new Map();
|
|
1950
2047
|
getFilePath(root) {
|
|
1951
|
-
return
|
|
2048
|
+
return join3(root, FILENAME2);
|
|
1952
2049
|
}
|
|
1953
2050
|
/**
|
|
1954
2051
|
* The vault an environment must be written to: its project's.
|
|
@@ -1961,6 +2058,17 @@ var EnvironmentStore = class {
|
|
|
1961
2058
|
* environment whose project is unknown belongs to the launch directory, which
|
|
1962
2059
|
* is where it lived before vaults existed.
|
|
1963
2060
|
*/
|
|
2061
|
+
/**
|
|
2062
|
+
* La clé sous laquelle chiffrer cet environnement.
|
|
2063
|
+
*
|
|
2064
|
+
* La provenance l'emporte sur le coffre tant que le projet n'est pas local :
|
|
2065
|
+
* un environnement reçu du cloud arrive avant lui, et `rootFor` désignerait
|
|
2066
|
+
* alors le répertoire de lancement — donc la clé de la machine plutôt que
|
|
2067
|
+
* celle de l'organisation qui a chiffré ces secrets.
|
|
2068
|
+
*/
|
|
2069
|
+
vaultOf(environment) {
|
|
2070
|
+
return this.remoteOrgs.get(environment.id) ?? vaultIdOfRoot(this.rootFor(environment));
|
|
2071
|
+
}
|
|
1964
2072
|
rootFor(environment) {
|
|
1965
2073
|
const known = this.roots.get(environment.id) ?? null;
|
|
1966
2074
|
const projectRoot = environment.projectId ? rootOfProjectAmong(environment.projectId, known) : null;
|
|
@@ -1997,13 +2105,22 @@ var EnvironmentStore = class {
|
|
|
1997
2105
|
);
|
|
1998
2106
|
return { envSlots };
|
|
1999
2107
|
}
|
|
2000
|
-
|
|
2108
|
+
/**
|
|
2109
|
+
* `vault` est fourni quand l'appelant sait à qui appartient l'environnement
|
|
2110
|
+
* mieux que le disque : à l'arrivée d'une entité distante, son projet n'est
|
|
2111
|
+
* pas encore local, et le coffre déduit serait celui du répertoire de
|
|
2112
|
+
* lancement — donc la mauvaise clé.
|
|
2113
|
+
*/
|
|
2114
|
+
encryptEnvironment(environment, vault) {
|
|
2001
2115
|
const cache = this.diskEncryptedSlots.get(environment.id);
|
|
2002
2116
|
let encryptedVars = environment.variables;
|
|
2003
2117
|
if (environment.variables && Object.keys(environment.variables).length > 0) {
|
|
2004
2118
|
encryptedVars = encryptVariableSlots(
|
|
2005
2119
|
environment.variables,
|
|
2006
|
-
cache?.envSlots
|
|
2120
|
+
cache?.envSlots,
|
|
2121
|
+
// La clé est celle du coffre où l'environnement sera écrit : les
|
|
2122
|
+
// secrets d'une organisation sont chiffrés par la sienne.
|
|
2123
|
+
vault ?? this.vaultOf(environment)
|
|
2007
2124
|
);
|
|
2008
2125
|
}
|
|
2009
2126
|
return { ...environment, variables: this.keepUnreadableSecrets(environment.id, encryptedVars) };
|
|
@@ -2037,14 +2154,15 @@ var EnvironmentStore = class {
|
|
|
2037
2154
|
}
|
|
2038
2155
|
return result;
|
|
2039
2156
|
}
|
|
2040
|
-
decryptEnvironment(environment) {
|
|
2157
|
+
decryptEnvironment(environment, vault) {
|
|
2041
2158
|
let decryptedVars = environment.variables;
|
|
2042
2159
|
if (environment.variables && Object.keys(environment.variables).length > 0) {
|
|
2043
2160
|
const failed = /* @__PURE__ */ new Set();
|
|
2044
2161
|
decryptedVars = decryptVariableSlots(
|
|
2045
2162
|
environment.variables,
|
|
2046
2163
|
`environment ${environment.id}`,
|
|
2047
|
-
(variableId) => failed.add(variableId)
|
|
2164
|
+
(variableId) => failed.add(variableId),
|
|
2165
|
+
vault ?? this.vaultOf(environment)
|
|
2048
2166
|
);
|
|
2049
2167
|
if (failed.size > 0) this.unreadableSecrets.set(environment.id, failed);
|
|
2050
2168
|
else this.unreadableSecrets.delete(environment.id);
|
|
@@ -2157,6 +2275,7 @@ var EnvironmentStore = class {
|
|
|
2157
2275
|
this.diskEncryptedSlots.delete(id);
|
|
2158
2276
|
this.unreadableSecrets.delete(id);
|
|
2159
2277
|
this.roots.delete(id);
|
|
2278
|
+
this.remoteOrgs.delete(id);
|
|
2160
2279
|
}
|
|
2161
2280
|
this.notify();
|
|
2162
2281
|
}
|
|
@@ -2369,8 +2488,9 @@ var EnvironmentStore = class {
|
|
|
2369
2488
|
* Validated rather than trusted, and diff-guarded against the on-disk form so
|
|
2370
2489
|
* re-applying an identical environment neither saves nor notifies (loop-safe).
|
|
2371
2490
|
*/
|
|
2372
|
-
async applyRemoteUpsert(id, fields) {
|
|
2491
|
+
async applyRemoteUpsert(id, fields, vault) {
|
|
2373
2492
|
await this.load();
|
|
2493
|
+
if (vault) this.remoteOrgs.set(id, vault);
|
|
2374
2494
|
const parsed = EnvironmentSchema.safeParse({ ...fields, id });
|
|
2375
2495
|
if (!parsed.success) {
|
|
2376
2496
|
console.error("[environment-store] Rejected remote environment %s:", id, parsed.error.message);
|
|
@@ -2378,11 +2498,11 @@ var EnvironmentStore = class {
|
|
|
2378
2498
|
}
|
|
2379
2499
|
const incoming = parsed.data;
|
|
2380
2500
|
const existing = this.environments.get(id);
|
|
2381
|
-
if (existing && JSON.stringify(this.encryptEnvironment(existing)) === JSON.stringify(incoming)) {
|
|
2501
|
+
if (existing && JSON.stringify(this.encryptEnvironment(existing, vault)) === JSON.stringify(incoming)) {
|
|
2382
2502
|
return { created: false };
|
|
2383
2503
|
}
|
|
2384
2504
|
this.diskEncryptedSlots.set(id, this.extractEncryptedCache(incoming));
|
|
2385
|
-
this.environments.set(id, this.decryptEnvironment(incoming));
|
|
2505
|
+
this.environments.set(id, this.decryptEnvironment(incoming, vault));
|
|
2386
2506
|
await this.save();
|
|
2387
2507
|
return { created: !existing };
|
|
2388
2508
|
}
|
|
@@ -2393,6 +2513,7 @@ var EnvironmentStore = class {
|
|
|
2393
2513
|
this.environments.delete(id);
|
|
2394
2514
|
this.diskEncryptedSlots.delete(id);
|
|
2395
2515
|
this.unreadableSecrets.delete(id);
|
|
2516
|
+
this.remoteOrgs.delete(id);
|
|
2396
2517
|
await this.save();
|
|
2397
2518
|
return true;
|
|
2398
2519
|
}
|
|
@@ -2401,25 +2522,27 @@ var environmentStore = new EnvironmentStore();
|
|
|
2401
2522
|
|
|
2402
2523
|
// ../server/src/services/service-store.ts
|
|
2403
2524
|
var FILENAME3 = "services.json";
|
|
2404
|
-
function encryptLogSources(logSources, previous) {
|
|
2525
|
+
function encryptLogSources(logSources, previous, vault) {
|
|
2405
2526
|
return logSources.map((src, i) => {
|
|
2406
2527
|
const prev = previous?.[i];
|
|
2407
2528
|
if (src.type === "mongo") {
|
|
2529
|
+
if (isEncryptedValue(src.connectionString)) return src;
|
|
2408
2530
|
const was = prev?.type === "mongo" ? prev.connectionString : void 0;
|
|
2409
|
-
return { ...src, connectionString: stableEncryptValue(src.connectionString, was) };
|
|
2531
|
+
return { ...src, connectionString: stableEncryptValue(src.connectionString, was, vault) };
|
|
2410
2532
|
}
|
|
2411
2533
|
if (src.type === "mysql" && src.password) {
|
|
2534
|
+
if (isEncryptedValue(src.password)) return src;
|
|
2412
2535
|
const was = prev?.type === "mysql" ? prev.password : void 0;
|
|
2413
|
-
return { ...src, password: stableEncryptValue(src.password, was) };
|
|
2536
|
+
return { ...src, password: stableEncryptValue(src.password, was, vault) };
|
|
2414
2537
|
}
|
|
2415
2538
|
return src;
|
|
2416
2539
|
});
|
|
2417
2540
|
}
|
|
2418
|
-
function decryptLogSources(logSources) {
|
|
2541
|
+
function decryptLogSources(logSources, vault) {
|
|
2419
2542
|
return logSources.map((src) => {
|
|
2420
2543
|
if (src.type === "mongo" && isEncryptedValue(src.connectionString)) {
|
|
2421
2544
|
try {
|
|
2422
|
-
return { ...src, connectionString: decryptValue(src.connectionString) };
|
|
2545
|
+
return { ...src, connectionString: decryptValue(src.connectionString, vault) };
|
|
2423
2546
|
} catch {
|
|
2424
2547
|
console.error("[service-store] Failed to decrypt mongo connectionString");
|
|
2425
2548
|
return src;
|
|
@@ -2427,7 +2550,7 @@ function decryptLogSources(logSources) {
|
|
|
2427
2550
|
}
|
|
2428
2551
|
if (src.type === "mysql" && src.password && isEncryptedValue(src.password)) {
|
|
2429
2552
|
try {
|
|
2430
|
-
return { ...src, password: decryptValue(src.password) };
|
|
2553
|
+
return { ...src, password: decryptValue(src.password, vault) };
|
|
2431
2554
|
} catch {
|
|
2432
2555
|
console.error("[service-store] Failed to decrypt mysql password");
|
|
2433
2556
|
return src;
|
|
@@ -2436,14 +2559,14 @@ function decryptLogSources(logSources) {
|
|
|
2436
2559
|
return src;
|
|
2437
2560
|
});
|
|
2438
2561
|
}
|
|
2439
|
-
function prepareForDisk(service, previous) {
|
|
2562
|
+
function prepareForDisk(service, previous, vault) {
|
|
2440
2563
|
return {
|
|
2441
2564
|
...service,
|
|
2442
2565
|
env: {},
|
|
2443
2566
|
envSecrets: [],
|
|
2444
2567
|
resolvedLogParsers: void 0,
|
|
2445
2568
|
resolvedCwd: void 0,
|
|
2446
|
-
logSources: encryptLogSources(service.logSources ?? [], previous?.logSources)
|
|
2569
|
+
logSources: encryptLogSources(service.logSources ?? [], previous?.logSources, vault)
|
|
2447
2570
|
};
|
|
2448
2571
|
}
|
|
2449
2572
|
var ServiceStore = class {
|
|
@@ -2464,8 +2587,18 @@ var ServiceStore = class {
|
|
|
2464
2587
|
}
|
|
2465
2588
|
/** Which vault each service was read from, used until its project is known. */
|
|
2466
2589
|
roots = /* @__PURE__ */ new Map();
|
|
2590
|
+
/**
|
|
2591
|
+
* L'organisation d'où vient un service reçu du cloud.
|
|
2592
|
+
*
|
|
2593
|
+
* Le coffre ne peut pas encore répondre : les contenus arrivent avant leur
|
|
2594
|
+
* projet, donc `rootFor` désignerait le répertoire de lancement et
|
|
2595
|
+
* chiffrerait les secrets de l'organisation avec la clé de la machine. Cette
|
|
2596
|
+
* provenance tient le temps que le projet devienne local — après quoi elle
|
|
2597
|
+
* dit la même chose que le coffre.
|
|
2598
|
+
*/
|
|
2599
|
+
remoteOrgs = /* @__PURE__ */ new Map();
|
|
2467
2600
|
getFilePath(root) {
|
|
2468
|
-
return
|
|
2601
|
+
return join4(root, FILENAME3);
|
|
2469
2602
|
}
|
|
2470
2603
|
/**
|
|
2471
2604
|
* The vault a service must be written to: the one of the project owning it.
|
|
@@ -2474,6 +2607,10 @@ var ServiceStore = class {
|
|
|
2474
2607
|
* so the registry answers, falling back to where the service was read and
|
|
2475
2608
|
* finally to the local vault.
|
|
2476
2609
|
*/
|
|
2610
|
+
/** La clé sous laquelle chiffrer ce service : son organisation, ou son coffre. */
|
|
2611
|
+
vaultOf(serviceId) {
|
|
2612
|
+
return this.remoteOrgs.get(serviceId) ?? vaultIdOfRoot(this.rootFor(serviceId));
|
|
2613
|
+
}
|
|
2477
2614
|
rootFor(serviceId) {
|
|
2478
2615
|
return rootOfService(serviceId, this.roots.get(serviceId) ?? null) ?? localVaultRoot();
|
|
2479
2616
|
}
|
|
@@ -2506,7 +2643,7 @@ var ServiceStore = class {
|
|
|
2506
2643
|
this.diskForm.set(s.id, s);
|
|
2507
2644
|
this.services.set(s.id, {
|
|
2508
2645
|
...s,
|
|
2509
|
-
logSources: decryptLogSources(s.logSources ?? [])
|
|
2646
|
+
logSources: decryptLogSources(s.logSources ?? [], vaultIdOfRoot(root))
|
|
2510
2647
|
});
|
|
2511
2648
|
this.roots.set(s.id, root);
|
|
2512
2649
|
}
|
|
@@ -2529,7 +2666,7 @@ var ServiceStore = class {
|
|
|
2529
2666
|
byRoot.set(localVaultRoot(), byRoot.get(localVaultRoot()) ?? []);
|
|
2530
2667
|
for (const service of this.services.values()) {
|
|
2531
2668
|
const root = this.rootFor(service.id);
|
|
2532
|
-
const prepared = prepareForDisk(service, this.diskForm.get(service.id));
|
|
2669
|
+
const prepared = prepareForDisk(service, this.diskForm.get(service.id), this.vaultOf(service.id));
|
|
2533
2670
|
this.diskForm.set(prepared.id, prepared);
|
|
2534
2671
|
this.roots.set(service.id, root);
|
|
2535
2672
|
if (isVaultConflicted(root)) continue;
|
|
@@ -2564,6 +2701,7 @@ var ServiceStore = class {
|
|
|
2564
2701
|
this.services.delete(id);
|
|
2565
2702
|
this.diskForm.delete(id);
|
|
2566
2703
|
this.roots.delete(id);
|
|
2704
|
+
this.remoteOrgs.delete(id);
|
|
2567
2705
|
}
|
|
2568
2706
|
this.notify();
|
|
2569
2707
|
}
|
|
@@ -2578,6 +2716,24 @@ var ServiceStore = class {
|
|
|
2578
2716
|
await this.load();
|
|
2579
2717
|
await this.save();
|
|
2580
2718
|
}
|
|
2719
|
+
/**
|
|
2720
|
+
* Réattribuer l'organisation de services dont le projet vient de changer de
|
|
2721
|
+
* coffre.
|
|
2722
|
+
*
|
|
2723
|
+
* Un service porte son `orgId` en propre : laissé à `null` après le passage
|
|
2724
|
+
* du projet dans une organisation, il partirait dans le doc en se disant
|
|
2725
|
+
* local. La sauvegarde qui suit les écrit dans leur nouveau coffre et les
|
|
2726
|
+
* retire de l'ancien, le registre ayant déjà été mis à jour par le projet.
|
|
2727
|
+
*/
|
|
2728
|
+
async reassignOrg(serviceIds, orgId) {
|
|
2729
|
+
await this.load();
|
|
2730
|
+
for (const id of serviceIds) {
|
|
2731
|
+
const service = this.services.get(id);
|
|
2732
|
+
if (service) this.services.set(id, { ...service, orgId });
|
|
2733
|
+
}
|
|
2734
|
+
await this.save();
|
|
2735
|
+
this.notify();
|
|
2736
|
+
}
|
|
2581
2737
|
async list() {
|
|
2582
2738
|
await this.load();
|
|
2583
2739
|
return Array.from(this.services.values());
|
|
@@ -2594,7 +2750,7 @@ var ServiceStore = class {
|
|
|
2594
2750
|
async getSanitized(id) {
|
|
2595
2751
|
await this.load();
|
|
2596
2752
|
const service = this.services.get(id);
|
|
2597
|
-
return service ? prepareForDisk(service, this.diskForm.get(id)) : null;
|
|
2753
|
+
return service ? prepareForDisk(service, this.diskForm.get(id), this.vaultOf(id)) : null;
|
|
2598
2754
|
}
|
|
2599
2755
|
async create(input) {
|
|
2600
2756
|
await this.load();
|
|
@@ -2682,7 +2838,7 @@ var ServiceStore = class {
|
|
|
2682
2838
|
const out = [];
|
|
2683
2839
|
for (const id of ids) {
|
|
2684
2840
|
const service = this.services.get(id);
|
|
2685
|
-
if (service) out.push(prepareForDisk(service, this.diskForm.get(id)));
|
|
2841
|
+
if (service) out.push(prepareForDisk(service, this.diskForm.get(id), this.vaultOf(id)));
|
|
2686
2842
|
}
|
|
2687
2843
|
return out;
|
|
2688
2844
|
}
|
|
@@ -2694,8 +2850,9 @@ var ServiceStore = class {
|
|
|
2694
2850
|
* `services.json`. Diff-guarded against the on-disk form so re-applying an
|
|
2695
2851
|
* identical service neither saves nor notifies (loop-safe).
|
|
2696
2852
|
*/
|
|
2697
|
-
async applyRemoteUpsert(id, fields) {
|
|
2853
|
+
async applyRemoteUpsert(id, fields, vault) {
|
|
2698
2854
|
await this.load();
|
|
2855
|
+
if (vault) this.remoteOrgs.set(id, vault);
|
|
2699
2856
|
const parsed = ServiceConfigSchema.safeParse({ ...fields, id });
|
|
2700
2857
|
if (!parsed.success) {
|
|
2701
2858
|
console.error("[service-store] Rejected remote service %s:", id, parsed.error.message);
|
|
@@ -2704,7 +2861,7 @@ var ServiceStore = class {
|
|
|
2704
2861
|
const incoming = parsed.data;
|
|
2705
2862
|
const existing = this.services.get(id);
|
|
2706
2863
|
if (existing) {
|
|
2707
|
-
const currentDisk = prepareForDisk(existing, this.diskForm.get(id));
|
|
2864
|
+
const currentDisk = prepareForDisk(existing, this.diskForm.get(id), vault ?? this.vaultOf(id));
|
|
2708
2865
|
if (JSON.stringify(currentDisk) === JSON.stringify(incoming)) return { created: false };
|
|
2709
2866
|
}
|
|
2710
2867
|
this.diskForm.set(id, incoming);
|
|
@@ -2712,7 +2869,7 @@ var ServiceStore = class {
|
|
|
2712
2869
|
...incoming,
|
|
2713
2870
|
// The doc carries the on-disk form, where credentials are ciphertext;
|
|
2714
2871
|
// in memory they are expected in the clear, as `load()` keeps them.
|
|
2715
|
-
logSources: decryptLogSources(incoming.logSources ?? [])
|
|
2872
|
+
logSources: decryptLogSources(incoming.logSources ?? [], vault ?? this.vaultOf(id))
|
|
2716
2873
|
});
|
|
2717
2874
|
await this.save();
|
|
2718
2875
|
this.notify();
|
|
@@ -2736,28 +2893,81 @@ var serviceStore = new ServiceStore();
|
|
|
2736
2893
|
import { spawn } from "child_process";
|
|
2737
2894
|
import { createInterface } from "readline";
|
|
2738
2895
|
import { watch } from "fs";
|
|
2739
|
-
import { dirname as dirname2, join as
|
|
2896
|
+
import { dirname as dirname2, join as join5 } from "path";
|
|
2740
2897
|
import { fileURLToPath } from "url";
|
|
2898
|
+
var POSIX_SAFE_KEYS = [
|
|
2899
|
+
"PATH",
|
|
2900
|
+
"HOME",
|
|
2901
|
+
"USER",
|
|
2902
|
+
"SHELL",
|
|
2903
|
+
"LANG",
|
|
2904
|
+
"TERM",
|
|
2905
|
+
"NODE_ENV",
|
|
2906
|
+
"TMPDIR",
|
|
2907
|
+
"TZ",
|
|
2908
|
+
"DBUS_SESSION_BUS_ADDRESS",
|
|
2909
|
+
"XDG_RUNTIME_DIR",
|
|
2910
|
+
// Needed so the agent can talk to the user's clipboard for the chat image-paste flow
|
|
2911
|
+
// (xclip needs DISPLAY/XAUTHORITY, wl-copy needs WAYLAND_DISPLAY).
|
|
2912
|
+
"DISPLAY",
|
|
2913
|
+
"XAUTHORITY",
|
|
2914
|
+
"WAYLAND_DISPLAY",
|
|
2915
|
+
"XDG_SESSION_TYPE"
|
|
2916
|
+
];
|
|
2917
|
+
var WINDOWS_SAFE_KEYS = [
|
|
2918
|
+
"PATH",
|
|
2919
|
+
"PATHEXT",
|
|
2920
|
+
"NODE_ENV",
|
|
2921
|
+
"TZ",
|
|
2922
|
+
"TERM",
|
|
2923
|
+
// Interpreter + OS roots
|
|
2924
|
+
"ComSpec",
|
|
2925
|
+
"SystemRoot",
|
|
2926
|
+
"SystemDrive",
|
|
2927
|
+
"windir",
|
|
2928
|
+
"OS",
|
|
2929
|
+
"PSModulePath",
|
|
2930
|
+
// User profile & app data (git config, credential helpers, npm/scoop shims)
|
|
2931
|
+
"USERPROFILE",
|
|
2932
|
+
"HOMEDRIVE",
|
|
2933
|
+
"HOMEPATH",
|
|
2934
|
+
"USERNAME",
|
|
2935
|
+
"USERDOMAIN",
|
|
2936
|
+
"USERDOMAIN_ROAMINGPROFILE",
|
|
2937
|
+
"LOGONSERVER",
|
|
2938
|
+
"APPDATA",
|
|
2939
|
+
"LOCALAPPDATA",
|
|
2940
|
+
// Machine-wide install roots
|
|
2941
|
+
"ProgramData",
|
|
2942
|
+
"ProgramFiles",
|
|
2943
|
+
"ProgramFiles(x86)",
|
|
2944
|
+
"ProgramW6432",
|
|
2945
|
+
"CommonProgramFiles",
|
|
2946
|
+
"CommonProgramFiles(x86)",
|
|
2947
|
+
"CommonProgramW6432",
|
|
2948
|
+
"ALLUSERSPROFILE",
|
|
2949
|
+
"PUBLIC",
|
|
2950
|
+
"DriverData",
|
|
2951
|
+
// Temp
|
|
2952
|
+
"TEMP",
|
|
2953
|
+
"TMP",
|
|
2954
|
+
// Architecture / CPU (used by installers and native module loaders)
|
|
2955
|
+
"PROCESSOR_ARCHITECTURE",
|
|
2956
|
+
"PROCESSOR_ARCHITEW6432",
|
|
2957
|
+
"PROCESSOR_IDENTIFIER",
|
|
2958
|
+
"PROCESSOR_LEVEL",
|
|
2959
|
+
"PROCESSOR_REVISION",
|
|
2960
|
+
"NUMBER_OF_PROCESSORS",
|
|
2961
|
+
// Session / terminal
|
|
2962
|
+
"SESSIONNAME",
|
|
2963
|
+
"COMPUTERNAME",
|
|
2964
|
+
"FPS_BROWSER_APP_PROFILE_STRING",
|
|
2965
|
+
"FPS_BROWSER_USER_PROFILE_STRING",
|
|
2966
|
+
"WT_SESSION",
|
|
2967
|
+
"WT_PROFILE_ID"
|
|
2968
|
+
];
|
|
2741
2969
|
function buildAgentEnv() {
|
|
2742
|
-
const safeKeys =
|
|
2743
|
-
"PATH",
|
|
2744
|
-
"HOME",
|
|
2745
|
-
"USER",
|
|
2746
|
-
"SHELL",
|
|
2747
|
-
"LANG",
|
|
2748
|
-
"TERM",
|
|
2749
|
-
"NODE_ENV",
|
|
2750
|
-
"TMPDIR",
|
|
2751
|
-
"TZ",
|
|
2752
|
-
"DBUS_SESSION_BUS_ADDRESS",
|
|
2753
|
-
"XDG_RUNTIME_DIR",
|
|
2754
|
-
// Needed so the agent can talk to the user's clipboard for the chat image-paste flow
|
|
2755
|
-
// (xclip needs DISPLAY/XAUTHORITY, wl-copy needs WAYLAND_DISPLAY).
|
|
2756
|
-
"DISPLAY",
|
|
2757
|
-
"XAUTHORITY",
|
|
2758
|
-
"WAYLAND_DISPLAY",
|
|
2759
|
-
"XDG_SESSION_TYPE"
|
|
2760
|
-
];
|
|
2970
|
+
const safeKeys = process.platform === "win32" ? WINDOWS_SAFE_KEYS : POSIX_SAFE_KEYS;
|
|
2761
2971
|
const agentEnv = {
|
|
2762
2972
|
RUNEYA_AGENT_PORT: String(env.RUNEYA_AGENT_PORT),
|
|
2763
2973
|
RUNEYA_AGENT_HOST: env.RUNEYA_AGENT_HOST
|
|
@@ -2769,9 +2979,10 @@ function buildAgentEnv() {
|
|
|
2769
2979
|
}
|
|
2770
2980
|
agentEnv.PASSPHRASE_OVERRIDE = passphrase;
|
|
2771
2981
|
}
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2982
|
+
const wanted = new Set(safeKeys.map((k) => k.toLowerCase()));
|
|
2983
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
2984
|
+
if (value && wanted.has(key.toLowerCase())) {
|
|
2985
|
+
agentEnv[key] = value;
|
|
2775
2986
|
}
|
|
2776
2987
|
}
|
|
2777
2988
|
return agentEnv;
|
|
@@ -2794,7 +3005,7 @@ var AgentSpawner = class {
|
|
|
2794
3005
|
}
|
|
2795
3006
|
console.log(`[agent-spawner] Spawning local agent on ${agentUrl}...`);
|
|
2796
3007
|
const isDev = process.env.NODE_ENV === "development";
|
|
2797
|
-
this.agentDistPath = env.AGENT_BINARY_PATH ||
|
|
3008
|
+
this.agentDistPath = env.AGENT_BINARY_PATH || join5(dirname2(fileURLToPath(import.meta.url)), "..", "..", "agent", "dist", "index.js");
|
|
2798
3009
|
this.agentProcess = spawn("node", [this.agentDistPath], {
|
|
2799
3010
|
env: agentEnv,
|
|
2800
3011
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -2897,7 +3108,7 @@ var AgentSpawner = class {
|
|
|
2897
3108
|
this.fileWatcher.close();
|
|
2898
3109
|
}
|
|
2899
3110
|
console.log("[agent-spawner] \u{1F50D} Watching agent dist for changes (hot reload enabled)");
|
|
2900
|
-
const distDir =
|
|
3111
|
+
const distDir = join5(this.agentDistPath, "..");
|
|
2901
3112
|
this.fileWatcher = watch(distDir, { persistent: false }, (eventType, filename) => {
|
|
2902
3113
|
if ((eventType === "change" || eventType === "rename") && filename === "index.js" && !this.isRestarting) {
|
|
2903
3114
|
this.isRestarting = true;
|
|
@@ -3328,8 +3539,12 @@ var AgentManager = class extends EventEmitter2 {
|
|
|
3328
3539
|
this.connectAgent(agent);
|
|
3329
3540
|
}
|
|
3330
3541
|
}
|
|
3331
|
-
|
|
3332
|
-
|
|
3542
|
+
/**
|
|
3543
|
+
* `owner` dit à quelle organisation l'agent appartient, ou `null` pour la
|
|
3544
|
+
* machine — l'agent local, qui n'exécute des processus que sur ce poste.
|
|
3545
|
+
*/
|
|
3546
|
+
async register(name, url, passphrase, owner = null) {
|
|
3547
|
+
const config = await agentStore.register(name, url, passphrase, owner);
|
|
3333
3548
|
const isReRegistration = this.connections.has(config.id);
|
|
3334
3549
|
if (isReRegistration) {
|
|
3335
3550
|
console.log(`[agent-manager] Re-registering agent ${config.name} (${config.id})`);
|
|
@@ -3671,15 +3886,19 @@ export {
|
|
|
3671
3886
|
clearEncryptionKey,
|
|
3672
3887
|
hasEncryptionKey,
|
|
3673
3888
|
getEncryptionKey,
|
|
3889
|
+
markVaultLocked,
|
|
3890
|
+
clearVaultLock,
|
|
3674
3891
|
ensureEncryptionKey,
|
|
3675
3892
|
setEncryptionKey,
|
|
3676
3893
|
machineRoot,
|
|
3677
3894
|
localVaultRoot,
|
|
3678
3895
|
orgVaultRoot,
|
|
3679
3896
|
projectVaultRoot,
|
|
3897
|
+
vaultIdOfRoot,
|
|
3680
3898
|
vaultFor,
|
|
3681
3899
|
stampOrgCloud,
|
|
3682
3900
|
readOrgClouds,
|
|
3901
|
+
listOrgVaults,
|
|
3683
3902
|
listCloudVaults,
|
|
3684
3903
|
allVaultRoots,
|
|
3685
3904
|
machineFilePath,
|
|
@@ -3737,6 +3956,8 @@ export {
|
|
|
3737
3956
|
setProjectVault,
|
|
3738
3957
|
forgetProject,
|
|
3739
3958
|
setProjectServices,
|
|
3959
|
+
rootOfProjectRef,
|
|
3960
|
+
refsOfProjectId,
|
|
3740
3961
|
rootOfProjectAmong,
|
|
3741
3962
|
refOfProjectAmong,
|
|
3742
3963
|
environmentStore,
|
|
@@ -3746,4 +3967,4 @@ export {
|
|
|
3746
3967
|
traefikManager,
|
|
3747
3968
|
agentManager
|
|
3748
3969
|
};
|
|
3749
|
-
//# sourceMappingURL=chunk-
|
|
3970
|
+
//# sourceMappingURL=chunk-EL75GG7O.js.map
|