@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,57 @@
1
+ /**
2
+ * Per-(workspace, branch, path) edit lock store. The spec calls for
3
+ * file-scoped locks acquired on first edit and released either explicitly
4
+ * (with an autosave commit) or implicitly by TTL expiry — preventing a
5
+ * disconnected client from holding a file hostage.
6
+ *
7
+ * Lock state lives in Postgres because workspaces share state across
8
+ * backend instances eventually. The hot read path (does someone hold this
9
+ * lock?) is one indexed lookup; the hot write path (heartbeat) is a single
10
+ * row update. We don't bother caching in process memory — the lock table
11
+ * is the source of truth and any cache would lose its purpose the moment
12
+ * a different replica takes over.
13
+ *
14
+ * Stale-lock semantics: `get`, `acquire`, and `heartbeat` all treat a row
15
+ * with `expires_at <= now()` as if the lock didn't exist. We purge it
16
+ * lazily on next access rather than running a sweeper — the row count is
17
+ * bounded by concurrent editors, not history, so lazy GC is fine.
18
+ */
19
+ import type { Database } from '../database/connection.js';
20
+ import type { AcquireLockResult, AuthUser, FileLock } from '@bevel-software/platform-shared';
21
+ export declare class FileLockService {
22
+ private readonly db;
23
+ constructor(db: Database);
24
+ /**
25
+ * Acquire a lock for `(workspaceId, branch, path)` on behalf of `user`.
26
+ *
27
+ * Three outcomes folded into the same return shape:
28
+ * - No existing row: insert + return `{ acquired: true, lock }`.
29
+ * - Existing row, expired: take it over (update) + `{ acquired: true }`.
30
+ * - Existing row, live, different user: return `{ acquired: false }`
31
+ * with the current holder's lock state so the UI can render
32
+ * "Locked by X" without a follow-up call.
33
+ * - Existing row, live, same user: refresh TTL + `{ acquired: true }`
34
+ * so re-acquiring your own lock is idempotent.
35
+ */
36
+ acquire(workspaceId: string, branch: string, targetPath: string, user: AuthUser): Promise<AcquireLockResult>;
37
+ /**
38
+ * Extend the lock's TTL. Refuses if the lock is held by someone else or
39
+ * doesn't exist — the client is then expected to re-call `acquire`,
40
+ * which will either succeed (taking over a stale lock) or surface the
41
+ * current holder.
42
+ */
43
+ heartbeat(workspaceId: string, branch: string, targetPath: string, user: AuthUser): Promise<FileLock>;
44
+ /**
45
+ * Idempotent release. Deletes the lock row when the caller holds it;
46
+ * silently no-ops otherwise (the lock may have expired and been taken
47
+ * over by someone else — that's not an error from the caller's POV).
48
+ */
49
+ release(workspaceId: string, branch: string, targetPath: string, user: AuthUser): Promise<void>;
50
+ /**
51
+ * Read the current lock for `(workspace, branch, path)`. Returns null when
52
+ * no one holds it, OR when the existing row is expired — expired locks
53
+ * are purged here lazily.
54
+ */
55
+ get(workspaceId: string, branch: string, targetPath: string): Promise<FileLock | null>;
56
+ }
57
+ //# sourceMappingURL=file-lock.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-lock.service.d.ts","sourceRoot":"","sources":["../../../src/modules/workflow/file-lock.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAE1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAwB7F,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ;IAEzC;;;;;;;;;;;OAWG;IACG,OAAO,CACX,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,iBAAiB,CAAC;IAuF7B;;;;;OAKG;IACG,SAAS,CACb,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,QAAQ,CAAC;IAoCpB;;;;OAIG;IACG,OAAO,CACX,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,IAAI,CAAC;IAahB;;;;OAIG;IACG,GAAG,CACP,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;CAoC5B"}
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Per-(workspace, branch, path) edit lock store. The spec calls for
3
+ * file-scoped locks acquired on first edit and released either explicitly
4
+ * (with an autosave commit) or implicitly by TTL expiry — preventing a
5
+ * disconnected client from holding a file hostage.
6
+ *
7
+ * Lock state lives in Postgres because workspaces share state across
8
+ * backend instances eventually. The hot read path (does someone hold this
9
+ * lock?) is one indexed lookup; the hot write path (heartbeat) is a single
10
+ * row update. We don't bother caching in process memory — the lock table
11
+ * is the source of truth and any cache would lose its purpose the moment
12
+ * a different replica takes over.
13
+ *
14
+ * Stale-lock semantics: `get`, `acquire`, and `heartbeat` all treat a row
15
+ * with `expires_at <= now()` as if the lock didn't exist. We purge it
16
+ * lazily on next access rather than running a sweeper — the row count is
17
+ * bounded by concurrent editors, not history, so lazy GC is fine.
18
+ */
19
+ import { and, eq, gt, lte } from 'drizzle-orm';
20
+ import { fileLocks } from '../database/schema.js';
21
+ import { WorkflowValidationError } from './workflow.errors.js';
22
+ /**
23
+ * Lock lifetime without a heartbeat. The client is expected to heartbeat
24
+ * every ~half this interval so a single missed ping doesn't release the
25
+ * lock out from under them. Bumping the TTL trades off "how long does a
26
+ * crashed client hold a file" against "how forgiving are we of network
27
+ * blips" — 60s is a balance.
28
+ */
29
+ const LOCK_TTL_MS = 60_000;
30
+ function rowToFileLock(row) {
31
+ return {
32
+ branch: row.branch,
33
+ path: row.path,
34
+ holderUserId: row.holderUserId,
35
+ holderName: row.holderName,
36
+ acquiredAt: row.acquiredAt.toISOString(),
37
+ lastHeartbeatAt: row.lastHeartbeatAt.toISOString(),
38
+ expiresAt: row.expiresAt.toISOString(),
39
+ };
40
+ }
41
+ export class FileLockService {
42
+ db;
43
+ constructor(db) {
44
+ this.db = db;
45
+ }
46
+ /**
47
+ * Acquire a lock for `(workspaceId, branch, path)` on behalf of `user`.
48
+ *
49
+ * Three outcomes folded into the same return shape:
50
+ * - No existing row: insert + return `{ acquired: true, lock }`.
51
+ * - Existing row, expired: take it over (update) + `{ acquired: true }`.
52
+ * - Existing row, live, different user: return `{ acquired: false }`
53
+ * with the current holder's lock state so the UI can render
54
+ * "Locked by X" without a follow-up call.
55
+ * - Existing row, live, same user: refresh TTL + `{ acquired: true }`
56
+ * so re-acquiring your own lock is idempotent.
57
+ */
58
+ async acquire(workspaceId, branch, targetPath, user) {
59
+ const now = new Date();
60
+ const expiresAt = new Date(now.getTime() + LOCK_TTL_MS);
61
+ // Atomic acquire-or-takeover, in a single statement. Two callers
62
+ // racing on the same `(workspace, branch, path)` would otherwise
63
+ // both SELECT no row → both INSERT (one PK-fails) or both SELECT a
64
+ // stale row → both UPDATE (one silently overwrites the other's
65
+ // takeover). PostgreSQL's INSERT ... ON CONFLICT DO UPDATE WHERE
66
+ // collapses both paths into one atomic statement:
67
+ //
68
+ // - No existing row → INSERT succeeds, RETURNING our new row.
69
+ // - Existing row, WHERE matches (stale OR same user) → UPDATE
70
+ // fires, RETURNING the updated row.
71
+ // - Existing row, WHERE doesn't match (live + different user) →
72
+ // the conflict is silently absorbed (PG's documented behavior),
73
+ // RETURNING is empty. We then read the live holder for the
74
+ // "Locked by X" payload.
75
+ //
76
+ // **Only expired rows can be taken over.** The same-user clause used
77
+ // to be here as an "idempotent refresh" shortcut, but it had a nasty
78
+ // side effect: the AGENT and the HUMAN EDITOR share the same `user.id`
79
+ // (agent edits attribute to the human), so the agent's
80
+ // `LockingFilesystem.withLock` would silently steal a lock the human
81
+ // had taken via the Edit button — overwriting their in-flight edits
82
+ // and dropping their lock on agent-release. Removing same-user from
83
+ // setWhere makes acquire strict: a non-expired lock is contended even
84
+ // by yourself, so the agent's retry/skip path kicks in and the human
85
+ // keeps editing. Real refresh-while-holding goes through
86
+ // `heartbeat()` (which has its own same-user UPDATE), and the
87
+ // editor's save flow detects "I already hold it" via `getLock` in
88
+ // `workspace.routes.withLock` rather than re-acquiring.
89
+ const upsertResult = await this.db
90
+ .insert(fileLocks)
91
+ .values({
92
+ workspaceId,
93
+ branch,
94
+ path: targetPath,
95
+ holderUserId: user.id,
96
+ holderName: user.name,
97
+ acquiredAt: now,
98
+ lastHeartbeatAt: now,
99
+ expiresAt,
100
+ })
101
+ .onConflictDoUpdate({
102
+ target: [fileLocks.workspaceId, fileLocks.branch, fileLocks.path],
103
+ set: {
104
+ holderUserId: user.id,
105
+ holderName: user.name,
106
+ acquiredAt: now,
107
+ lastHeartbeatAt: now,
108
+ expiresAt,
109
+ },
110
+ setWhere: lte(fileLocks.expiresAt, now),
111
+ })
112
+ .returning();
113
+ if (upsertResult.length > 0) {
114
+ return { acquired: true, lock: rowToFileLock(upsertResult[0]) };
115
+ }
116
+ // Live lock held by another user. Fetch it for the "Locked by X" UI
117
+ // payload. We don't filter on `expiresAt > now` here because the
118
+ // upsert above already proved an unreclaimable row exists; the only
119
+ // way this read returns null is a tight race where the holder
120
+ // released between the upsert and this select — rare enough to
121
+ // surface as a retryable error rather than complicate the happy path.
122
+ const [holder] = await this.db
123
+ .select()
124
+ .from(fileLocks)
125
+ .where(and(eq(fileLocks.workspaceId, workspaceId), eq(fileLocks.branch, branch), eq(fileLocks.path, targetPath)))
126
+ .limit(1);
127
+ if (!holder) {
128
+ throw new WorkflowValidationError(`Lock contention race on "${targetPath}" — please retry.`, { kind: 'lock-contention-race', branch, path: targetPath });
129
+ }
130
+ return { acquired: false, lock: rowToFileLock(holder) };
131
+ }
132
+ /**
133
+ * Extend the lock's TTL. Refuses if the lock is held by someone else or
134
+ * doesn't exist — the client is then expected to re-call `acquire`,
135
+ * which will either succeed (taking over a stale lock) or surface the
136
+ * current holder.
137
+ */
138
+ async heartbeat(workspaceId, branch, targetPath, user) {
139
+ const now = new Date();
140
+ const expiresAt = new Date(now.getTime() + LOCK_TTL_MS);
141
+ // The expiry guard (`expiresAt > now`) matters because an expired
142
+ // lock is conceptually released, even if its row hasn't been swept
143
+ // and no other user has taken it yet. Without it, a client whose
144
+ // tab was suspended past the TTL would silently extend a lock that
145
+ // the rest of the system considers "free for the next acquire" —
146
+ // any subsequent `acquire()` by another user could already have
147
+ // taken it (the upsert's `lte(expiresAt, now)` predicate matches),
148
+ // and the heartbeat would race with that takeover. Failing here
149
+ // forces the client to re-acquire (which goes through the proper
150
+ // takeover path) and surfaces the "your session went stale" state
151
+ // honestly.
152
+ const [updated] = await this.db
153
+ .update(fileLocks)
154
+ .set({ lastHeartbeatAt: now, expiresAt })
155
+ .where(and(eq(fileLocks.workspaceId, workspaceId), eq(fileLocks.branch, branch), eq(fileLocks.path, targetPath), eq(fileLocks.holderUserId, user.id), gt(fileLocks.expiresAt, now)))
156
+ .returning();
157
+ if (!updated) {
158
+ throw new WorkflowValidationError(`Cannot heartbeat lock on "${targetPath}": not held by you (or no longer exists).`, { kind: 'lock-not-held', branch, path: targetPath });
159
+ }
160
+ return rowToFileLock(updated);
161
+ }
162
+ /**
163
+ * Idempotent release. Deletes the lock row when the caller holds it;
164
+ * silently no-ops otherwise (the lock may have expired and been taken
165
+ * over by someone else — that's not an error from the caller's POV).
166
+ */
167
+ async release(workspaceId, branch, targetPath, user) {
168
+ await this.db
169
+ .delete(fileLocks)
170
+ .where(and(eq(fileLocks.workspaceId, workspaceId), eq(fileLocks.branch, branch), eq(fileLocks.path, targetPath), eq(fileLocks.holderUserId, user.id)));
171
+ }
172
+ /**
173
+ * Read the current lock for `(workspace, branch, path)`. Returns null when
174
+ * no one holds it, OR when the existing row is expired — expired locks
175
+ * are purged here lazily.
176
+ */
177
+ async get(workspaceId, branch, targetPath) {
178
+ const rows = await this.db
179
+ .select()
180
+ .from(fileLocks)
181
+ .where(and(eq(fileLocks.workspaceId, workspaceId), eq(fileLocks.branch, branch), eq(fileLocks.path, targetPath)))
182
+ .limit(1);
183
+ if (rows.length === 0)
184
+ return null;
185
+ const row = rows[0];
186
+ if (row.expiresAt.getTime() <= Date.now()) {
187
+ // Lazy GC — drop the stale row so the next `acquire` doesn't have
188
+ // to bypass it. Bind the delete to this exact row's `expiresAt` so
189
+ // a concurrent acquire that wrote a fresh row in the gap between
190
+ // our SELECT and DELETE doesn't get clobbered. Primary key
191
+ // `(workspaceId, branch, path)` alone isn't enough — a new acquire
192
+ // for the same triple updates that row in place with a future
193
+ // expiry, and a path-only delete here would silently nuke it.
194
+ await this.db
195
+ .delete(fileLocks)
196
+ .where(and(eq(fileLocks.workspaceId, workspaceId), eq(fileLocks.branch, branch), eq(fileLocks.path, targetPath), eq(fileLocks.expiresAt, row.expiresAt)));
197
+ return null;
198
+ }
199
+ return rowToFileLock(row);
200
+ }
201
+ }
202
+ //# sourceMappingURL=file-lock.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-lock.service.js","sourceRoot":"","sources":["../../../src/modules/workflow/file-lock.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export { PROTECTED_BRANCHES, isProtectedBranch } from '@bevel-software/platform-shared';
2
+ export { branchAuthorLocalpart, isBranchAuthoredBy } from '@bevel-software/platform-shared';
3
+ /** Throw if `name` cannot safely be passed to `git` as a branch name. */
4
+ export declare function assertValidBranchName(name: string): void;
5
+ /**
6
+ * Guard against path traversal and shell-unsafe characters on any workspace-relative
7
+ * path we pass to `git` as a pathspec. Must stay within the repo; forward slashes only.
8
+ */
9
+ export declare function assertValidRelativePath(relativePath: string): void;
10
+ //# sourceMappingURL=branch-name.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch-name.d.ts","sourceRoot":"","sources":["../../../../src/modules/workflow/git/branch-name.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAKxF,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAI5F,yEAAyE;AACzE,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAwBxD;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAyBlE"}
@@ -0,0 +1,76 @@
1
+ import { BranchNameError, WorkflowValidationError } from '../workflow.errors.js';
2
+ // Single source of truth for the protected-branch list lives in `@bevel-software/platform-shared` so
3
+ // the backend guard and the frontend banner/disabling logic can't drift apart.
4
+ export { PROTECTED_BRANCHES, isProtectedBranch } from '@bevel-software/platform-shared';
5
+ // Authorship inference lives in `@bevel-software/platform-shared` for the same reason — the
6
+ // picker's `canDelete` rule and the backend authorisation check on
7
+ // `deleteBranch` must agree on every edge case (uppercase email, dotted
8
+ // localpart, etc.).
9
+ export { branchAuthorLocalpart, isBranchAuthoredBy } from '@bevel-software/platform-shared';
10
+ const VALID_BRANCH_REGEX = /^[A-Za-z0-9][A-Za-z0-9/_\-.]*$/;
11
+ /** Throw if `name` cannot safely be passed to `git` as a branch name. */
12
+ export function assertValidBranchName(name) {
13
+ if (!name)
14
+ throw new BranchNameError('empty name', name);
15
+ if (name.length > 255)
16
+ throw new BranchNameError('too long', name);
17
+ if (!VALID_BRANCH_REGEX.test(name)) {
18
+ throw new BranchNameError('contains invalid characters', name);
19
+ }
20
+ if (name.includes('..'))
21
+ throw new BranchNameError('contains ".."', name);
22
+ if (name.includes('//'))
23
+ throw new BranchNameError('contains "//"', name);
24
+ if (name.endsWith('/') || name.endsWith('.')) {
25
+ throw new BranchNameError('ends with "/" or "."', name);
26
+ }
27
+ if (name.startsWith('-'))
28
+ throw new BranchNameError('starts with "-"', name);
29
+ if (name.includes('@{'))
30
+ throw new BranchNameError('contains "@{"', name);
31
+ // Per-segment rules: git forbids any `/`-separated segment from beginning
32
+ // with "." or ending with ".lock" (e.g. `foo/.tmp`, `foo.lock/bar`).
33
+ // The whole-name checks above can't catch nested violations.
34
+ for (const segment of name.split('/')) {
35
+ if (segment.startsWith('.')) {
36
+ throw new BranchNameError('segment starts with "."', name);
37
+ }
38
+ if (segment.endsWith('.lock')) {
39
+ throw new BranchNameError('segment ends with ".lock"', name);
40
+ }
41
+ }
42
+ }
43
+ /**
44
+ * Guard against path traversal and shell-unsafe characters on any workspace-relative
45
+ * path we pass to `git` as a pathspec. Must stay within the repo; forward slashes only.
46
+ */
47
+ export function assertValidRelativePath(relativePath) {
48
+ if (!relativePath)
49
+ throw new WorkflowValidationError('path is required');
50
+ if (relativePath.length > 1024)
51
+ throw new WorkflowValidationError('path too long');
52
+ if (relativePath.includes('\0'))
53
+ throw new WorkflowValidationError('path contains NUL');
54
+ if (relativePath.includes('\\')) {
55
+ throw new WorkflowValidationError('path must use forward slashes only');
56
+ }
57
+ if (relativePath.startsWith('/') || /^[A-Za-z]:/.test(relativePath)) {
58
+ throw new WorkflowValidationError('path must be relative');
59
+ }
60
+ const parts = relativePath.split('/');
61
+ if (parts.some((p) => p === '..' || p === '.')) {
62
+ throw new WorkflowValidationError('path must not contain "." or ".."');
63
+ }
64
+ if (relativePath.startsWith('-')) {
65
+ throw new WorkflowValidationError('path must not start with "-"');
66
+ }
67
+ // Pathspec glob characters (`*`, `?`, `[`, `]`, `!`) and pathspec magic (`:(…)`)
68
+ // would otherwise be interpreted by `git add -- <path>` / `git log -- <path>`
69
+ // and match the wrong files. `GitService.git()` sets `GIT_LITERAL_PATHSPECS=1`
70
+ // on every git subprocess, which forces literal interpretation across the
71
+ // board — so KB filenames containing `[Approved]`, `[New]`, etc. round-trip
72
+ // through commit cleanly. The shared `validateFilename` already rejects `:`
73
+ // along with the rest of Windows-forbidden characters before paths reach this
74
+ // layer, so a redundant check here would only confuse the error message.
75
+ }
76
+ //# sourceMappingURL=branch-name.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch-name.js","sourceRoot":"","sources":["../../../../src/modules/workflow/git/branch-name.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * The git configuration a per-branch workspace clone must have for its branch
3
+ * to track exactly ONE upstream ref.
4
+ *
5
+ * Why this exists: a clone's config is append-only from git's point of view,
6
+ * and several things write to it:
7
+ *
8
+ * - `git config --add branch.<name>.merge …` / `git branch --set-upstream-to`
9
+ * run out of band (an agent shell session in the workspace, a manual fix)
10
+ * leaves a SECOND `branch.<name>.merge` value;
11
+ * - `git remote set-branches --add origin …`, a re-run `git remote add`, or a
12
+ * hand-edited `.git/config` leaves a SECOND `remote.origin.fetch` refspec,
13
+ * so one fetch maps the same remote branch in twice.
14
+ *
15
+ * A multi-valued `branch.<name>.merge` is what makes a BARE `git fetch origin`
16
+ * write more than one *for-merge* entry into the clone's shared
17
+ * `.git/FETCH_HEAD` — git adds one per configured merge ref. That is the
18
+ * ammunition behind the reported failure: `git pull` reads its rebase target
19
+ * out of that same shared file, so when one of the app's unmutexed bare
20
+ * fetches lands inside the pull's fetch→read window, the pull sees two merge
21
+ * heads and dies with `fatal: Cannot rebase onto multiple branches.`
22
+ *
23
+ * The drift alone is NOT sufficient — an explicit `git pull --rebase origin
24
+ * <branch>` survives every drift shape on its own (verified across the shapes
25
+ * above on git 2.39.5); it takes the concurrent fetch too. `GitService.pull`
26
+ * closes the other half by never reading or writing FETCH_HEAD; normalising
27
+ * the config here removes the ammunition.
28
+ *
29
+ * These are the three keys that pin the clone back to "this branch tracks
30
+ * `origin/<branch>`, nothing else"; applied with `--replace-all` they collapse
31
+ * any accumulated duplicates into one value.
32
+ *
33
+ * Lives here — next to `assertValidBranchName` — as a leaf-level primitive
34
+ * shared by the git layer (self-heal before every pull) and `WorkspaceService`
35
+ * (stamped on new clones, and re-stamped on existing ones the first time this
36
+ * process opens them, which is the migration for clones already on disk).
37
+ */
38
+ /** The single fetch refspec a workspace clone of the KB is created with. */
39
+ export declare const ORIGIN_FETCH_REFSPEC = "+refs/heads/*:refs/remotes/origin/*";
40
+ /**
41
+ * The one safe shape for an implicit background fetch of a workspace clone —
42
+ * shared by `GitService.fetchOriginIfStale` and
43
+ * `WorkspaceService.ensureRemotesFetched`, both of which run OUTSIDE the
44
+ * workspace mutex. `--no-write-fetch-head` is what makes that safe: without it
45
+ * a bare fetch rewrites the clone's shared `.git/FETCH_HEAD` underneath
46
+ * whatever else is running in it, which is how the post-merge `git pull` read
47
+ * two merge heads and died with "Cannot rebase onto multiple branches" (see
48
+ * the header comment above and `GitService.pull`). These paths only want the
49
+ * remote-tracking refs refreshed; `--prune` keeps deleted remote branches from
50
+ * lingering. Callers prepend their own runner context (`-C <dir>` /
51
+ * `-c http.*` options) but must not vary these arguments.
52
+ */
53
+ export declare const SAFE_IMPLICIT_FETCH_ARGS: readonly string[];
54
+ /**
55
+ * `git` argument lists that normalise a clone's tracking config for `branch`.
56
+ * Returns the arguments rather than running them so each caller can use its own
57
+ * git runner (the git service's mutex-aware wrapper, `git -C` from the
58
+ * workspace service) — no process is spawned here.
59
+ */
60
+ export declare function cloneTrackingConfigArgs(branch: string): string[][];
61
+ //# sourceMappingURL=clone-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clone-config.d.ts","sourceRoot":"","sources":["../../../../src/modules/workflow/git/clone-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB,wCAAwC,CAAC;AAE1E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,wBAAwB,EAAE,SAAS,MAAM,EAErD,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAMlE"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * The git configuration a per-branch workspace clone must have for its branch
3
+ * to track exactly ONE upstream ref.
4
+ *
5
+ * Why this exists: a clone's config is append-only from git's point of view,
6
+ * and several things write to it:
7
+ *
8
+ * - `git config --add branch.<name>.merge …` / `git branch --set-upstream-to`
9
+ * run out of band (an agent shell session in the workspace, a manual fix)
10
+ * leaves a SECOND `branch.<name>.merge` value;
11
+ * - `git remote set-branches --add origin …`, a re-run `git remote add`, or a
12
+ * hand-edited `.git/config` leaves a SECOND `remote.origin.fetch` refspec,
13
+ * so one fetch maps the same remote branch in twice.
14
+ *
15
+ * A multi-valued `branch.<name>.merge` is what makes a BARE `git fetch origin`
16
+ * write more than one *for-merge* entry into the clone's shared
17
+ * `.git/FETCH_HEAD` — git adds one per configured merge ref. That is the
18
+ * ammunition behind the reported failure: `git pull` reads its rebase target
19
+ * out of that same shared file, so when one of the app's unmutexed bare
20
+ * fetches lands inside the pull's fetch→read window, the pull sees two merge
21
+ * heads and dies with `fatal: Cannot rebase onto multiple branches.`
22
+ *
23
+ * The drift alone is NOT sufficient — an explicit `git pull --rebase origin
24
+ * <branch>` survives every drift shape on its own (verified across the shapes
25
+ * above on git 2.39.5); it takes the concurrent fetch too. `GitService.pull`
26
+ * closes the other half by never reading or writing FETCH_HEAD; normalising
27
+ * the config here removes the ammunition.
28
+ *
29
+ * These are the three keys that pin the clone back to "this branch tracks
30
+ * `origin/<branch>`, nothing else"; applied with `--replace-all` they collapse
31
+ * any accumulated duplicates into one value.
32
+ *
33
+ * Lives here — next to `assertValidBranchName` — as a leaf-level primitive
34
+ * shared by the git layer (self-heal before every pull) and `WorkspaceService`
35
+ * (stamped on new clones, and re-stamped on existing ones the first time this
36
+ * process opens them, which is the migration for clones already on disk).
37
+ */
38
+ /** The single fetch refspec a workspace clone of the KB is created with. */
39
+ export const ORIGIN_FETCH_REFSPEC = '+refs/heads/*:refs/remotes/origin/*';
40
+ /**
41
+ * The one safe shape for an implicit background fetch of a workspace clone —
42
+ * shared by `GitService.fetchOriginIfStale` and
43
+ * `WorkspaceService.ensureRemotesFetched`, both of which run OUTSIDE the
44
+ * workspace mutex. `--no-write-fetch-head` is what makes that safe: without it
45
+ * a bare fetch rewrites the clone's shared `.git/FETCH_HEAD` underneath
46
+ * whatever else is running in it, which is how the post-merge `git pull` read
47
+ * two merge heads and died with "Cannot rebase onto multiple branches" (see
48
+ * the header comment above and `GitService.pull`). These paths only want the
49
+ * remote-tracking refs refreshed; `--prune` keeps deleted remote branches from
50
+ * lingering. Callers prepend their own runner context (`-C <dir>` /
51
+ * `-c http.*` options) but must not vary these arguments.
52
+ */
53
+ export const SAFE_IMPLICIT_FETCH_ARGS = [
54
+ 'fetch', '--prune', '--no-write-fetch-head', 'origin',
55
+ ];
56
+ /**
57
+ * `git` argument lists that normalise a clone's tracking config for `branch`.
58
+ * Returns the arguments rather than running them so each caller can use its own
59
+ * git runner (the git service's mutex-aware wrapper, `git -C` from the
60
+ * workspace service) — no process is spawned here.
61
+ */
62
+ export function cloneTrackingConfigArgs(branch) {
63
+ return [
64
+ ['config', '--replace-all', 'remote.origin.fetch', ORIGIN_FETCH_REFSPEC],
65
+ ['config', '--replace-all', `branch.${branch}.remote`, 'origin'],
66
+ ['config', '--replace-all', `branch.${branch}.merge`, `refs/heads/${branch}`],
67
+ ];
68
+ }
69
+ //# sourceMappingURL=clone-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clone-config.js","sourceRoot":"","sources":["../../../../src/modules/workflow/git/clone-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,4EAA4E;AAC5E,MAAM,CAAC,MAAM,oBAAoB,GAAG,qCAAqC,CAAC;AAE1E;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAsB;IACzD,OAAO,EAAE,SAAS,EAAE,uBAAuB,EAAE,QAAQ;CACtD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAc;IACpD,OAAO;QACL,CAAC,QAAQ,EAAE,eAAe,EAAE,qBAAqB,EAAE,oBAAoB,CAAC;QACxE,CAAC,QAAQ,EAAE,eAAe,EAAE,UAAU,MAAM,SAAS,EAAE,QAAQ,CAAC;QAChE,CAAC,QAAQ,EAAE,eAAe,EAAE,UAAU,MAAM,QAAQ,EAAE,cAAc,MAAM,EAAE,CAAC;KAC9E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * The `git` floor this app depends on.
3
+ *
4
+ * Every fetch the workspace layer runs passes `--no-write-fetch-head` — the
5
+ * option that keeps one clone's fetches from steering a concurrent refresh
6
+ * through the shared `.git/FETCH_HEAD` (see `GitService.pull`) — and git only
7
+ * learned it in 2.29. On an older binary every one of those fetches dies with
8
+ * `unknown option`, which takes out `pull`, `resetToRemote` and
9
+ * `mergeChangeRequest` at once.
10
+ *
11
+ * The production image installs git from Debian via `node:22-slim`, which is
12
+ * well past the floor, so this guard is about a re-based or swapped runtime
13
+ * image rather than a live problem. Its value is *when* it fires: at boot,
14
+ * naming the installed version, instead of at the first change-request merge
15
+ * with an opaque git error.
16
+ */
17
+ /** Oldest git that understands `--no-write-fetch-head`. */
18
+ export declare const MIN_GIT_VERSION: readonly [number, number];
19
+ /** `git version 2.39.5 (Apple Git-154)` → `[2, 39]`; null if unrecognisable. */
20
+ export declare function parseGitVersion(stdout: string): [number, number] | null;
21
+ /**
22
+ * Throw when `git --version` output names a version below the floor.
23
+ *
24
+ * An output we can't parse is NOT fatal: a git build with an unusual version
25
+ * string is far more likely than one older than 2.29, and refusing to boot over
26
+ * an unrecognised string would be a worse failure than the one being guarded.
27
+ */
28
+ export declare function assertSupportedGitVersion(stdout: string): void;
29
+ /**
30
+ * Run `git --version` and apply the floor. Call once during startup, before
31
+ * anything clones or fetches.
32
+ */
33
+ export declare function assertGitVersion(): Promise<void>;
34
+ //# sourceMappingURL=git-version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-version.d.ts","sourceRoot":"","sources":["../../../../src/modules/workflow/git/git-version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAOH,2DAA2D;AAC3D,eAAO,MAAM,eAAe,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAW,CAAC;AAElE,gFAAgF;AAChF,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAGvE;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAiB9D;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAQtD"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * The `git` floor this app depends on.
3
+ *
4
+ * Every fetch the workspace layer runs passes `--no-write-fetch-head` — the
5
+ * option that keeps one clone's fetches from steering a concurrent refresh
6
+ * through the shared `.git/FETCH_HEAD` (see `GitService.pull`) — and git only
7
+ * learned it in 2.29. On an older binary every one of those fetches dies with
8
+ * `unknown option`, which takes out `pull`, `resetToRemote` and
9
+ * `mergeChangeRequest` at once.
10
+ *
11
+ * The production image installs git from Debian via `node:22-slim`, which is
12
+ * well past the floor, so this guard is about a re-based or swapped runtime
13
+ * image rather than a live problem. Its value is *when* it fires: at boot,
14
+ * naming the installed version, instead of at the first change-request merge
15
+ * with an opaque git error.
16
+ */
17
+ import { execFile } from 'node:child_process';
18
+ import { promisify } from 'node:util';
19
+ const execFileAsync = promisify(execFile);
20
+ /** Oldest git that understands `--no-write-fetch-head`. */
21
+ export const MIN_GIT_VERSION = [2, 29];
22
+ /** `git version 2.39.5 (Apple Git-154)` → `[2, 39]`; null if unrecognisable. */
23
+ export function parseGitVersion(stdout) {
24
+ const m = /^git version (\d+)\.(\d+)/.exec(stdout.trim());
25
+ return m ? [Number(m[1]), Number(m[2])] : null;
26
+ }
27
+ /**
28
+ * Throw when `git --version` output names a version below the floor.
29
+ *
30
+ * An output we can't parse is NOT fatal: a git build with an unusual version
31
+ * string is far more likely than one older than 2.29, and refusing to boot over
32
+ * an unrecognised string would be a worse failure than the one being guarded.
33
+ */
34
+ export function assertSupportedGitVersion(stdout) {
35
+ const found = parseGitVersion(stdout);
36
+ const [minMajor, minMinor] = MIN_GIT_VERSION;
37
+ if (!found) {
38
+ console.warn(`[git] could not read a version from "${stdout.trim()}" — ` +
39
+ `skipping the git ${minMajor}.${minMinor}+ check`);
40
+ return;
41
+ }
42
+ const [major, minor] = found;
43
+ if (major > minMajor || (major === minMajor && minor >= minMinor))
44
+ return;
45
+ throw new Error(`git ${minMajor}.${minMinor} or newer is required, found ${major}.${minor}. ` +
46
+ 'Every workspace fetch passes --no-write-fetch-head, which older git rejects, ' +
47
+ 'so branch refresh and change-request merges cannot work on this runtime.');
48
+ }
49
+ /**
50
+ * Run `git --version` and apply the floor. Call once during startup, before
51
+ * anything clones or fetches.
52
+ */
53
+ export async function assertGitVersion() {
54
+ let stdout;
55
+ try {
56
+ ({ stdout } = await execFileAsync('git', ['--version']));
57
+ }
58
+ catch (err) {
59
+ throw new Error(`git is required but could not be run: ${String(err)}`);
60
+ }
61
+ assertSupportedGitVersion(stdout);
62
+ }
63
+ //# sourceMappingURL=git-version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-version.js","sourceRoot":"","sources":["../../../../src/modules/workflow/git/git-version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C,2DAA2D;AAC3D,MAAM,CAAC,MAAM,eAAe,GAA8B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAElE,gFAAgF;AAChF,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,MAAM,CAAC,GAAG,2BAA2B,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1D,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAc;IACtD,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IACtC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,eAAe,CAAC;IAC7C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CACV,wCAAwC,MAAM,CAAC,IAAI,EAAE,MAAM;YACzD,oBAAoB,QAAQ,IAAI,QAAQ,SAAS,CACpD,CAAC;QACF,OAAO;IACT,CAAC;IACD,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,KAAK,CAAC;IAC7B,IAAI,KAAK,GAAG,QAAQ,IAAI,CAAC,KAAK,KAAK,QAAQ,IAAI,KAAK,IAAI,QAAQ,CAAC;QAAE,OAAO;IAC1E,MAAM,IAAI,KAAK,CACb,OAAO,QAAQ,IAAI,QAAQ,gCAAgC,KAAK,IAAI,KAAK,IAAI;QAC3E,+EAA+E;QAC/E,0EAA0E,CAC7E,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QACH,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,yCAAyC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,yBAAyB,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC"}