@bevel-software/platform-core-backend 0.20.0 → 0.22.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 (666) hide show
  1. package/dist/core/catalog-cache-invalidation.d.ts +7 -2
  2. package/dist/core/catalog-cache-invalidation.d.ts.map +1 -1
  3. package/dist/core/catalog-cache-invalidation.js +8 -9
  4. package/dist/core/catalog-cache-invalidation.js.map +1 -1
  5. package/dist/core/core-ports.d.ts +19 -0
  6. package/dist/core/core-ports.d.ts.map +1 -1
  7. package/dist/core/core-ports.js.map +1 -1
  8. package/dist/core/create-core-server.d.ts +2 -0
  9. package/dist/core/create-core-server.d.ts.map +1 -1
  10. package/dist/core/create-core-server.js +55 -107
  11. package/dist/core/create-core-server.js.map +1 -1
  12. package/dist/core/create-core-services.d.ts +41 -4
  13. package/dist/core/create-core-services.d.ts.map +1 -1
  14. package/dist/core/create-core-services.js +183 -82
  15. package/dist/core/create-core-services.js.map +1 -1
  16. package/dist/core/lifecycle.d.ts +74 -28
  17. package/dist/core/lifecycle.d.ts.map +1 -1
  18. package/dist/core/lifecycle.js +157 -20
  19. package/dist/core/lifecycle.js.map +1 -1
  20. package/dist/core/public-config.d.ts +5 -1
  21. package/dist/core/public-config.d.ts.map +1 -1
  22. package/dist/core/public-config.js +7 -5
  23. package/dist/core/public-config.js.map +1 -1
  24. package/dist/core-config.d.ts +95 -1
  25. package/dist/core-config.d.ts.map +1 -1
  26. package/dist/core-config.js +24 -8
  27. package/dist/core-config.js.map +1 -1
  28. package/dist/index.d.ts +5 -3
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +6 -3
  31. package/dist/index.js.map +1 -1
  32. package/dist/modules/access/access-control.service.d.ts +18 -1
  33. package/dist/modules/access/access-control.service.d.ts.map +1 -1
  34. package/dist/modules/access/access-control.service.js +19 -8
  35. package/dist/modules/access/access-control.service.js.map +1 -1
  36. package/dist/modules/access/access-requests.contract.d.ts +75 -0
  37. package/dist/modules/access/access-requests.contract.d.ts.map +1 -0
  38. package/dist/modules/access/access-requests.contract.js +20 -0
  39. package/dist/modules/access/access-requests.contract.js.map +1 -0
  40. package/dist/modules/access/access-requests.routes.d.ts +35 -0
  41. package/dist/modules/access/access-requests.routes.d.ts.map +1 -0
  42. package/dist/modules/access/access-requests.routes.js +237 -0
  43. package/dist/modules/access/access-requests.routes.js.map +1 -0
  44. package/dist/modules/access/access-requests.service.d.ts +123 -0
  45. package/dist/modules/access/access-requests.service.d.ts.map +1 -0
  46. package/dist/modules/access/access-requests.service.js +337 -0
  47. package/dist/modules/access/access-requests.service.js.map +1 -0
  48. package/dist/modules/access/access.routes.d.ts +2 -1
  49. package/dist/modules/access/access.routes.d.ts.map +1 -1
  50. package/dist/modules/access/access.routes.js +10 -10
  51. package/dist/modules/access/access.routes.js.map +1 -1
  52. package/dist/modules/access/change-read-gate.d.ts +6 -3
  53. package/dist/modules/access/change-read-gate.d.ts.map +1 -1
  54. package/dist/modules/access/change-read-gate.js +9 -6
  55. package/dist/modules/access/change-read-gate.js.map +1 -1
  56. package/dist/modules/access/creator-access.d.ts +4 -2
  57. package/dist/modules/access/creator-access.d.ts.map +1 -1
  58. package/dist/modules/access/creator-access.js +7 -4
  59. package/dist/modules/access/creator-access.js.map +1 -1
  60. package/dist/modules/access-model/access-grammar.d.ts +12 -0
  61. package/dist/modules/access-model/access-grammar.d.ts.map +1 -1
  62. package/dist/modules/access-model/access-grammar.js +24 -0
  63. package/dist/modules/access-model/access-grammar.js.map +1 -1
  64. package/dist/modules/agent-instructions/read-preamble.d.ts +2 -1
  65. package/dist/modules/agent-instructions/read-preamble.d.ts.map +1 -1
  66. package/dist/modules/agent-instructions/read-preamble.js +6 -9
  67. package/dist/modules/agent-instructions/read-preamble.js.map +1 -1
  68. package/dist/modules/auth/account-admission.d.ts +40 -0
  69. package/dist/modules/auth/account-admission.d.ts.map +1 -0
  70. package/dist/modules/auth/account-admission.js +17 -0
  71. package/dist/modules/auth/account-admission.js.map +1 -0
  72. package/dist/modules/auth/account.routes.d.ts.map +1 -1
  73. package/dist/modules/auth/account.routes.js +4 -1
  74. package/dist/modules/auth/account.routes.js.map +1 -1
  75. package/dist/modules/auth/auth.service.d.ts +45 -2
  76. package/dist/modules/auth/auth.service.d.ts.map +1 -1
  77. package/dist/modules/auth/auth.service.js +44 -3
  78. package/dist/modules/auth/auth.service.js.map +1 -1
  79. package/dist/modules/auth/oidc-auth-provider.d.ts.map +1 -1
  80. package/dist/modules/auth/oidc-auth-provider.js +9 -0
  81. package/dist/modules/auth/oidc-auth-provider.js.map +1 -1
  82. package/dist/modules/connection-probe/connection-probe.service.d.ts +13 -1
  83. package/dist/modules/connection-probe/connection-probe.service.d.ts.map +1 -1
  84. package/dist/modules/connection-probe/connection-probe.service.js +10 -2
  85. package/dist/modules/connection-probe/connection-probe.service.js.map +1 -1
  86. package/dist/modules/database/advisory-lock.d.ts +17 -0
  87. package/dist/modules/database/advisory-lock.d.ts.map +1 -1
  88. package/dist/modules/database/advisory-lock.js +24 -3
  89. package/dist/modules/database/advisory-lock.js.map +1 -1
  90. package/dist/modules/database/connection.d.ts +67 -2
  91. package/dist/modules/database/connection.d.ts.map +1 -1
  92. package/dist/modules/database/connection.js +118 -12
  93. package/dist/modules/database/connection.js.map +1 -1
  94. package/dist/modules/database/migrate.d.ts +1 -1
  95. package/dist/modules/database/migrate.d.ts.map +1 -1
  96. package/dist/modules/database/migrate.js +27 -3
  97. package/dist/modules/database/migrate.js.map +1 -1
  98. package/dist/modules/github-app/github-app.client.d.ts +101 -0
  99. package/dist/modules/github-app/github-app.client.d.ts.map +1 -0
  100. package/dist/modules/github-app/github-app.client.js +222 -0
  101. package/dist/modules/github-app/github-app.client.js.map +1 -0
  102. package/dist/modules/github-app/github-app.connection.d.ts +102 -0
  103. package/dist/modules/github-app/github-app.connection.d.ts.map +1 -0
  104. package/dist/modules/github-app/github-app.connection.js +185 -0
  105. package/dist/modules/github-app/github-app.connection.js.map +1 -0
  106. package/dist/modules/github-app/github-app.routes.d.ts +59 -0
  107. package/dist/modules/github-app/github-app.routes.d.ts.map +1 -0
  108. package/dist/modules/github-app/github-app.routes.js +323 -0
  109. package/dist/modules/github-app/github-app.routes.js.map +1 -0
  110. package/dist/modules/github-app/index.d.ts +4 -0
  111. package/dist/modules/github-app/index.d.ts.map +1 -0
  112. package/dist/modules/github-app/index.js +4 -0
  113. package/dist/modules/github-app/index.js.map +1 -0
  114. package/dist/modules/kb-fs/branch-name.d.ts +0 -1
  115. package/dist/modules/kb-fs/branch-name.d.ts.map +1 -1
  116. package/dist/modules/kb-fs/branch-name.js +3 -3
  117. package/dist/modules/kb-fs/branch-name.js.map +1 -1
  118. package/dist/modules/kb-fs/clone-config.d.ts +9 -8
  119. package/dist/modules/kb-fs/clone-config.d.ts.map +1 -1
  120. package/dist/modules/kb-fs/clone-config.js +14 -12
  121. package/dist/modules/kb-fs/clone-config.js.map +1 -1
  122. package/dist/modules/kb-fs/remote-url.d.ts +22 -0
  123. package/dist/modules/kb-fs/remote-url.d.ts.map +1 -0
  124. package/dist/modules/kb-fs/remote-url.js +35 -0
  125. package/dist/modules/kb-fs/remote-url.js.map +1 -0
  126. package/dist/modules/mcp/mcp.service.d.ts +7 -0
  127. package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
  128. package/dist/modules/mcp/mcp.service.js +4 -4
  129. package/dist/modules/mcp/mcp.service.js.map +1 -1
  130. package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts +4 -4
  131. package/dist/modules/plugins/compile/marketplace-compiler.service.d.ts.map +1 -1
  132. package/dist/modules/plugins/compile/marketplace-compiler.service.js +7 -10
  133. package/dist/modules/plugins/compile/marketplace-compiler.service.js.map +1 -1
  134. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.d.ts +4 -1
  135. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.d.ts.map +1 -1
  136. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.js +5 -3
  137. package/dist/modules/plugins/discovery/bundle-dialect/bundle.source.js.map +1 -1
  138. package/dist/modules/plugins/discovery/kb-plugin-source.d.ts +6 -1
  139. package/dist/modules/plugins/discovery/kb-plugin-source.d.ts.map +1 -1
  140. package/dist/modules/plugins/discovery/kb-plugin-source.js +14 -9
  141. package/dist/modules/plugins/discovery/kb-plugin-source.js.map +1 -1
  142. package/dist/modules/plugins/discovery/native.source.d.ts +4 -1
  143. package/dist/modules/plugins/discovery/native.source.d.ts.map +1 -1
  144. package/dist/modules/plugins/discovery/native.source.js +4 -2
  145. package/dist/modules/plugins/discovery/native.source.js.map +1 -1
  146. package/dist/modules/plugins/index.d.ts +1 -1
  147. package/dist/modules/plugins/index.d.ts.map +1 -1
  148. package/dist/modules/plugins/index.js +1 -1
  149. package/dist/modules/plugins/index.js.map +1 -1
  150. package/dist/modules/plugins/join-proposals.d.ts +17 -5
  151. package/dist/modules/plugins/join-proposals.d.ts.map +1 -1
  152. package/dist/modules/plugins/join-proposals.js +76 -22
  153. package/dist/modules/plugins/join-proposals.js.map +1 -1
  154. package/dist/modules/plugins/join-request-jobs.service.d.ts +3 -1
  155. package/dist/modules/plugins/join-request-jobs.service.d.ts.map +1 -1
  156. package/dist/modules/plugins/join-request-jobs.service.js +6 -6
  157. package/dist/modules/plugins/join-request-jobs.service.js.map +1 -1
  158. package/dist/modules/plugins/join-requests.service.d.ts +113 -18
  159. package/dist/modules/plugins/join-requests.service.d.ts.map +1 -1
  160. package/dist/modules/plugins/join-requests.service.js +178 -33
  161. package/dist/modules/plugins/join-requests.service.js.map +1 -1
  162. package/dist/modules/plugins/plugin-links.d.ts +65 -10
  163. package/dist/modules/plugins/plugin-links.d.ts.map +1 -1
  164. package/dist/modules/plugins/plugin-links.js +136 -31
  165. package/dist/modules/plugins/plugin-links.js.map +1 -1
  166. package/dist/modules/plugins/plugin-links.service.d.ts +107 -5
  167. package/dist/modules/plugins/plugin-links.service.d.ts.map +1 -1
  168. package/dist/modules/plugins/plugin-links.service.js +151 -21
  169. package/dist/modules/plugins/plugin-links.service.js.map +1 -1
  170. package/dist/modules/plugins/plugin-provision.service.d.ts +10 -3
  171. package/dist/modules/plugins/plugin-provision.service.d.ts.map +1 -1
  172. package/dist/modules/plugins/plugin-provision.service.js +33 -26
  173. package/dist/modules/plugins/plugin-provision.service.js.map +1 -1
  174. package/dist/modules/plugins/plugin-rename.service.d.ts +4 -2
  175. package/dist/modules/plugins/plugin-rename.service.d.ts.map +1 -1
  176. package/dist/modules/plugins/plugin-rename.service.js +10 -12
  177. package/dist/modules/plugins/plugin-rename.service.js.map +1 -1
  178. package/dist/modules/plugins/plugins.routes.d.ts +3 -0
  179. package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
  180. package/dist/modules/plugins/plugins.routes.js +48 -17
  181. package/dist/modules/plugins/plugins.routes.js.map +1 -1
  182. package/dist/modules/plugins/plugins.service.d.ts +4 -4
  183. package/dist/modules/plugins/plugins.service.d.ts.map +1 -1
  184. package/dist/modules/plugins/plugins.service.js +7 -10
  185. package/dist/modules/plugins/plugins.service.js.map +1 -1
  186. package/dist/modules/plugins/teams.routes.d.ts +4 -1
  187. package/dist/modules/plugins/teams.routes.d.ts.map +1 -1
  188. package/dist/modules/plugins/teams.routes.js +11 -9
  189. package/dist/modules/plugins/teams.routes.js.map +1 -1
  190. package/dist/modules/secrets-vault/index.d.ts +1 -1
  191. package/dist/modules/secrets-vault/index.d.ts.map +1 -1
  192. package/dist/modules/secrets-vault/index.js +1 -1
  193. package/dist/modules/secrets-vault/index.js.map +1 -1
  194. package/dist/modules/secrets-vault/secrets-variable-loader.d.ts +29 -11
  195. package/dist/modules/secrets-vault/secrets-variable-loader.d.ts.map +1 -1
  196. package/dist/modules/secrets-vault/secrets-variable-loader.js +46 -21
  197. package/dist/modules/secrets-vault/secrets-variable-loader.js.map +1 -1
  198. package/dist/modules/secrets-vault/secrets-vault.routes.d.ts +3 -0
  199. package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -1
  200. package/dist/modules/secrets-vault/secrets-vault.routes.js +4 -6
  201. package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -1
  202. package/dist/modules/settings/deployment-settings.service.d.ts +34 -9
  203. package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
  204. package/dist/modules/settings/deployment-settings.service.js +113 -26
  205. package/dist/modules/settings/deployment-settings.service.js.map +1 -1
  206. package/dist/modules/settings/managed-repository.d.ts +43 -0
  207. package/dist/modules/settings/managed-repository.d.ts.map +1 -0
  208. package/dist/modules/settings/managed-repository.js +60 -0
  209. package/dist/modules/settings/managed-repository.js.map +1 -0
  210. package/dist/modules/settings/repository-source.d.ts +128 -0
  211. package/dist/modules/settings/repository-source.d.ts.map +1 -0
  212. package/dist/modules/settings/repository-source.js +150 -0
  213. package/dist/modules/settings/repository-source.js.map +1 -0
  214. package/dist/modules/settings/setup.routes.d.ts +34 -4
  215. package/dist/modules/settings/setup.routes.d.ts.map +1 -1
  216. package/dist/modules/settings/setup.routes.js +198 -18
  217. package/dist/modules/settings/setup.routes.js.map +1 -1
  218. package/dist/modules/skills/allowed-tools-check.d.ts +4 -3
  219. package/dist/modules/skills/allowed-tools-check.d.ts.map +1 -1
  220. package/dist/modules/skills/allowed-tools-check.js +8 -8
  221. package/dist/modules/skills/allowed-tools-check.js.map +1 -1
  222. package/dist/modules/skills/pending-skills.service.d.ts +3 -1
  223. package/dist/modules/skills/pending-skills.service.d.ts.map +1 -1
  224. package/dist/modules/skills/pending-skills.service.js +9 -6
  225. package/dist/modules/skills/pending-skills.service.js.map +1 -1
  226. package/dist/modules/skills/skill-access-requests.routes.d.ts +8 -9
  227. package/dist/modules/skills/skill-access-requests.routes.d.ts.map +1 -1
  228. package/dist/modules/skills/skill-access-requests.routes.js +26 -65
  229. package/dist/modules/skills/skill-access-requests.routes.js.map +1 -1
  230. package/dist/modules/skills/skills.routes.d.ts +4 -1
  231. package/dist/modules/skills/skills.routes.d.ts.map +1 -1
  232. package/dist/modules/skills/skills.routes.js +4 -4
  233. package/dist/modules/skills/skills.routes.js.map +1 -1
  234. package/dist/modules/skills/skills.service.d.ts +4 -2
  235. package/dist/modules/skills/skills.service.d.ts.map +1 -1
  236. package/dist/modules/skills/skills.service.js +13 -11
  237. package/dist/modules/skills/skills.service.js.map +1 -1
  238. package/dist/modules/tool-helpers/tool-context.d.ts.map +1 -1
  239. package/dist/modules/tool-helpers/tool-context.js +15 -0
  240. package/dist/modules/tool-helpers/tool-context.js.map +1 -1
  241. package/dist/modules/tool-manuals/mcp-json-discovery.d.ts +2 -1
  242. package/dist/modules/tool-manuals/mcp-json-discovery.d.ts.map +1 -1
  243. package/dist/modules/tool-manuals/mcp-json-discovery.js +6 -5
  244. package/dist/modules/tool-manuals/mcp-json-discovery.js.map +1 -1
  245. package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts +4 -2
  246. package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts.map +1 -1
  247. package/dist/modules/tool-manuals/mcp-server-edit.service.js +12 -10
  248. package/dist/modules/tool-manuals/mcp-server-edit.service.js.map +1 -1
  249. package/dist/modules/tool-manuals/pending-tools.service.d.ts +3 -1
  250. package/dist/modules/tool-manuals/pending-tools.service.d.ts.map +1 -1
  251. package/dist/modules/tool-manuals/pending-tools.service.js +19 -16
  252. package/dist/modules/tool-manuals/pending-tools.service.js.map +1 -1
  253. package/dist/modules/tool-manuals/tool-delete.service.d.ts +4 -2
  254. package/dist/modules/tool-manuals/tool-delete.service.d.ts.map +1 -1
  255. package/dist/modules/tool-manuals/tool-delete.service.js +14 -12
  256. package/dist/modules/tool-manuals/tool-delete.service.js.map +1 -1
  257. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts +3 -1
  258. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts.map +1 -1
  259. package/dist/modules/tool-manuals/tool-manuals.routes.js +7 -7
  260. package/dist/modules/tool-manuals/tool-manuals.routes.js.map +1 -1
  261. package/dist/modules/tool-manuals/tool-manuals.service.d.ts +4 -2
  262. package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
  263. package/dist/modules/tool-manuals/tool-manuals.service.js +15 -12
  264. package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
  265. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +3 -0
  266. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
  267. package/dist/modules/tool-manuals/tool-manuals.tools.js +4 -6
  268. package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
  269. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts +3 -2
  270. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
  271. package/dist/modules/workflow/agent-tools/workflow.tools.js +47 -11
  272. package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
  273. package/dist/modules/workflow/git/git.service.d.ts +14 -6
  274. package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
  275. package/dist/modules/workflow/git/git.service.js +40 -18
  276. package/dist/modules/workflow/git/git.service.js.map +1 -1
  277. package/dist/modules/workflow/git/node-git-runner.d.ts +26 -2
  278. package/dist/modules/workflow/git/node-git-runner.d.ts.map +1 -1
  279. package/dist/modules/workflow/git/node-git-runner.js +40 -5
  280. package/dist/modules/workflow/git/node-git-runner.js.map +1 -1
  281. package/dist/modules/workflow/git/pull-request.service.d.ts +45 -0
  282. package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -1
  283. package/dist/modules/workflow/git/pull-request.service.js +99 -0
  284. package/dist/modules/workflow/git/pull-request.service.js.map +1 -1
  285. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -1
  286. package/dist/modules/workflow/review-workflow/review-workflow.service.js +9 -4
  287. package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -1
  288. package/dist/modules/workflow/session-ontology.service.d.ts +6 -1
  289. package/dist/modules/workflow/session-ontology.service.d.ts.map +1 -1
  290. package/dist/modules/workflow/session-ontology.service.js +6 -2
  291. package/dist/modules/workflow/session-ontology.service.js.map +1 -1
  292. package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
  293. package/dist/modules/workflow/workflow.routes.js +3 -1
  294. package/dist/modules/workflow/workflow.routes.js.map +1 -1
  295. package/dist/modules/workflow/workflow.service.d.ts +42 -10
  296. package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
  297. package/dist/modules/workflow/workflow.service.js +181 -71
  298. package/dist/modules/workflow/workflow.service.js.map +1 -1
  299. package/dist/modules/workspace/session-ontology.gate.d.ts +3 -1
  300. package/dist/modules/workspace/session-ontology.gate.d.ts.map +1 -1
  301. package/dist/modules/workspace/session-ontology.gate.js +3 -3
  302. package/dist/modules/workspace/session-ontology.gate.js.map +1 -1
  303. package/dist/modules/workspace/startup/kb-git.d.ts +4 -3
  304. package/dist/modules/workspace/startup/kb-git.d.ts.map +1 -1
  305. package/dist/modules/workspace/startup/kb-git.js +15 -13
  306. package/dist/modules/workspace/startup/kb-git.js.map +1 -1
  307. package/dist/modules/workspace/startup/kb-startup-runner.d.ts +70 -7
  308. package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
  309. package/dist/modules/workspace/startup/kb-startup-runner.js +183 -38
  310. package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
  311. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.d.ts +7 -1
  312. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.d.ts.map +1 -1
  313. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js +23 -16
  314. package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js.map +1 -1
  315. package/dist/modules/workspace/startup/steps/personal-spaces.step.d.ts +7 -1
  316. package/dist/modules/workspace/startup/steps/personal-spaces.step.d.ts.map +1 -1
  317. package/dist/modules/workspace/startup/steps/personal-spaces.step.js +12 -5
  318. package/dist/modules/workspace/startup/steps/personal-spaces.step.js.map +1 -1
  319. package/dist/modules/workspace/startup/steps/plugin-display-names.step.d.ts +7 -1
  320. package/dist/modules/workspace/startup/steps/plugin-display-names.step.d.ts.map +1 -1
  321. package/dist/modules/workspace/startup/steps/plugin-display-names.step.js +12 -5
  322. package/dist/modules/workspace/startup/steps/plugin-display-names.step.js.map +1 -1
  323. package/dist/modules/workspace/startup/steps/plugin-manifests.step.d.ts +7 -1
  324. package/dist/modules/workspace/startup/steps/plugin-manifests.step.d.ts.map +1 -1
  325. package/dist/modules/workspace/startup/steps/plugin-manifests.step.js +12 -5
  326. package/dist/modules/workspace/startup/steps/plugin-manifests.step.js.map +1 -1
  327. package/dist/modules/workspace/startup/steps/seed-tree.d.ts +4 -1
  328. package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
  329. package/dist/modules/workspace/startup/steps/seed-tree.js +14 -11
  330. package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
  331. package/dist/modules/workspace/startup/steps/template-files.step.d.ts +17 -3
  332. package/dist/modules/workspace/startup/steps/template-files.step.d.ts.map +1 -1
  333. package/dist/modules/workspace/startup/steps/template-files.step.js +36 -30
  334. package/dist/modules/workspace/startup/steps/template-files.step.js.map +1 -1
  335. package/dist/modules/workspace/startup/steps/template-source.d.ts +6 -1
  336. package/dist/modules/workspace/startup/steps/template-source.d.ts.map +1 -1
  337. package/dist/modules/workspace/startup/steps/template-source.js +10 -6
  338. package/dist/modules/workspace/startup/steps/template-source.js.map +1 -1
  339. package/dist/modules/workspace/workspace.routes.d.ts +2 -1
  340. package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
  341. package/dist/modules/workspace/workspace.routes.js +8 -7
  342. package/dist/modules/workspace/workspace.routes.js.map +1 -1
  343. package/dist/modules/workspace/workspace.service.d.ts +18 -12
  344. package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
  345. package/dist/modules/workspace/workspace.service.js +49 -29
  346. package/dist/modules/workspace/workspace.service.js.map +1 -1
  347. package/dist/modules/workspace/workspace.tools.d.ts +2 -1
  348. package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
  349. package/dist/modules/workspace/workspace.tools.js +48 -20
  350. package/dist/modules/workspace/workspace.tools.js.map +1 -1
  351. package/dist/modules/workspace/write-denial.d.ts +3 -2
  352. package/dist/modules/workspace/write-denial.d.ts.map +1 -1
  353. package/dist/modules/workspace/write-denial.js +6 -5
  354. package/dist/modules/workspace/write-denial.js.map +1 -1
  355. package/dist/shared/domain-errors.d.ts +39 -0
  356. package/dist/shared/domain-errors.d.ts.map +1 -1
  357. package/dist/shared/domain-errors.js +55 -0
  358. package/dist/shared/domain-errors.js.map +1 -1
  359. package/dist/shared/git.contract.d.ts +62 -7
  360. package/dist/shared/git.contract.d.ts.map +1 -1
  361. package/dist/shared/git.contract.js +30 -8
  362. package/dist/shared/git.contract.js.map +1 -1
  363. package/dist/shared/kb-context.d.ts +76 -0
  364. package/dist/shared/kb-context.d.ts.map +1 -0
  365. package/dist/shared/kb-context.js +108 -0
  366. package/dist/shared/kb-context.js.map +1 -0
  367. package/dist/shared/kb-layout.d.ts +3 -2
  368. package/dist/shared/kb-layout.d.ts.map +1 -1
  369. package/dist/shared/kb-layout.js +4 -3
  370. package/dist/shared/kb-layout.js.map +1 -1
  371. package/dist/shared/kb-layout.test.js +35 -27
  372. package/dist/shared/kb-layout.test.js.map +1 -1
  373. package/dist/shared/pending-proposals.d.ts +4 -1
  374. package/dist/shared/pending-proposals.d.ts.map +1 -1
  375. package/dist/shared/pending-proposals.js +3 -4
  376. package/dist/shared/pending-proposals.js.map +1 -1
  377. package/dist/shared/redact-secret.d.ts +5 -5
  378. package/dist/shared/redact-secret.js +5 -5
  379. package/dist/tenancy/index.d.ts +13 -0
  380. package/dist/tenancy/index.d.ts.map +1 -0
  381. package/dist/tenancy/index.js +13 -0
  382. package/dist/tenancy/index.js.map +1 -0
  383. package/dist/tenancy/static-tenant-source.d.ts +98 -0
  384. package/dist/tenancy/static-tenant-source.d.ts.map +1 -0
  385. package/dist/tenancy/static-tenant-source.js +220 -0
  386. package/dist/tenancy/static-tenant-source.js.map +1 -0
  387. package/dist/tenancy/tenant-host.d.ts +80 -0
  388. package/dist/tenancy/tenant-host.d.ts.map +1 -0
  389. package/dist/tenancy/tenant-host.js +217 -0
  390. package/dist/tenancy/tenant-host.js.map +1 -0
  391. package/dist/tenancy/tenant-runtime.d.ts +91 -0
  392. package/dist/tenancy/tenant-runtime.d.ts.map +1 -0
  393. package/dist/tenancy/tenant-runtime.js +174 -0
  394. package/dist/tenancy/tenant-runtime.js.map +1 -0
  395. package/dist/tenancy/tenant-secrets.d.ts +24 -0
  396. package/dist/tenancy/tenant-secrets.d.ts.map +1 -0
  397. package/dist/tenancy/tenant-secrets.js +30 -0
  398. package/dist/tenancy/tenant-secrets.js.map +1 -0
  399. package/dist/tenancy/tenant-source.contract.d.ts +45 -0
  400. package/dist/tenancy/tenant-source.contract.d.ts.map +1 -0
  401. package/dist/tenancy/tenant-source.contract.js +21 -0
  402. package/dist/tenancy/tenant-source.contract.js.map +1 -0
  403. package/migrations/0000_core_init.sql +14 -14
  404. package/migrations/0003_deployment_settings.sql +1 -1
  405. package/migrations/0005_github_facade.sql +1 -1
  406. package/migrations/0012_agent_audit.sql +6 -6
  407. package/package.json +3 -3
  408. package/src/__tests__/branch-model.test.ts +7 -6
  409. package/src/__tests__/kb-context.ts +30 -0
  410. package/src/__tests__/kb-layout-config.test.ts +35 -30
  411. package/src/core/__tests__/catalog-cache-invalidation.test.ts +2 -1
  412. package/src/core/__tests__/lifecycle.test.ts +78 -1
  413. package/src/core/__tests__/public-config.test.ts +5 -1
  414. package/src/core/catalog-cache-invalidation.ts +16 -11
  415. package/src/core/core-ports.ts +19 -0
  416. package/src/core/create-core-server.ts +64 -107
  417. package/src/core/create-core-services.ts +238 -96
  418. package/src/core/lifecycle.ts +214 -29
  419. package/src/core/public-config.ts +8 -5
  420. package/src/core-config.ts +107 -8
  421. package/src/index.ts +25 -2
  422. package/src/modules/access/__tests__/access-control.admin-root-floor.test.ts +2 -1
  423. package/src/modules/access/__tests__/access-requests.recut.test.ts +134 -0
  424. package/src/modules/access/__tests__/access-requests.routes.test.ts +610 -0
  425. package/src/modules/access/__tests__/access.routes.batch.test.ts +2 -1
  426. package/src/modules/access/__tests__/access.routes.folder-governs.test.ts +2 -1
  427. package/src/modules/access/__tests__/access.routes.group-grant.test.ts +2 -1
  428. package/src/modules/access/__tests__/access.routes.overrides.test.ts +2 -1
  429. package/src/modules/access/__tests__/access.routes.proposal-branch.test.ts +2 -1
  430. package/src/modules/access/__tests__/access.routes.prospective.test.ts +2 -1
  431. package/src/modules/access/__tests__/access.routes.revoke.test.ts +2 -1
  432. package/src/modules/access/__tests__/access.routes.unknown-email.test.ts +2 -1
  433. package/src/modules/access/__tests__/change-read-gate.test.ts +13 -11
  434. package/src/modules/access/__tests__/creator-access.test.ts +3 -2
  435. package/src/modules/access/__tests__/roles.routes.test.ts +2 -1
  436. package/src/modules/access/access-control.service.ts +20 -6
  437. package/src/modules/access/access-requests.contract.ts +93 -0
  438. package/src/modules/access/access-requests.routes.ts +286 -0
  439. package/src/modules/access/access-requests.service.ts +420 -0
  440. package/src/modules/access/access.routes.ts +10 -13
  441. package/src/modules/access/change-read-gate.ts +10 -4
  442. package/src/modules/access/creator-access.ts +7 -2
  443. package/src/modules/access-model/access-grammar.ts +22 -0
  444. package/src/modules/agent-instructions/__tests__/read-preamble.test.ts +13 -12
  445. package/src/modules/agent-instructions/read-preamble.ts +10 -12
  446. package/src/modules/auth/__tests__/account.routes.test.ts +15 -0
  447. package/src/modules/auth/__tests__/auth.service.test.ts +98 -0
  448. package/src/modules/auth/account-admission.ts +44 -0
  449. package/src/modules/auth/account.routes.ts +4 -1
  450. package/src/modules/auth/auth.service.ts +61 -2
  451. package/src/modules/auth/oidc-auth-provider.ts +9 -0
  452. package/src/modules/connection-probe/connection-probe.service.ts +7 -1
  453. package/src/modules/database/__tests__/advisory-lock.test.ts +23 -1
  454. package/src/modules/database/__tests__/connection.test.ts +98 -0
  455. package/src/modules/database/__tests__/migrations-unqualified.test.ts +32 -0
  456. package/src/modules/database/advisory-lock.ts +28 -4
  457. package/src/modules/database/connection.ts +143 -13
  458. package/src/modules/database/migrate.ts +48 -14
  459. package/src/modules/diff/__tests__/diff.service.seed-atomicity.test.ts +2 -1
  460. package/src/modules/diff/__tests__/diff.service.test.ts +2 -1
  461. package/src/modules/github-app/__tests__/github-app.test.ts +848 -0
  462. package/src/modules/github-app/github-app.client.ts +268 -0
  463. package/src/modules/github-app/github-app.connection.ts +204 -0
  464. package/src/modules/github-app/github-app.routes.ts +359 -0
  465. package/src/modules/github-app/index.ts +19 -0
  466. package/src/modules/kb-fs/__tests__/branch-name.test.ts +6 -6
  467. package/src/modules/kb-fs/__tests__/clone-config.test.ts +24 -20
  468. package/src/modules/kb-fs/__tests__/remote-url.test.ts +38 -0
  469. package/src/modules/kb-fs/branch-name.ts +3 -3
  470. package/src/modules/kb-fs/clone-config.ts +15 -12
  471. package/src/modules/kb-fs/remote-url.ts +35 -0
  472. package/src/modules/marketplace/__tests__/marketplace-repo.head.test.ts +2 -1
  473. package/src/modules/mcp/mcp.service.ts +11 -4
  474. package/src/modules/plugins/__tests__/bundle-dialect.e2e.test.ts +12 -11
  475. package/src/modules/plugins/__tests__/bundle-dialect.test.ts +2 -1
  476. package/src/modules/plugins/__tests__/compile-marketplace.test.ts +6 -4
  477. package/src/modules/plugins/__tests__/join-proposals.test.ts +100 -19
  478. package/src/modules/plugins/__tests__/join-request-jobs.service.test.ts +2 -1
  479. package/src/modules/plugins/__tests__/join-requests.service.test.ts +28 -11
  480. package/src/modules/plugins/__tests__/join-requests.settlement.test.ts +371 -0
  481. package/src/modules/plugins/__tests__/plugin-creation-display-name.test.ts +4 -3
  482. package/src/modules/plugins/__tests__/plugin-index.service.test.ts +6 -4
  483. package/src/modules/plugins/__tests__/plugin-links.service.test.ts +220 -5
  484. package/src/modules/plugins/__tests__/plugin-provision.service.test.ts +3 -1
  485. package/src/modules/plugins/__tests__/plugin-rename.service.test.ts +7 -6
  486. package/src/modules/plugins/__tests__/plugins.routes.test.ts +12 -3
  487. package/src/modules/plugins/__tests__/teams.routes.test.ts +2 -1
  488. package/src/modules/plugins/compile/marketplace-compiler.service.ts +7 -9
  489. package/src/modules/plugins/discovery/__tests__/kb-plugin-source.test.ts +20 -16
  490. package/src/modules/plugins/discovery/bundle-dialect/bundle.source.ts +9 -2
  491. package/src/modules/plugins/discovery/kb-plugin-source.ts +15 -8
  492. package/src/modules/plugins/discovery/native.source.ts +4 -1
  493. package/src/modules/plugins/index.ts +1 -1
  494. package/src/modules/plugins/join-proposals.ts +87 -19
  495. package/src/modules/plugins/join-request-jobs.service.ts +8 -7
  496. package/src/modules/plugins/join-requests.service.ts +203 -43
  497. package/src/modules/plugins/plugin-links.service.ts +192 -19
  498. package/src/modules/plugins/plugin-links.ts +147 -27
  499. package/src/modules/plugins/plugin-provision.service.ts +54 -27
  500. package/src/modules/plugins/plugin-rename.service.ts +10 -10
  501. package/src/modules/plugins/plugins.routes.ts +48 -17
  502. package/src/modules/plugins/plugins.service.ts +7 -11
  503. package/src/modules/plugins/teams.routes.ts +16 -8
  504. package/src/modules/secrets-vault/__tests__/connect-pending.route.test.ts +7 -0
  505. package/src/modules/secrets-vault/__tests__/secrets-variable-loader.test.ts +40 -0
  506. package/src/modules/secrets-vault/__tests__/tool-owner-gate.route.test.ts +2 -0
  507. package/src/modules/secrets-vault/index.ts +2 -0
  508. package/src/modules/secrets-vault/secrets-variable-loader.ts +51 -21
  509. package/src/modules/secrets-vault/secrets-vault.routes.ts +7 -6
  510. package/src/modules/settings/__tests__/deployment-settings.service.test.ts +24 -11
  511. package/src/modules/settings/__tests__/git-root-folders.test.ts +2 -1
  512. package/src/modules/settings/__tests__/repository-source.test.ts +191 -0
  513. package/src/modules/settings/__tests__/setup.routes.boot-failure.test.ts +2 -1
  514. package/src/modules/settings/__tests__/setup.routes.git-mode.test.ts +353 -0
  515. package/src/modules/settings/__tests__/setup.routes.github-app.test.ts +282 -0
  516. package/src/modules/settings/__tests__/setup.routes.layout-phase.test.ts +7 -4
  517. package/src/modules/settings/__tests__/setup.routes.managed-phase.test.ts +233 -0
  518. package/src/modules/settings/__tests__/setup.routes.oidc.test.ts +2 -0
  519. package/src/modules/settings/__tests__/setup.routes.sync-status.test.ts +2 -0
  520. package/src/modules/settings/__tests__/setup.routes.test.ts +33 -52
  521. package/src/modules/settings/deployment-settings.service.ts +130 -23
  522. package/src/modules/settings/managed-repository.ts +68 -0
  523. package/src/modules/settings/repository-source.ts +197 -0
  524. package/src/modules/settings/setup.routes.ts +233 -19
  525. package/src/modules/skills/__tests__/allowed-tools-check.test.ts +11 -10
  526. package/src/modules/skills/__tests__/allowed-tools-warn.tools.test.ts +4 -3
  527. package/src/modules/skills/__tests__/pending-skills.service.test.ts +3 -1
  528. package/src/modules/skills/__tests__/skill-access-requests.routes.test.ts +7 -2
  529. package/src/modules/skills/__tests__/skills.routes.warnings.test.ts +2 -1
  530. package/src/modules/skills/__tests__/skills.service.test.ts +3 -2
  531. package/src/modules/skills/allowed-tools-check.ts +7 -6
  532. package/src/modules/skills/pending-skills.service.ts +9 -8
  533. package/src/modules/skills/skill-access-requests.routes.ts +29 -79
  534. package/src/modules/skills/skills.routes.ts +4 -3
  535. package/src/modules/skills/skills.service.ts +13 -9
  536. package/src/modules/tool-helpers/__tests__/agent-roles-write.test.ts +3 -2
  537. package/src/modules/tool-helpers/__tests__/phase4-tools.test.ts +3 -2
  538. package/src/modules/tool-helpers/tool-context.ts +15 -0
  539. package/src/modules/tool-manuals/__tests__/mcp-json-discovery.test.ts +17 -12
  540. package/src/modules/tool-manuals/__tests__/mcp-server-edit.service.test.ts +2 -1
  541. package/src/modules/tool-manuals/__tests__/pending-tools.service.test.ts +4 -1
  542. package/src/modules/tool-manuals/__tests__/tool-delete.service.test.ts +2 -1
  543. package/src/modules/tool-manuals/__tests__/tool-manuals.archive.route.test.ts +2 -1
  544. package/src/modules/tool-manuals/__tests__/tool-manuals.cli.test.ts +5 -4
  545. package/src/modules/tool-manuals/__tests__/tool-manuals.detail.route.test.ts +2 -1
  546. package/src/modules/tool-manuals/__tests__/tool-manuals.invalid.routes.test.ts +4 -2
  547. package/src/modules/tool-manuals/__tests__/tool-manuals.invalid.test.ts +13 -5
  548. package/src/modules/tool-manuals/__tests__/tool-manuals.mcp-oauth.test.ts +2 -1
  549. package/src/modules/tool-manuals/__tests__/tool-manuals.restart.test.ts +9 -1
  550. package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +3 -2
  551. package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +2 -0
  552. package/src/modules/tool-manuals/mcp-json-discovery.ts +6 -4
  553. package/src/modules/tool-manuals/mcp-server-edit.service.ts +13 -11
  554. package/src/modules/tool-manuals/pending-tools.service.ts +19 -16
  555. package/src/modules/tool-manuals/tool-delete.service.ts +13 -10
  556. package/src/modules/tool-manuals/tool-manuals.routes.ts +10 -8
  557. package/src/modules/tool-manuals/tool-manuals.service.ts +15 -13
  558. package/src/modules/tool-manuals/tool-manuals.tools.ts +7 -6
  559. package/src/modules/workflow/__tests__/apply-failure.test.ts +11 -2
  560. package/src/modules/workflow/__tests__/merge-announces-tree.test.ts +14 -26
  561. package/src/modules/workflow/__tests__/preserve-roles-yaml.test.ts +2 -1
  562. package/src/modules/workflow/__tests__/session-ontology.service.test.ts +3 -2
  563. package/src/modules/workflow/__tests__/workflow.routes.lock-path.test.ts +2 -1
  564. package/src/modules/workflow/__tests__/workflow.service.branch-in-use.test.ts +3 -10
  565. package/src/modules/workflow/__tests__/workflow.service.commitFileWhileLocked.test.ts +2 -1
  566. package/src/modules/workflow/__tests__/workflow.service.deleted-branch-sweep.test.ts +3 -10
  567. package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +187 -35
  568. package/src/modules/workflow/__tests__/workflow.service.folder-proposals.test.ts +2 -1
  569. package/src/modules/workflow/__tests__/workflow.service.platform-restore.test.ts +2 -1
  570. package/src/modules/workflow/__tests__/workflow.service.read-gate.test.ts +3 -2
  571. package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +2 -1
  572. package/src/modules/workflow/__tests__/workflow.service.sync.test.ts +5 -4
  573. package/src/modules/workflow/__tests__/workflow.service.update-from-target.test.ts +148 -41
  574. package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +143 -2
  575. package/src/modules/workflow/agent-tools/workflow.tools.ts +60 -12
  576. package/src/modules/workflow/git/__tests__/git.service.accessGating.test.ts +5 -4
  577. package/src/modules/workflow/git/__tests__/git.service.changedFilesForPr.test.ts +12 -11
  578. package/src/modules/workflow/git/__tests__/git.service.commitChanges.test.ts +9 -8
  579. package/src/modules/workflow/git/__tests__/git.service.commitFile.strayPath.test.ts +8 -7
  580. package/src/modules/workflow/git/__tests__/git.service.commitFile.test.ts +6 -5
  581. package/src/modules/workflow/git/__tests__/git.service.createBranch.test.ts +3 -2
  582. package/src/modules/workflow/git/__tests__/git.service.deleteBranch.test.ts +3 -2
  583. package/src/modules/workflow/git/__tests__/git.service.diffFileAtCommit.test.ts +7 -6
  584. package/src/modules/workflow/git/__tests__/git.service.diffFileBetweenBranches.test.ts +16 -15
  585. package/src/modules/workflow/git/__tests__/git.service.fileContentsAtCommit.test.ts +3 -2
  586. package/src/modules/workflow/git/__tests__/git.service.forkPoint.test.ts +2 -1
  587. package/src/modules/workflow/git/__tests__/git.service.history-guards.test.ts +2 -1
  588. package/src/modules/workflow/git/__tests__/git.service.list-branches.test.ts +10 -9
  589. package/src/modules/workflow/git/__tests__/git.service.listTrackedFiles.test.ts +2 -1
  590. package/src/modules/workflow/git/__tests__/git.service.logForFile.test.ts +6 -5
  591. package/src/modules/workflow/git/__tests__/git.service.mergeChangeRequest.test.ts +9 -8
  592. package/src/modules/workflow/git/__tests__/git.service.pendingChanges.test.ts +2 -1
  593. package/src/modules/workflow/git/__tests__/git.service.postMergePull.test.ts +4 -3
  594. package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +130 -8
  595. package/src/modules/workflow/git/__tests__/git.service.readFileAtRef.test.ts +2 -1
  596. package/src/modules/workflow/git/__tests__/git.service.revertPathsAndPush.test.ts +2 -1
  597. package/src/modules/workflow/git/__tests__/git.service.status.test.ts +4 -3
  598. package/src/modules/workflow/git/__tests__/git.service.syncFromRemote.test.ts +8 -7
  599. package/src/modules/workflow/git/__tests__/node-git-runner.test.ts +41 -3
  600. package/src/modules/workflow/git/__tests__/pull-request.service.getPrDetail.test.ts +145 -2
  601. package/src/modules/workflow/git/__tests__/pull-request.service.viewer-can-delete.test.ts +166 -0
  602. package/src/modules/workflow/git/git.service.ts +49 -17
  603. package/src/modules/workflow/git/node-git-runner.ts +43 -4
  604. package/src/modules/workflow/git/pull-request.service.ts +119 -0
  605. package/src/modules/workflow/review-workflow/review-workflow.service.ts +9 -6
  606. package/src/modules/workflow/session-ontology.service.ts +7 -2
  607. package/src/modules/workflow/workflow.routes.ts +3 -1
  608. package/src/modules/workflow/workflow.service.ts +201 -76
  609. package/src/modules/workspace/__tests__/file-stat-access.test.ts +3 -2
  610. package/src/modules/workspace/__tests__/git-internals.security.test.ts +10 -9
  611. package/src/modules/workspace/__tests__/session-ontology.gate.test.ts +4 -2
  612. package/src/modules/workspace/__tests__/workspace-paths-inside-the-repo.test.ts +3 -2
  613. package/src/modules/workspace/__tests__/workspace.routes.branch-errors.test.ts +2 -1
  614. package/src/modules/workspace/__tests__/workspace.routes.create-grant.test.ts +2 -1
  615. package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +2 -1
  616. package/src/modules/workspace/__tests__/workspace.routes.download-implies-read.test.ts +2 -1
  617. package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +2 -1
  618. package/src/modules/workspace/__tests__/workspace.routes.file-writes.test.ts +2 -1
  619. package/src/modules/workspace/__tests__/workspace.routes.folders.test.ts +5 -4
  620. package/src/modules/workspace/__tests__/workspace.routes.move-platform-files.test.ts +2 -1
  621. package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +2 -1
  622. package/src/modules/workspace/__tests__/workspace.service.ensure-remotes-fetched.test.ts +2 -2
  623. package/src/modules/workspace/__tests__/workspace.service.list-cloned.test.ts +6 -5
  624. package/src/modules/workspace/__tests__/workspace.service.move-never-overwrites.test.ts +2 -1
  625. package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +2 -1
  626. package/src/modules/workspace/__tests__/workspace.service.test.ts +84 -50
  627. package/src/modules/workspace/__tests__/workspace.service.unknown-branch.test.ts +45 -1
  628. package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +10 -7
  629. package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +237 -10
  630. package/src/modules/workspace/__tests__/workspace.tools.test.ts +44 -11
  631. package/src/modules/workspace/__tests__/write-denial.test.ts +5 -4
  632. package/src/modules/workspace/session-ontology.gate.ts +6 -4
  633. package/src/modules/workspace/startup/__tests__/kb-startup-runner.degraded.test.ts +6 -2
  634. package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +240 -21
  635. package/src/modules/workspace/startup/kb-git.ts +15 -22
  636. package/src/modules/workspace/startup/kb-startup-runner.ts +198 -45
  637. package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +104 -98
  638. package/src/modules/workspace/startup/steps/groups-to-plugins.step.ts +24 -16
  639. package/src/modules/workspace/startup/steps/personal-spaces.step.ts +14 -5
  640. package/src/modules/workspace/startup/steps/plugin-display-names.step.ts +13 -5
  641. package/src/modules/workspace/startup/steps/plugin-manifests.step.ts +14 -5
  642. package/src/modules/workspace/startup/steps/seed-tree.ts +11 -9
  643. package/src/modules/workspace/startup/steps/template-files.step.ts +43 -34
  644. package/src/modules/workspace/startup/steps/template-source.ts +8 -5
  645. package/src/modules/workspace/workspace.routes.ts +8 -7
  646. package/src/modules/workspace/workspace.service.ts +47 -28
  647. package/src/modules/workspace/workspace.tools.ts +56 -20
  648. package/src/modules/workspace/write-denial.ts +7 -5
  649. package/src/shared/__tests__/kb-layout.plugin.test.ts +19 -16
  650. package/src/shared/domain-errors.ts +58 -0
  651. package/src/shared/git.contract.ts +80 -8
  652. package/src/shared/kb-context.ts +130 -0
  653. package/src/shared/kb-layout.test.ts +37 -27
  654. package/src/shared/kb-layout.ts +4 -3
  655. package/src/shared/pending-proposals.ts +7 -4
  656. package/src/shared/redact-secret.ts +5 -5
  657. package/src/tenancy/__tests__/static-tenant-source.test.ts +177 -0
  658. package/src/tenancy/__tests__/tenant-host.test.ts +372 -0
  659. package/src/tenancy/__tests__/tenant-runtime.test.ts +221 -0
  660. package/src/tenancy/__tests__/tenant-secrets.test.ts +35 -0
  661. package/src/tenancy/index.ts +35 -0
  662. package/src/tenancy/static-tenant-source.ts +296 -0
  663. package/src/tenancy/tenant-host.ts +261 -0
  664. package/src/tenancy/tenant-runtime.ts +208 -0
  665. package/src/tenancy/tenant-secrets.ts +41 -0
  666. package/src/tenancy/tenant-source.contract.ts +59 -0
@@ -22,6 +22,7 @@
22
22
  */
23
23
 
24
24
  import { ontologyOf } from '../../shared/kb-layout.js';
25
+ import type { KbContext } from '../../shared/kb-context.js';
25
26
  import type { JsonSchema } from '../tool-registry/tool.contract.js';
26
27
  import { ToolError, type ToolContext } from '../tool-helpers/tool.contract.js';
27
28
  import type { ISessionOntologyService } from '../workflow/session-ontology.service.js';
@@ -75,7 +76,8 @@ export class MissingSessionError extends ToolError {
75
76
  export interface SessionOntologyGate {
76
77
  service: ISessionOntologyService;
77
78
  enabled: boolean;
78
- kbDirName: string;
79
+ /** The checkout folder and the layout a path is classified under. */
80
+ kb: Pick<KbContext, 'kbDirName' | 'layout'>;
79
81
  /** Lowercased email of the recovery/merge bot, which is exempt. */
80
82
  recoveryBotEmail: string;
81
83
  /**
@@ -103,7 +105,7 @@ function isAgentSource(ctx: ToolContext): boolean {
103
105
  function resolveGatedSession(gate: SessionOntologyGate, ctx: ToolContext, wsPath: string): string | 'skip' {
104
106
  if (!gate.enabled) return 'skip';
105
107
  // Neutral paths never pin/record/block — skip before any identity work.
106
- if (ontologyOf(wsPath, gate.kbDirName) === null) return 'skip';
108
+ if (ontologyOf(wsPath, gate.kb.layout, gate.kb.kbDirName) === null) return 'skip';
107
109
  // Humans (UI routes) and browser-JWT callers never hit these tools; only
108
110
  // agent tool calls are gated.
109
111
  if (!isAgentSource(ctx)) return 'skip';
@@ -125,7 +127,7 @@ export async function recordOntologyRead(gate: SessionOntologyGate, ctx: ToolCon
125
127
  const sessionId = resolveGatedSession(gate, ctx, wsPath);
126
128
  if (sessionId === 'skip') return;
127
129
  // checkOperation(isWrite=false) records the touch and always allows.
128
- await gate.service.checkOperation(sessionId, wsPath, false, gate.kbDirName);
130
+ await gate.service.checkOperation(sessionId, wsPath, false, gate.kb.kbDirName);
129
131
  }
130
132
 
131
133
  /**
@@ -155,7 +157,7 @@ export async function assertOntologyWriteAllowed(
155
157
  // Tracking stays core: record the (now-allowed) write's ontology touch.
156
158
  // A blocked write never reaches this line, so it records nothing — same as
157
159
  // before the hook split.
158
- await gate.service.checkOperation(sessionId, wsPath, false, gate.kbDirName);
160
+ await gate.service.checkOperation(sessionId, wsPath, false, gate.kb.kbDirName);
159
161
  }
160
162
 
161
163
  /**
@@ -6,7 +6,7 @@ import os from 'node:os';
6
6
  import path from 'node:path';
7
7
  import { KbRemoteUnreachableError, KbStartupRunner } from '../kb-startup-runner.js';
8
8
  import { NodeGitRunner } from '../../../workflow/git/node-git-runner.js';
9
- import { GitRunError, type IGitRunner } from '../../../../shared/git.contract.js';
9
+ import { GitRunError, NO_GIT_CREDENTIALS, type IGitRunner } from '../../../../shared/git.contract.js';
10
10
  import type { OnServerStart, ServerStartContext, StepResult } from '../on-server-start.js';
11
11
 
12
12
  /**
@@ -69,7 +69,6 @@ function makeRunner(steps: OnServerStart[], url: () => string, gitRunner: IGitRu
69
69
  return new KbStartupRunner({
70
70
  gitRunner,
71
71
  kbRepoUrl: url,
72
- gitUsername: () => 'x-access-token',
73
72
  workspacesRoot,
74
73
  kbDirName: 'knowledge-base',
75
74
  templateDir: path.join(root, 'template'),
@@ -101,6 +100,7 @@ describe('KbStartupRunner with an unreachable remote', () => {
101
100
  it('a git that never ran is not "unreachable" either: that failure is this host, and it stops the boot', async () => {
102
101
  const noGit: IGitRunner = {
103
102
  defaultTimeoutMs: 1000,
103
+ credentials: NO_GIT_CREDENTIALS,
104
104
  run: (async () => {
105
105
  throw new GitRunError('git ls-remote failed: spawn git ENOENT');
106
106
  }) as IGitRunner['run'],
@@ -251,6 +251,7 @@ describe('KbStartupRunner with a remote that rejects the credentials', () => {
251
251
  // re-dial a host that will never accept the token.
252
252
  const rejecting: IGitRunner = {
253
253
  defaultTimeoutMs: 1000,
254
+ credentials: NO_GIT_CREDENTIALS,
254
255
  run: (async () => {
255
256
  // The shape `NodeGitRunner` throws: git's words in the message (that
256
257
  // is what the boot classifies) and again in `stderr`.
@@ -275,6 +276,7 @@ describe('KbStartupRunner retry after a boot that survived a rejected token', ()
275
276
  let dials = 0;
276
277
  const rejecting: IGitRunner = {
277
278
  defaultTimeoutMs: 1000,
279
+ credentials: NO_GIT_CREDENTIALS,
278
280
  run: (async () => {
279
281
  dials += 1;
280
282
  const said = "fatal: Authentication failed for 'https://example.com/acme/kb.git/'";
@@ -319,6 +321,7 @@ describe('KbStartupRunner retry when the token is rejected while it sleeps', ()
319
321
  let dials = 0;
320
322
  const rejecting: IGitRunner = {
321
323
  defaultTimeoutMs: 1000,
324
+ credentials: NO_GIT_CREDENTIALS,
322
325
  run: (async () => {
323
326
  dials += 1;
324
327
  const said = "fatal: Authentication failed for 'https://example.com/acme/kb.git/'";
@@ -331,6 +334,7 @@ describe('KbStartupRunner retry when the token is rejected while it sleeps', ()
331
334
  let current: IGitRunner = new NodeGitRunner();
332
335
  const switching: IGitRunner = {
333
336
  defaultTimeoutMs: 1000,
337
+ credentials: NO_GIT_CREDENTIALS,
334
338
  run: ((...args: Parameters<IGitRunner['run']>) => current.run(...args)) as IGitRunner['run'],
335
339
  };
336
340
  let url = path.join(root, 'nowhere.git');
@@ -1,4 +1,5 @@
1
1
  import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
+ import { testKbContext } from '../../../../__tests__/kb-context.js';
2
3
  import { NodeFs } from '../../../kb-fs/node-fs.js';
3
4
  import { execFile } from 'node:child_process';
4
5
  import { promisify } from 'node:util';
@@ -9,8 +10,18 @@ import { KbStartupRunner } from '../kb-startup-runner.js';
9
10
  import { WorkspaceService } from '../../workspace.service.js';
10
11
  import { NodeGitRunner } from '../../../workflow/git/node-git-runner.js';
11
12
  import { ClassifiedFailure, classifyGitFailure, failureOf } from '../../../../shared/git-failure.js';
13
+ import { gitCredentials } from '../../../../shared/git.contract.js';
12
14
  import type { OnServerStart, ServerStartContext, StepResult } from '../on-server-start.js';
13
15
 
16
+ /**
17
+ * The token in effect for the runners these suites build, changed by the
18
+ * cases that need one — the way the setup screen changes it on a running
19
+ * deployment: through the provider the runner reads on every call, never
20
+ * through this process's environment.
21
+ */
22
+ let token: string | null = null;
23
+ const credentials = gitCredentials('x-access-token', () => token);
24
+
14
25
  const execFileAsync = promisify(execFile);
15
26
 
16
27
  const PROTECTED = ['current-company-state', 'target-company-state'];
@@ -65,10 +76,10 @@ function makeRunner(steps: OnServerStart[], overrides: Partial<Parameters<typeof
65
76
 
66
77
  function runnerOpts(steps: OnServerStart[], overrides: Record<string, unknown> = {}) {
67
78
  return {
68
- gitRunner: new NodeGitRunner(),
79
+ gitRunner: new NodeGitRunner(undefined, credentials),
69
80
  kbRepoUrl: () => upstream,
70
- gitUsername: () => 'x-access-token',
71
81
  workspacesRoot,
82
+ setAsideRoot: path.join(root, 'set-aside'),
72
83
  kbDirName: 'knowledge-base',
73
84
  templateDir: path.join(root, 'template'),
74
85
  defaultBranch: () => DEFAULT_BRANCH,
@@ -93,6 +104,216 @@ async function checkout(branch: string): Promise<string> {
93
104
  return dir;
94
105
  }
95
106
 
107
+ /**
108
+ * The configured repository was replaced while working copies of the old one
109
+ * were still on disk. A clone fetches through its OWN stored address, so
110
+ * every one of them kept asking the repository that was gone: the boot
111
+ * stopped on "repository not found" and took the setup screen with it.
112
+ */
113
+ describe('KbStartupRunner — the repository was replaced', () => {
114
+ const touchDefault = step('touch', async (ctx) => {
115
+ await (await ctx.defaultBranch()).repoDir();
116
+ return { outcome: 'ok' };
117
+ });
118
+ const cloneDir = (branch: string) => path.join(workspacesRoot, encodeURIComponent(branch), 'knowledge-base');
119
+
120
+ /** A second, unrelated repository with the same branch names. */
121
+ async function replacementUpstream(): Promise<string> {
122
+ const other = path.join(root, 'replacement.git');
123
+ await git(root, ['init', '--bare', '-b', DEFAULT_BRANCH, other]);
124
+ const seed = path.join(root, '.seed-replacement');
125
+ await fs.mkdir(seed);
126
+ await git(seed, ['init', '-b', DEFAULT_BRANCH]);
127
+ await fs.writeFile(path.join(seed, 'marker.txt'), 'replacement', 'utf8');
128
+ await git(seed, ['add', '-A']);
129
+ await git(seed, ['commit', '-m', 'init']);
130
+ await git(seed, ['branch', PROTECTED[1]!]);
131
+ await git(seed, ['remote', 'add', 'origin', other]);
132
+ await git(seed, ['push', 'origin', ...PROTECTED]);
133
+ return other;
134
+ }
135
+
136
+ /** Boot once against the first repository, and leave a draft's clone beside it. */
137
+ async function bootedOnTheOldRepository(): Promise<void> {
138
+ await populatedUpstream();
139
+ await makeRunner([touchDefault]).runAll();
140
+ await fs.mkdir(path.dirname(cloneDir('someone/draft')), { recursive: true });
141
+ await git(root, ['clone', '-b', DEFAULT_BRANCH, upstream, cloneDir('someone/draft')]);
142
+ }
143
+
144
+ /** Where one run set its working copies aside: the single dated folder under the root. */
145
+ async function setAside(): Promise<string> {
146
+ const runs = await fs.readdir(path.join(root, 'set-aside'));
147
+ expect(runs).toHaveLength(1);
148
+ return path.join(root, 'set-aside', runs[0]!);
149
+ }
150
+
151
+ it('clones the new repository in place of the old one\'s clones, even with the old one gone', async () => {
152
+ await bootedOnTheOldRepository();
153
+ const replacement = await replacementUpstream();
154
+ // Gone, as it was in production: any fetch through the old address fails.
155
+ await fs.rm(upstream, { recursive: true, force: true });
156
+
157
+ await makeRunner([touchDefault], { kbRepoUrl: () => replacement }).runAll();
158
+
159
+ const repo = cloneDir(DEFAULT_BRANCH);
160
+ expect((await git(repo, ['config', '--get', 'remote.origin.url'])).trim()).toBe(replacement);
161
+ expect(await fs.readFile(path.join(repo, 'marker.txt'), 'utf8')).toBe('replacement');
162
+ // A clone this boot had no reason to touch leaves the workspaces root
163
+ // too: the workspace service would otherwise adopt it and fetch from the
164
+ // old address.
165
+ await expect(fs.access(cloneDir('someone/draft'))).rejects.toThrow();
166
+ });
167
+
168
+ /**
169
+ * The old repository is GONE, so its clones are the last copy of what it
170
+ * held, and the commit nobody pushed exists nowhere else at all. They
171
+ * leave the workspaces root and nothing else happens to them.
172
+ */
173
+ it('sets the old repository\'s clones aside whole, unpushed work included, and deletes nothing', async () => {
174
+ await bootedOnTheOldRepository();
175
+ const old = cloneDir(DEFAULT_BRANCH);
176
+ await fs.writeFile(path.join(old, 'unpushed.md'), 'the only copy', 'utf8');
177
+ await git(old, ['add', '-A']);
178
+ await git(old, ['commit', '-m', 'never pushed']);
179
+ const head = (await git(old, ['rev-parse', 'HEAD'])).trim();
180
+ const replacement = await replacementUpstream();
181
+ await fs.rm(upstream, { recursive: true, force: true });
182
+
183
+ await makeRunner([touchDefault], { kbRepoUrl: () => replacement }).runAll();
184
+
185
+ const kept = await setAside();
186
+ const keptDefault = path.join(kept, encodeURIComponent(DEFAULT_BRANCH));
187
+ expect((await git(keptDefault, ['rev-parse', 'HEAD'])).trim()).toBe(head);
188
+ expect(await fs.readFile(path.join(keptDefault, 'unpushed.md'), 'utf8')).toBe('the only copy');
189
+ expect(await fs.readFile(path.join(keptDefault, 'marker.txt'), 'utf8')).toBe('seeded');
190
+ // The draft's clone too, under its own workspace's name.
191
+ await expect(fs.access(path.join(kept, encodeURIComponent('someone/draft'), '.git'))).resolves.toBeUndefined();
192
+ // And the probe that compared the histories left no refs behind in it.
193
+ expect((await git(keptDefault, ['for-each-ref', 'refs/hexis-probe/'])).trim()).toBe('');
194
+ });
195
+
196
+ /**
197
+ * The shipped compose files mount the backups root as a volume of its own,
198
+ * where a rename across to it is refused. That is the path production
199
+ * takes: a copy, and the original removed only once the copy is whole.
200
+ */
201
+ it('sets a clone aside across volumes, by copying it whole', async () => {
202
+ await bootedOnTheOldRepository();
203
+ const old = cloneDir(DEFAULT_BRANCH);
204
+ await fs.writeFile(path.join(old, 'unpushed.md'), 'the only copy', 'utf8');
205
+ await git(old, ['add', '-A']);
206
+ await git(old, ['commit', '-m', 'never pushed']);
207
+ const head = (await git(old, ['rev-parse', 'HEAD'])).trim();
208
+ const replacement = await replacementUpstream();
209
+ await fs.rm(upstream, { recursive: true, force: true });
210
+ const crossDevice = Object.assign(new Error('EXDEV: cross-device link not permitted'), { code: 'EXDEV' });
211
+ const rename = vi.spyOn(fs, 'rename').mockRejectedValue(crossDevice);
212
+ try {
213
+ await makeRunner([touchDefault], { kbRepoUrl: () => replacement }).runAll();
214
+ } finally {
215
+ rename.mockRestore();
216
+ }
217
+
218
+ const keptDefault = path.join(await setAside(), encodeURIComponent(DEFAULT_BRANCH));
219
+ expect((await git(keptDefault, ['rev-parse', 'HEAD'])).trim()).toBe(head);
220
+ expect(await fs.readFile(path.join(keptDefault, 'unpushed.md'), 'utf8')).toBe('the only copy');
221
+ expect(await fs.readFile(path.join(cloneDir(DEFAULT_BRANCH), 'marker.txt'), 'utf8')).toBe('replacement');
222
+ });
223
+
224
+ /**
225
+ * A clone that cannot be set aside stays exactly where it is, and the boot
226
+ * stops saying why: deleting it to get past would be the one outcome this
227
+ * whole path exists to rule out.
228
+ */
229
+ it('deletes nothing when a clone cannot be set aside, and says why', async () => {
230
+ await bootedOnTheOldRepository();
231
+ const old = cloneDir(DEFAULT_BRANCH);
232
+ const head = (await git(old, ['rev-parse', 'HEAD'])).trim();
233
+ const replacement = await replacementUpstream();
234
+ await fs.rm(upstream, { recursive: true, force: true });
235
+ const rename = vi.spyOn(fs, 'rename').mockRejectedValue(Object.assign(new Error('EXDEV'), { code: 'EXDEV' }));
236
+ const cp = vi.spyOn(fs, 'cp').mockRejectedValue(Object.assign(new Error('ENOSPC: no space left on device'), { code: 'ENOSPC' }));
237
+ try {
238
+ await expect(makeRunner([touchDefault], { kbRepoUrl: () => replacement }).runAll()).rejects.toThrow(
239
+ /Could not set aside the working copy.*no space left.*Nothing was deleted/s,
240
+ );
241
+ } finally {
242
+ rename.mockRestore();
243
+ cp.mockRestore();
244
+ }
245
+ expect((await git(old, ['rev-parse', 'HEAD'])).trim()).toBe(head);
246
+ });
247
+
248
+ /**
249
+ * The one change the setup screen tells an admin to make: the same
250
+ * repository, moved. The clone is pointed at the new address and kept, and
251
+ * the commit that was never pushed goes on to be pushed there.
252
+ */
253
+ it('keeps a clone of the same repository at a new address, and points it there', async () => {
254
+ await bootedOnTheOldRepository();
255
+ const repo = cloneDir(DEFAULT_BRANCH);
256
+ await fs.writeFile(path.join(repo, 'unpushed.md'), 'local work', 'utf8');
257
+ await git(repo, ['add', '-A']);
258
+ await git(repo, ['commit', '-m', 'local work']);
259
+ const head = (await git(repo, ['rev-parse', 'HEAD'])).trim();
260
+ // Moved: everything the old address held is at the new one, and the old
261
+ // one answers nothing any more.
262
+ const moved = path.join(root, 'moved.git');
263
+ await git(root, ['clone', '--bare', upstream, moved]);
264
+ await fs.rm(upstream, { recursive: true, force: true });
265
+
266
+ await makeRunner([touchDefault], { kbRepoUrl: () => moved }).runAll();
267
+
268
+ expect((await git(repo, ['config', '--get', 'remote.origin.url'])).trim()).toBe(moved);
269
+ expect((await git(repo, ['rev-parse', 'HEAD'])).trim()).toBe(head);
270
+ expect((await git(cloneDir('someone/draft'), ['config', '--get', 'remote.origin.url'])).trim()).toBe(moved);
271
+ expect((await git(repo, ['for-each-ref', 'refs/hexis-probe/'])).trim()).toBe('');
272
+ // Nothing was another repository's, so nothing was set aside.
273
+ await expect(fs.access(path.join(root, 'set-aside'))).rejects.toThrow();
274
+ });
275
+
276
+ it('leaves a clone of the configured repository alone, unpushed work included', async () => {
277
+ await bootedOnTheOldRepository();
278
+ const repo = cloneDir(DEFAULT_BRANCH);
279
+ await fs.writeFile(path.join(repo, 'unpushed.md'), 'local work', 'utf8');
280
+ await git(repo, ['add', '-A']);
281
+ await git(repo, ['commit', '-m', 'local work']);
282
+ const head = (await git(repo, ['rev-parse', 'HEAD'])).trim();
283
+
284
+ await makeRunner([touchDefault]).runAll();
285
+
286
+ expect((await git(repo, ['rev-parse', 'HEAD'])).trim()).toBe(head);
287
+ await expect(fs.access(cloneDir('someone/draft'))).resolves.toBeUndefined();
288
+ });
289
+
290
+ it('does not take a different spelling of the same address for another repository', async () => {
291
+ await bootedOnTheOldRepository();
292
+ const repo = cloneDir(DEFAULT_BRANCH);
293
+ await fs.writeFile(path.join(repo, 'unpushed.md'), 'local work', 'utf8');
294
+ await git(repo, ['add', '-A']);
295
+ await git(repo, ['commit', '-m', 'local work']);
296
+ const head = (await git(repo, ['rev-parse', 'HEAD'])).trim();
297
+
298
+ // `upstream` ends in `.git`; the same repository without it, and with a
299
+ // trailing slash.
300
+ await makeRunner([touchDefault], { kbRepoUrl: () => `${upstream.replace(/\.git$/, '')}/` }).runAll().catch(() => {});
301
+
302
+ expect((await git(repo, ['rev-parse', 'HEAD'])).trim()).toBe(head);
303
+ });
304
+
305
+ it('keeps every clone when the configured repository cannot be reached', async () => {
306
+ // A typo in the address must not cost the working copies: the sweep runs
307
+ // only once the configured remote has answered.
308
+ await bootedOnTheOldRepository();
309
+ await expect(
310
+ makeRunner([touchDefault], { kbRepoUrl: () => path.join(root, 'no-such-repository.git') }).runAll(),
311
+ ).rejects.toThrow();
312
+ await expect(fs.access(path.join(cloneDir(DEFAULT_BRANCH), '.git'))).resolves.toBeUndefined();
313
+ await expect(fs.access(cloneDir('someone/draft'))).resolves.toBeUndefined();
314
+ });
315
+ });
316
+
96
317
  describe('KbStartupRunner', () => {
97
318
  it('seeds an empty remote with every protected branch before any step runs', async () => {
98
319
  const seen: string[] = [];
@@ -486,7 +707,7 @@ describe('KbStartupRunner — what a failed phase throws', () => {
486
707
  try {
487
708
  const err = await makeRunner([step('noop', async () => ({ outcome: 'ok' }))], {
488
709
  kbRepoUrl: () => 'https://127.0.0.1:1/kb.git?X-Amz-Signature=SECRETSIG',
489
- gitToken: () => 'access',
710
+ gitRunner: new NodeGitRunner(undefined, gitCredentials('x-access-token', 'access')),
490
711
  })
491
712
  .runAll()
492
713
  .then(
@@ -518,7 +739,7 @@ describe('KbStartupRunner redaction', () => {
518
739
  throw new Error('the host said ghp_settingsonly42 is not welcome');
519
740
  }),
520
741
  ],
521
- { gitToken: () => 'ghp_settingsonly42' },
742
+ { gitRunner: new NodeGitRunner(undefined, gitCredentials('x-access-token', 'ghp_settingsonly42')) },
522
743
  );
523
744
  const err = await runner.runAll().then(
524
745
  () => null,
@@ -540,10 +761,8 @@ describe('KbStartupRunner credentials', () => {
540
761
  // the repo with nothing, so every later push prompts for a username, finds
541
762
  // no tty, and dies — commits pile up locally and reach the remote never.
542
763
  // Only real git tells the two spellings apart, so this drives real git.
543
- const ORIGINAL = process.env.GITHUB_TOKEN;
544
764
  afterEach(() => {
545
- if (ORIGINAL === undefined) delete process.env.GITHUB_TOKEN;
546
- else process.env.GITHUB_TOKEN = ORIGINAL;
765
+ token = null;
547
766
  });
548
767
 
549
768
 
@@ -561,7 +780,7 @@ describe('KbStartupRunner credentials', () => {
561
780
  }
562
781
 
563
782
  it('leaves the boot clone able to authenticate a push of its own', async () => {
564
- process.env.GITHUB_TOKEN = 'ghp_boot';
783
+ token = 'ghp_boot';
565
784
  await populatedUpstream();
566
785
  // The branch handle clones lazily, so a step has to actually reach for the
567
786
  // repo before there is anything on disk to inspect.
@@ -585,7 +804,7 @@ describe('KbStartupRunner credentials', () => {
585
804
  // path (`--replace-all`), so drift a second value in out of band and let
586
805
  // WorkspaceService adopt the clone — that is the code the guarantee is
587
806
  // about.
588
- process.env.GITHUB_TOKEN = 'ghp_boot';
807
+ token = 'ghp_boot';
589
808
  await populatedUpstream();
590
809
  const repo = await materializeDefaultBranchClone();
591
810
  // App-shaped drift: a second stamp of OURS with a stale username — the
@@ -594,7 +813,7 @@ describe('KbStartupRunner credentials', () => {
594
813
  await git(repo, ['config', '--add', 'credential.helper',
595
814
  '!f() { echo "username=stale-user"; echo "password=$GITHUB_TOKEN"; }; f']);
596
815
 
597
- const ws = new WorkspaceService(workspacesRoot, upstream, 'knowledge-base', new NodeFs(), () => 'x-access-token');
816
+ const ws = new WorkspaceService(workspacesRoot, upstream, testKbContext(), new NodeFs(), new NodeGitRunner(undefined, credentials));
598
817
  await ws.getOrCreateForBranch(DEFAULT_BRANCH);
599
818
 
600
819
  const all = (await git(repo, ['config', '--local', '--get-all', 'credential.helper'])).trim();
@@ -607,19 +826,19 @@ describe('KbStartupRunner credentials', () => {
607
826
  // git chains every configured helper, so an operator's clone-local
608
827
  // `cache`/`store`/custom helper coexists with ours — and losing it on a
609
828
  // token change would break the very fallback auth they set up.
610
- process.env.GITHUB_TOKEN = 'ghp_boot';
829
+ token = 'ghp_boot';
611
830
  await populatedUpstream();
612
831
  const repo = await materializeDefaultBranchClone();
613
832
  await git(repo, ['config', '--add', 'credential.helper', 'cache --timeout=300']);
614
833
 
615
- const ws = new WorkspaceService(workspacesRoot, upstream, 'knowledge-base', new NodeFs(), () => 'x-access-token');
834
+ const ws = new WorkspaceService(workspacesRoot, upstream, testKbContext(), new NodeFs(), new NodeGitRunner(undefined, credentials));
616
835
  await ws.getOrCreateForBranch(DEFAULT_BRANCH); // stamp with token
617
836
  let all = (await git(repo, ['config', '--local', '--get-all', 'credential.helper'])).trim();
618
837
  expect(all).toContain('cache --timeout=300');
619
838
  expect(all).toContain('password=$GITHUB_TOKEN');
620
839
 
621
- delete process.env.GITHUB_TOKEN;
622
- const ws2 = new WorkspaceService(workspacesRoot, upstream, 'knowledge-base', new NodeFs(), () => 'x-access-token');
840
+ token = null;
841
+ const ws2 =new WorkspaceService(workspacesRoot, upstream, testKbContext(), new NodeFs(), new NodeGitRunner(undefined, credentials));
623
842
  await ws2.getOrCreateForBranch(DEFAULT_BRANCH); // unset OUR helper only
624
843
  all = (await git(repo, ['config', '--local', '--get-all', 'credential.helper'])).trim();
625
844
  expect(all).toContain('cache --timeout=300');
@@ -630,12 +849,12 @@ describe('KbStartupRunner credentials', () => {
630
849
  // A deployment that lost its token must not keep a clone-local helper
631
850
  // answering with an empty password — it would shadow whatever fallback
632
851
  // auth the operator switched to.
633
- process.env.GITHUB_TOKEN = 'ghp_boot';
852
+ token = 'ghp_boot';
634
853
  await populatedUpstream();
635
854
  const repo = await materializeDefaultBranchClone(); // stamped
636
- delete process.env.GITHUB_TOKEN;
855
+ token = null;
637
856
 
638
- const ws = new WorkspaceService(workspacesRoot, upstream, 'knowledge-base', new NodeFs(), () => 'x-access-token');
857
+ const ws = new WorkspaceService(workspacesRoot, upstream, testKbContext(), new NodeFs(), new NodeGitRunner(undefined, credentials));
639
858
  await ws.getOrCreateForBranch(DEFAULT_BRANCH);
640
859
 
641
860
  await expect(git(repo, ['config', '--local', '--get', 'credential.helper']))
@@ -646,13 +865,13 @@ describe('KbStartupRunner credentials', () => {
646
865
  // The rotation gap: the setup screen can supply a token AFTER a branch
647
866
  // was first opened, and the cached fast path returns before the adoption
648
867
  // re-stamp. The fingerprint check must catch the change there.
649
- delete process.env.GITHUB_TOKEN;
868
+ token = null;
650
869
  await populatedUpstream();
651
870
  const repo = await materializeDefaultBranchClone(); // no helper
652
871
 
653
- const ws = new WorkspaceService(workspacesRoot, upstream, 'knowledge-base', new NodeFs(), () => 'x-access-token');
872
+ const ws = new WorkspaceService(workspacesRoot, upstream, testKbContext(), new NodeFs(), new NodeGitRunner(undefined, credentials));
654
873
  await ws.getOrCreateForBranch(DEFAULT_BRANCH); // adopt, tokenless
655
- process.env.GITHUB_TOKEN = 'ghp_late';
874
+ token = 'ghp_late';
656
875
  await ws.getOrCreateForBranch(DEFAULT_BRANCH); // cached fast path
657
876
 
658
877
  const helper = (await git(repo, ['config', '--local', '--get', 'credential.helper'])).trim();
@@ -661,7 +880,7 @@ describe('KbStartupRunner credentials', () => {
661
880
  });
662
881
 
663
882
  it('clones without a helper when the deployment has no token — an open remote still boots', async () => {
664
- delete process.env.GITHUB_TOKEN;
883
+ token = null;
665
884
  await populatedUpstream();
666
885
  const repo = await materializeDefaultBranchClone();
667
886
  // `--get` exits 1 when the key is unset. Assert on that exit code rather
@@ -29,12 +29,13 @@ const STARTUP_GIT_TIMEOUT_MS = 600_000;
29
29
 
30
30
  /**
31
31
  * Per-invocation `-c` config. Long paths always (Windows checkouts of deep
32
- * KB trees); when a token is present, an inline credential helper that reads
33
- * it from the environment at call time — the secret never appears in argv.
32
+ * KB trees); when the runner carries a token, an inline credential helper
33
+ * that reads it from the child's environment at call time — the secret never
34
+ * appears in argv.
34
35
  */
35
- function credArgs(gitUsername: string): string[] {
36
+ function credArgs(runner: IGitRunner): string[] {
36
37
  const args = ['-c', 'core.longpaths=true'];
37
- const helper = credentialHelperValue(gitUsername);
38
+ const helper = credentialHelperValue(runner.credentials);
38
39
  if (helper) args.push('-c', `credential.helper=${helper}`);
39
40
  return args;
40
41
  }
@@ -49,18 +50,14 @@ function credArgs(gitUsername: string): string[] {
49
50
  * clone to carry its own credentials. Persist them with `clone --config` (which
50
51
  * only means "write into the new repo" after the subcommand) so it does.
51
52
  */
52
- function withPersistedCloneConfig(gitUsername: string, args: string[]): string[] {
53
+ function withPersistedCloneConfig(runner: IGitRunner, args: string[]): string[] {
53
54
  if (args[0] !== 'clone') return args;
54
- return [args[0], ...cloneCredentialArgs(gitUsername), ...args.slice(1)];
55
+ return [args[0], ...cloneCredentialArgs(runner.credentials), ...args.slice(1)];
55
56
  }
56
57
 
57
- export async function git(
58
- runner: IGitRunner,
59
- cwd: string,
60
- gitUsername: string,
61
- args: string[],
62
- ): Promise<string> {
63
- const argv = [...credArgs(gitUsername), ...withPersistedCloneConfig(gitUsername, args)];
58
+ /** Run one git command of the phase, authenticated with the runner's own credentials. */
59
+ export async function git(runner: IGitRunner, cwd: string, args: string[]): Promise<string> {
60
+ const argv = [...credArgs(runner), ...withPersistedCloneConfig(runner, args)];
64
61
  try {
65
62
  // A floor under the configured ceiling, not a replacement for it: an
66
63
  // operator who raised GIT_TIMEOUT_MS past ten minutes gets that here too.
@@ -83,18 +80,14 @@ export async function git(
83
80
  }
84
81
  }
85
82
 
86
- export async function stampIdentity(runner: IGitRunner, repo: string, gitUsername: string): Promise<void> {
87
- await git(runner, repo, gitUsername, ['config', 'user.name', BOT_NAME]);
88
- await git(runner, repo, gitUsername, ['config', 'user.email', BOT_EMAIL]);
83
+ export async function stampIdentity(runner: IGitRunner, repo: string): Promise<void> {
84
+ await git(runner, repo, ['config', 'user.name', BOT_NAME]);
85
+ await git(runner, repo, ['config', 'user.email', BOT_EMAIL]);
89
86
  }
90
87
 
91
88
  /** Branch names present on the remote, from `ls-remote --heads`. */
92
- export async function lsRemoteHeads(
93
- runner: IGitRunner,
94
- repoUrl: string,
95
- gitUsername: string,
96
- ): Promise<Set<string>> {
97
- const out = await git(runner, os.tmpdir(), gitUsername, ['ls-remote', '--heads', repoUrl]);
89
+ export async function lsRemoteHeads(runner: IGitRunner, repoUrl: string): Promise<Set<string>> {
90
+ const out = await git(runner, os.tmpdir(), ['ls-remote', '--heads', repoUrl]);
98
91
  const heads = new Set<string>();
99
92
  for (const line of out.split('\n')) {
100
93
  const m = /\srefs\/heads\/(.+)$/.exec(line.trim());