@bevel-software/platform-core-backend 0.25.2 → 0.27.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 (733) hide show
  1. package/agent-guide/access-control.md +251 -0
  2. package/agent-guide/conventions.md +35 -0
  3. package/agent-guide/directory-structure.md +145 -0
  4. package/agent-guide/finding-things.md +7 -0
  5. package/agent-guide/html-views.md +83 -0
  6. package/agent-guide/introduction.md +27 -0
  7. package/agent-guide/new-knowledge-base.md +24 -0
  8. package/agent-guide/skills.md +47 -0
  9. package/agent-guide/tool-manuals.md +227 -0
  10. package/agent-guide/where-a-new-file-goes.md +36 -0
  11. package/dist/assets.d.ts +26 -0
  12. package/dist/assets.d.ts.map +1 -1
  13. package/dist/assets.js +35 -2
  14. package/dist/assets.js.map +1 -1
  15. package/dist/core/catalog-revision.d.ts +19 -1
  16. package/dist/core/catalog-revision.d.ts.map +1 -1
  17. package/dist/core/catalog-revision.js +14 -3
  18. package/dist/core/catalog-revision.js.map +1 -1
  19. package/dist/core/core-ports.d.ts +11 -0
  20. package/dist/core/core-ports.d.ts.map +1 -1
  21. package/dist/core/core-ports.js.map +1 -1
  22. package/dist/core/create-core-server.d.ts +5 -0
  23. package/dist/core/create-core-server.d.ts.map +1 -1
  24. package/dist/core/create-core-server.js +65 -3
  25. package/dist/core/create-core-server.js.map +1 -1
  26. package/dist/core/create-core-services.d.ts +35 -0
  27. package/dist/core/create-core-services.d.ts.map +1 -1
  28. package/dist/core/create-core-services.js +114 -12
  29. package/dist/core/create-core-services.js.map +1 -1
  30. package/dist/core/lifecycle.d.ts +16 -1
  31. package/dist/core/lifecycle.d.ts.map +1 -1
  32. package/dist/core/lifecycle.js +18 -1
  33. package/dist/core/lifecycle.js.map +1 -1
  34. package/dist/core-config.d.ts +21 -0
  35. package/dist/core-config.d.ts.map +1 -1
  36. package/dist/core-config.js +22 -1
  37. package/dist/core-config.js.map +1 -1
  38. package/dist/index.d.ts +1 -1
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +2 -2
  41. package/dist/index.js.map +1 -1
  42. package/dist/modules/access/access-control.interface.d.ts +17 -0
  43. package/dist/modules/access/access-control.interface.d.ts.map +1 -1
  44. package/dist/modules/access/access-control.service.d.ts +2 -0
  45. package/dist/modules/access/access-control.service.d.ts.map +1 -1
  46. package/dist/modules/access/access-control.service.js +27 -0
  47. package/dist/modules/access/access-control.service.js.map +1 -1
  48. package/dist/modules/access/directory-sync-bot.js +1 -1
  49. package/dist/modules/access/directory-sync-bot.js.map +1 -1
  50. package/dist/modules/agent-guide/agent-guide.d.ts +145 -0
  51. package/dist/modules/agent-guide/agent-guide.d.ts.map +1 -0
  52. package/dist/modules/agent-guide/agent-guide.js +199 -0
  53. package/dist/modules/agent-guide/agent-guide.js.map +1 -0
  54. package/dist/modules/agent-guide/agent-guide.tools.d.ts +24 -0
  55. package/dist/modules/agent-guide/agent-guide.tools.d.ts.map +1 -0
  56. package/dist/modules/agent-guide/agent-guide.tools.js +100 -0
  57. package/dist/modules/agent-guide/agent-guide.tools.js.map +1 -0
  58. package/dist/modules/agent-guide/index.d.ts +4 -0
  59. package/dist/modules/agent-guide/index.d.ts.map +1 -0
  60. package/dist/modules/agent-guide/index.js +4 -0
  61. package/dist/modules/agent-guide/index.js.map +1 -0
  62. package/dist/modules/agent-instructions/agent-instructions.routes.d.ts +3 -2
  63. package/dist/modules/agent-instructions/agent-instructions.routes.d.ts.map +1 -1
  64. package/dist/modules/agent-instructions/agent-instructions.routes.js +3 -2
  65. package/dist/modules/agent-instructions/agent-instructions.routes.js.map +1 -1
  66. package/dist/modules/agent-instructions/compose.d.ts +14 -6
  67. package/dist/modules/agent-instructions/compose.d.ts.map +1 -1
  68. package/dist/modules/agent-instructions/compose.js +28 -8
  69. package/dist/modules/agent-instructions/compose.js.map +1 -1
  70. package/dist/modules/agent-instructions/index.d.ts +1 -1
  71. package/dist/modules/agent-instructions/index.d.ts.map +1 -1
  72. package/dist/modules/agent-instructions/index.js +1 -1
  73. package/dist/modules/agent-instructions/index.js.map +1 -1
  74. package/dist/modules/agent-instructions/shared-file-rules.d.ts +10 -50
  75. package/dist/modules/agent-instructions/shared-file-rules.d.ts.map +1 -1
  76. package/dist/modules/agent-instructions/shared-file-rules.js +51 -104
  77. package/dist/modules/agent-instructions/shared-file-rules.js.map +1 -1
  78. package/dist/modules/audit/agent-audit.service.d.ts +21 -2
  79. package/dist/modules/audit/agent-audit.service.d.ts.map +1 -1
  80. package/dist/modules/audit/agent-audit.service.js +43 -2
  81. package/dist/modules/audit/agent-audit.service.js.map +1 -1
  82. package/dist/modules/audit/agent-connection.routes.d.ts +34 -0
  83. package/dist/modules/audit/agent-connection.routes.d.ts.map +1 -0
  84. package/dist/modules/audit/agent-connection.routes.js +38 -0
  85. package/dist/modules/audit/agent-connection.routes.js.map +1 -0
  86. package/dist/modules/audit/audit.contract.d.ts +24 -0
  87. package/dist/modules/audit/audit.contract.d.ts.map +1 -1
  88. package/dist/modules/audit/audit.contract.js.map +1 -1
  89. package/dist/modules/audit/index.d.ts +1 -0
  90. package/dist/modules/audit/index.d.ts.map +1 -1
  91. package/dist/modules/audit/index.js +1 -0
  92. package/dist/modules/audit/index.js.map +1 -1
  93. package/dist/modules/auth/account.routes.d.ts.map +1 -1
  94. package/dist/modules/auth/account.routes.js +10 -3
  95. package/dist/modules/auth/account.routes.js.map +1 -1
  96. package/dist/modules/auth/auth.middleware.d.ts +7 -0
  97. package/dist/modules/auth/auth.middleware.d.ts.map +1 -1
  98. package/dist/modules/auth/auth.middleware.js +1 -1
  99. package/dist/modules/auth/auth.middleware.js.map +1 -1
  100. package/dist/modules/code-mode/code-mode.tool.d.ts.map +1 -1
  101. package/dist/modules/code-mode/code-mode.tool.js +11 -3
  102. package/dist/modules/code-mode/code-mode.tool.js.map +1 -1
  103. package/dist/modules/database/core-schema.d.ts +96 -0
  104. package/dist/modules/database/core-schema.d.ts.map +1 -1
  105. package/dist/modules/database/core-schema.js +32 -3
  106. package/dist/modules/database/core-schema.js.map +1 -1
  107. package/dist/modules/embed/account-link.service.d.ts +42 -0
  108. package/dist/modules/embed/account-link.service.d.ts.map +1 -0
  109. package/dist/modules/embed/account-link.service.js +50 -0
  110. package/dist/modules/embed/account-link.service.js.map +1 -0
  111. package/dist/modules/embed/embed-link.d.ts +58 -0
  112. package/dist/modules/embed/embed-link.d.ts.map +1 -0
  113. package/dist/modules/embed/embed-link.js +160 -0
  114. package/dist/modules/embed/embed-link.js.map +1 -0
  115. package/dist/modules/embed/embed.errors.d.ts +30 -0
  116. package/dist/modules/embed/embed.errors.d.ts.map +1 -0
  117. package/dist/modules/embed/embed.errors.js +42 -0
  118. package/dist/modules/embed/embed.errors.js.map +1 -0
  119. package/dist/modules/embed/embed.interface.d.ts +204 -0
  120. package/dist/modules/embed/embed.interface.d.ts.map +1 -0
  121. package/dist/modules/embed/embed.interface.js +2 -0
  122. package/dist/modules/embed/embed.interface.js.map +1 -0
  123. package/dist/modules/embed/embed.routes.d.ts +59 -0
  124. package/dist/modules/embed/embed.routes.d.ts.map +1 -0
  125. package/dist/modules/embed/embed.routes.js +343 -0
  126. package/dist/modules/embed/embed.routes.js.map +1 -0
  127. package/dist/modules/embed/embed.service.d.ts +169 -0
  128. package/dist/modules/embed/embed.service.d.ts.map +1 -0
  129. package/dist/modules/embed/embed.service.js +627 -0
  130. package/dist/modules/embed/embed.service.js.map +1 -0
  131. package/dist/modules/embed/embed.tools.d.ts +51 -0
  132. package/dist/modules/embed/embed.tools.d.ts.map +1 -0
  133. package/dist/modules/embed/embed.tools.js +170 -0
  134. package/dist/modules/embed/embed.tools.js.map +1 -0
  135. package/dist/modules/embed/mcp-app.d.ts +64 -0
  136. package/dist/modules/embed/mcp-app.d.ts.map +1 -0
  137. package/dist/modules/embed/mcp-app.js +147 -0
  138. package/dist/modules/embed/mcp-app.js.map +1 -0
  139. package/dist/modules/embed/mcp-app.routes.d.ts +21 -0
  140. package/dist/modules/embed/mcp-app.routes.d.ts.map +1 -0
  141. package/dist/modules/embed/mcp-app.routes.js +36 -0
  142. package/dist/modules/embed/mcp-app.routes.js.map +1 -0
  143. package/dist/modules/github-app/github-app.connection.d.ts +15 -0
  144. package/dist/modules/github-app/github-app.connection.d.ts.map +1 -1
  145. package/dist/modules/github-app/github-app.connection.js +34 -3
  146. package/dist/modules/github-app/github-app.connection.js.map +1 -1
  147. package/dist/modules/kb-fs/locking-filesystem.d.ts +65 -0
  148. package/dist/modules/kb-fs/locking-filesystem.d.ts.map +1 -1
  149. package/dist/modules/kb-fs/locking-filesystem.js +300 -0
  150. package/dist/modules/kb-fs/locking-filesystem.js.map +1 -1
  151. package/dist/modules/kb-sync/kb-sync.interface.d.ts +5 -0
  152. package/dist/modules/kb-sync/kb-sync.interface.d.ts.map +1 -1
  153. package/dist/modules/kb-sync/kb-sync.service.d.ts.map +1 -1
  154. package/dist/modules/kb-sync/kb-sync.service.js +6 -0
  155. package/dist/modules/kb-sync/kb-sync.service.js.map +1 -1
  156. package/dist/modules/mcp/mcp-auth.middleware.d.ts.map +1 -1
  157. package/dist/modules/mcp/mcp-auth.middleware.js +2 -1
  158. package/dist/modules/mcp/mcp-auth.middleware.js.map +1 -1
  159. package/dist/modules/mcp/mcp.service.d.ts +57 -3
  160. package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
  161. package/dist/modules/mcp/mcp.service.js +177 -24
  162. package/dist/modules/mcp/mcp.service.js.map +1 -1
  163. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts +24 -0
  164. package/dist/modules/mcp/oauth/bevel-oauth-provider.d.ts.map +1 -1
  165. package/dist/modules/mcp/oauth/bevel-oauth-provider.js +32 -4
  166. package/dist/modules/mcp/oauth/bevel-oauth-provider.js.map +1 -1
  167. package/dist/modules/mcp/tool-schema-guard.d.ts +105 -0
  168. package/dist/modules/mcp/tool-schema-guard.d.ts.map +1 -0
  169. package/dist/modules/mcp/tool-schema-guard.js +171 -0
  170. package/dist/modules/mcp/tool-schema-guard.js.map +1 -0
  171. package/dist/modules/onboarding/onboarding.contract.d.ts +80 -0
  172. package/dist/modules/onboarding/onboarding.contract.d.ts.map +1 -0
  173. package/dist/modules/onboarding/onboarding.contract.js +7 -0
  174. package/dist/modules/onboarding/onboarding.contract.js.map +1 -0
  175. package/dist/modules/onboarding/onboarding.routes.d.ts +18 -0
  176. package/dist/modules/onboarding/onboarding.routes.d.ts.map +1 -0
  177. package/dist/modules/onboarding/onboarding.routes.js +81 -0
  178. package/dist/modules/onboarding/onboarding.routes.js.map +1 -0
  179. package/dist/modules/onboarding/starter-pack.service.d.ts +213 -0
  180. package/dist/modules/onboarding/starter-pack.service.d.ts.map +1 -0
  181. package/dist/modules/onboarding/starter-pack.service.js +492 -0
  182. package/dist/modules/onboarding/starter-pack.service.js.map +1 -0
  183. package/dist/modules/onboarding/starter-packs.d.ts +78 -0
  184. package/dist/modules/onboarding/starter-packs.d.ts.map +1 -0
  185. package/dist/modules/onboarding/starter-packs.js +156 -0
  186. package/dist/modules/onboarding/starter-packs.js.map +1 -0
  187. package/dist/modules/plugins/index.d.ts +1 -1
  188. package/dist/modules/plugins/index.d.ts.map +1 -1
  189. package/dist/modules/plugins/index.js +1 -1
  190. package/dist/modules/plugins/index.js.map +1 -1
  191. package/dist/modules/plugins/plugin-provision.service.d.ts +19 -0
  192. package/dist/modules/plugins/plugin-provision.service.d.ts.map +1 -1
  193. package/dist/modules/plugins/plugin-provision.service.js +18 -1
  194. package/dist/modules/plugins/plugin-provision.service.js.map +1 -1
  195. package/dist/modules/plugins/plugins.routes.d.ts +0 -36
  196. package/dist/modules/plugins/plugins.routes.d.ts.map +1 -1
  197. package/dist/modules/plugins/plugins.routes.js +31 -0
  198. package/dist/modules/plugins/plugins.routes.js.map +1 -1
  199. package/dist/modules/plugins/plugins.tools.d.ts +36 -2
  200. package/dist/modules/plugins/plugins.tools.d.ts.map +1 -1
  201. package/dist/modules/plugins/plugins.tools.js +71 -14
  202. package/dist/modules/plugins/plugins.tools.js.map +1 -1
  203. package/dist/modules/settings/deployment-settings.service.d.ts +34 -7
  204. package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -1
  205. package/dist/modules/settings/deployment-settings.service.js +148 -54
  206. package/dist/modules/settings/deployment-settings.service.js.map +1 -1
  207. package/dist/modules/settings/repository-source.d.ts +1 -0
  208. package/dist/modules/settings/repository-source.d.ts.map +1 -1
  209. package/dist/modules/settings/repository-source.js +3 -3
  210. package/dist/modules/settings/repository-source.js.map +1 -1
  211. package/dist/modules/settings/setup.routes.d.ts.map +1 -1
  212. package/dist/modules/settings/setup.routes.js +3 -6
  213. package/dist/modules/settings/setup.routes.js.map +1 -1
  214. package/dist/modules/skills/skills.tools.d.ts.map +1 -1
  215. package/dist/modules/skills/skills.tools.js +103 -43
  216. package/dist/modules/skills/skills.tools.js.map +1 -1
  217. package/dist/modules/tool-auth/connection-key-rejection.d.ts +10 -1
  218. package/dist/modules/tool-auth/connection-key-rejection.d.ts.map +1 -1
  219. package/dist/modules/tool-auth/connection-key-rejection.js +11 -3
  220. package/dist/modules/tool-auth/connection-key-rejection.js.map +1 -1
  221. package/dist/modules/tool-auth/external-api-key.interface.d.ts +8 -0
  222. package/dist/modules/tool-auth/external-api-key.interface.d.ts.map +1 -1
  223. package/dist/modules/tool-auth/external-api-key.service.d.ts +24 -2
  224. package/dist/modules/tool-auth/external-api-key.service.d.ts.map +1 -1
  225. package/dist/modules/tool-auth/external-api-key.service.js +59 -2
  226. package/dist/modules/tool-auth/external-api-key.service.js.map +1 -1
  227. package/dist/modules/tool-auth/tool-auth.middleware.d.ts.map +1 -1
  228. package/dist/modules/tool-auth/tool-auth.middleware.js +9 -4
  229. package/dist/modules/tool-auth/tool-auth.middleware.js.map +1 -1
  230. package/dist/modules/tool-helpers/index.d.ts +28 -1
  231. package/dist/modules/tool-helpers/index.d.ts.map +1 -1
  232. package/dist/modules/tool-helpers/index.js +28 -1
  233. package/dist/modules/tool-helpers/index.js.map +1 -1
  234. package/dist/modules/tool-helpers/route-argument-check.d.ts +10 -0
  235. package/dist/modules/tool-helpers/route-argument-check.d.ts.map +1 -0
  236. package/dist/modules/tool-helpers/route-argument-check.js +132 -0
  237. package/dist/modules/tool-helpers/route-argument-check.js.map +1 -0
  238. package/dist/modules/tool-helpers/route-tool-schemas.d.ts +89 -0
  239. package/dist/modules/tool-helpers/route-tool-schemas.d.ts.map +1 -0
  240. package/dist/modules/tool-helpers/route-tool-schemas.js +113 -0
  241. package/dist/modules/tool-helpers/route-tool-schemas.js.map +1 -0
  242. package/dist/modules/tool-helpers/tool-def.d.ts +71 -0
  243. package/dist/modules/tool-helpers/tool-def.d.ts.map +1 -1
  244. package/dist/modules/tool-helpers/tool-def.js +70 -6
  245. package/dist/modules/tool-helpers/tool-def.js.map +1 -1
  246. package/dist/modules/tool-helpers/tool-handler.d.ts +46 -6
  247. package/dist/modules/tool-helpers/tool-handler.d.ts.map +1 -1
  248. package/dist/modules/tool-helpers/tool-handler.js +157 -8
  249. package/dist/modules/tool-helpers/tool-handler.js.map +1 -1
  250. package/dist/modules/tool-helpers/tool.contract.d.ts +9 -0
  251. package/dist/modules/tool-helpers/tool.contract.d.ts.map +1 -1
  252. package/dist/modules/tool-helpers/tool.contract.js.map +1 -1
  253. package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +23 -4
  254. package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -1
  255. package/dist/modules/tool-manuals/tool-manuals.contract.js.map +1 -1
  256. package/dist/modules/tool-manuals/tool-manuals.service.d.ts +4 -0
  257. package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
  258. package/dist/modules/tool-manuals/tool-manuals.service.js +14 -0
  259. package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
  260. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts +7 -0
  261. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
  262. package/dist/modules/tool-manuals/tool-manuals.tools.js +77 -38
  263. package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
  264. package/dist/modules/tool-registry/description-length.d.ts +20 -16
  265. package/dist/modules/tool-registry/description-length.d.ts.map +1 -1
  266. package/dist/modules/tool-registry/description-length.js +50 -30
  267. package/dist/modules/tool-registry/description-length.js.map +1 -1
  268. package/dist/modules/tool-registry/guide-first.d.ts +27 -0
  269. package/dist/modules/tool-registry/guide-first.d.ts.map +1 -0
  270. package/dist/modules/tool-registry/guide-first.js +40 -0
  271. package/dist/modules/tool-registry/guide-first.js.map +1 -0
  272. package/dist/modules/tool-registry/tool-registry.d.ts +6 -0
  273. package/dist/modules/tool-registry/tool-registry.d.ts.map +1 -1
  274. package/dist/modules/tool-registry/tool-registry.js +9 -2
  275. package/dist/modules/tool-registry/tool-registry.js.map +1 -1
  276. package/dist/modules/workflow/agent-tools/change-request-read-shape.d.ts +449 -0
  277. package/dist/modules/workflow/agent-tools/change-request-read-shape.d.ts.map +1 -0
  278. package/dist/modules/workflow/agent-tools/change-request-read-shape.js +481 -0
  279. package/dist/modules/workflow/agent-tools/change-request-read-shape.js.map +1 -0
  280. package/dist/modules/workflow/agent-tools/change-request-read.tools.d.ts +126 -0
  281. package/dist/modules/workflow/agent-tools/change-request-read.tools.d.ts.map +1 -0
  282. package/dist/modules/workflow/agent-tools/change-request-read.tools.js +611 -0
  283. package/dist/modules/workflow/agent-tools/change-request-read.tools.js.map +1 -0
  284. package/dist/modules/workflow/agent-tools/change-request-summary.d.ts +12 -1
  285. package/dist/modules/workflow/agent-tools/change-request-summary.d.ts.map +1 -1
  286. package/dist/modules/workflow/agent-tools/change-request-summary.js +5 -1
  287. package/dist/modules/workflow/agent-tools/change-request-summary.js.map +1 -1
  288. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts +8 -1
  289. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
  290. package/dist/modules/workflow/agent-tools/workflow.tools.js +133 -37
  291. package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
  292. package/dist/modules/workflow/file-lock.service.d.ts +29 -5
  293. package/dist/modules/workflow/file-lock.service.d.ts.map +1 -1
  294. package/dist/modules/workflow/file-lock.service.js +62 -5
  295. package/dist/modules/workflow/file-lock.service.js.map +1 -1
  296. package/dist/modules/workflow/git/git.service.d.ts +282 -14
  297. package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
  298. package/dist/modules/workflow/git/git.service.js +627 -126
  299. package/dist/modules/workflow/git/git.service.js.map +1 -1
  300. package/dist/modules/workflow/git/merge-commit.d.ts +73 -0
  301. package/dist/modules/workflow/git/merge-commit.d.ts.map +1 -0
  302. package/dist/modules/workflow/git/merge-commit.js +89 -0
  303. package/dist/modules/workflow/git/merge-commit.js.map +1 -0
  304. package/dist/modules/workflow/git/node-git-runner.d.ts +15 -0
  305. package/dist/modules/workflow/git/node-git-runner.d.ts.map +1 -1
  306. package/dist/modules/workflow/git/node-git-runner.js +78 -6
  307. package/dist/modules/workflow/git/node-git-runner.js.map +1 -1
  308. package/dist/modules/workflow/git/pull-request.service.d.ts +94 -1
  309. package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -1
  310. package/dist/modules/workflow/git/pull-request.service.js +332 -37
  311. package/dist/modules/workflow/git/pull-request.service.js.map +1 -1
  312. package/dist/modules/workflow/pending-commits.service.d.ts +15 -0
  313. package/dist/modules/workflow/pending-commits.service.d.ts.map +1 -1
  314. package/dist/modules/workflow/pending-commits.service.js +25 -1
  315. package/dist/modules/workflow/pending-commits.service.js.map +1 -1
  316. package/dist/modules/workflow/pending-commits.worker.d.ts +6 -1
  317. package/dist/modules/workflow/pending-commits.worker.d.ts.map +1 -1
  318. package/dist/modules/workflow/pending-commits.worker.js +23 -6
  319. package/dist/modules/workflow/pending-commits.worker.js.map +1 -1
  320. package/dist/modules/workflow/recovery-bot.js +1 -1
  321. package/dist/modules/workflow/recovery-bot.js.map +1 -1
  322. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts +35 -0
  323. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -1
  324. package/dist/modules/workflow/review-workflow/review-workflow.service.js +180 -13
  325. package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -1
  326. package/dist/modules/workflow/sanitize-error.d.ts +16 -0
  327. package/dist/modules/workflow/sanitize-error.d.ts.map +1 -1
  328. package/dist/modules/workflow/sanitize-error.js +45 -0
  329. package/dist/modules/workflow/sanitize-error.js.map +1 -1
  330. package/dist/modules/workflow/workflow.routes.d.ts +6 -2
  331. package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
  332. package/dist/modules/workflow/workflow.routes.js +7 -2
  333. package/dist/modules/workflow/workflow.routes.js.map +1 -1
  334. package/dist/modules/workflow/workflow.service.d.ts +187 -15
  335. package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
  336. package/dist/modules/workflow/workflow.service.js +808 -106
  337. package/dist/modules/workflow/workflow.service.js.map +1 -1
  338. package/dist/modules/workspace/agent-download.builder.d.ts +105 -0
  339. package/dist/modules/workspace/agent-download.builder.d.ts.map +1 -0
  340. package/dist/modules/workspace/agent-download.builder.js +238 -0
  341. package/dist/modules/workspace/agent-download.builder.js.map +1 -0
  342. package/dist/modules/workspace/agent-download.routes.d.ts +77 -0
  343. package/dist/modules/workspace/agent-download.routes.d.ts.map +1 -0
  344. package/dist/modules/workspace/agent-download.routes.js +156 -0
  345. package/dist/modules/workspace/agent-download.routes.js.map +1 -0
  346. package/dist/modules/workspace/agent-download.store.d.ts +225 -0
  347. package/dist/modules/workspace/agent-download.store.d.ts.map +1 -0
  348. package/dist/modules/workspace/agent-download.store.js +423 -0
  349. package/dist/modules/workspace/agent-download.store.js.map +1 -0
  350. package/dist/modules/workspace/agent-upload.store.d.ts +10 -1
  351. package/dist/modules/workspace/agent-upload.store.d.ts.map +1 -1
  352. package/dist/modules/workspace/agent-upload.store.js +16 -6
  353. package/dist/modules/workspace/agent-upload.store.js.map +1 -1
  354. package/dist/modules/workspace/file-readers/raw-mime.d.ts +6 -0
  355. package/dist/modules/workspace/file-readers/raw-mime.d.ts.map +1 -0
  356. package/dist/modules/workspace/file-readers/raw-mime.js +38 -0
  357. package/dist/modules/workspace/file-readers/raw-mime.js.map +1 -0
  358. package/dist/modules/workspace/file-readers/text-reader.d.ts +5 -5
  359. package/dist/modules/workspace/file-readers/text-reader.d.ts.map +1 -1
  360. package/dist/modules/workspace/file-readers/text-reader.js +5 -8
  361. package/dist/modules/workspace/file-readers/text-reader.js.map +1 -1
  362. package/dist/modules/workspace/first-run.d.ts +111 -0
  363. package/dist/modules/workspace/first-run.d.ts.map +1 -0
  364. package/dist/modules/workspace/first-run.js +181 -0
  365. package/dist/modules/workspace/first-run.js.map +1 -0
  366. package/dist/modules/workspace/move-links.d.ts +92 -0
  367. package/dist/modules/workspace/move-links.d.ts.map +1 -0
  368. package/dist/modules/workspace/move-links.js +173 -0
  369. package/dist/modules/workspace/move-links.js.map +1 -0
  370. package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -1
  371. package/dist/modules/workspace/startup/steps/seed-tree.js +24 -39
  372. package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -1
  373. package/dist/modules/workspace/startup/steps/template-files.step.d.ts +58 -52
  374. package/dist/modules/workspace/startup/steps/template-files.step.d.ts.map +1 -1
  375. package/dist/modules/workspace/startup/steps/template-files.step.js +209 -223
  376. package/dist/modules/workspace/startup/steps/template-files.step.js.map +1 -1
  377. package/dist/modules/workspace/startup/steps/template-source.d.ts +5 -3
  378. package/dist/modules/workspace/startup/steps/template-source.d.ts.map +1 -1
  379. package/dist/modules/workspace/startup/steps/template-source.js +5 -3
  380. package/dist/modules/workspace/startup/steps/template-source.js.map +1 -1
  381. package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
  382. package/dist/modules/workspace/workspace.routes.js +63 -22
  383. package/dist/modules/workspace/workspace.routes.js.map +1 -1
  384. package/dist/modules/workspace/workspace.service.d.ts +75 -2
  385. package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
  386. package/dist/modules/workspace/workspace.service.js +197 -24
  387. package/dist/modules/workspace/workspace.service.js.map +1 -1
  388. package/dist/modules/workspace/workspace.tools.d.ts +68 -1
  389. package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
  390. package/dist/modules/workspace/workspace.tools.js +642 -71
  391. package/dist/modules/workspace/workspace.tools.js.map +1 -1
  392. package/dist/modules/write-access/write-access.d.ts.map +1 -1
  393. package/dist/modules/write-access/write-access.js +9 -0
  394. package/dist/modules/write-access/write-access.js.map +1 -1
  395. package/dist/shared/domain-errors.d.ts +84 -1
  396. package/dist/shared/domain-errors.d.ts.map +1 -1
  397. package/dist/shared/domain-errors.js +100 -12
  398. package/dist/shared/domain-errors.js.map +1 -1
  399. package/dist/shared/git.contract.d.ts +10 -1
  400. package/dist/shared/git.contract.d.ts.map +1 -1
  401. package/dist/shared/git.contract.js.map +1 -1
  402. package/dist/shared/hidden-tools.d.ts +44 -0
  403. package/dist/shared/hidden-tools.d.ts.map +1 -0
  404. package/dist/shared/hidden-tools.js +13 -0
  405. package/dist/shared/hidden-tools.js.map +1 -0
  406. package/dist/shared/utf8-text.d.ts +15 -0
  407. package/dist/shared/utf8-text.d.ts.map +1 -0
  408. package/dist/shared/utf8-text.js +20 -0
  409. package/dist/shared/utf8-text.js.map +1 -0
  410. package/dist/tenancy/static-tenant-source.d.ts +2 -1
  411. package/dist/tenancy/static-tenant-source.d.ts.map +1 -1
  412. package/dist/tenancy/static-tenant-source.js +9 -2
  413. package/dist/tenancy/static-tenant-source.js.map +1 -1
  414. package/kb-template/.bevelignore +0 -5
  415. package/mcp-app/page.html +349 -0
  416. package/migrations/0017_atlassian_account_links.sql +37 -0
  417. package/migrations/meta/0017_snapshot.json +2396 -0
  418. package/migrations/meta/_journal.json +8 -1
  419. package/package.json +6 -3
  420. package/src/__tests__/kb-layout-config.test.ts +10 -100
  421. package/src/__tests__/packaged-assets-ship.test.ts +66 -0
  422. package/src/assets.ts +38 -2
  423. package/src/core/__tests__/catalog-revision.test.ts +40 -0
  424. package/src/core/__tests__/gated-boot.test.ts +1 -0
  425. package/src/core/__tests__/lifecycle.test.ts +14 -0
  426. package/src/core/catalog-revision.ts +15 -2
  427. package/src/core/core-ports.ts +11 -0
  428. package/src/core/create-core-server.ts +78 -3
  429. package/src/core/create-core-services.ts +168 -10
  430. package/src/core/lifecycle.ts +28 -2
  431. package/src/core-config.ts +24 -1
  432. package/src/index.ts +2 -2
  433. package/src/modules/access/__tests__/access-control.atref-batch.test.ts +58 -0
  434. package/src/modules/access/__tests__/access-control.platform-restore.test.ts +8 -7
  435. package/src/modules/access/__tests__/access-control.service.test.ts +19 -0
  436. package/src/modules/access/__tests__/access-personal-plugin.test.ts +1 -18
  437. package/src/modules/access/access-control.interface.ts +28 -0
  438. package/src/modules/access/access-control.service.ts +37 -0
  439. package/src/modules/access/directory-sync-bot.ts +1 -1
  440. package/src/modules/agent-guide/__tests__/agent-guide.test.ts +386 -0
  441. package/src/modules/agent-guide/__tests__/agent-guide.tools.test.ts +207 -0
  442. package/src/modules/agent-guide/agent-guide.tools.ts +122 -0
  443. package/src/modules/agent-guide/agent-guide.ts +300 -0
  444. package/src/modules/agent-guide/index.ts +22 -0
  445. package/src/modules/agent-instructions/__tests__/shared-file-rules.test.ts +39 -118
  446. package/src/modules/agent-instructions/agent-instructions.routes.ts +3 -2
  447. package/src/modules/agent-instructions/compose.ts +26 -8
  448. package/src/modules/agent-instructions/index.ts +0 -3
  449. package/src/modules/agent-instructions/shared-file-rules.ts +50 -112
  450. package/src/modules/audit/__tests__/agent-audit.service.test.ts +64 -4
  451. package/src/modules/audit/__tests__/agent-connection.routes.test.ts +102 -0
  452. package/src/modules/audit/agent-audit.service.ts +58 -3
  453. package/src/modules/audit/agent-connection.routes.ts +56 -0
  454. package/src/modules/audit/audit.contract.ts +26 -0
  455. package/src/modules/audit/index.ts +1 -0
  456. package/src/modules/auth/__tests__/account.routes.test.ts +5 -3
  457. package/src/modules/auth/account.routes.ts +10 -3
  458. package/src/modules/auth/auth.middleware.ts +1 -1
  459. package/src/modules/code-mode/__tests__/code-mode.tool.test.ts +18 -2
  460. package/src/modules/code-mode/code-mode.tool.ts +13 -2
  461. package/src/modules/database/core-schema.ts +33 -3
  462. package/src/modules/embed/__tests__/account-links.migration.test.ts +98 -0
  463. package/src/modules/embed/__tests__/embed-link.test.ts +122 -0
  464. package/src/modules/embed/__tests__/embed.routes.test.ts +362 -0
  465. package/src/modules/embed/__tests__/embed.service.lock.test.ts +193 -0
  466. package/src/modules/embed/__tests__/embed.service.test.ts +805 -0
  467. package/src/modules/embed/__tests__/embed.tools.test.ts +304 -0
  468. package/src/modules/embed/__tests__/mcp-app.test.ts +207 -0
  469. package/src/modules/embed/account-link.service.ts +76 -0
  470. package/src/modules/embed/embed-link.ts +180 -0
  471. package/src/modules/embed/embed.errors.ts +43 -0
  472. package/src/modules/embed/embed.interface.ts +203 -0
  473. package/src/modules/embed/embed.routes.ts +363 -0
  474. package/src/modules/embed/embed.service.ts +705 -0
  475. package/src/modules/embed/embed.tools.ts +206 -0
  476. package/src/modules/embed/mcp-app.routes.ts +41 -0
  477. package/src/modules/embed/mcp-app.ts +173 -0
  478. package/src/modules/github-app/__tests__/github-app.test.ts +76 -0
  479. package/src/modules/github-app/github-app.connection.ts +38 -4
  480. package/src/modules/kb-fs/__tests__/move-with-edits.test.ts +304 -0
  481. package/src/modules/kb-fs/locking-filesystem.ts +287 -0
  482. package/src/modules/kb-sync/__tests__/kb-sync.service.test.ts +35 -0
  483. package/src/modules/kb-sync/kb-sync.interface.ts +2 -0
  484. package/src/modules/kb-sync/kb-sync.service.ts +6 -0
  485. package/src/modules/mcp/__tests__/bevel-oauth-provider.test.ts +68 -11
  486. package/src/modules/mcp/__tests__/fake-downstream-mcp-server.ts +14 -3
  487. package/src/modules/mcp/__tests__/mcp-proxy-helpers.test.ts +37 -2
  488. package/src/modules/mcp/__tests__/mcp.app.e2e.test.ts +200 -0
  489. package/src/modules/mcp/__tests__/mcp.e2e.test.ts +252 -0
  490. package/src/modules/mcp/__tests__/mcp.service.test.ts +42 -24
  491. package/src/modules/mcp/__tests__/tool-call-interface.e2e.test.ts +499 -0
  492. package/src/modules/mcp/__tests__/tool-schema-guard.test.ts +266 -0
  493. package/src/modules/mcp/mcp-auth.middleware.ts +2 -1
  494. package/src/modules/mcp/mcp.service.ts +218 -31
  495. package/src/modules/mcp/oauth/bevel-oauth-provider.ts +42 -4
  496. package/src/modules/mcp/tool-schema-guard.ts +196 -0
  497. package/src/modules/onboarding/__tests__/onboarding.routes.test.ts +163 -0
  498. package/src/modules/onboarding/__tests__/starter-pack.service.test.ts +635 -0
  499. package/src/modules/onboarding/__tests__/starter-packs.test.ts +169 -0
  500. package/src/modules/onboarding/onboarding.contract.ts +85 -0
  501. package/src/modules/onboarding/onboarding.routes.ts +85 -0
  502. package/src/modules/onboarding/starter-pack.service.ts +580 -0
  503. package/src/modules/onboarding/starter-packs.ts +182 -0
  504. package/src/modules/plugins/__tests__/plugins.tools.test.ts +177 -4
  505. package/src/modules/plugins/index.ts +1 -0
  506. package/src/modules/plugins/plugin-provision.service.ts +22 -1
  507. package/src/modules/plugins/plugins.routes.ts +29 -0
  508. package/src/modules/plugins/plugins.tools.ts +75 -15
  509. package/src/modules/settings/__tests__/deployment-settings.service.test.ts +176 -56
  510. package/src/modules/settings/__tests__/repository-source.test.ts +9 -0
  511. package/src/modules/settings/deployment-settings.service.ts +144 -55
  512. package/src/modules/settings/repository-source.ts +4 -4
  513. package/src/modules/settings/setup.routes.ts +3 -6
  514. package/src/modules/skills/__tests__/skills.tools.description.test.ts +95 -0
  515. package/src/modules/skills/skills.tools.ts +112 -46
  516. package/src/modules/tool-auth/__tests__/connection-key-rejection.test.ts +32 -0
  517. package/src/modules/tool-auth/__tests__/external-api-key.service.test.ts +65 -0
  518. package/src/modules/tool-auth/connection-key-rejection.ts +13 -3
  519. package/src/modules/tool-auth/external-api-key.interface.ts +9 -0
  520. package/src/modules/tool-auth/external-api-key.service.ts +61 -4
  521. package/src/modules/tool-auth/tool-auth.middleware.ts +13 -4
  522. package/src/modules/tool-helpers/__tests__/branch-declaration.test.ts +502 -0
  523. package/src/modules/tool-helpers/__tests__/route-argument-check.test.ts +337 -0
  524. package/src/modules/tool-helpers/index.ts +34 -1
  525. package/src/modules/tool-helpers/route-argument-check.ts +149 -0
  526. package/src/modules/tool-helpers/route-tool-schemas.ts +171 -0
  527. package/src/modules/tool-helpers/tool-def.ts +132 -7
  528. package/src/modules/tool-helpers/tool-handler.ts +196 -8
  529. package/src/modules/tool-helpers/tool.contract.ts +9 -0
  530. package/src/modules/tool-manuals/__tests__/tool-manuals.detail.route.test.ts +57 -0
  531. package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +73 -4
  532. package/src/modules/tool-manuals/tool-manuals.contract.ts +24 -4
  533. package/src/modules/tool-manuals/tool-manuals.service.ts +17 -0
  534. package/src/modules/tool-manuals/tool-manuals.tools.ts +86 -38
  535. package/src/modules/tool-registry/__tests__/own-tool-schemas.test.ts +173 -0
  536. package/src/modules/tool-registry/__tests__/tool-description-length.test.ts +81 -66
  537. package/src/modules/tool-registry/description-length.ts +57 -32
  538. package/src/modules/tool-registry/guide-first.ts +41 -0
  539. package/src/modules/tool-registry/tool-registry.ts +9 -2
  540. package/src/modules/workflow/__tests__/apply-failure.test.ts +6 -1
  541. package/src/modules/workflow/__tests__/file-lock.service.deletion-gate.test.ts +104 -0
  542. package/src/modules/workflow/__tests__/pending-commits.repository-replaced.test.ts +66 -0
  543. package/src/modules/workflow/__tests__/pending-commits.worker.test.ts +31 -2
  544. package/src/modules/workflow/__tests__/preserve-roles-yaml.test.ts +110 -6
  545. package/src/modules/workflow/__tests__/sanitize-error.test.ts +89 -1
  546. package/src/modules/workflow/__tests__/workflow.routes.push-refused.test.ts +202 -0
  547. package/src/modules/workflow/__tests__/workflow.service.branch-in-use.test.ts +6 -6
  548. package/src/modules/workflow/__tests__/workflow.service.delete-branch.test.ts +1026 -0
  549. package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +468 -10
  550. package/src/modules/workflow/__tests__/workflow.service.folder-proposals.test.ts +4 -0
  551. package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +5 -4
  552. package/src/modules/workflow/__tests__/workflow.service.update-from-target.test.ts +54 -2
  553. package/src/modules/workflow/agent-tools/__tests__/change-request-read-shape.test.ts +705 -0
  554. package/src/modules/workflow/agent-tools/__tests__/change-request-read.tools.test.ts +1554 -0
  555. package/src/modules/workflow/agent-tools/__tests__/workflow.tools.test.ts +150 -4
  556. package/src/modules/workflow/agent-tools/change-request-read-shape.ts +712 -0
  557. package/src/modules/workflow/agent-tools/change-request-read.tools.ts +759 -0
  558. package/src/modules/workflow/agent-tools/change-request-summary.ts +5 -1
  559. package/src/modules/workflow/agent-tools/workflow.tools.ts +137 -35
  560. package/src/modules/workflow/file-lock.service.ts +67 -5
  561. package/src/modules/workflow/git/__tests__/git.service.appliedChange.test.ts +285 -0
  562. package/src/modules/workflow/git/__tests__/git.service.changedFilesForPr.test.ts +124 -0
  563. package/src/modules/workflow/git/__tests__/git.service.deleteBranch.test.ts +164 -0
  564. package/src/modules/workflow/git/__tests__/git.service.mergeChangeRequest.test.ts +334 -0
  565. package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +48 -1
  566. package/src/modules/workflow/git/__tests__/node-git-runner.test.ts +231 -2
  567. package/src/modules/workflow/git/__tests__/pull-request.service.list-fetch.test.ts +72 -2
  568. package/src/modules/workflow/git/__tests__/pull-request.service.placeholder.test.ts +24 -2
  569. package/src/modules/workflow/git/__tests__/pull-request.service.test.ts +620 -1
  570. package/src/modules/workflow/git/git.service.ts +714 -133
  571. package/src/modules/workflow/git/merge-commit.ts +88 -0
  572. package/src/modules/workflow/git/node-git-runner.ts +82 -7
  573. package/src/modules/workflow/git/pull-request.service.ts +380 -54
  574. package/src/modules/workflow/pending-commits.service.ts +29 -1
  575. package/src/modules/workflow/pending-commits.worker.ts +24 -6
  576. package/src/modules/workflow/recovery-bot.ts +1 -1
  577. package/src/modules/workflow/review-workflow/__tests__/approval-states.test.ts +7 -1
  578. package/src/modules/workflow/review-workflow/__tests__/merge-records-own-commit.test.ts +407 -0
  579. package/src/modules/workflow/review-workflow/review-workflow.service.ts +191 -12
  580. package/src/modules/workflow/sanitize-error.ts +50 -0
  581. package/src/modules/workflow/workflow.routes.ts +7 -2
  582. package/src/modules/workflow/workflow.service.ts +886 -112
  583. package/src/modules/workspace/__tests__/agent-downloads.test.ts +823 -0
  584. package/src/modules/workspace/__tests__/escape-sequences.routes.test.ts +4 -3
  585. package/src/modules/workspace/__tests__/first-run.test.ts +234 -0
  586. package/src/modules/workspace/__tests__/git-internals.security.test.ts +5 -2
  587. package/src/modules/workspace/__tests__/md-links.test.ts +353 -0
  588. package/src/modules/workspace/__tests__/move-links.test.ts +261 -0
  589. package/src/modules/workspace/__tests__/rest-tool-arguments.test.ts +219 -0
  590. package/src/modules/workspace/__tests__/workspace-paths-inside-the-repo.test.ts +3 -0
  591. package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +102 -0
  592. package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +52 -5
  593. package/src/modules/workspace/__tests__/workspace.routes.folder-zip-access.test.ts +190 -0
  594. package/src/modules/workspace/__tests__/workspace.routes.move-platform-files.test.ts +21 -10
  595. package/src/modules/workspace/__tests__/workspace.service.forget-clone-races.test.ts +8 -4
  596. package/src/modules/workspace/__tests__/workspace.service.test.ts +50 -8
  597. package/src/modules/workspace/__tests__/workspace.tools.agents-file.test.ts +33 -55
  598. package/src/modules/workspace/__tests__/workspace.tools.branch-errors.test.ts +44 -1
  599. package/src/modules/workspace/__tests__/workspace.tools.test.ts +664 -34
  600. package/src/modules/workspace/agent-download.builder.ts +308 -0
  601. package/src/modules/workspace/agent-download.routes.ts +183 -0
  602. package/src/modules/workspace/agent-download.store.ts +533 -0
  603. package/src/modules/workspace/agent-upload.store.ts +23 -7
  604. package/src/modules/workspace/file-readers/raw-mime.ts +40 -0
  605. package/src/modules/workspace/file-readers/text-reader.ts +5 -8
  606. package/src/modules/workspace/first-run.ts +222 -0
  607. package/src/modules/workspace/move-links.ts +237 -0
  608. package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +191 -489
  609. package/src/modules/workspace/startup/steps/seed-tree.ts +23 -38
  610. package/src/modules/workspace/startup/steps/template-files.step.ts +217 -249
  611. package/src/modules/workspace/startup/steps/template-source.ts +5 -3
  612. package/src/modules/workspace/workspace.routes.ts +64 -22
  613. package/src/modules/workspace/workspace.service.ts +202 -25
  614. package/src/modules/workspace/workspace.tools.ts +707 -68
  615. package/src/modules/write-access/__tests__/write-access.test.ts +13 -0
  616. package/src/modules/write-access/write-access.ts +9 -0
  617. package/src/shared/domain-errors.ts +123 -11
  618. package/src/shared/git.contract.ts +8 -1
  619. package/src/shared/hidden-tools.ts +45 -0
  620. package/src/shared/utf8-text.ts +21 -0
  621. package/src/tenancy/__tests__/static-tenant-source.test.ts +1 -0
  622. package/src/tenancy/static-tenant-source.ts +10 -2
  623. package/starter-packs/README.md +103 -0
  624. package/starter-packs/engineering/KnowledgeBase/About us.md +9 -0
  625. package/starter-packs/engineering/KnowledgeBase/Architecture.md +9 -0
  626. package/starter-packs/engineering/KnowledgeBase/Glossary.md +9 -0
  627. package/starter-packs/engineering/KnowledgeBase/How we ship.md +9 -0
  628. package/starter-packs/engineering/Plugins/engineering-starter/LICENSE +21 -0
  629. package/starter-packs/engineering/Plugins/engineering-starter/SOURCE.md +20 -0
  630. package/starter-packs/engineering/Plugins/engineering-starter/access.md +19 -0
  631. package/starter-packs/engineering/Plugins/engineering-starter/plugin.json +10 -0
  632. package/starter-packs/engineering/Plugins/engineering-starter/skills/office-hours/SKILL.md +171 -0
  633. package/starter-packs/engineering/Plugins/engineering-starter/skills/office-hours/sections/phase-2a-startup-diagnostic.md +157 -0
  634. package/starter-packs/engineering/Plugins/engineering-starter/skills/office-hours/sections/phase-2b-builder-brainstorm.md +39 -0
  635. package/starter-packs/engineering/Plugins/engineering-starter/skills/plan-ceo-review/SKILL.md +144 -0
  636. package/starter-packs/engineering/Plugins/engineering-starter/skills/plan-eng-review/SKILL.md +144 -0
  637. package/starter-packs/engineering/Plugins/engineering-starter/skills/review/SKILL.md +80 -0
  638. package/starter-packs/engineering/Plugins/engineering-starter/skills/review/checklist.md +184 -0
  639. package/starter-packs/engineering/pack.yaml +11 -0
  640. package/starter-packs/general/KnowledgeBase/About us.md +9 -0
  641. package/starter-packs/general/KnowledgeBase/Glossary.md +9 -0
  642. package/starter-packs/general/KnowledgeBase/How we work.md +9 -0
  643. package/starter-packs/general/Plugins/general-starter/LICENSE +202 -0
  644. package/starter-packs/general/Plugins/general-starter/SOURCE.md +10 -0
  645. package/starter-packs/general/Plugins/general-starter/access.md +19 -0
  646. package/starter-packs/general/Plugins/general-starter/plugin.json +10 -0
  647. package/starter-packs/general/Plugins/general-starter/skills/memory-management/SKILL.md +332 -0
  648. package/starter-packs/general/Plugins/general-starter/skills/productivity-start/SKILL.md +163 -0
  649. package/starter-packs/general/Plugins/general-starter/skills/productivity-update/SKILL.md +167 -0
  650. package/starter-packs/general/Plugins/general-starter/skills/task-management/SKILL.md +83 -0
  651. package/starter-packs/general/pack.yaml +10 -0
  652. package/starter-packs/operations/KnowledgeBase/Glossary.md +9 -0
  653. package/starter-packs/operations/KnowledgeBase/How we work.md +9 -0
  654. package/starter-packs/operations/KnowledgeBase/Processes.md +9 -0
  655. package/starter-packs/operations/KnowledgeBase/Tools we use.md +9 -0
  656. package/starter-packs/operations/KnowledgeBase/Vendors.md +9 -0
  657. package/starter-packs/operations/Plugins/operations-starter/LICENSE +202 -0
  658. package/starter-packs/operations/Plugins/operations-starter/SOURCE.md +10 -0
  659. package/starter-packs/operations/Plugins/operations-starter/access.md +19 -0
  660. package/starter-packs/operations/Plugins/operations-starter/plugin.json +10 -0
  661. package/starter-packs/operations/Plugins/operations-starter/skills/capacity-plan/SKILL.md +111 -0
  662. package/starter-packs/operations/Plugins/operations-starter/skills/change-request/SKILL.md +119 -0
  663. package/starter-packs/operations/Plugins/operations-starter/skills/compliance-tracking/SKILL.md +44 -0
  664. package/starter-packs/operations/Plugins/operations-starter/skills/process-doc/SKILL.md +80 -0
  665. package/starter-packs/operations/Plugins/operations-starter/skills/process-optimization/SKILL.md +39 -0
  666. package/starter-packs/operations/Plugins/operations-starter/skills/risk-assessment/SKILL.md +40 -0
  667. package/starter-packs/operations/Plugins/operations-starter/skills/runbook/SKILL.md +85 -0
  668. package/starter-packs/operations/Plugins/operations-starter/skills/status-report/SKILL.md +75 -0
  669. package/starter-packs/operations/Plugins/operations-starter/skills/vendor-review/SKILL.md +102 -0
  670. package/starter-packs/operations/pack.yaml +12 -0
  671. package/starter-packs/sales/KnowledgeBase/About us.md +9 -0
  672. package/starter-packs/sales/KnowledgeBase/Customers.md +9 -0
  673. package/starter-packs/sales/KnowledgeBase/Glossary.md +9 -0
  674. package/starter-packs/sales/KnowledgeBase/How we sell.md +9 -0
  675. package/starter-packs/sales/KnowledgeBase/Objections.md +9 -0
  676. package/starter-packs/sales/KnowledgeBase/Pricing.md +9 -0
  677. package/starter-packs/sales/Plugins/sales-starter/LICENSE +202 -0
  678. package/starter-packs/sales/Plugins/sales-starter/SOURCE.md +10 -0
  679. package/starter-packs/sales/Plugins/sales-starter/access.md +19 -0
  680. package/starter-packs/sales/Plugins/sales-starter/plugin.json +10 -0
  681. package/starter-packs/sales/Plugins/sales-starter/skills/account-context/SKILL.md +94 -0
  682. package/starter-packs/sales/Plugins/sales-starter/skills/account-plan/SKILL.md +95 -0
  683. package/starter-packs/sales/Plugins/sales-starter/skills/account-research/SKILL.md +99 -0
  684. package/starter-packs/sales/Plugins/sales-starter/skills/account-tiering/SKILL.md +101 -0
  685. package/starter-packs/sales/Plugins/sales-starter/skills/call-prep/SKILL.md +111 -0
  686. package/starter-packs/sales/Plugins/sales-starter/skills/call-summary/SKILL.md +111 -0
  687. package/starter-packs/sales/Plugins/sales-starter/skills/close-plan/SKILL.md +106 -0
  688. package/starter-packs/sales/Plugins/sales-starter/skills/competitive-intelligence/SKILL.md +102 -0
  689. package/starter-packs/sales/Plugins/sales-starter/skills/create-an-asset/SKILL.md +105 -0
  690. package/starter-packs/sales/Plugins/sales-starter/skills/crm-hygiene-check/SKILL.md +103 -0
  691. package/starter-packs/sales/Plugins/sales-starter/skills/customer-health/SKILL.md +108 -0
  692. package/starter-packs/sales/Plugins/sales-starter/skills/customer-voice/SKILL.md +94 -0
  693. package/starter-packs/sales/Plugins/sales-starter/skills/daily-briefing/SKILL.md +61 -0
  694. package/starter-packs/sales/Plugins/sales-starter/skills/deal-advance-gap/SKILL.md +102 -0
  695. package/starter-packs/sales/Plugins/sales-starter/skills/deal-review/SKILL.md +105 -0
  696. package/starter-packs/sales/Plugins/sales-starter/skills/deal-signals/SKILL.md +96 -0
  697. package/starter-packs/sales/Plugins/sales-starter/skills/deal-slip-scenario/SKILL.md +104 -0
  698. package/starter-packs/sales/Plugins/sales-starter/skills/draft-outreach/SKILL.md +116 -0
  699. package/starter-packs/sales/Plugins/sales-starter/skills/end-of-day/SKILL.md +114 -0
  700. package/starter-packs/sales/Plugins/sales-starter/skills/expansion-whitespace/SKILL.md +97 -0
  701. package/starter-packs/sales/Plugins/sales-starter/skills/forecast/SKILL.md +100 -0
  702. package/starter-packs/sales/Plugins/sales-starter/skills/handle-objection/SKILL.md +93 -0
  703. package/starter-packs/sales/Plugins/sales-starter/skills/inbox-sweep/SKILL.md +114 -0
  704. package/starter-packs/sales/Plugins/sales-starter/skills/lead-triage/SKILL.md +106 -0
  705. package/starter-packs/sales/Plugins/sales-starter/skills/log-activity/SKILL.md +111 -0
  706. package/starter-packs/sales/Plugins/sales-starter/skills/pipeline-review/SKILL.md +97 -0
  707. package/starter-packs/sales/Plugins/sales-starter/skills/renewal-radar/SKILL.md +95 -0
  708. package/starter-packs/sales/Plugins/sales-starter/skills/rep-context/SKILL.md +90 -0
  709. package/starter-packs/sales/Plugins/sales-starter/skills/route-lead/SKILL.md +111 -0
  710. package/starter-packs/sales/Plugins/sales-starter/skills/sales-setup/SKILL.md +200 -0
  711. package/starter-packs/sales/Plugins/sales-starter/skills/schedule-meeting/SKILL.md +99 -0
  712. package/starter-packs/sales/Plugins/sales-starter/skills/stakeholder-map/SKILL.md +107 -0
  713. package/starter-packs/sales/Plugins/sales-starter/skills/team-pipeline/SKILL.md +105 -0
  714. package/starter-packs/sales/Plugins/sales-starter/skills/update-opportunity/SKILL.md +112 -0
  715. package/starter-packs/sales/Plugins/sales-starter/skills/weekly-wrap/SKILL.md +90 -0
  716. package/starter-packs/sales/Plugins/sales-starter/skills/win-loss-review/SKILL.md +88 -0
  717. package/starter-packs/sales/pack.yaml +13 -0
  718. package/starter-packs/support/KnowledgeBase/Escalations.md +9 -0
  719. package/starter-packs/support/KnowledgeBase/Glossary.md +9 -0
  720. package/starter-packs/support/KnowledgeBase/Known issues.md +9 -0
  721. package/starter-packs/support/KnowledgeBase/Products.md +9 -0
  722. package/starter-packs/support/KnowledgeBase/Tone of voice.md +9 -0
  723. package/starter-packs/support/Plugins/support-starter/LICENSE +202 -0
  724. package/starter-packs/support/Plugins/support-starter/SOURCE.md +10 -0
  725. package/starter-packs/support/Plugins/support-starter/access.md +19 -0
  726. package/starter-packs/support/Plugins/support-starter/plugin.json +10 -0
  727. package/starter-packs/support/Plugins/support-starter/skills/customer-escalation/SKILL.md +246 -0
  728. package/starter-packs/support/Plugins/support-starter/skills/customer-research/SKILL.md +250 -0
  729. package/starter-packs/support/Plugins/support-starter/skills/draft-response/SKILL.md +416 -0
  730. package/starter-packs/support/Plugins/support-starter/skills/kb-article/SKILL.md +350 -0
  731. package/starter-packs/support/Plugins/support-starter/skills/ticket-triage/SKILL.md +273 -0
  732. package/starter-packs/support/pack.yaml +12 -0
  733. package/kb-template/AGENTS.md +0 -730
@@ -0,0 +1,98 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { describe, expect, it } from 'vitest';
4
+ import { coreMigrationsDir } from '../../../assets.js';
5
+
6
+ const MIGRATION = '0017_atlassian_account_links.sql';
7
+
8
+ async function sql(): Promise<string> {
9
+ return fs.readFile(path.join(coreMigrationsDir(), MIGRATION), 'utf8');
10
+ }
11
+
12
+ /**
13
+ * The account-link table already EXISTS on an enterprise database: the Bevel
14
+ * Platform's own migration history created it, under this exact name and
15
+ * shape, while the embed lived there. Such a database must be ADOPTED as it
16
+ * stands, so every Atlassian link it holds keeps working and nobody re-links
17
+ * after the upgrade.
18
+ *
19
+ * That property lives in how this one file is WRITTEN, and the thing most
20
+ * likely to break it is regenerating it: `drizzle-kit generate` emits a bare
21
+ * `CREATE TABLE` and a bare `ADD CONSTRAINT`, either of which fails on a
22
+ * database that already has them — and a failed migration crash-loops the
23
+ * boot. So the guards are pinned here.
24
+ */
25
+ describe('the account-link migration adopts a database that already has the table', () => {
26
+ it('creates the table only if it is absent', async () => {
27
+ expect(await sql()).toMatch(/CREATE TABLE IF NOT EXISTS "atlassian_account_links"/i);
28
+ });
29
+
30
+ it('adds the foreign key behind an existence guard, under the name the enterprise used', async () => {
31
+ const text = await sql();
32
+ // The NAME is what the guard recognises. A different one would add a
33
+ // second, duplicate constraint to an upgraded database.
34
+ const name = 'atlassian_account_links_user_id_users_id_fk';
35
+ // The guard looks for THIS name, as a foreign key with the cascade, and
36
+ // the constraint it adds when the guard finds nothing carries the same
37
+ // one — tied together, so a guard naming anything else fails here.
38
+ const guard = /IF NOT EXISTS\s*\(\s*SELECT 1 FROM pg_constraint\s+WHERE([\s\S]*?)\)\s*THEN/i.exec(text);
39
+ expect(guard).not.toBeNull();
40
+ expect(guard![1]).toContain(`conname = '${name}'`);
41
+ expect(guard![1]).toMatch(/contype = 'f'/);
42
+ expect(guard![1]).toMatch(/confdeltype = 'c'/);
43
+ expect(text).toContain(`ADD CONSTRAINT "${name}"`);
44
+ // Links die with the user: an erasure request must never be blocked by a
45
+ // leftover embed link.
46
+ expect(text).toMatch(/ON DELETE cascade/i);
47
+ });
48
+
49
+ it('creates the by-user index only if it is absent', async () => {
50
+ expect(await sql()).toMatch(/CREATE INDEX IF NOT EXISTS "atlassian_account_links_by_user"/i);
51
+ });
52
+
53
+ /**
54
+ * Nothing here may remove or rewrite a row or a column somebody is using.
55
+ *
56
+ * Matched on STATEMENTS rather than on words: `ON DELETE cascade` and `ON
57
+ * UPDATE no action` are referential actions on the key being added, not
58
+ * destructive statements, and a word-level rule would forbid the very
59
+ * clause that makes an erasure request work.
60
+ */
61
+ it('is purely additive — it drops nothing and rewrites nothing', async () => {
62
+ const statements = (await sql())
63
+ .split('\n')
64
+ .filter((line) => !line.trimStart().startsWith('--'))
65
+ .join('\n')
66
+ .split(';');
67
+ // The VERB a statement opens with is what says whether it destroys
68
+ // anything. `ON DELETE cascade` and `ON UPDATE no action` sit mid-clause
69
+ // on the key being added and are the referential actions an erasure
70
+ // request depends on; `ALTER COLUMN` is a rewrite wherever it appears.
71
+ const destructive = statements.filter((statement) => {
72
+ const body = statement.trim();
73
+ // A statement opens a segment — or opens a block's body: inside a
74
+ // `DO $$ BEGIN … IF … THEN … END IF; END $$` the first statement shares
75
+ // its segment with the block's opening, so the verbs are looked for
76
+ // after BEGIN / THEN / ELSE / LOOP as well.
77
+ return (
78
+ /(^|\b(BEGIN|THEN|ELSE|LOOP)\s+)(DROP|DELETE|TRUNCATE|UPDATE)\b/i.test(body) ||
79
+ /ALTER\s+COLUMN/i.test(body)
80
+ );
81
+ });
82
+ expect(destructive).toEqual([]);
83
+ });
84
+
85
+ it('is registered in the journal the runner reads, exactly once', async () => {
86
+ const journal = JSON.parse(
87
+ await fs.readFile(path.join(coreMigrationsDir(), 'meta', '_journal.json'), 'utf8'),
88
+ ) as { entries: Array<{ tag: string; idx: number }> };
89
+ const mine = journal.entries.filter((e) => e.tag === MIGRATION.replace(/\.sql$/, ''));
90
+ expect(mine).toHaveLength(1);
91
+ // The runner applies entries in ARRAY order, so the array order is the
92
+ // ledger: every entry sits at the position its idx names, and this one
93
+ // after every migration numbered before it.
94
+ expect(journal.entries.map((e) => e.idx)).toEqual(journal.entries.map((_, i) => i));
95
+ expect(journal.entries.findIndex((e) => e.tag === mine[0].tag)).toBe(mine[0].idx);
96
+ expect(mine[0].tag.startsWith(String(mine[0].idx).padStart(4, '0'))).toBe(true);
97
+ });
98
+ });
@@ -0,0 +1,122 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import {
3
+ EmbedRefParseError,
4
+ isSafeRepoRelativeEmbedPath,
5
+ parseEmbedRef,
6
+ } from '../embed-link.js';
7
+
8
+ const KB = 'knowledge-base';
9
+
10
+ /**
11
+ * The mint's reference grammar — the boundary between Hexis and the Atlassian
12
+ * connector's own repository, which is why its shape may not change. Two
13
+ * consumers hand it very different strings: `open_page` a path from a model,
14
+ * the connector a `content:` marker a person pasted into a ticket.
15
+ */
16
+ describe('parseEmbedRef', () => {
17
+ it.each([
18
+ ['a bare path', 'Data/Thing.md', { repoRelative: 'Data/Thing.md' }],
19
+ ['a path under the kb folder', `${KB}/Data/Thing.md`, { repoRelative: 'Data/Thing.md' }],
20
+ ['a leading slash', '/Data/Thing.md', { repoRelative: 'Data/Thing.md' }],
21
+ ['a dot-slash', './Data/Thing.md', { repoRelative: 'Data/Thing.md' }],
22
+ [
23
+ 'a heading anchor',
24
+ 'Data/Thing.md#problem-statement',
25
+ { repoRelative: 'Data/Thing.md', slug: 'problem-statement' },
26
+ ],
27
+ [
28
+ 'an app URL',
29
+ `https://hexis.example/workspace/main/${KB}/Data/Thing.md#goal`,
30
+ { repoRelative: 'Data/Thing.md', slug: 'goal' },
31
+ ],
32
+ [
33
+ 'an embed URL (the branch segment is ignored)',
34
+ `https://hexis.example/embed/some-draft/${KB}/Data/Thing.md`,
35
+ { repoRelative: 'Data/Thing.md' },
36
+ ],
37
+ [
38
+ 'an app URL of a deployment served under a path prefix',
39
+ `https://hexis.example/hexis/workspace/main/${KB}/Data/Thing.md#goal`,
40
+ { repoRelative: 'Data/Thing.md', slug: 'goal' },
41
+ ],
42
+ [
43
+ 'an app URL whose route name arrives percent-encoded',
44
+ `https://hexis.example/%77orkspace/main/${KB}/Data/Thing.md`,
45
+ { repoRelative: 'Data/Thing.md' },
46
+ ],
47
+ [
48
+ 'an app URL whose default branch carries a slash, encoded in its segment',
49
+ `https://hexis.example/workspace/team%2Fmain/${KB}/Data/Thing.md`,
50
+ { repoRelative: 'Data/Thing.md' },
51
+ ],
52
+ ['a content: marker in angle brackets', '<content: Data/Thing.md>', { repoRelative: 'Data/Thing.md' }],
53
+ ['a percent-encoded space', 'Data/Some%20Thing.md', { repoRelative: 'Data/Some Thing.md' }],
54
+ ])('reads %s', (_label, raw, expected) => {
55
+ expect(parseEmbedRef(raw, KB)).toEqual(expected);
56
+ });
57
+
58
+ /**
59
+ * EVERY file type the app renders, because the embed renders them all with
60
+ * the app's own renderer. The enterprise panel this grammar came from
61
+ * accepted `.md`, `.html` and `.htm` only — the three its own renderer could
62
+ * draw — and that list would now be a second, narrower answer to "what can
63
+ * be shown".
64
+ */
65
+ it.each(['Shots/diagram.png', 'Docs/Report.pdf', 'Docs/Spec.docx', 'Data/rows.csv', 'Notes/plain.txt'])(
66
+ 'reads a path of any type: %s',
67
+ (path) => {
68
+ expect(parseEmbedRef(path, KB)).toEqual({ repoRelative: path });
69
+ },
70
+ );
71
+
72
+ it('reads a bare node id as an id, not a path', () => {
73
+ expect(parseEmbedRef('hx-some-ticket', KB)).toEqual({ nodeId: 'hx-some-ticket' });
74
+ expect(parseEmbedRef('hx-some-ticket#notes', KB)).toEqual({
75
+ nodeId: 'hx-some-ticket',
76
+ slug: 'notes',
77
+ });
78
+ });
79
+
80
+ it('reads a single segment WITH an extension as a path, not an id', () => {
81
+ expect(parseEmbedRef('AGENTS.md', KB)).toEqual({ repoRelative: 'AGENTS.md' });
82
+ });
83
+
84
+ it.each([
85
+ ['empty', ''],
86
+ ['traversal', '../../etc/passwd'],
87
+ ['a traversal inside', 'Data/../../etc/passwd'],
88
+ ['a percent-encoded separator', 'Data%2f..%2fsecret.md'],
89
+ ['a percent-encoded dot', 'Data/%2e%2e/secret.md'],
90
+ ])('refuses %s', (_label, raw) => {
91
+ expect(() => parseEmbedRef(raw, KB)).toThrow(EmbedRefParseError);
92
+ });
93
+
94
+ /**
95
+ * A single segment that is not a legal id is a FILE NAME, not a bad id — a
96
+ * space is perfectly legal in one, and the knowledge base is full of them.
97
+ * Only the shape of the trailing segment decides which form a reference is
98
+ * (see `looksLikeNodeId`), and nothing about that is a refusal.
99
+ */
100
+ it('reads a single segment that is not a legal id as a file name', () => {
101
+ expect(parseEmbedRef('Not An Id', KB)).toEqual({ repoRelative: 'Not An Id' });
102
+ });
103
+
104
+ it('refuses a malformed percent-escape rather than throwing a URIError', () => {
105
+ expect(() => parseEmbedRef('Data/%zz.md', KB)).toThrow(EmbedRefParseError);
106
+ });
107
+ });
108
+
109
+ describe('isSafeRepoRelativeEmbedPath', () => {
110
+ it('refuses an absolute path, traversal and a control character', () => {
111
+ expect(isSafeRepoRelativeEmbedPath('/etc/passwd')).toBe(false);
112
+ expect(isSafeRepoRelativeEmbedPath('a/../b.md')).toBe(false);
113
+ expect(isSafeRepoRelativeEmbedPath('a\nb.md')).toBe(false);
114
+ expect(isSafeRepoRelativeEmbedPath('')).toBe(false);
115
+ });
116
+
117
+ it('accepts a path with no extension at all', () => {
118
+ // Not a node id — it has a separator — and the app renders extensionless
119
+ // text files, so nothing here may refuse it.
120
+ expect(isSafeRepoRelativeEmbedPath('Data/LICENSE')).toBe(true);
121
+ });
122
+ });
@@ -0,0 +1,362 @@
1
+ import type { Server } from 'node:http';
2
+ import type { AddressInfo } from 'node:net';
3
+ import express from 'express';
4
+ import cors from 'cors';
5
+ import { afterEach, describe, expect, it, vi } from 'vitest';
6
+ import { createEmbedLinkRoutes, createEmbedRoutes, TOKEN_REQUIRED } from '../embed.routes.js';
7
+ import {
8
+ EmbedAccessError,
9
+ EmbedLockedError,
10
+ EmbedNodeNotFoundError,
11
+ EmbedTokenError,
12
+ } from '../embed.errors.js';
13
+
14
+ const TOKEN = 'a-valid-token';
15
+
16
+ let server: Server | null = null;
17
+ afterEach(async () => {
18
+ if (server) await new Promise<void>((resolve) => server!.close(() => resolve()));
19
+ server = null;
20
+ });
21
+
22
+ function stubService(overrides: Record<string, unknown> = {}) {
23
+ return {
24
+ sharedSecretConfigured: vi.fn(() => true),
25
+ verifySharedSecret: vi.fn((s?: string) => s === 'shh'),
26
+ mintForUser: vi.fn(async () => ({ token: TOKEN, embedUrl: 'https://hexis.example/embed?token=' + TOKEN })),
27
+ mintToken: vi.fn(async () => ({ token: TOKEN, embedUrl: 'https://hexis.example/embed?token=' + TOKEN })),
28
+ loadFile: vi.fn(async (token: string) => {
29
+ if (token !== TOKEN) throw new EmbedTokenError();
30
+ return { nodeName: 'Thing', content: '# Thing', canWrite: true };
31
+ }),
32
+ readBytes: vi.fn(async () => ({ bytes: Buffer.from([1, 2, 3]), path: 'Data/x.png' })),
33
+ acquireLock: vi.fn(async () => ({ acquired: true })),
34
+ heartbeat: vi.fn(async () => undefined),
35
+ cancel: vi.fn(async () => undefined),
36
+ save: vi.fn(async () => undefined),
37
+ propose: vi.fn(async () => ({ branch: 'suggestions/a-1/knowledge', number: 7, url: '/change-requests/7' })),
38
+ linkAccount: vi.fn(async () => undefined),
39
+ listLinkedAccounts: vi.fn(async () => [{ atlassianAccountId: 'acc-1', createdAt: 0 }]),
40
+ unlinkAccount: vi.fn(async () => true),
41
+ ...overrides,
42
+ };
43
+ }
44
+
45
+ /**
46
+ * The app as the server mounts it: the embed routes ahead of the JWT
47
+ * middleware, the link routes behind it, and a static catch-all last — the
48
+ * same order `create-core-server` uses, because the order is what makes the
49
+ * framing headers land before `index.html` is served.
50
+ */
51
+ async function serve(
52
+ service: ReturnType<typeof stubService>,
53
+ opts: { session?: boolean; restrictFraming?: boolean; appWideCors?: boolean } = {},
54
+ ) {
55
+ const app = express();
56
+ // The server's own CORS, as `create-core-server` mounts it ahead of every
57
+ // route: any origin reflected, credentials allowed, preflights answered.
58
+ if (opts.appWideCors) app.use(cors({ origin: true, credentials: true }));
59
+ app.use(express.json());
60
+ // A deployment (or a later change to this app) that stamps a framing
61
+ // restriction on EVERY response, ahead of the embed routes — the case the
62
+ // embed page's own header removal exists for.
63
+ if (opts.restrictFraming) {
64
+ app.use((_req, res, next) => {
65
+ res.setHeader('X-Frame-Options', 'SAMEORIGIN');
66
+ res.setHeader('Content-Security-Policy', "frame-ancestors 'self'");
67
+ next();
68
+ });
69
+ }
70
+ app.use(createEmbedRoutes(service as never));
71
+ const authMiddleware: express.RequestHandler = (req, res, next) => {
72
+ if (!opts.session) {
73
+ res.status(401).json({ error: 'Unauthenticated' });
74
+ return;
75
+ }
76
+ req.userId = 'u-1';
77
+ next();
78
+ };
79
+ app.use('/api', authMiddleware, createEmbedLinkRoutes(service as never));
80
+ app.get('{*path}', (_req, res) => res.type('html').send('<!doctype html><title>SPA</title>'));
81
+
82
+ server = app.listen(0);
83
+ await new Promise<void>((r) => server!.once('listening', () => r()));
84
+ const base = `http://127.0.0.1:${(server!.address() as AddressInfo).port}`;
85
+ return {
86
+ base,
87
+ get: (path: string, headers: Record<string, string> = {}) => fetch(`${base}${path}`, { headers }),
88
+ post: (path: string, body: unknown, headers: Record<string, string> = {}) =>
89
+ fetch(`${base}${path}`, {
90
+ method: 'POST',
91
+ headers: { 'content-type': 'application/json', ...headers },
92
+ body: JSON.stringify(body),
93
+ }),
94
+ del: (path: string) => fetch(`${base}${path}`, { method: 'DELETE' }),
95
+ };
96
+ }
97
+
98
+ /**
99
+ * Every route that serves FILE CONTENT or changes a file. The framing rule
100
+ * makes the embed page reachable from any site, so the token is the whole of
101
+ * the security — a session fallback would let a hostile frame read and write
102
+ * as whoever happened to be signed in.
103
+ */
104
+ const DATA_ROUTES = [
105
+ ['GET', '/api/embed/load'],
106
+ ['GET', '/api/embed/raw'],
107
+ ['POST', '/api/embed/lock'],
108
+ ['POST', '/api/embed/heartbeat'],
109
+ ['POST', '/api/embed/cancel'],
110
+ ['POST', '/api/embed/save'],
111
+ ['POST', '/api/embed/propose'],
112
+ ] as const;
113
+
114
+ describe('the embed data routes take the token and nothing else', () => {
115
+ it.each(DATA_ROUTES)('%s %s refuses a request with a valid session and no token', async (method, path) => {
116
+ const client = await serve(stubService(), { session: true });
117
+ const res =
118
+ method === 'GET'
119
+ ? await client.get(path, { cookie: 'bevel_token=a-real-session' })
120
+ : await client.post(path, { content: 'x' }, { cookie: 'bevel_token=a-real-session' });
121
+ expect(res.status).toBe(401);
122
+ expect((await res.json()).error).toBe(TOKEN_REQUIRED);
123
+ });
124
+
125
+ it.each(DATA_ROUTES)('%s %s answers a request with a token and no session', async (method, path) => {
126
+ const client = await serve(stubService());
127
+ const res =
128
+ method === 'GET'
129
+ ? await client.get(`${path}?token=${TOKEN}`)
130
+ : await client.post(path, { token: TOKEN, content: 'x' });
131
+ expect(res.status).toBeLessThan(400);
132
+ });
133
+
134
+ it('refuses an expired or rejected token with 401, so the view can say it expired', async () => {
135
+ const client = await serve(stubService());
136
+ const res = await client.get('/api/embed/load?token=stale');
137
+ expect(res.status).toBe(401);
138
+ });
139
+ });
140
+
141
+ describe('framing', () => {
142
+ /**
143
+ * Any host may frame the embed page — that is what makes it work in every
144
+ * host's sandbox without an admin entry per host, and the token is what
145
+ * secures it. `X-Frame-Options` is REMOVED rather than merely unset, so a
146
+ * header added globally later cannot silently break every host's embed.
147
+ */
148
+ it('sends no framing restriction on the embed page, even under a global one', async () => {
149
+ const client = await serve(stubService(), { restrictFraming: true });
150
+ // The restriction is really there on every other page…
151
+ const other = await client.get('/workspace/main');
152
+ expect(other.headers.get('x-frame-options')).toBe('SAMEORIGIN');
153
+ // …and the embed page clears it.
154
+ const res = await client.get('/embed?token=' + TOKEN);
155
+ expect(res.status).toBe(200);
156
+ expect(res.headers.get('x-frame-options')).toBeNull();
157
+ expect(res.headers.get('content-security-policy')).toBeNull();
158
+ // And it still falls through to the SPA.
159
+ expect(await res.text()).toContain('<!doctype html>');
160
+ });
161
+
162
+ /**
163
+ * The account-link page acts under the SIGNED-IN SESSION, so a page that
164
+ * could frame it could link a foreign account to a victim.
165
+ */
166
+ it('refuses every framing ancestor on the account-link page', async () => {
167
+ const client = await serve(stubService(), { restrictFraming: true });
168
+ const res = await client.get('/embed/link?token=' + TOKEN);
169
+ expect(res.status).toBe(200);
170
+ expect(res.headers.get('content-security-policy')).toBe("frame-ancestors 'none'");
171
+ expect(res.headers.get('x-frame-options')).toBe('DENY');
172
+ });
173
+ });
174
+
175
+ describe('the connector mint', () => {
176
+ it('mints from the shared secret, an account id and a reference', async () => {
177
+ const service = stubService();
178
+ const client = await serve(service);
179
+ const res = await client.post(
180
+ '/api/embed/token',
181
+ { accountId: 'acc-1', email: 'a@x.io', reference: 'Data/Thing.md' },
182
+ { 'x-embed-secret': 'shh' },
183
+ );
184
+ expect(res.status).toBe(200);
185
+ expect(await res.json()).toMatchObject({ token: TOKEN });
186
+ expect(service.mintToken).toHaveBeenCalledWith({
187
+ accountId: 'acc-1',
188
+ email: 'a@x.io',
189
+ reference: 'Data/Thing.md',
190
+ });
191
+ });
192
+
193
+ it('refuses a wrong secret and a missing one', async () => {
194
+ const client = await serve(stubService());
195
+ expect((await client.post('/api/embed/token', { accountId: 'a', reference: 'b' }, { 'x-embed-secret': 'no' })).status).toBe(401);
196
+ expect((await client.post('/api/embed/token', { accountId: 'a', reference: 'b' })).status).toBe(401);
197
+ });
198
+
199
+ it('refuses an incomplete body', async () => {
200
+ const client = await serve(stubService());
201
+ const res = await client.post('/api/embed/token', { accountId: 'acc-1' }, { 'x-embed-secret': 'shh' });
202
+ expect(res.status).toBe(400);
203
+ });
204
+
205
+ /** A deployment with no connector pointed at it has no such route at all. */
206
+ it('is absent when no shared secret is configured', async () => {
207
+ const service = stubService({ sharedSecretConfigured: vi.fn(() => false) });
208
+ const client = await serve(service);
209
+ const res = await client.post('/api/embed/token', { accountId: 'a', reference: 'b' }, { 'x-embed-secret': 'shh' });
210
+ expect(res.status).toBe(404);
211
+ expect(service.verifySharedSecret).not.toHaveBeenCalled();
212
+ });
213
+ });
214
+
215
+ describe('the data routes', () => {
216
+ it('serves the page to render', async () => {
217
+ const client = await serve(stubService());
218
+ const res = await client.get(`/api/embed/load?token=${TOKEN}`);
219
+ expect(await res.json()).toMatchObject({ nodeName: 'Thing' });
220
+ });
221
+
222
+ it('serves bytes inline, never as a download, and never from a shared cache', async () => {
223
+ const client = await serve(stubService());
224
+ const res = await client.get(`/api/embed/raw?token=${TOKEN}&path=assets/x.png`);
225
+ expect(res.status).toBe(200);
226
+ expect(res.headers.get('content-disposition')).toBe('inline');
227
+ expect(res.headers.get('cache-control')).toContain('no-store');
228
+ expect(res.headers.get('x-content-type-options')).toBe('nosniff');
229
+ expect([...new Uint8Array(await res.arrayBuffer())]).toEqual([1, 2, 3]);
230
+ });
231
+
232
+ it('saves, and proposes, through the service', async () => {
233
+ const service = stubService();
234
+ const client = await serve(service);
235
+ expect((await client.post('/api/embed/save', { token: TOKEN, content: 'new' })).status).toBe(204);
236
+ expect(service.save).toHaveBeenCalledWith(TOKEN, 'new');
237
+ const proposed = await client.post('/api/embed/propose', { token: TOKEN, content: 'draft' });
238
+ expect(await proposed.json()).toMatchObject({ number: 7 });
239
+ });
240
+
241
+ it('says who holds the lock when a save is refused for it', async () => {
242
+ const service = stubService({
243
+ save: vi.fn(async () => {
244
+ throw new EmbedLockedError('Bob');
245
+ }),
246
+ });
247
+ const client = await serve(service);
248
+ const res = await client.post('/api/embed/save', { token: TOKEN, content: 'x' });
249
+ expect(res.status).toBe(409);
250
+ expect((await res.json()).error).toContain('Bob');
251
+ });
252
+
253
+ /** Protected text and a token-bearing link: nothing may keep the answer. */
254
+ it('forbids caching the loaded page, as it does the raw bytes', async () => {
255
+ const client = await serve(stubService());
256
+ const load = await client.get(`/api/embed/load?token=${TOKEN}`);
257
+ expect(load.headers.get('cache-control')).toBe('no-store, private');
258
+ const refused = await client.get('/api/embed/load?token=wrong');
259
+ expect(refused.headers.get('cache-control')).toBe('no-store, private');
260
+ });
261
+
262
+ it('refuses a save with no content', async () => {
263
+ const client = await serve(stubService());
264
+ expect((await client.post('/api/embed/save', { token: TOKEN })).status).toBe(400);
265
+ });
266
+
267
+ it.each([
268
+ [new EmbedTokenError(), 401],
269
+ [new EmbedAccessError(), 403],
270
+ [new EmbedNodeNotFoundError('gone'), 404],
271
+ [new EmbedLockedError('Bob'), 409],
272
+ ])('maps %s to its status', async (error, status) => {
273
+ const service = stubService({
274
+ loadFile: vi.fn(async () => {
275
+ throw error;
276
+ }),
277
+ });
278
+ const client = await serve(service);
279
+ expect((await client.get(`/api/embed/load?token=${TOKEN}`)).status).toBe(status);
280
+ });
281
+
282
+ it('does not leak an unexpected failure message', async () => {
283
+ const service = stubService({
284
+ loadFile: vi.fn(async () => {
285
+ throw new Error('postgres://user:pw@host down');
286
+ }),
287
+ });
288
+ const client = await serve(service);
289
+ const res = await client.get(`/api/embed/load?token=${TOKEN}`);
290
+ expect(res.status).toBe(500);
291
+ expect((await res.json()).error).toBe('Something went wrong.');
292
+ });
293
+ });
294
+
295
+ describe('the account-link routes', () => {
296
+ it('link, list and unlink need a session', async () => {
297
+ const client = await serve(stubService(), { session: false });
298
+ expect((await client.post('/api/embed/link', { token: TOKEN })).status).toBe(401);
299
+ expect((await client.get('/api/embed/links')).status).toBe(401);
300
+ expect((await client.del('/api/embed/links/acc-1')).status).toBe(401);
301
+ });
302
+
303
+ it('links the token account to the signed-in user', async () => {
304
+ const service = stubService();
305
+ const client = await serve(service, { session: true });
306
+ expect((await client.post('/api/embed/link', { token: TOKEN })).status).toBe(204);
307
+ expect(service.linkAccount).toHaveBeenCalledWith(TOKEN, 'u-1');
308
+ });
309
+
310
+ it('answers 404 for a link that is not this user own, so it cannot probe others', async () => {
311
+ const service = stubService({ unlinkAccount: vi.fn(async () => false) });
312
+ const client = await serve(service, { session: true });
313
+ expect((await client.del('/api/embed/links/someone-elses')).status).toBe(404);
314
+ });
315
+ });
316
+
317
+ /**
318
+ * The MCP App view runs the embed inside a chat host's SANDBOX — another
319
+ * origin, and one no deployment can know in advance — and calls the token
320
+ * routes from there. The server's app-wide CORS is what lets it: mounted
321
+ * here as `create-core-server` mounts it, so what is pinned is the behaviour
322
+ * a sandbox actually meets, not a header these routes set themselves. Safe
323
+ * on the token routes for the reason the token-only rule exists: CORS guards
324
+ * a browser's ambient credentials, these routes take none, and the token in
325
+ * the request is the whole credential.
326
+ */
327
+ describe('a cross-origin caller reaches the token routes through the app-wide CORS', () => {
328
+ const SANDBOX = 'https://sandbox.example';
329
+ const FOREIGN = { origin: SANDBOX };
330
+
331
+ it.each(DATA_ROUTES)('%s %s answers the sandbox origin', async (method, path) => {
332
+ const client = await serve(stubService(), { appWideCors: true });
333
+ const res =
334
+ method === 'GET'
335
+ ? await client.get(`${path}?token=${TOKEN}`, FOREIGN)
336
+ : await client.post(path, { token: TOKEN, content: 'x' }, FOREIGN);
337
+ expect(res.status).toBeLessThan(400);
338
+ expect(res.headers.get('access-control-allow-origin')).toBe(SANDBOX);
339
+ });
340
+
341
+ it('answers the preflight a JSON POST from the sandbox triggers', async () => {
342
+ const client = await serve(stubService(), { appWideCors: true });
343
+ const res = await fetch(`${client.base}/api/embed/save`, {
344
+ method: 'OPTIONS',
345
+ headers: { ...FOREIGN, 'access-control-request-method': 'POST', 'access-control-request-headers': 'content-type' },
346
+ });
347
+ expect(res.status).toBe(204);
348
+ expect(res.headers.get('access-control-allow-origin')).toBe(SANDBOX);
349
+ expect(res.headers.get('access-control-allow-methods')).toContain('POST');
350
+ expect(res.headers.get('access-control-allow-headers')?.toLowerCase()).toContain('content-type');
351
+ });
352
+
353
+ it('still refuses a sandbox caller that brings no token', async () => {
354
+ // Being reachable from another origin changes nothing about who may
355
+ // read: the token is the credential, and a request without it is 401
356
+ // from the sandbox exactly as from a tab.
357
+ const client = await serve(stubService(), { appWideCors: true });
358
+ const res = await client.get('/api/embed/load', FOREIGN);
359
+ expect(res.status).toBe(401);
360
+ expect((await res.json()).error).toBe(TOKEN_REQUIRED);
361
+ });
362
+ });