@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,217 @@
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
+ import { CreatorAccessService } from '../creator-access.js';
9
+
10
+ const KB = 'knowledge-base';
11
+ const WS = 'ws-creator';
12
+
13
+ const ALICE = { name: 'Alice', email: 'alice@example.com' };
14
+
15
+ const ROLES_YAML = `roles:
16
+ Admin:
17
+ - razvan@bevel.software
18
+ `;
19
+
20
+ async function mkTmpRoot(): Promise<string> {
21
+ return fs.mkdtemp(path.join(os.tmpdir(), 'bevel-creator-access-'));
22
+ }
23
+
24
+ async function write(repo: string, rel: string, contents: string): Promise<void> {
25
+ const abs = path.join(repo, rel);
26
+ await fs.mkdir(path.dirname(abs), { recursive: true });
27
+ await fs.writeFile(abs, contents);
28
+ }
29
+
30
+ function stubWorkspaceService(workspaceDir: string): WorkspaceService {
31
+ return {
32
+ getWorkspacePath: async (id: string) => {
33
+ if (id !== WS) throw new Error(`unexpected workspace ${id}`);
34
+ return workspaceDir;
35
+ },
36
+ readFile: async (_id: string, wsRel: string) =>
37
+ fs.readFile(path.join(workspaceDir, wsRel), 'utf-8'),
38
+ } as unknown as WorkspaceService;
39
+ }
40
+
41
+ describe('CreatorAccessService.planForCreate', () => {
42
+ let root: string;
43
+ let repo: string;
44
+ let svc: CreatorAccessService;
45
+
46
+ beforeEach(async () => {
47
+ root = await mkTmpRoot();
48
+ const workspaceDir = path.join(root, WS);
49
+ repo = path.join(workspaceDir, KB);
50
+ await fs.mkdir(path.join(repo, 'KnowledgeBase'), { recursive: true });
51
+ await write(repo, 'roles.yaml', ROLES_YAML);
52
+ const ws = stubWorkspaceService(workspaceDir);
53
+ svc = new CreatorAccessService(ws, new AccessControlService(ws, KB), KB);
54
+ });
55
+
56
+ afterEach(async () => {
57
+ await fs.rm(root, { recursive: true, force: true });
58
+ });
59
+
60
+ it('returns null when the creator can already read via the folder chain', async () => {
61
+ await write(repo, 'KnowledgeBase/access.md', '---\nread:\n - everyone\n---\n');
62
+ const plan = await svc.planForCreate(WS, ALICE, `${KB}/KnowledgeBase/note.md`, 'file');
63
+ expect(plan).toBeNull();
64
+ });
65
+
66
+ it('a write grant folds into read — creating where you can write needs no grant', async () => {
67
+ await write(repo, 'KnowledgeBase/access.md', '---\nwrite:\n - Alice <alice@example.com>\n---\n');
68
+ const plan = await svc.planForCreate(WS, ALICE, `${KB}/KnowledgeBase/note.md`, 'file');
69
+ expect(plan).toBeNull();
70
+ });
71
+
72
+ it('a loose .md in a pre-existing unreadable folder gets a frontmatter grant', async () => {
73
+ const plan = await svc.planForCreate(WS, ALICE, `${KB}/KnowledgeBase/note.md`, 'file');
74
+ expect(plan?.kind).toBe('frontmatter');
75
+ if (plan?.kind !== 'frontmatter') return;
76
+ const granted = plan.apply('# Hello\n');
77
+ expect(granted).toBe('---\nread: Alice <alice@example.com>\n---\n# Hello\n');
78
+ });
79
+
80
+ it('frontmatter grant splices into existing frontmatter without touching the body', async () => {
81
+ const plan = await svc.planForCreate(WS, ALICE, `${KB}/KnowledgeBase/node.md`, 'file');
82
+ expect(plan?.kind).toBe('frontmatter');
83
+ if (plan?.kind !== 'frontmatter') return;
84
+ const granted = plan.apply('---\nnodeType: Process\n---\nBody\n');
85
+ expect(granted).toContain('nodeType: Process');
86
+ expect(granted).toContain('read: Alice <alice@example.com>');
87
+ expect(granted).toContain('Body');
88
+ });
89
+
90
+ it('a new folder gets its own access.md seeded, naming the creator under read:', async () => {
91
+ const plan = await svc.planForCreate(WS, ALICE, `${KB}/KnowledgeBase/Projects`, 'dir');
92
+ expect(plan?.kind).toBe('seed-access-md');
93
+ if (plan?.kind !== 'seed-access-md') return;
94
+ expect(plan.wsRelPath).toBe(`${KB}/KnowledgeBase/Projects/access.md`);
95
+ expect(plan.apply('')).toBe('---\nread:\n - Alice <alice@example.com>\n---\n');
96
+ });
97
+
98
+ it('the seed MERGES into existing access.md text — a concurrent creator grant survives', async () => {
99
+ const plan = await svc.planForCreate(WS, ALICE, `${KB}/KnowledgeBase/Projects`, 'dir');
100
+ expect(plan?.kind).toBe('seed-access-md');
101
+ if (plan?.kind !== 'seed-access-md') return;
102
+ // Simulate the two-creator race: by write time, Bob's seed already landed.
103
+ const bobs = '---\nread:\n - Bob <bob@example.com>\n---\n';
104
+ const merged = plan.apply(bobs);
105
+ expect(merged).toContain('- Bob <bob@example.com>');
106
+ expect(merged).toContain('- Alice <alice@example.com>');
107
+ // Idempotent: applying again changes nothing.
108
+ expect(plan.apply(merged)).toBe(merged);
109
+ });
110
+
111
+ it('a nested create seeds at the TOPMOST new directory, not the leaf', async () => {
112
+ const plan = await svc.planForCreate(WS, ALICE, `${KB}/KnowledgeBase/A/B/c.md`, 'file');
113
+ expect(plan?.kind).toBe('seed-access-md');
114
+ if (plan?.kind !== 'seed-access-md') return;
115
+ expect(plan.wsRelPath).toBe(`${KB}/KnowledgeBase/A/access.md`);
116
+ });
117
+
118
+ it('never targets a pre-existing directory: only new dirs are seeded', async () => {
119
+ await fs.mkdir(path.join(repo, 'KnowledgeBase/Existing'), { recursive: true });
120
+ const plan = await svc.planForCreate(WS, ALICE, `${KB}/KnowledgeBase/Existing/new.md`, 'file');
121
+ // Existing dir → the grant must land in the file's own frontmatter, not
122
+ // Existing/access.md (that would leak read on all its siblings).
123
+ expect(plan?.kind).toBe('frontmatter');
124
+ });
125
+
126
+ it('returns null for paths that already exist (an edit, not a create)', async () => {
127
+ await write(repo, 'KnowledgeBase/existing.md', 'x');
128
+ const plan = await svc.planForCreate(WS, ALICE, `${KB}/KnowledgeBase/existing.md`, 'file');
129
+ expect(plan).toBeNull();
130
+ });
131
+
132
+ it('returns null for access.md, roles.yaml, .gitkeep, and non-KB paths', async () => {
133
+ expect(await svc.planForCreate(WS, ALICE, `${KB}/KnowledgeBase/access.md`, 'file')).toBeNull();
134
+ expect(await svc.planForCreate(WS, ALICE, `${KB}/roles.yaml`, 'file')).toBeNull();
135
+ expect(await svc.planForCreate(WS, ALICE, `${KB}/KnowledgeBase/.gitkeep`, 'file')).toBeNull();
136
+ expect(await svc.planForCreate(WS, ALICE, 'reserved-config.json', 'file')).toBeNull();
137
+ });
138
+
139
+ it('returns null (never throws) for a non-markdown loose file in an existing folder', async () => {
140
+ const plan = await svc.planForCreate(WS, ALICE, `${KB}/KnowledgeBase/pic.png`, 'file');
141
+ expect(plan).toBeNull();
142
+ });
143
+
144
+ it('returns null (never throws) when the access config is unusable', async () => {
145
+ await fs.rm(path.join(repo, 'roles.yaml'));
146
+ const plan = await svc.planForCreate(WS, ALICE, `${KB}/KnowledgeBase/note.md`, 'file');
147
+ expect(plan).toBeNull();
148
+ });
149
+
150
+ it('sanitises a display name that would break the Name <email> entry shape', async () => {
151
+ const evil = { name: 'Al<ce # ', email: 'alice@example.com' };
152
+ const plan = await svc.planForCreate(WS, evil, `${KB}/KnowledgeBase/Dir`, 'dir');
153
+ expect(plan?.kind).toBe('seed-access-md');
154
+ if (plan?.kind !== 'seed-access-md') return;
155
+ expect(plan.apply('')).toContain('- Al ce <alice@example.com>');
156
+ });
157
+
158
+ it('the seeded grant makes the new folder readable — including via the batched tree check', async () => {
159
+ const ws = stubWorkspaceService(path.join(root, WS));
160
+ const access = new AccessControlService(ws, KB);
161
+ const plan = await svc.planForCreate(WS, ALICE, `${KB}/KnowledgeBase/Mine`, 'dir');
162
+ expect(plan?.kind).toBe('seed-access-md');
163
+ if (plan?.kind !== 'seed-access-md') return;
164
+ await write(repo, 'KnowledgeBase/Mine/access.md', plan.apply(''));
165
+ expect(await access.canRead(WS, ALICE.email, 'KnowledgeBase/Mine')).toBe(true);
166
+ const batch = await access.canReadBatch(WS, ALICE.email, [
167
+ 'KnowledgeBase/Mine',
168
+ 'KnowledgeBase/Mine/anything.md',
169
+ ]);
170
+ expect(batch.get('KnowledgeBase/Mine')).toBe(true);
171
+ expect(batch.get('KnowledgeBase/Mine/anything.md')).toBe(true);
172
+ });
173
+
174
+ it('the frontmatter grant makes a loose file readable via the FULL check', async () => {
175
+ const ws = stubWorkspaceService(path.join(root, WS));
176
+ const access = new AccessControlService(ws, KB);
177
+ const plan = await svc.planForCreate(WS, ALICE, `${KB}/KnowledgeBase/loose.md`, 'file');
178
+ expect(plan?.kind).toBe('frontmatter');
179
+ if (plan?.kind !== 'frontmatter') return;
180
+ await write(repo, 'KnowledgeBase/loose.md', plan.apply('# Loose\n'));
181
+ expect(await access.canRead(WS, ALICE.email, 'KnowledgeBase/loose.md')).toBe(true);
182
+ });
183
+ });
184
+
185
+ describe('CreatorAccessService.grantInExtractedFile', () => {
186
+ let root: string;
187
+ let repo: string;
188
+ let svc: CreatorAccessService;
189
+
190
+ beforeEach(async () => {
191
+ root = await mkTmpRoot();
192
+ const workspaceDir = path.join(root, WS);
193
+ repo = path.join(workspaceDir, KB);
194
+ await fs.mkdir(path.join(repo, 'KnowledgeBase'), { recursive: true });
195
+ await write(repo, 'roles.yaml', ROLES_YAML);
196
+ const ws = stubWorkspaceService(workspaceDir);
197
+ svc = new CreatorAccessService(ws, new AccessControlService(ws, KB), KB);
198
+ });
199
+
200
+ afterEach(async () => {
201
+ await fs.rm(root, { recursive: true, force: true });
202
+ });
203
+
204
+ it('splices the creator grant into an on-disk .md the creator cannot read', async () => {
205
+ await write(repo, 'KnowledgeBase/extracted.md', '# From zip\n');
206
+ const text = await svc.grantInExtractedFile(WS, ALICE, `${KB}/KnowledgeBase/extracted.md`);
207
+ expect(text).toBe('---\nread: Alice <alice@example.com>\n---\n# From zip\n');
208
+ });
209
+
210
+ it('returns null when the file is already readable, non-markdown, or non-KB', async () => {
211
+ await write(repo, 'KnowledgeBase/access.md', '---\nread:\n - everyone\n---\n');
212
+ await write(repo, 'KnowledgeBase/extracted.md', '# From zip\n');
213
+ expect(await svc.grantInExtractedFile(WS, ALICE, `${KB}/KnowledgeBase/extracted.md`)).toBeNull();
214
+ expect(await svc.grantInExtractedFile(WS, ALICE, `${KB}/KnowledgeBase/pic.png`)).toBeNull();
215
+ expect(await svc.grantInExtractedFile(WS, ALICE, 'reserved.md')).toBeNull();
216
+ });
217
+ });
@@ -0,0 +1,204 @@
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 mkTmpRoot(): Promise<string> {
12
+ return fs.mkdtemp(path.join(os.tmpdir(), 'bevel-grantsrc-'));
13
+ }
14
+
15
+ async function writeFile(repo: string, rel: string, contents: string): Promise<void> {
16
+ const abs = path.join(repo, rel);
17
+ await fs.mkdir(path.dirname(abs), { recursive: true });
18
+ await fs.writeFile(abs, contents);
19
+ }
20
+
21
+ function stubWorkspaceService(workspaceId: string, workspaceDir: string): WorkspaceService {
22
+ return {
23
+ getWorkspacePath: async (id: string) => {
24
+ if (id !== workspaceId) throw new Error(`unexpected workspace ${id}`);
25
+ return workspaceDir;
26
+ },
27
+ } as unknown as WorkspaceService;
28
+ }
29
+
30
+ const ROLES_YAML = `roles:
31
+ Admin:
32
+ - razvan@bevel.software
33
+ Engineer:
34
+ - ali@bevel.software
35
+ `;
36
+
37
+ const FELIX = { kind: 'user' as const, email: 'felix@example.com' };
38
+ const ALI = { kind: 'user' as const, email: 'ali@bevel.software' };
39
+ const RAZVAN = { kind: 'user' as const, email: 'razvan@bevel.software' };
40
+
41
+ describe('AccessControlService.grantSources', () => {
42
+ let root: string;
43
+ let repo: string;
44
+ let svc: AccessControlService;
45
+ const workspaceId = 'ws-gs';
46
+
47
+ beforeEach(async () => {
48
+ root = await mkTmpRoot();
49
+ const workspaceDir = path.join(root, workspaceId);
50
+ repo = path.join(workspaceDir, PROCESS_MAP_DIR);
51
+ await fs.mkdir(repo, { recursive: true });
52
+ await writeFile(repo, 'roles.yaml', ROLES_YAML);
53
+ svc = new AccessControlService(stubWorkspaceService(workspaceId, workspaceDir), PROCESS_MAP_DIR);
54
+ });
55
+
56
+ afterEach(async () => {
57
+ await fs.rm(root, { recursive: true, force: true });
58
+ });
59
+
60
+ it('a direct folder grant resolves to [{ kind: direct }]', async () => {
61
+ await writeFile(repo, 'access.md', '---\nwrite:\n - Admin\n---\n');
62
+ await writeFile(repo, 'Knowledge/access.md', '---\nwrite:\n - Felix <felix@example.com>\n---\n');
63
+ const src = await svc.grantSources(workspaceId, 'folder', 'Knowledge', FELIX);
64
+ expect(src.write).toEqual([{ kind: 'direct' }]);
65
+ });
66
+
67
+ it('an inherited grant resolves to [{ kind: ancestor, path }] (repo-relative)', async () => {
68
+ await writeFile(repo, 'access.md', '---\nwrite:\n - Admin\n---\n');
69
+ await writeFile(repo, 'Knowledge/access.md', '---\nwrite:\n - Felix <felix@example.com>\n---\n');
70
+ // Resolve for a file UNDER Knowledge — the write grant is inherited from Knowledge/access.md.
71
+ const src = await svc.grantSources(workspaceId, 'file', 'Knowledge/Deal.md', FELIX);
72
+ expect(src.write).toEqual([{ kind: 'ancestor', path: 'Knowledge/access.md' }]);
73
+ // The path is repo-relative — no `knowledge-base/` workspace prefix.
74
+ const first = src.write![0] as { path: string };
75
+ expect(first.path.startsWith(`${PROCESS_MAP_DIR}/`)).toBe(false);
76
+ });
77
+
78
+ it('a closer direct grant shadows the ancestor but BOTH scopes are reported (winner first)', async () => {
79
+ // h3xxit's case: granted on the target AND on an ancestor. The winner is
80
+ // direct (closest), but the ancestor must ALSO appear so callers can tell
81
+ // "direct only" apart from "direct + also inherited".
82
+ await writeFile(repo, 'access.md', '---\nwrite:\n - Felix <felix@example.com>\n---\n');
83
+ await writeFile(repo, 'Knowledge/access.md', '---\nwrite:\n - Felix <felix@example.com>\n---\n');
84
+ const src = await svc.grantSources(workspaceId, 'folder', 'Knowledge', FELIX);
85
+ // Closest-first: Knowledge/access.md (direct) then the root access.md (ancestor).
86
+ expect(src.write).toEqual([{ kind: 'direct' }, { kind: 'ancestor', path: 'access.md' }]);
87
+ expect(src.write![0]).toEqual({ kind: 'direct' }); // the effective/winning source
88
+ });
89
+
90
+ it('direct-only is distinguishable from direct+ancestor (just [direct], no tail)', async () => {
91
+ // Same person, granted ONLY on the target (root grants Admin, not Felix).
92
+ await writeFile(repo, 'access.md', '---\nwrite:\n - Admin\n---\n');
93
+ await writeFile(repo, 'Knowledge/access.md', '---\nwrite:\n - Felix <felix@example.com>\n---\n');
94
+ const src = await svc.grantSources(workspaceId, 'folder', 'Knowledge', FELIX);
95
+ expect(src.write).toEqual([{ kind: 'direct' }]); // no ancestor tail — direct ONLY
96
+ });
97
+
98
+ it('reports per-verb sources: direct on one verb, ancestor on another', async () => {
99
+ await writeFile(repo, 'access.md', '---\nwrite:\n - Admin\n---\n');
100
+ await writeFile(repo, 'Knowledge/access.md', '---\nwrite:\n - Felix <felix@example.com>\n---\n');
101
+ // download granted directly on the file's own frontmatter; write inherited from Knowledge.
102
+ await writeFile(
103
+ repo,
104
+ 'Knowledge/Deal.md',
105
+ '---\nnodeType: process\ndownload:\n - Felix <felix@example.com>\n---\n# body\n',
106
+ );
107
+ const src = await svc.grantSources(workspaceId, 'file', 'Knowledge/Deal.md', FELIX);
108
+ expect(src.download).toEqual([{ kind: 'direct' }]);
109
+ expect(src.write).toEqual([{ kind: 'ancestor', path: 'Knowledge/access.md' }]);
110
+ });
111
+
112
+ it('a USER who holds a verb only via a group they belong to has NO source (the group row carries it)', async () => {
113
+ await writeFile(repo, 'access.md', '---\nwrite:\n - Engineer\n---\n');
114
+ // Ali is an Engineer (per roles.yaml) — his write flows through the GROUP, not
115
+ // a per-user file entry. He isn't named in any file, so there's nothing to
116
+ // remove for HIM here; the Engineering group is the removable principal.
117
+ const src = await svc.grantSources(workspaceId, 'folder', 'Knowledge', ALI);
118
+ expect(src.write).toBeUndefined();
119
+ expect(src).toEqual({}); // no verb resolves to a per-user file entry
120
+ });
121
+
122
+ it('the GROUP principal itself resolves to its own file scope (direct/ancestor)', async () => {
123
+ // The same Engineer grant, asked about as the ROLE principal, IS a removable
124
+ // file entry — the group is named directly on Knowledge/access.md.
125
+ await writeFile(repo, 'access.md', '---\nwrite:\n - Admin\n---\n');
126
+ await writeFile(repo, 'Knowledge/access.md', '---\nwrite:\n - Engineer\n---\n');
127
+ const src = await svc.grantSources(workspaceId, 'folder', 'Knowledge', {
128
+ kind: 'role',
129
+ role: 'Engineer',
130
+ });
131
+ expect(src.write).toEqual([{ kind: 'direct' }]);
132
+ });
133
+
134
+ it('a verb a user holds only via everyone has NO source (not a per-user file entry)', async () => {
135
+ await writeFile(repo, 'access.md', '---\nread:\n - everyone\nwrite:\n - Admin\n---\n');
136
+ const src = await svc.grantSources(workspaceId, 'file', 'Knowledge/Deal.md', FELIX);
137
+ expect(src.read).toBeUndefined(); // resolves via everyone, but not removable as Felix
138
+ expect(src.write).toBeUndefined(); // Felix is not an admin and has no write
139
+ expect(src).toEqual({});
140
+ });
141
+
142
+ it('an admin on an access.md target has NO source (rescue is not a removable file entry)', async () => {
143
+ // No write entry names Razvan on this access.md; he holds write on it ONLY
144
+ // via the admin rescue. That isn't a per-target file entry, so grantSources
145
+ // reports no source — there's nothing to remove for him here. (The share
146
+ // dialog never targets an access.md directly; this is the defensive path.)
147
+ await writeFile(repo, 'access.md', '---\nwrite:\n - Engineer\n---\n');
148
+ const src = await svc.grantSources(workspaceId, 'file', 'access.md', RAZVAN);
149
+ expect(src.write).toBeUndefined();
150
+ expect(src).toEqual({});
151
+ });
152
+
153
+ it("a folder-target admin whose access is via the Admin GROUP has NO per-user source", async () => {
154
+ // Razvan's effective write comes from the `Admin` group grant, not a per-user
155
+ // entry — so as a USER principal he has no removable source here (the Admin
156
+ // group row carries it, exactly like any other group).
157
+ await writeFile(repo, 'access.md', '---\nwrite:\n - Admin\n---\n');
158
+ const src = await svc.grantSources(workspaceId, 'folder', 'Knowledge', RAZVAN);
159
+ expect(src.write).toBeUndefined();
160
+ expect(src).toEqual({});
161
+ });
162
+
163
+ it("a user named DIRECTLY in a file keeps a source even if they're also in a group", async () => {
164
+ // Razvan is in the Admin group AND named inline on Knowledge — the inline
165
+ // entry is a removable file grant, so his source is direct (tier-1 email
166
+ // beats the group at the same scope).
167
+ await writeFile(repo, 'access.md', '---\nwrite:\n - Admin\n---\n');
168
+ await writeFile(
169
+ repo,
170
+ 'Knowledge/access.md',
171
+ '---\nwrite:\n - Razvan <razvan@bevel.software>\n---\n',
172
+ );
173
+ const src = await svc.grantSources(workspaceId, 'folder', 'Knowledge', RAZVAN);
174
+ expect(src.write).toEqual([{ kind: 'direct' }]);
175
+ });
176
+
177
+ it('a role principal is matched by its own scope entry, not a role indirection', async () => {
178
+ await writeFile(repo, 'access.md', '---\nwrite:\n - Admin\n---\n');
179
+ await writeFile(repo, 'Knowledge/access.md', '---\nwrite:\n - Engineer\n---\n');
180
+ // The Engineer GROUP itself is granted on Knowledge — for the role principal that's a direct grant.
181
+ const src = await svc.grantSources(workspaceId, 'folder', 'Knowledge', {
182
+ kind: 'role',
183
+ role: 'Engineer',
184
+ });
185
+ expect(src.write).toEqual([{ kind: 'direct' }]);
186
+ });
187
+
188
+ it('a principal with no effective access yields an empty map', async () => {
189
+ await writeFile(repo, 'access.md', '---\nwrite:\n - Admin\n---\n');
190
+ const src = await svc.grantSources(workspaceId, 'file', 'Knowledge/Deal.md', FELIX);
191
+ expect(src).toEqual({});
192
+ });
193
+
194
+ it('owner folds in the lower verbs, all sourced from the owner grant', async () => {
195
+ await writeFile(repo, 'access.md', '---\nwrite:\n - Admin\n---\n');
196
+ await writeFile(repo, 'Knowledge/access.md', '---\nowner:\n - Felix <felix@example.com>\n---\n');
197
+ const src = await svc.grantSources(workspaceId, 'folder', 'Knowledge', FELIX);
198
+ // owner is direct; the implied read/write/download also resolve to the same direct scope.
199
+ expect(src.owner).toEqual([{ kind: 'direct' }]);
200
+ expect(src.write).toEqual([{ kind: 'direct' }]);
201
+ expect(src.read).toEqual([{ kind: 'direct' }]);
202
+ expect(src.download).toEqual([{ kind: 'direct' }]);
203
+ });
204
+ });
@@ -0,0 +1,70 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { toKbRelative, resolveReadableMap, type ReadBatchFn } from '../kb-read-filter.js';
3
+
4
+ const KB = 'staging-repo';
5
+
6
+ describe('toKbRelative', () => {
7
+ it('strips the kbDir prefix to a repo-relative path', () => {
8
+ expect(toKbRelative('staging-repo/Product/Knowledge/x.md', KB)).toBe('Product/Knowledge/x.md');
9
+ });
10
+
11
+ it('tolerates a leading ./ or /', () => {
12
+ expect(toKbRelative('./staging-repo/Product/x.md', KB)).toBe('Product/x.md');
13
+ expect(toKbRelative('/staging-repo/Product/x.md', KB)).toBe('Product/x.md');
14
+ });
15
+
16
+ it('tolerates a trailing slash (directory path)', () => {
17
+ expect(toKbRelative('staging-repo/Product/Knowledge/', KB)).toBe('Product/Knowledge');
18
+ });
19
+
20
+ it('returns null for a path outside the KB dir (reserved/non-KB → ungated)', () => {
21
+ expect(toKbRelative('some-other-file.txt', KB)).toBeNull();
22
+ expect(toKbRelative('Uploads/x.png', KB)).toBeNull();
23
+ });
24
+
25
+ it('returns null for the KB dir itself (no node)', () => {
26
+ expect(toKbRelative('staging-repo', KB)).toBeNull();
27
+ expect(toKbRelative('staging-repo/', KB)).toBeNull();
28
+ });
29
+
30
+ it('does not match a sibling dir that merely starts with the kbDir name', () => {
31
+ expect(toKbRelative('staging-repo-backup/x.md', KB)).toBeNull();
32
+ });
33
+ });
34
+
35
+ describe('resolveReadableMap', () => {
36
+ it('always allows non-KB paths and never asks the batch fn about them', async () => {
37
+ const batch = vi.fn<ReadBatchFn>(async () => new Map());
38
+ const out = await resolveReadableMap(batch, 'ws', 'u@x', KB, ['reserved.txt', 'Uploads/a.png']);
39
+ expect(out.get('reserved.txt')).toBe(true);
40
+ expect(out.get('Uploads/a.png')).toBe(true);
41
+ expect(batch).not.toHaveBeenCalled();
42
+ });
43
+
44
+ it('maps wsPaths through one batched call and keys the result by wsPath', async () => {
45
+ const batch = vi.fn<ReadBatchFn>(async (_w, _e, rels) => new Map(rels.map((r) => [r, r.startsWith('Product')])));
46
+ const out = await resolveReadableMap(batch, 'ws', 'u@x', KB, [
47
+ 'staging-repo/Product/a.md',
48
+ 'staging-repo/Platform/b.md',
49
+ ]);
50
+ expect(out.get('staging-repo/Product/a.md')).toBe(true);
51
+ expect(out.get('staging-repo/Platform/b.md')).toBe(false);
52
+ expect(batch).toHaveBeenCalledTimes(1);
53
+ expect(batch.mock.calls[0]![2]).toEqual(['Product/a.md', 'Platform/b.md']);
54
+ });
55
+
56
+ it('dedupes repeated KB-relative paths into one batch entry', async () => {
57
+ const batch = vi.fn<ReadBatchFn>(async (_w, _e, rels) => new Map(rels.map((r) => [r, true])));
58
+ await resolveReadableMap(batch, 'ws', 'u@x', KB, [
59
+ 'staging-repo/Product/a.md',
60
+ 'staging-repo/Product/a.md',
61
+ ]);
62
+ expect(batch.mock.calls[0]![2]).toEqual(['Product/a.md']);
63
+ });
64
+
65
+ it('fails closed: a KB path missing from the verdict resolves to not-readable', async () => {
66
+ const batch = vi.fn<ReadBatchFn>(async () => new Map()); // verdict omits the path
67
+ const out = await resolveReadableMap(batch, 'ws', 'u@x', KB, ['staging-repo/Product/a.md']);
68
+ expect(out.get('staging-repo/Product/a.md')).toBe(false);
69
+ });
70
+ });