@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,257 @@
1
+ import dotenv from 'dotenv';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { defaultKbTemplateDir } from './assets.js';
5
+
6
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
+ dotenv.config({ path: path.resolve(__dirname, '../../../.env') });
8
+
9
+ /**
10
+ * Configuration for the CORE platform: the git-backed workspace/workflow,
11
+ * skills, tools, secrets vault, access control, and the MCP surface. Contains
12
+ * NO LLM, connector, or SSO-provider settings — those live on the enterprise
13
+ * `AppConfig` (config.ts), which extends this class. A core-only deployment
14
+ * boots from exactly these env vars.
15
+ */
16
+ export class CoreConfig {
17
+ readonly port: number;
18
+ readonly databaseUrl: string;
19
+ readonly nodeEnv: string;
20
+ /**
21
+ * Tenant slug injected into every credential prefix so a deploy can brand its
22
+ * keys (`<tenant>_…` external API keys, `<tenant>-int_…` internal tokens,
23
+ * `<tenant>-up_…` upload tokens). Defaults to `bevel`. Changing it on an
24
+ * existing deployment invalidates previously minted keys/tokens (their
25
+ * prefix no longer matches), so pick it once. Lowercase alphanumeric only —
26
+ * `_` and `-` are reserved as prefix separators.
27
+ */
28
+ readonly tenantId: string;
29
+ readonly workspacesRoot: string;
30
+ /**
31
+ * Sibling-to-`workspacesRoot` location for the diff-review backup ledger.
32
+ * Layout mirrors `workspacesRoot` one-to-one: each user's repo lives at
33
+ * `<workspacesRoot>/<userId>/<repo>/...` and its backup at
34
+ * `<backupsRoot>/<userId>/<repo>/...`. Default sits next to workspaces so
35
+ * the two move together when ops point them at a different volume.
36
+ */
37
+ readonly backupsRoot: string;
38
+ /**
39
+ * Sibling-to-`workspacesRoot` location for `call_tool_chain` spill files —
40
+ * oversized tool-chain results parked outside any workspace so any agent (in-
41
+ * process or external over MCP) can read them back via `read_file`. Ephemeral,
42
+ * never committed, best-effort GC'd on write.
43
+ */
44
+ readonly spillRoot: string;
45
+ readonly jwtSecret: string;
46
+ readonly testPassword: string;
47
+ /** Clone/push URL for the KB repo. Any https git host (GitHub, GitLab, Bitbucket, Azure DevOps, self-hosted). */
48
+ readonly kbRepoUrl: string;
49
+ /** Directory name the KB lives under inside each user's workspace dir. */
50
+ readonly kbDirName: string;
51
+ /**
52
+ * Username sent in the git-over-HTTPS Basic credential (password = the git
53
+ * token). All major hosts accept a token as the password but differ on the
54
+ * username: GitHub `x-access-token` (default), GitLab `oauth2`, Bitbucket
55
+ * `x-token-auth`, Azure DevOps any non-empty value. Set `GIT_USERNAME` per
56
+ * host. Restricted to a safe charset because it's interpolated into the
57
+ * credential-helper shell snippet.
58
+ */
59
+ readonly gitUsername: string;
60
+ /**
61
+ * Filesystem path to the KB seed template (the `kb-template/` folder shipped
62
+ * inside this package — see `defaultKbTemplateDir()`). The seeder reads this
63
+ * to initialise an empty KB remote, and to top-up missing scaffolding on an
64
+ * existing one. Override with `KB_TEMPLATE_DIR`.
65
+ */
66
+ readonly kbTemplateDir: string;
67
+ /**
68
+ * Admin emails written into the generated `roles.yaml` when a fresh KB repo is
69
+ * seeded. Comma/whitespace-separated. A freshly-seeded repo with no Admin is
70
+ * unusable (access resolution requires ≥1 Admin), so seeding an EMPTY remote
71
+ * fails fast when this is empty. Not needed once the remote is already seeded.
72
+ */
73
+ readonly seedAdminEmails: string[];
74
+ /**
75
+ * Ontology-session boundary kill-switch. When true (default), an agent run
76
+ * that has read across more than one ontology can no longer write. A no-op on
77
+ * a single-ontology KB. Set `ONTOLOGY_SESSION_BLOCK=false` to disable.
78
+ *
79
+ * Stays on CORE config (not `AppConfig`) even though the write BLOCK itself
80
+ * is an enterprise-registered hook: the flag also switches off the core-owned
81
+ * touch TRACKING (the gate skips entirely when false — see
82
+ * `session-ontology.gate.ts`), so it must exist wherever the tracking runs.
83
+ */
84
+ readonly ontologySessionBlock: boolean;
85
+ /**
86
+ * Password-login toggle for the login screen. Default enabled; set
87
+ * `LOGIN_PASSWORD=false` to hide the method AND reject `/auth/login`
88
+ * server-side. SSO methods are separate `AuthProviderPlugin`s wired by the
89
+ * composition root — their toggles live with their configuration.
90
+ */
91
+ readonly loginPasswordEnabled: boolean;
92
+ /**
93
+ * Optional allow-list of email domains. When non-empty, ONLY emails whose
94
+ * domain matches (exactly, or as a subdomain) may log in via ANY method
95
+ * (shared-password or SSO). Comma/whitespace-separated; empty (default)
96
+ * allows any email. A leading `@` or `.` on an entry is tolerated, so
97
+ * `ALLOWED_EMAIL_DOMAINS=bevel.software, example.com` works as expected.
98
+ */
99
+ readonly allowedEmailDomains: string[];
100
+ /**
101
+ * 32-byte key (hex or base64) for AES-256-GCM encryption of core at-rest
102
+ * secrets: the secrets-vault values and the MCP OAuth client secrets/tokens.
103
+ * Read from `SECRETS_ENC_KEY`, falling back to the legacy
104
+ * `CONNECTOR_CONFIG_ENC_KEY` → `SHAREPOINT_TOKEN_ENC_KEY` chain so existing
105
+ * deploys keep decrypting without re-keying. Empty = secret values can't be
106
+ * saved (a clear error surfaces only when a secret is actually written/read).
107
+ */
108
+ readonly secretsEncKey: string;
109
+ /**
110
+ * Public base URL of THIS backend, used to build OAuth redirect URIs.
111
+ * Must match a redirect URI registered with the OAuth provider(s).
112
+ */
113
+ readonly publicBackendUrl: string;
114
+ /** Public base URL of the frontend, where callbacks redirect post-login. */
115
+ readonly publicFrontendUrl: string;
116
+
117
+ constructor() {
118
+ this.port = parseInt(process.env.PORT || '3001', 10);
119
+ this.databaseUrl = process.env.DATABASE_URL || 'postgresql://bevel:bevel@localhost:5432/bevel';
120
+ this.nodeEnv = process.env.NODE_ENV || 'development';
121
+ this.tenantId = (process.env.TENANT_ID || 'bevel').trim().toLowerCase();
122
+ if (!/^[a-z0-9]+$/.test(this.tenantId)) {
123
+ throw new Error(
124
+ `TENANT_ID must be lowercase alphanumeric (no separators); got "${this.tenantId}"`,
125
+ );
126
+ }
127
+ this.workspacesRoot = process.env.WORKSPACES_ROOT || path.resolve(process.cwd(), 'workspaces');
128
+ this.backupsRoot = process.env.BACKUPS_ROOT || path.resolve(this.workspacesRoot, '..', 'backups');
129
+ this.spillRoot = process.env.SPILL_ROOT || path.resolve(this.workspacesRoot, '..', 'tool-chain-spills');
130
+ this.jwtSecret = process.env.JWT_SECRET || '';
131
+ this.testPassword = process.env.TEST_PASSWORD || '';
132
+ // No default: the KB repo is deployment-specific, and a wrong fallback
133
+ // would surface much later as a confusing clone failure. Fail at boot.
134
+ this.kbRepoUrl = (process.env.KB_REPO_URL || '').trim();
135
+ if (this.kbRepoUrl === '') {
136
+ throw new Error(
137
+ 'KB_REPO_URL is required — the https clone/push URL of the git repository that stores your knowledge base.',
138
+ );
139
+ }
140
+ this.kbDirName = process.env.KB_DIR_NAME || 'knowledge-base';
141
+ // Provider-neutral git token: operators can set GIT_TOKEN (or the legacy
142
+ // GITHUB_TOKEN / GH_TOKEN). Normalize onto GITHUB_TOKEN — the name the
143
+ // credential helper and every `$GITHUB_TOKEN` read + redaction use — so all
144
+ // three work unchanged. GIT_TOKEN takes PRECEDENCE: it's the provider-neutral
145
+ // name, so setting it must override a stale legacy GITHUB_TOKEN (e.g. when
146
+ // switching the KB from GitHub to GitLab), not be shadowed by it.
147
+ const gitToken = process.env.GIT_TOKEN || process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
148
+ if (gitToken) process.env.GITHUB_TOKEN = gitToken;
149
+ this.gitUsername = (process.env.GIT_USERNAME || 'x-access-token').trim();
150
+ // Interpolated into the credential-helper shell snippet, so reject anything
151
+ // that isn't a plain token — no quotes, spaces, or shell metacharacters.
152
+ if (!/^[A-Za-z0-9._-]+$/.test(this.gitUsername)) {
153
+ throw new Error(
154
+ `GIT_USERNAME must match [A-Za-z0-9._-]+ (a plain auth username); got "${this.gitUsername}"`,
155
+ );
156
+ }
157
+ // Default: the `kb-template/` folder shipped inside this package (works
158
+ // both from src/ and compiled dist/ — see assets.ts).
159
+ this.kbTemplateDir = process.env.KB_TEMPLATE_DIR || defaultKbTemplateDir();
160
+ this.seedAdminEmails = (process.env.SEED_ADMIN_EMAILS || '')
161
+ .split(/[\s,]+/)
162
+ .map((e) => e.trim().toLowerCase())
163
+ .filter((e) => e.length > 0);
164
+ this.ontologySessionBlock =
165
+ (process.env.ONTOLOGY_SESSION_BLOCK ?? 'true').trim().toLowerCase() !== 'false';
166
+ this.loginPasswordEnabled =
167
+ (process.env.LOGIN_PASSWORD ?? 'true').trim().toLowerCase() !== 'false';
168
+ this.allowedEmailDomains = (process.env.ALLOWED_EMAIL_DOMAINS || '')
169
+ .split(/[\s,]+/)
170
+ .map((d) => d.trim().toLowerCase().replace(/^[@.]+/, ''))
171
+ .filter((d) => d.length > 0);
172
+ this.secretsEncKey = (
173
+ process.env.SECRETS_ENC_KEY ||
174
+ process.env.CONNECTOR_CONFIG_ENC_KEY ||
175
+ process.env.SHAREPOINT_TOKEN_ENC_KEY ||
176
+ ''
177
+ ).trim();
178
+ this.publicBackendUrl = (process.env.PUBLIC_BACKEND_URL || `http://localhost:${this.port}`)
179
+ .trim()
180
+ .replace(/\/+$/, '');
181
+ this.publicFrontendUrl = (process.env.PUBLIC_FRONTEND_URL || 'http://localhost:5173')
182
+ .trim()
183
+ .replace(/\/+$/, '');
184
+ // Parse-validate so a malformed URL fails at boot rather than producing a
185
+ // broken OAuth redirect later. (We intentionally don't force https / reject
186
+ // localhost in production: local Docker runs prod mode over http://localhost.)
187
+ for (const [name, value] of [
188
+ ['PUBLIC_BACKEND_URL', this.publicBackendUrl],
189
+ ['PUBLIC_FRONTEND_URL', this.publicFrontendUrl],
190
+ ] as const) {
191
+ try {
192
+ new URL(value);
193
+ } catch {
194
+ throw new Error(`${name} is not a valid URL: "${value}"`);
195
+ }
196
+ }
197
+
198
+ // Validate format now so a typo surfaces at boot, not at first-seed time.
199
+ // Emptiness is NOT an error here: an already-seeded remote never needs it.
200
+ for (const email of this.seedAdminEmails) {
201
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
202
+ throw new Error(`SEED_ADMIN_EMAILS contains an invalid email: "${email}"`);
203
+ }
204
+ }
205
+
206
+ this.validateKbIdentity();
207
+ }
208
+
209
+ /** Prefix for external API keys (connection keys): `<tenant>_`. */
210
+ get externalApiKeyPrefix(): string {
211
+ return `${this.tenantId}_`;
212
+ }
213
+
214
+ /** Prefix for in-process internal HMAC tokens: `<tenant>-int_`. */
215
+ get internalTokenPrefix(): string {
216
+ return `${this.tenantId}-int_`;
217
+ }
218
+
219
+ /** Prefix for scoped single-use bulk-upload tokens: `<tenant>-up_`. */
220
+ get uploadTokenPrefix(): string {
221
+ return `${this.tenantId}-up_`;
222
+ }
223
+
224
+ /** Prefix for MCP OAuth access tokens: `<tenant>-mcp_`. */
225
+ get mcpOAuthTokenPrefix(): string {
226
+ return `${this.tenantId}-mcp_`;
227
+ }
228
+
229
+ private validateKbIdentity(): void {
230
+ // Validate the two KB-identity inputs up front: `kbRepoUrl` (the clone/push
231
+ // URL) must be a valid https URL, and `kbDirName` (the dir the clone lives
232
+ // under in each workspace) must be a single safe path segment. A bad value
233
+ // in either otherwise surfaces much later as a confusing clone/path failure.
234
+ let parsed: URL;
235
+ try {
236
+ parsed = new URL(this.kbRepoUrl);
237
+ } catch {
238
+ throw new Error(`KB_REPO_URL is not a valid URL: ${this.kbRepoUrl}`);
239
+ }
240
+ if (parsed.protocol !== 'https:') {
241
+ throw new Error(`KB_REPO_URL must use https://: ${this.kbRepoUrl}`);
242
+ }
243
+
244
+ // Joined with workspace paths via path.join — separators or ".." would let it
245
+ // escape the workspace dir.
246
+ if (
247
+ !this.kbDirName ||
248
+ this.kbDirName === '.' ||
249
+ this.kbDirName === '..' ||
250
+ this.kbDirName.includes('/') ||
251
+ this.kbDirName.includes('\\') ||
252
+ path.isAbsolute(this.kbDirName)
253
+ ) {
254
+ throw new Error(`KB_DIR_NAME must be a single path segment: ${this.kbDirName}`);
255
+ }
256
+ }
257
+ }
package/src/index.ts ADDED
@@ -0,0 +1,69 @@
1
+ /**
2
+ * @bevel-software/platform-core-backend — the open-source core of the Bevel platform:
3
+ * git-backed knowledge workspace, workflow (branches / change requests /
4
+ * locks / SSE), skills, tool manuals + registry + auth, secrets vault, access
5
+ * control, diff/backup ledger, code-mode and the remote MCP surface.
6
+ *
7
+ * Composition entry points:
8
+ * - `new CoreConfig()` — env-driven core configuration
9
+ * - `createCoreServices(config, ports)` — construct every core service
10
+ * - `createCoreServer(core, ext, opts)` — the Express app (fixed mount order)
11
+ *
12
+ * Importing this package ALSO applies the global Express `Request`
13
+ * augmentation (`req.userId` / `req.userEmail` / token payloads) — the
14
+ * middleware modules re-exported below carry the `declare global` blocks, so
15
+ * consumers get the augmented types without a side-effect import of their own.
16
+ *
17
+ * Finer-grained internals are available via the `./modules/*` subpath exports.
18
+ */
19
+
20
+ export { CoreConfig } from './core-config.js';
21
+ export { createCoreServices, type CoreServices } from './core/create-core-services.js';
22
+ export {
23
+ createCoreServer,
24
+ type ServerExtensions,
25
+ type ToolSurfaceCtx,
26
+ } from './core/create-core-server.js';
27
+ export { noopRecoveryAgent, type CorePorts } from './core/core-ports.js';
28
+
29
+ // Packaged assets (migrations/, kb-template/) + the migration runners.
30
+ export { coreMigrationsDir, defaultKbTemplateDir } from './assets.js';
31
+ export {
32
+ runCoreMigrations,
33
+ runEnterpriseMigrations,
34
+ } from './modules/database/migrate.js';
35
+ export { getDb, type Database } from './modules/database/connection.js';
36
+
37
+ // Build identity surfaced by GET /api/health.
38
+ export { GIT_SHA, resolveGitSha } from './version.js';
39
+
40
+ // Express `Request` augmentation carriers (userId/userEmail — auth.middleware;
41
+ // token payloads — tool-auth + external-api-key interface). Re-exported by
42
+ // VALUE/type so the `declare global` blocks land in this package's public
43
+ // declaration graph.
44
+ export { createAuthMiddleware, AUTH_COOKIE_NAME } from './modules/auth/auth.middleware.js';
45
+ export {
46
+ createToolAuthMiddleware,
47
+ createManualAuthMiddleware,
48
+ } from './modules/tool-auth/tool-auth.middleware.js';
49
+ export type {
50
+ IExternalApiKeyService,
51
+ ExternalApiKeySummary,
52
+ } from './modules/tool-auth/external-api-key.interface.js';
53
+
54
+ // Key port/seam types an overlay implements.
55
+ export type { ISessionSink } from './modules/workspace/session-sink.js';
56
+ export type {
57
+ ISystemNoticeSink,
58
+ RecoveryAgentRunner,
59
+ } from './modules/workflow/pending-commits.worker.js';
60
+ export type { ILlmUsageMeter } from './modules/tool-auth/llm-usage-meter.js';
61
+ export type { AuthProviderPlugin } from './modules/auth/auth.routes.js';
62
+ export type { IErasureParticipant } from './modules/auth/account-erasure.service.js';
63
+ export {
64
+ WorkflowHooks,
65
+ type CommitValidationHook,
66
+ type CommitValidationContext,
67
+ type PreWriteHook,
68
+ type PreWriteContext,
69
+ } from './modules/workflow/workflow-hooks.js';
@@ -0,0 +1,98 @@
1
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
2
+ import { execFile } from 'node:child_process';
3
+ import { promisify } from 'node:util';
4
+ import fs from 'node:fs/promises';
5
+ import path from 'node:path';
6
+ import os from 'node:os';
7
+
8
+ import type { WorkspaceService } from '../../workspace/workspace.service.js';
9
+ import { AccessControlService } from '../access-control.service.js';
10
+
11
+ const execFileAsync = promisify(execFile);
12
+ const PROCESS_MAP_DIR = 'knowledge-base';
13
+
14
+ /**
15
+ * `canWriteBatchAtRef` / the batched at-ref own-entries read — backed by ONE
16
+ * `git cat-file --batch` process whose length-prefixed output we parse by
17
+ * hand, so exercise it against a REAL git repo: found blobs, a path missing
18
+ * at the ref (the `<spec> missing` line), a path with spaces, and frontmatter
19
+ * deny resolution — all in one batch, order-aligned.
20
+ */
21
+ describe('AccessControlService — at-ref batch reads (git cat-file --batch)', () => {
22
+ let root: string;
23
+ let repo: string;
24
+ let svc: AccessControlService;
25
+ const workspaceId = 'ws-atref-1';
26
+ const admin = 'razvan@bevel.software';
27
+
28
+ async function git(...args: string[]): Promise<void> {
29
+ await execFileAsync('git', ['-C', repo, ...args]);
30
+ }
31
+
32
+ beforeAll(async () => {
33
+ root = await fs.mkdtemp(path.join(os.tmpdir(), 'bevel-atref-'));
34
+ const workspaceDir = path.join(root, workspaceId);
35
+ repo = path.join(workspaceDir, PROCESS_MAP_DIR);
36
+ await fs.mkdir(path.join(repo, 'Knowledge'), { recursive: true });
37
+
38
+ await fs.writeFile(path.join(repo, 'roles.yaml'), 'roles:\n Admin:\n - razvan@bevel.software\n');
39
+ await fs.writeFile(path.join(repo, 'access.md'), '---\nwrite:\n - Admin\n---\n');
40
+ await fs.writeFile(path.join(repo, 'Knowledge/plain.md'), '# plain\n');
41
+ await fs.writeFile(
42
+ path.join(repo, 'Knowledge/denied.md'),
43
+ '---\nwrite:\n - deny razvan <razvan@bevel.software>\n---\n# denied\n',
44
+ );
45
+ await fs.writeFile(path.join(repo, 'Knowledge/with space.md'), '# spaced\n');
46
+
47
+ await execFileAsync('git', ['init', '-b', 'main', repo]);
48
+ await git('config', 'user.email', 'test@example.com');
49
+ await git('config', 'user.name', 'Test');
50
+ await git('add', '-A');
51
+ await git('commit', '-m', 'seed');
52
+
53
+ const stub = {
54
+ getWorkspacePath: async () => workspaceDir,
55
+ // Fixture repo has no remote; at-ref model loading fetches best-effort.
56
+ ensureRemotesFetched: async () => undefined,
57
+ } as unknown as WorkspaceService;
58
+ svc = new AccessControlService(stub, PROCESS_MAP_DIR);
59
+ });
60
+
61
+ afterAll(async () => {
62
+ await fs.rm(root, { recursive: true, force: true });
63
+ });
64
+
65
+ it('resolves a mixed batch in one pass: grants, frontmatter deny, spaces, and a missing path', async () => {
66
+ const paths = [
67
+ 'Knowledge/plain.md', // dir-chain Admin grant → true
68
+ 'Knowledge/denied.md', // own frontmatter deny → false
69
+ 'Knowledge/with space.md', // found blob whose SPEC contains spaces → true
70
+ 'Knowledge/not-there.md', // missing at the ref (`<spec> missing` line) → dir-chain verdict
71
+ ];
72
+ const map = await svc.canWriteBatchAtRef(workspaceId, 'main', admin, paths);
73
+ expect(map).not.toBeNull();
74
+ expect(map!.get('Knowledge/plain.md')).toBe(true);
75
+ expect(map!.get('Knowledge/denied.md')).toBe(false);
76
+ expect(map!.get('Knowledge/with space.md')).toBe(true);
77
+ expect(map!.get('Knowledge/not-there.md')).toBe(true);
78
+ });
79
+
80
+ it('matches the single-path at-ref resolution exactly', async () => {
81
+ // The batch is a pure performance change — verdicts must be identical to
82
+ // the per-path `git show` route the single-path helper still uses.
83
+ expect(await svc.canWriteAtRef(workspaceId, 'main', admin, 'Knowledge/denied.md')).toBe(false);
84
+ expect(await svc.canWriteAtRef(workspaceId, 'main', admin, 'Knowledge/plain.md')).toBe(true);
85
+ });
86
+
87
+ it('eligibleWritersForPathsAtRef honours the same batched own-entries', async () => {
88
+ const map = await svc.eligibleWritersForPathsAtRef(workspaceId, 'main', [
89
+ 'Knowledge/plain.md',
90
+ 'Knowledge/denied.md',
91
+ ]);
92
+ expect(map).not.toBeNull();
93
+ expect(map!.get('Knowledge/plain.md')!.roles).toContain('Admin');
94
+ // The per-user deny strips razvan from the expanded email set.
95
+ expect(map!.get('Knowledge/denied.md')!.emails.has(admin)).toBe(false);
96
+ expect(map!.get('Knowledge/plain.md')!.emails.has(admin)).toBe(true);
97
+ });
98
+ });
@@ -0,0 +1,132 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import fs from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import os from 'node:os';
5
+
6
+ import type { WorkspaceService } from '../../workspace/workspace.service.js';
7
+ import { AccessControlService } from '../access-control.service.js';
8
+
9
+ const PROCESS_MAP_DIR = 'knowledge-base';
10
+
11
+ async function writeFile(repo: string, rel: string, contents: string): Promise<void> {
12
+ const abs = path.join(repo, rel);
13
+ await fs.mkdir(path.dirname(abs), { recursive: true });
14
+ await fs.writeFile(abs, contents);
15
+ }
16
+
17
+ function stubWorkspaceService(workspaceId: string, workspaceDir: string): WorkspaceService {
18
+ return {
19
+ getWorkspacePath: async (id: string) => {
20
+ if (id !== workspaceId) throw new Error(`unexpected workspace ${id}`);
21
+ return workspaceDir;
22
+ },
23
+ } as unknown as WorkspaceService;
24
+ }
25
+
26
+ const ROLES_YAML = `roles:
27
+ Admin:
28
+ - razvan@bevel.software
29
+ Product Manager:
30
+ - felix@example.com
31
+ `;
32
+
33
+ /**
34
+ * canReadBatch = the read check behind BOTH the content routes and the
35
+ * file-explorer tree. It must honour the FULL rule set — the folder
36
+ * `access.md` chain AND each node's own frontmatter — so a file the caller
37
+ * can't open never appears in the tree, and a frontmatter-only grant is
38
+ * discoverable. (This replaced the dir-chain-only `canReadBatchShallow`,
39
+ * whose frontmatter blindness let a frontmatter-denied file show in the
40
+ * sidebar and then 403 on open.)
41
+ */
42
+ describe('AccessControlService.canReadBatch — tree/content parity', () => {
43
+ let root: string;
44
+ const workspaceId = 'ws-read-batch-1';
45
+
46
+ beforeEach(async () => {
47
+ root = await fs.mkdtemp(path.join(os.tmpdir(), 'bevel-read-batch-'));
48
+ });
49
+ afterEach(async () => {
50
+ await fs.rm(root, { recursive: true, force: true });
51
+ });
52
+
53
+ async function seed() {
54
+ const workspaceDir = path.join(root, workspaceId);
55
+ const repo = path.join(workspaceDir, PROCESS_MAP_DIR);
56
+ await fs.mkdir(repo, { recursive: true });
57
+ await writeFile(repo, 'roles.yaml', ROLES_YAML);
58
+ await writeFile(repo, 'access.md', '---\nwrite:\n - Admin\n---\n');
59
+ // Folder-level read restriction (dir-chain rule). Product Manager = felix; ali has no role.
60
+ await writeFile(repo, 'Knowledge/Secret/access.md', '---\nread:\n - Product Manager\n---\n');
61
+ await writeFile(repo, 'Knowledge/Secret/Foo.md', '# secret\n');
62
+ // Public folder via the built-in everyone role.
63
+ await writeFile(repo, 'Knowledge/Open/access.md', '---\nread:\n - everyone\n---\n');
64
+ // Node restricted ONLY by its own frontmatter — the batch must see it.
65
+ await writeFile(
66
+ repo,
67
+ 'Knowledge/Open/SelfRestricted.md',
68
+ '---\nread:\n - deny everyone\n - Product Manager\n---\n# self\n',
69
+ );
70
+ // Public via folder access.md.
71
+ await writeFile(repo, 'Knowledge/Open/Normal.md', '# normal\n');
72
+ // Node granted ONLY by its own frontmatter — the batch must discover it.
73
+ await writeFile(
74
+ repo,
75
+ 'Knowledge/Closed/SelfGranted.md',
76
+ '---\nread:\n - Product Manager\n---\n# self\n',
77
+ );
78
+ const svc = new AccessControlService(stubWorkspaceService(workspaceId, workspaceDir), PROCESS_MAP_DIR);
79
+ return { svc, repo };
80
+ }
81
+
82
+ const ali = 'ali@bevel.software'; // not in any read: list, not admin
83
+ const felix = 'felix@example.com'; // listed
84
+
85
+ it('honours folder-level read rules (denies non-listed, allows listed)', async () => {
86
+ const { svc } = await seed();
87
+ const m = await svc.canReadBatch(workspaceId, ali, ['Knowledge/Secret/Foo.md']);
88
+ expect(m.get('Knowledge/Secret/Foo.md')).toBe(false);
89
+ const mf = await svc.canReadBatch(workspaceId, felix, ['Knowledge/Secret/Foo.md']);
90
+ expect(mf.get('Knowledge/Secret/Foo.md')).toBe(true);
91
+ });
92
+
93
+ it('honours a node-only frontmatter DENY (batch verdict matches the content route)', async () => {
94
+ const { svc } = await seed();
95
+ const p = 'Knowledge/Open/SelfRestricted.md';
96
+ // Full single-file canRead denies ali…
97
+ expect(await svc.canRead(workspaceId, ali, p)).toBe(false);
98
+ // …and the batch (tree) agrees, so the file never shows in the sidebar.
99
+ const batch = await svc.canReadBatch(workspaceId, ali, [p]);
100
+ expect(batch.get(p)).toBe(false);
101
+ // The frontmatter grant still lets felix through.
102
+ const felixBatch = await svc.canReadBatch(workspaceId, felix, [p]);
103
+ expect(felixBatch.get(p)).toBe(true);
104
+ });
105
+
106
+ it('discovers a node whose ONLY read grant is in node frontmatter', async () => {
107
+ const { svc } = await seed();
108
+ const p = 'Knowledge/Closed/SelfGranted.md';
109
+ expect(await svc.canRead(workspaceId, felix, p)).toBe(true);
110
+ const batch = await svc.canReadBatch(workspaceId, felix, [p]);
111
+ expect(batch.get(p)).toBe(true);
112
+ });
113
+
114
+ it('allows a public node via read: everyone', async () => {
115
+ const { svc } = await seed();
116
+ const m = await svc.canReadBatch(workspaceId, ali, ['Knowledge/Open/Normal.md']);
117
+ expect(m.get('Knowledge/Open/Normal.md')).toBe(true);
118
+ });
119
+
120
+ it('memoizes frontmatter reads per workspace and re-reads after invalidate()', async () => {
121
+ const { svc, repo } = await seed();
122
+ const p = 'Knowledge/Open/SelfRestricted.md';
123
+ // Warm the cache with the deny in place.
124
+ expect((await svc.canReadBatch(workspaceId, ali, [p])).get(p)).toBe(false);
125
+ // Remove the deny on disk. The memo may still serve the old verdict…
126
+ await writeFile(repo, p, '# self, unrestricted\n');
127
+ // …but after invalidate() (fired on every commit/pull/switch) the fresh
128
+ // frontmatter is read and the folder's `read: everyone` applies.
129
+ svc.invalidate(workspaceId);
130
+ expect((await svc.canReadBatch(workspaceId, ali, [p])).get(p)).toBe(true);
131
+ });
132
+ });