@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,414 @@
1
+ import type { Server as HttpServer } from 'node:http';
2
+ import express from 'express';
3
+ import { afterEach, describe, expect, it } from 'vitest';
4
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
5
+ import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';
6
+ import { tmpdir } from 'node:os';
7
+ import { join } from 'node:path';
8
+ import { McpService } from '../mcp.service.js';
9
+ import { McpSessionStore } from '../mcp-session-store.js';
10
+ import { SpillStore } from '../../workspace/spill-store.js';
11
+ import { createManualRoutes } from '../../tool-registry/manual.routes.js';
12
+ import { ToolRegistry } from '../../tool-registry/tool-registry.js';
13
+ import { toolDef } from '../../tool-helpers/tool-def.js';
14
+
15
+ /**
16
+ * End-to-end proxy test: a real express app serving the registry-driven tool
17
+ * surface over loopback, a real per-session `UtcpClient` discovering it, and a
18
+ * real MCP `Client` driving the proxy over an in-memory transport. Exercises
19
+ * discovery, prefix stripping, schema/args passthrough, dispatch, result
20
+ * mapping, and error translation — without any UTCP/MCP fakes.
21
+ */
22
+
23
+ let httpServer: HttpServer | undefined;
24
+ const cleanups: Array<() => Promise<void>> = [];
25
+
26
+ // Module-hosted tool endpoints + their registered defs: a stand-in echo `ask`
27
+ // (mirrors the real `{text, sessionId}` contract) and an erroring `boom`.
28
+ async function setup(deps?: {
29
+ secretsVault?: unknown;
30
+ toolManuals?: unknown;
31
+ /** Session auth kind: a connection-key id (default), or null for an OAuth/JWT session. */
32
+ tokenId?: string | null;
33
+ /** Spy for the session-grant reset fired on broken sign-ins. */
34
+ revokeOAuthAccess?: (bearer: string) => Promise<void>;
35
+ }) {
36
+ const registry = new ToolRegistry();
37
+ registry.registerExternalTool(
38
+ toolDef({
39
+ name: 'ask',
40
+ description: 'echo the prompt',
41
+ path: '/api/agent/tools/ask',
42
+ inputs: {
43
+ type: 'object',
44
+ properties: { prompt: { type: 'string' }, sessionId: { type: 'string' } },
45
+ required: ['prompt'],
46
+ },
47
+ }),
48
+ );
49
+ registry.registerExternalTool(
50
+ toolDef({ name: 'boom', description: 'always errors', path: '/api/agent/tools/boom', inputs: { type: 'object', properties: {} } }),
51
+ );
52
+ // A tool whose input schema uses $defs/$ref — the shape Google's gmail/calendar
53
+ // MCP servers emit. It must survive the whole pipe (discover → flatten → list)
54
+ // and be accepted by a real MCP client, with the refs inlined out.
55
+ registry.registerExternalTool(
56
+ toolDef({
57
+ name: 'refy',
58
+ description: 'has $defs/$ref in its schema',
59
+ path: '/api/agent/tools/refy',
60
+ inputs: {
61
+ type: 'object',
62
+ $defs: { Recipient: { type: 'object', properties: { email: { type: 'string' } }, required: ['email'] } },
63
+ properties: { to: { type: 'array', items: { $ref: '#/$defs/Recipient' } } },
64
+ required: ['to'],
65
+ } as never,
66
+ }),
67
+ );
68
+
69
+ const app = express();
70
+ app.use(express.json());
71
+ const noAuth: express.RequestHandler = (_req, _res, next) => next();
72
+ app.post('/api/agent/tools/ask', (req, res) => {
73
+ const b = (req.body ?? {}) as { prompt?: string; sessionId?: string };
74
+ res.json({ text: `echo: ${b.prompt}`, sessionId: typeof b.sessionId === 'string' ? b.sessionId : 'new-sess' });
75
+ });
76
+ app.post('/api/agent/tools/boom', (_req, res) => res.status(500).json({ error: 'kaboom' }));
77
+ app.use('/api', createManualRoutes(registry, noAuth));
78
+ httpServer = await new Promise<HttpServer>((resolve) => {
79
+ const s = app.listen(0, () => resolve(s));
80
+ });
81
+ const port = (httpServer.address() as { port: number }).port;
82
+
83
+ const mcp = new McpService(
84
+ new McpSessionStore(),
85
+ {
86
+ loopbackBaseUrl: `http://127.0.0.1:${port}`,
87
+ manualName: 'KNOWLEDGE_BASE',
88
+ spillStore: new SpillStore(join(tmpdir(), 'bevel-test-spills')),
89
+ publicFrontendUrl: 'http://localhost:5173',
90
+ },
91
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
92
+ deps?.secretsVault as any,
93
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
94
+ deps?.toolManuals as any,
95
+ undefined, // internalTokens — the fake loopback here accepts any bearer
96
+ deps?.revokeOAuthAccess,
97
+ );
98
+ const tokenId = deps?.tokenId === undefined ? 'tok-1' : deps.tokenId;
99
+ const { server } = await mcp.createSession('user-A', tokenId, 'bevel_testkey', () => {});
100
+
101
+ const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
102
+ await server.connect(serverTransport);
103
+ const client = new Client({ name: 'test-client', version: '0.0.0' }, { capabilities: {} });
104
+ await client.connect(clientTransport);
105
+
106
+ cleanups.push(async () => {
107
+ await client.close();
108
+ await server.close();
109
+ });
110
+ return client;
111
+ }
112
+
113
+ afterEach(async () => {
114
+ for (const c of cleanups.splice(0)) await c().catch(() => {});
115
+ if (httpServer) await new Promise<void>((r) => httpServer!.close(() => r()));
116
+ httpServer = undefined;
117
+ });
118
+
119
+ describe('McpService (UTCP→MCP proxy)', () => {
120
+ it('lists the discovered tools with clean (prefix-stripped) schemas, envelope intact', async () => {
121
+ const client = await setup();
122
+ const { tools } = await client.listTools();
123
+ const byName = Object.fromEntries(tools.map((t) => [t.name, t]));
124
+
125
+ // The direct tools, plus the always-present code-mode meta-tools.
126
+ expect(Object.keys(byName).sort()).toEqual(['ask', 'boom', 'call_tool_chain', 'list_tools', 'refy', 'tools_info']);
127
+ // The manual's schema passes through verbatim: KB tools advertise the same
128
+ // {body} envelope UTCP dispatches on (and that call_tool_chain documents).
129
+ const askSchema = byName.ask.inputSchema as { properties: { body?: { properties?: Record<string, unknown> } } };
130
+ expect(askSchema.properties.body?.properties?.prompt).toBeDefined();
131
+ });
132
+
133
+ it('a $defs/$ref tool schema survives tools/list and a real MCP client accepts it', async () => {
134
+ // No tokenId filter for this assertion — an OAuth-style session lists all.
135
+ const client = await setup({ tokenId: null });
136
+ const { tools } = await client.listTools(); // throws if the SDK client rejects the payload
137
+ const refy = tools.find((t) => t.name === 'refy')!;
138
+ expect(refy).toBeDefined();
139
+ // Whatever became of the refs, none may leak to the client — an Anthropic-
140
+ // backed client rejects the ENTIRE tools/list over one $ref/$defs.
141
+ const schema = JSON.stringify(refy.inputSchema);
142
+ expect(schema).not.toContain('$ref');
143
+ expect(schema).not.toContain('$defs');
144
+ });
145
+
146
+ it('list_tools returns the discovered tools in TS-accessible form', async () => {
147
+ const client = await setup();
148
+ const res = await client.callTool({ name: 'list_tools', arguments: {} });
149
+ const parsed = JSON.parse((res.content as Array<{ text: string }>)[0].text);
150
+ expect(parsed.tools).toContain('KNOWLEDGE_BASE.ask');
151
+ expect(parsed.tools).toContain('KNOWLEDGE_BASE.boom');
152
+ });
153
+
154
+ it('call_tool_chain runs TS that invokes a real tool over loopback', async () => {
155
+ const client = await setup();
156
+ const res = await client.callTool({
157
+ name: 'call_tool_chain',
158
+ arguments: { code: "return KNOWLEDGE_BASE.ask({ body: { prompt: 'hi' } });" },
159
+ });
160
+ const parsed = JSON.parse((res.content as Array<{ text: string }>)[0].text);
161
+ expect(parsed.success).toBe(true);
162
+ // The chain executed in the isolated-vm, called the ask endpoint over
163
+ // loopback with the caller's key, and returned its echo result.
164
+ expect(parsed.result).toMatchObject({ text: 'echo: hi' });
165
+ });
166
+
167
+ it('dispatches a tool call back through the REST endpoint and returns its result text', async () => {
168
+ const client = await setup();
169
+ const res = await client.callTool({ name: 'ask', arguments: { body: { prompt: 'hello' } } });
170
+ // The whole structured result is stringified, so both the answer text and the
171
+ // sessionId a client must echo back to poll survive (no collapsing to `text`).
172
+ const payload = JSON.parse((res.content as Array<{ text: string }>)[0].text);
173
+ expect(payload.text).toBe('echo: hello');
174
+ expect(payload.sessionId).toBe('new-sess');
175
+ expect(res.isError).toBeFalsy();
176
+ });
177
+
178
+ it('translates a downstream tool failure into an MCP isError result', async () => {
179
+ const client = await setup();
180
+ const res = await client.callTool({ name: 'boom', arguments: {} });
181
+ expect(res.isError).toBe(true);
182
+ expect((res.content as Array<{ text: string }>)[0].text).toMatch(/boom/i);
183
+ });
184
+
185
+ it('returns an isError result for an unknown tool', async () => {
186
+ const client = await setup();
187
+ const res = await client.callTool({ name: 'ghost', arguments: {} });
188
+ expect(res.isError).toBe(true);
189
+ });
190
+ });
191
+
192
+ describe('McpService — per-user credential pre-check', () => {
193
+ // The discovered `ask`/`boom` tools live under the `KNOWLEDGE_BASE` manual, so
194
+ // these stubs answer as if that manual declared a per-user variable.
195
+ const vault = (userConfigured: boolean, userAuthorized?: boolean, grantedScopes?: string) => ({
196
+ statusFor: async (_userId: string, keys: string[]) =>
197
+ keys.map((key) => ({ key, adminConfigured: false, userConfigured, userAuthorized, grantedScopes })),
198
+ });
199
+ const manualsWithUserVar = {
200
+ userScopedKeysForManual: async (manual: string) =>
201
+ manual === 'KNOWLEDGE_BASE'
202
+ ? [{ key: 'KNOWLEDGE_BASE_API_KEY', name: 'API_KEY', label: 'Your API key', oauth: false }]
203
+ : [],
204
+ };
205
+ const manualsWithOAuthVar = {
206
+ userScopedKeysForManual: async (manual: string) =>
207
+ manual === 'KNOWLEDGE_BASE'
208
+ ? [{ key: 'KNOWLEDGE_BASE_GOOGLE', name: 'GOOGLE', label: 'Google', oauth: true }]
209
+ : [],
210
+ };
211
+ // An OAuth var that requires two scopes — for the scope-coverage cases.
212
+ const manualsWithScopedOAuthVar = {
213
+ userScopedKeysForManual: async (manual: string) =>
214
+ manual === 'KNOWLEDGE_BASE'
215
+ ? [
216
+ {
217
+ key: 'KNOWLEDGE_BASE_GOOGLE',
218
+ name: 'GOOGLE',
219
+ label: 'Google',
220
+ oauth: true,
221
+ oauthScopes: ['openid', 'https://www.googleapis.com/auth/calendar.readonly'],
222
+ },
223
+ ]
224
+ : [],
225
+ };
226
+ const manualsNoUserVar = {
227
+ userScopedKeysForManual: async () =>
228
+ [] as { key: string; name: string; label: string | null; oauth: boolean }[],
229
+ };
230
+
231
+ it('gates a tool whose personal credential is unset — returns the setup link, not the tool', async () => {
232
+ const client = await setup({ secretsVault: vault(false), toolManuals: manualsWithUserVar });
233
+ const res = await client.callTool({ name: 'ask', arguments: { body: { prompt: 'hello' } } });
234
+ expect(res.isError).toBe(true);
235
+ const text = (res.content as Array<{ text: string }>)[0].text;
236
+ expect(text).toMatch(/ask/); // names the tool
237
+ expect(text).toMatch(/Your API key/); // names the missing item by label
238
+ expect(text).toContain('http://localhost:5173/connect'); // the setup link
239
+ // Crucially, it did NOT run the tool (no echo payload).
240
+ expect(text).not.toMatch(/echo:/);
241
+ });
242
+
243
+ it('lets the tool run once every personal credential is set', async () => {
244
+ const client = await setup({ secretsVault: vault(true), toolManuals: manualsWithUserVar });
245
+ const res = await client.callTool({ name: 'ask', arguments: { body: { prompt: 'hello' } } });
246
+ expect(res.isError).toBeFalsy();
247
+ const payload = JSON.parse((res.content as Array<{ text: string }>)[0].text);
248
+ expect(payload.text).toBe('echo: hello');
249
+ });
250
+
251
+ it('never gates a tool whose manual declares no personal credential', async () => {
252
+ const client = await setup({ secretsVault: vault(false), toolManuals: manualsNoUserVar });
253
+ const res = await client.callTool({ name: 'ask', arguments: { body: { prompt: 'hi' } } });
254
+ expect(res.isError).toBeFalsy();
255
+ expect(JSON.parse((res.content as Array<{ text: string }>)[0].text).text).toBe('echo: hi');
256
+ });
257
+
258
+ it('skips the check entirely when the vault/manual services are not wired', async () => {
259
+ const client = await setup(); // no deps → check is a no-op
260
+ const res = await client.callTool({ name: 'ask', arguments: { body: { prompt: 'hi' } } });
261
+ expect(res.isError).toBeFalsy();
262
+ });
263
+
264
+ it('gates an OAuth var whose row exists but is NOT yet authorized', async () => {
265
+ // Row present (userConfigured) but no token yet (userAuthorized:false) → needs auth.
266
+ const client = await setup({
267
+ secretsVault: vault(true, false),
268
+ toolManuals: manualsWithOAuthVar,
269
+ });
270
+ const res = await client.callTool({ name: 'ask', arguments: { body: { prompt: 'hi' } } });
271
+ expect(res.isError).toBe(true);
272
+ const text = (res.content as Array<{ text: string }>)[0].text;
273
+ expect(text).toMatch(/Google/);
274
+ expect(text).toContain('/connect');
275
+ expect(text).not.toMatch(/echo:/);
276
+ });
277
+
278
+ it('lets the tool run once the OAuth var is authorized', async () => {
279
+ const client = await setup({
280
+ secretsVault: vault(true, true),
281
+ toolManuals: manualsWithOAuthVar,
282
+ });
283
+ const res = await client.callTool({ name: 'ask', arguments: { body: { prompt: 'hi' } } });
284
+ expect(res.isError).toBeFalsy();
285
+ expect(JSON.parse((res.content as Array<{ text: string }>)[0].text).text).toBe('echo: hi');
286
+ });
287
+
288
+ it('gates an authorized OAuth var whose token is missing a now-required scope', async () => {
289
+ // Authorized, but the token was granted only `openid` while the tool now
290
+ // requires `calendar.readonly` too → route to re-auth instead of a provider 400.
291
+ const client = await setup({
292
+ secretsVault: vault(true, true, 'openid'),
293
+ toolManuals: manualsWithScopedOAuthVar,
294
+ });
295
+ const res = await client.callTool({ name: 'ask', arguments: { body: { prompt: 'hi' } } });
296
+ expect(res.isError).toBe(true);
297
+ const text = (res.content as Array<{ text: string }>)[0].text;
298
+ expect(text).toMatch(/Google/);
299
+ expect(text).toContain('/connect');
300
+ expect(text).not.toMatch(/echo:/);
301
+ });
302
+
303
+ it('lets the tool run when the token covers every now-required scope', async () => {
304
+ const client = await setup({
305
+ secretsVault: vault(true, true, 'openid https://www.googleapis.com/auth/calendar.readonly'),
306
+ toolManuals: manualsWithScopedOAuthVar,
307
+ });
308
+ const res = await client.callTool({ name: 'ask', arguments: { body: { prompt: 'hi' } } });
309
+ expect(res.isError).toBeFalsy();
310
+ expect(JSON.parse((res.content as Array<{ text: string }>)[0].text).text).toBe('echo: hi');
311
+ });
312
+
313
+ it('gates an authorized OAuth var whose token has no recorded granted scopes', async () => {
314
+ // A token minted before granted scopes were captured (grantedScopes undefined)
315
+ // cannot prove it covers the required scopes → fail safe to re-auth.
316
+ const client = await setup({
317
+ secretsVault: vault(true, true, undefined),
318
+ toolManuals: manualsWithScopedOAuthVar,
319
+ });
320
+ const res = await client.callTool({ name: 'ask', arguments: { body: { prompt: 'hi' } } });
321
+ expect(res.isError).toBe(true);
322
+ expect((res.content as Array<{ text: string }>)[0].text).toContain('/connect');
323
+ });
324
+
325
+ // A sign-in that EXISTS but is broken resets an interactive session's own
326
+ // grant, so the MCP client re-runs the browser authorization and lands the
327
+ // user on /connect. Never-configured tools and connection-key sessions must
328
+ // NOT trigger it.
329
+ describe('session-grant reset (re-auth trigger)', () => {
330
+ const revokeSpy = () => {
331
+ const calls: string[] = [];
332
+ return { calls, fn: async (bearer: string) => void calls.push(bearer) };
333
+ };
334
+
335
+ it('revokes the session grant when an EXISTING sign-in is broken (OAuth session)', async () => {
336
+ const revoke = revokeSpy();
337
+ // Row exists (userConfigured) but sign-in never completed / grant dead.
338
+ const client = await setup({
339
+ secretsVault: vault(true, false),
340
+ toolManuals: manualsWithOAuthVar,
341
+ tokenId: null,
342
+ revokeOAuthAccess: revoke.fn,
343
+ });
344
+ const res = await client.callTool({ name: 'ask', arguments: { body: { prompt: 'hi' } } });
345
+ expect(res.isError).toBe(true);
346
+ expect(revoke.calls).toEqual(['bevel_testkey']); // the session's bearer
347
+ });
348
+
349
+ it('also triggers for an authorized-but-under-scoped sign-in', async () => {
350
+ const revoke = revokeSpy();
351
+ const client = await setup({
352
+ secretsVault: vault(true, true, 'openid'),
353
+ toolManuals: manualsWithScopedOAuthVar,
354
+ tokenId: null,
355
+ revokeOAuthAccess: revoke.fn,
356
+ });
357
+ await client.callTool({ name: 'ask', arguments: { body: { prompt: 'hi' } } });
358
+ expect(revoke.calls.length).toBe(1);
359
+ });
360
+
361
+ it('does NOT trigger for a never-configured sign-in (no row) — just the /connect link', async () => {
362
+ const revoke = revokeSpy();
363
+ const client = await setup({
364
+ secretsVault: vault(false),
365
+ toolManuals: manualsWithOAuthVar,
366
+ tokenId: null,
367
+ revokeOAuthAccess: revoke.fn,
368
+ });
369
+ const res = await client.callTool({ name: 'ask', arguments: { body: { prompt: 'hi' } } });
370
+ expect(res.isError).toBe(true);
371
+ expect(revoke.calls).toEqual([]);
372
+ });
373
+
374
+ it('does NOT trigger on a connection-key session (no grant to reset)', async () => {
375
+ const revoke = revokeSpy();
376
+ const client = await setup({
377
+ secretsVault: vault(true, false),
378
+ toolManuals: manualsWithOAuthVar,
379
+ tokenId: 'tok-1',
380
+ revokeOAuthAccess: revoke.fn,
381
+ });
382
+ await client.callTool({ name: 'ask', arguments: { body: { prompt: 'hi' } } });
383
+ expect(revoke.calls).toEqual([]);
384
+ });
385
+ });
386
+
387
+ // Connection-key sessions are autonomous pipelines: a tool whose personal
388
+ // credentials aren't satisfied is not REGISTERED at all (absent from
389
+ // tools/list), instead of failing mid-run at call time.
390
+ describe('listing-time filter (connection-key sessions only)', () => {
391
+ const toolNames = async (client: Awaited<ReturnType<typeof setup>>) =>
392
+ (await client.listTools()).tools.map((t) => t.name).sort();
393
+
394
+ it('hides a tool with an unset personal credential from a connection-key session', async () => {
395
+ const client = await setup({ secretsVault: vault(false), toolManuals: manualsWithUserVar });
396
+ // The KNOWLEDGE_BASE tools are gone; the meta-tools always remain.
397
+ expect(await toolNames(client)).toEqual(['call_tool_chain', 'list_tools', 'tools_info']);
398
+ });
399
+
400
+ it('lists the tool once the personal credential is set', async () => {
401
+ const client = await setup({ secretsVault: vault(true), toolManuals: manualsWithUserVar });
402
+ expect(await toolNames(client)).toEqual(['ask', 'boom', 'call_tool_chain', 'list_tools', 'refy', 'tools_info']);
403
+ });
404
+
405
+ it('keeps the full listing for an OAuth/JWT session (tokenId null) — the caller configures interactively', async () => {
406
+ const client = await setup({
407
+ secretsVault: vault(false),
408
+ toolManuals: manualsWithUserVar,
409
+ tokenId: null,
410
+ });
411
+ expect(await toolNames(client)).toEqual(['ask', 'boom', 'call_tool_chain', 'list_tools', 'refy', 'tools_info']);
412
+ });
413
+ });
414
+ });
@@ -0,0 +1,126 @@
1
+ import type { Request, Response, NextFunction } from 'express';
2
+ import { InvalidTokenError } from '@modelcontextprotocol/sdk/server/auth/errors.js';
3
+ import type { AuthService } from '../auth/auth.service.js';
4
+ import type { IExternalApiKeyService } from '../tool-auth/external-api-key.interface.js';
5
+ import type { BevelOAuthProvider } from './oauth/bevel-oauth-provider.js';
6
+ import '../tool-auth/external-api-key.interface.js'; // Express Request augmentation (req.externalApiKeyId)
7
+
8
+ /**
9
+ * Auth middleware for the MCP endpoint. Accepts any of:
10
+ *
11
+ * 1. A connection key (Bearer `bevel_…`) — minted from the settings UI,
12
+ * resolved via ExternalApiKeyService.
13
+ * 2. An MCP OAuth access token (Bearer `bevel-mcp_…`) — issued by our own
14
+ * authorization server after the /connect consent flow, resolved via
15
+ * BevelOAuthProvider.
16
+ * 3. A regular JWT — same shape the web app uses. Lets a logged-in user
17
+ * hit the MCP endpoint from their browser if we ever need it
18
+ * (e.g. an in-app debugger). Keeps the surface from forking.
19
+ *
20
+ * The middleware **must** run before the MCP transport handler — the
21
+ * transport pulls `req.userId` to populate the session row at `initialize`.
22
+ *
23
+ * Failures return 401 with a `WWW-Authenticate` challenge carrying
24
+ * `resource_metadata` (RFC 9728) so an OAuth-capable MCP client discovers our
25
+ * authorization server and starts the flow, while clients configured with a
26
+ * key simply prompt for it.
27
+ */
28
+ export function createMcpAuthMiddleware(
29
+ authService: AuthService,
30
+ externalApiKeyService: IExternalApiKeyService,
31
+ oauthProvider: BevelOAuthProvider,
32
+ resourceMetadataUrl: string,
33
+ ) {
34
+ const wwwAuthenticate = `Bearer realm="bevel-mcp", resource_metadata="${resourceMetadataUrl}"`;
35
+ const unauthorized = (res: Response, error: string) => {
36
+ res.setHeader('WWW-Authenticate', wwwAuthenticate);
37
+ res.status(401).json({ error });
38
+ };
39
+
40
+ return async (req: Request, res: Response, next: NextFunction) => {
41
+ const header = req.headers.authorization;
42
+ // RFC 7235 §2.1: auth scheme matching is case-insensitive ("bearer",
43
+ // "BEARER", "BeArEr" are all valid). Match on the lowercased prefix and
44
+ // then take the token as whatever follows the first whitespace, so the
45
+ // extraction stays correct regardless of the caller's casing.
46
+ if (!header || !header.toLowerCase().startsWith('bearer ')) {
47
+ unauthorized(res, 'Missing or invalid Authorization header');
48
+ return;
49
+ }
50
+
51
+ const firstSpace = header.indexOf(' ');
52
+ const token = header.slice(firstSpace + 1).trim();
53
+
54
+ // Route on the tenant key prefixes so we never accidentally pass a JWT
55
+ // through hash lookup or an external API key through jsonwebtoken — both
56
+ // would 500 instead of cleanly 401-ing. Order matters only for clarity:
57
+ // the connection-key (`bevel_`), OAuth (`bevel-mcp_`), and JWT (`eyJ…`)
58
+ // shapes are mutually non-overlapping.
59
+ if (externalApiKeyService.looksLikeExternalApiKey(token)) {
60
+ try {
61
+ // Resolve the token *id* alongside the user so the tool handler can
62
+ // meter the internal model against this key's daily cap — the same
63
+ // per-key guardrail the LLM proxy enforces. OAuth and JWT callers
64
+ // have no connection key, so those paths below leave
65
+ // `externalApiKeyId` unset and are not metered.
66
+ const resolved = await externalApiKeyService.verifyAndLoadToken(token);
67
+ if (!resolved) {
68
+ unauthorized(res, 'Invalid or revoked connection key');
69
+ return;
70
+ }
71
+ req.userId = resolved.user.id;
72
+ req.userEmail = resolved.user.email;
73
+ req.externalApiKeyId = resolved.tokenId;
74
+ next();
75
+ return;
76
+ } catch (err) {
77
+ // A DB error during verification is a 500, not a 401 — the caller's
78
+ // credentials may be valid; we just can't check them right now.
79
+ console.error('[mcp-auth] connection-key verification failed:', err);
80
+ res.status(500).json({ error: 'Authentication backend unavailable' });
81
+ return;
82
+ }
83
+ }
84
+
85
+ // MCP OAuth access token — issued by our own authorization server. An
86
+ // invalid/expired/revoked token is a clean 401 (re-challenging with
87
+ // resource_metadata so the client can re-authorize); a DB failure is a
88
+ // 500, same split as the connection-key branch above.
89
+ if (oauthProvider.looksLikeAccessToken(token)) {
90
+ try {
91
+ const info = await oauthProvider.verifyAccessToken(token);
92
+ req.userId = String(info.extra?.userId ?? '');
93
+ req.userEmail = String(info.extra?.userEmail ?? '');
94
+ if (!req.userId) {
95
+ unauthorized(res, 'Invalid access token');
96
+ return;
97
+ }
98
+ } catch (err) {
99
+ if (err instanceof InvalidTokenError) {
100
+ unauthorized(res, 'Invalid, expired, or revoked access token');
101
+ } else {
102
+ console.error('[mcp-auth] OAuth token verification failed:', err);
103
+ res.status(500).json({ error: 'Authentication backend unavailable' });
104
+ }
105
+ return;
106
+ }
107
+ // Outside the try so a synchronous throw from a downstream handler isn't
108
+ // misclassified as a token-verification failure (and doesn't try to write
109
+ // a second response).
110
+ next();
111
+ return;
112
+ }
113
+
114
+ // JWT path — same logic as `createAuthMiddleware` in modules/auth, kept
115
+ // duplicated rather than imported because that one writes its own 401
116
+ // body shape and we want the WWW-Authenticate header set.
117
+ try {
118
+ const { userId, email } = authService.verifyToken(token);
119
+ req.userId = userId;
120
+ req.userEmail = email;
121
+ next();
122
+ } catch {
123
+ unauthorized(res, 'Invalid or expired token');
124
+ }
125
+ };
126
+ }