@runeya/runeya 2.0.150 → 2.0.152
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 +17 -8
- package/agent/index.js.map +1 -1
- package/agent-manager-SF4CAJJC.js +13 -0
- package/chat-Z7SFBEXS.js +28 -0
- package/{chunk-T6Y5KICH.js → chunk-26Q43CB2.js} +2 -2
- package/{chunk-76D52RTB.js → chunk-2DIW5EUT.js} +6 -6
- package/{chunk-3RCVOPTL.js → chunk-3C3R5ZVX.js} +2 -2
- package/{chunk-AZSHM3NM.js → chunk-3O54EIGT.js} +4 -4
- package/{chunk-HRNYFWGP.js → chunk-DTRZ5ZN7.js} +5 -5
- package/{chunk-UJ2OHNEN.js → chunk-EUTW2S4P.js} +87 -16
- package/chunk-EUTW2S4P.js.map +1 -0
- package/{chunk-SHSWOE5S.js → chunk-MGKGIHT4.js} +2 -4
- package/{chunk-SHSWOE5S.js.map → chunk-MGKGIHT4.js.map} +1 -1
- package/{chunk-ZVXPGKK5.js → chunk-PU6REPMY.js} +5 -5
- package/{chunk-ZVXPGKK5.js.map → chunk-PU6REPMY.js.map} +1 -1
- package/{chunk-OPVJAPUF.js → chunk-QD2OVLK4.js} +2 -2
- package/{chunk-XQGABRZY.js → chunk-QJSIN26R.js} +45 -38
- package/chunk-QJSIN26R.js.map +1 -0
- package/{chunk-UEK7QFWY.js → chunk-R4SKU6AO.js} +10 -12
- package/chunk-R4SKU6AO.js.map +1 -0
- package/{chunk-LJ7KLYFQ.js → chunk-RVZATF7R.js} +17 -9
- package/chunk-RVZATF7R.js.map +1 -0
- package/{chunk-64FCYYAB.js → chunk-TBNCGMDM.js} +70 -16
- package/chunk-TBNCGMDM.js.map +1 -0
- package/{companion-H24L2MGY.js → companion-ZDEGNZ2G.js} +11 -9
- package/{desktop-installer-page-V2NXWT43.js → desktop-installer-page-TBKSXVFD.js} +3 -3
- package/{desktop-launcher-46OJ5NAA.js → desktop-launcher-WBYP3KTF.js} +3 -3
- package/{environment-resolver-SY36Q67E.js → environment-resolver-R2GH6QOX.js} +6 -6
- package/{external-NPJBOEYV.js → external-UJ46WKBL.js} +3 -3
- package/index.js +15 -15
- package/index.js.map +1 -1
- package/{install-gate-6KHRGTTC.js → install-gate-TSCXUCYE.js} +2 -2
- package/mcp-server/external.js +15 -7
- package/mcp-server/external.js.map +1 -1
- package/mcp-server/index.js +15 -7
- package/mcp-server/index.js.map +1 -1
- package/package.json +1 -1
- package/{project-store-BYAE4SVZ.js → project-store-GBKM34QP.js} +7 -7
- package/settings-manager-VSOC3XGI.js +10 -0
- package/{src-AAOVGV5C.js → src-6WZKSNN7.js} +4 -2
- package/{src-OENXLZKQ.js → src-NWPED6TK.js} +34 -40
- package/src-NWPED6TK.js.map +1 -0
- package/{vault-resolver-B6BCVP47.js → vault-resolver-GGHULMG6.js} +3 -3
- package/web/assets/{AgentScalarChatInterface.vue-DwycfPE9.js → AgentScalarChatInterface.vue-0pB6D9jL.js} +1 -1
- package/web/assets/{AgentTerminalPage-BO1uzTvb.js → AgentTerminalPage-D1c5A1Ol.js} +1 -1
- package/web/assets/{AiChatModals-Ci8Essyi.js → AiChatModals-B_Cn5wNS.js} +1 -1
- package/web/assets/AppLayout-BsFZ6nG3.js +1 -0
- package/web/assets/{AppLayout-BlhwflMq.css → AppLayout-Djk3-XbN.css} +1 -1
- package/web/assets/{AuditPage-DC9xkftS.js → AuditPage-B_Ee8f0S.js} +1 -1
- package/web/assets/{CloudAccountPage-Ctf2gtpm.css → CloudAccountPage-CYcW_3tO.css} +1 -1
- package/web/assets/CloudAccountPage-D1L8Z_V3.js +1 -0
- package/web/assets/{CloudMessagingPage-DWgBG6iS.js → CloudMessagingPage-CyZF0sdY.js} +1 -1
- package/web/assets/{DashboardPage-6JrhJP8C.js → DashboardPage-BeWd0GWF.js} +1 -1
- package/web/assets/{DirectoryPickerDialog-B6tPuRZv.js → DirectoryPickerDialog-BGhbB66i.js} +1 -1
- package/web/assets/{EnvironmentForm-C-pr29o0.js → EnvironmentForm-B0FYydAK.js} +1 -1
- package/web/assets/EnvironmentForm-BnTLokUw.css +1 -0
- package/web/assets/{EnvironmentFormPage-DNBRaZH7.js → EnvironmentFormPage-BdTdOUBD.js} +1 -1
- package/web/assets/{EnvironmentListPage-D1Zom-yp.js → EnvironmentListPage-Cy9Kg5pY.js} +1 -1
- package/web/assets/{KanbanBoardPage-DeZRYB00.js → KanbanBoardPage-BOEK_sKt.js} +3 -3
- package/web/assets/{KanbanListPage-Bw0TFzqM.js → KanbanListPage-BOxLKDpW.js} +1 -1
- package/web/assets/{LaunchProjectPage-D1nMVxOW.js → LaunchProjectPage-zlY3PK3t.js} +1 -1
- package/web/assets/{LaunchServicesPage-CgondJcg.js → LaunchServicesPage-BsM0bP8N.js} +1 -1
- package/web/assets/{LaunchShell-DmAPUl7p.js → LaunchShell-BznQ7GLD.js} +1 -1
- package/web/assets/{LogViewer-B-rfzSpn.js → LogViewer-9e3e9X-R.js} +1 -1
- package/web/assets/{OrgKeyPrompt-DWkRmHYb.js → OrgKeyPrompt-Ckq1sJ8-.js} +1 -1
- package/web/assets/{ProcessControls-C7LX2uQD.js → ProcessControls-Br_aLfW7.js} +1 -1
- package/web/assets/ProcessDetailPage-B7bD2jmj.css +1 -0
- package/web/assets/ProcessDetailPage-D3BNcm7N.js +1 -0
- package/web/assets/{ProjectCreateDialog-C-VN-f05.js → ProjectCreateDialog-BzJRqXun.js} +1 -1
- package/web/assets/{ProjectLocationGate-CM6YNXYc.js → ProjectLocationGate-DjBwSAKc.js} +1 -1
- package/web/assets/{ProjectPublishDialog-CwItEKmm.js → ProjectPublishDialog-yakoPg1D.js} +1 -1
- package/web/assets/{RandomJobTestPage-BY6kBvm3.js → RandomJobTestPage-Dh0-shVq.js} +1 -1
- package/web/assets/{ScenarioEditorPage-BtKSjE2X.css → ScenarioEditorPage-BwLBCVeS.css} +1 -1
- package/web/assets/ScenarioEditorPage-DEdlwmf3.js +14 -0
- package/web/assets/{SendToChatDialog-uXvbEybU.js → SendToChatDialog-_ai4UP8l.js} +1 -1
- package/web/assets/{ServiceControlsBar-CoKPrw7b.js → ServiceControlsBar-Bo-jHhJK.js} +1 -1
- package/web/assets/ServiceDetailPage-CWB3XIMA.js +2 -0
- package/web/assets/ServiceDetailPage-DuXvqXk4.css +1 -0
- package/web/assets/{ServiceFormPage-CS9rZyjG.js → ServiceFormPage-BzARwyAF.js} +1 -1
- package/web/assets/{SettingsPage-ByJ9v8kA.js → SettingsPage-CsIXEQrW.js} +7 -7
- package/web/assets/{SettingsPage-B951NEBm.css → SettingsPage-NpFX7FAy.css} +1 -1
- package/web/assets/{UnlockPage-CavRr6dk.js → UnlockPage-C08Itng5.js} +1 -1
- package/web/assets/{VaultMigrationPage-C9-taMLq.js → VaultMigrationPage-BLZc5pXH.js} +1 -1
- package/web/assets/{VersionBadge-D5eE6rPL.js → VersionBadge-lBKbqt98.js} +1 -1
- package/web/assets/{WikiPage-op2Y2UTo.js → WikiPage-RCU0T1IS.js} +1 -1
- package/web/assets/{WikiView-CpiYONPK.js → WikiView-BV8MZ8qm.js} +1 -1
- package/web/assets/{add-scalar-classes-t1J2lZx-.js → add-scalar-classes-CvUuKrM6.js} +1 -1
- package/web/assets/{agent.store-CmFNwq8b.js → agent.store-yrwtq9oP.js} +1 -1
- package/web/assets/{auth-BlB_Xe9D.js → auth-LbzJj0JF.js} +2 -2
- package/web/assets/{cloud-chat.store-30i6G2hv.js → cloud-chat.store-y_9urSQZ.js} +1 -1
- package/web/assets/{cloud-client-Dqa_CDfk.js → cloud-client-DhjJyZHU.js} +2 -2
- package/web/assets/{cloud-session-D04EJ2X2.js → cloud-session-BlihYcy2.js} +2 -2
- package/web/assets/dist-C9Qdh18x.js +1 -0
- package/web/assets/i18n-DxVwqoxL.js +1 -0
- package/web/assets/{index-B7Lb37Xl.js → index-Ci2pSJuu.js} +7 -7
- package/web/assets/{index-CnXzQkLZ.css → index-Ck_3m_I9.css} +1 -1
- package/web/assets/{modal-BUQs190g.js → modal-KpWdqKSY.js} +1 -1
- package/web/assets/notification.store-Bp37Xsss.js +1 -0
- package/web/assets/{project-launch.store-BsXk5Ngh.js → project-launch.store-AB257LRF.js} +1 -1
- package/web/assets/{project.store-BAx14h4J.js → project.store-qBZ_R1td.js} +1 -1
- package/web/assets/{scenario.store-BHnWFonP.js → scenario.store-B5ybSSzx.js} +1 -1
- package/web/assets/{service.store-BdRBLSCW.js → service.store-BrKRjCtb.js} +1 -1
- package/web/assets/{settings-scope-DSoix6om.js → settings-scope-BSdUKgjx.js} +1 -1
- package/web/assets/settings.store-C8guF9Fl.js +1 -0
- package/web/assets/{src-Dp7BndBf.js → src-Br-M9ln7.js} +1 -1
- package/web/assets/{src-Bfb0PBSC.css → src-dQGrnDw0.css} +1 -1
- package/web/assets/{src-CCCeCa_V.js → src-recq0B6o.js} +2 -2
- package/web/assets/{trpc-D2QgyyrU.js → trpc-CAKhySL_.js} +3 -3
- package/web/assets/{useCloudOrg-iYu-mVBY.js → useCloudOrg-B_JPalTv.js} +1 -1
- package/web/assets/useEnvVarAutocomplete-DCZCMfLC.js +1 -0
- package/web/assets/useEnvVarAutocomplete-gV2loQYv.css +1 -0
- package/web/assets/{useProjectCatalog-ByEs2zGK.js → useProjectCatalog-CCJAkQi_.js} +1 -1
- package/web/assets/{useProjectCloudOrg-Fo1WYzwi.js → useProjectCloudOrg-CG4CriU2.js} +1 -1
- package/web/assets/{useServiceUrlHost-DzjlYxkb.js → useServiceUrlHost-C1gL6Mjg.js} +1 -1
- package/web/index.html +17 -17
- package/agent-manager-5VR5TDBZ.js +0 -13
- package/chat-EMWEVXGR.js +0 -28
- package/chunk-64FCYYAB.js.map +0 -1
- package/chunk-DA2DZBTL.js +0 -43
- package/chunk-DA2DZBTL.js.map +0 -1
- package/chunk-LJ7KLYFQ.js.map +0 -1
- package/chunk-UEK7QFWY.js.map +0 -1
- package/chunk-UJ2OHNEN.js.map +0 -1
- package/chunk-XQGABRZY.js.map +0 -1
- package/mcp-ready-TAPBAOZY.js +0 -9
- package/settings-manager-GIRMJQKL.js +0 -10
- package/src-OENXLZKQ.js.map +0 -1
- package/vault-resolver-B6BCVP47.js.map +0 -1
- package/web/assets/AppLayout-f6SKHFJd.js +0 -1
- package/web/assets/CloudAccountPage-uK9FpJ4U.js +0 -1
- package/web/assets/EnvironmentForm-CkKVSiT7.css +0 -1
- package/web/assets/ProcessDetailPage-CJcIxbLm.css +0 -1
- package/web/assets/ProcessDetailPage-DOnYh6nd.js +0 -1
- package/web/assets/ScenarioEditorPage-bDoQIzB2.js +0 -14
- package/web/assets/ServiceDetailPage-DnSf5cm9.css +0 -1
- package/web/assets/ServiceDetailPage-WlcVr1uy.js +0 -2
- package/web/assets/dist-DTLmCuqE.js +0 -1
- package/web/assets/i18n-D3P4ZExP.js +0 -1
- package/web/assets/notification.store-CxPriNmY.js +0 -1
- package/web/assets/settings.store-CIAnRUSA.js +0 -1
- package/web/assets/useEnvVarAutocomplete-7Ok6yien.js +0 -1
- package/web/assets/useEnvVarAutocomplete-Czt8ZZ1E.css +0 -1
- /package/{agent-manager-5VR5TDBZ.js.map → agent-manager-SF4CAJJC.js.map} +0 -0
- /package/{chat-EMWEVXGR.js.map → chat-Z7SFBEXS.js.map} +0 -0
- /package/{chunk-T6Y5KICH.js.map → chunk-26Q43CB2.js.map} +0 -0
- /package/{chunk-76D52RTB.js.map → chunk-2DIW5EUT.js.map} +0 -0
- /package/{chunk-3RCVOPTL.js.map → chunk-3C3R5ZVX.js.map} +0 -0
- /package/{chunk-AZSHM3NM.js.map → chunk-3O54EIGT.js.map} +0 -0
- /package/{chunk-HRNYFWGP.js.map → chunk-DTRZ5ZN7.js.map} +0 -0
- /package/{chunk-OPVJAPUF.js.map → chunk-QD2OVLK4.js.map} +0 -0
- /package/{companion-H24L2MGY.js.map → companion-ZDEGNZ2G.js.map} +0 -0
- /package/{desktop-installer-page-V2NXWT43.js.map → desktop-installer-page-TBKSXVFD.js.map} +0 -0
- /package/{desktop-launcher-46OJ5NAA.js.map → desktop-launcher-WBYP3KTF.js.map} +0 -0
- /package/{environment-resolver-SY36Q67E.js.map → environment-resolver-R2GH6QOX.js.map} +0 -0
- /package/{external-NPJBOEYV.js.map → external-UJ46WKBL.js.map} +0 -0
- /package/{install-gate-6KHRGTTC.js.map → install-gate-TSCXUCYE.js.map} +0 -0
- /package/{mcp-ready-TAPBAOZY.js.map → project-store-GBKM34QP.js.map} +0 -0
- /package/{project-store-BYAE4SVZ.js.map → settings-manager-VSOC3XGI.js.map} +0 -0
- /package/{settings-manager-GIRMJQKL.js.map → src-6WZKSNN7.js.map} +0 -0
- /package/{src-AAOVGV5C.js.map → vault-resolver-GGHULMG6.js.map} +0 -0
package/chunk-64FCYYAB.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../server/src/services/environment-overrides-store.ts","../../server/src/services/environment-resolver.ts"],"sourcesContent":["import { readFile, writeFile, mkdir, chmod } from 'node:fs/promises';\nimport { renameWithRetry } from './run-store-utils.js';\nimport { dirname, join } from 'node:path';\nimport { getEncryptionKey } from '../utils/encryption-key.js';\nimport { allVaultRoots, keyedFilePath, legacyMachineFilePath , vaultIdOfRoot } from './vault-resolver.js';\nimport { environmentStore } from './environment-store.js';\nimport { StoreDiskCoordinator } from './store-disk-coordinator.js';\nimport { fingerprintFiles } from './disk-freshness.js';\nimport { ensureProjectsLoaded } from './vault-registry.js';\nimport {\n encryptVariableSlots,\n decryptVariableSlots,\n extractEncryptedVariableSlots,\n} from './crypto-helpers.js';\nimport type { VariableOverride, VariableSlot } from '@runeya/packages-shared';\n\nconst FILENAME = 'environment-overrides.json';\n\n// On disk: flat Record<variableId, VariableOverride>\n// An override holds only a value slot — the env var name always comes from the\n// variable definition, resolved by variable ID.\ntype OverridesData = Record<string, VariableOverride>;\n\nclass EnvironmentOverridesStore {\n private data: OverridesData = {};\n private loaded = false;\n /**\n * Le coordinateur partagé par les stores : un seul rechargement à la fois,\n * jamais pendant une écriture, et une substitution atomique à la fin.\n *\n * Ce store faisait sa propre cuisine et se marquait « chargé » avant ses\n * `await` : toute lecture concurrente repartait avec une table vide — une\n * surcharge déjà écrite paraissait absente, et l'assistant réclamait au\n * déverrouillage des variables que ce poste avait déjà renseignées.\n */\n private readonly disk = new StoreDiskCoordinator();\n /** Ce que le disque portait au dernier chargement (cf. `load`). */\n private fingerprint = '';\n private diskEncryptedSlots: Record<string, string> = {};\n /**\n * Les surcharges dont le secret ne s'est pas ouvert.\n *\n * Vides en mémoire, elles doivent repartir chiffrées : sans cela, la\n * sauvegarde suivante remplacerait par du blanc une valeur dont il ne\n * manquait que la clé.\n */\n private unreadableSecrets: Set<string> = new Set();\n /** Which vault each override was read from, until its project is known. */\n private roots: Map<string, string> = new Map();\n\n /**\n * An override belongs to the project whose variable it answers.\n *\n * Nothing in an override says so — they are keyed by variable id alone — so\n * the owning project is resolved through the environment that defines the\n * variable. Overrides are never synced: they stay in the project's vault on\n * this machine, and no other machine sees them.\n *\n * An override whose variable no longer exists (a deleted environment, a row\n * left behind) has no project to belong to. It stays wherever it was read,\n * falling back to the key's own directory — never dropped, since the variable\n * may simply not be loaded yet.\n */\n private async rootFor(variableId: string): Promise<string> {\n // Le coffre de l'environnement qui définit la variable, plutôt que l'id de\n // son projet : cet id peut nommer un projet dans chaque organisation, le\n // coffre en désigne un seul.\n const root = await environmentStore.rootOfVariable(variableId);\n if (root) return root;\n return this.roots.get(variableId) ?? dirname(await keyedFilePath(FILENAME));\n }\n\n /** Where earlier versions kept them: read once, rewritten to their vaults. */\n private getLegacyFilePath(): string {\n return legacyMachineFilePath(FILENAME);\n }\n\n /** Les fichiers qui portent des surcharges : les coffres, et l'emplacement d'avant. */\n private async sourcePaths(): Promise<string[]> {\n const roots = await allVaultRoots();\n return [\n this.getLegacyFilePath(),\n await keyedFilePath(FILENAME),\n ...roots.map((root) => join(root, FILENAME)),\n ];\n }\n\n /**\n * Charger, et recharger quand les fichiers ont bougé sous nos pieds.\n *\n * L'empreinte se prend **après** `ensureProjectsLoaded` : la liste des coffres\n * en dépend, et une empreinte prise sur une liste incomplète ne ressemblerait\n * à aucune des suivantes — le store se rechargerait à chaque lecture.\n */\n private async load(): Promise<void> {\n await this.disk.load(async () => {\n // Verrouillé : rien ne se déchiffre, et marquer le store chargé avec la\n // moitié des données cacherait le reste jusqu'au redémarrage. Testé avant\n // tout le reste : tant que la clé manque, il n'y a rien à aller voir.\n if (!getEncryptionKey()) return null;\n // Les projets ensuite : tant qu'ils sont inconnus, tout se résoudrait vers\n // le coffre de lancement et y serait réécrit à la première sauvegarde —\n // hors de l'organisation propriétaire.\n await ensureProjectsLoaded();\n const fingerprint = await fingerprintFiles(await this.sourcePaths());\n if (this.loaded && fingerprint === this.fingerprint) return null;\n const next = await this.readVaults();\n return () => {\n this.data = next.data;\n this.diskEncryptedSlots = next.diskEncryptedSlots;\n this.roots = next.roots;\n this.unreadableSecrets = next.unreadableSecrets;\n this.fingerprint = fingerprint;\n this.loaded = true;\n };\n });\n }\n\n /**\n * Read every vault, then the places older versions used, into fresh tables\n * that `load` swaps in at once.\n *\n * Variable ids are unique, so merging the files cannot collide; a vault read\n * later simply wins over a legacy copy of the same override.\n */\n private async readVaults(): Promise<{\n data: OverridesData;\n diskEncryptedSlots: Record<string, string>;\n roots: Map<string, string>;\n unreadableSecrets: Set<string>;\n }> {\n const data: OverridesData = {};\n const diskEncryptedSlots: Record<string, string> = {};\n const roots = new Map<string, string>();\n const unreadableSecrets = new Set<string>();\n\n for (const path of await this.sourcePaths()) {\n let parsed: OverridesData;\n try {\n parsed = JSON.parse(await readFile(path, 'utf-8')) as OverridesData;\n } catch {\n continue;\n }\n\n // Cache encrypted slots then decrypt\n Object.assign(\n diskEncryptedSlots,\n extractEncryptedVariableSlots(parsed as Record<string, { value: VariableSlot }>),\n );\n const decrypted = decryptVariableSlots(\n parsed as Record<string, { value: VariableSlot }>,\n 'environment-overrides',\n (variableId) => unreadableSecrets.add(variableId),\n vaultIdOfRoot(dirname(path)),\n ) as Record<string, { value: VariableSlot }>;\n\n for (const [id, override] of Object.entries(decrypted)) {\n // Drop any legacy `key` field written by older versions: it has no\n // authority and goes stale when the variable is renamed.\n data[id] = { value: override.value };\n roots.set(id, dirname(path));\n }\n }\n\n return { data, diskEncryptedSlots, roots, unreadableSecrets };\n }\n\n private save(): Promise<void> {\n return this.disk.save(() => this.doSave());\n }\n\n /**\n * Write each vault that holds — or held — an override.\n *\n * A vault emptied by this save is still written, as an empty object: an\n * override that moved to its project's vault must not survive in the one it\n * came from.\n */\n private async doSave(): Promise<void> {\n const byRoot = new Map<string, OverridesData>();\n for (const root of this.roots.values()) byRoot.set(root, {});\n\n for (const [variableId, override] of Object.entries(this.data)) {\n const root = await this.rootFor(variableId);\n this.roots.set(variableId, root);\n const bucket = byRoot.get(root) ?? {};\n bucket[variableId] = override;\n byRoot.set(root, bucket);\n }\n\n for (const [root, overrides] of byRoot) {\n const encrypted = this.keepUnreadableSecrets(encryptVariableSlots(\n overrides as Record<string, { value: VariableSlot }>,\n this.diskEncryptedSlots,\n vaultIdOfRoot(root),\n ) as OverridesData);\n Object.assign(\n this.diskEncryptedSlots,\n extractEncryptedVariableSlots(encrypted as Record<string, { value: VariableSlot }>),\n );\n\n await mkdir(root, { recursive: true });\n const path = join(root, FILENAME);\n const tmpPath = path + '.tmp';\n await writeFile(tmpPath, JSON.stringify(encrypted, null, 2), 'utf-8');\n await renameWithRetry(tmpPath, path);\n await chmod(path, 0o600);\n }\n }\n\n /**\n * Rendre au disque le chiffré d'une surcharge illisible, plutôt qu'un blanc.\n *\n * Pendant du garde-fou du store des environnements : tant que la valeur en\n * mémoire est vide, c'est que personne n'a retouché la variable et que son\n * chiffré fait toujours foi.\n */\n private keepUnreadableSecrets(overrides: OverridesData): OverridesData {\n if (this.unreadableSecrets.size === 0) return overrides;\n const result = { ...overrides };\n for (const variableId of this.unreadableSecrets) {\n const ciphertext = this.diskEncryptedSlots[variableId];\n const override = result[variableId];\n if (!ciphertext || !override || override.value.value) continue;\n result[variableId] = { ...override, value: { ...override.value, value: ciphertext } };\n }\n return result;\n }\n\n async getOverride(variableId: string): Promise<VariableOverride | null> {\n await this.load();\n return this.data[variableId] ?? null;\n }\n\n async setOverride(variableId: string, override: VariableOverride): Promise<void> {\n await this.load();\n this.data[variableId] = { value: override.value };\n await this.save();\n }\n\n async removeOverride(variableId: string): Promise<void> {\n await this.load();\n if (!this.data[variableId]) return;\n delete this.data[variableId];\n this.unreadableSecrets.delete(variableId);\n await this.save();\n }\n\n async getAll(): Promise<Record<string, VariableOverride>> {\n await this.load();\n return { ...this.data };\n }\n\n async removeOverridesForVariables(variableIds: string[]): Promise<void> {\n await this.load();\n let changed = false;\n for (const id of variableIds) {\n if (this.data[id]) {\n delete this.data[id];\n this.unreadableSecrets.delete(id);\n changed = true;\n }\n }\n if (changed) await this.save();\n }\n}\n\nexport const environmentOverridesStore = new EnvironmentOverridesStore();\n","import type { Environment, Variable, VariableSlot, VariableOverride, ResolvedEnvironment, MissingVariable } from '@runeya/packages-shared';\nimport { MASKED_VALUE, isSharedWithAi } from '@runeya/packages-shared';\nimport { environmentStore } from './environment-store.js';\nimport { environmentOverridesStore } from './environment-overrides-store.js';\n\n/** Options de résolution. */\nexport interface ResolveOptions {\n /** `false` pour ignorer les surcharges machine-locales. Défaut : elles s'appliquent. */\n applyOverrides?: boolean;\n}\n\ninterface VariableSource {\n environmentId: string;\n environmentName: string;\n overridden: boolean;\n resolvedFrom?: { environmentId: string; environmentName: string };\n /** Environment carrying the machine-local override that won for this key */\n overriddenBy?: { environmentId: string; environmentName: string };\n}\n\n/** Winning override for a variable key, plus the environment it comes from */\ninterface WinningOverride {\n variable: Variable;\n source?: { environmentId: string; environmentName: string };\n}\n\ninterface DagResult {\n variables: Record<string, Variable>;\n sources: Record<string, VariableSource>;\n /** Concrete parent values keyed by variable key (pre-dedup), used for interpolation context */\n parentEnv: Record<string, string>;\n /** Keys in parentEnv that are secret */\n parentSecretKeys: Set<string>;\n /** Maps variable key → source environment info for parent variables (before child override) */\n parentKeySources: Record<string, { environmentId: string; environmentName: string }>;\n}\n\n/**\n * Interpolate {{environment.KEY}} references in a value string.\n * envContext is the flat dict of resolved environment values.\n * Returns the interpolated string.\n * Missing keys are left as-is ({{environment.MISSING}} -> unchanged).\n */\nfunction interpolateValue(raw: string, envContext: Record<string, string>): string {\n return raw.replace(/\\{\\{environment\\.([^}]+)\\}\\}/g, (match, key) => {\n return envContext[key] !== undefined ? envContext[key] : match;\n });\n}\n\n/**\n * Resolve a Variable to its final string value.\n * Uses variable.value slot, computes interpolate(pre + value + post).\n *\n * The three parts are interpolated, not just `value`: a prefix like\n * `postgres://{{environment.DB_USER}}@` is as legitimate a reference as the\n * value itself, and the parts are concatenated into one string anyway. They\n * are interpolated separately so that a reference cannot be formed by the\n * seam between two parts (a `pre` ending in `{{environment.` completed by a\n * `value` starting with `KEY}}`), which would let a prefix reach a variable\n * the author never named.\n */\nfunction resolveVariable(\n variable: Variable,\n envContext: Record<string, string>,\n): { value: string; isSecret: boolean } {\n const slot = variable.value;\n const finalValue = interpolateValue(slot.pre, envContext)\n + interpolateValue(slot.value, envContext)\n + interpolateValue(slot.post, envContext);\n return { value: finalValue, isSecret: slot.isSecret };\n}\n\n/** Every part of a slot that may carry `{{environment.KEY}}` references. */\nfunction slotReferenceText(variable: Variable): string {\n const slot = variable.value;\n // Séparateur : deux parties voisines ne doivent pas former une référence\n // qu'aucune ne contient — même raison que l'interpolation partie par partie.\n return `${slot.pre}\\n${slot.value}\\n${slot.post}`;\n}\n\n/**\n * Ce qu'un agent IA a le droit de lire d'un environnement résolu.\n *\n * Une variable publique n'est pas un secret : elle ressort telle quelle. Un\n * secret ne ressort que si son auteur l'a partagé — `sharedKeys` porte les\n * clés dont la définition le dit (`isSharedWithAi`).\n *\n * Le croisement se fait ici, et pas dans le drapeau, parce que les deux moitiés\n * ne viennent pas du même endroit : ce qui est secret se décide à la résolution\n * (une variable non marquée qui référence un secret le devient), ce qui est\n * partagé se lit sur la définition.\n *\n * **Ce qui est caché, c'est la valeur, pas la clé.** Retirer la clé aussi\n * faisait croire à l'agent que la variable n'existait pas : il proposait de\n * l'ajouter, ou cherchait ailleurs la cause d'un service qui, lui, la reçoit\n * bien. Une clé masquée sort donc avec `***` pour valeur, et `hiddenKeys` la\n * nomme.\n *\n * `***` masque d'un seul coup le préfixe, la valeur et le suffixe : l'env\n * résolu ne porte déjà qu'une chaîne, leur concaténation interpolée. Un masque\n * partie par partie livrerait la forme du secret (« https://…@ » d'un préfixe,\n * un suffixe de domaine), et c'est encore trop.\n */\nexport const HIDDEN_VALUES_NOTICE =\n `Values shown as ${MASKED_VALUE} are secrets their author did not share with AI. `\n + 'The service does receive them: never treat such a key as missing, and never pass '\n + `${MASKED_VALUE} as its value.`;\n\nexport function filterEnvForAi(\n resolved: { env: Record<string, string>; envSecrets: string[] },\n sharedKeys: Iterable<string>,\n): { env: Record<string, string>; envSecrets: string[]; hiddenKeys: string[]; hiddenNotice?: string } {\n const secret = new Set(resolved.envSecrets);\n const shared = new Set(sharedKeys);\n const env: Record<string, string> = {};\n const envSecrets: string[] = [];\n const hiddenKeys: string[] = [];\n for (const [key, value] of Object.entries(resolved.env)) {\n const hidden = secret.has(key) && !shared.has(key);\n env[key] = hidden ? MASKED_VALUE : value;\n if (secret.has(key)) envSecrets.push(key);\n if (hidden) hiddenKeys.push(key);\n }\n return {\n env,\n envSecrets,\n hiddenKeys,\n ...(hiddenKeys.length > 0 ? { hiddenNotice: HIDDEN_VALUES_NOTICE } : {}),\n };\n}\n\n/** Ce qu'un agent peut savoir d'une variable sans en lire la valeur. */\nexport interface AiVariableDetail {\n key: string;\n /** Ce service reçoit-il cette variable ? Sinon elle est définie ailleurs dans le projet. */\n inService: boolean;\n environmentId: string;\n environmentName: string;\n /** `service` : environnement dédié à un service. `global` : environnement de projet. */\n scope: 'global' | 'service';\n /** Le service auquel cet environnement est dédié, quand `scope` vaut `service`. */\n environmentServiceId?: string;\n description?: string;\n secret: boolean;\n /** La valeur de ce secret est-elle lisible par une IA ? (`isSharedWithAi`) */\n readableByAi: boolean;\n /** Posée dans l'environnement du process des agents lancés depuis Runeya. */\n injectedIntoAi: boolean;\n required: boolean;\n overrideOnly: boolean;\n /** Ce poste porte une surcharge pour cette variable. */\n overridden: boolean;\n /**\n * Ce que la surcharge de ce poste remplace : la valeur partagée par l'équipe,\n * soumise au même masquage que les autres (`***` si la clé ne se lit pas).\n * Absent quand il n'y a pas de surcharge — la valeur partagée est alors celle\n * que `env` rend déjà.\n *\n * Les `{{service.*}}` n'y sont pas interpolés : ces variables intégrées sont\n * résolues plus tard, au moment du déploiement.\n */\n sharedValue?: string;\n}\n\n/**\n * Décrire les variables d'un projet **sans en rendre aucune valeur**.\n *\n * Un agent qui lit `env` connaît l'effet (lisible, ou `***`) mais pas la cause :\n * il ne peut ni dire dans quel environnement aller changer une variable, ni\n * répéter à quoi elle sert, ni distinguer « non partagée » de « pas encore\n * renseignée ». Il le devinait, et devinait parfois de travers.\n *\n * Ce qui justifie de sortir ici ce que `environment.get` n'a pas le droit de\n * rendre au MCP : l'interdit porte sur les **valeurs**, que cet inventaire ne\n * touche pas. Une clé, un nom d'environnement et une case cochée ne sont pas\n * des secrets — et la description est écrite précisément pour celui qui devra\n * remplir la variable.\n *\n * Une clé définie dans plusieurs environnements donne une entrée par\n * environnement : c'est ce qui dit où la changer.\n *\n * `secret` et `readableByAi` décrivent ce que `env` fait vraiment, jamais ce\n * que le slot laisse croire : une variable masquée par contagion doit sortir\n * `readableByAi: false`, sinon l'agent lit une contradiction et cherche le bug\n * ailleurs — voire tente de contourner le masquage.\n */\nexport function describeVariables(\n environments: Environment[],\n ctx: {\n serviceKeys: Set<string>;\n overriddenVariableIds: Set<string>;\n /**\n * Les valeurs partagées, clé → valeur, **déjà passées par\n * `filterEnvForAi`** : le masquage ne se décide pas deux fois.\n */\n sharedValues: Record<string, string>;\n /**\n * Les clés que la résolution tient pour secrètes, contagion comprise : une\n * variable non marquée qui interpole un secret en devient un\n * (`collectSecretKeys`). Le slot seul l'ignore, et l'inventaire annonçait\n * alors « lisible » une clé que `env` rendait pourtant masquée.\n */\n resolvedSecretKeys: Set<string>;\n /** Les clés que `env` a effectivement masquées, pour ne pas les contredire. */\n maskedKeys: Set<string>;\n },\n): AiVariableDetail[] {\n const details: AiVariableDetail[] = [];\n for (const environment of environments) {\n for (const [variableId, variable] of Object.entries(environment.variables ?? {})) {\n const slot = variable.value;\n const isOverridden = ctx.overriddenVariableIds.has(variableId);\n // Le secret se décide à la résolution, la permission sur la définition.\n // Hors de l'environnement de ce service, la résolution n'a rien à dire :\n // le slot fait alors foi, faute de mieux.\n const isSecret = slot.isSecret || ctx.resolvedSecretKeys.has(variable.key);\n const readableByAi = ctx.maskedKeys.has(variable.key)\n ? false\n : !isSecret || isSharedWithAi(slot);\n details.push({\n key: variable.key,\n inService: ctx.serviceKeys.has(variable.key),\n environmentId: environment.id,\n environmentName: environment.name,\n scope: environment.scope,\n ...(environment.scope === 'service' && environment.reference\n ? { environmentServiceId: environment.reference }\n : {}),\n ...(slot.description ? { description: slot.description } : {}),\n secret: isSecret,\n readableByAi,\n injectedIntoAi: slot.injectIntoAi,\n required: slot.required,\n overrideOnly: slot.overrideOnly,\n overridden: isOverridden,\n ...(isOverridden && ctx.sharedValues[variable.key] !== undefined\n ? { sharedValue: ctx.sharedValues[variable.key] }\n : {}),\n });\n }\n }\n return details.sort((a, b) => a.key.localeCompare(b.key) || a.environmentName.localeCompare(b.environmentName));\n}\n\n/**\n * Appliquer une surcharge machine à une variable : **sa valeur, et rien\n * d'autre**.\n *\n * Une surcharge répond à « quelle valeur sur ce poste » (un chemin local, un\n * jeton personnel, un port déjà pris). Elle ne répond pas à « cette variable\n * est-elle secrète, partagée avec l'IA, obligatoire » — ce sont des décisions\n * qui appartiennent à la définition, partagées par toute l'équipe.\n *\n * Le slot d'une surcharge porte pourtant ces champs, parce qu'il réutilise le\n * schéma d'un slot ordinaire, et l'interface y recopiait `isSecret`. Prendre le\n * slot entier revenait donc à figer une copie des drapeaux au jour de\n * l'écriture : une variable repassée en publique restait secrète à la\n * résolution parce que sa surcharge, écrite la veille, disait encore le\n * contraire — l'écran et le serveur ne décrivaient plus la même variable, et\n * aucun geste dans l'interface ne rattrapait l'écart.\n *\n * Les drapeaux de la surcharge sont donc ignorés ici, comme\n * `findMissingVariables` le fait déjà pour `required` et `overrideOnly`.\n */\nfunction withOverriddenValue(variable: Variable, override: VariableSlot): Variable {\n return {\n ...variable,\n value: {\n ...variable.value,\n value: override.value,\n pre: override.pre,\n post: override.post,\n },\n };\n}\n\nclass EnvironmentResolver {\n async resolveForService(\n ctx: { serviceId: string; activeEnvironmentId: string },\n opts?: ResolveOptions,\n ): Promise<{ env: Record<string, string>; envSecrets: string[] }> {\n if (!ctx.activeEnvironmentId) {\n return { env: {}, envSecrets: [] };\n }\n\n // Find the service-scoped environment for this service + active global env\n const serviceEnv = await environmentStore.findServiceEnvironment(ctx.serviceId, ctx.activeEnvironmentId);\n\n if (!serviceEnv) {\n // No service env: resolve just the global env\n return this.resolveEnvironment(ctx.activeEnvironmentId, opts);\n }\n\n // Resolve the service env (which inherits from global via parentIds)\n return this.resolveEnvironment(serviceEnv.id, opts);\n }\n\n /**\n * `applyOverrides: false` rend ce que l'équipe partage, sans ce que ce poste\n * a mis par-dessus : c'est la réponse à « qu'est-ce que ma surcharge\n * remplace ». Le défaut reste `true` — tout le reste du produit veut la\n * valeur avec laquelle le service tourne réellement.\n */\n async resolveEnvironment(environmentId: string, opts?: ResolveOptions): Promise<{ env: Record<string, string>; envSecrets: string[] }> {\n const visited = new Set<string>();\n const result = await this.resolveDag(environmentId, visited);\n\n // Apply overrides, resolved as their own chain (see resolveOverridesByKey)\n const overridesByKey = opts?.applyOverrides === false\n ? {}\n : await this.resolveOverridesByKey(environmentId);\n for (const [varId, variable] of Object.entries(result.variables)) {\n const override = overridesByKey[variable.key];\n if (override) {\n result.variables[varId] = withOverriddenValue(variable, override.variable.value);\n }\n }\n\n // First pass: build raw env dict (no interpolation yet)\n const rawEnv: Record<string, string> = {};\n for (const [_varId, variable] of Object.entries(result.variables)) {\n const slot = variable.value;\n rawEnv[variable.key] = slot.pre + slot.value + slot.post;\n }\n\n // Build interpolation context:\n // Start from parent concrete values, then overlay with current concrete values.\n // This ensures {{environment.KEY}} resolves against parent values when the child\n // redefines KEY as an interpolation reference.\n const { ctx: interpolationCtx, secretKeys: ctxSecretKeys } = await this.buildInterpolationContext(environmentId, rawEnv, result.parentEnv, result.parentSecretKeys, result.parentKeySources);\n const secretKeys = this.collectSecretKeys(result.variables, ctxSecretKeys);\n\n // Second pass: interpolate and build final env dict\n const env: Record<string, string> = {};\n const envSecrets: string[] = [];\n for (const [_varId, variable] of Object.entries(result.variables)) {\n const { value, isSecret } = resolveVariable(variable, interpolationCtx);\n env[variable.key] = value;\n if (isSecret || secretKeys.has(variable.key)) {\n envSecrets.push(variable.key);\n }\n }\n\n return { env, envSecrets };\n }\n\n /**\n * Resolve an environment (with inheritance) and return only the variables\n * flagged `injectIntoAi`, as a flat KEY→value dict ready to be injected into\n * the process environment of an AI agent spawn.\n */\n async resolveAiInjectedEnv(environmentId: string): Promise<Record<string, string>> {\n if (!environmentId) return {};\n\n const visited = new Set<string>();\n const result = await this.resolveDag(environmentId, visited);\n\n // Apply overrides (same as resolveEnvironment)\n const overridesByKey = await this.resolveOverridesByKey(environmentId);\n for (const [varId, variable] of Object.entries(result.variables)) {\n const override = overridesByKey[variable.key];\n if (override) {\n result.variables[varId] = withOverriddenValue(variable, override.variable.value);\n }\n }\n\n // Build raw env for interpolation context\n const rawEnv: Record<string, string> = {};\n for (const variable of Object.values(result.variables)) {\n const slot = variable.value;\n rawEnv[variable.key] = slot.pre + slot.value + slot.post;\n }\n const { ctx: interpolationCtx } = await this.buildInterpolationContext(\n environmentId,\n rawEnv,\n result.parentEnv,\n result.parentSecretKeys,\n result.parentKeySources,\n );\n\n // Keep only flagged variables, interpolating their final value.\n const injected: Record<string, string> = {};\n for (const variable of Object.values(result.variables)) {\n if (!variable.value.injectIntoAi) continue;\n const { value } = resolveVariable(variable, interpolationCtx);\n injected[variable.key] = value;\n }\n return injected;\n }\n\n /**\n * Les variables qu'il faut remplir avant qu'un service de cet environnement\n * puisse démarrer.\n *\n * Deux motifs, et ils ne se mesurent pas au même endroit :\n *\n * - `required` porte sur la valeur **finale**, interpolation et surcharge\n * comprises : une variable obligatoire dont la valeur ne tient qu'à une\n * référence morte est aussi vide qu'une case blanche.\n * - `overrideOnly` porte sur l'**existence d'une surcharge machine**. Elle\n * n'a par construction pas de valeur partagée ; ce qui manque n'est pas un\n * contenu, c'est la réponse de ce poste-ci.\n *\n * Les drapeaux se lisent sur la définition, jamais sur le slot résolu : une\n * surcharge remplace le slot entier et ne porte aucun drapeau — les y lire\n * rendrait toute variable surchargée silencieusement facultative.\n */\n async findMissingVariables(environmentId: string): Promise<MissingVariable[]> {\n if (!environmentId) return [];\n\n const [{ env }, definitions, overridesByKey] = await Promise.all([\n this.resolveEnvironment(environmentId),\n this.resolveDag(environmentId, new Set()),\n this.resolveOverridesByKey(environmentId),\n ]);\n\n const missing: MissingVariable[] = [];\n for (const [variableId, variable] of Object.entries(definitions.variables)) {\n const slot = variable.value;\n const source = definitions.sources[variableId];\n const base = {\n variableId,\n key: variable.key,\n description: slot.description,\n isSecret: slot.isSecret,\n environmentId: source?.environmentId ?? environmentId,\n environmentName: source?.environmentName ?? '',\n };\n\n if (slot.overrideOnly && !overridesByKey[variable.key]) {\n missing.push({ ...base, reason: 'overrideOnly' });\n continue;\n }\n if (slot.required && (env[variable.key] ?? '') === '') {\n missing.push({ ...base, reason: 'required' });\n }\n }\n return missing;\n }\n\n /**\n * Tout ce qu'il reste à remplir sous l'environnement courant.\n *\n * Deux périmètres, et il faut les deux :\n *\n * 1. **L'environnement courant lui-même**, héritage compris —\n * `findMissingVariables` remonte ses `parentIds`. C'est là que vivent les\n * variables globales du projet, et c'est la première branche balayée.\n * 2. **Les environnements de service qui s'activent avec lui**\n * (`activateOn`). Ceux-là ne sont pas des ancêtres du global : ils en\n * héritent, dans l'autre sens. Ne pas y descendre revenait à ne rien\n * réclamer d'un service jusqu'à ce qu'on essaie de le démarrer.\n *\n * Dédoublonné par identifiant de variable : une variable du global remonte\n * dans chaque branche de service qui en hérite, et l'assistant ne doit pas\n * demander deux fois la même chose.\n */\n async findMissingForActiveEnvironment(globalEnvId: string): Promise<MissingVariable[]> {\n if (!globalEnvId) return [];\n\n const serviceEnvs = await environmentStore.listByActivateOn(globalEnvId);\n const branches = await Promise.all([\n this.findMissingVariables(globalEnvId),\n ...serviceEnvs.map((env) => this.findMissingVariables(env.id)),\n ]);\n\n const seen = new Set<string>();\n const missing: MissingVariable[] = [];\n for (const branch of branches) {\n for (const item of branch) {\n if (seen.has(item.variableId)) continue;\n seen.add(item.variableId);\n missing.push(item);\n }\n }\n return missing;\n }\n\n /**\n * Les clés que leur auteur a partagées avec les IA, héritage compris.\n *\n * Le partage se lit sur la **définition**, et seulement là : une surcharge\n * machine ne dit que la valeur de ce poste (`withOverriddenValue`). Il n'y a\n * donc qu'un endroit où ce drapeau existe, et rien à réconcilier.\n *\n * Des clés, pas des valeurs : la valeur rendue reste celle que le service\n * reçoit, surcharges et interpolation comprises.\n */\n async resolveAiSharedKeys(environmentId: string): Promise<Set<string>> {\n if (!environmentId) return new Set();\n const result = await this.resolveDag(environmentId, new Set());\n const keys = new Set<string>();\n for (const variable of Object.values(result.variables)) {\n if (isSharedWithAi(variable.value)) keys.add(variable.key);\n }\n return keys;\n }\n\n /**\n * Idem, pour ce qu'un service verra réellement : son environnement dédié\n * quand il en a un, l'environnement global sinon — la règle de sélection de\n * `resolveForService`.\n */\n async resolveAiSharedKeysForService(ctx: { serviceId: string; activeEnvironmentId: string }): Promise<Set<string>> {\n if (!ctx.activeEnvironmentId) return new Set();\n const serviceEnv = await environmentStore.findServiceEnvironment(ctx.serviceId, ctx.activeEnvironmentId);\n return this.resolveAiSharedKeys(serviceEnv ? serviceEnv.id : ctx.activeEnvironmentId);\n }\n\n /**\n * Idem, pour ce qu'un service verra réellement : son environnement dédié\n * quand il en a un, l'environnement global sinon. Miroir de\n * `resolveForService`, dont il partage la règle de sélection.\n */\n async findMissingForService(ctx: { serviceId: string; activeEnvironmentId: string }): Promise<MissingVariable[]> {\n if (!ctx.activeEnvironmentId) return [];\n const serviceEnv = await environmentStore.findServiceEnvironment(ctx.serviceId, ctx.activeEnvironmentId);\n return this.findMissingVariables(serviceEnv ? serviceEnv.id : ctx.activeEnvironmentId);\n }\n\n async resolveEnvironmentWithSources(environmentId: string): Promise<ResolvedEnvironment> {\n const visited = new Set<string>();\n const result = await this.resolveDag(environmentId, visited);\n\n // Apply overrides, resolved as their own chain (see resolveOverridesByKey)\n const overridesByKey = await this.resolveOverridesByKey(environmentId);\n for (const [varId, variable] of Object.entries(result.variables)) {\n const override = overridesByKey[variable.key];\n if (override) {\n result.variables[varId] = withOverriddenValue(variable, override.variable.value);\n result.sources[varId] = {\n ...result.sources[varId],\n overridden: true,\n ...(override.source ? { overriddenBy: override.source } : {}),\n };\n }\n }\n\n // First pass: build raw env dict (no interpolation yet)\n const rawEnv: Record<string, string> = {};\n for (const [_varId, variable] of Object.entries(result.variables)) {\n const slot = variable.value;\n rawEnv[variable.key] = slot.pre + slot.value + slot.post;\n }\n\n // Build interpolation context\n const { ctx: interpolationCtx, secretKeys: ctxSecretKeys, keySources } = await this.buildInterpolationContext(environmentId, rawEnv, result.parentEnv, result.parentSecretKeys, result.parentKeySources);\n const secretKeys = this.collectSecretKeys(result.variables, ctxSecretKeys);\n\n // Second pass: interpolate and build final env dict\n const env: Record<string, string> = {};\n const envSecrets: string[] = [];\n for (const [_varId, variable] of Object.entries(result.variables)) {\n const { value, isSecret } = resolveVariable(variable, interpolationCtx);\n env[variable.key] = value;\n if (isSecret || secretKeys.has(variable.key)) {\n envSecrets.push(variable.key);\n }\n }\n\n // Post-process: for pure interpolation references, annotate `resolvedFrom`\n // so the frontend knows where the resolved value actually comes from,\n // while keeping the source pointing to where the variable is defined.\n const refPattern = /^\\{\\{environment\\.([^}]+)\\}\\}$/;\n for (const [varId, variable] of Object.entries(result.variables)) {\n const match = variable.value.value.match(refPattern);\n if (match) {\n const refSource = keySources[match[1]];\n if (refSource && result.sources[varId]?.environmentId !== refSource.environmentId) {\n result.sources[varId] = {\n ...result.sources[varId],\n resolvedFrom: refSource,\n };\n }\n }\n }\n\n return {\n variables: result.variables,\n env,\n envSecrets,\n sources: result.sources,\n };\n }\n\n /** Check if a raw value string interpolates any key that is secret in the context */\n /**\n * Toutes les clés dont la valeur est, directement ou par interpolation, un\n * secret.\n *\n * Le contexte d'interpolation ne connaît que les secrets *hérités* : les\n * secrets définis dans le même environnement n'y figurent pas, si bien qu'un\n * `AUTH='Bearer {{environment.TOKEN}}'` voisin de son propre `TOKEN` secret\n * ressortait non marqué — et donc non masqué par toute la chaîne en aval.\n *\n * On part des secrets hérités plus ceux déclarés ici, puis on propage\n * jusqu'au point fixe : une valeur qui référence une clé secrète devient\n * secrète à son tour, y compris en chaîne (A secret → B cite A → C cite B).\n */\n private collectSecretKeys(\n variables: Record<string, Variable>,\n parentSecretKeys: Set<string>,\n ): Set<string> {\n const secretKeys = new Set(parentSecretKeys);\n for (const variable of Object.values(variables)) {\n if (variable.value.isSecret) secretKeys.add(variable.key);\n }\n let changed = true;\n while (changed) {\n changed = false;\n for (const variable of Object.values(variables)) {\n if (secretKeys.has(variable.key)) continue;\n if (this.interpolatesSecretKey(slotReferenceText(variable), secretKeys)) {\n secretKeys.add(variable.key);\n changed = true;\n }\n }\n }\n return secretKeys;\n }\n\n private interpolatesSecretKey(rawValue: string, ctxSecretKeys: Set<string>): boolean {\n const refs = [...rawValue.matchAll(/\\{\\{environment\\.([^}]+)\\}\\}/g)].map(m => m[1]);\n return refs.some(ref => ctxSecretKeys.has(ref));\n }\n\n /**\n * Build the interpolation context for an environment.\n *\n * For inheriting envs (has parents): start from parent concrete values,\n * then overlay with current concrete values. This ensures that\n * {{environment.KEY}} resolves against the parent's value when the child\n * redefines KEY as an interpolation reference.\n *\n * For isolated service envs (scope=service, activateOn set, no parents):\n * the global env is resolved and used as fallback.\n */\n private async buildInterpolationContext(\n environmentId: string,\n rawEnv: Record<string, string>,\n parentEnv: Record<string, string>,\n parentSecretKeys: Set<string>,\n parentKeySources: Record<string, { environmentId: string; environmentName: string }>,\n ): Promise<{ ctx: Record<string, string>; secretKeys: Set<string>; keySources: Record<string, { environmentId: string; environmentName: string }> }> {\n const environment = await environmentStore.get(environmentId);\n\n // Isolated service env: resolve global env for interpolation context\n if (\n environment\n && environment.scope === 'service'\n && environment.activateOn\n && (!environment.parentIds || environment.parentIds.length === 0)\n ) {\n const globalResolved = await this.resolveEnvironmentWithSources(environment.activateOn);\n const secretKeys = new Set(globalResolved.envSecrets);\n // Build keySources from global env variables\n const keySources: Record<string, { environmentId: string; environmentName: string }> = {};\n for (const [varId, variable] of Object.entries(globalResolved.variables)) {\n const source = globalResolved.sources[varId];\n if (source) {\n keySources[variable.key] = { environmentId: source.environmentId, environmentName: source.environmentName };\n }\n }\n // Start with global values, then override with local values that are\n // concrete (not themselves interpolation references)\n const ctx = { ...globalResolved.env };\n for (const [key, value] of Object.entries(rawEnv)) {\n if (!/\\{\\{environment\\.[^}]+\\}\\}/.test(value)) {\n ctx[key] = value;\n }\n }\n return { ctx, secretKeys, keySources };\n }\n\n // Inheriting env: start from parent concrete values, overlay with concrete rawEnv values\n const ctx = { ...parentEnv };\n for (const [key, value] of Object.entries(rawEnv)) {\n if (!/\\{\\{environment\\.[^}]+\\}\\}/.test(value)) {\n ctx[key] = value;\n }\n }\n return { ctx, secretKeys: parentSecretKeys, keySources: parentKeySources };\n }\n\n /**\n * For service-scoped envs, compute effective parentIds by also including\n * the service-scoped envs of ancestor global environments.\n *\n * Example: \"Server (test)\" has parentIds=[test-global]. test-global has\n * parentIds=[Local-global]. This method adds \"Server (Local)\" to the\n * effective parents so service-specific variables from ancestor envs\n * are inherited correctly.\n */\n private async getEffectiveParentIds(environment: { scope?: string; reference?: string; activateOn?: string; parentIds: string[] }): Promise<string[]> {\n if (environment.scope !== 'service' || !environment.reference || !environment.activateOn) {\n return environment.parentIds;\n }\n\n // Walk each global parent and find the service-scoped env for the same service\n const additionalIds: string[] = [];\n for (const parentId of environment.parentIds) {\n const parentEnv = await environmentStore.get(parentId);\n if (!parentEnv || parentEnv.scope !== 'global') continue;\n\n for (const grandparentGlobalId of parentEnv.parentIds) {\n const ancestorServiceEnv = await environmentStore.findServiceEnvironment(environment.reference, grandparentGlobalId);\n if (ancestorServiceEnv && !environment.parentIds.includes(ancestorServiceEnv.id)) {\n additionalIds.push(ancestorServiceEnv.id);\n }\n }\n }\n\n if (additionalIds.length === 0) return environment.parentIds;\n return [...environment.parentIds, ...additionalIds];\n }\n\n /**\n * Project an environment's variables onto their overrides: keep only the\n * variables that have one, and swap in the override's value slot. The key\n * always comes from the definition.\n *\n * Feeding this projection back through `resolveDag` resolves the override\n * chain with the exact same inheritance and dedup-by-key rules as the value\n * chain — so an override set on a parent env is no longer swallowed when a\n * child (or a service env) redeclares the same key.\n */\n private projectOverrides(\n variables: Record<string, Variable>,\n overrides: Record<string, VariableOverride>,\n ): Record<string, Variable> {\n const projected: Record<string, Variable> = {};\n for (const [varId, variable] of Object.entries(variables)) {\n const override = overrides[varId];\n if (override) {\n projected[varId] = { key: variable.key, value: override.value };\n }\n }\n return projected;\n }\n\n /**\n * Resolve the override chain independently of the value chain and return the\n * winning override per variable key (empty when nothing is overridden).\n */\n private async resolveOverridesByKey(environmentId: string): Promise<Record<string, WinningOverride>> {\n const allOverrides = await environmentOverridesStore.getAll();\n if (Object.keys(allOverrides).length === 0) return {};\n\n const result = await this.resolveDag(environmentId, new Set(), (variables) =>\n this.projectOverrides(variables, allOverrides),\n );\n\n const byKey: Record<string, WinningOverride> = {};\n for (const [varId, variable] of Object.entries(result.variables)) {\n const source = result.sources[varId];\n byKey[variable.key] = {\n variable,\n ...(source ? { source: { environmentId: source.environmentId, environmentName: source.environmentName } } : {}),\n };\n }\n return byKey;\n }\n\n private async resolveDag(\n environmentId: string,\n visited: Set<string>,\n project?: (variables: Record<string, Variable>) => Record<string, Variable>,\n ): Promise<DagResult> {\n if (visited.has(environmentId)) {\n throw new Error(`Circular dependency detected in environment inheritance for ${environmentId}`);\n }\n\n const environment = await environmentStore.get(environmentId);\n if (!environment) {\n throw new Error(`Environment \"${environmentId}\" not found`);\n }\n\n visited.add(environmentId);\n\n // For service-scoped envs: ensure we also inherit from ancestor service-scoped envs.\n // When a service env's global parent itself has parent globals, we need to include\n // the service-scoped envs of those ancestor globals in the resolution chain.\n const effectiveParentIds = await this.getEffectiveParentIds(environment);\n\n // Resolve all parents first\n const parentResults: DagResult[] = [];\n for (const parentId of effectiveParentIds) {\n const parentVisited = new Set(visited);\n const parentResult = await this.resolveDag(parentId, parentVisited, project);\n parentResults.push(parentResult);\n }\n\n // Merge parent variables (left-to-right, later parents override earlier)\n const mergedVariables: Record<string, Variable> = {};\n const sources: Record<string, VariableSource> = {};\n\n for (const result of parentResults) {\n // Dedup by key: if a later parent has a variable with the same key, remove the earlier one\n for (const [varId, variable] of Object.entries(result.variables)) {\n for (const [existingId, existingVar] of Object.entries(mergedVariables)) {\n if (existingVar.key === variable.key && existingId !== varId) {\n delete mergedVariables[existingId];\n delete sources[existingId];\n }\n }\n mergedVariables[varId] = variable;\n sources[varId] = result.sources[varId] ?? sources[varId];\n }\n }\n\n // Build parentEnv: concrete values from parents BEFORE child dedup/override\n // Used as interpolation context so {{environment.KEY}} resolves against parent values\n const parentEnv: Record<string, string> = {};\n const parentSecretKeys = new Set<string>();\n const parentKeySources: Record<string, { environmentId: string; environmentName: string }> = {};\n for (const [varId, variable] of Object.entries(mergedVariables)) {\n const slot = variable.value;\n parentEnv[variable.key] = slot.pre + slot.value + slot.post;\n if (slot.isSecret) {\n parentSecretKeys.add(variable.key);\n }\n const source = sources[varId];\n if (source) {\n parentKeySources[variable.key] = { environmentId: source.environmentId, environmentName: source.environmentName };\n }\n }\n // Also include parent-of-parent values for deeper chains.\n // Prefer concrete values over interpolation references: if parentEnv already has a\n // raw {{environment.KEY}} ref for a key, replace it with a concrete value if found.\n const isInterpRef = (v: string) => /\\{\\{environment\\.[^}]+\\}\\}/.test(v);\n for (const result of parentResults) {\n for (const [key, value] of Object.entries(result.parentEnv)) {\n const existingIsRef = key in parentEnv && isInterpRef(parentEnv[key]);\n const newIsConcrete = !isInterpRef(value);\n if (!(key in parentEnv) || (existingIsRef && newIsConcrete)) {\n parentEnv[key] = value;\n }\n }\n for (const key of result.parentSecretKeys) {\n parentSecretKeys.add(key);\n }\n for (const [key, source] of Object.entries(result.parentKeySources)) {\n if (!(key in parentKeySources)) {\n parentKeySources[key] = source;\n }\n }\n }\n // Une variable héritée qui interpole un secret est elle-même un secret, et\n // doit le rester pour les descendants — sans ça le caractère secret se perd\n // dès qu'on descend d'un niveau.\n for (const key of this.collectSecretKeys(mergedVariables, parentSecretKeys)) {\n parentSecretKeys.add(key);\n }\n\n // Apply current environment's own variables\n const ownVariables = project ? project(environment.variables) : environment.variables;\n for (const [varId, variable] of Object.entries(ownVariables)) {\n // Remove any parent variable with the same key but different variableId (dedup by key)\n let wasInherited = varId in mergedVariables;\n for (const [existingId, existingVar] of Object.entries(mergedVariables)) {\n if (existingVar.key === variable.key && existingId !== varId) {\n delete mergedVariables[existingId];\n delete sources[existingId];\n wasInherited = true;\n }\n }\n mergedVariables[varId] = variable;\n sources[varId] = {\n environmentId: environment.id,\n environmentName: environment.name,\n overridden: wasInherited,\n };\n }\n\n return {\n variables: mergedVariables,\n sources,\n parentEnv,\n parentSecretKeys,\n parentKeySources,\n };\n }\n}\n\nexport const environmentResolver = new EnvironmentResolver();\n"],"mappings":"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","names":["ctx"]}
|
package/chunk-DA2DZBTL.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
// ../server/src/services/mcp-ready.ts
|
|
2
|
-
var EARLY_SIGNAL_TTL_MS = 6e4;
|
|
3
|
-
var waiters = /* @__PURE__ */ new Map();
|
|
4
|
-
var earlySignals = /* @__PURE__ */ new Map();
|
|
5
|
-
function signalMcpReady(id) {
|
|
6
|
-
const waiter = waiters.get(id);
|
|
7
|
-
if (waiter) {
|
|
8
|
-
waiter();
|
|
9
|
-
return;
|
|
10
|
-
}
|
|
11
|
-
if (earlySignals.has(id)) return;
|
|
12
|
-
const timer = setTimeout(() => earlySignals.delete(id), EARLY_SIGNAL_TTL_MS);
|
|
13
|
-
timer.unref?.();
|
|
14
|
-
earlySignals.set(id, timer);
|
|
15
|
-
}
|
|
16
|
-
function waitForMcpReady(id, timeoutMs, signal) {
|
|
17
|
-
const early = earlySignals.get(id);
|
|
18
|
-
if (early) {
|
|
19
|
-
clearTimeout(early);
|
|
20
|
-
earlySignals.delete(id);
|
|
21
|
-
return Promise.resolve(true);
|
|
22
|
-
}
|
|
23
|
-
if (signal?.aborted) return Promise.resolve(false);
|
|
24
|
-
return new Promise((resolve) => {
|
|
25
|
-
const finish = (ready) => {
|
|
26
|
-
clearTimeout(timer);
|
|
27
|
-
signal?.removeEventListener("abort", onAbort);
|
|
28
|
-
if (waiters.get(id) === onReady) waiters.delete(id);
|
|
29
|
-
resolve(ready);
|
|
30
|
-
};
|
|
31
|
-
const onReady = () => finish(true);
|
|
32
|
-
const onAbort = () => finish(false);
|
|
33
|
-
const timer = setTimeout(() => finish(false), timeoutMs);
|
|
34
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
35
|
-
waiters.set(id, onReady);
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export {
|
|
40
|
-
signalMcpReady,
|
|
41
|
-
waitForMcpReady
|
|
42
|
-
};
|
|
43
|
-
//# sourceMappingURL=chunk-DA2DZBTL.js.map
|
package/chunk-DA2DZBTL.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../server/src/services/mcp-ready.ts"],"sourcesContent":["/**\n * Attente du serveur MCP Runeya d'un terminal lancé par le serveur.\n *\n * Claude Code traite le prompt passé en argument avant d'avoir connecté ses\n * serveurs MCP : sur un tour court, les outils `mcp__runeya__*` manquent au\n * moment de répondre. Le runner PTY lance donc le terminal sans prompt, avec un\n * identifiant que l'agent transmet au serveur MCP (`RUNEYA_MCP_READY_ID`).\n * Une fois initialisé par le CLI, ce serveur appelle `mcpReady.signal` avec cet\n * identifiant, et le runner écrit alors le prompt.\n *\n * Tout vit en mémoire : un identifiant ne sert qu'à un lancement.\n */\n\n/** Durée de vie d'un signal arrivé avant que quelqu'un l'attende. */\nconst EARLY_SIGNAL_TTL_MS = 60_000;\n\nconst waiters = new Map<string, () => void>();\nconst earlySignals = new Map<string, ReturnType<typeof setTimeout>>();\n\n/** Note que le serveur MCP du lancement `id` est prêt. */\nexport function signalMcpReady(id: string): void {\n const waiter = waiters.get(id);\n if (waiter) { waiter(); return; }\n if (earlySignals.has(id)) return;\n const timer = setTimeout(() => earlySignals.delete(id), EARLY_SIGNAL_TTL_MS);\n timer.unref?.();\n earlySignals.set(id, timer);\n}\n\n/**\n * Attend le signal du lancement `id`. Rend `true` s'il arrive (ou était déjà\n * arrivé), `false` au bout de `timeoutMs` ou si `signal` est interrompu.\n *\n * Un agent trop ancien pour transmettre l'identifiant n'enverra jamais ce\n * signal : le délai couvre ce cas.\n */\nexport function waitForMcpReady(id: string, timeoutMs: number, signal?: AbortSignal): Promise<boolean> {\n const early = earlySignals.get(id);\n if (early) {\n clearTimeout(early);\n earlySignals.delete(id);\n return Promise.resolve(true);\n }\n if (signal?.aborted) return Promise.resolve(false);\n return new Promise<boolean>((resolve) => {\n const finish = (ready: boolean) => {\n clearTimeout(timer);\n signal?.removeEventListener('abort', onAbort);\n if (waiters.get(id) === onReady) waiters.delete(id);\n resolve(ready);\n };\n const onReady = () => finish(true);\n const onAbort = () => finish(false);\n const timer = setTimeout(() => finish(false), timeoutMs);\n signal?.addEventListener('abort', onAbort, { once: true });\n waiters.set(id, onReady);\n });\n}\n"],"mappings":";AAcA,IAAM,sBAAsB;AAE5B,IAAM,UAAU,oBAAI,IAAwB;AAC5C,IAAM,eAAe,oBAAI,IAA2C;AAG7D,SAAS,eAAe,IAAkB;AAC/C,QAAM,SAAS,QAAQ,IAAI,EAAE;AAC7B,MAAI,QAAQ;AAAE,WAAO;AAAG;AAAA,EAAQ;AAChC,MAAI,aAAa,IAAI,EAAE,EAAG;AAC1B,QAAM,QAAQ,WAAW,MAAM,aAAa,OAAO,EAAE,GAAG,mBAAmB;AAC3E,QAAM,QAAQ;AACd,eAAa,IAAI,IAAI,KAAK;AAC5B;AASO,SAAS,gBAAgB,IAAY,WAAmB,QAAwC;AACrG,QAAM,QAAQ,aAAa,IAAI,EAAE;AACjC,MAAI,OAAO;AACT,iBAAa,KAAK;AAClB,iBAAa,OAAO,EAAE;AACtB,WAAO,QAAQ,QAAQ,IAAI;AAAA,EAC7B;AACA,MAAI,QAAQ,QAAS,QAAO,QAAQ,QAAQ,KAAK;AACjD,SAAO,IAAI,QAAiB,CAAC,YAAY;AACvC,UAAM,SAAS,CAAC,UAAmB;AACjC,mBAAa,KAAK;AAClB,cAAQ,oBAAoB,SAAS,OAAO;AAC5C,UAAI,QAAQ,IAAI,EAAE,MAAM,QAAS,SAAQ,OAAO,EAAE;AAClD,cAAQ,KAAK;AAAA,IACf;AACA,UAAM,UAAU,MAAM,OAAO,IAAI;AACjC,UAAM,UAAU,MAAM,OAAO,KAAK;AAClC,UAAM,QAAQ,WAAW,MAAM,OAAO,KAAK,GAAG,SAAS;AACvD,YAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AACzD,YAAQ,IAAI,IAAI,OAAO;AAAA,EACzB,CAAC;AACH;","names":[]}
|