@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,224 @@
1
+ /**
2
+ * In-process event bus that fans workflow state-change events out to
3
+ * subscribed SSE sessions. The shape and scope rules live in
4
+ * `@bevel-software/platform-shared/workflow/events.ts` — this module is the runtime that
5
+ * makes them deliverable.
6
+ *
7
+ * **What this owns**
8
+ *
9
+ * 1. **The monotonic event id.** Each `emit` stamps the next id; clients
10
+ * reconnecting with `Last-Event-ID: <n>` use it to replay everything
11
+ * they missed.
12
+ *
13
+ * 2. **A per-process ring buffer** of the last `BUFFER_CAPACITY` events.
14
+ * Replay works if the gap is short. Long disconnects fall back to
15
+ * `{ kind: 'resync' }` so the client refetches cleanly.
16
+ *
17
+ * 3. **A registry of subscribers**, each owning a per-session push
18
+ * function. On `emit`, every subscriber that matches the event's scope
19
+ * (see `isWorkspaceScoped` / `isUserScoped`) gets the event pushed
20
+ * synchronously to its push callback — the route layer translates that
21
+ * to an SSE `data:` line.
22
+ *
23
+ * **What this does NOT own**
24
+ *
25
+ * - Transport (SSE framing, heartbeats): the route layer.
26
+ * - Auth (which user owns a session): the route layer wires
27
+ * userId + sessionId in at subscription time, this just stores them.
28
+ * - Persistence: in-memory only. A server restart resets the id counter
29
+ * and empties the buffer; clients that reconnect after a restart will
30
+ * get a `resync` (their stored Last-Event-ID is necessarily older than
31
+ * the new buffer can serve), which is exactly the right behavior.
32
+ *
33
+ * **Concurrency** — Node is single-threaded for JS, so a synchronous fan-out
34
+ * inside `emit` is safe. Subscribers must not throw from their push
35
+ * callback; we wrap every push in try/catch and log so one bad subscriber
36
+ * never blocks the rest.
37
+ */
38
+ import { isUserScoped, isWorkspaceScoped, } from '@bevel-software/platform-shared';
39
+ /**
40
+ * Capacity of the global event ring buffer. A new event evicts the oldest
41
+ * when full. Sized for "should comfortably catch any client through a brief
42
+ * network blip" — 500 events at e.g. one edit per second buys ~8 minutes of
43
+ * coverage, plenty for transient reconnects. Sized down would push more
44
+ * clients onto the `resync` path; sized up wastes RSS on no-op edits.
45
+ */
46
+ const BUFFER_CAPACITY = 500;
47
+ /**
48
+ * Decode-once, idempotent. Both sides of the focus / workspaceId
49
+ * comparison get fed through this so we don't care whether the caller
50
+ * sent the URL-encoded form (`razvan-radulescu%2Fsc`) or the canonical
51
+ * form (`razvan-radulescu/sc`). Catches malformed input by returning the
52
+ * original string — broken encoding shouldn't crash the dispatcher.
53
+ */
54
+ function canonicalize(workspaceId) {
55
+ try {
56
+ return decodeURIComponent(workspaceId);
57
+ }
58
+ catch {
59
+ return workspaceId;
60
+ }
61
+ }
62
+ export class WorkflowEventBus {
63
+ nextId = 1;
64
+ buffer = [];
65
+ subscribers = new Map();
66
+ /**
67
+ * Stamp `payload` with `id` + `ts`, append to the ring buffer, then fan
68
+ * out synchronously to every matching subscriber. Returns the stamped
69
+ * event so callers (e.g. tests, debug logs) can see what was actually
70
+ * delivered.
71
+ */
72
+ emit(payload) {
73
+ const event = {
74
+ id: this.nextId++,
75
+ ts: new Date().toISOString(),
76
+ ...payload,
77
+ };
78
+ this.buffer.push(event);
79
+ if (this.buffer.length > BUFFER_CAPACITY) {
80
+ this.buffer.shift();
81
+ }
82
+ // Single-line emit log with all the fields most useful for tracing a
83
+ // failed delivery: which event, which scope it'll filter on, and the
84
+ // total subscriber pool size before fan-out. Per-subscriber matched/
85
+ // skipped decisions are logged below at debug level.
86
+ const scope = 'workspaceId' in event && event.workspaceId
87
+ ? `ws=${event.workspaceId}`
88
+ : 'forUserId' in event && event.forUserId
89
+ ? `user=${event.forUserId}`
90
+ : 'global';
91
+ const extra = [];
92
+ if ('path' in event && event.path)
93
+ extra.push(`path=${event.path}`);
94
+ if ('branch' in event && event.branch)
95
+ extra.push(`branch=${event.branch}`);
96
+ if ('newSha' in event && event.newSha !== undefined)
97
+ extra.push(`sha=${event.newSha ?? 'null'}`);
98
+ if ('holderName' in event && event.holderName)
99
+ extra.push(`holder=${event.holderName}`);
100
+ console.log(`[event-bus] EMIT id=${event.id} kind=${event.kind} ${scope}${extra.length ? ' ' + extra.join(' ') : ''} subs=${this.subscribers.size}`);
101
+ let matched = 0;
102
+ let skipped = 0;
103
+ for (const sub of this.subscribers.values()) {
104
+ // Best-effort per subscriber — one bad subscriber must not block
105
+ // the rest of the fan-out OR propagate back to the caller. The
106
+ // try/catch covers both the scope check (`matches` reaches into
107
+ // `sub.getFocusedWorkspaceId()`, which could throw if a bizarre
108
+ // subscriber holds buggy state) and the dispatch itself, so
109
+ // workflow mutations stay successful even if a listener throws.
110
+ // Callers can rely on `emit` never throwing, so they don't need
111
+ // to wrap every emit call site in their own try/catch.
112
+ try {
113
+ if (!this.matches(event, sub)) {
114
+ skipped++;
115
+ continue;
116
+ }
117
+ sub.push(event);
118
+ matched++;
119
+ }
120
+ catch (err) {
121
+ console.warn(`[event-bus] dispatch to session ${sub.sessionId} threw:`, err instanceof Error ? err.message : err);
122
+ }
123
+ }
124
+ console.log(`[event-bus] EMIT id=${event.id} kind=${event.kind} → delivered=${matched} skipped=${skipped}`);
125
+ return event;
126
+ }
127
+ /**
128
+ * Register a subscriber. Returns an `unsubscribe` function the route
129
+ * layer is expected to call from `res.on('close', …)` — without it a
130
+ * disconnected client leaks the session entry forever.
131
+ */
132
+ subscribe(sub) {
133
+ this.subscribers.set(sub.sessionId, sub);
134
+ console.log(`[event-bus] SUBSCRIBE session=${sub.sessionId} user=${sub.userId} → total=${this.subscribers.size}`);
135
+ return () => {
136
+ // Only delete if the same Subscriber is still registered — protects
137
+ // against a stale unsubscribe (e.g. a reconnect replaced the entry
138
+ // before the old `close` handler fired).
139
+ if (this.subscribers.get(sub.sessionId) === sub) {
140
+ this.subscribers.delete(sub.sessionId);
141
+ console.log(`[event-bus] UNSUBSCRIBE session=${sub.sessionId} user=${sub.userId} → total=${this.subscribers.size}`);
142
+ }
143
+ };
144
+ }
145
+ /**
146
+ * Snapshot of every event in the ring buffer strictly newer than
147
+ * `lastSeenId` that this `sub` would have received if it had been
148
+ * subscribed at the time. Used by the SSE route on reconnect:
149
+ *
150
+ * - The client sends `Last-Event-ID: <n>` (browser does this
151
+ * automatically when an `EventSource` reconnects).
152
+ * - The route fetches `replayAfter(n, sub)` and emits each event
153
+ * before resuming live delivery.
154
+ *
155
+ * Returns `null` when the gap is larger than the buffer — the route
156
+ * sends a `resync` event in that case and the client refetches everything.
157
+ * "Gap is larger" is detected by checking whether the buffer's oldest id
158
+ * is greater than `lastSeenId + 1` (i.e. we evicted events the client
159
+ * needs to see).
160
+ */
161
+ replayAfter(lastSeenId, sub) {
162
+ // Empty buffer: a client that never saw anything (lastSeenId === 0) has
163
+ // nothing to replay and the empty array is correct. A client that DID
164
+ // see events (lastSeenId > 0) but reached an empty buffer means the
165
+ // process restarted — the id counter reset to 1, so anything the client
166
+ // saw before is unreachable. Force a `resync` rather than silently
167
+ // delivering nothing.
168
+ if (this.buffer.length === 0) {
169
+ return lastSeenId === 0 ? [] : null;
170
+ }
171
+ const oldestBufferedId = this.buffer[0].id;
172
+ const newestBufferedId = this.buffer[this.buffer.length - 1].id;
173
+ if (oldestBufferedId > lastSeenId + 1) {
174
+ return null; // Caller emits a `resync`.
175
+ }
176
+ // Process restart can also leave `lastSeenId` ahead of the buffer's
177
+ // newest id (counter reset → newer events have lower ids than what the
178
+ // client last saw). Same outcome: client must resync from scratch.
179
+ if (lastSeenId > newestBufferedId) {
180
+ return null;
181
+ }
182
+ const tail = this.buffer.filter((e) => e.id > lastSeenId);
183
+ return tail.filter((e) => this.matches(e, sub));
184
+ }
185
+ /** Subscriber count — exposed for `/health` and tests. */
186
+ size() {
187
+ return this.subscribers.size;
188
+ }
189
+ /**
190
+ * Filter rule that decides whether `event` should reach `sub`:
191
+ *
192
+ * - Workspace-scoped events: only sessions currently focused on the
193
+ * same `workspaceId`.
194
+ * - User-scoped events: only sessions whose `userId` matches `forUserId`.
195
+ * - Global events (heartbeat, resync, change-request-*): everyone.
196
+ *
197
+ * The focus check resolves through `getFocusedWorkspaceId()` so a session
198
+ * that hasn't yet POSTed its focus gets no workspace events (correct —
199
+ * we don't know what it cares about).
200
+ */
201
+ matches(event, sub) {
202
+ if (isWorkspaceScoped(event)) {
203
+ const focus = sub.getFocusedWorkspaceId();
204
+ if (focus === null)
205
+ return false;
206
+ // **Normalise URL encoding before comparing.** The frontend stores
207
+ // `workspace.id` as `encodeURIComponent(branch)` (e.g.
208
+ // `razvan-radulescu%2Fsc`) and sends that as the focus value via
209
+ // the POST /focus endpoint. The backend route handlers, however,
210
+ // extract `req.params.id` which Express auto-decodes — so events
211
+ // fire with `workspaceId = razvan-radulescu/sc`. Naïve `===` then
212
+ // rejects every workspace-scoped event for any branch that
213
+ // contains a `/`, silently dropping all live updates (lock state,
214
+ // file-changed, fs-tree) on feature branches. Decoding both sides
215
+ // collapses the two forms into the same canonical key.
216
+ return canonicalize(focus) === canonicalize(event.workspaceId);
217
+ }
218
+ if (isUserScoped(event)) {
219
+ return sub.userId === event.forUserId;
220
+ }
221
+ return true;
222
+ }
223
+ }
224
+ //# sourceMappingURL=event-bus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../../../src/modules/workflow/event-bus.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * SSE event-bus HTTP surface.
3
+ *
4
+ * GET /api/events?session=<sessionId> — open the long-lived SSE stream
5
+ * POST /api/events/:sessionId/focus — update which workspace this
6
+ * session cares about (changes
7
+ * over the connection's lifetime
8
+ * as the user / agent switches
9
+ * branches)
10
+ *
11
+ * **Why a per-tab session id, not per-workspace** — the connection must
12
+ * survive a workspace re-focus (when the user navigates between branches
13
+ * the URL changes and the workspace bootstrap rebinds `workspaceId`, but
14
+ * the EventSource stays open). So scope = `(userId, sessionId)`; the
15
+ * "what workspace events do I want" state is mutable and lives in the
16
+ * focus endpoint above.
17
+ *
18
+ * **Auth** — the SSE route can't read `Authorization: Bearer …` (the
19
+ * browser's EventSource API can't set headers), so the auth middleware
20
+ * also accepts the JWT from the `bevel_token` cookie set at login. The
21
+ * focus POST goes through the regular auth middleware too, and verifies
22
+ * that the cookie-authed user matches the session's owner.
23
+ *
24
+ * **Reconnect** — the browser's EventSource auto-reconnects on close
25
+ * (~3 s backoff). On reconnect it sends `Last-Event-ID: <n>` and the
26
+ * route replays anything still in the bus's ring buffer; if the buffer
27
+ * has evicted past `n`, the route emits `{ kind: 'resync' }` so the
28
+ * client refetches state from scratch.
29
+ *
30
+ * **Heartbeat** — every 25 s the route writes an SSE comment (`:\n\n`).
31
+ * Keeps proxies (nginx, Coolify's Traefik, Cloudflare) from killing the
32
+ * connection as idle. Cheap (~15 bytes), eliminates a whole class of bug.
33
+ */
34
+ import type { Response } from 'express';
35
+ import express from 'express';
36
+ import type { WorkflowEvent } from '@bevel-software/platform-shared';
37
+ import type { WorkflowEventBus } from './event-bus.js';
38
+ import '../auth/auth.middleware.js';
39
+ /**
40
+ * Per-session bookkeeping the route owns. The bus's `Subscriber` holds a
41
+ * `getFocusedWorkspaceId()` getter pointing at `session.focusedWorkspaceId`,
42
+ * so the focus POST mutates this object and the next event fan-out picks
43
+ * up the new value with no re-subscribe.
44
+ */
45
+ interface ActiveSession {
46
+ sessionId: string;
47
+ userId: string;
48
+ focusedWorkspaceId: string | null;
49
+ /** Set when the SSE connection closes. Used by the focus POST so a
50
+ * request that arrives after the connection drops 404s cleanly. */
51
+ closed: boolean;
52
+ /** The Express response stream backing this session. Stored so a
53
+ * same-id reconnect can `end()` the old response and close its TCP
54
+ * socket immediately, rather than leaving a dangling connection that
55
+ * silently accumulates server-side resources. */
56
+ res: Response;
57
+ /** Tear down bus subscription + heartbeat. Stored on the session so a
58
+ * same-id reconnect can run cleanup directly rather than relying on
59
+ * the old `res.on('close')` path (which short-circuits if we mark the
60
+ * session closed before the OS-level close event fires). */
61
+ cleanup: () => void;
62
+ }
63
+ export declare function createEventsRoutes(bus: WorkflowEventBus, authMiddleware: express.RequestHandler): express.Router;
64
+ /**
65
+ * Serialise `event` into the SSE wire format. Each frame is:
66
+ *
67
+ * id: <event.id>
68
+ * data: <JSON payload>
69
+ * \n
70
+ *
71
+ * The `id` field is what the browser's EventSource exposes as
72
+ * `event.lastEventId` and re-sends as `Last-Event-ID` on reconnect.
73
+ * Data is a single line of JSON — never embedded newlines, which would
74
+ * break the SSE parser. JSON.stringify guarantees that.
75
+ */
76
+ declare function writeSseEvent(res: Response, event: WorkflowEvent): void;
77
+ /** Re-exported so tests / future hooks can construct the response shape. */
78
+ export { writeSseEvent as _writeSseEventForTests };
79
+ export type { ActiveSession };
80
+ //# sourceMappingURL=events.routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.routes.d.ts","sourceRoot":"","sources":["../../../src/modules/workflow/events.routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAW,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,4BAA4B,CAAC;AAMpC;;;;;GAKG;AACH,UAAU,aAAa;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC;wEACoE;IACpE,MAAM,EAAE,OAAO,CAAC;IAChB;;;sDAGkD;IAClD,GAAG,EAAE,QAAQ,CAAC;IACd;;;iEAG6D;IAC7D,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,gBAAgB,EACrB,cAAc,EAAE,OAAO,CAAC,cAAc,GACrC,OAAO,CAAC,MAAM,CA4KhB;AAED;;;;;;;;;;;GAWG;AACH,iBAAS,aAAa,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CAGhE;AAED,4EAA4E;AAC5E,OAAO,EAAE,aAAa,IAAI,sBAAsB,EAAE,CAAC;AACnD,YAAY,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,216 @@
1
+ /**
2
+ * SSE event-bus HTTP surface.
3
+ *
4
+ * GET /api/events?session=<sessionId> — open the long-lived SSE stream
5
+ * POST /api/events/:sessionId/focus — update which workspace this
6
+ * session cares about (changes
7
+ * over the connection's lifetime
8
+ * as the user / agent switches
9
+ * branches)
10
+ *
11
+ * **Why a per-tab session id, not per-workspace** — the connection must
12
+ * survive a workspace re-focus (when the user navigates between branches
13
+ * the URL changes and the workspace bootstrap rebinds `workspaceId`, but
14
+ * the EventSource stays open). So scope = `(userId, sessionId)`; the
15
+ * "what workspace events do I want" state is mutable and lives in the
16
+ * focus endpoint above.
17
+ *
18
+ * **Auth** — the SSE route can't read `Authorization: Bearer …` (the
19
+ * browser's EventSource API can't set headers), so the auth middleware
20
+ * also accepts the JWT from the `bevel_token` cookie set at login. The
21
+ * focus POST goes through the regular auth middleware too, and verifies
22
+ * that the cookie-authed user matches the session's owner.
23
+ *
24
+ * **Reconnect** — the browser's EventSource auto-reconnects on close
25
+ * (~3 s backoff). On reconnect it sends `Last-Event-ID: <n>` and the
26
+ * route replays anything still in the bus's ring buffer; if the buffer
27
+ * has evicted past `n`, the route emits `{ kind: 'resync' }` so the
28
+ * client refetches state from scratch.
29
+ *
30
+ * **Heartbeat** — every 25 s the route writes an SSE comment (`:\n\n`).
31
+ * Keeps proxies (nginx, Coolify's Traefik, Cloudflare) from killing the
32
+ * connection as idle. Cheap (~15 bytes), eliminates a whole class of bug.
33
+ */
34
+ import express from 'express';
35
+ import '../auth/auth.middleware.js'; // Express Request augmentation
36
+ /** Interval between SSE keep-alive comments (ms). 25 s sits comfortably under
37
+ * the typical 30–100 s proxy idle timeout. */
38
+ const HEARTBEAT_INTERVAL_MS = 25_000;
39
+ export function createEventsRoutes(bus, authMiddleware) {
40
+ const router = express.Router();
41
+ /**
42
+ * Process-wide session registry. The same map services the SSE open
43
+ * (creates the entry) and the focus POST (mutates `focusedWorkspaceId`).
44
+ * Entries clear when the SSE connection closes.
45
+ */
46
+ const sessions = new Map();
47
+ router.get('/events', authMiddleware, (req, res) => {
48
+ const sessionId = typeof req.query.session === 'string' ? req.query.session : '';
49
+ if (!sessionId) {
50
+ res.status(400).json({ error: 'session query parameter is required' });
51
+ return;
52
+ }
53
+ const userId = req.userId;
54
+ // SSE headers. `X-Accel-Buffering: no` tells nginx not to buffer the
55
+ // response (would batch events behind a flush boundary, killing
56
+ // latency). `Cache-Control: no-cache` + omitted `Content-Length`
57
+ // signal "long-lived stream, don't cache."
58
+ res.setHeader('Content-Type', 'text/event-stream');
59
+ res.setHeader('Cache-Control', 'no-cache, no-transform');
60
+ res.setHeader('Connection', 'keep-alive');
61
+ res.setHeader('X-Accel-Buffering', 'no');
62
+ res.flushHeaders();
63
+ // If a previous session with the same id is still registered (e.g.
64
+ // browser refresh that reuses sessionStorage), close it gracefully
65
+ // before we replace it. Two SSE streams for one session id would
66
+ // double-fire every event to that browser. We also `end()` the old
67
+ // response so the underlying TCP socket goes away immediately —
68
+ // without that, the previous `res` lingers in keep-alive state
69
+ // until the network times it out (minutes), wasting an FD per
70
+ // refresh.
71
+ const existing = sessions.get(sessionId);
72
+ if (existing && !existing.closed) {
73
+ // Tear down the bus subscription + heartbeat FIRST, then mark
74
+ // closed, then end the response. Order matters: marking `closed`
75
+ // before cleanup would make the OS-close handler's own cleanup
76
+ // short-circuit (it returns early on `closed`), leaking the
77
+ // subscriber + heartbeat for this session id forever.
78
+ try {
79
+ existing.cleanup();
80
+ }
81
+ catch (err) {
82
+ console.warn(`[events] supersede cleanup threw for session=${sessionId}:`, err instanceof Error ? err.message : err);
83
+ }
84
+ existing.closed = true;
85
+ try {
86
+ if (!existing.res.writableEnded)
87
+ existing.res.end();
88
+ }
89
+ catch (err) {
90
+ console.warn(`[events] failed to end superseded SSE response for session=${sessionId}:`, err instanceof Error ? err.message : err);
91
+ }
92
+ }
93
+ const session = {
94
+ sessionId,
95
+ userId,
96
+ focusedWorkspaceId: null,
97
+ closed: false,
98
+ res,
99
+ // Filled in below once `unsubscribe` + `heartbeat` exist.
100
+ cleanup: () => { },
101
+ };
102
+ sessions.set(sessionId, session);
103
+ const push = (event) => {
104
+ if (session.closed)
105
+ return;
106
+ writeSseEvent(res, event);
107
+ };
108
+ const unsubscribe = bus.subscribe({
109
+ sessionId,
110
+ userId,
111
+ getFocusedWorkspaceId: () => session.focusedWorkspaceId,
112
+ push,
113
+ });
114
+ // Replay anything the client missed since their last seen id. Browsers
115
+ // auto-send `Last-Event-ID` when EventSource reconnects, so this just
116
+ // works — no client cooperation needed beyond using the standard API.
117
+ const lastSeenHeader = req.headers['last-event-id'];
118
+ const lastSeenId = typeof lastSeenHeader === 'string' ? Number(lastSeenHeader) : NaN;
119
+ if (Number.isFinite(lastSeenId) && lastSeenId > 0) {
120
+ const replay = bus.replayAfter(lastSeenId, {
121
+ userId,
122
+ getFocusedWorkspaceId: () => session.focusedWorkspaceId,
123
+ });
124
+ if (replay === null) {
125
+ // Buffer evicted past `lastSeenId` — client must refetch from
126
+ // scratch rather than trust a partial replay.
127
+ writeSseEvent(res, {
128
+ id: 0,
129
+ ts: new Date().toISOString(),
130
+ kind: 'resync',
131
+ reason: 'last-event-id too old; ring buffer evicted',
132
+ });
133
+ }
134
+ else {
135
+ for (const event of replay)
136
+ writeSseEvent(res, event);
137
+ }
138
+ }
139
+ const heartbeat = setInterval(() => {
140
+ if (session.closed)
141
+ return;
142
+ // SSE comments start with `:` and are ignored by the EventSource
143
+ // parser. Cheapest possible keep-alive payload.
144
+ res.write(': heartbeat\n\n');
145
+ }, HEARTBEAT_INTERVAL_MS);
146
+ const cleanup = () => {
147
+ if (session.closed)
148
+ return;
149
+ session.closed = true;
150
+ clearInterval(heartbeat);
151
+ unsubscribe();
152
+ // Only delete if we're still the registered session — a reconnect
153
+ // for the same id may have already replaced us.
154
+ if (sessions.get(sessionId) === session) {
155
+ sessions.delete(sessionId);
156
+ }
157
+ };
158
+ session.cleanup = cleanup;
159
+ res.on('close', cleanup);
160
+ res.on('error', cleanup);
161
+ console.log(`[events] open session=${sessionId} user=${userId} subscribers=${bus.size()}`);
162
+ });
163
+ router.post('/events/:sessionId/focus', authMiddleware, express.json(), (req, res) => {
164
+ const sessionId = String(req.params.sessionId ?? '');
165
+ const userId = req.userId;
166
+ if (!sessionId) {
167
+ res.status(400).json({ error: 'sessionId is required' });
168
+ return;
169
+ }
170
+ const session = sessions.get(sessionId);
171
+ if (!session || session.closed) {
172
+ // 404 is the cleanest signal — the client should open a new SSE
173
+ // stream and POST focus again on success. (Browser EventSource
174
+ // auto-reconnects, so this should be rare in practice.)
175
+ res.status(404).json({ error: 'Session not found' });
176
+ return;
177
+ }
178
+ if (session.userId !== userId) {
179
+ // Hard 403 — a user must never be able to set focus on another
180
+ // user's session, which would let them mirror that user's events
181
+ // into their own connection. Belt-and-braces; cookie auth already
182
+ // gates which userId reaches this handler.
183
+ res.status(403).json({ error: 'Session belongs to another user' });
184
+ return;
185
+ }
186
+ const { workspaceId } = (req.body ?? {});
187
+ if (typeof workspaceId !== 'string' || workspaceId.length === 0) {
188
+ res.status(400).json({ error: 'workspaceId is required in body' });
189
+ return;
190
+ }
191
+ const previous = session.focusedWorkspaceId;
192
+ session.focusedWorkspaceId = workspaceId;
193
+ console.log(`[events] FOCUS session=${sessionId} user=${userId} ${previous ?? '(none)'} → ${workspaceId}`);
194
+ res.json({ status: 'ok', focusedWorkspaceId: workspaceId });
195
+ });
196
+ return router;
197
+ }
198
+ /**
199
+ * Serialise `event` into the SSE wire format. Each frame is:
200
+ *
201
+ * id: <event.id>
202
+ * data: <JSON payload>
203
+ * \n
204
+ *
205
+ * The `id` field is what the browser's EventSource exposes as
206
+ * `event.lastEventId` and re-sends as `Last-Event-ID` on reconnect.
207
+ * Data is a single line of JSON — never embedded newlines, which would
208
+ * break the SSE parser. JSON.stringify guarantees that.
209
+ */
210
+ function writeSseEvent(res, event) {
211
+ res.write(`id: ${event.id}\n`);
212
+ res.write(`data: ${JSON.stringify(event)}\n\n`);
213
+ }
214
+ /** Re-exported so tests / future hooks can construct the response shape. */
215
+ export { writeSseEvent as _writeSseEventForTests };
216
+ //# sourceMappingURL=events.routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.routes.js","sourceRoot":"","sources":["../../../src/modules/workflow/events.routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * One in-process notification fired AFTER a set of file changes is committed +
3
+ * pushed (post-lock-release), so backend services can react to KB writes without
4
+ * the per-file TTL wait. Distinct from the SSE `WorkflowEventBus`, which fans
5
+ * scoped events to browser sessions; this is an unscoped, server-side domain hook.
6
+ *
7
+ * BATCHED by design: a single-file save emits `paths: [p]`, a batch write
8
+ * (`LockingFilesystem.writeFiles`, e.g. a bulk node upload) emits ONE event with
9
+ * every path it committed. Subscribers that do expensive per-event work (the
10
+ * id-repair rebuilds the id index) handle a whole batch off one rebuild instead
11
+ * of N back-to-back ones.
12
+ *
13
+ * Emitted from the two post-commit chokepoints (`WorkflowService.runPendingCommit`
14
+ * for single-file writes, `LockingFilesystem.writeFiles` for batches).
15
+ *
16
+ * Every listener is invoked inside try/catch — a throwing subscriber must never
17
+ * fail the commit that triggered it (mirrors the SSE bus's per-subscriber
18
+ * isolation). Firing is fire-and-forget; a listener that needs to write files
19
+ * (id-repair) does so on its own, after the locks have already been released.
20
+ */
21
+ import type { AuthUser } from '@bevel-software/platform-shared';
22
+ export interface FilesChange {
23
+ workspaceId: string;
24
+ branch: string;
25
+ /** Workspace-relative paths committed in this change (≥1; sorted for batches). */
26
+ paths: string[];
27
+ /** Who the change was committed as — a reacting write (id-repair) acts as the same user. */
28
+ byUser: AuthUser;
29
+ }
30
+ export type FilesChangedListener = (change: FilesChange) => void;
31
+ export declare class FileChangeNotifier {
32
+ private readonly listeners;
33
+ /** Register a listener. Returns an unsubscribe fn. */
34
+ onFilesChanged(listener: FilesChangedListener): () => void;
35
+ /** Fan a change out to every listener; isolate + log each so one can't break the commit. */
36
+ emit(change: FilesChange): void;
37
+ }
38
+ //# sourceMappingURL=file-change-notifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-change-notifier.d.ts","sourceRoot":"","sources":["../../../src/modules/workflow/file-change-notifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAEhE,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,4FAA4F;IAC5F,MAAM,EAAE,QAAQ,CAAC;CAClB;AAED,MAAM,MAAM,oBAAoB,GAAG,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAC;AAEjE,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmC;IAE7D,sDAAsD;IACtD,cAAc,CAAC,QAAQ,EAAE,oBAAoB,GAAG,MAAM,IAAI;IAK1D,4FAA4F;IAC5F,IAAI,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;CAUhC"}
@@ -0,0 +1,22 @@
1
+ export class FileChangeNotifier {
2
+ listeners = new Set();
3
+ /** Register a listener. Returns an unsubscribe fn. */
4
+ onFilesChanged(listener) {
5
+ this.listeners.add(listener);
6
+ return () => this.listeners.delete(listener);
7
+ }
8
+ /** Fan a change out to every listener; isolate + log each so one can't break the commit. */
9
+ emit(change) {
10
+ if (change.paths.length === 0)
11
+ return;
12
+ for (const listener of this.listeners) {
13
+ try {
14
+ listener(change);
15
+ }
16
+ catch (err) {
17
+ console.error('[file-change] listener threw:', err instanceof Error ? err.message : err);
18
+ }
19
+ }
20
+ }
21
+ }
22
+ //# sourceMappingURL=file-change-notifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-change-notifier.js","sourceRoot":"","sources":["../../../src/modules/workflow/file-change-notifier.ts"],"names":[],"mappings":"AAiCA,MAAM,OAAO,kBAAkB;IACZ,SAAS,GAAG,IAAI,GAAG,EAAwB,CAAC;IAE7D,sDAAsD;IACtD,cAAc,CAAC,QAA8B;QAC3C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED,4FAA4F;IAC5F,IAAI,CAAC,MAAmB;QACtB,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACtC,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACtC,IAAI,CAAC;gBACH,QAAQ,CAAC,MAAM,CAAC,CAAC;YACnB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAC3F,CAAC;QACH,CAAC;IACH,CAAC;CACF"}