@bevel-software/platform-core-backend 0.1.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 (720) hide show
  1. package/LICENSE +202 -0
  2. package/dist/assets.d.ts +5 -0
  3. package/dist/assets.d.ts.map +1 -0
  4. package/dist/assets.js +23 -0
  5. package/dist/assets.js.map +1 -0
  6. package/dist/core/core-ports.d.ts +83 -0
  7. package/dist/core/core-ports.d.ts.map +1 -0
  8. package/dist/core/core-ports.js +12 -0
  9. package/dist/core/core-ports.js.map +1 -0
  10. package/dist/core/create-core-server.d.ts +62 -0
  11. package/dist/core/create-core-server.d.ts.map +1 -0
  12. package/dist/core/create-core-server.js +204 -0
  13. package/dist/core/create-core-server.js.map +1 -0
  14. package/dist/core/create-core-services.d.ts +95 -0
  15. package/dist/core/create-core-services.d.ts.map +1 -0
  16. package/dist/core/create-core-services.js +352 -0
  17. package/dist/core/create-core-services.js.map +1 -0
  18. package/dist/core-config.d.ts +119 -0
  19. package/dist/core-config.d.ts.map +1 -0
  20. package/dist/core-config.js +240 -0
  21. package/dist/core-config.js.map +1 -0
  22. package/dist/index.d.ts +36 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +36 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/modules/access/access-control.interface.d.ts +348 -0
  27. package/dist/modules/access/access-control.interface.d.ts.map +1 -0
  28. package/dist/modules/access/access-control.interface.js +2 -0
  29. package/dist/modules/access/access-control.interface.js.map +1 -0
  30. package/dist/modules/access/access-control.service.d.ts +323 -0
  31. package/dist/modules/access/access-control.service.d.ts.map +1 -0
  32. package/dist/modules/access/access-control.service.js +1431 -0
  33. package/dist/modules/access/access-control.service.js.map +1 -0
  34. package/dist/modules/access/access-errors.d.ts +34 -0
  35. package/dist/modules/access/access-errors.d.ts.map +1 -0
  36. package/dist/modules/access/access-errors.js +40 -0
  37. package/dist/modules/access/access-errors.js.map +1 -0
  38. package/dist/modules/access/access-mutation.service.d.ts +176 -0
  39. package/dist/modules/access/access-mutation.service.d.ts.map +1 -0
  40. package/dist/modules/access/access-mutation.service.js +307 -0
  41. package/dist/modules/access/access-mutation.service.js.map +1 -0
  42. package/dist/modules/access/access-splice.d.ts +98 -0
  43. package/dist/modules/access/access-splice.d.ts.map +1 -0
  44. package/dist/modules/access/access-splice.js +346 -0
  45. package/dist/modules/access/access-splice.js.map +1 -0
  46. package/dist/modules/access/access.routes.d.ts +10 -0
  47. package/dist/modules/access/access.routes.d.ts.map +1 -0
  48. package/dist/modules/access/access.routes.js +757 -0
  49. package/dist/modules/access/access.routes.js.map +1 -0
  50. package/dist/modules/access/creator-access.d.ts +113 -0
  51. package/dist/modules/access/creator-access.d.ts.map +1 -0
  52. package/dist/modules/access/creator-access.js +212 -0
  53. package/dist/modules/access/creator-access.js.map +1 -0
  54. package/dist/modules/access/kb-read-filter.d.ts +41 -0
  55. package/dist/modules/access/kb-read-filter.d.ts.map +1 -0
  56. package/dist/modules/access/kb-read-filter.js +60 -0
  57. package/dist/modules/access/kb-read-filter.js.map +1 -0
  58. package/dist/modules/access/roles-admin.service.d.ts +240 -0
  59. package/dist/modules/access/roles-admin.service.d.ts.map +1 -0
  60. package/dist/modules/access/roles-admin.service.js +630 -0
  61. package/dist/modules/access/roles-admin.service.js.map +1 -0
  62. package/dist/modules/access/roles-edit.d.ts +91 -0
  63. package/dist/modules/access/roles-edit.d.ts.map +1 -0
  64. package/dist/modules/access/roles-edit.js +232 -0
  65. package/dist/modules/access/roles-edit.js.map +1 -0
  66. package/dist/modules/access/roles-yaml-guard.d.ts +56 -0
  67. package/dist/modules/access/roles-yaml-guard.d.ts.map +1 -0
  68. package/dist/modules/access/roles-yaml-guard.js +79 -0
  69. package/dist/modules/access/roles-yaml-guard.js.map +1 -0
  70. package/dist/modules/admin/admin-access.routes.d.ts +18 -0
  71. package/dist/modules/admin/admin-access.routes.d.ts.map +1 -0
  72. package/dist/modules/admin/admin-access.routes.js +26 -0
  73. package/dist/modules/admin/admin-access.routes.js.map +1 -0
  74. package/dist/modules/admin/admin-access.service.d.ts +24 -0
  75. package/dist/modules/admin/admin-access.service.d.ts.map +1 -0
  76. package/dist/modules/admin/admin-access.service.js +41 -0
  77. package/dist/modules/admin/admin-access.service.js.map +1 -0
  78. package/dist/modules/admin/admin.interface.d.ts +11 -0
  79. package/dist/modules/admin/admin.interface.d.ts.map +1 -0
  80. package/dist/modules/admin/admin.interface.js +2 -0
  81. package/dist/modules/admin/admin.interface.js.map +1 -0
  82. package/dist/modules/auth/account-erasure.service.d.ts +80 -0
  83. package/dist/modules/auth/account-erasure.service.d.ts.map +1 -0
  84. package/dist/modules/auth/account-erasure.service.js +91 -0
  85. package/dist/modules/auth/account-erasure.service.js.map +1 -0
  86. package/dist/modules/auth/auth.middleware.d.ts +23 -0
  87. package/dist/modules/auth/auth.middleware.d.ts.map +1 -0
  88. package/dist/modules/auth/auth.middleware.js +68 -0
  89. package/dist/modules/auth/auth.middleware.js.map +1 -0
  90. package/dist/modules/auth/auth.routes.d.ts +25 -0
  91. package/dist/modules/auth/auth.routes.d.ts.map +1 -0
  92. package/dist/modules/auth/auth.routes.js +72 -0
  93. package/dist/modules/auth/auth.routes.js.map +1 -0
  94. package/dist/modules/auth/auth.service.d.ts +76 -0
  95. package/dist/modules/auth/auth.service.d.ts.map +1 -0
  96. package/dist/modules/auth/auth.service.js +168 -0
  97. package/dist/modules/auth/auth.service.js.map +1 -0
  98. package/dist/modules/code-mode/code-mode-names.d.ts +16 -0
  99. package/dist/modules/code-mode/code-mode-names.d.ts.map +1 -0
  100. package/dist/modules/code-mode/code-mode-names.js +30 -0
  101. package/dist/modules/code-mode/code-mode-names.js.map +1 -0
  102. package/dist/modules/code-mode/code-mode.tool.d.ts +13 -0
  103. package/dist/modules/code-mode/code-mode.tool.d.ts.map +1 -0
  104. package/dist/modules/code-mode/code-mode.tool.js +112 -0
  105. package/dist/modules/code-mode/code-mode.tool.js.map +1 -0
  106. package/dist/modules/code-mode/index.d.ts +3 -0
  107. package/dist/modules/code-mode/index.d.ts.map +1 -0
  108. package/dist/modules/code-mode/index.js +3 -0
  109. package/dist/modules/code-mode/index.js.map +1 -0
  110. package/dist/modules/database/connection.d.ts +6 -0
  111. package/dist/modules/database/connection.d.ts.map +1 -0
  112. package/dist/modules/database/connection.js +12 -0
  113. package/dist/modules/database/connection.js.map +1 -0
  114. package/dist/modules/database/core-schema.d.ts +2273 -0
  115. package/dist/modules/database/core-schema.d.ts.map +1 -0
  116. package/dist/modules/database/core-schema.js +413 -0
  117. package/dist/modules/database/core-schema.js.map +1 -0
  118. package/dist/modules/database/migrate.d.ts +10 -0
  119. package/dist/modules/database/migrate.d.ts.map +1 -0
  120. package/dist/modules/database/migrate.js +40 -0
  121. package/dist/modules/database/migrate.js.map +1 -0
  122. package/dist/modules/database/schema.d.ts +12 -0
  123. package/dist/modules/database/schema.d.ts.map +1 -0
  124. package/dist/modules/database/schema.js +12 -0
  125. package/dist/modules/database/schema.js.map +1 -0
  126. package/dist/modules/diff/diff-paths.d.ts +2 -0
  127. package/dist/modules/diff/diff-paths.d.ts.map +1 -0
  128. package/dist/modules/diff/diff-paths.js +9 -0
  129. package/dist/modules/diff/diff-paths.js.map +1 -0
  130. package/dist/modules/diff/diff.config.d.ts +8 -0
  131. package/dist/modules/diff/diff.config.d.ts.map +1 -0
  132. package/dist/modules/diff/diff.config.js +13 -0
  133. package/dist/modules/diff/diff.config.js.map +1 -0
  134. package/dist/modules/diff/diff.interface.d.ts +73 -0
  135. package/dist/modules/diff/diff.interface.d.ts.map +1 -0
  136. package/dist/modules/diff/diff.interface.js +2 -0
  137. package/dist/modules/diff/diff.interface.js.map +1 -0
  138. package/dist/modules/diff/diff.routes.d.ts +35 -0
  139. package/dist/modules/diff/diff.routes.d.ts.map +1 -0
  140. package/dist/modules/diff/diff.routes.js +228 -0
  141. package/dist/modules/diff/diff.routes.js.map +1 -0
  142. package/dist/modules/diff/diff.service.d.ts +51 -0
  143. package/dist/modules/diff/diff.service.d.ts.map +1 -0
  144. package/dist/modules/diff/diff.service.js +489 -0
  145. package/dist/modules/diff/diff.service.js.map +1 -0
  146. package/dist/modules/diff/line-diff.d.ts +16 -0
  147. package/dist/modules/diff/line-diff.d.ts.map +1 -0
  148. package/dist/modules/diff/line-diff.js +67 -0
  149. package/dist/modules/diff/line-diff.js.map +1 -0
  150. package/dist/modules/mcp/mcp-auth.middleware.d.ts +27 -0
  151. package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -0
  152. package/dist/modules/mcp/mcp-auth.middleware.js +116 -0
  153. package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -0
  154. package/dist/modules/mcp/mcp-session-store.d.ts +74 -0
  155. package/dist/modules/mcp/mcp-session-store.d.ts.map +1 -0
  156. package/dist/modules/mcp/mcp-session-store.js +131 -0
  157. package/dist/modules/mcp/mcp-session-store.js.map +1 -0
  158. package/dist/modules/mcp/mcp.routes.d.ts +24 -0
  159. package/dist/modules/mcp/mcp.routes.d.ts.map +1 -0
  160. package/dist/modules/mcp/mcp.routes.js +229 -0
  161. package/dist/modules/mcp/mcp.routes.js.map +1 -0
  162. package/dist/modules/mcp/mcp.service.d.ts +198 -0
  163. package/dist/modules/mcp/mcp.service.d.ts.map +1 -0
  164. package/dist/modules/mcp/mcp.service.js +840 -0
  165. package/dist/modules/mcp/mcp.service.js.map +1 -0
  166. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts +76 -0
  167. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -0
  168. package/dist/modules/mcp/oauth/bevel-oauth-provider.js +291 -0
  169. package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -0
  170. package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts +18 -0
  171. package/dist/modules/mcp/oauth/oauth-consent.routes.d.ts.map +1 -0
  172. package/dist/modules/mcp/oauth/oauth-consent.routes.js +52 -0
  173. package/dist/modules/mcp/oauth/oauth-consent.routes.js.map +1 -0
  174. package/dist/modules/mcp/oauth/oauth-state.d.ts +32 -0
  175. package/dist/modules/mcp/oauth/oauth-state.d.ts.map +1 -0
  176. package/dist/modules/mcp/oauth/oauth-state.js +34 -0
  177. package/dist/modules/mcp/oauth/oauth-state.js.map +1 -0
  178. package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts +92 -0
  179. package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts.map +1 -0
  180. package/dist/modules/secrets-vault/db-secrets-vault.service.js +728 -0
  181. package/dist/modules/secrets-vault/db-secrets-vault.service.js.map +1 -0
  182. package/dist/modules/secrets-vault/index.d.ts +7 -0
  183. package/dist/modules/secrets-vault/index.d.ts.map +1 -0
  184. package/dist/modules/secrets-vault/index.js +6 -0
  185. package/dist/modules/secrets-vault/index.js.map +1 -0
  186. package/dist/modules/secrets-vault/mcp-oauth-discovery.service.d.ts +63 -0
  187. package/dist/modules/secrets-vault/mcp-oauth-discovery.service.d.ts.map +1 -0
  188. package/dist/modules/secrets-vault/mcp-oauth-discovery.service.js +269 -0
  189. package/dist/modules/secrets-vault/mcp-oauth-discovery.service.js.map +1 -0
  190. package/dist/modules/secrets-vault/secrets-variable-loader.d.ts +46 -0
  191. package/dist/modules/secrets-vault/secrets-variable-loader.d.ts.map +1 -0
  192. package/dist/modules/secrets-vault/secrets-variable-loader.js +87 -0
  193. package/dist/modules/secrets-vault/secrets-variable-loader.js.map +1 -0
  194. package/dist/modules/secrets-vault/secrets-vault.contract.d.ts +210 -0
  195. package/dist/modules/secrets-vault/secrets-vault.contract.d.ts.map +1 -0
  196. package/dist/modules/secrets-vault/secrets-vault.contract.js +90 -0
  197. package/dist/modules/secrets-vault/secrets-vault.contract.js.map +1 -0
  198. package/dist/modules/secrets-vault/secrets-vault.routes.d.ts +30 -0
  199. package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -0
  200. package/dist/modules/secrets-vault/secrets-vault.routes.js +490 -0
  201. package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -0
  202. package/dist/modules/skills/index.d.ts +5 -0
  203. package/dist/modules/skills/index.d.ts.map +1 -0
  204. package/dist/modules/skills/index.js +4 -0
  205. package/dist/modules/skills/index.js.map +1 -0
  206. package/dist/modules/skills/skills.contract.d.ts +58 -0
  207. package/dist/modules/skills/skills.contract.d.ts.map +1 -0
  208. package/dist/modules/skills/skills.contract.js +10 -0
  209. package/dist/modules/skills/skills.contract.js.map +1 -0
  210. package/dist/modules/skills/skills.routes.d.ts +15 -0
  211. package/dist/modules/skills/skills.routes.d.ts.map +1 -0
  212. package/dist/modules/skills/skills.routes.js +34 -0
  213. package/dist/modules/skills/skills.routes.js.map +1 -0
  214. package/dist/modules/skills/skills.service.d.ts +21 -0
  215. package/dist/modules/skills/skills.service.d.ts.map +1 -0
  216. package/dist/modules/skills/skills.service.js +202 -0
  217. package/dist/modules/skills/skills.service.js.map +1 -0
  218. package/dist/modules/skills/skills.tools.d.ts +15 -0
  219. package/dist/modules/skills/skills.tools.d.ts.map +1 -0
  220. package/dist/modules/skills/skills.tools.js +96 -0
  221. package/dist/modules/skills/skills.tools.js.map +1 -0
  222. package/dist/modules/tool-auth/external-api-key.errors.d.ts +14 -0
  223. package/dist/modules/tool-auth/external-api-key.errors.d.ts.map +1 -0
  224. package/dist/modules/tool-auth/external-api-key.errors.js +23 -0
  225. package/dist/modules/tool-auth/external-api-key.errors.js.map +1 -0
  226. package/dist/modules/tool-auth/external-api-key.interface.d.ts +90 -0
  227. package/dist/modules/tool-auth/external-api-key.interface.d.ts.map +1 -0
  228. package/dist/modules/tool-auth/external-api-key.interface.js +2 -0
  229. package/dist/modules/tool-auth/external-api-key.interface.js.map +1 -0
  230. package/dist/modules/tool-auth/external-api-key.service.d.ts +25 -0
  231. package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -0
  232. package/dist/modules/tool-auth/external-api-key.service.js +164 -0
  233. package/dist/modules/tool-auth/external-api-key.service.js.map +1 -0
  234. package/dist/modules/tool-auth/internal-token.service.d.ts +62 -0
  235. package/dist/modules/tool-auth/internal-token.service.d.ts.map +1 -0
  236. package/dist/modules/tool-auth/internal-token.service.js +85 -0
  237. package/dist/modules/tool-auth/internal-token.service.js.map +1 -0
  238. package/dist/modules/tool-auth/llm-usage-meter.d.ts +16 -0
  239. package/dist/modules/tool-auth/llm-usage-meter.d.ts.map +1 -0
  240. package/dist/modules/tool-auth/llm-usage-meter.js +6 -0
  241. package/dist/modules/tool-auth/llm-usage-meter.js.map +1 -0
  242. package/dist/modules/tool-auth/tool-auth.middleware.d.ts +101 -0
  243. package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -0
  244. package/dist/modules/tool-auth/tool-auth.middleware.js +166 -0
  245. package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -0
  246. package/dist/modules/tool-helpers/index.d.ts +19 -0
  247. package/dist/modules/tool-helpers/index.d.ts.map +1 -0
  248. package/dist/modules/tool-helpers/index.js +18 -0
  249. package/dist/modules/tool-helpers/index.js.map +1 -0
  250. package/dist/modules/tool-helpers/tool-context.d.ts +35 -0
  251. package/dist/modules/tool-helpers/tool-context.d.ts.map +1 -0
  252. package/dist/modules/tool-helpers/tool-context.js +66 -0
  253. package/dist/modules/tool-helpers/tool-context.js.map +1 -0
  254. package/dist/modules/tool-helpers/tool-def.d.ts +33 -0
  255. package/dist/modules/tool-helpers/tool-def.d.ts.map +1 -0
  256. package/dist/modules/tool-helpers/tool-def.js +57 -0
  257. package/dist/modules/tool-helpers/tool-def.js.map +1 -0
  258. package/dist/modules/tool-helpers/tool-handler.d.ts +19 -0
  259. package/dist/modules/tool-helpers/tool-handler.d.ts.map +1 -0
  260. package/dist/modules/tool-helpers/tool-handler.js +84 -0
  261. package/dist/modules/tool-helpers/tool-handler.js.map +1 -0
  262. package/dist/modules/tool-helpers/tool.contract.d.ts +64 -0
  263. package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -0
  264. package/dist/modules/tool-helpers/tool.contract.js +24 -0
  265. package/dist/modules/tool-helpers/tool.contract.js.map +1 -0
  266. package/dist/modules/tool-helpers/validate-token.d.ts +31 -0
  267. package/dist/modules/tool-helpers/validate-token.d.ts.map +1 -0
  268. package/dist/modules/tool-helpers/validate-token.js +20 -0
  269. package/dist/modules/tool-helpers/validate-token.js.map +1 -0
  270. package/dist/modules/tool-manuals/index.d.ts +5 -0
  271. package/dist/modules/tool-manuals/index.d.ts.map +1 -0
  272. package/dist/modules/tool-manuals/index.js +5 -0
  273. package/dist/modules/tool-manuals/index.js.map +1 -0
  274. package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +182 -0
  275. package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -0
  276. package/dist/modules/tool-manuals/tool-manuals.contract.js +19 -0
  277. package/dist/modules/tool-manuals/tool-manuals.contract.js.map +1 -0
  278. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts +24 -0
  279. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts.map +1 -0
  280. package/dist/modules/tool-manuals/tool-manuals.routes.js +102 -0
  281. package/dist/modules/tool-manuals/tool-manuals.routes.js.map +1 -0
  282. package/dist/modules/tool-manuals/tool-manuals.service.d.ts +108 -0
  283. package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -0
  284. package/dist/modules/tool-manuals/tool-manuals.service.js +710 -0
  285. package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -0
  286. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +35 -0
  287. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -0
  288. package/dist/modules/tool-manuals/tool-manuals.tools.js +157 -0
  289. package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -0
  290. package/dist/modules/tool-registry/manual.routes.d.ts +6 -0
  291. package/dist/modules/tool-registry/manual.routes.d.ts.map +1 -0
  292. package/dist/modules/tool-registry/manual.routes.js +76 -0
  293. package/dist/modules/tool-registry/manual.routes.js.map +1 -0
  294. package/dist/modules/tool-registry/tool-registry.d.ts +23 -0
  295. package/dist/modules/tool-registry/tool-registry.d.ts.map +1 -0
  296. package/dist/modules/tool-registry/tool-registry.js +46 -0
  297. package/dist/modules/tool-registry/tool-registry.js.map +1 -0
  298. package/dist/modules/tool-registry/tool.contract.d.ts +48 -0
  299. package/dist/modules/tool-registry/tool.contract.d.ts.map +1 -0
  300. package/dist/modules/tool-registry/tool.contract.js +2 -0
  301. package/dist/modules/tool-registry/tool.contract.js.map +1 -0
  302. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts +14 -0
  303. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -0
  304. package/dist/modules/workflow/agent-tools/workflow.tools.js +437 -0
  305. package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -0
  306. package/dist/modules/workflow/event-bus.d.ts +107 -0
  307. package/dist/modules/workflow/event-bus.d.ts.map +1 -0
  308. package/dist/modules/workflow/event-bus.js +224 -0
  309. package/dist/modules/workflow/event-bus.js.map +1 -0
  310. package/dist/modules/workflow/events.routes.d.ts +80 -0
  311. package/dist/modules/workflow/events.routes.d.ts.map +1 -0
  312. package/dist/modules/workflow/events.routes.js +216 -0
  313. package/dist/modules/workflow/events.routes.js.map +1 -0
  314. package/dist/modules/workflow/file-change-notifier.d.ts +38 -0
  315. package/dist/modules/workflow/file-change-notifier.d.ts.map +1 -0
  316. package/dist/modules/workflow/file-change-notifier.js +22 -0
  317. package/dist/modules/workflow/file-change-notifier.js.map +1 -0
  318. package/dist/modules/workflow/file-lock.service.d.ts +57 -0
  319. package/dist/modules/workflow/file-lock.service.d.ts.map +1 -0
  320. package/dist/modules/workflow/file-lock.service.js +202 -0
  321. package/dist/modules/workflow/file-lock.service.js.map +1 -0
  322. package/dist/modules/workflow/git/branch-name.d.ts +10 -0
  323. package/dist/modules/workflow/git/branch-name.d.ts.map +1 -0
  324. package/dist/modules/workflow/git/branch-name.js +76 -0
  325. package/dist/modules/workflow/git/branch-name.js.map +1 -0
  326. package/dist/modules/workflow/git/clone-config.d.ts +61 -0
  327. package/dist/modules/workflow/git/clone-config.d.ts.map +1 -0
  328. package/dist/modules/workflow/git/clone-config.js +69 -0
  329. package/dist/modules/workflow/git/clone-config.js.map +1 -0
  330. package/dist/modules/workflow/git/git-version.d.ts +34 -0
  331. package/dist/modules/workflow/git/git-version.d.ts.map +1 -0
  332. package/dist/modules/workflow/git/git-version.js +63 -0
  333. package/dist/modules/workflow/git/git-version.js.map +1 -0
  334. package/dist/modules/workflow/git/git.service.d.ts +427 -0
  335. package/dist/modules/workflow/git/git.service.d.ts.map +1 -0
  336. package/dist/modules/workflow/git/git.service.js +1987 -0
  337. package/dist/modules/workflow/git/git.service.js.map +1 -0
  338. package/dist/modules/workflow/git/mutex.d.ts +11 -0
  339. package/dist/modules/workflow/git/mutex.d.ts.map +1 -0
  340. package/dist/modules/workflow/git/mutex.js +23 -0
  341. package/dist/modules/workflow/git/mutex.js.map +1 -0
  342. package/dist/modules/workflow/git/pull-request.service.d.ts +124 -0
  343. package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -0
  344. package/dist/modules/workflow/git/pull-request.service.js +328 -0
  345. package/dist/modules/workflow/git/pull-request.service.js.map +1 -0
  346. package/dist/modules/workflow/locking-filesystem.d.ts +133 -0
  347. package/dist/modules/workflow/locking-filesystem.d.ts.map +1 -0
  348. package/dist/modules/workflow/locking-filesystem.js +400 -0
  349. package/dist/modules/workflow/locking-filesystem.js.map +1 -0
  350. package/dist/modules/workflow/pending-commits.service.d.ts +221 -0
  351. package/dist/modules/workflow/pending-commits.service.d.ts.map +1 -0
  352. package/dist/modules/workflow/pending-commits.service.js +364 -0
  353. package/dist/modules/workflow/pending-commits.service.js.map +1 -0
  354. package/dist/modules/workflow/pending-commits.worker.d.ts +148 -0
  355. package/dist/modules/workflow/pending-commits.worker.d.ts.map +1 -0
  356. package/dist/modules/workflow/pending-commits.worker.js +245 -0
  357. package/dist/modules/workflow/pending-commits.worker.js.map +1 -0
  358. package/dist/modules/workflow/read-only-filesystem.d.ts +24 -0
  359. package/dist/modules/workflow/read-only-filesystem.d.ts.map +1 -0
  360. package/dist/modules/workflow/read-only-filesystem.js +39 -0
  361. package/dist/modules/workflow/read-only-filesystem.js.map +1 -0
  362. package/dist/modules/workflow/recovery-bot.d.ts +31 -0
  363. package/dist/modules/workflow/recovery-bot.d.ts.map +1 -0
  364. package/dist/modules/workflow/recovery-bot.js +64 -0
  365. package/dist/modules/workflow/recovery-bot.js.map +1 -0
  366. package/dist/modules/workflow/review-workflow/review-workflow.interface.d.ts +137 -0
  367. package/dist/modules/workflow/review-workflow/review-workflow.interface.d.ts.map +1 -0
  368. package/dist/modules/workflow/review-workflow/review-workflow.interface.js +2 -0
  369. package/dist/modules/workflow/review-workflow/review-workflow.interface.js.map +1 -0
  370. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts +26 -0
  371. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -0
  372. package/dist/modules/workflow/review-workflow/review-workflow.service.js +636 -0
  373. package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -0
  374. package/dist/modules/workflow/sanitize-error.d.ts +29 -0
  375. package/dist/modules/workflow/sanitize-error.d.ts.map +1 -0
  376. package/dist/modules/workflow/sanitize-error.js +60 -0
  377. package/dist/modules/workflow/sanitize-error.js.map +1 -0
  378. package/dist/modules/workflow/session-ontology.policy.d.ts +52 -0
  379. package/dist/modules/workflow/session-ontology.policy.d.ts.map +1 -0
  380. package/dist/modules/workflow/session-ontology.policy.js +62 -0
  381. package/dist/modules/workflow/session-ontology.policy.js.map +1 -0
  382. package/dist/modules/workflow/session-ontology.service.d.ts +100 -0
  383. package/dist/modules/workflow/session-ontology.service.d.ts.map +1 -0
  384. package/dist/modules/workflow/session-ontology.service.js +143 -0
  385. package/dist/modules/workflow/session-ontology.service.js.map +1 -0
  386. package/dist/modules/workflow/workflow-hooks.d.ts +87 -0
  387. package/dist/modules/workflow/workflow-hooks.d.ts.map +1 -0
  388. package/dist/modules/workflow/workflow-hooks.js +35 -0
  389. package/dist/modules/workflow/workflow-hooks.js.map +1 -0
  390. package/dist/modules/workflow/workflow.errors.d.ts +171 -0
  391. package/dist/modules/workflow/workflow.errors.d.ts.map +1 -0
  392. package/dist/modules/workflow/workflow.errors.js +260 -0
  393. package/dist/modules/workflow/workflow.errors.js.map +1 -0
  394. package/dist/modules/workflow/workflow.routes.d.ts +26 -0
  395. package/dist/modules/workflow/workflow.routes.d.ts.map +1 -0
  396. package/dist/modules/workflow/workflow.routes.js +804 -0
  397. package/dist/modules/workflow/workflow.routes.js.map +1 -0
  398. package/dist/modules/workflow/workflow.service.d.ts +385 -0
  399. package/dist/modules/workflow/workflow.service.d.ts.map +1 -0
  400. package/dist/modules/workflow/workflow.service.js +1155 -0
  401. package/dist/modules/workflow/workflow.service.js.map +1 -0
  402. package/dist/modules/workspace/bevel-ignore.d.ts +25 -0
  403. package/dist/modules/workspace/bevel-ignore.d.ts.map +1 -0
  404. package/dist/modules/workspace/bevel-ignore.js +57 -0
  405. package/dist/modules/workspace/bevel-ignore.js.map +1 -0
  406. package/dist/modules/workspace/kb-seed.interface.d.ts +36 -0
  407. package/dist/modules/workspace/kb-seed.interface.d.ts.map +1 -0
  408. package/dist/modules/workspace/kb-seed.interface.js +2 -0
  409. package/dist/modules/workspace/kb-seed.interface.js.map +1 -0
  410. package/dist/modules/workspace/kb-seed.service.d.ts +70 -0
  411. package/dist/modules/workspace/kb-seed.service.d.ts.map +1 -0
  412. package/dist/modules/workspace/kb-seed.service.js +325 -0
  413. package/dist/modules/workspace/kb-seed.service.js.map +1 -0
  414. package/dist/modules/workspace/routine-write-policy.d.ts +49 -0
  415. package/dist/modules/workspace/routine-write-policy.d.ts.map +1 -0
  416. package/dist/modules/workspace/routine-write-policy.js +46 -0
  417. package/dist/modules/workspace/routine-write-policy.js.map +1 -0
  418. package/dist/modules/workspace/session-ontology.gate.d.ts +112 -0
  419. package/dist/modules/workspace/session-ontology.gate.d.ts.map +1 -0
  420. package/dist/modules/workspace/session-ontology.gate.js +161 -0
  421. package/dist/modules/workspace/session-ontology.gate.js.map +1 -0
  422. package/dist/modules/workspace/session-sink.d.ts +25 -0
  423. package/dist/modules/workspace/session-sink.d.ts.map +1 -0
  424. package/dist/modules/workspace/session-sink.js +8 -0
  425. package/dist/modules/workspace/session-sink.js.map +1 -0
  426. package/dist/modules/workspace/spill-store.d.ts +24 -0
  427. package/dist/modules/workspace/spill-store.d.ts.map +1 -0
  428. package/dist/modules/workspace/spill-store.js +87 -0
  429. package/dist/modules/workspace/spill-store.js.map +1 -0
  430. package/dist/modules/workspace/workspace.routes.d.ts +25 -0
  431. package/dist/modules/workspace/workspace.routes.d.ts.map +1 -0
  432. package/dist/modules/workspace/workspace.routes.js +1046 -0
  433. package/dist/modules/workspace/workspace.routes.js.map +1 -0
  434. package/dist/modules/workspace/workspace.service.d.ts +339 -0
  435. package/dist/modules/workspace/workspace.service.d.ts.map +1 -0
  436. package/dist/modules/workspace/workspace.service.js +1221 -0
  437. package/dist/modules/workspace/workspace.service.js.map +1 -0
  438. package/dist/modules/workspace/workspace.tools.d.ts +19 -0
  439. package/dist/modules/workspace/workspace.tools.d.ts.map +1 -0
  440. package/dist/modules/workspace/workspace.tools.js +767 -0
  441. package/dist/modules/workspace/workspace.tools.js.map +1 -0
  442. package/dist/shared/frontmatter-id.d.ts +35 -0
  443. package/dist/shared/frontmatter-id.d.ts.map +1 -0
  444. package/dist/shared/frontmatter-id.js +68 -0
  445. package/dist/shared/frontmatter-id.js.map +1 -0
  446. package/dist/shared/fs-walk.d.ts +9 -0
  447. package/dist/shared/fs-walk.d.ts.map +1 -0
  448. package/dist/shared/fs-walk.js +34 -0
  449. package/dist/shared/fs-walk.js.map +1 -0
  450. package/dist/shared/hash-email.d.ts +11 -0
  451. package/dist/shared/hash-email.d.ts.map +1 -0
  452. package/dist/shared/hash-email.js +14 -0
  453. package/dist/shared/hash-email.js.map +1 -0
  454. package/dist/shared/kb-layout.d.ts +38 -0
  455. package/dist/shared/kb-layout.d.ts.map +1 -0
  456. package/dist/shared/kb-layout.js +102 -0
  457. package/dist/shared/kb-layout.js.map +1 -0
  458. package/dist/shared/kb-layout.test.d.ts +2 -0
  459. package/dist/shared/kb-layout.test.d.ts.map +1 -0
  460. package/dist/shared/kb-layout.test.js +67 -0
  461. package/dist/shared/kb-layout.test.js.map +1 -0
  462. package/dist/shared/ssrf.d.ts +20 -0
  463. package/dist/shared/ssrf.d.ts.map +1 -0
  464. package/dist/shared/ssrf.js +89 -0
  465. package/dist/shared/ssrf.js.map +1 -0
  466. package/dist/shared/token-crypto.d.ts +16 -0
  467. package/dist/shared/token-crypto.d.ts.map +1 -0
  468. package/dist/shared/token-crypto.js +49 -0
  469. package/dist/shared/token-crypto.js.map +1 -0
  470. package/dist/shared/ttl-cache.d.ts +16 -0
  471. package/dist/shared/ttl-cache.d.ts.map +1 -0
  472. package/dist/shared/ttl-cache.js +27 -0
  473. package/dist/shared/ttl-cache.js.map +1 -0
  474. package/dist/shared/utcp-namespace.d.ts +46 -0
  475. package/dist/shared/utcp-namespace.d.ts.map +1 -0
  476. package/dist/shared/utcp-namespace.js +82 -0
  477. package/dist/shared/utcp-namespace.js.map +1 -0
  478. package/dist/version.d.ts +17 -0
  479. package/dist/version.d.ts.map +1 -0
  480. package/dist/version.js +19 -0
  481. package/dist/version.js.map +1 -0
  482. package/kb-template/.bevelignore +21 -0
  483. package/kb-template/Agents/.gitkeep +0 -0
  484. package/kb-template/Agents/README.md +38 -0
  485. package/kb-template/CLAUDE.md +419 -0
  486. package/kb-template/Data/.gitkeep +0 -0
  487. package/kb-template/Data/README.md +39 -0
  488. package/kb-template/KnowledgeBase/.gitkeep +0 -0
  489. package/kb-template/KnowledgeBase/README.md +37 -0
  490. package/kb-template/Pipelines/.gitkeep +0 -0
  491. package/kb-template/Pipelines/README.md +38 -0
  492. package/kb-template/Skills/.gitkeep +0 -0
  493. package/kb-template/Skills/README.md +32 -0
  494. package/kb-template/Tools/.gitkeep +0 -0
  495. package/kb-template/Tools/README.md +42 -0
  496. package/kb-template/access.md +36 -0
  497. package/migrations/0000_core_init.sql +243 -0
  498. package/migrations/meta/0000_snapshot.json +1480 -0
  499. package/migrations/meta/_journal.json +13 -0
  500. package/package.json +80 -0
  501. package/src/assets.ts +25 -0
  502. package/src/core/core-ports.ts +91 -0
  503. package/src/core/create-core-server.ts +338 -0
  504. package/src/core/create-core-services.ts +501 -0
  505. package/src/core-config.ts +257 -0
  506. package/src/index.ts +69 -0
  507. package/src/modules/access/__tests__/access-control.atref-batch.test.ts +98 -0
  508. package/src/modules/access/__tests__/access-control.read-batch.test.ts +132 -0
  509. package/src/modules/access/__tests__/access-control.service.test.ts +1011 -0
  510. package/src/modules/access/__tests__/access-mutation.service.test.ts +439 -0
  511. package/src/modules/access/__tests__/access-splice.test.ts +247 -0
  512. package/src/modules/access/__tests__/access.routes.revoke.test.ts +407 -0
  513. package/src/modules/access/__tests__/creator-access.test.ts +217 -0
  514. package/src/modules/access/__tests__/grant-sources.test.ts +204 -0
  515. package/src/modules/access/__tests__/kb-read-filter.test.ts +70 -0
  516. package/src/modules/access/__tests__/roles-admin.service.test.ts +469 -0
  517. package/src/modules/access/__tests__/roles-edit.test.ts +138 -0
  518. package/src/modules/access/__tests__/roles-yaml-guard.test.ts +70 -0
  519. package/src/modules/access/__tests__/roles.routes.test.ts +234 -0
  520. package/src/modules/access/access-control.interface.ts +383 -0
  521. package/src/modules/access/access-control.service.ts +1794 -0
  522. package/src/modules/access/access-errors.ts +60 -0
  523. package/src/modules/access/access-mutation.service.ts +369 -0
  524. package/src/modules/access/access-splice.ts +413 -0
  525. package/src/modules/access/access.routes.ts +894 -0
  526. package/src/modules/access/creator-access.ts +270 -0
  527. package/src/modules/access/kb-read-filter.ts +76 -0
  528. package/src/modules/access/roles-admin.service.ts +741 -0
  529. package/src/modules/access/roles-edit.ts +248 -0
  530. package/src/modules/access/roles-yaml-guard.ts +89 -0
  531. package/src/modules/admin/admin-access.routes.ts +29 -0
  532. package/src/modules/admin/admin-access.service.ts +38 -0
  533. package/src/modules/admin/admin.interface.ts +10 -0
  534. package/src/modules/auth/account-erasure.service.ts +183 -0
  535. package/src/modules/auth/auth.middleware.ts +78 -0
  536. package/src/modules/auth/auth.routes.ts +97 -0
  537. package/src/modules/auth/auth.service.ts +199 -0
  538. package/src/modules/code-mode/code-mode-names.ts +38 -0
  539. package/src/modules/code-mode/code-mode.tool.ts +117 -0
  540. package/src/modules/code-mode/index.ts +6 -0
  541. package/src/modules/database/connection.ts +15 -0
  542. package/src/modules/database/core-schema.ts +431 -0
  543. package/src/modules/database/migrate.ts +43 -0
  544. package/src/modules/database/schema.ts +11 -0
  545. package/src/modules/diff/__tests__/diff.routes.read-gate.test.ts +87 -0
  546. package/src/modules/diff/__tests__/diff.routes.rejectPathsLocked.test.ts +150 -0
  547. package/src/modules/diff/__tests__/diff.service.seed-atomicity.test.ts +184 -0
  548. package/src/modules/diff/__tests__/diff.service.test.ts +202 -0
  549. package/src/modules/diff/diff-paths.ts +9 -0
  550. package/src/modules/diff/diff.config.ts +12 -0
  551. package/src/modules/diff/diff.interface.ts +78 -0
  552. package/src/modules/diff/diff.routes.ts +277 -0
  553. package/src/modules/diff/diff.service.ts +508 -0
  554. package/src/modules/diff/line-diff.ts +79 -0
  555. package/src/modules/mcp/__tests__/bevel-oauth-provider.test.ts +287 -0
  556. package/src/modules/mcp/__tests__/mcp-auth.middleware.test.ts +249 -0
  557. package/src/modules/mcp/__tests__/mcp-proxy-helpers.test.ts +253 -0
  558. package/src/modules/mcp/__tests__/mcp-session-store.test.ts +151 -0
  559. package/src/modules/mcp/__tests__/mcp.e2e.test.ts +150 -0
  560. package/src/modules/mcp/__tests__/mcp.routes.delete.test.ts +92 -0
  561. package/src/modules/mcp/__tests__/mcp.service.test.ts +414 -0
  562. package/src/modules/mcp/mcp-auth.middleware.ts +126 -0
  563. package/src/modules/mcp/mcp-session-store.ts +162 -0
  564. package/src/modules/mcp/mcp.routes.ts +263 -0
  565. package/src/modules/mcp/mcp.service.ts +973 -0
  566. package/src/modules/mcp/oauth/bevel-oauth-provider.ts +401 -0
  567. package/src/modules/mcp/oauth/oauth-consent.routes.ts +60 -0
  568. package/src/modules/mcp/oauth/oauth-state.ts +61 -0
  569. package/src/modules/secrets-vault/__tests__/connect-pending.route.test.ts +277 -0
  570. package/src/modules/secrets-vault/__tests__/db-secrets-vault.oauth.test.ts +206 -0
  571. package/src/modules/secrets-vault/__tests__/mcp-oauth-discovery.service.test.ts +178 -0
  572. package/src/modules/secrets-vault/__tests__/scopes-covered.test.ts +101 -0
  573. package/src/modules/secrets-vault/__tests__/secrets-variable-loader.test.ts +54 -0
  574. package/src/modules/secrets-vault/__tests__/tool-owner-gate.route.test.ts +143 -0
  575. package/src/modules/secrets-vault/db-secrets-vault.service.ts +792 -0
  576. package/src/modules/secrets-vault/index.ts +25 -0
  577. package/src/modules/secrets-vault/mcp-oauth-discovery.service.ts +289 -0
  578. package/src/modules/secrets-vault/secrets-variable-loader.ts +104 -0
  579. package/src/modules/secrets-vault/secrets-vault.contract.ts +270 -0
  580. package/src/modules/secrets-vault/secrets-vault.routes.ts +526 -0
  581. package/src/modules/skills/__tests__/skills.service.test.ts +176 -0
  582. package/src/modules/skills/index.ts +10 -0
  583. package/src/modules/skills/skills.contract.ts +54 -0
  584. package/src/modules/skills/skills.routes.ts +38 -0
  585. package/src/modules/skills/skills.service.ts +245 -0
  586. package/src/modules/skills/skills.tools.ts +121 -0
  587. package/src/modules/tool-auth/__tests__/external-api-key.service.test.ts +358 -0
  588. package/src/modules/tool-auth/__tests__/internal-token.service.test.ts +79 -0
  589. package/src/modules/tool-auth/__tests__/manual-auth.middleware.test.ts +88 -0
  590. package/src/modules/tool-auth/external-api-key.errors.ts +25 -0
  591. package/src/modules/tool-auth/external-api-key.interface.ts +99 -0
  592. package/src/modules/tool-auth/external-api-key.service.ts +209 -0
  593. package/src/modules/tool-auth/internal-token.service.ts +124 -0
  594. package/src/modules/tool-auth/llm-usage-meter.ts +19 -0
  595. package/src/modules/tool-auth/tool-auth.middleware.ts +220 -0
  596. package/src/modules/tool-helpers/__tests__/phase0-loopback-spike.test.ts +129 -0
  597. package/src/modules/tool-helpers/__tests__/phase4-tools.test.ts +95 -0
  598. package/src/modules/tool-helpers/__tests__/tools-surface.test.ts +146 -0
  599. package/src/modules/tool-helpers/__tests__/validate-token.test.ts +75 -0
  600. package/src/modules/tool-helpers/index.ts +18 -0
  601. package/src/modules/tool-helpers/tool-context.ts +98 -0
  602. package/src/modules/tool-helpers/tool-def.ts +73 -0
  603. package/src/modules/tool-helpers/tool-handler.ts +91 -0
  604. package/src/modules/tool-helpers/tool.contract.ts +85 -0
  605. package/src/modules/tool-helpers/validate-token.ts +50 -0
  606. package/src/modules/tool-manuals/__tests__/tool-manuals.mcp-oauth.test.ts +200 -0
  607. package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +499 -0
  608. package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +156 -0
  609. package/src/modules/tool-manuals/index.ts +12 -0
  610. package/src/modules/tool-manuals/tool-manuals.contract.ts +183 -0
  611. package/src/modules/tool-manuals/tool-manuals.routes.ts +110 -0
  612. package/src/modules/tool-manuals/tool-manuals.service.ts +781 -0
  613. package/src/modules/tool-manuals/tool-manuals.tools.ts +202 -0
  614. package/src/modules/tool-registry/__tests__/tool-registry.test.ts +64 -0
  615. package/src/modules/tool-registry/manual.routes.ts +87 -0
  616. package/src/modules/tool-registry/tool-registry.ts +55 -0
  617. package/src/modules/tool-registry/tool.contract.ts +52 -0
  618. package/src/modules/workflow/__tests__/event-bus.test.ts +322 -0
  619. package/src/modules/workflow/__tests__/file-change-notifier.test.ts +51 -0
  620. package/src/modules/workflow/__tests__/format-affected-owners.test.ts +67 -0
  621. package/src/modules/workflow/__tests__/locking-filesystem.test.ts +445 -0
  622. package/src/modules/workflow/__tests__/pending-commits.canonical.test.ts +36 -0
  623. package/src/modules/workflow/__tests__/pending-commits.worker.test.ts +243 -0
  624. package/src/modules/workflow/__tests__/preserve-roles-yaml.test.ts +308 -0
  625. package/src/modules/workflow/__tests__/sanitize-error.test.ts +67 -0
  626. package/src/modules/workflow/__tests__/session-ontology.policy.test.ts +62 -0
  627. package/src/modules/workflow/__tests__/session-ontology.service.test.ts +200 -0
  628. package/src/modules/workflow/__tests__/workflow.service.commitFileWhileLocked.test.ts +232 -0
  629. package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +380 -0
  630. package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +340 -0
  631. package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +192 -0
  632. package/src/modules/workflow/agent-tools/workflow.tools.ts +502 -0
  633. package/src/modules/workflow/event-bus.ts +262 -0
  634. package/src/modules/workflow/events.routes.ts +266 -0
  635. package/src/modules/workflow/file-change-notifier.ts +54 -0
  636. package/src/modules/workflow/file-lock.service.ts +269 -0
  637. package/src/modules/workflow/git/__tests__/branch-name.test.ts +86 -0
  638. package/src/modules/workflow/git/__tests__/branchAuthor.test.ts +80 -0
  639. package/src/modules/workflow/git/__tests__/clone-config.test.ts +15 -0
  640. package/src/modules/workflow/git/__tests__/git-test-helpers.ts +47 -0
  641. package/src/modules/workflow/git/__tests__/git-version.failure.test.ts +24 -0
  642. package/src/modules/workflow/git/__tests__/git-version.test.ts +49 -0
  643. package/src/modules/workflow/git/__tests__/git.service.accessGating.test.ts +389 -0
  644. package/src/modules/workflow/git/__tests__/git.service.changedFilesForPr.test.ts +124 -0
  645. package/src/modules/workflow/git/__tests__/git.service.commitChanges.test.ts +105 -0
  646. package/src/modules/workflow/git/__tests__/git.service.commitFile.test.ts +211 -0
  647. package/src/modules/workflow/git/__tests__/git.service.createBranch.test.ts +154 -0
  648. package/src/modules/workflow/git/__tests__/git.service.deleteBranch.test.ts +320 -0
  649. package/src/modules/workflow/git/__tests__/git.service.diffFileAtCommit.test.ts +202 -0
  650. package/src/modules/workflow/git/__tests__/git.service.diffFileBetweenBranches.test.ts +453 -0
  651. package/src/modules/workflow/git/__tests__/git.service.list-branches.test.ts +198 -0
  652. package/src/modules/workflow/git/__tests__/git.service.listTrackedFiles.test.ts +125 -0
  653. package/src/modules/workflow/git/__tests__/git.service.logForFile.test.ts +219 -0
  654. package/src/modules/workflow/git/__tests__/git.service.mergeChangeRequest.test.ts +145 -0
  655. package/src/modules/workflow/git/__tests__/git.service.pendingChanges.test.ts +240 -0
  656. package/src/modules/workflow/git/__tests__/git.service.postMergePull.test.ts +272 -0
  657. package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +232 -0
  658. package/src/modules/workflow/git/__tests__/git.service.readFileAtRef.test.ts +101 -0
  659. package/src/modules/workflow/git/__tests__/git.service.status.test.ts +127 -0
  660. package/src/modules/workflow/git/__tests__/mutex.test.ts +78 -0
  661. package/src/modules/workflow/git/__tests__/pull-request.service.test.ts +225 -0
  662. package/src/modules/workflow/git/__tests__/pull-request.service.viewer-can-cancel.test.ts +101 -0
  663. package/src/modules/workflow/git/branch-name.ts +70 -0
  664. package/src/modules/workflow/git/clone-config.ts +71 -0
  665. package/src/modules/workflow/git/git-version.ts +70 -0
  666. package/src/modules/workflow/git/git.service.ts +2248 -0
  667. package/src/modules/workflow/git/mutex.ts +22 -0
  668. package/src/modules/workflow/git/pull-request.service.ts +447 -0
  669. package/src/modules/workflow/locking-filesystem.ts +489 -0
  670. package/src/modules/workflow/pending-commits.service.ts +444 -0
  671. package/src/modules/workflow/pending-commits.worker.ts +361 -0
  672. package/src/modules/workflow/read-only-filesystem.ts +54 -0
  673. package/src/modules/workflow/recovery-bot.ts +73 -0
  674. package/src/modules/workflow/review-workflow/__tests__/approval-states.test.ts +560 -0
  675. package/src/modules/workflow/review-workflow/__tests__/cancel-pr.test.ts +176 -0
  676. package/src/modules/workflow/review-workflow/__tests__/merge-gate.test.ts +258 -0
  677. package/src/modules/workflow/review-workflow/review-workflow.interface.ts +199 -0
  678. package/src/modules/workflow/review-workflow/review-workflow.service.ts +806 -0
  679. package/src/modules/workflow/sanitize-error.ts +62 -0
  680. package/src/modules/workflow/session-ontology.policy.ts +70 -0
  681. package/src/modules/workflow/session-ontology.service.ts +178 -0
  682. package/src/modules/workflow/workflow-hooks.ts +101 -0
  683. package/src/modules/workflow/workflow.errors.ts +285 -0
  684. package/src/modules/workflow/workflow.routes.ts +858 -0
  685. package/src/modules/workflow/workflow.service.ts +1555 -0
  686. package/src/modules/workspace/__tests__/kb-seed.service.test.ts +213 -0
  687. package/src/modules/workspace/__tests__/routine-write-policy.test.ts +68 -0
  688. package/src/modules/workspace/__tests__/session-ontology.gate.test.ts +237 -0
  689. package/src/modules/workspace/__tests__/spill-store.test.ts +43 -0
  690. package/src/modules/workspace/__tests__/workspace.routes.create-grant.test.ts +233 -0
  691. package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +176 -0
  692. package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +303 -0
  693. package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +276 -0
  694. package/src/modules/workspace/__tests__/workspace.service.read-filter.test.ts +120 -0
  695. package/src/modules/workspace/__tests__/workspace.service.test.ts +565 -0
  696. package/src/modules/workspace/__tests__/workspace.tools.test.ts +504 -0
  697. package/src/modules/workspace/bevel-ignore.ts +62 -0
  698. package/src/modules/workspace/kb-seed.interface.ts +36 -0
  699. package/src/modules/workspace/kb-seed.service.ts +361 -0
  700. package/src/modules/workspace/routine-write-policy.ts +79 -0
  701. package/src/modules/workspace/session-ontology.gate.ts +189 -0
  702. package/src/modules/workspace/session-sink.ts +25 -0
  703. package/src/modules/workspace/spill-store.ts +87 -0
  704. package/src/modules/workspace/workspace.routes.ts +1114 -0
  705. package/src/modules/workspace/workspace.service.ts +1343 -0
  706. package/src/modules/workspace/workspace.tools.ts +885 -0
  707. package/src/shared/__tests__/frontmatter-id.test.ts +88 -0
  708. package/src/shared/__tests__/fs-walk.test.ts +42 -0
  709. package/src/shared/__tests__/ssrf.test.ts +53 -0
  710. package/src/shared/__tests__/utcp-namespace.test.ts +19 -0
  711. package/src/shared/frontmatter-id.ts +72 -0
  712. package/src/shared/fs-walk.ts +30 -0
  713. package/src/shared/hash-email.ts +14 -0
  714. package/src/shared/kb-layout.test.ts +88 -0
  715. package/src/shared/kb-layout.ts +101 -0
  716. package/src/shared/ssrf.ts +78 -0
  717. package/src/shared/token-crypto.ts +54 -0
  718. package/src/shared/ttl-cache.ts +27 -0
  719. package/src/shared/utcp-namespace.ts +88 -0
  720. package/src/version.ts +19 -0
@@ -0,0 +1,504 @@
1
+ import type { Server as HttpServer } from 'node:http';
2
+ import { execFile } from 'node:child_process';
3
+ import { mkdir, mkdtemp, rm } from 'node:fs/promises';
4
+ import { tmpdir } from 'node:os';
5
+ import { join } from 'node:path';
6
+ import { promisify } from 'node:util';
7
+ import express from 'express';
8
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
9
+ import { LocalFilesystem } from '@mastra/core/workspace';
10
+ import { ToolRegistry } from '../../tool-registry/tool-registry.js';
11
+ import { createToolHandlerFactory } from '../../tool-helpers/tool-handler.js';
12
+ import type { ToolContext } from '../../tool-helpers/tool.contract.js';
13
+ import type { ToolAuth } from '../../tool-auth/tool-auth.middleware.js';
14
+ import { registerWorkspaceTools } from '../workspace.tools.js';
15
+ import { RoutineWritePolicyService } from '../routine-write-policy.js';
16
+ import { WorkflowHooks } from '../../workflow/workflow-hooks.js';
17
+ import { SpillStore } from '../spill-store.js';
18
+ import type { IAccessControl } from '../../access/access-control.interface.js';
19
+
20
+ const KB_DIR = 'knowledge-base';
21
+
22
+ /** Allow-all access control — the default for tests not exercising read gating. */
23
+ const allowAll = {
24
+ canRead: async () => true,
25
+ canReadBatch: async (_w: string, _u: string, paths: string[]) =>
26
+ new Map(paths.map((p) => [p, true])),
27
+ } as unknown as IAccessControl;
28
+
29
+ /** Access control that denies `canRead` for an explicit set of repo-relative paths. */
30
+ function denyReads(denied: Set<string>): IAccessControl {
31
+ return {
32
+ canRead: async (_w: string, _u: string, rel: string) => !denied.has(rel),
33
+ canReadBatch: async (_w: string, _u: string, paths: string[]) =>
34
+ new Map(paths.map((p) => [p, !denied.has(p)])),
35
+ } as unknown as IAccessControl;
36
+ }
37
+
38
+ /**
39
+ * File primitives over a REAL LocalFilesystem on a temp dir — proves read_file /
40
+ * write_file / edit_file / list_files / grep / file_stat / execute_command
41
+ * actually work (the handlers re-expose the same filesystem methods Mastra
42
+ * uses). No locking pipeline (plain LocalFilesystem), so writes don't commit.
43
+ */
44
+
45
+ let httpServer: HttpServer | undefined;
46
+ let tempDir = '';
47
+ let fs: LocalFilesystem;
48
+ /**
49
+ * Every branch / workspaceId `execute_command`'s handler resolves a workspace
50
+ * for. Resolving a workspace is what triggers the lazy per-branch CLONE in
51
+ * production, so asserting this never contains `"undefined"` proves the
52
+ * missing-branch guard short-circuits before any clone of a branch literally
53
+ * named "undefined" is attempted.
54
+ */
55
+ let workspacePathCalls: string[] = [];
56
+ /** The policy instance the tools were mounted with, so a test can restrict a session. */
57
+ let writePolicy: RoutineWritePolicyService;
58
+
59
+ async function start(
60
+ scope: 'read' | 'write' = 'write',
61
+ access: IAccessControl = allowAll,
62
+ ): Promise<string> {
63
+ tempDir = await mkdtemp(join(tmpdir(), 'ws-tools-'));
64
+ fs = new LocalFilesystem({ basePath: tempDir, contained: true });
65
+ await fs.writeFile('a.md', 'hello\nworld\n');
66
+ workspacePathCalls = [];
67
+ writePolicy = new RoutineWritePolicyService();
68
+
69
+ const registry = new ToolRegistry();
70
+ const resolve = async (auth: ToolAuth, signal: AbortSignal, sessionId?: string): Promise<ToolContext> => ({
71
+ user: { id: 'u', email: 'e@x', name: 'N' },
72
+ scope: auth.scope,
73
+ source: auth.source,
74
+ sessionId,
75
+ abortSignal: signal,
76
+ workspaceService: {
77
+ // Both entry points record, so the guard tests prove NEITHER resolves a
78
+ // workspace for an invalid branch.
79
+ getOrCreateForBranch: async (branch: string) => {
80
+ workspacePathCalls.push(branch);
81
+ return { id: encodeURIComponent(branch), name: branch, absolutePath: tempDir, createdAt: '', kbDirName: KB_DIR };
82
+ },
83
+ getWorkspacePath: async (id: string) => {
84
+ workspacePathCalls.push(id);
85
+ return tempDir;
86
+ },
87
+ } as never,
88
+ workflowService: {} as never,
89
+ events: {} as never,
90
+ getFilesystem: async () => fs,
91
+ });
92
+ const toolHandler = createToolHandlerFactory(resolve);
93
+ const fakeAuth = (req: express.Request, _res: express.Response, next: express.NextFunction) => {
94
+ req.toolAuth = { source: 'internal', userId: 'u', scope };
95
+ next();
96
+ };
97
+ const app = express();
98
+ app.use(express.json());
99
+ const router = express.Router();
100
+ registerWorkspaceTools(registry, router, fakeAuth, toolHandler, new SpillStore(join(tmpdir(), 'bevel-test-spills')), access, KB_DIR, {
101
+ service: {} as never,
102
+ enabled: false, // these tests predate and don't exercise the ontology boundary
103
+ kbDirName: KB_DIR,
104
+ recoveryBotEmail: 'recovery-bot@bevel.local',
105
+ hooks: new WorkflowHooks(),
106
+ }, writePolicy, {} as never /* sessionSink — start_session not exercised here */);
107
+ app.use('/api', router);
108
+ httpServer = await new Promise<HttpServer>((r) => {
109
+ const s = app.listen(0, () => r(s));
110
+ });
111
+ return `http://127.0.0.1:${(httpServer.address() as { port: number }).port}`;
112
+ }
113
+
114
+ const post = (url: string, body: unknown = {}) =>
115
+ fetch(url, { method: 'POST', headers: { 'content-type': 'application/json', authorization: 'Bearer x' }, body: JSON.stringify(body) });
116
+
117
+ beforeEach(() => {
118
+ /* fresh per test via start() */
119
+ });
120
+ afterEach(async () => {
121
+ if (httpServer) await new Promise<void>((r) => httpServer!.close(() => r()));
122
+ httpServer = undefined;
123
+ if (tempDir) {
124
+ await rm(tempDir, { recursive: true, force: true });
125
+ tempDir = '';
126
+ }
127
+ });
128
+
129
+ describe('workspace file primitives', () => {
130
+ it('read_file returns the content', async () => {
131
+ const base = await start();
132
+ expect(await (await post(`${base}/api/agent/tools/read_file`, { path: 'a.md' })).json()).toEqual({ path: 'a.md', content: 'hello\nworld\n' });
133
+ });
134
+
135
+ it('write_file then read_file round-trips', async () => {
136
+ const base = await start();
137
+ await post(`${base}/api/agent/tools/write_file`, { path: 'b.md', content: 'fresh' });
138
+ expect(await (await post(`${base}/api/agent/tools/read_file`, { path: 'b.md' })).json()).toMatchObject({ content: 'fresh' });
139
+ });
140
+
141
+ it('edit_file replaces an exact unique string', async () => {
142
+ const base = await start();
143
+ const res = await post(`${base}/api/agent/tools/edit_file`, { path: 'a.md', old_string: 'world', new_string: 'earth' });
144
+ expect(await res.json()).toMatchObject({ path: 'a.md', replaced: 1 });
145
+ expect(await (await post(`${base}/api/agent/tools/read_file`, { path: 'a.md' })).json()).toMatchObject({ content: 'hello\nearth\n' });
146
+ });
147
+
148
+ it('edit_file 400s when old_string is missing', async () => {
149
+ const base = await start();
150
+ expect((await post(`${base}/api/agent/tools/edit_file`, { path: 'a.md', old_string: 'nope', new_string: 'x' })).status).toBe(400);
151
+ });
152
+
153
+ it('list_files + file_stat', async () => {
154
+ const base = await start();
155
+ const list = (await (await post(`${base}/api/agent/tools/list_files`, {})).json()) as { entries: { name: string }[] };
156
+ expect(list.entries.map((e) => e.name)).toContain('a.md');
157
+ expect(await (await post(`${base}/api/agent/tools/file_stat`, { path: 'a.md' })).json()).toMatchObject({ type: 'file' });
158
+ });
159
+
160
+ it('grep finds a match with line number', async () => {
161
+ const base = await start();
162
+ const res = (await (await post(`${base}/api/agent/tools/grep`, { pattern: 'wor' })).json()) as { matches: { path: string; line: number }[] };
163
+ expect(res.matches).toContainEqual(expect.objectContaining({ path: 'a.md', line: 2 }));
164
+ });
165
+
166
+ it('execute_command runs in the workspace dir', async () => {
167
+ const base = await start();
168
+ const res = (await (await post(`${base}/api/agent/tools/execute_command`, { branch: 'main', command: 'echo hello-exec' })).json()) as { stdout: string; exitCode: number };
169
+ expect(res.stdout).toContain('hello-exec');
170
+ expect(res.exitCode).toBe(0);
171
+ });
172
+
173
+ it('execute_command 400s when no branch is given (never clones "undefined")', async () => {
174
+ const base = await start();
175
+ // A missing branch must NOT resolve the workspace id to "undefined" and try
176
+ // to clone a branch literally named "undefined" — it must fail closed with a
177
+ // clear 4xx naming the missing branch context, BEFORE any workspace resolve.
178
+ const res = await post(`${base}/api/agent/tools/execute_command`, { command: 'echo should-not-run' });
179
+ expect(res.status).toBe(400);
180
+ expect((await res.json()).error).toMatch(/branch/i);
181
+ // The guard runs before `getWorkspacePath`, so no workspace (least of all the
182
+ // "undefined" one) is ever resolved — proving no clone is attempted.
183
+ expect(workspacePathCalls).toEqual([]);
184
+ });
185
+
186
+ // Every branch value that must fail closed without resolving a workspace.
187
+ // `''` (like the missing field above) is refused a layer earlier by the input
188
+ // schema's `minLength: 1`; the rest satisfy the schema and reach the handler,
189
+ // so they exercise the guard itself. Both layers must produce the same 400.
190
+ // The malformed refs below are rejected by the shared `assertValidBranchName`,
191
+ // which replaced the hand-listed "undefined"/"null" reservations: those are
192
+ // legal git branch names, and the bug PR #285 fixed was an ABSENT `branch`
193
+ // (caught by the missing/non-string check above), not a caller that says
194
+ // "undefined" on purpose.
195
+ const invalidBranches: Array<[label: string, branch: string]> = [
196
+ ['empty', ''],
197
+ ['whitespace-only', ' '],
198
+ ['whitespace-padded', ' main '],
199
+ ['containing a space', 'alice/my draft'],
200
+ ['containing ".."', 'alice/../../etc'],
201
+ ['starting with "-"', '--upload-pack=touch'],
202
+ ['containing "//"', 'alice//draft'],
203
+ ['ending with "/"', 'alice/'],
204
+ ['a segment starting with "."', 'alice/.hidden'],
205
+ ['a segment ending with ".lock"', 'alice/draft.lock'],
206
+ ['containing "@{"', 'alice/draft@{0}'],
207
+ ['containing a shell metacharacter', 'alice/draft;rm -rf /'],
208
+ ];
209
+ for (const [label, branch] of invalidBranches) {
210
+ it(`execute_command 400s when branch is ${label}`, async () => {
211
+ const base = await start();
212
+ const res = await post(`${base}/api/agent/tools/execute_command`, { branch, command: 'echo should-not-run' });
213
+ expect(res.status).toBe(400);
214
+ expect((await res.json()).error).toMatch(/branch/i);
215
+ // No workspace is resolved for the bad value — proving no clone is attempted.
216
+ expect(workspacePathCalls).toEqual([]);
217
+ });
218
+ }
219
+
220
+ it('execute_command accepts a branch git itself considers valid (no literal-name reservations)', async () => {
221
+ const base = await start();
222
+ // "undefined"/"null" used to be hand-reserved here. They're ordinary branch
223
+ // names as far as git is concerned, and the real PR #285 guard is the
224
+ // missing/non-string check — so the validator must let them through.
225
+ for (const branch of ['undefined', 'null']) {
226
+ const res = (await (await post(`${base}/api/agent/tools/execute_command`, { branch, command: 'echo ok' })).json()) as { stdout: string; exitCode: number };
227
+ expect(res.exitCode).toBe(0);
228
+ }
229
+ expect(workspacePathCalls).toEqual(['undefined', 'null']);
230
+ });
231
+
232
+ it('execute_command validates the branch BEFORE the write-policy gate', async () => {
233
+ const base = await start();
234
+ // A routine-restricted session is refused by `assertUnrestricted` with 403.
235
+ // The branch guard must still run first, so a malformed call gets the 400
236
+ // that names the bad context instead of a 403 masking it.
237
+ writePolicy.restrictToExtensions('restricted-run', ['.html']);
238
+ const res = await post(`${base}/api/agent/tools/execute_command`, {
239
+ branch: 'alice/../../etc',
240
+ command: 'echo should-not-run',
241
+ sessionId: 'restricted-run',
242
+ });
243
+ expect(res.status).toBe(400);
244
+ expect((await res.json()).error).toMatch(/branch/i);
245
+ expect(workspacePathCalls).toEqual([]);
246
+ // …and the restriction really is live for that session (so the 400 above is
247
+ // the guard winning the race, not an inert policy).
248
+ const gated = await post(`${base}/api/agent/tools/execute_command`, {
249
+ branch: 'main',
250
+ command: 'echo should-not-run',
251
+ sessionId: 'restricted-run',
252
+ });
253
+ expect(gated.status).toBe(403);
254
+ });
255
+
256
+ it('execute_command bootstraps the workspace through getOrCreateForBranch', async () => {
257
+ const base = await start();
258
+ // Per-branch bootstrap is the service's job: the shell passes the branch
259
+ // itself rather than hand-encoding a workspace id.
260
+ await post(`${base}/api/agent/tools/execute_command`, { branch: 'alice/draft', command: 'echo hi' });
261
+ expect(workspacePathCalls).toEqual(['alice/draft']);
262
+ });
263
+
264
+ it('execute_command runs plain git against the nested KB clone', async () => {
265
+ const base = await start();
266
+ // Production layout: the repo lives one level BELOW the shell's cwd, at
267
+ // <workspace>/<kbDirName>/.git. A bare `git …` (what the agent prompt
268
+ // teaches) must still target that clone instead of failing with
269
+ // "not a git repository".
270
+ const execFileAsync = promisify(execFile);
271
+ const repoDir = join(tempDir, KB_DIR);
272
+ await mkdir(repoDir, { recursive: true });
273
+ await execFileAsync('git', ['init'], { cwd: repoDir });
274
+ await execFileAsync(
275
+ 'git',
276
+ ['-c', 'user.email=t@test', '-c', 'user.name=t', 'commit', '--allow-empty', '-m', 'kb-seed'],
277
+ { cwd: repoDir },
278
+ );
279
+ const res = (await (await post(`${base}/api/agent/tools/execute_command`, { branch: 'main', command: 'git log -1 --format=%s' })).json()) as { stdout: string; stderr: string; exitCode: number };
280
+ expect(res.exitCode).toBe(0);
281
+ expect(res.stdout.trim()).toBe('kb-seed');
282
+ });
283
+
284
+ it('execute_command does not leak GIT_DIR into non-git commands', async () => {
285
+ const base = await start();
286
+ // The KB-clone GIT_DIR/GIT_WORK_TREE override is scoped to bare `git …`
287
+ // only; a non-git command (e.g. npm/pip that shells git internally) must
288
+ // NOT inherit it, or the nested git child would target the KB clone.
289
+ const res = (await (await post(`${base}/api/agent/tools/execute_command`, { branch: 'main', command: 'echo "GIT_DIR=[$GIT_DIR]"' })).json()) as { stdout: string; stderr: string; exitCode: number };
290
+ expect(res.exitCode).toBe(0);
291
+ expect(res.stdout.trim()).toBe('GIT_DIR=[]');
292
+ });
293
+
294
+ it('execute_command does not leak GIT_DIR into a chained step after git', async () => {
295
+ const base = await start();
296
+ // Runs under `shell: true`, so a command that merely STARTS with git but
297
+ // chains another step must not export the KB git env to the whole shell —
298
+ // otherwise `git … && npm ci` would leak the KB repo context into the npm/pip
299
+ // git subprocess. `git --version` needs no repo, so exit stays 0.
300
+ const res = (await (await post(`${base}/api/agent/tools/execute_command`, { branch: 'main', command: 'git --version >/dev/null && echo "leak=[$GIT_DIR]"' })).json()) as { stdout: string; stderr: string; exitCode: number };
301
+ expect(res.exitCode).toBe(0);
302
+ expect(res.stdout.trim()).toBe('leak=[]');
303
+ });
304
+
305
+ it('read scope refuses write tools (403) but allows reads', async () => {
306
+ const base = await start('read');
307
+ expect((await post(`${base}/api/agent/tools/write_file`, { path: 'c.md', content: 'x' })).status).toBe(403);
308
+ expect((await post(`${base}/api/agent/tools/read_file`, { path: 'a.md' })).status).toBe(200);
309
+ });
310
+ });
311
+
312
+ describe('read-permission gating', () => {
313
+ // Seed two KB nodes; the access stub denies read on the "secret" one.
314
+ async function startGated(): Promise<string> {
315
+ const base = await start('write', denyReads(new Set([`Knowledge/Secret.md`])));
316
+ await fs.writeFile(`${KB_DIR}/Knowledge/Public.md`, 'public body\nneedle\n');
317
+ await fs.writeFile(`${KB_DIR}/Knowledge/Secret.md`, 'secret body\nneedle\n');
318
+ return base;
319
+ }
320
+
321
+ it('read_file denies an unreadable KB node with 403', async () => {
322
+ const base = await startGated();
323
+ expect((await post(`${base}/api/agent/tools/read_file`, { path: `${KB_DIR}/Knowledge/Secret.md` })).status).toBe(403);
324
+ expect((await post(`${base}/api/agent/tools/read_file`, { path: `${KB_DIR}/Knowledge/Public.md` })).status).toBe(200);
325
+ });
326
+
327
+ it('list_files hides unreadable KB nodes but keeps readable ones', async () => {
328
+ const base = await startGated();
329
+ const list = (await (await post(`${base}/api/agent/tools/list_files`, { path: `${KB_DIR}/Knowledge` })).json()) as {
330
+ entries: { name: string }[];
331
+ };
332
+ const names = list.entries.map((e) => e.name);
333
+ expect(names).toContain('Public.md');
334
+ expect(names).not.toContain('Secret.md');
335
+ });
336
+
337
+ it('grep never returns a line from an unreadable KB node', async () => {
338
+ const base = await startGated();
339
+ const res = (await (await post(`${base}/api/agent/tools/grep`, { pattern: 'needle', path: KB_DIR })).json()) as {
340
+ matches: { path: string }[];
341
+ };
342
+ const paths = res.matches.map((m) => m.path);
343
+ expect(paths).toContain(`${KB_DIR}/Knowledge/Public.md`);
344
+ expect(paths).not.toContain(`${KB_DIR}/Knowledge/Secret.md`);
345
+ });
346
+
347
+ it('non-KB workspace files are never gated', async () => {
348
+ // `a.md` lives at the workspace root, outside the KB dir → always readable.
349
+ const base = await start('read', denyReads(new Set(['a.md'])));
350
+ expect((await post(`${base}/api/agent/tools/read_file`, { path: 'a.md' })).status).toBe(200);
351
+ });
352
+ });
353
+
354
+ /**
355
+ * start_session must mint a REAL chat thread and return its id (not a bare
356
+ * random UUID), so the same id works for KB reads AND for `ask` (whose
357
+ * sessionId IS a chat thread). This is what unifies the ontology boundary
358
+ * across reads + ask — see workspace.tools.ts start_session comment.
359
+ */
360
+ describe('start_session', () => {
361
+ // Minimal harness: own app + a fake ISessionSink that records createSession.
362
+ let server: HttpServer | undefined;
363
+ let created: Array<{ userId: string; startedAt: Date }> = [];
364
+
365
+ async function startSessionApp(source: 'external' | 'internal' = 'external'): Promise<string> {
366
+ created = [];
367
+ const registry = new ToolRegistry();
368
+ const resolve = async (auth: ToolAuth, signal: AbortSignal): Promise<ToolContext> => ({
369
+ user: { id: 'user-42', email: 'e@x', name: 'N' },
370
+ scope: auth.scope,
371
+ source: auth.source,
372
+ abortSignal: signal,
373
+ workspaceService: {} as never,
374
+ workflowService: {} as never,
375
+ events: {} as never,
376
+ getFilesystem: async () => ({}) as never,
377
+ });
378
+ const toolHandler = createToolHandlerFactory(resolve);
379
+ const auth = (req: express.Request, _res: express.Response, next: express.NextFunction) => {
380
+ req.toolAuth = { source, userId: 'user-42', scope: 'write' };
381
+ next();
382
+ };
383
+ // Fake ISessionSink: record the call, return a fixed session id.
384
+ const fakeSessionSink = {
385
+ createSession: async (userId: string, startedAt: Date) => {
386
+ created.push({ userId, startedAt });
387
+ return { sessionId: 'thread-xyz' };
388
+ },
389
+ };
390
+
391
+ const app = express();
392
+ app.use(express.json());
393
+ const router = express.Router();
394
+ registerWorkspaceTools(
395
+ registry, router, auth, toolHandler,
396
+ new SpillStore(join(tmpdir(), 'bevel-test-spills')), allowAll, KB_DIR,
397
+ { service: {} as never, enabled: false, kbDirName: KB_DIR, recoveryBotEmail: 'recovery-bot@bevel.local', hooks: new WorkflowHooks() },
398
+ new RoutineWritePolicyService(),
399
+ fakeSessionSink,
400
+ );
401
+ app.use('/api', router);
402
+ server = await new Promise<HttpServer>((r) => {
403
+ const s = app.listen(0, () => r(s));
404
+ });
405
+ return `http://127.0.0.1:${(server.address() as { port: number }).port}`;
406
+ }
407
+
408
+ afterEach(async () => {
409
+ if (server) await new Promise<void>((r) => server!.close(() => r()));
410
+ server = undefined;
411
+ });
412
+
413
+ it('returns the sink-minted id as sessionId', async () => {
414
+ const base = await startSessionApp();
415
+ const res = (await (await post(`${base}/api/agent/tools/start_session`)).json()) as { sessionId: string };
416
+ expect(res.sessionId).toBe('thread-xyz');
417
+ });
418
+
419
+ it('mints the session for the authenticated user', async () => {
420
+ const base = await startSessionApp();
421
+ await post(`${base}/api/agent/tools/start_session`);
422
+ expect(created).toHaveLength(1);
423
+ expect(created[0].userId).toBe('user-42');
424
+ expect(created[0].startedAt).toBeInstanceOf(Date);
425
+ });
426
+
427
+ it('rejects an internal-source caller (external-only) so an agent cannot mint a session mid-run', async () => {
428
+ // Note: an OAuth/JWT MCP session is NOT this case — its `externalProxy`
429
+ // loopback token resolves to source 'external' at the verifier (see
430
+ // tool-auth), so it is admitted here like any external agent.
431
+ const base = await startSessionApp('internal');
432
+ const res = await post(`${base}/api/agent/tools/start_session`);
433
+ expect(res.status).toBe(403);
434
+ expect(created).toHaveLength(0);
435
+ });
436
+ });
437
+
438
+ /**
439
+ * Contract-level guarantee: `branch` is a REQUIRED input on every workspace tool
440
+ * def, on BOTH the internal and external manuals — one convention everywhere, so
441
+ * the caller always names the branch (there is no implied "current" workspace).
442
+ * This is what stops a call from ever resolving a `undefined` workspace at the
443
+ * schema layer, complementing the handler-level guard exercised above.
444
+ */
445
+ describe('branch is a required parameter in the tool contract', () => {
446
+ /** Register the workspace tools into a fresh registry (no server needed). */
447
+ function buildRegistry(): ToolRegistry {
448
+ const registry = new ToolRegistry();
449
+ const router = express.Router();
450
+ const noopAuth: express.RequestHandler = (_req, _res, next) => next();
451
+ // The handler factory is only invoked to build routes; its output is never
452
+ // called in this test, so a no-op express handler suffices.
453
+ const toolHandler = (() => () => {}) as never;
454
+ registerWorkspaceTools(
455
+ registry,
456
+ router,
457
+ noopAuth,
458
+ toolHandler,
459
+ new SpillStore(join(tmpdir(), 'bevel-test-spills')),
460
+ allowAll,
461
+ KB_DIR,
462
+ { service: {} as never, enabled: false, kbDirName: KB_DIR, recoveryBotEmail: 'recovery-bot@bevel.local', hooks: new WorkflowHooks() },
463
+ new RoutineWritePolicyService(),
464
+ {} as never,
465
+ );
466
+ return registry;
467
+ }
468
+
469
+ /** The flat input schema's `required` list (unwrapping `toolDef`'s `{ body }` envelope). */
470
+ function bodyRequired(tool: { inputs?: unknown } | undefined): string[] {
471
+ const inputs = tool?.inputs as { properties?: { body?: { required?: string[] } } } | undefined;
472
+ return inputs?.properties?.body?.required ?? [];
473
+ }
474
+
475
+ it('execute_command declares branch required on the INTERNAL manual', async () => {
476
+ const internal = await buildRegistry().listInternal();
477
+ const exec = internal.find((t) => t.name === 'execute_command');
478
+ expect(exec).toBeDefined();
479
+ expect(bodyRequired(exec)).toContain('branch');
480
+ expect(bodyRequired(exec)).toContain('command');
481
+ });
482
+
483
+ it('execute_command is internal-only — never advertised on the external manual', async () => {
484
+ const external = await buildRegistry().listExternal();
485
+ expect(external.find((t) => t.name === 'execute_command')).toBeUndefined();
486
+ });
487
+
488
+ it('every workspace file tool requires branch on BOTH manuals (one convention everywhere)', async () => {
489
+ const registry = buildRegistry();
490
+ const [internal, external] = await Promise.all([registry.listInternal(), registry.listExternal()]);
491
+ const fileTools = [
492
+ 'read_file', 'write_file', 'write_files', 'edit_file', 'delete_file',
493
+ 'mkdir', 'move_file', 'copy_file', 'list_files', 'file_stat', 'grep', 'unzip',
494
+ ];
495
+ for (const name of fileTools) {
496
+ const int = internal.find((t) => t.name === name);
497
+ const ext = external.find((t) => t.name === name);
498
+ expect(int, `${name} should be on the internal manual`).toBeDefined();
499
+ expect(ext, `${name} should be on the external manual`).toBeDefined();
500
+ expect(bodyRequired(int), `${name} internal requires branch`).toContain('branch');
501
+ expect(bodyRequired(ext), `${name} external requires branch`).toContain('branch');
502
+ }
503
+ });
504
+ });
@@ -0,0 +1,62 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import ignore, { type Ignore } from 'ignore';
4
+
5
+ const IGNORE_FILENAME = '.bevelignore';
6
+
7
+ /** One .bevelignore file's rules, scoped to the directory it lives in. */
8
+ interface IgnoreLayer {
9
+ /** Absolute path of the directory where the .bevelignore lives. */
10
+ readonly root: string;
11
+ readonly matcher: Ignore;
12
+ }
13
+
14
+ /**
15
+ * A hierarchical stack of `.bevelignore` rule sets.
16
+ *
17
+ * Each `.bevelignore` file applies to paths beneath the directory it lives in,
18
+ * using standard gitignore syntax (negations, `**`, directory-only patterns, anchoring).
19
+ * Deeper files combine with — and can override — rules from shallower files,
20
+ * mirroring how git layers `.gitignore` files.
21
+ */
22
+ export class BevelIgnoreStack {
23
+ private constructor(private readonly layers: readonly IgnoreLayer[]) {}
24
+
25
+ static empty(): BevelIgnoreStack {
26
+ return new BevelIgnoreStack([]);
27
+ }
28
+
29
+ /**
30
+ * Return a new stack that additionally includes a `.bevelignore` from `dir`
31
+ * (if present). If no `.bevelignore` exists in `dir`, returns this stack unchanged.
32
+ */
33
+ async extendedWith(dir: string): Promise<BevelIgnoreStack> {
34
+ const file = path.join(dir, IGNORE_FILENAME);
35
+ let contents: string;
36
+ try {
37
+ contents = await fs.readFile(file, 'utf-8');
38
+ } catch {
39
+ return this;
40
+ }
41
+ const matcher = ignore().add(contents);
42
+ return new BevelIgnoreStack([...this.layers, { root: dir, matcher }]);
43
+ }
44
+
45
+ /**
46
+ * Whether the given entry should be hidden from the file tree.
47
+ * @param absolutePath absolute path of the entry
48
+ * @param isDirectory needed because gitignore patterns ending in `/` match directories only
49
+ */
50
+ isIgnored(absolutePath: string, isDirectory: boolean): boolean {
51
+ for (const layer of this.layers) {
52
+ const rel = path.relative(layer.root, absolutePath).replace(/\\/g, '/');
53
+ // Skip entries that aren't under this layer's root (shouldn't happen in normal
54
+ // recursion, but guards against absolute-path quirks on Windows).
55
+ if (!rel || rel.startsWith('..')) continue;
56
+ // Append trailing slash for directories so `foo/`-style rules match correctly.
57
+ const probe = isDirectory ? `${rel}/` : rel;
58
+ if (layer.matcher.ignores(probe)) return true;
59
+ }
60
+ return false;
61
+ }
62
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Bootstraps the KB *remote* so the rest of the app's assumption — that the KB
3
+ * repo it clones already carries the protected branches and base scaffolding —
4
+ * holds even for a brand-new (or partially-populated) GitHub repo.
5
+ *
6
+ * The platform used to require the KB remote to have been forked from the
7
+ * standalone `knowledge-base-template` repo. That template now ships inside the
8
+ * platform (`kb-template/` at the repo root) and this service seeds from it.
9
+ */
10
+ export interface IKbSeedService {
11
+ /**
12
+ * Ensure the KB remote can be cloned: seed a fully-empty repo, and make sure
13
+ * every protected branch exists as a ref (so `clone -b <branch>` succeeds).
14
+ * Idempotent and single-flight — safe to await before every clone; the real
15
+ * work runs at most once per process.
16
+ *
17
+ * - **Empty remote** → full seed: all template files (incl. the sample
18
+ * ontology) committed to every protected branch. Requires `SEED_ADMIN_EMAILS`
19
+ * (a repo with no Admin is unusable), otherwise throws.
20
+ * - **Existing remote** → create only the protected branches that don't exist
21
+ * yet, off an existing one. No file changes here — per-branch base files are
22
+ * filled in by {@link topUpWorkspace} when a branch is loaded.
23
+ */
24
+ ensureRemoteSeeded(): Promise<void>;
25
+
26
+ /**
27
+ * Fill in any missing base scaffolding on the freshly-cloned workspace of the
28
+ * branch a user just loaded, then commit + push it to that branch. Add-only —
29
+ * never overwrites existing files, and never restores the sample ontology.
30
+ * Best-effort: never throws, so a top-up hiccup can't block loading the branch.
31
+ *
32
+ * @param repoDir Absolute path to the checked-out KB clone for `branch`.
33
+ * @param branch The branch that clone is on (the push target).
34
+ */
35
+ topUpWorkspace(repoDir: string, branch: string): Promise<void>;
36
+ }