@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,804 @@
1
+ /**
2
+ * `/workflow/*` HTTP surface — the route family the frontend and agent
3
+ * should reach for instead of `/git/*` and `/pr/*`. Today these are additive
4
+ * (the old families keep working); migration plan in `bevel-platform/PLAN.md`.
5
+ *
6
+ * URL layout:
7
+ * /workspace/:id/workflow/... — workspace-scoped ops (branches, changes, locks, compare)
8
+ * /workflow/change-requests/... — change-request ops (list/detail/comments/approvals/merge/reject)
9
+ *
10
+ * Workspace ids are `encodeURIComponent(branch)` (PLAN §3) — branches are
11
+ * shared by every user editing them, so route handlers gate on
12
+ * authentication only. Coordination of concurrent edits happens via the
13
+ * file-lock service, not via per-user clones.
14
+ *
15
+ * Error mapping: every workflow error class extends `WorkflowDomainError`
16
+ * which exposes `.status` + optional `.payload`, so a single `toHttpError`
17
+ * covers all branches/changes/CR errors uniformly.
18
+ */
19
+ import express from 'express';
20
+ import { branchForWorkspaceId } from '../workspace/workspace.service.js';
21
+ import { WorkflowDomainError } from './workflow.errors.js';
22
+ import '../auth/auth.middleware.js'; // Express Request augmentation
23
+ function toHttpError(err) {
24
+ if (err instanceof WorkflowDomainError) {
25
+ return {
26
+ status: err.status,
27
+ body: { error: err.message, ...(err.payload ?? {}) },
28
+ };
29
+ }
30
+ console.error('[workflow.routes] unhandled error:', err);
31
+ return { status: 500, body: { error: 'Internal server error' } };
32
+ }
33
+ function parsePrNumber(raw) {
34
+ if (!/^\d+$/.test(raw))
35
+ return null;
36
+ const n = Number(raw);
37
+ return n > 0 && Number.isSafeInteger(n) ? n : null;
38
+ }
39
+ function isTruthyQuery(v) {
40
+ return v === '1' || v === 'true';
41
+ }
42
+ export function createWorkflowRoutes(workflow, workspaceService, authService, events) {
43
+ const router = express.Router({ mergeParams: true });
44
+ /**
45
+ * Authentication gate. Per PLAN §3, branches are shared workspaces —
46
+ * any authenticated user can access any branch. Authorization for
47
+ * mutations happens at the workflow / git layer (access tree, file
48
+ * locks, change-request approval gate). This helper just resolves the
49
+ * caller's `AuthUser` record; route bodies pass it to workflow methods
50
+ * for per-operation auth.
51
+ */
52
+ async function requireUser(req, res) {
53
+ if (!req.userId) {
54
+ res.status(401).json({ error: 'Unauthenticated' });
55
+ return null;
56
+ }
57
+ try {
58
+ const user = await authService.getUserById(req.userId);
59
+ if (!user) {
60
+ res.status(401).json({ error: 'User not found' });
61
+ return null;
62
+ }
63
+ return user;
64
+ }
65
+ catch (err) {
66
+ console.error('[workflow.routes] requireUser failed:', err);
67
+ res.status(500).json({ error: 'Internal server error' });
68
+ return null;
69
+ }
70
+ }
71
+ // ── Branches ──────────────────────────────────────────────────────────────
72
+ router.get('/workspace/:id/workflow/branches', async (req, res) => {
73
+ if (!(await requireUser(req, res)))
74
+ return;
75
+ try {
76
+ // `?fresh=1` forces a `git fetch --prune` (bypasses the implicit-fetch
77
+ // TTL) so a user-initiated refresh — e.g. opening the branch selector —
78
+ // immediately reflects branches another workspace just created/deleted.
79
+ const freshFetch = isTruthyQuery(req.query.fresh);
80
+ res.json(await workflow.listBranches(req.params.id, { freshFetch }));
81
+ }
82
+ catch (err) {
83
+ const { status, body } = toHttpError(err);
84
+ res.status(status).json(body);
85
+ }
86
+ });
87
+ router.post('/workspace/:id/workflow/branches', async (req, res) => {
88
+ if (!(await requireUser(req, res)))
89
+ return;
90
+ const { name, fromBase } = req.body;
91
+ if (!name) {
92
+ res.status(400).json({ error: 'name is required' });
93
+ return;
94
+ }
95
+ try {
96
+ res.json(await workflow.createBranch(req.params.id, name, fromBase));
97
+ }
98
+ catch (err) {
99
+ const { status, body } = toHttpError(err);
100
+ res.status(status).json(body);
101
+ }
102
+ });
103
+ router.delete('/workspace/:id/workflow/branches/:name', async (req, res) => {
104
+ const user = await requireUser(req, res);
105
+ if (!user)
106
+ return;
107
+ const onlyIfNoRemote = isTruthyQuery(req.query.onlyIfNoRemote);
108
+ try {
109
+ await workflow.deleteBranch(req.params.id, req.params.name, user, { onlyIfNoRemote });
110
+ res.json({ status: 'deleted' });
111
+ }
112
+ catch (err) {
113
+ const { status, body } = toHttpError(err);
114
+ res.status(status).json(body);
115
+ }
116
+ });
117
+ // The legacy `POST /workspace/:id/workflow/switch` route is gone. Under
118
+ // the per-branch workspace model the UI switches branches by navigating
119
+ // the URL — the frontend's workspace bootstrap clones (or selects) the
120
+ // destination branch's per-branch workspace dir. There is no separate
121
+ // server-side "switch" step on the source workspace's clone, which was
122
+ // the only place a dirty working tree could leak as a user-facing 409.
123
+ // `POST /workspace/:id/workflow/fork-draft` removed: the dirty-tree
124
+ // carry-along escape hatch has no callers under save=share + per-branch
125
+ // workspaces. Use `POST /workflow/branches` (createBranch) instead.
126
+ router.get('/workspace/:id/workflow/branch-status', async (req, res) => {
127
+ if (!(await requireUser(req, res)))
128
+ return;
129
+ try {
130
+ // Make sure the per-branch workspace is fully cloned before we run any
131
+ // git command against it. Without this, a frontend hitting branch-status
132
+ // on first load can race the cold clone and `git rev-parse HEAD` returns
133
+ // "ambiguous argument 'HEAD'" against a half-initialised .git directory.
134
+ // The call is idempotent and ~free in the warm case (Map lookup), so it
135
+ // costs nothing once the workspace is already on disk.
136
+ await workspaceService.getOrCreateForBranch(branchForWorkspaceId(req.params.id));
137
+ res.json(await workflow.branchStatus(req.params.id));
138
+ }
139
+ catch (err) {
140
+ const { status, body } = toHttpError(err);
141
+ res.status(status).json(body);
142
+ }
143
+ });
144
+ // `POST /workspace/:id/workflow/discard` removed: under save=share the
145
+ // working tree is never dirty, so there's nothing to discard.
146
+ router.post('/workspace/:id/workflow/share', async (req, res) => {
147
+ const user = await requireUser(req, res);
148
+ if (!user)
149
+ return;
150
+ try {
151
+ await workflow.shareCurrentBranch(req.params.id, user);
152
+ res.json({ status: 'shared' });
153
+ }
154
+ catch (err) {
155
+ const { status, body } = toHttpError(err);
156
+ res.status(status).json(body);
157
+ }
158
+ });
159
+ router.post('/workspace/:id/workflow/refresh-remotes', async (req, res) => {
160
+ if (!(await requireUser(req, res)))
161
+ return;
162
+ try {
163
+ await workflow.refreshRemotes(req.params.id);
164
+ res.json({ status: 'refreshed' });
165
+ }
166
+ catch (err) {
167
+ const { status, body } = toHttpError(err);
168
+ res.status(status).json(body);
169
+ }
170
+ });
171
+ router.post('/workspace/:id/workflow/update-from-remote', async (req, res) => {
172
+ if (!(await requireUser(req, res)))
173
+ return;
174
+ try {
175
+ await workflow.updateFromRemote(req.params.id);
176
+ res.json({ status: 'updated' });
177
+ }
178
+ catch (err) {
179
+ const { status, body } = toHttpError(err);
180
+ res.status(status).json(body);
181
+ }
182
+ });
183
+ router.get('/workspace/:id/workflow/fork-base', async (req, res) => {
184
+ if (!(await requireUser(req, res)))
185
+ return;
186
+ const branch = typeof req.query.branch === 'string' ? req.query.branch : '';
187
+ if (!branch) {
188
+ res.status(400).json({ error: 'branch is required' });
189
+ return;
190
+ }
191
+ try {
192
+ const base = await workflow.resolveForkBase(req.params.id, branch);
193
+ res.json({ base });
194
+ }
195
+ catch (err) {
196
+ const { status, body } = toHttpError(err);
197
+ res.status(status).json(body);
198
+ }
199
+ });
200
+ router.get('/workspace/:id/workflow/pending-changes', async (req, res) => {
201
+ if (!(await requireUser(req, res)))
202
+ return;
203
+ try {
204
+ const paths = await workflow.listPendingChangePaths(req.params.id);
205
+ res.json({ paths });
206
+ }
207
+ catch (err) {
208
+ const { status, body } = toHttpError(err);
209
+ res.status(status).json(body);
210
+ }
211
+ });
212
+ // `GET /workspace/:id/workflow/working-changes` + `working-diff` removed:
213
+ // working-tree dirty state is always empty under save=share.
214
+ // ── Changes ───────────────────────────────────────────────────────────────
215
+ router.post('/workspace/:id/workflow/changes', async (req, res) => {
216
+ const user = await requireUser(req, res);
217
+ if (!user)
218
+ return;
219
+ const input = req.body;
220
+ try {
221
+ res.json(await workflow.commitChange(req.params.id, user, input));
222
+ }
223
+ catch (err) {
224
+ const { status, body } = toHttpError(err);
225
+ res.status(status).json(body);
226
+ }
227
+ });
228
+ router.get('/workspace/:id/workflow/changes', async (req, res) => {
229
+ if (!(await requireUser(req, res)))
230
+ return;
231
+ const pathParam = typeof req.query.path === 'string' ? req.query.path : '';
232
+ if (!pathParam) {
233
+ res.status(400).json({ error: 'path is required' });
234
+ return;
235
+ }
236
+ const rawLimit = Number.parseInt(String(req.query.limit ?? '20'), 10);
237
+ const limit = Number.isFinite(rawLimit) ? Math.max(1, Math.min(rawLimit, 100)) : 20;
238
+ try {
239
+ res.json({ changes: await workflow.listChangesForFile(req.params.id, pathParam, limit) });
240
+ }
241
+ catch (err) {
242
+ const { status, body } = toHttpError(err);
243
+ res.status(status).json(body);
244
+ }
245
+ });
246
+ router.post('/workspace/:id/workflow/changes/:sha/revert', async (req, res) => {
247
+ const user = await requireUser(req, res);
248
+ if (!user)
249
+ return;
250
+ try {
251
+ res.json(await workflow.revertChange(req.params.id, user, req.params.sha));
252
+ }
253
+ catch (err) {
254
+ const { status, body } = toHttpError(err);
255
+ res.status(status).json(body);
256
+ }
257
+ });
258
+ router.get('/workspace/:id/workflow/compare-file', async (req, res) => {
259
+ if (!(await requireUser(req, res)))
260
+ return;
261
+ const pathParam = typeof req.query.path === 'string' ? req.query.path : '';
262
+ const fromBranch = typeof req.query.from === 'string' ? req.query.from : '';
263
+ const toBranch = typeof req.query.to === 'string' ? req.query.to : '';
264
+ if (!pathParam || !fromBranch || !toBranch) {
265
+ res.status(400).json({ error: 'path, from, and to are required' });
266
+ return;
267
+ }
268
+ try {
269
+ const diff = await workflow.compareFile(req.params.id, pathParam, fromBranch, toBranch);
270
+ res.json({ diff });
271
+ }
272
+ catch (err) {
273
+ const { status, body } = toHttpError(err);
274
+ res.status(status).json(body);
275
+ }
276
+ });
277
+ router.get('/workspace/:id/workflow/show-file', async (req, res) => {
278
+ if (!(await requireUser(req, res)))
279
+ return;
280
+ const pathParam = typeof req.query.path === 'string' ? req.query.path : '';
281
+ const sha = typeof req.query.sha === 'string' ? req.query.sha : '';
282
+ if (!pathParam || !sha) {
283
+ res.status(400).json({ error: 'path and sha are required' });
284
+ return;
285
+ }
286
+ try {
287
+ const diff = await workflow.showFileAtChange(req.params.id, pathParam, sha);
288
+ res.json({ diff });
289
+ }
290
+ catch (err) {
291
+ const { status, body } = toHttpError(err);
292
+ res.status(status).json(body);
293
+ }
294
+ });
295
+ // ── File locks ────────────────────────────────────────────────────────────
296
+ router.post('/workspace/:id/workflow/locks', async (req, res) => {
297
+ const user = await requireUser(req, res);
298
+ if (!user)
299
+ return;
300
+ const { branch, path: targetPath } = req.body;
301
+ if (!branch || !targetPath) {
302
+ res.status(400).json({ error: 'branch and path are required' });
303
+ return;
304
+ }
305
+ try {
306
+ res.json(await workflow.acquireLock(req.params.id, branch, targetPath, user));
307
+ }
308
+ catch (err) {
309
+ const { status, body } = toHttpError(err);
310
+ res.status(status).json(body);
311
+ }
312
+ });
313
+ // Release: branch + path travel via the body, not the query string,
314
+ // because DELETE bodies are reliable for our own clients. Under the
315
+ // pending-commits queue the release no longer returns a `Change` — the
316
+ // commit hasn't happened yet (the background worker drains the queue
317
+ // out of band). The route's `{ queued: true }` reply just signals
318
+ // "lock released, commit scheduled."
319
+ router.delete('/workspace/:id/workflow/locks', async (req, res) => {
320
+ const user = await requireUser(req, res);
321
+ if (!user)
322
+ return;
323
+ const body = (req.body ?? {});
324
+ const branch = body.branch ?? (typeof req.query.branch === 'string' ? req.query.branch : '');
325
+ const targetPath = body.path ?? (typeof req.query.path === 'string' ? req.query.path : '');
326
+ if (!branch || !targetPath) {
327
+ res.status(400).json({ error: 'branch and path are required' });
328
+ return;
329
+ }
330
+ try {
331
+ await workflow.releaseLock(req.params.id, branch, targetPath, user);
332
+ res.json({ queued: true });
333
+ }
334
+ catch (err) {
335
+ const { status, body } = toHttpError(err);
336
+ res.status(status).json(body);
337
+ }
338
+ });
339
+ // Commit-while-locked — autosave checkpoint. Lock stays held; the
340
+ // file's accumulated edits land as a one-file change.
341
+ router.post('/workspace/:id/workflow/locks/checkpoint', async (req, res) => {
342
+ const user = await requireUser(req, res);
343
+ if (!user)
344
+ return;
345
+ const { branch, path: targetPath, summary } = req.body;
346
+ if (!branch || !targetPath) {
347
+ res.status(400).json({ error: 'branch and path are required' });
348
+ return;
349
+ }
350
+ try {
351
+ const change = await workflow.commitFileWhileLocked(req.params.id, branch, targetPath, user, summary);
352
+ res.json({ change });
353
+ }
354
+ catch (err) {
355
+ const { status, body } = toHttpError(err);
356
+ res.status(status).json(body);
357
+ }
358
+ });
359
+ router.post('/workspace/:id/workflow/locks/heartbeat', async (req, res) => {
360
+ const user = await requireUser(req, res);
361
+ if (!user)
362
+ return;
363
+ const { branch, path: targetPath } = req.body;
364
+ if (!branch || !targetPath) {
365
+ res.status(400).json({ error: 'branch and path are required' });
366
+ return;
367
+ }
368
+ try {
369
+ res.json(await workflow.heartbeatLock(req.params.id, branch, targetPath, user));
370
+ }
371
+ catch (err) {
372
+ const { status, body } = toHttpError(err);
373
+ res.status(status).json(body);
374
+ }
375
+ });
376
+ router.get('/workspace/:id/workflow/locks', async (req, res) => {
377
+ if (!(await requireUser(req, res)))
378
+ return;
379
+ const branch = typeof req.query.branch === 'string' ? req.query.branch : '';
380
+ const targetPath = typeof req.query.path === 'string' ? req.query.path : '';
381
+ if (!branch || !targetPath) {
382
+ res.status(400).json({ error: 'branch and path are required' });
383
+ return;
384
+ }
385
+ try {
386
+ res.json({ lock: await workflow.getLock(req.params.id, branch, targetPath) });
387
+ }
388
+ catch (err) {
389
+ const { status, body } = toHttpError(err);
390
+ res.status(status).json(body);
391
+ }
392
+ });
393
+ // ── Change Requests ───────────────────────────────────────────────────────
394
+ router.get('/workflow/change-requests', async (req, res) => {
395
+ const fresh = isTruthyQuery(req.query.fresh);
396
+ try {
397
+ res.json(await workflow.listChangeRequests({ fresh }));
398
+ }
399
+ catch (err) {
400
+ const { status, body } = toHttpError(err);
401
+ res.status(status).json(body);
402
+ }
403
+ });
404
+ router.get('/workflow/change-requests/mine', async (req, res) => {
405
+ const user = await requireUser(req, res);
406
+ if (!user)
407
+ return;
408
+ try {
409
+ res.json(await workflow.listChangeRequestsAuthoredBy(user.email));
410
+ }
411
+ catch (err) {
412
+ const { status, body } = toHttpError(err);
413
+ res.status(status).json(body);
414
+ }
415
+ });
416
+ router.get('/workflow/change-requests/for-me', async (req, res) => {
417
+ const user = await requireUser(req, res);
418
+ if (!user)
419
+ return;
420
+ const fresh = isTruthyQuery(req.query.fresh);
421
+ try {
422
+ const workspace = await workspaceService.getOrCreateForUser(user);
423
+ res.json(await workflow.listChangeRequestsForUser(workspace.id, user.email, { fresh }));
424
+ }
425
+ catch (err) {
426
+ const { status, body } = toHttpError(err);
427
+ res.status(status).json(body);
428
+ }
429
+ });
430
+ router.get('/workflow/change-requests/:number', async (req, res) => {
431
+ const num = parsePrNumber(req.params.number);
432
+ if (num === null) {
433
+ res.status(400).json({ error: 'invalid change request number' });
434
+ return;
435
+ }
436
+ try {
437
+ const cr = await workflow.getChangeRequest(num);
438
+ if (!cr) {
439
+ res.status(404).json({ error: 'change request not found' });
440
+ return;
441
+ }
442
+ res.json(cr);
443
+ }
444
+ catch (err) {
445
+ const { status, body } = toHttpError(err);
446
+ res.status(status).json(body);
447
+ }
448
+ });
449
+ router.get('/workflow/change-requests/:number/detail', async (req, res) => {
450
+ const num = parsePrNumber(req.params.number);
451
+ if (num === null) {
452
+ res.status(400).json({ error: 'invalid change request number' });
453
+ return;
454
+ }
455
+ try {
456
+ const fresh = isTruthyQuery(req.query.fresh);
457
+ let workspaceId;
458
+ let viewerEmail;
459
+ // Best-effort caller resolution — anonymous detail fetches still work
460
+ // (mirroring the legacy /pr/:n/detail behaviour), they just don't get
461
+ // `viewerCanApprove` populated.
462
+ if (req.userId) {
463
+ try {
464
+ const user = await authService.getUserById(req.userId);
465
+ if (user) {
466
+ const ws = await workspaceService.getOrCreateForUser(user);
467
+ workspaceId = ws.id;
468
+ viewerEmail = user.email;
469
+ }
470
+ }
471
+ catch {
472
+ // Swallow — keeps the detail fetch resilient to a transient auth
473
+ // blip when the caller's workspace isn't yet provisioned.
474
+ }
475
+ }
476
+ const detail = await workflow.getChangeRequestDetail(num, {
477
+ fresh,
478
+ workspaceId,
479
+ viewerEmail,
480
+ });
481
+ if (!detail) {
482
+ res.status(404).json({ error: 'change request not found' });
483
+ return;
484
+ }
485
+ res.json(detail);
486
+ }
487
+ catch (err) {
488
+ const { status, body } = toHttpError(err);
489
+ res.status(status).json(body);
490
+ }
491
+ });
492
+ router.post('/workflow/change-requests', async (req, res) => {
493
+ const user = await requireUser(req, res);
494
+ if (!user)
495
+ return;
496
+ const body = req.body;
497
+ if (!body.sourceBranch || !body.targetBranch || !body.title) {
498
+ res.status(400).json({ error: 'sourceBranch, targetBranch and title are required' });
499
+ return;
500
+ }
501
+ try {
502
+ // Resolve the source-branch workspace — `git.mergeFromOrigin`
503
+ // requires the clone to be checked out to `sourceBranch`, and with
504
+ // workspace-per-branch the right clone is `workspaces/<encoded
505
+ // sourceBranch>/...`. Falling back to `getOrCreateForUser` returned
506
+ // the default workspace (target-company-state), which broke CRs
507
+ // whose source wasn't the default. `getOrCreateForBranch` lazily
508
+ // bootstraps the clone if this is the first request for it.
509
+ const workspace = await workspaceService.getOrCreateForBranch(body.sourceBranch);
510
+ res.json(await workflow.openChangeRequest(workspace.id, user, {
511
+ sourceBranch: body.sourceBranch,
512
+ targetBranch: body.targetBranch,
513
+ title: body.title,
514
+ description: body.description,
515
+ }));
516
+ }
517
+ catch (err) {
518
+ const { status, body } = toHttpError(err);
519
+ res.status(status).json(body);
520
+ }
521
+ });
522
+ router.post('/workflow/change-requests/:number/update-from-target', async (req, res) => {
523
+ const num = parsePrNumber(req.params.number);
524
+ if (num === null) {
525
+ res.status(400).json({ error: 'invalid change request number' });
526
+ return;
527
+ }
528
+ const user = await requireUser(req, res);
529
+ if (!user)
530
+ return;
531
+ try {
532
+ // `updateFromTarget` re-runs the `target → source` merge, which
533
+ // needs the source branch's workspace (the on-disk clone checked
534
+ // out to that branch). Discover the source branch from the CR
535
+ // first, then resolve the matching workspace — same reasoning as
536
+ // `openChangeRequest` above. `getOrCreateForBranch` lazily clones
537
+ // if the source branch hasn't been touched on this replica yet.
538
+ const cr = await workflow.getChangeRequest(num);
539
+ if (!cr) {
540
+ res.status(404).json({ error: 'change request not found' });
541
+ return;
542
+ }
543
+ const workspace = await workspaceService.getOrCreateForBranch(cr.branch);
544
+ res.json(await workflow.updateFromTarget(workspace.id, user, num));
545
+ }
546
+ catch (err) {
547
+ const { status, body } = toHttpError(err);
548
+ res.status(status).json(body);
549
+ }
550
+ });
551
+ router.get('/workflow/change-requests/:number/comments', async (req, res) => {
552
+ const num = parsePrNumber(req.params.number);
553
+ if (num === null) {
554
+ res.status(400).json({ error: 'invalid change request number' });
555
+ return;
556
+ }
557
+ try {
558
+ res.json(await workflow.listComments(num));
559
+ }
560
+ catch (err) {
561
+ const { status, body } = toHttpError(err);
562
+ res.status(status).json(body);
563
+ }
564
+ });
565
+ router.post('/workflow/change-requests/:number/comments', async (req, res) => {
566
+ const num = parsePrNumber(req.params.number);
567
+ if (num === null) {
568
+ res.status(400).json({ error: 'invalid change request number' });
569
+ return;
570
+ }
571
+ const user = await requireUser(req, res);
572
+ if (!user)
573
+ return;
574
+ const body = (req.body ?? {});
575
+ if (typeof body.body !== 'string') {
576
+ res.status(400).json({ error: 'body is required' });
577
+ return;
578
+ }
579
+ try {
580
+ // Resolve the current head from the detail endpoint so the comment
581
+ // anchors against what the user is actually viewing. Mirrors the
582
+ // legacy /pr/:n/comments handler.
583
+ const detail = await workflow.getChangeRequestDetail(num, { fresh: true });
584
+ if (!detail) {
585
+ res.status(404).json({ error: 'change request not found' });
586
+ return;
587
+ }
588
+ const comment = await workflow.postComment(num, user, {
589
+ body: body.body,
590
+ path: body.path,
591
+ line: body.line,
592
+ parentId: body.parentId,
593
+ }, detail.headSha);
594
+ res.json(comment);
595
+ }
596
+ catch (err) {
597
+ const { status, body } = toHttpError(err);
598
+ res.status(status).json(body);
599
+ }
600
+ });
601
+ router.patch('/workflow/change-requests/:number/comments/:id', async (req, res) => {
602
+ const num = parsePrNumber(req.params.number);
603
+ if (num === null) {
604
+ res.status(400).json({ error: 'invalid change request number' });
605
+ return;
606
+ }
607
+ const user = await requireUser(req, res);
608
+ if (!user)
609
+ return;
610
+ const body = (req.body ?? {});
611
+ if (typeof body.body !== 'string') {
612
+ res.status(400).json({ error: 'body is required' });
613
+ return;
614
+ }
615
+ try {
616
+ res.json(await workflow.editComment(req.params.id, num, user, body.body));
617
+ }
618
+ catch (err) {
619
+ const { status, body } = toHttpError(err);
620
+ res.status(status).json(body);
621
+ }
622
+ });
623
+ router.delete('/workflow/change-requests/:number/comments/:id', async (req, res) => {
624
+ const num = parsePrNumber(req.params.number);
625
+ if (num === null) {
626
+ res.status(400).json({ error: 'invalid change request number' });
627
+ return;
628
+ }
629
+ const user = await requireUser(req, res);
630
+ if (!user)
631
+ return;
632
+ try {
633
+ await workflow.deleteComment(req.params.id, num, user);
634
+ res.json({ status: 'deleted' });
635
+ }
636
+ catch (err) {
637
+ const { status, body } = toHttpError(err);
638
+ res.status(status).json(body);
639
+ }
640
+ });
641
+ // Approve / unapprove. Both fetch fresh detail so the approval pins to the
642
+ // current head — a stale cached head could let the gate accept an approval
643
+ // the user never actually saw.
644
+ router.post('/workflow/change-requests/:number/files/approve', async (req, res) => {
645
+ const num = parsePrNumber(req.params.number);
646
+ if (num === null) {
647
+ res.status(400).json({ error: 'invalid change request number' });
648
+ return;
649
+ }
650
+ const user = await requireUser(req, res);
651
+ if (!user)
652
+ return;
653
+ const body = (req.body ?? {});
654
+ if (typeof body.path !== 'string' || !body.path) {
655
+ res.status(400).json({ error: 'path is required' });
656
+ return;
657
+ }
658
+ try {
659
+ const workspace = await workspaceService.getOrCreateForUser(user);
660
+ const detail = await workflow.getChangeRequestDetail(num, {
661
+ fresh: true,
662
+ workspaceId: workspace.id,
663
+ viewerEmail: user.email,
664
+ });
665
+ if (!detail) {
666
+ res.status(404).json({ error: 'change request not found' });
667
+ return;
668
+ }
669
+ const approvals = await workflow.approveFile(num, body.path, user, detail.files, detail.headSha, detail.base, detail.authorId ?? null, workspace.id);
670
+ res.json({ approvals });
671
+ }
672
+ catch (err) {
673
+ const { status, body } = toHttpError(err);
674
+ res.status(status).json(body);
675
+ }
676
+ });
677
+ router.delete('/workflow/change-requests/:number/files/approve', async (req, res) => {
678
+ const num = parsePrNumber(req.params.number);
679
+ if (num === null) {
680
+ res.status(400).json({ error: 'invalid change request number' });
681
+ return;
682
+ }
683
+ const user = await requireUser(req, res);
684
+ if (!user)
685
+ return;
686
+ const targetPath = typeof req.query.path === 'string' ? req.query.path : '';
687
+ if (!targetPath) {
688
+ res.status(400).json({ error: 'path is required' });
689
+ return;
690
+ }
691
+ try {
692
+ const workspace = await workspaceService.getOrCreateForUser(user);
693
+ const detail = await workflow.getChangeRequestDetail(num, {
694
+ fresh: true,
695
+ workspaceId: workspace.id,
696
+ viewerEmail: user.email,
697
+ });
698
+ if (!detail) {
699
+ res.status(404).json({ error: 'change request not found' });
700
+ return;
701
+ }
702
+ const approvals = await workflow.unapproveFile(num, targetPath, user, detail.files, detail.headSha, detail.base, detail.authorId ?? null, workspace.id);
703
+ res.json({ approvals });
704
+ }
705
+ catch (err) {
706
+ const { status, body } = toHttpError(err);
707
+ res.status(status).json(body);
708
+ }
709
+ });
710
+ router.post('/workflow/change-requests/:number/reject', async (req, res) => {
711
+ const num = parsePrNumber(req.params.number);
712
+ if (num === null) {
713
+ res.status(400).json({ error: 'invalid change request number' });
714
+ return;
715
+ }
716
+ const user = await requireUser(req, res);
717
+ if (!user)
718
+ return;
719
+ try {
720
+ const workspace = await workspaceService.getOrCreateForUser(user);
721
+ const detail = await workflow.getChangeRequestDetail(num, {
722
+ fresh: true,
723
+ workspaceId: workspace.id,
724
+ viewerEmail: user.email,
725
+ });
726
+ if (!detail) {
727
+ res.status(404).json({ error: 'change request not found' });
728
+ return;
729
+ }
730
+ const result = await workflow.rejectChangeRequest(num, user, detail.state, detail.authorId ?? null, detail.base, workspace.id);
731
+ res.json(result);
732
+ }
733
+ catch (err) {
734
+ const { status, body } = toHttpError(err);
735
+ res.status(status).json(body);
736
+ }
737
+ });
738
+ router.post('/workflow/change-requests/:number/merge', async (req, res) => {
739
+ const num = parsePrNumber(req.params.number);
740
+ if (num === null) {
741
+ res.status(400).json({ error: 'invalid change request number' });
742
+ return;
743
+ }
744
+ const user = await requireUser(req, res);
745
+ if (!user)
746
+ return;
747
+ const body = (req.body ?? {});
748
+ const bypass = body.bypass === true;
749
+ // Async merge. The gate re-validation fetches the PR's full file list from
750
+ // GitHub (paginated — slow on a large change request) and `gh pr merge` can
751
+ // itself take tens of seconds, long enough to outlive the gateway's idle
752
+ // timeout — surfacing to the user as a 502 even while the merge is still
753
+ // running. So we ack with 202 and run the merge in the background, reporting
754
+ // the result over the event bus: `change-request-merged` on success (emitted
755
+ // by the workflow service; the PR viewer refreshes off it), and a
756
+ // user-scoped `change-request-merge-failed` on a gate block / conflict /
757
+ // merge error so the UI that kicked it off can react.
758
+ res.status(202).json({ status: 'merging', number: num });
759
+ void (async () => {
760
+ try {
761
+ const workspace = await workspaceService.getOrCreateForUser(user);
762
+ const detail = await workflow.getChangeRequestDetail(num, {
763
+ fresh: true,
764
+ workspaceId: workspace.id,
765
+ viewerEmail: user.email,
766
+ });
767
+ if (!detail) {
768
+ events.emit({
769
+ kind: 'change-request-merge-failed',
770
+ forUserId: user.id,
771
+ number: num,
772
+ reason: 'change request not found',
773
+ conflicts: false,
774
+ });
775
+ return;
776
+ }
777
+ const outcome = await workflow.mergeChangeRequest(num, user, detail.headSha, detail.approvals, detail.state, detail.title, detail.base, workspace.id, { bypass });
778
+ if (outcome.kind === 'conflicts-need-resolution') {
779
+ events.emit({
780
+ kind: 'change-request-merge-failed',
781
+ forUserId: user.id,
782
+ number: num,
783
+ reason: 'This draft conflicts with the target and needs resolving first.',
784
+ conflicts: true,
785
+ });
786
+ }
787
+ // Success path: `workflow.mergeChangeRequest` emits `change-request-merged`.
788
+ }
789
+ catch (err) {
790
+ const { body: errBody } = toHttpError(err);
791
+ console.error(`[workflow.routes] async merge of change request #${num} failed:`, err);
792
+ events.emit({
793
+ kind: 'change-request-merge-failed',
794
+ forUserId: user.id,
795
+ number: num,
796
+ reason: typeof errBody.error === 'string' ? errBody.error : 'Merge failed',
797
+ conflicts: false,
798
+ });
799
+ }
800
+ })();
801
+ });
802
+ return router;
803
+ }
804
+ //# sourceMappingURL=workflow.routes.js.map