dodo-mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (447) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +425 -0
  3. package/dist/auth/adapter.js +43 -0
  4. package/dist/auth/adapter.js.map +1 -0
  5. package/dist/auth/clientDeletion.js +45 -0
  6. package/dist/auth/clientDeletion.js.map +1 -0
  7. package/dist/auth/clients.js +55 -0
  8. package/dist/auth/clients.js.map +1 -0
  9. package/dist/auth/constants.js +10 -0
  10. package/dist/auth/constants.js.map +1 -0
  11. package/dist/auth/interactions.js +184 -0
  12. package/dist/auth/interactions.js.map +1 -0
  13. package/dist/auth/keys.js +56 -0
  14. package/dist/auth/keys.js.map +1 -0
  15. package/dist/auth/provider.js +131 -0
  16. package/dist/auth/provider.js.map +1 -0
  17. package/dist/auth/verifier.js +74 -0
  18. package/dist/auth/verifier.js.map +1 -0
  19. package/dist/cli/kill.js +124 -0
  20. package/dist/cli/kill.js.map +1 -0
  21. package/dist/cli/main.js +1393 -0
  22. package/dist/cli/main.js.map +1 -0
  23. package/dist/cli/menu.js +127 -0
  24. package/dist/cli/menu.js.map +1 -0
  25. package/dist/cli/terminal.js +30 -0
  26. package/dist/cli/terminal.js.map +1 -0
  27. package/dist/config/globalConfig.js +144 -0
  28. package/dist/config/globalConfig.js.map +1 -0
  29. package/dist/config/limits.js +42 -0
  30. package/dist/config/limits.js.map +1 -0
  31. package/dist/config/paths.js +94 -0
  32. package/dist/config/paths.js.map +1 -0
  33. package/dist/config/projectConfig.js +63 -0
  34. package/dist/config/projectConfig.js.map +1 -0
  35. package/dist/config/stateImport.js +306 -0
  36. package/dist/config/stateImport.js.map +1 -0
  37. package/dist/config/tunnelConfig.js +23 -0
  38. package/dist/config/tunnelConfig.js.map +1 -0
  39. package/dist/errors.js +82 -0
  40. package/dist/errors.js.map +1 -0
  41. package/dist/evaluation/contracts.js +86 -0
  42. package/dist/evaluation/contracts.js.map +1 -0
  43. package/dist/evaluation/dodoBench.js +69 -0
  44. package/dist/evaluation/dodoBench.js.map +1 -0
  45. package/dist/index.js +26 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/ipc/authentication.js +117 -0
  48. package/dist/ipc/authentication.js.map +1 -0
  49. package/dist/ipc/client.js +86 -0
  50. package/dist/ipc/client.js.map +1 -0
  51. package/dist/ipc/installationClient.js +83 -0
  52. package/dist/ipc/installationClient.js.map +1 -0
  53. package/dist/ipc/ownerControl.js +46 -0
  54. package/dist/ipc/ownerControl.js.map +1 -0
  55. package/dist/ipc/protocol.js +2 -0
  56. package/dist/ipc/protocol.js.map +1 -0
  57. package/dist/ipc/server.js +108 -0
  58. package/dist/ipc/server.js.map +1 -0
  59. package/dist/platform/execResolve.js +64 -0
  60. package/dist/platform/execResolve.js.map +1 -0
  61. package/dist/platform/fileIdentity.js +26 -0
  62. package/dist/platform/fileIdentity.js.map +1 -0
  63. package/dist/platform/fsRetry.js +22 -0
  64. package/dist/platform/fsRetry.js.map +1 -0
  65. package/dist/platform/pathPolicy.js +29 -0
  66. package/dist/platform/pathPolicy.js.map +1 -0
  67. package/dist/platform/privateFs.js +116 -0
  68. package/dist/platform/privateFs.js.map +1 -0
  69. package/dist/platform/processTree.js +31 -0
  70. package/dist/platform/processTree.js.map +1 -0
  71. package/dist/platform/shell.js +74 -0
  72. package/dist/platform/shell.js.map +1 -0
  73. package/dist/platform/speech.js +94 -0
  74. package/dist/platform/speech.js.map +1 -0
  75. package/dist/platform/system.js +28 -0
  76. package/dist/platform/system.js.map +1 -0
  77. package/dist/platform/windowsSandbox.js +129 -0
  78. package/dist/platform/windowsSandbox.js.map +1 -0
  79. package/dist/projects/federation.js +312 -0
  80. package/dist/projects/federation.js.map +1 -0
  81. package/dist/projects/registry.js +291 -0
  82. package/dist/projects/registry.js.map +1 -0
  83. package/dist/security/accessMode.js +19 -0
  84. package/dist/security/accessMode.js.map +1 -0
  85. package/dist/security/approvals.js +56 -0
  86. package/dist/security/approvals.js.map +1 -0
  87. package/dist/security/env.js +57 -0
  88. package/dist/security/env.js.map +1 -0
  89. package/dist/security/mutationQueue.js +78 -0
  90. package/dist/security/mutationQueue.js.map +1 -0
  91. package/dist/security/policy.js +22 -0
  92. package/dist/security/policy.js.map +1 -0
  93. package/dist/security/projectAuthority.js +22 -0
  94. package/dist/security/projectAuthority.js.map +1 -0
  95. package/dist/security/redact.js +30 -0
  96. package/dist/security/redact.js.map +1 -0
  97. package/dist/server/aiAdmin.js +201 -0
  98. package/dist/server/aiAdmin.js.map +1 -0
  99. package/dist/server/appServer.js +461 -0
  100. package/dist/server/appServer.js.map +1 -0
  101. package/dist/server/bootstrap.js +185 -0
  102. package/dist/server/bootstrap.js.map +1 -0
  103. package/dist/server/configUi/app.css +347 -0
  104. package/dist/server/configUi/app.js +958 -0
  105. package/dist/server/configUi/index.html +379 -0
  106. package/dist/server/configUi/ui/alerts.js +92 -0
  107. package/dist/server/configUi/ui/dom.js +19 -0
  108. package/dist/server/configUi/ui/tooltips.js +115 -0
  109. package/dist/server/configUi/vendor/VERSION.txt +1 -0
  110. package/dist/server/configUi/vendor/sweetalert2.min.css +1 -0
  111. package/dist/server/configUi/vendor/sweetalert2.min.js +5 -0
  112. package/dist/server/configUi/workbench.css +62 -0
  113. package/dist/server/configUi/workbench.js +394 -0
  114. package/dist/server/installationRuntime.js +155 -0
  115. package/dist/server/installationRuntime.js.map +1 -0
  116. package/dist/server/instructions.js +17 -0
  117. package/dist/server/instructions.js.map +1 -0
  118. package/dist/server/ipcDispatch.js +225 -0
  119. package/dist/server/ipcDispatch.js.map +1 -0
  120. package/dist/server/localConfig.js +561 -0
  121. package/dist/server/localConfig.js.map +1 -0
  122. package/dist/server/optionalServices.js +30 -0
  123. package/dist/server/optionalServices.js.map +1 -0
  124. package/dist/server/projectLease.js +46 -0
  125. package/dist/server/projectLease.js.map +1 -0
  126. package/dist/server/stdioServer.js +75 -0
  127. package/dist/server/stdioServer.js.map +1 -0
  128. package/dist/server/version.js +13 -0
  129. package/dist/server/version.js.map +1 -0
  130. package/dist/server/workspaceHost.js +194 -0
  131. package/dist/server/workspaceHost.js.map +1 -0
  132. package/dist/services/agent/agentService.js +598 -0
  133. package/dist/services/agent/agentService.js.map +1 -0
  134. package/dist/services/agent/contracts.js +102 -0
  135. package/dist/services/agent/contracts.js.map +1 -0
  136. package/dist/services/ai/adapters.js +287 -0
  137. package/dist/services/ai/adapters.js.map +1 -0
  138. package/dist/services/ai/contracts.js +39 -0
  139. package/dist/services/ai/contracts.js.map +1 -0
  140. package/dist/services/ai/credentials.js +77 -0
  141. package/dist/services/ai/credentials.js.map +1 -0
  142. package/dist/services/ai/network.js +113 -0
  143. package/dist/services/ai/network.js.map +1 -0
  144. package/dist/services/ai/settings.js +178 -0
  145. package/dist/services/ai/settings.js.map +1 -0
  146. package/dist/services/ai/subagents.js +468 -0
  147. package/dist/services/ai/subagents.js.map +1 -0
  148. package/dist/services/assistance/analysis.js +352 -0
  149. package/dist/services/assistance/analysis.js.map +1 -0
  150. package/dist/services/assistance/contracts.js +54 -0
  151. package/dist/services/assistance/contracts.js.map +1 -0
  152. package/dist/services/assistance/verification.js +274 -0
  153. package/dist/services/assistance/verification.js.map +1 -0
  154. package/dist/services/brain/brainParser.js +97 -0
  155. package/dist/services/brain/brainParser.js.map +1 -0
  156. package/dist/services/brain/brainService.js +733 -0
  157. package/dist/services/brain/brainService.js.map +1 -0
  158. package/dist/services/brain/brainWorker.js +212 -0
  159. package/dist/services/brain/brainWorker.js.map +1 -0
  160. package/dist/services/brain/contracts.js +154 -0
  161. package/dist/services/brain/contracts.js.map +1 -0
  162. package/dist/services/brain/protocol.js +2 -0
  163. package/dist/services/brain/protocol.js.map +1 -0
  164. package/dist/services/changes/applier.js +544 -0
  165. package/dist/services/changes/applier.js.map +1 -0
  166. package/dist/services/changes/contentBudget.js +11 -0
  167. package/dist/services/changes/contentBudget.js.map +1 -0
  168. package/dist/services/changes/planner.js +284 -0
  169. package/dist/services/changes/planner.js.map +1 -0
  170. package/dist/services/changes/types.js +3 -0
  171. package/dist/services/changes/types.js.map +1 -0
  172. package/dist/services/context/contextEngine.js +746 -0
  173. package/dist/services/context/contextEngine.js.map +1 -0
  174. package/dist/services/context/contracts.js +88 -0
  175. package/dist/services/context/contracts.js.map +1 -0
  176. package/dist/services/desktop/desktopPolicy.js +76 -0
  177. package/dist/services/desktop/desktopPolicy.js.map +1 -0
  178. package/dist/services/desktop/desktopService.js +130 -0
  179. package/dist/services/desktop/desktopService.js.map +1 -0
  180. package/dist/services/desktop/nativeBackend.js +174 -0
  181. package/dist/services/desktop/nativeBackend.js.map +1 -0
  182. package/dist/services/desktop/protocol.js +32 -0
  183. package/dist/services/desktop/protocol.js.map +1 -0
  184. package/dist/services/files/readService.js +136 -0
  185. package/dist/services/files/readService.js.map +1 -0
  186. package/dist/services/git/gitService.js +369 -0
  187. package/dist/services/git/gitService.js.map +1 -0
  188. package/dist/services/intelligence/intelService.js +136 -0
  189. package/dist/services/intelligence/intelService.js.map +1 -0
  190. package/dist/services/intelligence/protocol.js +2 -0
  191. package/dist/services/intelligence/protocol.js.map +1 -0
  192. package/dist/services/intelligence/tsWorker.js +419 -0
  193. package/dist/services/intelligence/tsWorker.js.map +1 -0
  194. package/dist/services/jobs/commandInput.js +34 -0
  195. package/dist/services/jobs/commandInput.js.map +1 -0
  196. package/dist/services/jobs/jobManager.js +398 -0
  197. package/dist/services/jobs/jobManager.js.map +1 -0
  198. package/dist/services/jobs/sandbox.js +156 -0
  199. package/dist/services/jobs/sandbox.js.map +1 -0
  200. package/dist/services/jobs/sandboxWiring.js +37 -0
  201. package/dist/services/jobs/sandboxWiring.js.map +1 -0
  202. package/dist/services/jobs/spool.js +112 -0
  203. package/dist/services/jobs/spool.js.map +1 -0
  204. package/dist/services/jobs/windowsSandboxChild.js +24 -0
  205. package/dist/services/jobs/windowsSandboxChild.js.map +1 -0
  206. package/dist/services/jobs/windowsSandboxWorker.js +155 -0
  207. package/dist/services/jobs/windowsSandboxWorker.js.map +1 -0
  208. package/dist/services/lsp/documentUri.js +16 -0
  209. package/dist/services/lsp/documentUri.js.map +1 -0
  210. package/dist/services/lsp/jsonrpc.js +382 -0
  211. package/dist/services/lsp/jsonrpc.js.map +1 -0
  212. package/dist/services/lsp/lspService.js +1051 -0
  213. package/dist/services/lsp/lspService.js.map +1 -0
  214. package/dist/services/memory/contracts.js +94 -0
  215. package/dist/services/memory/contracts.js.map +1 -0
  216. package/dist/services/memory/memoryService.js +683 -0
  217. package/dist/services/memory/memoryService.js.map +1 -0
  218. package/dist/services/multimodal/browserService.js +407 -0
  219. package/dist/services/multimodal/browserService.js.map +1 -0
  220. package/dist/services/multimodal/byteRange.js +31 -0
  221. package/dist/services/multimodal/byteRange.js.map +1 -0
  222. package/dist/services/multimodal/contracts.js +59 -0
  223. package/dist/services/multimodal/contracts.js.map +1 -0
  224. package/dist/services/multimodal/gameService.js +95 -0
  225. package/dist/services/multimodal/gameService.js.map +1 -0
  226. package/dist/services/multimodal/images.js +107 -0
  227. package/dist/services/multimodal/images.js.map +1 -0
  228. package/dist/services/multimodal/mediaService.js +279 -0
  229. package/dist/services/multimodal/mediaService.js.map +1 -0
  230. package/dist/services/multimodal/mediaWorker.js +143 -0
  231. package/dist/services/multimodal/mediaWorker.js.map +1 -0
  232. package/dist/services/multimodal/multimodalService.js +51 -0
  233. package/dist/services/multimodal/multimodalService.js.map +1 -0
  234. package/dist/services/multimodal/network.js +69 -0
  235. package/dist/services/multimodal/network.js.map +1 -0
  236. package/dist/services/multimodal/operations.js +40 -0
  237. package/dist/services/multimodal/operations.js.map +1 -0
  238. package/dist/services/multimodal/storage.js +160 -0
  239. package/dist/services/multimodal/storage.js.map +1 -0
  240. package/dist/services/multimodal/workflowService.js +179 -0
  241. package/dist/services/multimodal/workflowService.js.map +1 -0
  242. package/dist/services/overview.js +284 -0
  243. package/dist/services/overview.js.map +1 -0
  244. package/dist/services/resources/casStore.js +304 -0
  245. package/dist/services/resources/casStore.js.map +1 -0
  246. package/dist/services/resources/contracts.js +75 -0
  247. package/dist/services/resources/contracts.js.map +1 -0
  248. package/dist/services/resources/mime.js +77 -0
  249. package/dist/services/resources/mime.js.map +1 -0
  250. package/dist/services/resources/providerRegistry.js +22 -0
  251. package/dist/services/resources/providerRegistry.js.map +1 -0
  252. package/dist/services/resources/providers.js +120 -0
  253. package/dist/services/resources/providers.js.map +1 -0
  254. package/dist/services/resources/resourceService.js +282 -0
  255. package/dist/services/resources/resourceService.js.map +1 -0
  256. package/dist/services/runtime/contracts.js +65 -0
  257. package/dist/services/runtime/contracts.js.map +1 -0
  258. package/dist/services/runtime/runtimeService.js +364 -0
  259. package/dist/services/runtime/runtimeService.js.map +1 -0
  260. package/dist/services/schedules/scheduleService.js +198 -0
  261. package/dist/services/schedules/scheduleService.js.map +1 -0
  262. package/dist/services/search/searchService.js +434 -0
  263. package/dist/services/search/searchService.js.map +1 -0
  264. package/dist/services/search/searchWorker.js +58 -0
  265. package/dist/services/search/searchWorker.js.map +1 -0
  266. package/dist/setup/componentProbes.js +259 -0
  267. package/dist/setup/componentProbes.js.map +1 -0
  268. package/dist/setup/download.js +139 -0
  269. package/dist/setup/download.js.map +1 -0
  270. package/dist/setup/managedTools.js +118 -0
  271. package/dist/setup/managedTools.js.map +1 -0
  272. package/dist/setup/sandboxProbe.js +172 -0
  273. package/dist/setup/sandboxProbe.js.map +1 -0
  274. package/dist/setup/setup.js +522 -0
  275. package/dist/setup/setup.js.map +1 -0
  276. package/dist/setup/windowsChromiumAcl.js +56 -0
  277. package/dist/setup/windowsChromiumAcl.js.map +1 -0
  278. package/dist/setup/windowsSandboxInstall.js +94 -0
  279. package/dist/setup/windowsSandboxInstall.js.map +1 -0
  280. package/dist/setup/windowsSpeechInstall.js +86 -0
  281. package/dist/setup/windowsSpeechInstall.js.map +1 -0
  282. package/dist/store/db.js +711 -0
  283. package/dist/store/db.js.map +1 -0
  284. package/dist/store/scopeEncoding.js +15 -0
  285. package/dist/store/scopeEncoding.js.map +1 -0
  286. package/dist/store/store.js +467 -0
  287. package/dist/store/store.js.map +1 -0
  288. package/dist/tools/agentRuntimeTools.js +216 -0
  289. package/dist/tools/agentRuntimeTools.js.map +1 -0
  290. package/dist/tools/agentTools.js +317 -0
  291. package/dist/tools/agentTools.js.map +1 -0
  292. package/dist/tools/assistanceTools.js +126 -0
  293. package/dist/tools/assistanceTools.js.map +1 -0
  294. package/dist/tools/brainTools.js +130 -0
  295. package/dist/tools/brainTools.js.map +1 -0
  296. package/dist/tools/catalog.js +30 -0
  297. package/dist/tools/catalog.js.map +1 -0
  298. package/dist/tools/changeTools.js +188 -0
  299. package/dist/tools/changeTools.js.map +1 -0
  300. package/dist/tools/context.js +243 -0
  301. package/dist/tools/context.js.map +1 -0
  302. package/dist/tools/contextTools.js +57 -0
  303. package/dist/tools/contextTools.js.map +1 -0
  304. package/dist/tools/coreCatalog.js +82 -0
  305. package/dist/tools/coreCatalog.js.map +1 -0
  306. package/dist/tools/desktopTools.js +41 -0
  307. package/dist/tools/desktopTools.js.map +1 -0
  308. package/dist/tools/directTools.js +273 -0
  309. package/dist/tools/directTools.js.map +1 -0
  310. package/dist/tools/envelope.js +71 -0
  311. package/dist/tools/envelope.js.map +1 -0
  312. package/dist/tools/extraTools.js +298 -0
  313. package/dist/tools/extraTools.js.map +1 -0
  314. package/dist/tools/gitTools.js +93 -0
  315. package/dist/tools/gitTools.js.map +1 -0
  316. package/dist/tools/jobTools.js +454 -0
  317. package/dist/tools/jobTools.js.map +1 -0
  318. package/dist/tools/memoryTools.js +102 -0
  319. package/dist/tools/memoryTools.js.map +1 -0
  320. package/dist/tools/metaTools.js +153 -0
  321. package/dist/tools/metaTools.js.map +1 -0
  322. package/dist/tools/multimodalTools.js +262 -0
  323. package/dist/tools/multimodalTools.js.map +1 -0
  324. package/dist/tools/projectTools.js +261 -0
  325. package/dist/tools/projectTools.js.map +1 -0
  326. package/dist/tools/resourceTools.js +81 -0
  327. package/dist/tools/resourceTools.js.map +1 -0
  328. package/dist/tools/runtimeTools.js +137 -0
  329. package/dist/tools/runtimeTools.js.map +1 -0
  330. package/dist/tools/scheduleTools.js +10 -0
  331. package/dist/tools/scheduleTools.js.map +1 -0
  332. package/dist/tools/semanticTools.js +141 -0
  333. package/dist/tools/semanticTools.js.map +1 -0
  334. package/dist/tools/subagentTools.js +32 -0
  335. package/dist/tools/subagentTools.js.map +1 -0
  336. package/dist/tools/surface.js +644 -0
  337. package/dist/tools/surface.js.map +1 -0
  338. package/dist/tunnel/control.js +113 -0
  339. package/dist/tunnel/control.js.map +1 -0
  340. package/dist/tunnel/credentials.js +392 -0
  341. package/dist/tunnel/credentials.js.map +1 -0
  342. package/dist/tunnel/log.js +84 -0
  343. package/dist/tunnel/log.js.map +1 -0
  344. package/dist/tunnel/runtime.js +55 -0
  345. package/dist/tunnel/runtime.js.map +1 -0
  346. package/dist/tunnel/supervisor.js +280 -0
  347. package/dist/tunnel/supervisor.js.map +1 -0
  348. package/dist/util/bytes.js +53 -0
  349. package/dist/util/bytes.js.map +1 -0
  350. package/dist/util/hash.js +53 -0
  351. package/dist/util/hash.js.map +1 -0
  352. package/dist/workspace/fs.js +305 -0
  353. package/dist/workspace/fs.js.map +1 -0
  354. package/dist/workspace/identity.js +17 -0
  355. package/dist/workspace/identity.js.map +1 -0
  356. package/dist/workspace/ignores.js +173 -0
  357. package/dist/workspace/ignores.js.map +1 -0
  358. package/dist/workspace/root.js +59 -0
  359. package/dist/workspace/root.js.map +1 -0
  360. package/docs/AGENT_RUNTIME.md +154 -0
  361. package/docs/AI_PROVIDERS.md +110 -0
  362. package/docs/ARCHITECTURE.md +331 -0
  363. package/docs/ASSISTANCE.md +31 -0
  364. package/docs/AUTH.md +59 -0
  365. package/docs/BRAIN.md +92 -0
  366. package/docs/COMPATIBILITY.md +92 -0
  367. package/docs/CONFIRMATION.md +13 -0
  368. package/docs/CONTEXT.md +87 -0
  369. package/docs/DESKTOP.md +35 -0
  370. package/docs/EVALUATION.md +86 -0
  371. package/docs/LARGE_INPUTS.md +21 -0
  372. package/docs/LSP.md +21 -0
  373. package/docs/MANUAL_ACCEPTANCE.md +283 -0
  374. package/docs/MEMORY.md +128 -0
  375. package/docs/MULTIMODAL.md +32 -0
  376. package/docs/PROJECTS.md +146 -0
  377. package/docs/RELEASE_1.0.0.md +111 -0
  378. package/docs/RELEASE_NOTES.md +92 -0
  379. package/docs/RESOURCES.md +83 -0
  380. package/docs/RUNTIME.md +125 -0
  381. package/docs/SCHEDULES.md +23 -0
  382. package/docs/SECURITY.md +250 -0
  383. package/docs/TEST_REPORT.md +312 -0
  384. package/docs/TUNNEL.md +86 -0
  385. package/docs/WEB_CLIENTS.md +43 -0
  386. package/docs/WINDOWS.md +79 -0
  387. package/docs/adr/001-one-process-one-workspace.md +22 -0
  388. package/docs/adr/002-external-tunnel.md +19 -0
  389. package/docs/adr/003-sdk-v2-legacy-stateless.md +20 -0
  390. package/docs/adr/004-embedded-oauth-provider.md +19 -0
  391. package/docs/adr/005-static-client-baseline.md +19 -0
  392. package/docs/adr/006-guarded-fs-explicit-exec.md +16 -0
  393. package/docs/adr/007-preview-hash-journal.md +18 -0
  394. package/docs/adr/008-ts-js-semantics-first.md +17 -0
  395. package/docs/adr/009-jobs-polling.md +18 -0
  396. package/docs/adr/010-sqlite-better-sqlite3.md +18 -0
  397. package/docs/adr/011-env-example-secure-default.md +19 -0
  398. package/docs/adr/012-workspace-scope-grant.md +24 -0
  399. package/docs/adr/013-loopback-proxy-trust.md +18 -0
  400. package/docs/adr/014-direct-coding-tier.md +48 -0
  401. package/docs/adr/015-coding-agent-parity.md +56 -0
  402. package/docs/adr/016-oidc-openid-consent.md +15 -0
  403. package/docs/adr/017-installation-identity-local-config.md +44 -0
  404. package/docs/adr/018-access-scope-encoding.md +11 -0
  405. package/docs/adr/019-runtime-workspace-switch.md +59 -0
  406. package/docs/adr/020-desktop-access.md +50 -0
  407. package/docs/adr/021-persistent-desktop-consent.md +39 -0
  408. package/docs/adr/022-owner-kill-preserves-login.md +30 -0
  409. package/docs/adr/023-large-coding-inputs.md +49 -0
  410. package/docs/adr/024-usage-rounds-and-schedules.md +72 -0
  411. package/docs/adr/025-owner-chat-whitelist.md +53 -0
  412. package/docs/adr/026-remove-conversation-confirmation.md +35 -0
  413. package/docs/adr/027-workspace-client-list.md +20 -0
  414. package/docs/adr/028-owner-client-deletion.md +25 -0
  415. package/docs/adr/029-compact-tool-surface.md +121 -0
  416. package/docs/adr/030-windows-native-candidate.md +71 -0
  417. package/docs/adr/031-owner-selected-tunnel-supervision.md +13 -0
  418. package/docs/adr/032-owner-project-registry.md +43 -0
  419. package/docs/adr/033-read-only-project-federation.md +61 -0
  420. package/docs/adr/034-universal-resource-cas.md +60 -0
  421. package/docs/adr/035-project-brain-incremental-index.md +51 -0
  422. package/docs/adr/036-context-engine-evidence.md +53 -0
  423. package/docs/adr/037-owner-reviewed-memory.md +46 -0
  424. package/docs/adr/038-runtime-intelligence.md +46 -0
  425. package/docs/adr/039-advanced-agent-runtime.md +57 -0
  426. package/docs/adr/040-dodobench-release-gate.md +43 -0
  427. package/docs/adr/041-local-macos-docker-linux-gates.md +32 -0
  428. package/docs/adr/042-project-directory-generation-identity.md +36 -0
  429. package/docs/adr/043-trusted-self-hosted-platform-gates.md +38 -0
  430. package/docs/adr/044-global-launcher-and-cli-menu.md +43 -0
  431. package/docs/adr/045-ai-providers-multiproject.md +56 -0
  432. package/docs/adr/046-personal-access-mode.md +32 -0
  433. package/docs/adr/README.md +64 -0
  434. package/examples/.dodo.json.example +20 -0
  435. package/examples/cloudflared.yml +23 -0
  436. package/examples/reverse-proxy-fixture.mjs +37 -0
  437. package/native/desktop-linux.py +387 -0
  438. package/native/desktop-windows.cs +180 -0
  439. package/native/desktop.swift +212 -0
  440. package/package.json +145 -0
  441. package/schemas/global-config.schema.json +497 -0
  442. package/schemas/project-config.schema.json +75 -0
  443. package/schemas/tools.compact.json +3236 -0
  444. package/schemas/tools.hybrid.json +8194 -0
  445. package/schemas/tools.json +34518 -0
  446. package/scripts/guard-publish.mjs +12 -0
  447. package/scripts/setup-multimodal.mjs +70 -0
@@ -0,0 +1,184 @@
1
+ import { Router } from 'express';
2
+ import { phraseFor } from '../util/hash.js';
3
+ import { ALL_SCOPES } from '../security/policy.js';
4
+ import { INSTALLATION_AUTHORITY_EPOCH, INSTALLATION_AUTHORITY_ID, OWNER_ACCOUNT_ID } from './constants.js';
5
+ import { isPersonalMode } from '../security/accessMode.js';
6
+ /**
7
+ * Owner-consent interactions (spec §8.4).
8
+ *
9
+ * Flow: OAuth client starts → provider creates an interaction bound to the
10
+ * BROWSER session cookie → the page shows a request id + phrase → the owner
11
+ * verifies details on the terminal (`dodo auth pending`) and approves over
12
+ * the private IPC socket (`dodo auth approve -- <id>`) → the SAME browser
13
+ * session completes the interaction (custom-header + SameSite protected) →
14
+ * the provider issues the code to the registered exact redirect URI.
15
+ *
16
+ * The public listener has NO endpoint that approves an interaction from a
17
+ * request id alone: approval state changes only over local IPC, and the
18
+ * complete endpoint requires the provider's own session cookie.
19
+ */
20
+ const MAX_PENDING_OAUTH = 20;
21
+ export const OAUTH_INTERACTION_TTL_MS = 5 * 60 * 1000;
22
+ export function interactionRouter(opts) {
23
+ const { provider, store } = opts;
24
+ const authority = { workspaceId: INSTALLATION_AUTHORITY_ID, epoch: INSTALLATION_AUTHORITY_EPOCH };
25
+ const router = Router();
26
+ router.get('/interaction/:uid', async (req, res) => {
27
+ try {
28
+ const details = await provider.interactionDetails(req, res);
29
+ const params = details.params;
30
+ const clientId = String(params['client_id'] ?? '');
31
+ if (!store.getOAuthClient(clientId))
32
+ throw new Error('unknown client');
33
+ const redirectUri = String(params['redirect_uri'] ?? '');
34
+ const requested = typeof params['scope'] === 'string' ? params['scope'].split(' ').filter(Boolean) : [];
35
+ const scopes = requested.filter((s) => ALL_SCOPES.includes(s));
36
+ const effectiveScopes = scopes.length > 0 ? scopes : [...ALL_SCOPES];
37
+ const { workspaceId, epoch } = authority;
38
+ const existing = store.getApproval(details.uid);
39
+ if (existing && (existing.workspaceId !== workspaceId || existing.epoch !== epoch)) {
40
+ res.status(400).send('Workspace changed; start a fresh authorization request.');
41
+ return;
42
+ }
43
+ if (!existing) {
44
+ if (store.listPendingApprovals('oauth').length >= MAX_PENDING_OAUTH) {
45
+ res.status(429).type('text/plain').send('Too many pending authorization requests. Try again later.');
46
+ return;
47
+ }
48
+ const summary = {
49
+ clientId,
50
+ redirectUri,
51
+ scopes: effectiveScopes,
52
+ phrase: phraseFor(details.uid),
53
+ };
54
+ store.createApproval({
55
+ kind: 'oauth',
56
+ workspaceId,
57
+ epoch,
58
+ id: details.uid,
59
+ summary: JSON.stringify(summary),
60
+ ttlMs: OAUTH_INTERACTION_TTL_MS,
61
+ });
62
+ }
63
+ res
64
+ .status(200)
65
+ .type('html')
66
+ .setHeader('Cache-Control', 'no-store')
67
+ .setHeader('Content-Security-Policy', "default-src 'none'; style-src 'unsafe-inline'; script-src 'unsafe-inline'; connect-src 'self'")
68
+ .send(interactionPage(details.uid, phraseFor(details.uid), clientId, effectiveScopes, isPersonalMode(store)));
69
+ }
70
+ catch {
71
+ res.status(400).type('text/plain').send('Unknown or expired authorization request.');
72
+ }
73
+ });
74
+ router.get('/interaction/:uid/status', async (req, res) => {
75
+ try {
76
+ const details = await provider.interactionDetails(req, res); // session-cookie bound
77
+ const approval = store.getApproval(details.uid);
78
+ res.setHeader('Cache-Control', 'no-store').json({ status: approval?.status ?? 'pending' });
79
+ }
80
+ catch {
81
+ res.status(400).json({ status: 'unknown' });
82
+ }
83
+ });
84
+ router.post('/interaction/:uid/complete', async (req, res) => {
85
+ try {
86
+ const details = await provider.interactionDetails(req, res); // session-cookie bound
87
+ // Cross-site form posts cannot set custom headers; require one.
88
+ if (req.headers['x-dodo-interaction'] !== details.uid) {
89
+ res.status(403).json({ error: 'bad interaction header' });
90
+ return;
91
+ }
92
+ const { workspaceId, epoch } = authority;
93
+ const approval = store.getApproval(details.uid);
94
+ if (!approval || approval.kind !== 'oauth' || approval.workspaceId !== workspaceId || approval.epoch !== epoch || approval.status !== 'approved') {
95
+ res.status(403).json({ error: 'not approved' });
96
+ return;
97
+ }
98
+ if (!store.setApprovalStatus(details.uid, 'consumed')) {
99
+ res.status(403).json({ error: 'approval expired' });
100
+ return;
101
+ }
102
+ const summary = JSON.parse(approval.summary);
103
+ const params = details.params;
104
+ const clientId = String(params['client_id'] ?? '');
105
+ if (clientId !== summary.clientId || !store.getOAuthClient(clientId)) {
106
+ res.status(403).json({ error: 'client mismatch' });
107
+ return;
108
+ }
109
+ const grant = new provider.Grant({ accountId: OWNER_ACCOUNT_ID, clientId });
110
+ // Grant at both levels: OIDC scope satisfies the authorization request's
111
+ // `scope` param; resource scope binds the token audience to /mcp.
112
+ // OIDC clients request openid in addition to resource permissions. It
113
+ // must be consented at the OIDC level or the provider prompts forever.
114
+ // Never add it to the workspace's resource permissions.
115
+ const requestedScopes = typeof params['scope'] === 'string' ? params['scope'].split(/\s+/) : [];
116
+ const oidcScopes = [...summary.scopes, 'offline_access'];
117
+ if (requestedScopes.includes('openid'))
118
+ oidcScopes.push('openid');
119
+ grant.addOIDCScope(oidcScopes.join(' '));
120
+ grant.addResourceScope(opts.resourceUrl, summary.scopes.join(' '));
121
+ const grantId = await grant.save();
122
+ // Deletion may run while provider persistence yields. Never recreate ACLs.
123
+ if (!store.getOAuthClient(clientId)) {
124
+ await grant.destroy();
125
+ throw new Error('client was deleted');
126
+ }
127
+ store.putGrant({
128
+ id: grantId,
129
+ workspaceId,
130
+ clientId,
131
+ accountId: OWNER_ACCOUNT_ID,
132
+ scopes: summary.scopes,
133
+ });
134
+ store.setMeta(`identity-grant:${grantId}`, '2');
135
+ const returnTo = await provider.interactionResult(req, res, { login: { accountId: OWNER_ACCOUNT_ID }, consent: { grantId } }, { mergeWithLastSubmission: false });
136
+ res.setHeader('Cache-Control', 'no-store').json({ returnTo });
137
+ }
138
+ catch {
139
+ res.status(400).json({ error: 'interaction failed' });
140
+ }
141
+ });
142
+ return router;
143
+ }
144
+ function interactionPage(uid, phrase, clientId, scopes, personal) {
145
+ const esc = (s) => s.replace(/[&<>"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' })[c]);
146
+ return `<!doctype html><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>DODO authorization</title>
147
+ <body style="font-family:system-ui;max-width:38rem;margin:3rem auto;line-height:1.5;padding:0 1rem">
148
+ <h1 style="font-size:1.4rem">Authorize this connection on your terminal</h1>
149
+ <p>A client is asking to connect to this DODO installation.</p>
150
+ <p><strong>${personal ? 'Personal mode is active.' : 'Managed mode is active.'}</strong> ${personal ? 'After local approval, this client can use owner-registered projects according to these OAuth scopes; no second project permission step is needed.' : 'This login grants no project access. The owner assigns each project and its read/write/exec scopes later in Local Config.'}</p>
151
+ <table style="border-collapse:collapse">
152
+ <tr><td style="padding:.2rem .8rem .2rem 0;color:#555">Request ID</td><td><code>${esc(uid)}</code></td></tr>
153
+ <tr><td style="padding:.2rem .8rem .2rem 0;color:#555">Check phrase</td><td><strong>${esc(phrase)}</strong></td></tr>
154
+ <tr><td style="padding:.2rem .8rem .2rem 0;color:#555">Client</td><td><code>${esc(clientId)}</code></td></tr>
155
+ <tr><td style="padding:.2rem .8rem .2rem 0;color:#555">Scopes</td><td><code>${esc(scopes.join(' '))}</code></td></tr>
156
+ </table>
157
+ <p>On the machine running DODO, verify the same request ID, phrase, client and callback URL with:</p>
158
+ <pre style="background:#f4f4f4;padding:.6rem">dodo auth pending
159
+ dodo auth approve -- ${esc(uid)}</pre>
160
+ <p id="st" aria-live="polite">Waiting for local approval…</p>
161
+ <script>
162
+ (function(){
163
+ var uid=${JSON.stringify(uid)};
164
+ var done=false;
165
+ function tick(){
166
+ if(done)return;
167
+ fetch('/interaction/'+uid+'/status',{headers:{'accept':'application/json'}}).then(function(r){return r.json()}).then(function(d){
168
+ if(d.status==='approved'){
169
+ done=true;
170
+ document.getElementById('st').textContent='Approved — finishing sign-in…';
171
+ fetch('/interaction/'+uid+'/complete',{method:'POST',headers:{'x-dodo-interaction':uid}}).then(function(r){return r.json()}).then(function(d){
172
+ if(d.returnTo){window.location.assign(d.returnTo);}else{document.getElementById('st').textContent='Error: '+(d.error||'unknown');}
173
+ });
174
+ } else if(d.status==='denied'||d.status==='expired'){
175
+ done=true;document.getElementById('st').textContent='Request '+d.status+'.';
176
+ } else { setTimeout(tick,2000); }
177
+ }).catch(function(){setTimeout(tick,3000)});
178
+ }
179
+ tick();
180
+ })();
181
+ </script>
182
+ </body>`;
183
+ }
184
+ //# sourceMappingURL=interactions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactions.js","sourceRoot":"","sources":["../../src/auth/interactions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import fs from 'node:fs';
2
+ import { generateKeyPairSync, randomBytes, createPrivateKey, createPublicKey } from 'node:crypto';
3
+ import { DodoError } from '../errors.js';
4
+ export function loadOrCreateJwks(jwksFile) {
5
+ try {
6
+ const raw = fs.readFileSync(jwksFile, 'utf8');
7
+ const parsed = JSON.parse(raw);
8
+ if (!Array.isArray(parsed.keys) || parsed.keys.length === 0)
9
+ throw new Error('empty');
10
+ return parsed;
11
+ }
12
+ catch (err) {
13
+ if (err.code !== 'ENOENT') {
14
+ throw new DodoError('INTERNAL_ERROR', 'signing key store is corrupt; refusing to regenerate silently', {
15
+ recovery: `inspect ${jwksFile}; deleting it invalidates all issued tokens`,
16
+ });
17
+ }
18
+ }
19
+ const { privateKey } = generateKeyPairSync('ec', { namedCurve: 'P-256' });
20
+ const jwk = privateKey.export({ format: 'jwk' });
21
+ jwk['kid'] = `dodo-${randomBytes(6).toString('hex')}`;
22
+ jwk['alg'] = 'ES256';
23
+ jwk['use'] = 'sig';
24
+ const out = { keys: [jwk] };
25
+ fs.writeFileSync(jwksFile, JSON.stringify(out, null, 2), { mode: 0o600 });
26
+ return out;
27
+ }
28
+ /** Public JWKS derived from the private file (for local verification). */
29
+ export function publicJwks(jwks) {
30
+ return {
31
+ keys: jwks.keys.map((priv) => {
32
+ const key = createPrivateKey({ key: priv, format: 'jwk' });
33
+ const pub = createPublicKey(key).export({ format: 'jwk' });
34
+ pub['kid'] = priv['kid'];
35
+ pub['alg'] = priv['alg'];
36
+ pub['use'] = 'sig';
37
+ return pub;
38
+ }),
39
+ };
40
+ }
41
+ export function loadOrCreateCookieKeys(cookieKeysFile) {
42
+ try {
43
+ const parsed = JSON.parse(fs.readFileSync(cookieKeysFile, 'utf8'));
44
+ if (Array.isArray(parsed.keys) && parsed.keys.length > 0)
45
+ return parsed.keys;
46
+ }
47
+ catch (err) {
48
+ if (err.code !== 'ENOENT') {
49
+ throw new DodoError('INTERNAL_ERROR', 'cookie key store is corrupt', { recovery: `inspect ${cookieKeysFile}` });
50
+ }
51
+ }
52
+ const keys = [randomBytes(32).toString('hex'), randomBytes(32).toString('hex')];
53
+ fs.writeFileSync(cookieKeysFile, JSON.stringify({ keys }, null, 2), { mode: 0o600 });
54
+ return keys;
55
+ }
56
+ //# sourceMappingURL=keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/auth/keys.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,131 @@
1
+ import Provider from 'oidc-provider';
2
+ import { createAdapterFactory } from './adapter.js';
3
+ import { ALL_SCOPES } from '../security/policy.js';
4
+ import { OWNER_ACCOUNT_ID } from './constants.js';
5
+ export { OWNER_ACCOUNT_ID } from './constants.js';
6
+ export function buildProvider(opts) {
7
+ const { store, resourceUrl } = opts;
8
+ const activeWorkspaceId = () => (typeof opts.workspaceId === 'function' ? opts.workspaceId() : opts.workspaceId);
9
+ const scopeString = ALL_SCOPES.join(' ');
10
+ const configuration = {
11
+ adapter: createAdapterFactory(store),
12
+ clients: [],
13
+ jwks: { keys: opts.jwks.keys },
14
+ cookies: {
15
+ keys: opts.cookieKeys,
16
+ short: { signed: true, httpOnly: true, sameSite: 'lax' },
17
+ long: { signed: true, httpOnly: true, sameSite: 'lax' },
18
+ },
19
+ // dodo:* are advertised both as global scopes (so the authorization
20
+ // request's `scope` param is accepted) and as resource scopes via
21
+ // resourceIndicators below (so the access token's audience is the /mcp
22
+ // resource). The grant binds both levels; the verifier still checks the
23
+ // exact resource audience.
24
+ scopes: ['offline_access', ...ALL_SCOPES],
25
+ claims: {},
26
+ clientDefaults: {
27
+ grant_types: ['authorization_code', 'refresh_token'],
28
+ response_types: ['code'],
29
+ token_endpoint_auth_method: 'client_secret_basic',
30
+ // The signing key set is ES256-only; align client alg defaults with it.
31
+ id_token_signed_response_alg: 'ES256',
32
+ },
33
+ pkce: {
34
+ required: () => true,
35
+ },
36
+ responseTypes: ['code'],
37
+ interactions: {
38
+ // The default login+consent policy still applies; we simply render the
39
+ // prompt ourselves (owner terminal approval) at this URL. On resume the
40
+ // interaction result carries both login and consent, satisfying it.
41
+ url: (_ctx, interaction) => `/interaction/${interaction.uid}`,
42
+ },
43
+ findAccount: async (_ctx, id) => id === OWNER_ACCOUNT_ID
44
+ ? {
45
+ accountId: OWNER_ACCOUNT_ID,
46
+ claims: async () => ({ sub: OWNER_ACCOUNT_ID }),
47
+ }
48
+ : undefined,
49
+ /**
50
+ * Reuse the DODO grant the owner just approved (or approved earlier) for
51
+ * THIS client and THIS workspace. Consent for the single owner is granted
52
+ * once over local IPC; the flow must not then re-prompt in the browser.
53
+ * A grant bound to a different workspace never authorizes this one (spec
54
+ * §6, AUTH-07) — it is filtered out, forcing a fresh owner approval.
55
+ */
56
+ loadExistingGrant: async (ctx) => {
57
+ const clientId = ctx.oidc.client?.clientId;
58
+ const result = ctx.oidc.result;
59
+ const accountId = ctx.oidc.session?.accountId ?? result?.login?.accountId;
60
+ if (!clientId || accountId !== OWNER_ACCOUNT_ID)
61
+ return undefined;
62
+ // Prefer a grantId explicitly carried by the just-submitted interaction.
63
+ const explicit = result?.consent?.grantId;
64
+ const wsId = activeWorkspaceId();
65
+ const candidate = (explicit && store.getGrant(explicit)) ||
66
+ store
67
+ .listGrants()
68
+ .filter((g) => g.clientId === clientId && g.revokedAt === null && (g.workspaceId === wsId || store.getMeta(`identity-grant:${g.id}`) === '2'))
69
+ .pop();
70
+ if (!candidate || candidate.revokedAt !== null || (candidate.workspaceId !== wsId && store.getMeta(`identity-grant:${candidate.id}`) !== '2'))
71
+ return undefined;
72
+ return ctx.oidc.provider.Grant.find(candidate.id);
73
+ },
74
+ issueRefreshToken: async (_ctx, client) => client.grantTypeAllowed('refresh_token'),
75
+ rotateRefreshToken: true,
76
+ extraTokenClaims: async (_ctx, token) => {
77
+ // Preserve the original grant and version across refresh. dodo_ws is
78
+ // retained for legacy tokens; v2 authorization checks the active ACL.
79
+ const grantId = token.grantId;
80
+ const appGrant = grantId ? store.getGrant(grantId) : undefined;
81
+ return {
82
+ dodo_grant: grantId ?? null,
83
+ dodo_ws: appGrant?.workspaceId ?? null,
84
+ dodo_auth: grantId && store.getMeta(`identity-grant:${grantId}`) === '2' ? 2 : 1,
85
+ };
86
+ },
87
+ ttl: {
88
+ AccessToken: opts.accessTokenTtlSec ?? 600,
89
+ IdToken: 600,
90
+ AuthorizationCode: 60,
91
+ Grant: 30 * 24 * 3600,
92
+ Interaction: 300,
93
+ Session: 14 * 24 * 3600,
94
+ RefreshToken: 30 * 24 * 3600,
95
+ },
96
+ features: {
97
+ devInteractions: { enabled: false },
98
+ revocation: { enabled: true },
99
+ introspection: { enabled: false },
100
+ registration: { enabled: false }, // DCR off by default (spec §8.3)
101
+ rpInitiatedLogout: { enabled: false },
102
+ resourceIndicators: {
103
+ enabled: true,
104
+ defaultResource: () => resourceUrl,
105
+ useGrantedResource: () => true,
106
+ getResourceServerInfo: () => ({
107
+ scope: scopeString,
108
+ audience: resourceUrl,
109
+ accessTokenTTL: opts.accessTokenTtlSec ?? 600,
110
+ accessTokenFormat: 'jwt',
111
+ jwt: { sign: { alg: 'ES256' } },
112
+ }),
113
+ },
114
+ },
115
+ renderError: async (ctx, out, _error) => {
116
+ ctx.type = 'html';
117
+ ctx.body = `<!doctype html><meta charset="utf-8"><title>DODO auth error</title><body style="font-family:system-ui;max-width:36rem;margin:4rem auto"><h1>Authorization error</h1><p>${escapeHtml(out.error ?? 'error')}</p><p>${escapeHtml(out.error_description ?? '')}</p></body>`;
118
+ },
119
+ };
120
+ const provider = new Provider(opts.issuer, configuration);
121
+ // The only hop in front of DODO is the owner's local tunnel daemon on
122
+ // loopback; X-Forwarded-Proto from it is trusted so secure-cookie and
123
+ // https checks reflect the public HTTPS origin (ADR-013; Host is
124
+ // allowlisted before the provider ever sees a request).
125
+ provider.proxy = true;
126
+ return provider;
127
+ }
128
+ function escapeHtml(s) {
129
+ return s.replace(/[&<>"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' })[c]);
130
+ }
131
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/auth/provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ import { createLocalJWKSet, jwtVerify } from 'jose';
2
+ import { OAuthError, OAuthErrorCode } from '@modelcontextprotocol/server';
3
+ import { publicJwks } from './keys.js';
4
+ export function buildTokenVerifier(opts) {
5
+ const jwkSet = createLocalJWKSet(publicJwks(opts.jwks));
6
+ const active = () => {
7
+ if (opts.active)
8
+ return opts.active();
9
+ if (opts.workspaceId === undefined || opts.store === undefined)
10
+ throw new Error('verifier needs workspaceId+store or active()');
11
+ return { workspaceId: opts.workspaceId, store: opts.store };
12
+ };
13
+ return {
14
+ async verifyAccessToken(token) {
15
+ const { workspaceId, store } = active();
16
+ let payload;
17
+ try {
18
+ const result = await jwtVerify(token, jwkSet, {
19
+ issuer: opts.issuer,
20
+ audience: opts.resourceUrl,
21
+ algorithms: ['ES256'],
22
+ typ: 'at+jwt',
23
+ });
24
+ payload = result.payload;
25
+ }
26
+ catch {
27
+ throw new OAuthError(OAuthErrorCode.InvalidToken, 'invalid access token');
28
+ }
29
+ const grantId = payload['dodo_grant'];
30
+ const tokenWs = payload['dodo_ws'];
31
+ const clientId = payload['client_id'];
32
+ const exp = payload['exp'];
33
+ if (typeof grantId !== 'string' || typeof tokenWs !== 'string' || typeof clientId !== 'string' || typeof exp !== 'number') {
34
+ throw new OAuthError(OAuthErrorCode.InvalidToken, 'invalid access token');
35
+ }
36
+ const grant = store.getGrant(grantId);
37
+ if (!store.getOAuthClient(clientId) || !grant || grant.revokedAt !== null) {
38
+ throw new OAuthError(OAuthErrorCode.InvalidToken, 'grant revoked or unknown');
39
+ }
40
+ if (grant.clientId !== clientId) {
41
+ throw new OAuthError(OAuthErrorCode.InvalidToken, 'client mismatch');
42
+ }
43
+ const identityGrant = payload['dodo_auth'] === 2 && store.getMeta(`identity-grant:${grantId}`) === '2';
44
+ if (!identityGrant && (tokenWs !== grant.workspaceId || (!opts.targetRouting && tokenWs !== workspaceId))) {
45
+ // Token from another workspace on the same hostname: consent is
46
+ // per-workspace; never disclose the current root in the refusal.
47
+ throw new OAuthError(OAuthErrorCode.InvalidToken, 'token is not valid for this workspace');
48
+ }
49
+ let scopes = typeof payload['scope'] === 'string' ? payload['scope'].split(' ').filter(Boolean) : [];
50
+ const tokenScopes = [...scopes];
51
+ {
52
+ const access = store.clientAccess(workspaceId, clientId);
53
+ scopes = scopes.filter((scope) => access.includes(scope) && grant.scopes.includes(scope));
54
+ // Authentication remains valid with no workspace permissions. Tool gate
55
+ // returns WORKSPACE_ACCESS_REQUIRED without an OAuth relinking challenge.
56
+ }
57
+ return {
58
+ token,
59
+ clientId,
60
+ scopes,
61
+ expiresAt: exp,
62
+ resource: new URL(opts.resourceUrl),
63
+ extra: {
64
+ tokenScopes,
65
+ identityGrant,
66
+ grantId,
67
+ workspaceId,
68
+ sub: typeof payload['sub'] === 'string' ? payload['sub'] : 'owner',
69
+ },
70
+ };
71
+ },
72
+ };
73
+ }
74
+ //# sourceMappingURL=verifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifier.js","sourceRoot":"","sources":["../../src/auth/verifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,124 @@
1
+ import fs from 'node:fs';
2
+ import { ipcIdentity } from '../ipc/authentication.js';
3
+ import { z } from 'zod';
4
+ import { ipcSocketPath, statePaths } from '../config/paths.js';
5
+ import { openDatabaseReadonly } from '../store/db.js';
6
+ import { Store } from '../store/store.js';
7
+ import { mintWorkspaceId } from '../workspace/identity.js';
8
+ import { ipcCall, IpcError } from '../ipc/client.js';
9
+ const LiveStatus = z.looseObject({
10
+ pid: z.number().int().positive(), root: z.string().min(1).max(4096),
11
+ workspaceId: z.string(), workspaceEpoch: z.string().min(1),
12
+ version: z.string(), transport: z.enum(['http', 'stdio']),
13
+ });
14
+ /** Owner-only shutdown discovery. Never sends signals to PIDs or scans ports. */
15
+ export async function killServers(configDir, timeoutMs = 30_000) {
16
+ const report = { configDir, stopped: [], failed: [], authPreserved: true };
17
+ const dbFile = statePaths(configDir).dbFile;
18
+ if (!fs.existsSync(dbFile))
19
+ return report;
20
+ const db = openDatabaseReadonly(dbFile);
21
+ if (!db)
22
+ throw new Error('cannot read DODO state; no processes were stopped');
23
+ const candidates = [];
24
+ try {
25
+ const secret = new Store(db).readInstallSecret();
26
+ if (!secret)
27
+ throw new Error('DODO installation identity is missing; no processes were stopped');
28
+ let roots = db.prepare('SELECT id, root FROM workspaces ORDER BY root LIMIT 10001').all();
29
+ if (roots.length > 10000)
30
+ throw new Error('too many workspace records to inspect safely; use dodo stop for a specific workspace');
31
+ roots = roots.filter(w => typeof w.root === 'string' && typeof w.id === 'string' && w.id === mintWorkspaceId(secret, w.root));
32
+ for (const w of roots)
33
+ candidates.push({ ...w, socket: ipcSocketPath(configDir, w.id, { createDirectory: false }) });
34
+ const instances = db.prepare("SELECT value FROM meta WHERE key LIKE 'ipc-instance:%' LIMIT 10001").all();
35
+ if (instances.length > 10000)
36
+ throw new Error('too many instance records to inspect safely');
37
+ const Instance = z.object({ socketKey: z.string().regex(/^[a-f0-9]{32}$/), workspaceId: z.string(), root: z.string() }).strict();
38
+ for (const row of instances) {
39
+ try {
40
+ const i = Instance.parse(JSON.parse(row.value));
41
+ if (!roots.some(w => w.id === i.workspaceId && w.root === i.root))
42
+ continue;
43
+ candidates.unshift({ id: i.workspaceId, root: i.root, socket: ipcSocketPath(configDir, i.socketKey, { createDirectory: false }), instance: true });
44
+ }
45
+ catch { /* malformed historical metadata cannot authorize a target */ }
46
+ }
47
+ }
48
+ finally {
49
+ db.close();
50
+ }
51
+ // Probe all candidates before stopping anything, so root aliases cannot race
52
+ // their per-instance endpoints. Never trust stored PIDs as signal targets.
53
+ // Windows identity/credential validation runs synchronous ACL probes. A
54
+ // second worker would block the event loop while the first awaits its IPC
55
+ // handshake, spending that request's deadline on unrelated PowerShell work.
56
+ // Serialize there; retain every live identity and credential recheck.
57
+ const concurrency = process.platform === 'win32' ? 1 : 8;
58
+ const live = new Map();
59
+ let index = 0;
60
+ await Promise.all(Array.from({ length: Math.min(concurrency, candidates.length) }, async () => {
61
+ while (index < candidates.length) {
62
+ const w = candidates[index++], { socket } = w;
63
+ try {
64
+ const original = socketIdentity(socket);
65
+ if (!original)
66
+ continue;
67
+ let status;
68
+ try {
69
+ status = LiveStatus.parse(await ipcCall(socket, 'status', {}, 1500));
70
+ }
71
+ catch (e) {
72
+ if (isNotRunning(e))
73
+ continue;
74
+ throw e;
75
+ }
76
+ if (status.workspaceId !== w.id || status.root !== w.root)
77
+ throw new Error('IPC identity does not match the registered workspace');
78
+ if (socketIdentity(socket) !== original)
79
+ throw new Error('server changed while checking; retry dodo kill');
80
+ if (!live.has(status.pid) || (w.instance && !live.get(status.pid).candidate.instance))
81
+ live.set(status.pid, { candidate: w, status, identity: original });
82
+ }
83
+ catch (e) {
84
+ if (!isNotRunning(e))
85
+ report.failed.push({ root: w.root, reason: e instanceof Error ? e.message : 'shutdown failed' });
86
+ }
87
+ }
88
+ }));
89
+ const targets = [...live.values()];
90
+ index = 0;
91
+ await Promise.all(Array.from({ length: Math.min(concurrency, targets.length) }, async () => {
92
+ while (index < targets.length) {
93
+ const { candidate: w, status, identity } = targets[index++];
94
+ try {
95
+ if (socketIdentity(w.socket) !== identity)
96
+ throw new Error('server changed before shutdown; retry dodo kill');
97
+ const result = await ipcCall(w.socket, 'stop', { expectedPid: status.pid, expectedEpoch: status.workspaceEpoch }, 1500);
98
+ if (!z.object({ stopping: z.literal(true) }).safeParse(result).success)
99
+ throw new Error('server did not acknowledge shutdown');
100
+ const deadline = Date.now() + timeoutMs;
101
+ while (socketIdentity(w.socket) === identity) {
102
+ if (Date.now() >= deadline)
103
+ throw new Error('shutdown is still draining work; retry status later (no force kill sent)');
104
+ await new Promise(resolve => setTimeout(resolve, 100));
105
+ }
106
+ report.stopped.push({ pid: status.pid, root: status.root, transport: status.transport });
107
+ }
108
+ catch (e) {
109
+ if (!isNotRunning(e))
110
+ report.failed.push({ root: w.root, reason: e instanceof Error ? e.message : 'shutdown failed' });
111
+ }
112
+ }
113
+ }));
114
+ report.stopped.sort((a, b) => a.root.localeCompare(b.root));
115
+ report.failed.sort((a, b) => a.root.localeCompare(b.root));
116
+ return report;
117
+ }
118
+ function isNotRunning(e) {
119
+ return e instanceof IpcError && e.message.startsWith('no running DODO server');
120
+ }
121
+ function socketIdentity(socket) {
122
+ return ipcIdentity(socket);
123
+ }
124
+ //# sourceMappingURL=kill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kill.js","sourceRoot":"","sources":["../../src/cli/kill.ts"],"names":[],"mappings":"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"}