@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,358 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { createHash } from 'node:crypto';
3
+ import { ExternalApiKeyService } from '../external-api-key.service.js';
4
+ import {
5
+ InvalidTokenLabelError,
6
+ TokenNotFoundError,
7
+ TokenStillActiveError,
8
+ } from '../external-api-key.errors.js';
9
+ import type { Database } from '../../database/connection.js';
10
+ import { externalApiKeys } from '../../database/schema.js';
11
+
12
+ /**
13
+ * Builds a fake drizzle chain. Every chainable method returns the same
14
+ * chain object, and the chain itself is thenable — so `await db.x().y().z()`
15
+ * resolves to whatever the test queued for this operation. Each call to
16
+ * `db.insert / .select / .update` pops the next result off `queue`.
17
+ *
18
+ * We use this instead of a real Postgres because the service is pure
19
+ * domain logic on top of drizzle; integration coverage of the migration
20
+ * shape lives with the route tests later.
21
+ */
22
+ function makeFakeDb(queue: any[]) {
23
+ const calls: Record<string, any[][]> = {
24
+ insert: [],
25
+ select: [],
26
+ update: [],
27
+ delete: [],
28
+ values: [],
29
+ set: [],
30
+ where: [],
31
+ orderBy: [],
32
+ limit: [],
33
+ innerJoin: [],
34
+ from: [],
35
+ returning: [],
36
+ };
37
+
38
+ function nextChain() {
39
+ const result = queue.shift();
40
+ const chain: any = {};
41
+ const passthrough = (name: string) =>
42
+ vi.fn((...args: any[]) => {
43
+ calls[name].push(args);
44
+ return chain;
45
+ });
46
+ chain.values = passthrough('values');
47
+ chain.set = passthrough('set');
48
+ chain.where = passthrough('where');
49
+ chain.orderBy = passthrough('orderBy');
50
+ chain.limit = passthrough('limit');
51
+ chain.innerJoin = passthrough('innerJoin');
52
+ chain.from = passthrough('from');
53
+ chain.returning = passthrough('returning');
54
+ chain.then = (onF: any, onR: any) =>
55
+ Promise.resolve(result).then(onF, onR);
56
+ return chain;
57
+ }
58
+
59
+ const db = {
60
+ insert: vi.fn((...args: any[]) => {
61
+ calls.insert.push(args);
62
+ return nextChain();
63
+ }),
64
+ select: vi.fn((...args: any[]) => {
65
+ calls.select.push(args);
66
+ return nextChain();
67
+ }),
68
+ update: vi.fn((...args: any[]) => {
69
+ calls.update.push(args);
70
+ return nextChain();
71
+ }),
72
+ delete: vi.fn((...args: any[]) => {
73
+ calls.delete.push(args);
74
+ return nextChain();
75
+ }),
76
+ // Transactions run the callback against the same fake db, so queued
77
+ // results are consumed in order just like a non-transactional call.
78
+ transaction: vi.fn((fn: (tx: any) => Promise<unknown>) => fn(db)),
79
+ } as unknown as Database;
80
+
81
+ return { db, calls };
82
+ }
83
+
84
+ function makeRow(overrides: Partial<{
85
+ id: string;
86
+ userId: string;
87
+ tokenHash: string;
88
+ label: string;
89
+ createdAt: Date;
90
+ lastUsedAt: Date | null;
91
+ revokedAt: Date | null;
92
+ }> = {}) {
93
+ return {
94
+ id: overrides.id ?? 'tok-1',
95
+ userId: overrides.userId ?? 'user-1',
96
+ tokenHash: overrides.tokenHash ?? 'hash-1',
97
+ label: overrides.label ?? 'My laptop',
98
+ createdAt: overrides.createdAt ?? new Date('2026-01-01T00:00:00Z'),
99
+ lastUsedAt: overrides.lastUsedAt ?? null,
100
+ revokedAt: overrides.revokedAt ?? null,
101
+ };
102
+ }
103
+
104
+ function sha256Hex(s: string): string {
105
+ return createHash('sha256').update(s).digest('hex');
106
+ }
107
+
108
+ // Flush queued microtasks so a fire-and-forget `.catch(...)` runs before
109
+ // we assert. The service intentionally does not await its touchLastUsed
110
+ // call, so the rejection handler runs in a later microtask.
111
+ const flushMicrotasks = () => new Promise<void>((r) => setImmediate(r));
112
+
113
+ describe('ExternalApiKeyService', () => {
114
+ describe('mint', () => {
115
+ it('generates a bevel_-prefixed token, persists its sha256 hash (never the plaintext), and returns both', async () => {
116
+ const row = makeRow({ id: 'tok-42', label: 'My laptop' });
117
+ const { db, calls } = makeFakeDb([[row]]);
118
+ const service = new ExternalApiKeyService(db, 'bevel_');
119
+
120
+ const result = await service.mint('user-1', 'My laptop');
121
+
122
+ expect(result.plaintext.startsWith('bevel_')).toBe(true);
123
+ // 32 random bytes base64url-encoded => 43 chars after the prefix.
124
+ expect(result.plaintext.length).toBe('bevel_'.length + 43);
125
+
126
+ const inserted = calls.values[0][0];
127
+ expect(inserted.userId).toBe('user-1');
128
+ expect(inserted.label).toBe('My laptop');
129
+ expect(inserted.tokenHash).toBe(sha256Hex(result.plaintext));
130
+ // The plaintext must never land in the DB row.
131
+ expect(inserted.tokenHash).not.toBe(result.plaintext);
132
+ expect(inserted).not.toHaveProperty('plaintext');
133
+
134
+ expect(result.summary).toEqual({
135
+ id: 'tok-42',
136
+ label: 'My laptop',
137
+ createdAt: row.createdAt.getTime(),
138
+ lastUsedAt: null,
139
+ revokedAt: null,
140
+ });
141
+ });
142
+
143
+ it('trims the label before persisting', async () => {
144
+ const { db, calls } = makeFakeDb([[makeRow()]]);
145
+ const service = new ExternalApiKeyService(db, 'bevel_');
146
+
147
+ await service.mint('user-1', ' spacey ');
148
+
149
+ expect(calls.values[0][0].label).toBe('spacey');
150
+ });
151
+
152
+ it('rejects empty/whitespace labels without touching the DB', async () => {
153
+ const { db } = makeFakeDb([]);
154
+ const service = new ExternalApiKeyService(db, 'bevel_');
155
+
156
+ await expect(service.mint('user-1', '')).rejects.toBeInstanceOf(
157
+ InvalidTokenLabelError,
158
+ );
159
+ await expect(service.mint('user-1', ' \n\t ')).rejects.toBeInstanceOf(
160
+ InvalidTokenLabelError,
161
+ );
162
+ expect((db as any).insert).not.toHaveBeenCalled();
163
+ });
164
+
165
+ it('rejects oversized labels (>200 chars) without touching the DB', async () => {
166
+ const { db } = makeFakeDb([]);
167
+ const service = new ExternalApiKeyService(db, 'bevel_');
168
+
169
+ await expect(
170
+ service.mint('user-1', 'a'.repeat(201)),
171
+ ).rejects.toBeInstanceOf(InvalidTokenLabelError);
172
+ expect((db as any).insert).not.toHaveBeenCalled();
173
+ });
174
+ });
175
+
176
+ describe('verifyAndLoadUser', () => {
177
+ it('returns the owning user when the token hash matches an un-revoked row', async () => {
178
+ const row = {
179
+ tokenId: 'tok-1',
180
+ userId: 'user-7',
181
+ email: 'alice@example.com',
182
+ name: 'Alice',
183
+ avatarUrl: null,
184
+ };
185
+ // Two queued ops: the SELECT for verify, then the UPDATE for the
186
+ // fire-and-forget last_used_at touch.
187
+ const { db } = makeFakeDb([[row], undefined]);
188
+ const service = new ExternalApiKeyService(db, 'bevel_');
189
+
190
+ const user = await service.verifyAndLoadUser('bevel_abc123');
191
+
192
+ expect(user).toEqual({
193
+ id: 'user-7',
194
+ email: 'alice@example.com',
195
+ name: 'Alice',
196
+ avatarUrl: undefined,
197
+ });
198
+ });
199
+
200
+ it('returns null for tokens not carrying the `bevel_` prefix without hitting the DB', async () => {
201
+ const { db } = makeFakeDb([]);
202
+ const service = new ExternalApiKeyService(db, 'bevel_');
203
+
204
+ expect(await service.verifyAndLoadUser('eyJhbGciOiJIUzI1NiJ9')).toBeNull();
205
+ expect(await service.verifyAndLoadUser('')).toBeNull();
206
+ expect(await service.verifyAndLoadUser(null as any)).toBeNull();
207
+ expect((db as any).select).not.toHaveBeenCalled();
208
+ });
209
+
210
+ it('returns null when no matching un-revoked row exists', async () => {
211
+ const { db } = makeFakeDb([[]]);
212
+ const service = new ExternalApiKeyService(db, 'bevel_');
213
+
214
+ expect(await service.verifyAndLoadUser('bevel_unknown')).toBeNull();
215
+ });
216
+
217
+ it('still resolves with the user even when the last_used_at update fails (fire-and-forget)', async () => {
218
+ const row = {
219
+ tokenId: 'tok-1',
220
+ userId: 'user-7',
221
+ email: 'alice@example.com',
222
+ name: 'Alice',
223
+ avatarUrl: null,
224
+ };
225
+ // Queue: SELECT returns the row; UPDATE rejects.
226
+ const queue: any[] = [[row]];
227
+ const { db } = makeFakeDb(queue);
228
+ // Replace the update chain with one that rejects on await, so the
229
+ // service's fire-and-forget `.catch` handler runs.
230
+ (db as any).update = vi.fn(() => {
231
+ const chain: any = {};
232
+ chain.set = vi.fn().mockReturnValue(chain);
233
+ chain.where = vi.fn().mockReturnValue(chain);
234
+ chain.then = (_onF: any, onR: any) =>
235
+ Promise.resolve().then(() => onR(new Error('connection lost')));
236
+ return chain;
237
+ });
238
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
239
+
240
+ const service = new ExternalApiKeyService(db, 'bevel_');
241
+ const user = await service.verifyAndLoadUser('bevel_abc');
242
+
243
+ expect(user?.id).toBe('user-7');
244
+ await flushMicrotasks();
245
+ expect(warn).toHaveBeenCalled();
246
+ warn.mockRestore();
247
+ });
248
+ });
249
+
250
+ describe('listForUser', () => {
251
+ it('maps DB rows to summaries, newest-first via desc(createdAt)', async () => {
252
+ const rows = [
253
+ makeRow({
254
+ id: 'a',
255
+ createdAt: new Date('2026-03-01T00:00:00Z'),
256
+ lastUsedAt: new Date('2026-03-02T00:00:00Z'),
257
+ }),
258
+ makeRow({
259
+ id: 'b',
260
+ revokedAt: new Date('2026-02-15T00:00:00Z'),
261
+ }),
262
+ ];
263
+ const { db, calls } = makeFakeDb([rows]);
264
+ const service = new ExternalApiKeyService(db, 'bevel_');
265
+
266
+ const summaries = await service.listForUser('user-1');
267
+
268
+ expect(summaries).toHaveLength(2);
269
+ expect(summaries[0]).toEqual({
270
+ id: 'a',
271
+ label: rows[0].label,
272
+ createdAt: rows[0].createdAt.getTime(),
273
+ lastUsedAt: rows[0].lastUsedAt!.getTime(),
274
+ revokedAt: null,
275
+ });
276
+ expect(summaries[1].revokedAt).toBe(rows[1].revokedAt!.getTime());
277
+ // sanity-check that ordering was requested (we can't introspect the
278
+ // SQL fragment here, but we can confirm the call shape).
279
+ expect(calls.orderBy).toHaveLength(1);
280
+ });
281
+ });
282
+
283
+ describe('revoke', () => {
284
+ it('updates the row and returns silently when the token belongs to the user and was active', async () => {
285
+ // First op: UPDATE returns 1 row.
286
+ const { db, calls } = makeFakeDb([[{ id: 'tok-1' }]]);
287
+ const service = new ExternalApiKeyService(db, 'bevel_');
288
+
289
+ await service.revoke('tok-1', 'user-1');
290
+
291
+ const setArgs = calls.set[0][0];
292
+ expect(setArgs.revokedAt).toBeInstanceOf(Date);
293
+ // No follow-up SELECT — the UPDATE found a row.
294
+ expect((db as any).select).not.toHaveBeenCalled();
295
+ });
296
+
297
+ it('is idempotent on already-revoked tokens: returns silently without throwing', async () => {
298
+ // UPDATE matches 0 rows (because `isNull(revokedAt)` filtered it out),
299
+ // then SELECT confirms the row exists for this user → idempotent path.
300
+ const { db } = makeFakeDb([[], [{ id: 'tok-1' }]]);
301
+ const service = new ExternalApiKeyService(db, 'bevel_');
302
+
303
+ await expect(service.revoke('tok-1', 'user-1')).resolves.toBeUndefined();
304
+ });
305
+
306
+ it('throws TokenNotFoundError when the token does not exist or belongs to another user', async () => {
307
+ // UPDATE matches 0 rows, follow-up SELECT also returns empty.
308
+ const { db } = makeFakeDb([[], []]);
309
+ const service = new ExternalApiKeyService(db, 'bevel_');
310
+
311
+ await expect(service.revoke('tok-x', 'user-1')).rejects.toBeInstanceOf(
312
+ TokenNotFoundError,
313
+ );
314
+ });
315
+ });
316
+
317
+ describe('remove', () => {
318
+ it('validates then deletes the key (dependents cascade at the DB layer)', async () => {
319
+ // Queue: SELECT finds a revoked row; then the key delete consumes one.
320
+ const { db } = makeFakeDb([
321
+ [{ revokedAt: new Date('2026-02-01T00:00:00Z') }],
322
+ undefined,
323
+ ]);
324
+ const service = new ExternalApiKeyService(db, 'bevel_');
325
+
326
+ await service.remove('tok-1', 'user-1');
327
+
328
+ // Validation SELECT first, then ONE delete of the key row. Dependent
329
+ // rows (e.g. llm_usage metering) are removed by ON DELETE CASCADE —
330
+ // this service must not know those tables exist.
331
+ expect((db as any).select).toHaveBeenCalledTimes(1);
332
+ expect((db as any).delete).toHaveBeenCalledTimes(1);
333
+ expect((db as any).delete).toHaveBeenCalledWith(externalApiKeys);
334
+ });
335
+
336
+ it('throws TokenStillActiveError when the token exists but was never disconnected', async () => {
337
+ // SELECT finds the row with a null revokedAt → still active; no delete.
338
+ const { db } = makeFakeDb([[{ revokedAt: null }]]);
339
+ const service = new ExternalApiKeyService(db, 'bevel_');
340
+
341
+ await expect(service.remove('tok-1', 'user-1')).rejects.toBeInstanceOf(
342
+ TokenStillActiveError,
343
+ );
344
+ expect((db as any).delete).not.toHaveBeenCalled();
345
+ });
346
+
347
+ it('throws TokenNotFoundError when the token does not exist or belongs to another user', async () => {
348
+ // SELECT returns empty → not found; no delete.
349
+ const { db } = makeFakeDb([[]]);
350
+ const service = new ExternalApiKeyService(db, 'bevel_');
351
+
352
+ await expect(service.remove('tok-x', 'user-1')).rejects.toBeInstanceOf(
353
+ TokenNotFoundError,
354
+ );
355
+ expect((db as any).delete).not.toHaveBeenCalled();
356
+ });
357
+ });
358
+ });
@@ -0,0 +1,79 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { InternalTokenService } from '../internal-token.service.js';
3
+ import { createTokenVerifier } from '../tool-auth.middleware.js';
4
+ import type { IExternalApiKeyService } from '../external-api-key.interface.js';
5
+
6
+ const claim = { userId: 'user-A' };
7
+
8
+ describe('InternalTokenService', () => {
9
+ it('mints a token that verifies back to the same claim', () => {
10
+ const svc = new InternalTokenService({ secret: 'test-secret' });
11
+ const token = svc.mint(claim);
12
+ expect(svc.looksLikeInternalToken(token)).toBe(true);
13
+ expect(svc.verify(token)).toEqual(claim);
14
+ });
15
+
16
+ it('round-trips the externalProxy flag (the MCP proxy loopback identity)', () => {
17
+ const svc = new InternalTokenService({ secret: 'test-secret' });
18
+ const token = svc.mint({ userId: 'user-A', externalProxy: true });
19
+ expect(svc.verify(token)).toEqual({ userId: 'user-A', externalProxy: true });
20
+ });
21
+
22
+ it('rejects a tampered token', () => {
23
+ const svc = new InternalTokenService({ secret: 'test-secret' });
24
+ const token = svc.mint(claim);
25
+ expect(svc.verify(token + 'x')).toBeNull();
26
+ expect(svc.verify(token.replace(/.$/, (c) => (c === 'a' ? 'b' : 'a')))).toBeNull();
27
+ });
28
+
29
+ it('rejects a token signed with a different secret', () => {
30
+ const a = new InternalTokenService({ secret: 'secret-a' });
31
+ const b = new InternalTokenService({ secret: 'secret-b' });
32
+ expect(b.verify(a.mint(claim))).toBeNull();
33
+ });
34
+
35
+ it('rejects an expired token', () => {
36
+ let now = 1_000_000;
37
+ const svc = new InternalTokenService({ secret: 's', ttlMs: 1000, now: () => now });
38
+ const token = svc.mint(claim);
39
+ now += 1500;
40
+ expect(svc.verify(token)).toBeNull();
41
+ });
42
+
43
+ it('rejects a connection-key-shaped bearer', () => {
44
+ const svc = new InternalTokenService({ secret: 's' });
45
+ expect(svc.verify('bevel_abc123')).toBeNull();
46
+ expect(svc.looksLikeInternalToken('bevel_abc123')).toBe(false);
47
+ });
48
+ });
49
+
50
+ describe('createTokenVerifier — internal-token source resolution', () => {
51
+ const noExternalKeys = {
52
+ looksLikeExternalApiKey: () => false,
53
+ verifyAndLoadToken: async () => null,
54
+ } as unknown as IExternalApiKeyService;
55
+
56
+ it('a plain per-run internal token resolves to source internal with its sessionId', async () => {
57
+ const svc = new InternalTokenService({ secret: 's' });
58
+ const verify = createTokenVerifier(noExternalKeys, svc);
59
+ const result = await verify(svc.mint({ userId: 'user-A', sessionId: 'run-1' }));
60
+ expect(result).toEqual({
61
+ ok: true,
62
+ auth: { source: 'internal', userId: 'user-A', sessionId: 'run-1', scope: 'write' },
63
+ });
64
+ });
65
+
66
+ it('an externalProxy token resolves to source EXTERNAL — the caller is an external agent', async () => {
67
+ // The MCP proxy mints this as the loopback identity of an OAuth/JWT MCP
68
+ // session. Resolving it internal used to deadlock those sessions: the
69
+ // external-only `start_session` refused them, and every session-gated
70
+ // tool demands the sessionId they then couldn't mint.
71
+ const svc = new InternalTokenService({ secret: 's' });
72
+ const verify = createTokenVerifier(noExternalKeys, svc);
73
+ const result = await verify(svc.mint({ userId: 'user-A', externalProxy: true }));
74
+ expect(result).toEqual({
75
+ ok: true,
76
+ auth: { source: 'external', userId: 'user-A', scope: 'write' },
77
+ });
78
+ });
79
+ });
@@ -0,0 +1,88 @@
1
+ import type { Server as HttpServer } from 'node:http';
2
+ import express from 'express';
3
+ import { afterEach, describe, expect, it } from 'vitest';
4
+ import { ToolRegistry } from '../../tool-registry/tool-registry.js';
5
+ import { toolDef } from '../../tool-helpers/tool-def.js';
6
+ import { createManualRoutes } from '../../tool-registry/manual.routes.js';
7
+ import { InternalTokenService } from '../internal-token.service.js';
8
+ import { createManualAuthMiddleware } from '../tool-auth.middleware.js';
9
+ import type { IExternalApiKeyService } from '../external-api-key.interface.js';
10
+ import type { AuthService } from '../../auth/auth.service.js';
11
+
12
+ /**
13
+ * The manual endpoints (`/agent/utcp`, `/agent/internal/utcp`) accept a browser
14
+ * JWT in ADDITION to a connection key / internal token, so a logged-in user can
15
+ * browse the catalog with their session — but the internal catalog stays
16
+ * `requireInternalSource`-gated, and a JWT never reaches an execution route.
17
+ */
18
+ const KEY = 'bevel_validkey';
19
+ const JWT = 'browser-jwt';
20
+
21
+ const fakeExternalApiKeys = {
22
+ looksLikeExternalApiKey: (t: string) => typeof t === 'string' && t.startsWith('bevel_'),
23
+ verifyAndLoadToken: async (t: string) =>
24
+ t === KEY ? { user: { id: 'u-key' }, tokenId: 'tok-1' } : null,
25
+ } as unknown as IExternalApiKeyService;
26
+
27
+ const fakeAuth = {
28
+ verifyToken: (t: string) => {
29
+ if (t === JWT) return { userId: 'u-jwt', email: 'jwt@x' };
30
+ throw new Error('bad jwt');
31
+ },
32
+ } as unknown as AuthService;
33
+
34
+ let server: HttpServer | undefined;
35
+ afterEach(async () => {
36
+ if (server) await new Promise<void>((r) => server!.close(() => r()));
37
+ server = undefined;
38
+ });
39
+
40
+ async function start() {
41
+ const internalTokens = new InternalTokenService({ secret: 'test-secret' });
42
+ const registry = new ToolRegistry();
43
+ registry.registerExternalTool(toolDef({ name: 'pub', description: 'd', path: '/api/agent/tools/pub', inputs: { type: 'object', properties: {} } }));
44
+ registry.registerInternalTool(toolDef({ name: 'sec', description: 'd', path: '/api/agent/tools/sec', inputs: { type: 'object', properties: {} } }));
45
+ const manualAuth = createManualAuthMiddleware(fakeExternalApiKeys, internalTokens, fakeAuth);
46
+ const app = express();
47
+ app.use('/api', createManualRoutes(registry, manualAuth));
48
+ server = await new Promise<HttpServer>((res) => {
49
+ const s = app.listen(0, () => res(s));
50
+ });
51
+ const port = (server.address() as { port: number }).port;
52
+ return { base: `http://127.0.0.1:${port}`, intToken: internalTokens.mint({ userId: 'u-int' }) };
53
+ }
54
+
55
+ const get = (base: string, path: string, bearer?: string) =>
56
+ fetch(`${base}${path}`, bearer ? { headers: { Authorization: `Bearer ${bearer}` } } : undefined);
57
+
58
+ describe('createManualAuthMiddleware (read-only manual endpoints)', () => {
59
+ it('serves the external manual to a browser JWT', async () => {
60
+ const { base } = await start();
61
+ const r = await get(base, '/api/agent/utcp', JWT);
62
+ expect(r.status).toBe(200);
63
+ const m = (await r.json()) as { tools: { name: string }[] };
64
+ expect(m.tools.map((t) => t.name)).toContain('pub');
65
+ });
66
+
67
+ it('serves the external manual to a connection key', async () => {
68
+ const { base } = await start();
69
+ expect((await get(base, '/api/agent/utcp', KEY)).status).toBe(200);
70
+ });
71
+
72
+ it('401s a missing or unrecognised bearer', async () => {
73
+ const { base } = await start();
74
+ expect((await get(base, '/api/agent/utcp')).status).toBe(401);
75
+ expect((await get(base, '/api/agent/utcp', 'garbage')).status).toBe(401);
76
+ });
77
+
78
+ it('refuses the INTERNAL manual to a browser JWT (403) but allows an internal token', async () => {
79
+ const { base, intToken } = await start();
80
+ expect((await get(base, '/api/agent/internal/utcp', JWT)).status).toBe(403);
81
+ expect((await get(base, '/api/agent/internal/utcp', intToken)).status).toBe(200);
82
+ });
83
+
84
+ it('refuses the INTERNAL manual to a connection key (403)', async () => {
85
+ const { base } = await start();
86
+ expect((await get(base, '/api/agent/internal/utcp', KEY)).status).toBe(403);
87
+ });
88
+ });
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Domain errors for the API token service. Distinct classes so callers can
3
+ * map each to an HTTP status and a user-facing message without string-matching.
4
+ */
5
+
6
+ export class InvalidTokenLabelError extends Error {
7
+ constructor(message: string) {
8
+ super(message);
9
+ this.name = 'InvalidTokenLabelError';
10
+ }
11
+ }
12
+
13
+ export class TokenNotFoundError extends Error {
14
+ constructor(message = 'Token not found') {
15
+ super(message);
16
+ this.name = 'TokenNotFoundError';
17
+ }
18
+ }
19
+
20
+ export class TokenStillActiveError extends Error {
21
+ constructor(message = 'Disconnect this key before deleting it') {
22
+ super(message);
23
+ this.name = 'TokenStillActiveError';
24
+ }
25
+ }
@@ -0,0 +1,99 @@
1
+ import type { AuthUser } from '@bevel-software/platform-shared';
2
+
3
+ declare global {
4
+ // eslint-disable-next-line @typescript-eslint/no-namespace
5
+ namespace Express {
6
+ interface Request {
7
+ /**
8
+ * Connection-key id bound by whichever auth middleware resolved a
9
+ * `<tenant>_…` key (MCP auth, LLM-proxy auth) — consumers use it for
10
+ * per-key attribution/metering. Declared beside the key contract so
11
+ * every key-resolving surface shares one augmentation.
12
+ */
13
+ externalApiKeyId?: string;
14
+ }
15
+ }
16
+ }
17
+
18
+ /**
19
+ * Summary row shown in the user's "Connection keys" settings panel. Never
20
+ * carries the plaintext — that is returned exactly once from `mint`.
21
+ */
22
+ export interface ExternalApiKeySummary {
23
+ id: string;
24
+ label: string;
25
+ createdAt: number;
26
+ lastUsedAt: number | null;
27
+ revokedAt: number | null;
28
+ }
29
+
30
+ /**
31
+ * Result of minting a new connection key. `plaintext` is shown to the user
32
+ * once (with a "you won't see this again" warning); the stored DB row only
33
+ * carries the hash.
34
+ */
35
+ export interface MintedExternalApiKey {
36
+ plaintext: string;
37
+ summary: ExternalApiKeySummary;
38
+ }
39
+
40
+ /**
41
+ * Contract for connection-key (API token) lifecycle. Used by the MCP auth
42
+ * middleware to resolve a Bearer token to a Bevel user, and by the settings
43
+ * UI to mint, list, and revoke keys.
44
+ *
45
+ * Verification is a hash lookup on a unique index, so it stays O(1) even
46
+ * with many tokens per user. Revoked tokens are kept (not deleted) so an
47
+ * operator can audit `last_used_at` after a leak.
48
+ */
49
+ export interface IExternalApiKeyService {
50
+ /**
51
+ * True if a bearer string carries this tenant's external-API-key prefix
52
+ * (`<tenant>_…`). Lets auth middlewares route a key vs a JWT / internal token
53
+ * without a DB round-trip, using the tenant prefix the service was built with.
54
+ */
55
+ looksLikeExternalApiKey(token: string): boolean;
56
+
57
+ /**
58
+ * Generate a new token, persist its hash, and return the plaintext. The
59
+ * plaintext is **only** returned here — there is no read path that can
60
+ * surface it again.
61
+ */
62
+ mint(userId: string, label: string): Promise<MintedExternalApiKey>;
63
+
64
+ /**
65
+ * Resolve a plaintext token to the owning user. Returns null when the
66
+ * token is unknown, revoked, or malformed. Bumps `last_used_at`
67
+ * fire-and-forget — verification latency stays bounded by the hash
68
+ * lookup, not the update.
69
+ */
70
+ verifyAndLoadUser(plaintext: string): Promise<AuthUser | null>;
71
+
72
+ /**
73
+ * Like `verifyAndLoadUser`, but also returns the matching token's id. The
74
+ * LLM proxy needs the token id (not just the user) to meter per-key usage
75
+ * against the daily cap. Returns null on unknown/revoked/malformed tokens.
76
+ */
77
+ verifyAndLoadToken(
78
+ plaintext: string,
79
+ ): Promise<{ tokenId: string; user: AuthUser } | null>;
80
+
81
+ /** Active + revoked tokens for the user, newest-first. */
82
+ listForUser(userId: string): Promise<ExternalApiKeySummary[]>;
83
+
84
+ /**
85
+ * Mark a token revoked. Idempotent — revoking an already-revoked token
86
+ * is a no-op (the row's `revokedAt` is not overwritten). Throws
87
+ * TokenNotFoundError if the token doesn't belong to the user.
88
+ */
89
+ revoke(id: string, userId: string): Promise<void>;
90
+
91
+ /**
92
+ * Permanently delete a token row, dropping its audit trail. Only permitted
93
+ * on an already-revoked token — an active key must be disconnected first,
94
+ * so a live agent's access is never yanked by a single click. Throws
95
+ * TokenNotFoundError if the token doesn't belong to the user, and
96
+ * TokenStillActiveError if it hasn't been revoked yet.
97
+ */
98
+ remove(id: string, userId: string): Promise<void>;
99
+ }