@bevel-software/platform-core-backend 0.21.0 → 0.23.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 (434) hide show
  1. package/dist/core/core-ports.d.ts +11 -1
  2. package/dist/core/core-ports.d.ts.map +1 -1
  3. package/dist/core/core-ports.js.map +1 -1
  4. package/dist/core/create-core-server.d.ts +3 -3
  5. package/dist/core/create-core-server.d.ts.map +1 -1
  6. package/dist/core/create-core-server.js +62 -13
  7. package/dist/core/create-core-server.js.map +1 -1
  8. package/dist/core/create-core-services.d.ts +22 -3
  9. package/dist/core/create-core-services.d.ts.map +1 -1
  10. package/dist/core/create-core-services.js +158 -23
  11. package/dist/core/create-core-services.js.map +1 -1
  12. package/dist/core/lifecycle.d.ts +34 -1
  13. package/dist/core/lifecycle.d.ts.map +1 -1
  14. package/dist/core/lifecycle.js +89 -13
  15. package/dist/core/lifecycle.js.map +1 -1
  16. package/dist/core-config.d.ts +0 -12
  17. package/dist/core-config.d.ts.map +1 -1
  18. package/dist/core-config.js +11 -13
  19. package/dist/core-config.js.map +1 -1
  20. package/dist/index.d.ts +3 -2
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +2 -1
  23. package/dist/index.js.map +1 -1
  24. package/dist/modules/access/access-control.interface.d.ts +42 -12
  25. package/dist/modules/access/access-control.interface.d.ts.map +1 -1
  26. package/dist/modules/access/access-control.service.d.ts +67 -10
  27. package/dist/modules/access/access-control.service.d.ts.map +1 -1
  28. package/dist/modules/access/access-control.service.js +214 -35
  29. package/dist/modules/access/access-control.service.js.map +1 -1
  30. package/dist/modules/access/access-requests.contract.d.ts +75 -0
  31. package/dist/modules/access/access-requests.contract.d.ts.map +1 -0
  32. package/dist/modules/access/access-requests.contract.js +20 -0
  33. package/dist/modules/access/access-requests.contract.js.map +1 -0
  34. package/dist/modules/access/access-requests.routes.d.ts +35 -0
  35. package/dist/modules/access/access-requests.routes.d.ts.map +1 -0
  36. package/dist/modules/access/access-requests.routes.js +237 -0
  37. package/dist/modules/access/access-requests.routes.js.map +1 -0
  38. package/dist/modules/access/access-requests.service.d.ts +123 -0
  39. package/dist/modules/access/access-requests.service.d.ts.map +1 -0
  40. package/dist/modules/access/access-requests.service.js +337 -0
  41. package/dist/modules/access/access-requests.service.js.map +1 -0
  42. package/dist/modules/access/access.routes.d.ts.map +1 -1
  43. package/dist/modules/access/access.routes.js +13 -15
  44. package/dist/modules/access/access.routes.js.map +1 -1
  45. package/dist/modules/access-model/access-grammar.d.ts +12 -0
  46. package/dist/modules/access-model/access-grammar.d.ts.map +1 -1
  47. package/dist/modules/access-model/access-grammar.js +24 -0
  48. package/dist/modules/access-model/access-grammar.js.map +1 -1
  49. package/dist/modules/auth/account-admission.d.ts +58 -7
  50. package/dist/modules/auth/account-admission.d.ts.map +1 -1
  51. package/dist/modules/auth/account-admission.js +44 -1
  52. package/dist/modules/auth/account-admission.js.map +1 -1
  53. package/dist/modules/auth/account.routes.d.ts +1 -1
  54. package/dist/modules/auth/account.routes.d.ts.map +1 -1
  55. package/dist/modules/auth/account.routes.js +61 -5
  56. package/dist/modules/auth/account.routes.js.map +1 -1
  57. package/dist/modules/auth/auth.middleware.d.ts +1 -1
  58. package/dist/modules/auth/auth.middleware.d.ts.map +1 -1
  59. package/dist/modules/auth/auth.middleware.js +18 -7
  60. package/dist/modules/auth/auth.middleware.js.map +1 -1
  61. package/dist/modules/auth/auth.routes.d.ts.map +1 -1
  62. package/dist/modules/auth/auth.routes.js +8 -0
  63. package/dist/modules/auth/auth.routes.js.map +1 -1
  64. package/dist/modules/auth/auth.service.d.ts +96 -3
  65. package/dist/modules/auth/auth.service.d.ts.map +1 -1
  66. package/dist/modules/auth/auth.service.js +187 -9
  67. package/dist/modules/auth/auth.service.js.map +1 -1
  68. package/dist/modules/auth/oidc-auth-provider.d.ts.map +1 -1
  69. package/dist/modules/auth/oidc-auth-provider.js +7 -2
  70. package/dist/modules/auth/oidc-auth-provider.js.map +1 -1
  71. package/dist/modules/database/core-schema.d.ts +41 -24
  72. package/dist/modules/database/core-schema.d.ts.map +1 -1
  73. package/dist/modules/database/core-schema.js +35 -27
  74. package/dist/modules/database/core-schema.js.map +1 -1
  75. package/dist/modules/github-app/github-app.client.d.ts +101 -0
  76. package/dist/modules/github-app/github-app.client.d.ts.map +1 -0
  77. package/dist/modules/github-app/github-app.client.js +222 -0
  78. package/dist/modules/github-app/github-app.client.js.map +1 -0
  79. package/dist/modules/github-app/github-app.connection.d.ts +102 -0
  80. package/dist/modules/github-app/github-app.connection.d.ts.map +1 -0
  81. package/dist/modules/github-app/github-app.connection.js +185 -0
  82. package/dist/modules/github-app/github-app.connection.js.map +1 -0
  83. package/dist/modules/github-app/github-app.routes.d.ts +59 -0
  84. package/dist/modules/github-app/github-app.routes.d.ts.map +1 -0
  85. package/dist/modules/github-app/github-app.routes.js +323 -0
  86. package/dist/modules/github-app/github-app.routes.js.map +1 -0
  87. package/dist/modules/github-app/index.d.ts +4 -0
  88. package/dist/modules/github-app/index.d.ts.map +1 -0
  89. package/dist/modules/github-app/index.js +4 -0
  90. package/dist/modules/github-app/index.js.map +1 -0
  91. package/dist/modules/kb-fs/branch-name.d.ts.map +1 -1
  92. package/dist/modules/kb-fs/branch-name.js +12 -2
  93. package/dist/modules/kb-fs/branch-name.js.map +1 -1
  94. package/dist/modules/kb-fs/remote-url.d.ts +22 -0
  95. package/dist/modules/kb-fs/remote-url.d.ts.map +1 -0
  96. package/dist/modules/kb-fs/remote-url.js +35 -0
  97. package/dist/modules/kb-fs/remote-url.js.map +1 -0
  98. package/dist/modules/kb-fs/repo-path.d.ts +11 -16
  99. package/dist/modules/kb-fs/repo-path.d.ts.map +1 -1
  100. package/dist/modules/kb-fs/repo-path.js +79 -0
  101. package/dist/modules/kb-fs/repo-path.js.map +1 -1
  102. package/dist/modules/kb-sync/kb-sync.routes.d.ts +2 -2
  103. package/dist/modules/kb-sync/kb-sync.routes.d.ts.map +1 -1
  104. package/dist/modules/kb-sync/kb-sync.routes.js +14 -3
  105. package/dist/modules/kb-sync/kb-sync.routes.js.map +1 -1
  106. package/dist/modules/kb-sync/sync-auth.d.ts +3 -1
  107. package/dist/modules/kb-sync/sync-auth.d.ts.map +1 -1
  108. package/dist/modules/kb-sync/sync-auth.js +1 -1
  109. package/dist/modules/kb-sync/sync-auth.js.map +1 -1
  110. package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -1
  111. package/dist/modules/mcp/mcp-auth.middleware.js +21 -6
  112. package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -1
  113. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -1
  114. package/dist/modules/mcp/oauth/bevel-oauth-provider.js +3 -2
  115. package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -1
  116. package/dist/modules/plugins/join-proposals.d.ts +17 -5
  117. package/dist/modules/plugins/join-proposals.d.ts.map +1 -1
  118. package/dist/modules/plugins/join-proposals.js +76 -22
  119. package/dist/modules/plugins/join-proposals.js.map +1 -1
  120. package/dist/modules/plugins/join-requests.service.d.ts +111 -18
  121. package/dist/modules/plugins/join-requests.service.d.ts.map +1 -1
  122. package/dist/modules/plugins/join-requests.service.js +173 -29
  123. package/dist/modules/plugins/join-requests.service.js.map +1 -1
  124. package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
  125. package/dist/modules/plugins/plugins.routes.js +3 -2
  126. package/dist/modules/plugins/plugins.routes.js.map +1 -1
  127. package/dist/modules/settings/deployment-settings.service.d.ts +22 -1
  128. package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
  129. package/dist/modules/settings/deployment-settings.service.js +101 -7
  130. package/dist/modules/settings/deployment-settings.service.js.map +1 -1
  131. package/dist/modules/settings/managed-repository.d.ts +43 -0
  132. package/dist/modules/settings/managed-repository.d.ts.map +1 -0
  133. package/dist/modules/settings/managed-repository.js +60 -0
  134. package/dist/modules/settings/managed-repository.js.map +1 -0
  135. package/dist/modules/settings/repository-source.d.ts +128 -0
  136. package/dist/modules/settings/repository-source.d.ts.map +1 -0
  137. package/dist/modules/settings/repository-source.js +150 -0
  138. package/dist/modules/settings/repository-source.js.map +1 -0
  139. package/dist/modules/settings/setup.routes.d.ts +78 -4
  140. package/dist/modules/settings/setup.routes.d.ts.map +1 -1
  141. package/dist/modules/settings/setup.routes.js +379 -17
  142. package/dist/modules/settings/setup.routes.js.map +1 -1
  143. package/dist/modules/skills/skill-access-requests.routes.d.ts +6 -8
  144. package/dist/modules/skills/skill-access-requests.routes.d.ts.map +1 -1
  145. package/dist/modules/skills/skill-access-requests.routes.js +24 -63
  146. package/dist/modules/skills/skill-access-requests.routes.js.map +1 -1
  147. package/dist/modules/skills/skills.contract.d.ts +90 -18
  148. package/dist/modules/skills/skills.contract.d.ts.map +1 -1
  149. package/dist/modules/skills/skills.contract.js +4 -1
  150. package/dist/modules/skills/skills.contract.js.map +1 -1
  151. package/dist/modules/skills/skills.service.d.ts +98 -9
  152. package/dist/modules/skills/skills.service.d.ts.map +1 -1
  153. package/dist/modules/skills/skills.service.js +239 -37
  154. package/dist/modules/skills/skills.service.js.map +1 -1
  155. package/dist/modules/skills/skills.tools.d.ts +7 -0
  156. package/dist/modules/skills/skills.tools.d.ts.map +1 -1
  157. package/dist/modules/skills/skills.tools.js +71 -7
  158. package/dist/modules/skills/skills.tools.js.map +1 -1
  159. package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -1
  160. package/dist/modules/tool-auth/external-api-key.service.js +4 -2
  161. package/dist/modules/tool-auth/external-api-key.service.js.map +1 -1
  162. package/dist/modules/tool-auth/internal-token.service.d.ts +3 -3
  163. package/dist/modules/tool-auth/tool-auth.middleware.d.ts +16 -7
  164. package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
  165. package/dist/modules/tool-auth/tool-auth.middleware.js +34 -12
  166. package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -1
  167. package/dist/modules/tool-helpers/tool-context.d.ts.map +1 -1
  168. package/dist/modules/tool-helpers/tool-context.js +15 -0
  169. package/dist/modules/tool-helpers/tool-context.js.map +1 -1
  170. package/dist/modules/tool-helpers/tool-handler.d.ts +2 -1
  171. package/dist/modules/tool-helpers/tool-handler.d.ts.map +1 -1
  172. package/dist/modules/tool-helpers/tool-handler.js +25 -4
  173. package/dist/modules/tool-helpers/tool-handler.js.map +1 -1
  174. package/dist/modules/tool-helpers/tool.contract.d.ts +3 -2
  175. package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -1
  176. package/dist/modules/tool-helpers/tool.contract.js.map +1 -1
  177. package/dist/modules/tool-helpers/validate-token.js +1 -1
  178. package/dist/modules/tool-helpers/validate-token.js.map +1 -1
  179. package/dist/modules/workflow/agent-tools/change-request-summary.d.ts +98 -0
  180. package/dist/modules/workflow/agent-tools/change-request-summary.d.ts.map +1 -0
  181. package/dist/modules/workflow/agent-tools/change-request-summary.js +81 -0
  182. package/dist/modules/workflow/agent-tools/change-request-summary.js.map +1 -0
  183. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
  184. package/dist/modules/workflow/agent-tools/workflow.tools.js +113 -37
  185. package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
  186. package/dist/modules/workflow/file-lock.service.d.ts +24 -0
  187. package/dist/modules/workflow/file-lock.service.d.ts.map +1 -1
  188. package/dist/modules/workflow/file-lock.service.js +30 -0
  189. package/dist/modules/workflow/file-lock.service.js.map +1 -1
  190. package/dist/modules/workflow/git/git.service.d.ts +72 -1
  191. package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
  192. package/dist/modules/workflow/git/git.service.js +170 -6
  193. package/dist/modules/workflow/git/git.service.js.map +1 -1
  194. package/dist/modules/workflow/git/node-git-runner.d.ts.map +1 -1
  195. package/dist/modules/workflow/git/node-git-runner.js +5 -0
  196. package/dist/modules/workflow/git/node-git-runner.js.map +1 -1
  197. package/dist/modules/workflow/git/pull-request.service.d.ts +45 -0
  198. package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -1
  199. package/dist/modules/workflow/git/pull-request.service.js +99 -0
  200. package/dist/modules/workflow/git/pull-request.service.js.map +1 -1
  201. package/dist/modules/workflow/pending-commits.service.d.ts +38 -0
  202. package/dist/modules/workflow/pending-commits.service.d.ts.map +1 -1
  203. package/dist/modules/workflow/pending-commits.service.js +55 -0
  204. package/dist/modules/workflow/pending-commits.service.js.map +1 -1
  205. package/dist/modules/workflow/workflow-hooks.d.ts +54 -32
  206. package/dist/modules/workflow/workflow-hooks.d.ts.map +1 -1
  207. package/dist/modules/workflow/workflow-hooks.js +16 -1
  208. package/dist/modules/workflow/workflow-hooks.js.map +1 -1
  209. package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
  210. package/dist/modules/workflow/workflow.routes.js +3 -1
  211. package/dist/modules/workflow/workflow.routes.js.map +1 -1
  212. package/dist/modules/workflow/workflow.service.d.ts +94 -13
  213. package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
  214. package/dist/modules/workflow/workflow.service.js +258 -51
  215. package/dist/modules/workflow/workflow.service.js.map +1 -1
  216. package/dist/modules/workspace/agent-access.gate.d.ts +94 -0
  217. package/dist/modules/workspace/agent-access.gate.d.ts.map +1 -0
  218. package/dist/modules/workspace/agent-access.gate.js +123 -0
  219. package/dist/modules/workspace/agent-access.gate.js.map +1 -0
  220. package/dist/modules/workspace/routine-write-policy.d.ts +5 -6
  221. package/dist/modules/workspace/routine-write-policy.d.ts.map +1 -1
  222. package/dist/modules/workspace/routine-write-policy.js +5 -6
  223. package/dist/modules/workspace/routine-write-policy.js.map +1 -1
  224. package/dist/modules/workspace/session-sink.d.ts +5 -5
  225. package/dist/modules/workspace/set-aside-clone.d.ts +46 -0
  226. package/dist/modules/workspace/set-aside-clone.d.ts.map +1 -0
  227. package/dist/modules/workspace/set-aside-clone.js +92 -0
  228. package/dist/modules/workspace/set-aside-clone.js.map +1 -0
  229. package/dist/modules/workspace/startup/kb-startup-runner.d.ts +117 -1
  230. package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -1
  231. package/dist/modules/workspace/startup/kb-startup-runner.js +190 -1
  232. package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -1
  233. package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
  234. package/dist/modules/workspace/workspace.routes.js +92 -3
  235. package/dist/modules/workspace/workspace.routes.js.map +1 -1
  236. package/dist/modules/workspace/workspace.service.d.ts +115 -5
  237. package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
  238. package/dist/modules/workspace/workspace.service.js +272 -26
  239. package/dist/modules/workspace/workspace.service.js.map +1 -1
  240. package/dist/modules/workspace/workspace.tools.d.ts +2 -2
  241. package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
  242. package/dist/modules/workspace/workspace.tools.js +337 -117
  243. package/dist/modules/workspace/workspace.tools.js.map +1 -1
  244. package/dist/modules/write-access/write-access.d.ts +60 -0
  245. package/dist/modules/write-access/write-access.d.ts.map +1 -0
  246. package/dist/modules/write-access/write-access.js +129 -0
  247. package/dist/modules/write-access/write-access.js.map +1 -0
  248. package/dist/shared/domain-errors.d.ts +64 -0
  249. package/dist/shared/domain-errors.d.ts.map +1 -1
  250. package/dist/shared/domain-errors.js +83 -0
  251. package/dist/shared/domain-errors.js.map +1 -1
  252. package/dist/shared/git.contract.d.ts +30 -0
  253. package/dist/shared/git.contract.d.ts.map +1 -1
  254. package/dist/shared/git.contract.js +26 -0
  255. package/dist/shared/git.contract.js.map +1 -1
  256. package/dist/tenancy/static-tenant-source.d.ts +0 -1
  257. package/dist/tenancy/static-tenant-source.d.ts.map +1 -1
  258. package/dist/tenancy/static-tenant-source.js +0 -2
  259. package/dist/tenancy/static-tenant-source.js.map +1 -1
  260. package/migrations/0014_change_request_closed_reason.sql +1 -0
  261. package/migrations/0015_account_deactivation.sql +3 -0
  262. package/migrations/meta/0014_snapshot.json +2265 -0
  263. package/migrations/meta/0015_snapshot.json +2271 -0
  264. package/migrations/meta/_journal.json +14 -0
  265. package/package.json +3 -3
  266. package/src/__tests__/kb-layout-config.test.ts +0 -2
  267. package/src/__tests__/retired-settings.test.ts +96 -0
  268. package/src/core/__tests__/gated-boot.test.ts +132 -0
  269. package/src/core/__tests__/lifecycle.test.ts +170 -1
  270. package/src/core/__tests__/set-aside-root-is-one-place.test.ts +63 -0
  271. package/src/core/core-ports.ts +11 -1
  272. package/src/core/create-core-server.ts +69 -15
  273. package/src/core/create-core-services.ts +190 -27
  274. package/src/core/lifecycle.ts +98 -13
  275. package/src/core-config.ts +13 -14
  276. package/src/index.ts +12 -1
  277. package/src/modules/access/__tests__/access-control.preview-relocation.test.ts +385 -0
  278. package/src/modules/access/__tests__/access-control.prospective.test.ts +94 -18
  279. package/src/modules/access/__tests__/access-requests.recut.test.ts +134 -0
  280. package/src/modules/access/__tests__/access-requests.routes.test.ts +610 -0
  281. package/src/modules/access/__tests__/access.routes.prospective.test.ts +6 -7
  282. package/src/modules/access/access-control.interface.ts +43 -12
  283. package/src/modules/access/access-control.service.ts +234 -36
  284. package/src/modules/access/access-requests.contract.ts +93 -0
  285. package/src/modules/access/access-requests.routes.ts +286 -0
  286. package/src/modules/access/access-requests.service.ts +420 -0
  287. package/src/modules/access/access.routes.ts +13 -15
  288. package/src/modules/access-model/access-grammar.ts +22 -0
  289. package/src/modules/agent-instructions/__tests__/agent-instructions.route.test.ts +3 -1
  290. package/src/modules/auth/__tests__/account-deactivation.test.ts +252 -0
  291. package/src/modules/auth/__tests__/account.routes.test.ts +81 -3
  292. package/src/modules/auth/__tests__/auth.middleware.test.ts +45 -22
  293. package/src/modules/auth/__tests__/auth.service.test.ts +39 -1
  294. package/src/modules/auth/account-admission.ts +78 -9
  295. package/src/modules/auth/account.routes.ts +63 -7
  296. package/src/modules/auth/auth.middleware.ts +19 -8
  297. package/src/modules/auth/auth.routes.ts +8 -0
  298. package/src/modules/auth/auth.service.ts +207 -7
  299. package/src/modules/auth/oidc-auth-provider.ts +7 -2
  300. package/src/modules/database/core-schema.ts +35 -27
  301. package/src/modules/github-app/__tests__/github-app.test.ts +848 -0
  302. package/src/modules/github-app/github-app.client.ts +268 -0
  303. package/src/modules/github-app/github-app.connection.ts +204 -0
  304. package/src/modules/github-app/github-app.routes.ts +359 -0
  305. package/src/modules/github-app/index.ts +19 -0
  306. package/src/modules/kb-fs/__tests__/branch-name.test.ts +10 -0
  307. package/src/modules/kb-fs/__tests__/remote-url.test.ts +38 -0
  308. package/src/modules/kb-fs/__tests__/repo-path.test.ts +123 -0
  309. package/src/modules/kb-fs/branch-name.ts +14 -1
  310. package/src/modules/kb-fs/remote-url.ts +35 -0
  311. package/src/modules/kb-fs/repo-path.ts +85 -0
  312. package/src/modules/kb-sync/__tests__/kb-sync.routes.test.ts +26 -1
  313. package/src/modules/kb-sync/kb-sync.routes.ts +14 -4
  314. package/src/modules/kb-sync/sync-auth.ts +2 -2
  315. package/src/modules/mcp/__tests__/mcp-auth.middleware.test.ts +60 -3
  316. package/src/modules/mcp/__tests__/mcp.service.test.ts +68 -6
  317. package/src/modules/mcp/mcp-auth.middleware.ts +20 -6
  318. package/src/modules/mcp/oauth/bevel-oauth-provider.ts +3 -1
  319. package/src/modules/plugins/__tests__/join-proposals.test.ts +100 -19
  320. package/src/modules/plugins/__tests__/join-requests.service.test.ts +27 -11
  321. package/src/modules/plugins/__tests__/join-requests.settlement.test.ts +371 -0
  322. package/src/modules/plugins/__tests__/plugins.routes.test.ts +1 -1
  323. package/src/modules/plugins/__tests__/plugins.tools.test.ts +2 -1
  324. package/src/modules/plugins/join-proposals.ts +87 -19
  325. package/src/modules/plugins/join-requests.service.ts +199 -39
  326. package/src/modules/plugins/plugins.routes.ts +3 -2
  327. package/src/modules/settings/__tests__/deployment-settings.service.test.ts +16 -0
  328. package/src/modules/settings/__tests__/repository-source.test.ts +191 -0
  329. package/src/modules/settings/__tests__/setup.routes.git-mode.test.ts +386 -0
  330. package/src/modules/settings/__tests__/setup.routes.github-app.test.ts +299 -0
  331. package/src/modules/settings/__tests__/setup.routes.managed-phase.test.ts +236 -0
  332. package/src/modules/settings/__tests__/setup.routes.repository-change.test.ts +390 -0
  333. package/src/modules/settings/__tests__/setup.routes.test.ts +3 -0
  334. package/src/modules/settings/deployment-settings.service.ts +117 -6
  335. package/src/modules/settings/managed-repository.ts +68 -0
  336. package/src/modules/settings/repository-source.ts +197 -0
  337. package/src/modules/settings/setup.routes.ts +463 -15
  338. package/src/modules/skills/__tests__/allowed-tools-warn.tools.test.ts +2 -1
  339. package/src/modules/skills/__tests__/branch-skills.tools.test.ts +218 -0
  340. package/src/modules/skills/__tests__/skill-access-requests.routes.test.ts +5 -1
  341. package/src/modules/skills/__tests__/skills.service.test.ts +229 -5
  342. package/src/modules/skills/skill-access-requests.routes.ts +25 -75
  343. package/src/modules/skills/skills.contract.ts +91 -18
  344. package/src/modules/skills/skills.service.ts +278 -41
  345. package/src/modules/skills/skills.tools.ts +80 -8
  346. package/src/modules/tool-auth/__tests__/manual-auth.middleware.test.ts +14 -1
  347. package/src/modules/tool-auth/external-api-key.service.ts +4 -2
  348. package/src/modules/tool-auth/internal-token.service.ts +3 -3
  349. package/src/modules/tool-auth/tool-auth.middleware.ts +34 -11
  350. package/src/modules/tool-helpers/__tests__/agent-roles-write.test.ts +5 -3
  351. package/src/modules/tool-helpers/__tests__/phase4-tools.test.ts +3 -3
  352. package/src/modules/tool-helpers/__tests__/validate-token.test.ts +11 -1
  353. package/src/modules/tool-helpers/tool-context.ts +15 -0
  354. package/src/modules/tool-helpers/tool-handler.ts +24 -4
  355. package/src/modules/tool-helpers/tool.contract.ts +3 -2
  356. package/src/modules/tool-helpers/validate-token.ts +1 -1
  357. package/src/modules/workflow/__tests__/apply-failure.test.ts +9 -1
  358. package/src/modules/workflow/__tests__/pending-commits.repository-replaced.test.ts +111 -0
  359. package/src/modules/workflow/__tests__/workflow.routes.history-read-gate.test.ts +25 -0
  360. package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +159 -8
  361. package/src/modules/workflow/__tests__/workflow.service.repository-replaced.test.ts +249 -0
  362. package/src/modules/workflow/__tests__/workflow.service.update-from-target.test.ts +146 -40
  363. package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +405 -7
  364. package/src/modules/workflow/agent-tools/change-request-summary.ts +182 -0
  365. package/src/modules/workflow/agent-tools/workflow.tools.ts +135 -38
  366. package/src/modules/workflow/file-lock.service.ts +31 -0
  367. package/src/modules/workflow/git/__tests__/git.service.fileBytesAtCommit.test.ts +260 -0
  368. package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +121 -0
  369. package/src/modules/workflow/git/__tests__/pull-request.service.getPrDetail.test.ts +145 -2
  370. package/src/modules/workflow/git/__tests__/pull-request.service.viewer-can-delete.test.ts +166 -0
  371. package/src/modules/workflow/git/git.service.ts +193 -4
  372. package/src/modules/workflow/git/node-git-runner.ts +6 -0
  373. package/src/modules/workflow/git/pull-request.service.ts +119 -0
  374. package/src/modules/workflow/pending-commits.service.ts +59 -1
  375. package/src/modules/workflow/workflow-hooks.ts +64 -26
  376. package/src/modules/workflow/workflow.routes.ts +3 -1
  377. package/src/modules/workflow/workflow.service.ts +290 -55
  378. package/src/modules/workspace/__tests__/agent-access.gate.test.ts +208 -0
  379. package/src/modules/workspace/__tests__/escape-sequences.routes.test.ts +384 -0
  380. package/src/modules/workspace/__tests__/file-stat-access.test.ts +2 -1
  381. package/src/modules/workspace/__tests__/git-internals.security.test.ts +2 -1
  382. package/src/modules/workspace/__tests__/set-aside-clone.test.ts +52 -0
  383. package/src/modules/workspace/__tests__/workspace.routes.at-ref.test.ts +305 -0
  384. package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +2 -0
  385. package/src/modules/workspace/__tests__/workspace.service.forget-clone-races.test.ts +147 -0
  386. package/src/modules/workspace/__tests__/workspace.service.replaced-repository.test.ts +326 -0
  387. package/src/modules/workspace/__tests__/workspace.service.test.ts +20 -9
  388. package/src/modules/workspace/__tests__/workspace.service.unknown-branch.test.ts +43 -0
  389. package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +2 -3
  390. package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +235 -10
  391. package/src/modules/workspace/__tests__/workspace.tools.test.ts +720 -17
  392. package/src/modules/workspace/agent-access.gate.ts +164 -0
  393. package/src/modules/workspace/routine-write-policy.ts +5 -6
  394. package/src/modules/workspace/session-sink.ts +5 -5
  395. package/src/modules/workspace/set-aside-clone.ts +96 -0
  396. package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +297 -0
  397. package/src/modules/workspace/startup/kb-startup-runner.ts +242 -2
  398. package/src/modules/workspace/workspace.routes.ts +95 -3
  399. package/src/modules/workspace/workspace.service.ts +273 -25
  400. package/src/modules/workspace/workspace.tools.ts +373 -119
  401. package/src/modules/write-access/__tests__/write-access.test.ts +248 -0
  402. package/src/modules/write-access/write-access.ts +153 -0
  403. package/src/shared/domain-errors.ts +89 -0
  404. package/src/shared/git.contract.ts +37 -0
  405. package/src/tenancy/__tests__/static-tenant-source.test.ts +0 -1
  406. package/src/tenancy/static-tenant-source.ts +0 -3
  407. package/dist/modules/workflow/session-ontology.policy.d.ts +0 -52
  408. package/dist/modules/workflow/session-ontology.policy.d.ts.map +0 -1
  409. package/dist/modules/workflow/session-ontology.policy.js +0 -62
  410. package/dist/modules/workflow/session-ontology.policy.js.map +0 -1
  411. package/dist/modules/workflow/session-ontology.service.d.ts +0 -105
  412. package/dist/modules/workflow/session-ontology.service.d.ts.map +0 -1
  413. package/dist/modules/workflow/session-ontology.service.js +0 -147
  414. package/dist/modules/workflow/session-ontology.service.js.map +0 -1
  415. package/dist/modules/workspace/session-ontology.gate.d.ts +0 -114
  416. package/dist/modules/workspace/session-ontology.gate.d.ts.map +0 -1
  417. package/dist/modules/workspace/session-ontology.gate.js +0 -161
  418. package/dist/modules/workspace/session-ontology.gate.js.map +0 -1
  419. package/dist/shared/kb-layout.d.ts +0 -39
  420. package/dist/shared/kb-layout.d.ts.map +0 -1
  421. package/dist/shared/kb-layout.js +0 -103
  422. package/dist/shared/kb-layout.js.map +0 -1
  423. package/dist/shared/kb-layout.test.d.ts +0 -2
  424. package/dist/shared/kb-layout.test.d.ts.map +0 -1
  425. package/dist/shared/kb-layout.test.js +0 -75
  426. package/dist/shared/kb-layout.test.js.map +0 -1
  427. package/src/modules/workflow/__tests__/session-ontology.policy.test.ts +0 -62
  428. package/src/modules/workflow/__tests__/session-ontology.service.test.ts +0 -201
  429. package/src/modules/workflow/session-ontology.policy.ts +0 -70
  430. package/src/modules/workflow/session-ontology.service.ts +0 -183
  431. package/src/modules/workspace/__tests__/session-ontology.gate.test.ts +0 -239
  432. package/src/modules/workspace/session-ontology.gate.ts +0 -191
  433. package/src/shared/kb-layout.test.ts +0 -98
  434. package/src/shared/kb-layout.ts +0 -102
@@ -0,0 +1,323 @@
1
+ import { randomBytes, timingSafeEqual } from 'node:crypto';
2
+ import express from 'express';
3
+ import { logger } from '../../shared/logging.js';
4
+ import { GitHubAppClient, GitHubAppError } from './github-app.client.js';
5
+ import { repositoriesAsSetting } from './github-app.connection.js';
6
+ import '../auth/auth.middleware.js'; // Express Request augmentation
7
+ const log = logger('github-app');
8
+ const STATE_COOKIE = 'hexis_github_state';
9
+ const STATE_MAX_AGE_S = 15 * 60;
10
+ /** A GitHub organisation's name, as it appears in an address. */
11
+ const ORGANIZATION_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?$/;
12
+ /** GitHub refuses an app name longer than this. */
13
+ const MAX_APP_NAME = 34;
14
+ /** The address GitHub is told to send the browser back to once the app is installed. */
15
+ export function githubAppCallbackUrl(publicBackendUrl) {
16
+ return `${publicBackendUrl}/api/setup/github-app/callback`;
17
+ }
18
+ /**
19
+ * The manifest a deployment's own GitHub App is created from. It asks for
20
+ * what the deployment does and nothing else: read and write the contents of
21
+ * the repositories it is installed on. No webhook, no events, not public:
22
+ * the app is this deployment's, installed by its owner on the one
23
+ * repository the knowledge base lives in.
24
+ */
25
+ export function githubAppManifest(publicBackendUrl, publicFrontendUrl) {
26
+ const host = new URL(publicFrontendUrl).host;
27
+ return {
28
+ name: `Hexis ${host}`.slice(0, MAX_APP_NAME),
29
+ url: publicFrontendUrl,
30
+ description: `Lets the Hexis deployment at ${host} read and write the repository its knowledge base lives in.`,
31
+ redirect_url: `${publicBackendUrl}/api/setup/github-app/registered`,
32
+ callback_urls: [githubAppCallbackUrl(publicBackendUrl)],
33
+ // GitHub then sends the person back signed in, which is what lets the
34
+ // deployment check that the installation they name is one they hold.
35
+ request_oauth_on_install: true,
36
+ public: false,
37
+ default_permissions: { contents: 'write', metadata: 'read' },
38
+ default_events: [],
39
+ };
40
+ }
41
+ function readCookie(req, name) {
42
+ for (const segment of (req.headers.cookie ?? '').split(';')) {
43
+ const trimmed = segment.trim();
44
+ if (!trimmed.startsWith(`${name}=`))
45
+ continue;
46
+ try {
47
+ return decodeURIComponent(trimmed.slice(name.length + 1)) || null;
48
+ }
49
+ catch {
50
+ return null;
51
+ }
52
+ }
53
+ return null;
54
+ }
55
+ function same(a, b) {
56
+ const left = Buffer.from(a, 'utf8');
57
+ const right = Buffer.from(b, 'utf8');
58
+ return left.length === right.length && timingSafeEqual(left, right);
59
+ }
60
+ /**
61
+ * Connecting a repository on GitHub through a GitHub App, from the setup
62
+ * screen. Mounted behind the deployment's sign-in; every route is an
63
+ * admin's.
64
+ *
65
+ * GET /setup/github-app where the connection stands
66
+ * POST /setup/github-app/manifest start registering this deployment's own app
67
+ * GET /setup/github-app/registered GitHub sends the browser back: the app exists
68
+ * POST /setup/github-app/install where on GitHub the app is installed
69
+ * POST /setup/github-app/refresh where to sign in, to read again what may be connected
70
+ * GET /setup/github-app/callback GitHub sends the browser back: the app is installed
71
+ * GET /setup/github-app/repositories what the deployment may be pointed at
72
+ *
73
+ * A ROUND TRIP IS STARTED BY A POST AND ENDED BY A GET. The two routes
74
+ * GitHub sends the browser to are ordinary navigations, authenticated by
75
+ * the session cookie; each checks a state this browser was given when the
76
+ * round trip started, and spends it. Nothing that starts one is a link, so
77
+ * a link somebody was sent starts nothing.
78
+ *
79
+ * WHAT THE DEPLOYMENT MAY REACH is never taken from the address the browser
80
+ * came back on. GitHub puts an installation's number there and anyone can
81
+ * write another: with one app serving many deployments, that number is the
82
+ * only thing between a deployment and another organisation's repositories.
83
+ * GitHub sends the person back signed in, and the deployment asks GitHub
84
+ * two things about THAT PERSON: which installations they reach, and which
85
+ * repositories of the one they named they can push to with their own
86
+ * account. The first alone is not enough, since read access to one
87
+ * repository puts an installation on that list. Only the second is what
88
+ * the deployment may be pointed at.
89
+ */
90
+ export function createGitHubAppRoutes(deps) {
91
+ const router = express.Router();
92
+ const client = deps.client ?? new GitHubAppClient();
93
+ const { settings, connection } = deps;
94
+ const secure = deps.publicBackendUrl.startsWith('https');
95
+ const requireAdmin = async (req, res, next) => {
96
+ if (!(await deps.adminAccess.isAdmin(req.userEmail))) {
97
+ res.status(403).json({ error: 'Admins only' });
98
+ return;
99
+ }
100
+ next();
101
+ };
102
+ /** A state for one round trip, kept in this browser until it comes back. */
103
+ const beginRoundTrip = (res) => {
104
+ const tag = settings.resolve('githubAppStateTag');
105
+ const state = `${tag ? `${tag}.` : ''}${randomBytes(24).toString('base64url')}`;
106
+ res.cookie(STATE_COOKIE, state, { httpOnly: true, sameSite: 'lax', secure, maxAge: STATE_MAX_AGE_S * 1000, path: '/' });
107
+ return state;
108
+ };
109
+ /** Whether the browser that came back is the one that was sent. */
110
+ const cameBack = (req) => {
111
+ const kept = readCookie(req, STATE_COOKIE);
112
+ const given = typeof req.query.state === 'string' ? req.query.state : '';
113
+ return Boolean(kept && given && same(kept, given));
114
+ };
115
+ /** Back to the setup screen, saying how the round trip ended. */
116
+ const finish = (res, outcome) => {
117
+ const page = deps.isComplete() ? '/deployment' : '/';
118
+ res.redirect(`${deps.publicFrontendUrl}${page}?github=${encodeURIComponent(outcome)}`);
119
+ };
120
+ const installUrl = (slug, state) => `https://github.com/apps/${encodeURIComponent(slug)}/installations/new?state=${encodeURIComponent(state)}`;
121
+ const outcomeOf = (err) => err instanceof GitHubAppError && err.kind === 'unreachable' ? 'unreachable' : 'refused';
122
+ router.get('/setup/github-app', requireAdmin, (_req, res) => {
123
+ const credentials = connection.credentials();
124
+ res.json({
125
+ // Who supplied the app. Null: this deployment has none yet, and can register its own.
126
+ registeredBy: connection.registeredBy(),
127
+ app: credentials ? { slug: credentials.slug, url: `https://github.com/apps/${credentials.slug}` } : null,
128
+ installation: connection.installationId()
129
+ ? { id: connection.installationId(), account: settings.resolve('githubInstallationAccount') }
130
+ : null,
131
+ repository: settings.resolve('githubRepository') || null,
132
+ });
133
+ });
134
+ router.post('/setup/github-app/manifest', requireAdmin, (req, res) => {
135
+ if (connection.credentials()) {
136
+ res.status(409).json({ error: 'This deployment already has a GitHub App.' });
137
+ return;
138
+ }
139
+ const organization = req.body?.organization;
140
+ const org = typeof organization === 'string' ? organization.trim() : '';
141
+ if (org && !ORGANIZATION_PATTERN.test(org)) {
142
+ res.status(400).json({ error: 'Enter the organisation’s name as it appears in its GitHub address.' });
143
+ return;
144
+ }
145
+ const state = beginRoundTrip(res);
146
+ const base = org ? `https://github.com/organizations/${org}/settings/apps/new` : 'https://github.com/settings/apps/new';
147
+ // The browser posts the manifest to GitHub itself: a form, not a request of ours.
148
+ res.json({
149
+ action: `${base}?state=${encodeURIComponent(state)}`,
150
+ manifest: githubAppManifest(deps.publicBackendUrl, deps.publicFrontendUrl),
151
+ });
152
+ });
153
+ router.get('/setup/github-app/registered', requireAdmin, async (req, res) => {
154
+ // Spent on return, however the return ends.
155
+ const returned = cameBack(req);
156
+ res.clearCookie(STATE_COOKIE, { path: '/' });
157
+ if (!returned) {
158
+ finish(res, 'state');
159
+ return;
160
+ }
161
+ const code = typeof req.query.code === 'string' ? req.query.code : '';
162
+ if (!code || connection.credentials()) {
163
+ finish(res, code ? 'already-registered' : 'refused');
164
+ return;
165
+ }
166
+ try {
167
+ const app = await client.convertManifest(code);
168
+ await settings.record({
169
+ githubAppId: app.appId,
170
+ githubAppSlug: app.slug,
171
+ githubAppPrivateKey: app.privateKey,
172
+ githubAppClientId: app.clientId,
173
+ githubAppClientSecret: app.clientSecret,
174
+ }, req.userId ?? null);
175
+ log.info(`GitHub App "${app.slug}" registered for this deployment`, { slug: app.slug, owner: app.owner });
176
+ // Straight on to installing it: the same round trip, the same state.
177
+ res.redirect(installUrl(app.slug, beginRoundTrip(res)));
178
+ }
179
+ catch (err) {
180
+ log.error('the GitHub App could not be registered:', { detail: err instanceof Error ? err.message : String(err) });
181
+ finish(res, outcomeOf(err));
182
+ }
183
+ });
184
+ /**
185
+ * A POST that answers with the address, and the page sends the browser
186
+ * there. As a link it was a round trip anyone could start in an admin's
187
+ * browser by getting them to follow it: the state would be set, and
188
+ * whatever they then installed would come back with a state that matched.
189
+ */
190
+ router.post('/setup/github-app/install', requireAdmin, (_req, res) => {
191
+ const credentials = connection.credentials();
192
+ if (!credentials) {
193
+ res.status(409).json({ error: 'This deployment has no GitHub App yet. Create it first.' });
194
+ return;
195
+ }
196
+ res.json({ url: installUrl(credentials.slug, beginRoundTrip(res)) });
197
+ });
198
+ /**
199
+ * Ask GitHub again what the person may connect, WITHOUT installing
200
+ * anything: a sign-in with the app and nothing more, which comes back on
201
+ * the same callback with a code and no installation named.
202
+ *
203
+ * It exists because installing comes back only the first time. Once the
204
+ * app is installed, the address that installs it opens the installation's
205
+ * settings on GitHub, and GitHub sends nobody back from there: a
206
+ * repository added on that page was reached by the app and never offered
207
+ * here, since what is offered is what was recorded when the person
208
+ * connected. The same goes for an installation an organisation's owner
209
+ * approved later, in a browser of their own.
210
+ */
211
+ router.post('/setup/github-app/refresh', requireAdmin, (_req, res) => {
212
+ const credentials = connection.credentials();
213
+ if (!credentials) {
214
+ res.status(409).json({ error: 'This deployment has no GitHub App yet. Create it first.' });
215
+ return;
216
+ }
217
+ const state = beginRoundTrip(res);
218
+ res.json({
219
+ url: `https://github.com/login/oauth/authorize?client_id=${encodeURIComponent(credentials.clientId)}&state=${encodeURIComponent(state)}`,
220
+ });
221
+ });
222
+ router.get('/setup/github-app/callback', requireAdmin, async (req, res) => {
223
+ const returned = cameBack(req);
224
+ res.clearCookie(STATE_COOKIE, { path: '/' });
225
+ if (!returned) {
226
+ finish(res, 'state');
227
+ return;
228
+ }
229
+ const credentials = connection.credentials();
230
+ if (!credentials) {
231
+ finish(res, 'not-registered');
232
+ return;
233
+ }
234
+ // Someone without the right to install asked their organisation's owner
235
+ // to: nothing is installed yet, and there is nothing to record.
236
+ if (req.query.setup_action === 'request') {
237
+ finish(res, 'requested');
238
+ return;
239
+ }
240
+ const code = typeof req.query.code === 'string' ? req.query.code : '';
241
+ const given = typeof req.query.installation_id === 'string' ? req.query.installation_id : '';
242
+ if (!code || (given !== '' && !/^\d+$/.test(given))) {
243
+ finish(res, 'refused');
244
+ return;
245
+ }
246
+ // Back from installing, GitHub names the installation. Back from a
247
+ // sign-in alone (see `refresh`) it names none, and the one in question
248
+ // is the one this deployment has. Either way it is only a name: what
249
+ // decides is what GitHub says the person reaches, below.
250
+ const refreshing = given === '';
251
+ const named = given || connection.installationId();
252
+ try {
253
+ const userToken = await client.exchangeUserCode(credentials, code);
254
+ const reached = await client.installationsOf(userToken);
255
+ let held = named ? reached.find((installation) => installation.id === named) : undefined;
256
+ if (!named) {
257
+ // No installation on record and none named: the app was installed
258
+ // where this browser never came back from (an owner approved it
259
+ // later). One the person reaches is the one; several are a choice
260
+ // only installing from here can make.
261
+ if (reached.length === 0) {
262
+ finish(res, 'not-installed');
263
+ return;
264
+ }
265
+ if (reached.length > 1) {
266
+ finish(res, 'several');
267
+ return;
268
+ }
269
+ held = reached[0];
270
+ }
271
+ if (!held) {
272
+ log.warn('an installation was named that the person who came back cannot reach', { installation: named });
273
+ finish(res, 'not-yours');
274
+ return;
275
+ }
276
+ // Reaching the installation is not holding it: read access to one
277
+ // repository it covers is enough for GitHub to list it. What the
278
+ // deployment may be pointed at is what THIS PERSON can push to.
279
+ const theirs = await client.repositoriesOf(userToken, held.id);
280
+ const writable = theirs.repositories.filter((repository) => repository.writable).map((r) => r.fullName);
281
+ if (writable.length === 0) {
282
+ log.warn('the person who came back can push to nothing the installation covers', { installation: held.id });
283
+ finish(res, 'nothing-to-write');
284
+ return;
285
+ }
286
+ await settings.record({
287
+ githubInstallationId: held.id,
288
+ githubRepositoriesPermitted: repositoriesAsSetting(writable),
289
+ ...(held.account ? { githubInstallationAccount: held.account } : {}),
290
+ }, req.userId ?? null);
291
+ // A token in hand was another installation's.
292
+ connection.forget();
293
+ log.info(refreshing
294
+ ? `what may be connected through the GitHub App on "${held.account}" was read again`
295
+ : `GitHub App installed on "${held.account}"`, { installation: held.id, account: held.account, repositories: writable.length });
296
+ finish(res, refreshing ? 'refreshed' : 'connected');
297
+ }
298
+ catch (err) {
299
+ log.error('the installation could not be confirmed:', { detail: err instanceof Error ? err.message : String(err) });
300
+ finish(res, outcomeOf(err));
301
+ }
302
+ });
303
+ router.get('/setup/github-app/repositories', requireAdmin, async (_req, res) => {
304
+ if (!connection.credentials() || !connection.installationId()) {
305
+ res.status(409).json({ error: 'Connect GitHub first.' });
306
+ return;
307
+ }
308
+ try {
309
+ res.json(await connection.repositories());
310
+ }
311
+ catch (err) {
312
+ log.error('the repositories could not be listed:', { detail: err instanceof Error ? err.message : String(err) });
313
+ const unreachable = err instanceof GitHubAppError && err.kind === 'unreachable';
314
+ res.status(502).json({
315
+ error: unreachable
316
+ ? 'GitHub could not be reached. Try again shortly.'
317
+ : 'GitHub would not list the repositories. The app may have been uninstalled: connect it again.',
318
+ });
319
+ }
320
+ });
321
+ return router;
322
+ }
323
+ //# sourceMappingURL=github-app.routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-app.routes.js","sourceRoot":"","sources":["../../../src/modules/github-app/github-app.routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { GitHubAppClient, GitHubAppError, appJwt, normalizePrivateKey, type GitHubAppCredentials, type GitHubFailureKind, type Installation, type InstallationRepository, type InstallationToken, type RegisteredApp, } from './github-app.client.js';
2
+ export { GitHubAppConnection, repositoriesAsSetting, type GitHubAppConnectionOptions } from './github-app.connection.js';
3
+ export { createGitHubAppRoutes, githubAppCallbackUrl, githubAppManifest, type GitHubAppRoutesDeps, } from './github-app.routes.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modules/github-app/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,cAAc,EACd,MAAM,EACN,mBAAmB,EACnB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,aAAa,GACnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,KAAK,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACzH,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,KAAK,mBAAmB,GACzB,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { GitHubAppClient, GitHubAppError, appJwt, normalizePrivateKey, } from './github-app.client.js';
2
+ export { GitHubAppConnection, repositoriesAsSetting } from './github-app.connection.js';
3
+ export { createGitHubAppRoutes, githubAppCallbackUrl, githubAppManifest, } from './github-app.routes.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/github-app/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,cAAc,EACd,MAAM,EACN,mBAAmB,GAOpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAmC,MAAM,4BAA4B,CAAC;AACzH,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,GAElB,MAAM,wBAAwB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"branch-name.d.ts","sourceRoot":"","sources":["../../../src/modules/kb-fs/branch-name.ts"],"names":[],"mappings":"AASA,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,iCAAiC,CAAC;AAIzC,yEAAyE;AACzE,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAwBxD;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAyBlE"}
1
+ {"version":3,"file":"branch-name.d.ts","sourceRoot":"","sources":["../../../src/modules/kb-fs/branch-name.ts"],"names":[],"mappings":"AASA,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,iCAAiC,CAAC;AAIzC,yEAAyE;AACzE,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAwBxD;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAsClE"}
@@ -49,8 +49,18 @@ export function assertValidRelativePath(relativePath) {
49
49
  throw new WorkflowValidationError('path is required');
50
50
  if (relativePath.length > 1024)
51
51
  throw new WorkflowValidationError('path too long');
52
- if (relativePath.includes('\0'))
53
- throw new WorkflowValidationError('path contains NUL');
52
+ // NUL, every other C0 control and DEL. A NUL is named on its own because it
53
+ // terminates a C string and git's `-z` output; the rest are refused with it
54
+ // because a LINE BREAK in a path is a separator in git's line-oriented stdin
55
+ // protocols — `cat-file --batch` reads one `<ref>:<path>` per line, so
56
+ // `Docs/secret.md\nzzz` is two object names while every gate upstream was
57
+ // asked about one string. See `CONTROL_CHARACTERS` in `repo-path.ts`, which
58
+ // refuses the same range at the normaliser; this is the same rule at the
59
+ // check every path handed to git as a pathspec passes through.
60
+ // eslint-disable-next-line no-control-regex
61
+ if (/[\x00-\x1F\x7F]/.test(relativePath)) {
62
+ throw new WorkflowValidationError(relativePath.includes('\0') ? 'path contains NUL' : 'path contains a control character');
63
+ }
54
64
  if (relativePath.includes('\\')) {
55
65
  throw new WorkflowValidationError('path must use forward slashes only');
56
66
  }
@@ -1 +1 @@
1
- {"version":3,"file":"branch-name.js","sourceRoot":"","sources":["../../../src/modules/kb-fs/branch-name.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAEzF,qFAAqF;AACrF,8EAA8E;AAC9E,+EAA+E;AAC/E,4FAA4F;AAC5F,mEAAmE;AACnE,wEAAwE;AACxE,oBAAoB;AACpB,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,iCAAiC,CAAC;AAEzC,MAAM,kBAAkB,GAAG,gCAAgC,CAAC;AAE5D,yEAAyE;AACzE,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,eAAe,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IACzD,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG;QAAE,MAAM,IAAI,eAAe,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACnE,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,eAAe,CAAC,6BAA6B,EAAE,IAAI,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,eAAe,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;IAC1E,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,eAAe,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;IAC1E,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,eAAe,CAAC,sBAAsB,EAAE,IAAI,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,eAAe,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;IAC7E,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,eAAe,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;IAC1E,0EAA0E;IAC1E,qEAAqE;IACrE,6DAA6D;IAC7D,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACtC,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,eAAe,CAAC,yBAAyB,EAAE,IAAI,CAAC,CAAC;QAC7D,CAAC;QACD,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,eAAe,CAAC,2BAA2B,EAAE,IAAI,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,YAAoB;IAC1D,IAAI,CAAC,YAAY;QAAE,MAAM,IAAI,uBAAuB,CAAC,kBAAkB,CAAC,CAAC;IACzE,IAAI,YAAY,CAAC,MAAM,GAAG,IAAI;QAAE,MAAM,IAAI,uBAAuB,CAAC,eAAe,CAAC,CAAC;IACnF,IAAI,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,uBAAuB,CAAC,mBAAmB,CAAC,CAAC;IACxF,IAAI,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,uBAAuB,CAAC,oCAAoC,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,uBAAuB,CAAC,uBAAuB,CAAC,CAAC;IAC7D,CAAC;IACD,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,uBAAuB,CAAC,mCAAmC,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,uBAAuB,CAAC,8BAA8B,CAAC,CAAC;IACpE,CAAC;IACD,iFAAiF;IACjF,8EAA8E;IAC9E,+EAA+E;IAC/E,0EAA0E;IAC1E,4EAA4E;IAC5E,4EAA4E;IAC5E,8EAA8E;IAC9E,yEAAyE;AAC3E,CAAC"}
1
+ {"version":3,"file":"branch-name.js","sourceRoot":"","sources":["../../../src/modules/kb-fs/branch-name.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Whether two repository addresses name the same repository.
3
+ *
4
+ * The answer decides whether a working copy on disk is KEPT or DELETED, so it
5
+ * errs towards "same": only differences that cannot change which repository
6
+ * is meant are ignored, and they are ignored on both sides.
7
+ *
8
+ * - a trailing slash, and a `.git` suffix — hosts serve both spellings;
9
+ * - the letter case of the scheme and the host — DNS does not distinguish;
10
+ * - userinfo (`user:token@`) — who asks does not change what is asked for,
11
+ * and a credential must never decide, or appear in, a comparison.
12
+ *
13
+ * The PATH keeps its case: hosts that fold it and hosts that do not both
14
+ * exist, and treating `Org/Repo` and `org/repo` as one would keep a clone of
15
+ * the wrong repository on a host that tells them apart — but deleting a clone
16
+ * of the right one is the worse error, and an operator who only changed the
17
+ * case gets a re-clone, not a loss: the work on that clone was pushed to the
18
+ * same place.
19
+ */
20
+ export declare function normalizeRepositoryAddress(address: string): string;
21
+ export declare function sameRepository(a: string, b: string): boolean;
22
+ //# sourceMappingURL=remote-url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-url.d.ts","sourceRoot":"","sources":["../../../src/modules/kb-fs/remote-url.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAWlE;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAE5D"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Whether two repository addresses name the same repository.
3
+ *
4
+ * The answer decides whether a working copy on disk is KEPT or DELETED, so it
5
+ * errs towards "same": only differences that cannot change which repository
6
+ * is meant are ignored, and they are ignored on both sides.
7
+ *
8
+ * - a trailing slash, and a `.git` suffix — hosts serve both spellings;
9
+ * - the letter case of the scheme and the host — DNS does not distinguish;
10
+ * - userinfo (`user:token@`) — who asks does not change what is asked for,
11
+ * and a credential must never decide, or appear in, a comparison.
12
+ *
13
+ * The PATH keeps its case: hosts that fold it and hosts that do not both
14
+ * exist, and treating `Org/Repo` and `org/repo` as one would keep a clone of
15
+ * the wrong repository on a host that tells them apart — but deleting a clone
16
+ * of the right one is the worse error, and an operator who only changed the
17
+ * case gets a re-clone, not a loss: the work on that clone was pushed to the
18
+ * same place.
19
+ */
20
+ export function normalizeRepositoryAddress(address) {
21
+ let a = address.trim();
22
+ const url = /^([a-z][a-z0-9+.-]*):\/\/([^/]*)(\/.*)?$/i.exec(a);
23
+ if (url) {
24
+ const host = url[2].replace(/^[^@]*@/, '').toLowerCase();
25
+ a = `${url[1].toLowerCase()}://${host}${url[3] ?? ''}`;
26
+ }
27
+ return a
28
+ .replace(/[\\/]+$/, '')
29
+ .replace(/\.git$/i, '')
30
+ .replace(/[\\/]+$/, '');
31
+ }
32
+ export function sameRepository(a, b) {
33
+ return normalizeRepositoryAddress(a) === normalizeRepositoryAddress(b);
34
+ }
35
+ //# sourceMappingURL=remote-url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-url.js","sourceRoot":"","sources":["../../../src/modules/kb-fs/remote-url.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,0BAA0B,CAAC,OAAe;IACxD,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IACvB,MAAM,GAAG,GAAG,2CAA2C,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChE,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1D,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;IAC1D,CAAC;IACD,OAAO,CAAC;SACL,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;SACtB,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;SACtB,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,CAAS,EAAE,CAAS;IACjD,OAAO,0BAA0B,CAAC,CAAC,CAAC,KAAK,0BAA0B,CAAC,CAAC,CAAC,CAAC;AACzE,CAAC"}
@@ -1,21 +1,16 @@
1
1
  /**
2
- * Workspace-relative paths and the repository folder.
3
- *
4
- * A workspace directory holds the git clone as `<kbDirName>/` (plus transient
5
- * scratch such as `tmp/`). The agent filesystem, the lock keys and the human
6
- * editor all speak WORKSPACE-relative paths, so a path reaches git only when
7
- * it starts with that folder — and `KnowledgeBase/Foo.md` on its own names a
8
- * location BESIDE the clone, that nothing commits and nothing pushes.
9
- *
10
- * Which is why nothing on this platform resolves a workspace path for itself.
11
- * Every accepted path goes through {@link normalizeWorkspacePath} first, which
12
- * places it inside the clone; {@link assertInsideRepo} is then the check that
13
- * what came out really is in there. A route or a tool that resolved a path of
14
- * its own would be the drift this file exists to prevent — a `KnowledgeBase/`
15
- * folder, a `Plugins/` folder and eight uploaded documents sitting beside a
16
- * staging checkout is what it looked like the last time two spellings of this
17
- * rule were allowed to exist.
2
+ * Whether `value` carries one of them — THE predicate, so the places that
3
+ * accept a NAME enforce the same rule as the normaliser that joins it into a
4
+ * path. The checkout folder name is the one that matters: it is not a caller's
5
+ * path, it is deployment configuration (`KB_DIR_NAME`, and the `kbDirName`
6
+ * setting), and it is PREFIXED onto every workspace-relative path. A name with
7
+ * a line break in it would therefore make the normaliser emit exactly the path
8
+ * this rule exists to exclude, from inputs that were each clean. Refused where
9
+ * the name is set — at boot in `core-config` and in the settings validator —
10
+ * so the deployment fails loudly instead of serving a path nothing downstream
11
+ * can safely read.
18
12
  */
13
+ export declare function hasControlCharacter(value: string): boolean;
19
14
  /**
20
15
  * True when `wsPath` is the repository folder or lies under it.
21
16
  *
@@ -1 +1 @@
1
- {"version":3,"file":"repo-path.d.ts","sourceRoot":"","sources":["../../../src/modules/kb-fs/repo-path.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAKvE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAexE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAwChF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAY9E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,IAAI,CAaN;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC9F,IAAI,CAiBN;AAKD;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,GAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiBzB"}
1
+ {"version":3,"file":"repo-path.d.ts","sourceRoot":"","sources":["../../../src/modules/kb-fs/repo-path.ts"],"names":[],"mappings":"AAoDA;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CASvE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CA+BxE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CA2DhF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAY9E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,IAAI,CAaN;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC9F,IAAI,CAiBN;AAKD;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,GAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiBzB"}
@@ -1,5 +1,6 @@
1
1
  import path from 'node:path';
2
2
  import { WorkflowValidationError } from '../../shared/domain-errors.js';
3
+ import { sanitizedPath } from '../../shared/printable.js';
3
4
  /**
4
5
  * Workspace-relative paths and the repository folder.
5
6
  *
@@ -18,6 +19,49 @@ import { WorkflowValidationError } from '../../shared/domain-errors.js';
18
19
  * staging checkout is what it looked like the last time two spellings of this
19
20
  * rule were allowed to exist.
20
21
  */
22
+ /**
23
+ * NUL, the C0 controls (a line break among them) and DEL — refused in a
24
+ * workspace path wherever one enters.
25
+ *
26
+ * Not merely hygiene about names nobody can type. A `\n` is a SEPARATOR in
27
+ * git's own line-oriented stdin protocols: `cat-file --batch` reads one
28
+ * `<ref>:<path>` object name per LINE, so `Docs/secret.md\nzzz` is TWO specs.
29
+ * Everything upstream — the read gate, the download gate, the not-a-directory
30
+ * check — is then asked about the whole string, which names nothing, while git
31
+ * answers about `Docs/secret.md` and hands over its bytes. A file denied by
32
+ * its own frontmatter inside a folder its reader may list would be readable
33
+ * that way, and in a batch of several specs the extra answer shifts every
34
+ * result after it, so the access resolver reads one directory's `access.md` as
35
+ * another's.
36
+ *
37
+ * Refused HERE, at the normaliser every accepted path goes through, rather
38
+ * than at each route: the fence has to be at the mechanism, because the next
39
+ * caller to assemble a git spec from a path will not remember this. The
40
+ * shared `validateFilename` has always refused the same range per segment, so
41
+ * no name any surface can create is lost — this closes the gap between it and
42
+ * the paths that reach git. U+2028/U+2029 are NOT in it: they are nothing to
43
+ * git's protocols (which read bytes, and a line break there is 0x0A), a name
44
+ * carrying one is creatable today, and refusing it here would make an existing
45
+ * file unreadable. They are escaped for display instead, which is what
46
+ * `sanitizedPath` is for.
47
+ */
48
+ // eslint-disable-next-line no-control-regex
49
+ const CONTROL_CHARACTERS = /[\x00-\x1F\x7F]/;
50
+ /**
51
+ * Whether `value` carries one of them — THE predicate, so the places that
52
+ * accept a NAME enforce the same rule as the normaliser that joins it into a
53
+ * path. The checkout folder name is the one that matters: it is not a caller's
54
+ * path, it is deployment configuration (`KB_DIR_NAME`, and the `kbDirName`
55
+ * setting), and it is PREFIXED onto every workspace-relative path. A name with
56
+ * a line break in it would therefore make the normaliser emit exactly the path
57
+ * this rule exists to exclude, from inputs that were each clean. Refused where
58
+ * the name is set — at boot in `core-config` and in the settings validator —
59
+ * so the deployment fails loudly instead of serving a path nothing downstream
60
+ * can safely read.
61
+ */
62
+ export function hasControlCharacter(value) {
63
+ return CONTROL_CHARACTERS.test(value);
64
+ }
21
65
  /**
22
66
  * True when `wsPath` is the repository folder or lies under it.
23
67
  *
@@ -32,6 +76,11 @@ import { WorkflowValidationError } from '../../shared/domain-errors.js';
32
76
  export function isInsideRepo(wsPath, kbDirName) {
33
77
  if (typeof wsPath !== 'string' || wsPath.includes('\\'))
34
78
  return false;
79
+ // A control character is not a spelling of any path under the repository —
80
+ // see {@link CONTROL_CHARACTERS}. Refused here too, so the check AFTER the
81
+ // normaliser cannot pass one that somehow skipped it.
82
+ if (CONTROL_CHARACTERS.test(wsPath))
83
+ return false;
35
84
  const segments = wsPath.replace(/\/$/, '').split('/');
36
85
  if (segments[0] !== kbDirName)
37
86
  return false;
@@ -52,6 +101,19 @@ export function isInsideRepo(wsPath, kbDirName) {
52
101
  export function assertInsideRepo(wsPath, kbDirName) {
53
102
  if (isInsideRepo(wsPath, kbDirName))
54
103
  return;
104
+ // Said as what it is, before the suggestion below: a control character is
105
+ // not a path that landed in the wrong place, and a "use this instead"
106
+ // carrying an invisible character back to the caller would be nonsense.
107
+ if (typeof wsPath === 'string' && CONTROL_CHARACTERS.test(wsPath)) {
108
+ // Through `sanitizedPath`, like every other refusal that names a path: the
109
+ // character that makes this path invalid is also the character that would
110
+ // forge a second line of the answer, in the message and in the `path` a
111
+ // JSON consumer reads.
112
+ const shown = sanitizedPath(wsPath);
113
+ throw new WorkflowValidationError(`"${shown}" contains a control character: a line break, a NUL or another invisible byte is not part of any ` +
114
+ 'file name, and git reads a line break in a path as the end of one object name and the start of another. ' +
115
+ 'Remove it and send the name as it is written.', { kind: 'path-control-character', path: shown, kbDirName });
116
+ }
55
117
  // The suggestion collapses what made the path wrong: backslashes, leading
56
118
  // `./` or `/`, and any `..` climbing back out (a bare `..` included, so the
57
119
  // suggestion is never itself a climb). The agent gets a path it can use.
@@ -101,6 +163,23 @@ export function normalizeWorkspacePath(wsPath, kbDirName) {
101
163
  // read. Refused before anything is collapsed, never rewritten to `/`.
102
164
  if (wsPath.includes('\\'))
103
165
  refuse();
166
+ // A line break (or any other control character) is a SEPARATOR to git, not
167
+ // part of a name — see {@link CONTROL_CHARACTERS}. Refused before the path
168
+ // is normalised, so no gate downstream is ever asked about a string that
169
+ // means one thing to it and two things to git.
170
+ if (CONTROL_CHARACTERS.test(wsPath))
171
+ refuse();
172
+ // …and the FOLDER NAME, which is prefixed onto the result rather than read
173
+ // from it: a clean path joined to `kb\nname` comes out carrying the line
174
+ // break, so the normaliser would itself emit what the check above refuses.
175
+ // Said as the configuration error it is — the caller's path is fine, and an
176
+ // operator reading a refusal about their own path would have nothing to fix.
177
+ // `core-config` and the `kbDirName` setting validator both refuse this at
178
+ // the point it is SET, so reaching here means the two drifted.
179
+ if (CONTROL_CHARACTERS.test(kbDirName)) {
180
+ throw new WorkflowValidationError(`the configured checkout folder name (kbDirName / KB_DIR_NAME) contains a control character: "${sanitizedPath(kbDirName)}". ` +
181
+ 'Every workspace path is prefixed with it, so no path can be resolved until the setting is corrected.', { kind: 'kb-dir-name-control-character', kbDirName: sanitizedPath(kbDirName) });
182
+ }
104
183
  // The root-anchored form, and ONLY for the repository folder: `/<kbDirName>/…`
105
184
  // is what the app's Copy path gives (it is the form a Markdown link resolves
106
185
  // from) and names the same workspace path. `/tmp/x` and `//x` are not that