@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,80 @@
1
+ import type { Database } from '../database/connection.js';
2
+ /** A user row as the admin surface needs it (no avatar, no timestamps churn). */
3
+ export interface AdminUserView {
4
+ id: string;
5
+ email: string;
6
+ name: string;
7
+ createdAt: number;
8
+ }
9
+ /** The drizzle client erasure participants receive inside the transaction. */
10
+ export type ErasureTx = Parameters<Parameters<Database['transaction']>[0]>[0];
11
+ /** Identity context for one erasure run. */
12
+ export interface ErasureTarget {
13
+ userId: string;
14
+ /** The user's (lowercased) email at erasure time — for email-keyed rows. */
15
+ email: string;
16
+ /**
17
+ * Per-erasure placeholder identity for anonymized audit rows. Random per
18
+ * erasure: no link back to the person, but rows from ONE erasure stay
19
+ * correlated and email-keyed unique indexes can't collide across erasures.
20
+ */
21
+ erasedEmail: string;
22
+ erasedName: string;
23
+ }
24
+ /**
25
+ * A module-owned slice of account erasure. The core service erases the rows
26
+ * it owns (tokens, locks, review-trail anonymization, the user row) and runs
27
+ * every registered participant so each module cleans up its own tables —
28
+ * chat threads, connector links, routine authorship, … — without the auth
29
+ * module knowing they exist. Registered at the composition root.
30
+ *
31
+ * - `before` runs OUTSIDE the transaction, first. For idempotent pre-cleanup
32
+ * against external stores (e.g. chat-thread message memory) where a failure
33
+ * must leave a retryable state, not a half-committed one.
34
+ * - `inTransaction` runs INSIDE the erasure transaction, BEFORE the users row
35
+ * is deleted (so FKs onto users are still satisfiable and RESTRICT FKs make
36
+ * missed rows fail loudly). It may return a callback, which runs after the
37
+ * transaction commits — for external-store cleanup of rows captured during
38
+ * the transaction.
39
+ */
40
+ export interface IErasureParticipant {
41
+ before?(target: ErasureTarget): Promise<void>;
42
+ inTransaction?(tx: ErasureTx, target: ErasureTarget): Promise<void | (() => Promise<void>)>;
43
+ }
44
+ /**
45
+ * GDPR account erasure (Art. 17). Operator-driven: an admin deletes a user in
46
+ * response to an erasure request. What it guarantees:
47
+ *
48
+ * - Rows that ARE the user's personal data are hard-deleted: API/OAuth
49
+ * tokens, held file locks, the user row itself, and every registered
50
+ * participant's module-owned rows (chat threads incl. message memory,
51
+ * Microsoft connection, feedback, revalidation requests, upload tokens).
52
+ * Deleting the user row cascades whatever FKs onto it with ON DELETE
53
+ * CASCADE (account links, watchlist sources/findings, connector configs,
54
+ * vault secrets); deleting a connection key cascades its usage metering.
55
+ * - Audit rows that must survive for the review trail (approvals, merge log,
56
+ * review comments, change requests, queued commits — and, via participants,
57
+ * e.g. routine authorship) are kept but ANONYMIZED with the per-erasure
58
+ * placeholder identity.
59
+ *
60
+ * Out of scope, by firm policy (disclosed in the DPA): git history is never
61
+ * rewritten. Commit authorship and historical access-file entries stay in the
62
+ * KB's version history permanently as part of the tamper-evident record;
63
+ * erasure covers every database/filesystem store plus the CURRENT KB state.
64
+ *
65
+ * Note: sign-in is get-or-create by email, so a person who authenticates again
66
+ * after erasure simply gets a fresh, empty account — that is intended.
67
+ */
68
+ export interface IAccountErasureService {
69
+ listUsers(): Promise<AdminUserView[]>;
70
+ /** Erase `userId`. Returns false when no such user exists. */
71
+ eraseUser(userId: string): Promise<boolean>;
72
+ }
73
+ export declare class AccountErasureService implements IAccountErasureService {
74
+ private readonly db;
75
+ private readonly participants;
76
+ constructor(db: Database, participants?: IErasureParticipant[]);
77
+ listUsers(): Promise<AdminUserView[]>;
78
+ eraseUser(userId: string): Promise<boolean>;
79
+ }
80
+ //# sourceMappingURL=account-erasure.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-erasure.service.d.ts","sourceRoot":"","sources":["../../../src/modules/auth/account-erasure.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAc1D,iFAAiF;AACjF,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,8EAA8E;AAC9E,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9E,4CAA4C;AAC5C,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,aAAa,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;CAC7F;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,sBAAsB;IACrC,SAAS,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IACtC,8DAA8D;IAC9D,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7C;AAED,qBAAa,qBAAsB,YAAW,sBAAsB;IAEhE,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,YAAY;gBADZ,EAAE,EAAE,QAAQ,EACZ,YAAY,GAAE,mBAAmB,EAAO;IAGrD,SAAS,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IAQrC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CA4ElD"}
@@ -0,0 +1,91 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { eq } from 'drizzle-orm';
3
+ import { changeRequests, externalApiKeys, fileLocks, oauthAuthCodes, oauthTokens, pendingCommits, prComments, prFileApprovals, prMergeLog, users, } from '../database/schema.js';
4
+ export class AccountErasureService {
5
+ db;
6
+ participants;
7
+ constructor(db, participants = []) {
8
+ this.db = db;
9
+ this.participants = participants;
10
+ }
11
+ async listUsers() {
12
+ const rows = await this.db
13
+ .select({ id: users.id, email: users.email, name: users.name, createdAt: users.createdAt })
14
+ .from(users)
15
+ .orderBy(users.email);
16
+ return rows.map((r) => ({ ...r, createdAt: r.createdAt.getTime() }));
17
+ }
18
+ async eraseUser(userId) {
19
+ const [user] = await this.db.select().from(users).where(eq(users.id, userId)).limit(1);
20
+ if (!user)
21
+ return false;
22
+ const target = {
23
+ userId,
24
+ email: user.email.toLowerCase(),
25
+ erasedEmail: `deleted-${randomUUID()}@erased.invalid`,
26
+ erasedName: 'Deleted user',
27
+ };
28
+ // Participant pre-passes (e.g. chat threads + their Mastra memory) run
29
+ // outside the transaction on purpose: external stores are separate
30
+ // systems, and the pre-passes are idempotent, so a failure here leaves a
31
+ // retryable state rather than a half-committed one.
32
+ for (const p of this.participants) {
33
+ if (p.before)
34
+ await p.before(target);
35
+ }
36
+ const postCommit = [];
37
+ await this.db.transaction(async (tx) => {
38
+ // Token-shaped rows (all hashed, but they key to the user). Dependents
39
+ // like the LLM-usage metering rows cascade at the DB layer.
40
+ await tx.delete(externalApiKeys).where(eq(externalApiKeys.userId, userId));
41
+ await tx.delete(oauthAuthCodes).where(eq(oauthAuthCodes.userId, userId));
42
+ await tx.delete(oauthTokens).where(eq(oauthTokens.userId, userId));
43
+ // Personal-data rows the core owns.
44
+ await tx.delete(fileLocks).where(eq(fileLocks.holderUserId, userId));
45
+ // Audit rows: anonymize in place (no user FK on these; they key by email).
46
+ await tx
47
+ .update(prFileApprovals)
48
+ .set({ approverEmail: target.erasedEmail, approverName: target.erasedName })
49
+ .where(eq(prFileApprovals.approverEmail, target.email));
50
+ await tx
51
+ .update(prMergeLog)
52
+ .set({ triggeredByEmail: target.erasedEmail, triggeredByName: target.erasedName })
53
+ .where(eq(prMergeLog.triggeredByEmail, target.email));
54
+ await tx
55
+ .update(prComments)
56
+ .set({ authorEmail: target.erasedEmail, authorName: target.erasedName })
57
+ .where(eq(prComments.authorEmail, target.email));
58
+ await tx
59
+ .update(changeRequests)
60
+ .set({ authorEmail: target.erasedEmail, authorName: target.erasedName })
61
+ .where(eq(changeRequests.authorEmail, target.email));
62
+ // Queued-but-uncommitted saves: the eventual git commit is authored with
63
+ // the placeholder instead of the erased identity. The file content still
64
+ // lands — erasing an account must not lose other people's KB state.
65
+ await tx
66
+ .update(pendingCommits)
67
+ .set({ authorEmail: target.erasedEmail, authorName: target.erasedName })
68
+ .where(eq(pendingCommits.authorEmail, target.email));
69
+ // Module-owned rows, before the users delete so FKs onto users are
70
+ // still satisfiable — and so a participant that MISSES rows makes the
71
+ // users delete below fail on its RESTRICT FK, rolling everything back:
72
+ // a loud retry, never a silent orphan.
73
+ for (const p of this.participants) {
74
+ if (!p.inTransaction)
75
+ continue;
76
+ const cb = await p.inTransaction(tx, target);
77
+ if (cb)
78
+ postCommit.push(cb);
79
+ }
80
+ // Finally the user row (plus its ON DELETE CASCADE dependents).
81
+ await tx.delete(users).where(eq(users.id, userId));
82
+ });
83
+ // Post-commit callbacks (e.g. Mastra memory cleanup for chat threads
84
+ // captured inside the transaction).
85
+ for (const cb of postCommit)
86
+ await cb();
87
+ console.log(`[account-erasure] erased user id=${userId}`);
88
+ return true;
89
+ }
90
+ }
91
+ //# sourceMappingURL=account-erasure.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-erasure.service.js","sourceRoot":"","sources":["../../../src/modules/auth/account-erasure.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { Request, Response, NextFunction } from 'express';
2
+ import type { AuthService } from './auth.service.js';
3
+ declare global {
4
+ namespace Express {
5
+ interface Request {
6
+ userId?: string;
7
+ userEmail?: string;
8
+ }
9
+ }
10
+ }
11
+ /**
12
+ * Name of the auth cookie set alongside the Bearer JWT at login. The cookie
13
+ * exists solely so the SSE route can authenticate — the browser's
14
+ * `EventSource` API can't set custom headers, so a Bearer token in
15
+ * `Authorization` can't reach it. All other routes still use the Bearer
16
+ * header, which the frontend stores in memory and attaches via `authFetch`.
17
+ *
18
+ * Same JWT value as the Bearer token. The cookie is `HttpOnly` + `SameSite=Lax`
19
+ * + `Secure` (in prod) — see `auth.routes.ts` for the issue site.
20
+ */
21
+ export declare const AUTH_COOKIE_NAME = "bevel_token";
22
+ export declare function createAuthMiddleware(authService: AuthService): (req: Request, res: Response, next: NextFunction) => void;
23
+ //# sourceMappingURL=auth.middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.middleware.d.ts","sourceRoot":"","sources":["../../../src/modules/auth/auth.middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,MAAM,CAAC,EAAE,MAAM,CAAC;YAChB,SAAS,CAAC,EAAE,MAAM,CAAC;SACpB;KACF;CACF;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,gBAAgB,CAAC;AAyB9C,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,WAAW,IACnD,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,UA4BxD"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Name of the auth cookie set alongside the Bearer JWT at login. The cookie
3
+ * exists solely so the SSE route can authenticate — the browser's
4
+ * `EventSource` API can't set custom headers, so a Bearer token in
5
+ * `Authorization` can't reach it. All other routes still use the Bearer
6
+ * header, which the frontend stores in memory and attaches via `authFetch`.
7
+ *
8
+ * Same JWT value as the Bearer token. The cookie is `HttpOnly` + `SameSite=Lax`
9
+ * + `Secure` (in prod) — see `auth.routes.ts` for the issue site.
10
+ */
11
+ export const AUTH_COOKIE_NAME = 'bevel_token';
12
+ /**
13
+ * Read the auth cookie out of the raw `Cookie` header without pulling in
14
+ * `cookie-parser`. We only ever look for one cookie, so a tiny parser
15
+ * beats the dep surface of a middleware. Returns `null` if the cookie
16
+ * is absent or empty.
17
+ */
18
+ function readAuthCookie(req) {
19
+ const header = req.headers.cookie;
20
+ if (!header)
21
+ return null;
22
+ for (const segment of header.split(';')) {
23
+ const trimmed = segment.trim();
24
+ if (!trimmed.startsWith(`${AUTH_COOKIE_NAME}=`))
25
+ continue;
26
+ const value = trimmed.slice(AUTH_COOKIE_NAME.length + 1);
27
+ if (!value)
28
+ return null;
29
+ try {
30
+ return decodeURIComponent(value);
31
+ }
32
+ catch {
33
+ return value;
34
+ }
35
+ }
36
+ return null;
37
+ }
38
+ export function createAuthMiddleware(authService) {
39
+ return (req, res, next) => {
40
+ // Bearer is the primary path — every JSON API call in the frontend
41
+ // attaches it via `authFetch`. Cookie is the fallback for transports
42
+ // that can't carry headers (EventSource, image tags), set at login by
43
+ // `/auth/login` so SSE in particular Just Works after login without
44
+ // any frontend cooperation.
45
+ const header = req.headers.authorization;
46
+ let token = null;
47
+ if (header && header.startsWith('Bearer ')) {
48
+ token = header.slice('Bearer '.length).trim() || null;
49
+ }
50
+ if (!token) {
51
+ token = readAuthCookie(req);
52
+ }
53
+ if (!token) {
54
+ res.status(401).json({ error: 'Missing or invalid Authorization header or auth cookie' });
55
+ return;
56
+ }
57
+ try {
58
+ const { userId, email } = authService.verifyToken(token);
59
+ req.userId = userId;
60
+ req.userEmail = email;
61
+ next();
62
+ }
63
+ catch {
64
+ res.status(401).json({ error: 'Invalid or expired token' });
65
+ }
66
+ };
67
+ }
68
+ //# sourceMappingURL=auth.middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.middleware.js","sourceRoot":"","sources":["../../../src/modules/auth/auth.middleware.ts"],"names":[],"mappings":"AAaA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAa,CAAC;AAE9C;;;;;GAKG;AACH,SAAS,cAAc,CAAC,GAAY;IAClC,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;IAClC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACxC,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC/B,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,gBAAgB,GAAG,CAAC;YAAE,SAAS;QAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,IAAI,CAAC;YACH,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,WAAwB;IAC3D,OAAO,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;QACzD,mEAAmE;QACnE,qEAAqE;QACrE,sEAAsE;QACtE,oEAAoE;QACpE,4BAA4B;QAC5B,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;QACzC,IAAI,KAAK,GAAkB,IAAI,CAAC;QAChC,IAAI,MAAM,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3C,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;QACxD,CAAC;QACD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC;QACD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,wDAAwD,EAAE,CAAC,CAAC;YAC1F,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YACzD,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC;YACpB,GAAG,CAAC,SAAS,GAAG,KAAK,CAAC;YACtB,IAAI,EAAE,CAAC;QACT,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,25 @@
1
+ import express from 'express';
2
+ import type { AuthService } from './auth.service.js';
3
+ /**
4
+ * Max age of the JWT cookie (seconds). Matches the JWT's own `expiresIn:
5
+ * '7d'` so the cookie expires when the token does — browsers stop
6
+ * sending it past expiry, sparing the auth middleware verifying tokens
7
+ * that are guaranteed to fail.
8
+ */
9
+ export declare const AUTH_COOKIE_MAX_AGE_S: number;
10
+ /**
11
+ * A pluggable SSO login method. Core ships password login only; the
12
+ * composition root passes provider plugins (e.g. Microsoft OIDC, owned by the
13
+ * sharepoint module) which mount their own routes under `/auth/<key>/…` and
14
+ * are advertised to the login screen under `key` by the capability probe.
15
+ * A plugin is only passed in when its machinery is configured AND the
16
+ * instance hasn't switched it off — presence means enabled.
17
+ */
18
+ export interface AuthProviderPlugin {
19
+ /** Probe key + route namespace (e.g. 'microsoft' → /auth/microsoft/…). */
20
+ readonly key: string;
21
+ /** Mount the provider's routes (login redirect, callback) on the auth router. */
22
+ mountRoutes(router: express.Router, authService: AuthService): void;
23
+ }
24
+ export declare function createAuthRoutes(authService: AuthService, authMiddleware: express.RequestHandler, providers?: AuthProviderPlugin[], passwordLoginEnabled?: boolean): express.Router;
25
+ //# sourceMappingURL=auth.routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.routes.d.ts","sourceRoot":"","sources":["../../../src/modules/auth/auth.routes.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,QAAmB,CAAC;AAEtD;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,0EAA0E;IAC1E,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;CACrE;AAED,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,WAAW,EACxB,cAAc,EAAE,OAAO,CAAC,cAAc,EACtC,SAAS,GAAE,kBAAkB,EAAO,EACpC,oBAAoB,UAAO,GAC1B,OAAO,CAAC,MAAM,CAgEhB"}
@@ -0,0 +1,72 @@
1
+ import express from 'express';
2
+ import { AUTH_COOKIE_NAME } from './auth.middleware.js'; // also imports Express Request augmentation
3
+ /**
4
+ * Max age of the JWT cookie (seconds). Matches the JWT's own `expiresIn:
5
+ * '7d'` so the cookie expires when the token does — browsers stop
6
+ * sending it past expiry, sparing the auth middleware verifying tokens
7
+ * that are guaranteed to fail.
8
+ */
9
+ export const AUTH_COOKIE_MAX_AGE_S = 7 * 24 * 60 * 60;
10
+ export function createAuthRoutes(authService, authMiddleware, providers = [], passwordLoginEnabled = true) {
11
+ const router = express.Router();
12
+ // POST /api/auth/login — email + shared-password login (unprotected)
13
+ router.post('/auth/login', async (req, res) => {
14
+ if (!passwordLoginEnabled) {
15
+ res.status(403).json({ error: 'Password login is disabled' });
16
+ return;
17
+ }
18
+ const { email, password } = req.body;
19
+ if (!email || !password) {
20
+ res.status(400).json({ error: 'email and password are required' });
21
+ return;
22
+ }
23
+ try {
24
+ const result = await authService.loginWithPassword(email, password);
25
+ // Also set the JWT as an HttpOnly cookie so transports that can't
26
+ // carry headers (EventSource for SSE, image tags) authenticate
27
+ // automatically. JSON callers continue to use the Bearer header
28
+ // returned in the body. Secure in production; off in dev so the
29
+ // cookie survives `http://localhost` requests.
30
+ res.cookie(AUTH_COOKIE_NAME, result.token, {
31
+ httpOnly: true,
32
+ sameSite: 'lax',
33
+ secure: process.env.NODE_ENV === 'production',
34
+ maxAge: AUTH_COOKIE_MAX_AGE_S * 1000,
35
+ path: '/',
36
+ });
37
+ res.json(result);
38
+ }
39
+ catch (error) {
40
+ const msg = error instanceof Error ? error.message : 'Unknown error';
41
+ console.error('Login error:', msg);
42
+ res.status(401).json({ error: 'Authentication failed' });
43
+ }
44
+ });
45
+ // GET /api/auth/providers — unprotected capability probe so the login screen
46
+ // knows which login methods to render. SSO providers appear under their key.
47
+ router.get('/auth/providers', (_req, res) => {
48
+ res.json({
49
+ password: passwordLoginEnabled,
50
+ ...Object.fromEntries(providers.map((p) => [p.key, true])),
51
+ });
52
+ });
53
+ for (const provider of providers)
54
+ provider.mountRoutes(router, authService);
55
+ // GET /api/auth/me — validate stored JWT, return user info (protected)
56
+ router.get('/auth/me', authMiddleware, async (req, res) => {
57
+ try {
58
+ const user = await authService.getUserById(req.userId);
59
+ if (!user) {
60
+ res.status(404).json({ error: 'User not found' });
61
+ return;
62
+ }
63
+ res.json(user);
64
+ }
65
+ catch (error) {
66
+ const msg = error instanceof Error ? error.message : 'Unknown error';
67
+ res.status(500).json({ error: msg });
68
+ }
69
+ });
70
+ return router;
71
+ }
72
+ //# sourceMappingURL=auth.routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.routes.js","sourceRoot":"","sources":["../../../src/modules/auth/auth.routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ import type { Database } from '../database/connection.js';
2
+ import type { CoreConfig } from '../../core-config.js';
3
+ import type { AuthUser } from '@bevel-software/platform-shared';
4
+ export declare class AuthService {
5
+ private readonly db;
6
+ private readonly config;
7
+ constructor(db: Database, config: CoreConfig);
8
+ loginWithPassword(email: string, password: string): Promise<{
9
+ token: string;
10
+ user: AuthUser;
11
+ }>;
12
+ /**
13
+ * Establish a session for a user who authenticated via "Sign in with
14
+ * Microsoft". Same upsert-by-email + JWT path as password login — the only
15
+ * difference is identity came from a verified Microsoft id_token instead of
16
+ * the shared password. Email is the idempotency key, so a user who first
17
+ * used password login and later signs in with Microsoft (same email) keeps
18
+ * the same account/id.
19
+ */
20
+ loginWithMicrosoft(email: string, name: string): Promise<{
21
+ token: string;
22
+ user: AuthUser;
23
+ }>;
24
+ private signToken;
25
+ /**
26
+ * Get-or-create a user record by email, without issuing a session token.
27
+ * Used by the embed surface: an Atlassian (Forge) editor whose identity was
28
+ * verified server-side needs a real user row so file-lock commits attribute
29
+ * to them — but they never get a Bevel browser session. Same email-keyed
30
+ * upsert as the login paths, so an embed editor who later logs in keeps the
31
+ * same account/id. Returns `null` for a malformed email.
32
+ */
33
+ getOrCreateByEmail(email: string, name?: string): Promise<{
34
+ id: string;
35
+ email: string;
36
+ name: string;
37
+ } | null>;
38
+ private upsertUserByEmail;
39
+ verifyToken(token: string): {
40
+ userId: string;
41
+ email: string;
42
+ };
43
+ /**
44
+ * Resolve a set of `authorId` hashes back to the app users that produced
45
+ * them. Used by the PR list to display the human who triggered each PR
46
+ * instead of the shared GitHub service account.
47
+ *
48
+ * Loads all users and hashes them in-process rather than indexing on a
49
+ * stored hash column — the user table is small (one row per team member)
50
+ * and refreshes are infrequent (PR list polls at 60s), so the cost is
51
+ * negligible and we avoid carrying a denormalised hash column.
52
+ */
53
+ findUsersByEmailHash(hashes: Set<string>): Promise<Map<string, {
54
+ id: string;
55
+ email: string;
56
+ name: string;
57
+ }>>;
58
+ getUserById(userId: string): Promise<AuthUser | null>;
59
+ /**
60
+ * Whether `email` passes the optional `ALLOWED_EMAIL_DOMAINS` guard. Returns
61
+ * true when no guard is configured (the default). Matches the email's domain
62
+ * exactly or as a subdomain, so `bevel.software` admits `a@bevel.software`
63
+ * and `a@eu.bevel.software` but not `a@notbevel.software`. When a guard IS
64
+ * configured, a missing/blank email fails closed. Exposed so non-login
65
+ * surfaces (the embed panel) can apply the same gate.
66
+ */
67
+ isEmailDomainAllowed(email: string): boolean;
68
+ /**
69
+ * Enforce {@link isEmailDomainAllowed} at the login paths. No-op when the
70
+ * guard is unset. Expects an already-normalized (trimmed, lower-cased,
71
+ * regex-validated) email.
72
+ */
73
+ private assertAllowedDomain;
74
+ private checkPassword;
75
+ }
76
+ //# sourceMappingURL=auth.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.service.d.ts","sourceRoot":"","sources":["../../../src/modules/auth/auth.service.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAmBhE,qBAAa,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,EAAE;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,EAAE,EAAE,QAAQ,EACZ,MAAM,EAAE,UAAU;IAG/B,iBAAiB,CACrB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC;IAiB7C;;;;;;;OAOG;IACG,kBAAkB,CACtB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC;IAW7C,OAAO,CAAC,SAAS;IAIjB;;;;;;;OAOG;IACG,kBAAkB,CACtB,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;YAQhD,iBAAiB;IAS/B,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;IAQ7D;;;;;;;;;OASG;IACG,oBAAoB,CACxB,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,GAClB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAY9D,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAiB3D;;;;;;;OAOG;IACH,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAQ5C;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAM3B,OAAO,CAAC,aAAa;CAiBtB"}
@@ -0,0 +1,168 @@
1
+ import { timingSafeEqual } from 'node:crypto';
2
+ import jwt from 'jsonwebtoken';
3
+ import { eq } from 'drizzle-orm';
4
+ import { users } from '../database/schema.js';
5
+ import { hashEmail } from '../../shared/hash-email.js';
6
+ const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
7
+ function toAuthUser(user) {
8
+ return {
9
+ id: user.id,
10
+ email: user.email,
11
+ name: user.name,
12
+ avatarUrl: user.avatarUrl ?? undefined,
13
+ };
14
+ }
15
+ export class AuthService {
16
+ db;
17
+ config;
18
+ constructor(db, config) {
19
+ this.db = db;
20
+ this.config = config;
21
+ }
22
+ async loginWithPassword(email, password) {
23
+ const normalizedEmail = (email ?? '').trim().toLowerCase();
24
+ if (!EMAIL_REGEX.test(normalizedEmail)) {
25
+ throw new Error('Invalid email');
26
+ }
27
+ this.assertAllowedDomain(normalizedEmail);
28
+ if (!this.checkPassword(password ?? '')) {
29
+ throw new Error('Invalid password');
30
+ }
31
+ // Derive a default display name from the local-part of the email
32
+ const defaultName = normalizedEmail.split('@')[0] || normalizedEmail;
33
+ const user = await this.upsertUserByEmail(normalizedEmail, defaultName);
34
+ return { token: this.signToken(user.id, user.email), user: toAuthUser(user) };
35
+ }
36
+ /**
37
+ * Establish a session for a user who authenticated via "Sign in with
38
+ * Microsoft". Same upsert-by-email + JWT path as password login — the only
39
+ * difference is identity came from a verified Microsoft id_token instead of
40
+ * the shared password. Email is the idempotency key, so a user who first
41
+ * used password login and later signs in with Microsoft (same email) keeps
42
+ * the same account/id.
43
+ */
44
+ async loginWithMicrosoft(email, name) {
45
+ const normalizedEmail = (email ?? '').trim().toLowerCase();
46
+ if (!EMAIL_REGEX.test(normalizedEmail)) {
47
+ throw new Error('Microsoft sign-in returned an invalid email');
48
+ }
49
+ this.assertAllowedDomain(normalizedEmail);
50
+ const displayName = (name ?? '').trim() || normalizedEmail.split('@')[0] || normalizedEmail;
51
+ const user = await this.upsertUserByEmail(normalizedEmail, displayName);
52
+ return { token: this.signToken(user.id, user.email), user: toAuthUser(user) };
53
+ }
54
+ signToken(userId, email) {
55
+ return jwt.sign({ userId, email }, this.config.jwtSecret, { expiresIn: '7d' });
56
+ }
57
+ /**
58
+ * Get-or-create a user record by email, without issuing a session token.
59
+ * Used by the embed surface: an Atlassian (Forge) editor whose identity was
60
+ * verified server-side needs a real user row so file-lock commits attribute
61
+ * to them — but they never get a Bevel browser session. Same email-keyed
62
+ * upsert as the login paths, so an embed editor who later logs in keeps the
63
+ * same account/id. Returns `null` for a malformed email.
64
+ */
65
+ async getOrCreateByEmail(email, name) {
66
+ const normalizedEmail = (email ?? '').trim().toLowerCase();
67
+ if (!EMAIL_REGEX.test(normalizedEmail))
68
+ return null;
69
+ const displayName = (name ?? '').trim() || normalizedEmail.split('@')[0] || normalizedEmail;
70
+ const user = await this.upsertUserByEmail(normalizedEmail, displayName);
71
+ return { id: user.id, email: user.email, name: user.name };
72
+ }
73
+ async upsertUserByEmail(email, name) {
74
+ const [user] = await this.db
75
+ .insert(users)
76
+ .values({ email, name })
77
+ .onConflictDoUpdate({ target: users.email, set: { updatedAt: new Date() } })
78
+ .returning();
79
+ return user;
80
+ }
81
+ verifyToken(token) {
82
+ const decoded = jwt.verify(token, this.config.jwtSecret);
83
+ return { userId: decoded.userId, email: decoded.email };
84
+ }
85
+ /**
86
+ * Resolve a set of `authorId` hashes back to the app users that produced
87
+ * them. Used by the PR list to display the human who triggered each PR
88
+ * instead of the shared GitHub service account.
89
+ *
90
+ * Loads all users and hashes them in-process rather than indexing on a
91
+ * stored hash column — the user table is small (one row per team member)
92
+ * and refreshes are infrequent (PR list polls at 60s), so the cost is
93
+ * negligible and we avoid carrying a denormalised hash column.
94
+ */
95
+ async findUsersByEmailHash(hashes) {
96
+ const result = new Map();
97
+ if (hashes.size === 0)
98
+ return result;
99
+ const rows = await this.db.select().from(users);
100
+ for (const row of rows) {
101
+ const h = hashEmail(row.email);
102
+ if (!hashes.has(h))
103
+ continue;
104
+ result.set(h, { id: row.id, email: row.email, name: row.name });
105
+ }
106
+ return result;
107
+ }
108
+ async getUserById(userId) {
109
+ const [user] = await this.db
110
+ .select()
111
+ .from(users)
112
+ .where(eq(users.id, userId))
113
+ .limit(1);
114
+ if (!user)
115
+ return null;
116
+ return {
117
+ id: user.id,
118
+ email: user.email,
119
+ name: user.name,
120
+ avatarUrl: user.avatarUrl ?? undefined,
121
+ };
122
+ }
123
+ /**
124
+ * Whether `email` passes the optional `ALLOWED_EMAIL_DOMAINS` guard. Returns
125
+ * true when no guard is configured (the default). Matches the email's domain
126
+ * exactly or as a subdomain, so `bevel.software` admits `a@bevel.software`
127
+ * and `a@eu.bevel.software` but not `a@notbevel.software`. When a guard IS
128
+ * configured, a missing/blank email fails closed. Exposed so non-login
129
+ * surfaces (the embed panel) can apply the same gate.
130
+ */
131
+ isEmailDomainAllowed(email) {
132
+ const allowed = this.config.allowedEmailDomains;
133
+ if (allowed.length === 0)
134
+ return true;
135
+ const domain = (email ?? '').trim().toLowerCase().split('@')[1] ?? '';
136
+ if (!domain)
137
+ return false;
138
+ return allowed.some((d) => domain === d || domain.endsWith(`.${d}`));
139
+ }
140
+ /**
141
+ * Enforce {@link isEmailDomainAllowed} at the login paths. No-op when the
142
+ * guard is unset. Expects an already-normalized (trimmed, lower-cased,
143
+ * regex-validated) email.
144
+ */
145
+ assertAllowedDomain(normalizedEmail) {
146
+ if (!this.isEmailDomainAllowed(normalizedEmail)) {
147
+ throw new Error('Email domain is not allowed');
148
+ }
149
+ }
150
+ checkPassword(provided) {
151
+ const expected = this.config.testPassword;
152
+ // Reject if no password is configured on the server
153
+ if (!expected)
154
+ return false;
155
+ const a = Buffer.from(provided, 'utf8');
156
+ const b = Buffer.from(expected, 'utf8');
157
+ // Pad both buffers to the same length so timingSafeEqual runs unconditionally —
158
+ // returning early on length mismatch would leak the expected password's length via timing.
159
+ const len = Math.max(a.length, b.length);
160
+ const aPadded = Buffer.alloc(len);
161
+ const bPadded = Buffer.alloc(len);
162
+ a.copy(aPadded);
163
+ b.copy(bPadded);
164
+ const equal = timingSafeEqual(aPadded, bPadded);
165
+ return equal && a.length === b.length;
166
+ }
167
+ }
168
+ //# sourceMappingURL=auth.service.js.map