@bevel-software/platform-core-backend 0.4.1 → 0.5.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 (304) hide show
  1. package/dist/core/core-ports.d.ts +15 -0
  2. package/dist/core/core-ports.d.ts.map +1 -1
  3. package/dist/core/core-ports.js.map +1 -1
  4. package/dist/core/create-core-server.d.ts.map +1 -1
  5. package/dist/core/create-core-server.js +40 -6
  6. package/dist/core/create-core-server.js.map +1 -1
  7. package/dist/core/create-core-services.d.ts +17 -1
  8. package/dist/core/create-core-services.d.ts.map +1 -1
  9. package/dist/core/create-core-services.js +153 -29
  10. package/dist/core/create-core-services.js.map +1 -1
  11. package/dist/core-config.d.ts +70 -21
  12. package/dist/core-config.d.ts.map +1 -1
  13. package/dist/core-config.js +134 -58
  14. package/dist/core-config.js.map +1 -1
  15. package/dist/modules/access/access-control.interface.d.ts +6 -0
  16. package/dist/modules/access/access-control.interface.d.ts.map +1 -1
  17. package/dist/modules/access/access-control.service.d.ts +74 -5
  18. package/dist/modules/access/access-control.service.d.ts.map +1 -1
  19. package/dist/modules/access/access-control.service.js +116 -15
  20. package/dist/modules/access/access-control.service.js.map +1 -1
  21. package/dist/modules/access/access-declarations.d.ts +93 -0
  22. package/dist/modules/access/access-declarations.d.ts.map +1 -0
  23. package/dist/modules/access/access-declarations.js +168 -0
  24. package/dist/modules/access/access-declarations.js.map +1 -0
  25. package/dist/modules/access/access-mutation.service.js +4 -4
  26. package/dist/modules/access/access-mutation.service.js.map +1 -1
  27. package/dist/modules/access/access-splice.d.ts +16 -1
  28. package/dist/modules/access/access-splice.d.ts.map +1 -1
  29. package/dist/modules/access/access-splice.js +40 -21
  30. package/dist/modules/access/access-splice.js.map +1 -1
  31. package/dist/modules/access/access.routes.d.ts.map +1 -1
  32. package/dist/modules/access/access.routes.js +51 -0
  33. package/dist/modules/access/access.routes.js.map +1 -1
  34. package/dist/modules/access/creator-access.d.ts +8 -0
  35. package/dist/modules/access/creator-access.d.ts.map +1 -1
  36. package/dist/modules/access/creator-access.js +21 -2
  37. package/dist/modules/access/creator-access.js.map +1 -1
  38. package/dist/modules/admin/admin-access.service.d.ts +1 -1
  39. package/dist/modules/admin/admin-access.service.d.ts.map +1 -1
  40. package/dist/modules/admin/admin-access.service.js +3 -2
  41. package/dist/modules/admin/admin-access.service.js.map +1 -1
  42. package/dist/modules/auth/auth.routes.d.ts.map +1 -1
  43. package/dist/modules/auth/auth.routes.js +50 -1
  44. package/dist/modules/auth/auth.routes.js.map +1 -1
  45. package/dist/modules/auth/auth.service.d.ts +39 -10
  46. package/dist/modules/auth/auth.service.d.ts.map +1 -1
  47. package/dist/modules/auth/auth.service.js +38 -16
  48. package/dist/modules/auth/auth.service.js.map +1 -1
  49. package/dist/modules/database/core-schema.d.ts +124 -0
  50. package/dist/modules/database/core-schema.d.ts.map +1 -1
  51. package/dist/modules/database/core-schema.js +45 -0
  52. package/dist/modules/database/core-schema.js.map +1 -1
  53. package/dist/modules/groups/group-provision.service.d.ts +130 -0
  54. package/dist/modules/groups/group-provision.service.d.ts.map +1 -0
  55. package/dist/modules/groups/group-provision.service.js +288 -0
  56. package/dist/modules/groups/group-provision.service.js.map +1 -0
  57. package/dist/modules/groups/groups.contract.d.ts +106 -0
  58. package/dist/modules/groups/groups.contract.d.ts.map +1 -0
  59. package/dist/modules/groups/groups.contract.js +36 -0
  60. package/dist/modules/groups/groups.contract.js.map +1 -0
  61. package/dist/modules/groups/groups.routes.d.ts +42 -0
  62. package/dist/modules/groups/groups.routes.d.ts.map +1 -0
  63. package/dist/modules/groups/groups.routes.js +379 -0
  64. package/dist/modules/groups/groups.routes.js.map +1 -0
  65. package/dist/modules/groups/groups.service.d.ts +60 -0
  66. package/dist/modules/groups/groups.service.d.ts.map +1 -0
  67. package/dist/modules/groups/groups.service.js +172 -0
  68. package/dist/modules/groups/groups.service.js.map +1 -0
  69. package/dist/modules/groups/index.d.ts +7 -0
  70. package/dist/modules/groups/index.d.ts.map +1 -0
  71. package/dist/modules/groups/index.js +6 -0
  72. package/dist/modules/groups/index.js.map +1 -0
  73. package/dist/modules/groups/join-proposals.d.ts +53 -0
  74. package/dist/modules/groups/join-proposals.d.ts.map +1 -0
  75. package/dist/modules/groups/join-proposals.js +67 -0
  76. package/dist/modules/groups/join-proposals.js.map +1 -0
  77. package/dist/modules/groups/join-requests.service.d.ts +81 -0
  78. package/dist/modules/groups/join-requests.service.d.ts.map +1 -0
  79. package/dist/modules/groups/join-requests.service.js +135 -0
  80. package/dist/modules/groups/join-requests.service.js.map +1 -0
  81. package/dist/modules/secrets-vault/secrets-vault.routes.d.ts +20 -0
  82. package/dist/modules/secrets-vault/secrets-vault.routes.d.ts.map +1 -1
  83. package/dist/modules/secrets-vault/secrets-vault.routes.js +59 -11
  84. package/dist/modules/secrets-vault/secrets-vault.routes.js.map +1 -1
  85. package/dist/modules/settings/deployment-settings.service.d.ts +129 -0
  86. package/dist/modules/settings/deployment-settings.service.d.ts.map +1 -0
  87. package/dist/modules/settings/deployment-settings.service.js +368 -0
  88. package/dist/modules/settings/deployment-settings.service.js.map +1 -0
  89. package/dist/modules/settings/setup.routes.d.ts +49 -0
  90. package/dist/modules/settings/setup.routes.d.ts.map +1 -0
  91. package/dist/modules/settings/setup.routes.js +292 -0
  92. package/dist/modules/settings/setup.routes.js.map +1 -0
  93. package/dist/modules/skills/index.d.ts +2 -1
  94. package/dist/modules/skills/index.d.ts.map +1 -1
  95. package/dist/modules/skills/index.js +1 -0
  96. package/dist/modules/skills/index.js.map +1 -1
  97. package/dist/modules/skills/pending-skills.service.d.ts +40 -0
  98. package/dist/modules/skills/pending-skills.service.d.ts.map +1 -0
  99. package/dist/modules/skills/pending-skills.service.js +147 -0
  100. package/dist/modules/skills/pending-skills.service.js.map +1 -0
  101. package/dist/modules/skills/skills.contract.d.ts +32 -3
  102. package/dist/modules/skills/skills.contract.d.ts.map +1 -1
  103. package/dist/modules/skills/skills.contract.js +1 -1
  104. package/dist/modules/skills/skills.routes.d.ts +3 -2
  105. package/dist/modules/skills/skills.routes.d.ts.map +1 -1
  106. package/dist/modules/skills/skills.routes.js +18 -1
  107. package/dist/modules/skills/skills.routes.js.map +1 -1
  108. package/dist/modules/skills/skills.service.d.ts +22 -0
  109. package/dist/modules/skills/skills.service.d.ts.map +1 -1
  110. package/dist/modules/skills/skills.service.js +24 -12
  111. package/dist/modules/skills/skills.service.js.map +1 -1
  112. package/dist/modules/tool-manuals/index.d.ts +1 -1
  113. package/dist/modules/tool-manuals/index.d.ts.map +1 -1
  114. package/dist/modules/tool-manuals/index.js.map +1 -1
  115. package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +47 -2
  116. package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -1
  117. package/dist/modules/tool-manuals/tool-manuals.contract.js +1 -1
  118. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts +4 -0
  119. package/dist/modules/tool-manuals/tool-manuals.routes.d.ts.map +1 -1
  120. package/dist/modules/tool-manuals/tool-manuals.routes.js +23 -0
  121. package/dist/modules/tool-manuals/tool-manuals.routes.js.map +1 -1
  122. package/dist/modules/tool-manuals/tool-manuals.service.d.ts +3 -1
  123. package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
  124. package/dist/modules/tool-manuals/tool-manuals.service.js +84 -17
  125. package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
  126. package/dist/modules/tool-manuals/tool-manuals.tools.d.ts.map +1 -1
  127. package/dist/modules/tool-manuals/tool-manuals.tools.js +6 -2
  128. package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
  129. package/dist/modules/workflow/agent-tools/workflow.tools.d.ts.map +1 -1
  130. package/dist/modules/workflow/agent-tools/workflow.tools.js +4 -2
  131. package/dist/modules/workflow/agent-tools/workflow.tools.js.map +1 -1
  132. package/dist/modules/workflow/event-bus.d.ts +11 -0
  133. package/dist/modules/workflow/event-bus.d.ts.map +1 -1
  134. package/dist/modules/workflow/event-bus.js +22 -0
  135. package/dist/modules/workflow/event-bus.js.map +1 -1
  136. package/dist/modules/workflow/file-lock.service.d.ts +9 -0
  137. package/dist/modules/workflow/file-lock.service.d.ts.map +1 -1
  138. package/dist/modules/workflow/file-lock.service.js +16 -0
  139. package/dist/modules/workflow/file-lock.service.js.map +1 -1
  140. package/dist/modules/workflow/git/branch-name.d.ts +1 -1
  141. package/dist/modules/workflow/git/branch-name.d.ts.map +1 -1
  142. package/dist/modules/workflow/git/branch-name.js +1 -1
  143. package/dist/modules/workflow/git/branch-name.js.map +1 -1
  144. package/dist/modules/workflow/git/git.service.d.ts +31 -2
  145. package/dist/modules/workflow/git/git.service.d.ts.map +1 -1
  146. package/dist/modules/workflow/git/git.service.js +144 -52
  147. package/dist/modules/workflow/git/git.service.js.map +1 -1
  148. package/dist/modules/workflow/git/pull-request.service.d.ts +12 -6
  149. package/dist/modules/workflow/git/pull-request.service.d.ts.map +1 -1
  150. package/dist/modules/workflow/git/pull-request.service.js +19 -9
  151. package/dist/modules/workflow/git/pull-request.service.js.map +1 -1
  152. package/dist/modules/workflow/review-workflow/review-workflow.service.d.ts.map +1 -1
  153. package/dist/modules/workflow/review-workflow/review-workflow.service.js +12 -3
  154. package/dist/modules/workflow/review-workflow/review-workflow.service.js.map +1 -1
  155. package/dist/modules/workflow/workflow.routes.d.ts.map +1 -1
  156. package/dist/modules/workflow/workflow.routes.js +95 -14
  157. package/dist/modules/workflow/workflow.routes.js.map +1 -1
  158. package/dist/modules/workflow/workflow.service.d.ts +92 -3
  159. package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
  160. package/dist/modules/workflow/workflow.service.js +381 -108
  161. package/dist/modules/workflow/workflow.service.js.map +1 -1
  162. package/dist/modules/workspace/bevel-ignore.d.ts +5 -0
  163. package/dist/modules/workspace/bevel-ignore.d.ts.map +1 -1
  164. package/dist/modules/workspace/bevel-ignore.js +5 -1
  165. package/dist/modules/workspace/bevel-ignore.js.map +1 -1
  166. package/dist/modules/workspace/kb-seed.interface.d.ts +1 -1
  167. package/dist/modules/workspace/kb-seed.service.d.ts +60 -5
  168. package/dist/modules/workspace/kb-seed.service.d.ts.map +1 -1
  169. package/dist/modules/workspace/kb-seed.service.js +228 -51
  170. package/dist/modules/workspace/kb-seed.service.js.map +1 -1
  171. package/dist/modules/workspace/workspace.routes.d.ts +2 -1
  172. package/dist/modules/workspace/workspace.routes.d.ts.map +1 -1
  173. package/dist/modules/workspace/workspace.routes.js +51 -18
  174. package/dist/modules/workspace/workspace.routes.js.map +1 -1
  175. package/dist/modules/workspace/workspace.service.d.ts +16 -4
  176. package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
  177. package/dist/modules/workspace/workspace.service.js +36 -9
  178. package/dist/modules/workspace/workspace.service.js.map +1 -1
  179. package/dist/modules/workspace/workspace.tools.d.ts.map +1 -1
  180. package/dist/modules/workspace/workspace.tools.js +8 -3
  181. package/dist/modules/workspace/workspace.tools.js.map +1 -1
  182. package/dist/shared/kb-layout.test.js +2 -2
  183. package/dist/test-setup.d.ts +2 -0
  184. package/dist/test-setup.d.ts.map +1 -0
  185. package/dist/test-setup.js +18 -0
  186. package/dist/test-setup.js.map +1 -0
  187. package/kb-template/.bevelignore +6 -2
  188. package/kb-template/AGENTS.md +272 -0
  189. package/kb-template/KnowledgeBase/How to get started.md +65 -0
  190. package/kb-template/access.md +36 -36
  191. package/migrations/0002_user_onboarding_done.sql +1 -0
  192. package/migrations/0003_deployment_settings.sql +9 -0
  193. package/migrations/meta/0001_snapshot.json +1486 -0
  194. package/migrations/meta/0002_snapshot.json +1493 -0
  195. package/migrations/meta/0003_snapshot.json +1552 -0
  196. package/migrations/meta/_journal.json +15 -1
  197. package/package.json +3 -3
  198. package/src/__tests__/branch-model.test.ts +79 -0
  199. package/src/__tests__/core-config.admin.test.ts +114 -0
  200. package/src/__tests__/database-url.test.ts +70 -0
  201. package/src/core/core-ports.ts +15 -0
  202. package/src/core/create-core-server.ts +55 -6
  203. package/src/core/create-core-services.ts +201 -36
  204. package/src/core-config.ts +139 -59
  205. package/src/modules/access/__tests__/access-declarations.test.ts +195 -0
  206. package/src/modules/access/__tests__/access-md-format.test.ts +191 -0
  207. package/src/modules/access/__tests__/access-splice.test.ts +21 -0
  208. package/src/modules/access/__tests__/access.routes.overrides.test.ts +214 -0
  209. package/src/modules/access/access-control.interface.ts +11 -0
  210. package/src/modules/access/access-control.service.ts +113 -15
  211. package/src/modules/access/access-declarations.ts +251 -0
  212. package/src/modules/access/access-mutation.service.ts +4 -4
  213. package/src/modules/access/access-splice.ts +64 -21
  214. package/src/modules/access/access.routes.ts +61 -0
  215. package/src/modules/access/creator-access.ts +22 -2
  216. package/src/modules/admin/admin-access.service.ts +4 -3
  217. package/src/modules/auth/__tests__/auth.service.test.ts +57 -0
  218. package/src/modules/auth/__tests__/onboarding-done.route.test.ts +147 -0
  219. package/src/modules/auth/auth.routes.ts +50 -1
  220. package/src/modules/auth/auth.service.ts +55 -17
  221. package/src/modules/database/core-schema.ts +46 -0
  222. package/src/modules/groups/__tests__/group-index.service.test.ts +225 -0
  223. package/src/modules/groups/__tests__/group-provision.service.test.ts +247 -0
  224. package/src/modules/groups/__tests__/groups.routes.test.ts +493 -0
  225. package/src/modules/groups/__tests__/join-proposals.test.ts +101 -0
  226. package/src/modules/groups/__tests__/join-requests.service.test.ts +175 -0
  227. package/src/modules/groups/group-provision.service.ts +328 -0
  228. package/src/modules/groups/groups.contract.ts +107 -0
  229. package/src/modules/groups/groups.routes.ts +433 -0
  230. package/src/modules/groups/groups.service.ts +193 -0
  231. package/src/modules/groups/index.ts +17 -0
  232. package/src/modules/groups/join-proposals.ts +114 -0
  233. package/src/modules/groups/join-requests.service.ts +185 -0
  234. package/src/modules/secrets-vault/__tests__/oauth-return-to.route.test.ts +283 -0
  235. package/src/modules/secrets-vault/secrets-vault.routes.ts +68 -12
  236. package/src/modules/settings/__tests__/deployment-settings.service.test.ts +256 -0
  237. package/src/modules/settings/__tests__/setup.routes.test.ts +201 -0
  238. package/src/modules/settings/deployment-settings.service.ts +419 -0
  239. package/src/modules/settings/setup.routes.ts +317 -0
  240. package/src/modules/skills/__tests__/pending-skills.service.test.ts +240 -0
  241. package/src/modules/skills/__tests__/skills.service.test.ts +13 -13
  242. package/src/modules/skills/index.ts +3 -0
  243. package/src/modules/skills/pending-skills.service.ts +168 -0
  244. package/src/modules/skills/skills.contract.ts +34 -3
  245. package/src/modules/skills/skills.routes.ts +23 -2
  246. package/src/modules/skills/skills.service.ts +24 -16
  247. package/src/modules/tool-manuals/__tests__/tool-manuals.detail.route.test.ts +262 -0
  248. package/src/modules/tool-manuals/__tests__/tool-manuals.mcp-oauth.test.ts +2 -2
  249. package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +61 -23
  250. package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +156 -156
  251. package/src/modules/tool-manuals/index.ts +2 -0
  252. package/src/modules/tool-manuals/tool-manuals.contract.ts +50 -2
  253. package/src/modules/tool-manuals/tool-manuals.routes.ts +21 -0
  254. package/src/modules/tool-manuals/tool-manuals.service.ts +86 -17
  255. package/src/modules/tool-manuals/tool-manuals.tools.ts +206 -202
  256. package/src/modules/workflow/__tests__/event-bus.test.ts +35 -0
  257. package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +251 -5
  258. package/src/modules/workflow/agent-tools/workflow.tools.ts +4 -2
  259. package/src/modules/workflow/event-bus.ts +25 -0
  260. package/src/modules/workflow/file-lock.service.ts +17 -0
  261. package/src/modules/workflow/git/__tests__/git.service.accessGating.test.ts +9 -49
  262. package/src/modules/workflow/git/__tests__/git.service.changedFilesForPr.test.ts +101 -0
  263. package/src/modules/workflow/git/__tests__/git.service.commitFile.test.ts +219 -211
  264. package/src/modules/workflow/git/__tests__/git.service.fileContentsAtCommit.test.ts +132 -0
  265. package/src/modules/workflow/git/__tests__/git.service.logForFile.test.ts +4 -2
  266. package/src/modules/workflow/git/__tests__/git.service.postMergePull.test.ts +275 -272
  267. package/src/modules/workflow/git/__tests__/git.service.pull.test.ts +5 -0
  268. package/src/modules/workflow/git/__tests__/pull-request.service.viewer-can-cancel.test.ts +44 -0
  269. package/src/modules/workflow/git/branch-name.ts +5 -1
  270. package/src/modules/workflow/git/git.service.ts +159 -62
  271. package/src/modules/workflow/git/pull-request.service.ts +22 -11
  272. package/src/modules/workflow/review-workflow/__tests__/cancel-pr.test.ts +4 -1
  273. package/src/modules/workflow/review-workflow/review-workflow.service.ts +12 -3
  274. package/src/modules/workflow/workflow.routes.ts +91 -13
  275. package/src/modules/workflow/workflow.service.ts +353 -13
  276. package/src/modules/workspace/__tests__/kb-seed.service.test.ts +255 -24
  277. package/src/modules/workspace/__tests__/workspace.routes.create-grant.test.ts +236 -233
  278. package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +179 -176
  279. package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +320 -303
  280. package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +337 -276
  281. package/src/modules/workspace/__tests__/workspace.tools.test.ts +14 -6
  282. package/src/modules/workspace/bevel-ignore.ts +66 -62
  283. package/src/modules/workspace/kb-seed.interface.ts +1 -1
  284. package/src/modules/workspace/kb-seed.service.ts +247 -53
  285. package/src/modules/workspace/workspace.routes.ts +54 -18
  286. package/src/modules/workspace/workspace.service.ts +45 -7
  287. package/src/modules/workspace/workspace.tools.ts +922 -917
  288. package/src/shared/__tests__/frontmatter-id.test.ts +53 -0
  289. package/src/shared/__tests__/join-request.test.ts +96 -0
  290. package/src/shared/__tests__/kb-layout.group.test.ts +45 -0
  291. package/src/shared/kb-layout.test.ts +2 -2
  292. package/src/test-setup.ts +18 -0
  293. package/kb-template/Agents/README.md +0 -38
  294. package/kb-template/CLAUDE.md +0 -419
  295. package/kb-template/Data/.gitkeep +0 -0
  296. package/kb-template/Data/README.md +0 -39
  297. package/kb-template/KnowledgeBase/README.md +0 -37
  298. package/kb-template/Pipelines/.gitkeep +0 -0
  299. package/kb-template/Pipelines/README.md +0 -38
  300. package/kb-template/Skills/.gitkeep +0 -0
  301. package/kb-template/Skills/README.md +0 -32
  302. package/kb-template/Tools/.gitkeep +0 -0
  303. package/kb-template/Tools/README.md +0 -42
  304. /package/kb-template/{Agents → Groups}/.gitkeep +0 -0
@@ -6,7 +6,7 @@ export { PROTECTED_BRANCHES, isProtectedBranch } from '@bevel-software/platform-
6
6
  // picker's `canDelete` rule and the backend authorisation check on
7
7
  // `deleteBranch` must agree on every edge case (uppercase email, dotted
8
8
  // localpart, etc.).
9
- export { branchAuthorLocalpart, isBranchAuthoredBy } from '@bevel-software/platform-shared';
9
+ export { branchAuthorLocalpart, isBranchAuthoredBy, isOwnSuggestionsBranch, } from '@bevel-software/platform-shared';
10
10
  const VALID_BRANCH_REGEX = /^[A-Za-z0-9][A-Za-z0-9/_\-.]*$/;
11
11
  /** Throw if `name` cannot safely be passed to `git` as a branch name. */
12
12
  export function assertValidBranchName(name) {
@@ -1 +1 @@
1
- {"version":3,"file":"branch-name.js","sourceRoot":"","sources":["../../../../src/modules/workflow/git/branch-name.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"branch-name.js","sourceRoot":"","sources":["../../../../src/modules/workflow/git/branch-name.ts"],"names":[],"mappings":"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"}
@@ -114,6 +114,7 @@ export declare class GitService implements IGitService {
114
114
  createBranch(workspaceId: string, name: string, fromBase?: string): Promise<BranchInfo>;
115
115
  deleteBranch(workspaceId: string, name: string, user: AuthUser, opts?: {
116
116
  onlyIfNoRemote?: boolean;
117
+ systemCleanup?: boolean;
117
118
  }): Promise<void>;
118
119
  /**
119
120
  * True iff the given ref (e.g. `refs/heads/foo`, `refs/remotes/origin/foo`)
@@ -172,7 +173,9 @@ export declare class GitService implements IGitService {
172
173
  * (mirrors `commitFile` + `push`).
173
174
  */
174
175
  commitChanges(workspaceId: string, user: AuthUser, summary: string): Promise<CommitAttribution | null>;
175
- push(workspaceId: string, user: AuthUser): Promise<void>;
176
+ push(workspaceId: string, user: AuthUser, opts?: {
177
+ systemAuthorized?: boolean;
178
+ }): Promise<void>;
176
179
  /**
177
180
  * Attempt a local merge of `origin/<targetBranch>` into the currently-
178
181
  * checked-out branch. Used by the workflow module to auto-merge target →
@@ -330,9 +333,20 @@ export declare class GitService implements IGitService {
330
333
  * excluded — the caller gets exactly the working tree's committed contents.
331
334
  */
332
335
  listTrackedFiles(workspaceId: string): Promise<string[]>;
333
- revertCommit(workspaceId: string, user: AuthUser, sha: string): Promise<CommitAttribution>;
334
336
  logForFile(workspaceId: string, relativePath: string, limit?: number): Promise<CommitAttribution[]>;
335
337
  diffFileAtCommit(workspaceId: string, relativePath: string, sha: string): Promise<string>;
338
+ /**
339
+ * Full file contents on both sides of one commit: `baseline` is the file at
340
+ * `<sha>^` (the parent), `current` at `<sha>`. Null means the file is absent
341
+ * at that ref — added files have `baseline: null`, deleted files
342
+ * `current: null`. A root commit (no parent) also yields `baseline: null`.
343
+ * Feeds the rendered-markdown history view, which needs before/after text
344
+ * rather than the patch `diffFileAtCommit` returns.
345
+ */
346
+ fileContentsAtCommit(workspaceId: string, relativePath: string, sha: string): Promise<{
347
+ baseline: string | null;
348
+ current: string | null;
349
+ }>;
336
350
  diffFileBetweenBranches(workspaceId: string, relativePath: string, fromBranch: string, toBranch: string): Promise<string>;
337
351
  /**
338
352
  * Head/base commit SHAs for a change request, computed locally — no provider
@@ -364,6 +378,21 @@ export declare class GitService implements IGitService {
364
378
  * routing. `changedFilesForPr` is the full version with statuses + diffs.
365
379
  */
366
380
  changedPathsForPr(workspaceId: string, baseBranch: string, headBranch: string): Promise<string[]>;
381
+ /**
382
+ * The merge-base commit of a change request's two branches (their origin
383
+ * refs), or null when they share no history. This is the "before" the CR's
384
+ * three-dot diff is read against — the ref a per-file revert restores from,
385
+ * so the reverted file drops OUT of that same diff.
386
+ */
387
+ mergeBaseForPr(workspaceId: string, baseBranch: string, headBranch: string): Promise<string | null>;
388
+ /**
389
+ * Restore one path in the working tree (and index) to its content at `ref`;
390
+ * a path ABSENT at `ref` is deleted — the revert of an added file is its
391
+ * removal. Byte-exact via git itself (`checkout <ref> -- <path>`), never a
392
+ * read-as-string round-trip that would mangle binary files. The caller owns
393
+ * committing the result (see `commitFile`).
394
+ */
395
+ restorePathFromRef(workspaceId: string, ref: string, repoRelativePath: string): Promise<void>;
367
396
  /** Fetch the two branches a CR spans so origin refs reflect the latest push. */
368
397
  private fetchPrRefs;
369
398
  /** Unified-diff patch for one file across the CR range (rename-aware). */
@@ -1 +1 @@
1
- {"version":3,"file":"git.service.d.ts","sourceRoot":"","sources":["../../../../src/modules/workflow/git/git.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"git.service.d.ts","sourceRoot":"","sources":["../../../../src/modules/workflow/git/git.service.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@ import { promisify } from 'node:util';
5
5
  import { AccessDeniedError } from '../../access/access-errors.js';
6
6
  import { WorkspaceMutex } from './mutex.js';
7
7
  import { cloneTrackingConfigArgs, SAFE_IMPLICIT_FETCH_ARGS } from './clone-config.js';
8
- import { assertValidBranchName, assertValidRelativePath, isBranchAuthoredBy, isProtectedBranch, PROTECTED_BRANCHES, } from './branch-name.js';
8
+ import { assertValidBranchName, assertValidRelativePath, isBranchAuthoredBy, isOwnSuggestionsBranch, isProtectedBranch, PROTECTED_BRANCHES, } from './branch-name.js';
9
9
  import { BranchAuthorshipError, WorkflowValidationError, ProtectedBranchError, PullRebaseConflictError, } from '../workflow.errors.js';
10
10
  const execFileAsync = promisify(execFile);
11
11
  function redact(msg) {
@@ -539,7 +539,13 @@ export class GitService {
539
539
  if (current === name) {
540
540
  throw new WorkflowValidationError(`Cannot delete "${name}" while it's the checked-out branch.`);
541
541
  }
542
- if (opts.onlyIfNoRemote) {
542
+ if (opts.systemCleanup) {
543
+ // Internal post-merge retirement (never reachable from a route): the
544
+ // merge that emptied this branch was itself authorized, so no
545
+ // authorship check — the protected-branch and checked-out guards
546
+ // above still hold.
547
+ }
548
+ else if (opts.onlyIfNoRemote) {
543
549
  // Legacy orphan-cleanup path (PR merged + remote head pruned). Skip
544
550
  // the authorship check — callers prune any orphan they encounter,
545
551
  // not just their own — but keep the "refuse if origin still has the
@@ -558,7 +564,12 @@ export class GitService {
558
564
  // that predicate is the existing source of truth for `Admin`-role
559
565
  // membership inside the access model — no separate `isAdmin()` plumbing
560
566
  // needed.
561
- const isAuthor = isBranchAuthoredBy(name, user.email);
567
+ // Two authorship conventions: `<localpart>/…` UI drafts, and the
568
+ // `suggestions/<who>-<id8>/…` namespace the propose flow files its
569
+ // branches under — a user resetting THEIR OWN suggestion bundle is
570
+ // deleting their own branch.
571
+ const isAuthor = isBranchAuthoredBy(name, user.email) ||
572
+ isOwnSuggestionsBranch(name, { email: user.email, id: user.id });
562
573
  const isAdmin = this.accessControl
563
574
  ? await this.accessControl.canWrite(workspaceId, user.email, 'roles.yaml')
564
575
  : false;
@@ -881,7 +892,7 @@ export class GitService {
881
892
  };
882
893
  });
883
894
  }
884
- async push(workspaceId, user) {
895
+ async push(workspaceId, user, opts) {
885
896
  return this.mutex.run(workspaceId, async () => {
886
897
  const cwd = await this.repoDir(workspaceId);
887
898
  const branch = await this.currentBranch(cwd);
@@ -893,7 +904,14 @@ export class GitService {
893
904
  // PR. Gate against `origin/<branch>` — the published state — for
894
905
  // protected pushes; that's defence-in-depth against local rebases or
895
906
  // `commit-tree` shenanigans that might bypass the commit-time gate.
896
- if (isProtectedBranch(branch)) {
907
+ // `systemAuthorized` skips the gate for flows whose ENDPOINT is the
908
+ // authorization — group provisioning commits an access.md into a
909
+ // folder that does not exist at origin yet, which this gate can only
910
+ // ever read as "write: Admin". The provisioning service has already
911
+ // decided the write is legitimate (unused name, exclusive create);
912
+ // gating it here again just refuses every non-admin the product
913
+ // promised a group to.
914
+ if (isProtectedBranch(branch) && !opts?.systemAuthorized) {
897
915
  const touched = await this.unpushedTouchedPaths(cwd);
898
916
  await this.assertCanWriteAtRef(workspaceId, `origin/${branch}`, user.email, touched);
899
917
  }
@@ -1426,50 +1444,6 @@ export class GitService {
1426
1444
  return stdout.split('\0').filter(Boolean);
1427
1445
  });
1428
1446
  }
1429
- async revertCommit(workspaceId, user, sha) {
1430
- if (!/^[a-f0-9]{7,40}$/i.test(sha)) {
1431
- throw new WorkflowValidationError('invalid commit sha');
1432
- }
1433
- assertValidAuthor(user);
1434
- return this.mutex.run(workspaceId, async () => {
1435
- const cwd = await this.repoDir(workspaceId);
1436
- const branch = await this.currentBranch(cwd);
1437
- // Revert creates a new commit reversing `sha`. Same model as commit:
1438
- // gate only on protected branches; reverts on feature/draft branches
1439
- // are free (they produce a commit that would still need to merge via
1440
- // PR to affect canonical state).
1441
- if (isProtectedBranch(branch)) {
1442
- const { stdout: diffOut } = await this.git(cwd, [
1443
- 'diff-tree', '--no-commit-id', '--name-only', '-r', sha,
1444
- ]);
1445
- const touched = diffOut.split('\n').map((s) => s.trim()).filter(Boolean);
1446
- await this.assertCanWriteAtRef(workspaceId, 'HEAD', user.email, touched);
1447
- }
1448
- await this.git(cwd, [
1449
- 'revert',
1450
- '--no-edit',
1451
- `--author=${user.name} <${user.email}>`,
1452
- sha,
1453
- ]);
1454
- const { stdout } = await this.git(cwd, [
1455
- 'log',
1456
- '-1',
1457
- '--pretty=format:%H%x00%an%x00%ae%x00%s%x00%aI',
1458
- ]);
1459
- const [headSha, authorName, authorEmail, subj, committedAt] = stdout.split('\x00');
1460
- // A revert may have touched roles.yaml or access.md — drop cached
1461
- // access state so the next gate read reflects the rolled-back tree.
1462
- // Mirrors the commit / pull paths.
1463
- this.accessControl?.invalidate(workspaceId);
1464
- return {
1465
- sha: headSha?.trim() ?? '',
1466
- authorName: authorName ?? '',
1467
- authorEmail: authorEmail ?? '',
1468
- subject: subj ?? '',
1469
- committedAt: committedAt?.trim() ?? new Date().toISOString(),
1470
- };
1471
- });
1472
- }
1473
1447
  async logForFile(workspaceId, relativePath, limit = 20) {
1474
1448
  assertValidRelativePath(relativePath);
1475
1449
  const max = Math.max(1, Math.min(limit, 100));
@@ -1522,6 +1496,41 @@ export class GitService {
1522
1496
  }
1523
1497
  });
1524
1498
  }
1499
+ /**
1500
+ * Full file contents on both sides of one commit: `baseline` is the file at
1501
+ * `<sha>^` (the parent), `current` at `<sha>`. Null means the file is absent
1502
+ * at that ref — added files have `baseline: null`, deleted files
1503
+ * `current: null`. A root commit (no parent) also yields `baseline: null`.
1504
+ * Feeds the rendered-markdown history view, which needs before/after text
1505
+ * rather than the patch `diffFileAtCommit` returns.
1506
+ */
1507
+ async fileContentsAtCommit(workspaceId, relativePath, sha) {
1508
+ assertValidRelativePath(relativePath);
1509
+ if (!/^[a-f0-9]{7,40}$/i.test(sha)) {
1510
+ throw new WorkflowValidationError('invalid commit sha');
1511
+ }
1512
+ const repoRelativePath = this.stripRepoPrefix(relativePath);
1513
+ return this.mutex.run(workspaceId, async () => {
1514
+ const current = await this.readFileAtRef(workspaceId, sha, repoRelativePath);
1515
+ let baseline;
1516
+ try {
1517
+ baseline = await this.readFileAtRef(workspaceId, `${sha}^`, repoRelativePath);
1518
+ }
1519
+ catch (err) {
1520
+ // `readFileAtRef` maps "path absent at ref" to null but propagates an
1521
+ // unresolvable ref. `<sha>^` on a root commit is exactly that (git
1522
+ // reports it as "invalid object name '<sha>^'", or "unknown/bad
1523
+ // revision" in other codepaths), and it legitimately means "no parent
1524
+ // side" — fold it into null. Anything else stays fatal.
1525
+ const stderr = err.stderr ?? (err instanceof Error ? err.message : String(err));
1526
+ if (/invalid object name|unknown revision|bad revision/i.test(stderr))
1527
+ baseline = null;
1528
+ else
1529
+ throw err;
1530
+ }
1531
+ return { baseline, current };
1532
+ });
1533
+ }
1525
1534
  async diffFileBetweenBranches(workspaceId, relativePath, fromBranch, toBranch) {
1526
1535
  assertValidRelativePath(relativePath);
1527
1536
  assertValidBranchName(fromBranch);
@@ -1632,8 +1641,21 @@ export class GitService {
1632
1641
  this.git(cwd, ['diff', '-M', '-z', '--name-status', range]),
1633
1642
  this.git(cwd, ['diff', '-M', '-z', '--numstat', range]),
1634
1643
  ]);
1635
- const statuses = parseNameStatusZ(nameStatusOut);
1636
- const counts = parseNumstatZ(numstatOut);
1644
+ let statuses = parseNameStatusZ(nameStatusOut);
1645
+ let counts = parseNumstatZ(numstatOut);
1646
+ // roles.yaml can NEVER change through a merge — `preserveBaseRolesYaml`
1647
+ // restores the base copy onto the source branch before every merge — so
1648
+ // listing it as "changed" claims something the merge will not do, and
1649
+ // (worse) makes its approval a requirement for a change that cannot
1650
+ // land. Filter it from the review surface entirely; the neutralisation
1651
+ // reads the raw refs itself and is unaffected. Both lists are filtered
1652
+ // IN STEP so the index-zip below stays aligned.
1653
+ if (statuses.some((s) => s.path === 'roles.yaml')) {
1654
+ const keep = statuses.map((s) => s.path !== 'roles.yaml');
1655
+ statuses = statuses.filter((_, i) => keep[i]);
1656
+ if (counts.length === keep.length)
1657
+ counts = counts.filter((_, i) => keep[i]);
1658
+ }
1637
1659
  // `--name-status` and `--numstat` enumerate the same files in the same
1638
1660
  // order (same `-M` over the same range), so we zip by index. If the two
1639
1661
  // ever disagree in length, the index alignment is unsafe — fall back to
@@ -1689,7 +1711,77 @@ export class GitService {
1689
1711
  const { stdout } = await this.git(cwd, [
1690
1712
  'diff', '-M', '--name-only', `${baseRef}...${headRef}`,
1691
1713
  ]);
1692
- return stdout.split('\n').map((s) => s.trim()).filter(Boolean);
1714
+ return (stdout
1715
+ .split('\n')
1716
+ .map((s) => s.trim())
1717
+ .filter(Boolean)
1718
+ // Same rule as `changedFilesForPr`: a roles.yaml change never
1719
+ // survives a merge, so it is not a touched path for routing or
1720
+ // summaries either.
1721
+ .filter((p) => p !== 'roles.yaml'));
1722
+ });
1723
+ }
1724
+ /**
1725
+ * The merge-base commit of a change request's two branches (their origin
1726
+ * refs), or null when they share no history. This is the "before" the CR's
1727
+ * three-dot diff is read against — the ref a per-file revert restores from,
1728
+ * so the reverted file drops OUT of that same diff.
1729
+ */
1730
+ async mergeBaseForPr(workspaceId, baseBranch, headBranch) {
1731
+ assertValidBranchName(baseBranch);
1732
+ assertValidBranchName(headBranch);
1733
+ const cwd = await this.repoDir(workspaceId);
1734
+ await this.fetchPrRefs(cwd, baseBranch, headBranch);
1735
+ return this.mutex.run(workspaceId, async () => {
1736
+ const baseRef = await this.resolveBranchRef(cwd, baseBranch);
1737
+ const headRef = await this.resolveBranchRef(cwd, headBranch);
1738
+ try {
1739
+ const { stdout } = await this.git(cwd, ['merge-base', baseRef, headRef]);
1740
+ return stdout.trim() || null;
1741
+ }
1742
+ catch (err) {
1743
+ // Exit 1 is git's specific "no common ancestor" answer; anything else
1744
+ // is an infra failure that must not masquerade as it.
1745
+ if (err.exitCode === 1)
1746
+ return null;
1747
+ throw err;
1748
+ }
1749
+ });
1750
+ }
1751
+ /**
1752
+ * Restore one path in the working tree (and index) to its content at `ref`;
1753
+ * a path ABSENT at `ref` is deleted — the revert of an added file is its
1754
+ * removal. Byte-exact via git itself (`checkout <ref> -- <path>`), never a
1755
+ * read-as-string round-trip that would mangle binary files. The caller owns
1756
+ * committing the result (see `commitFile`).
1757
+ */
1758
+ async restorePathFromRef(workspaceId, ref, repoRelativePath) {
1759
+ assertValidRelativePath(repoRelativePath);
1760
+ return this.mutex.run(workspaceId, async () => {
1761
+ const cwd = await this.repoDir(workspaceId);
1762
+ let existsAtRef = true;
1763
+ try {
1764
+ await this.git(cwd, ['cat-file', '-e', `${ref}:${repoRelativePath}`]);
1765
+ }
1766
+ catch {
1767
+ existsAtRef = false;
1768
+ }
1769
+ if (existsAtRef) {
1770
+ await this.git(cwd, ['checkout', ref, '--', repoRelativePath]);
1771
+ }
1772
+ else {
1773
+ // First re-align the INDEX with HEAD for this path. A previous failed
1774
+ // attempt (the git-rm era of this method) can have left a staged
1775
+ // deletion — index entry gone — and `git add` can only stage a
1776
+ // deletion for a path the index still tracks. No-op on a clean tree.
1777
+ await this.git(cwd, ['reset', '-q', 'HEAD', '--', repoRelativePath]);
1778
+ // Then delete from the WORKING TREE only, never `git rm`: the
1779
+ // follow-up `commitFile` stages via `git add -- <path>`, and dropping
1780
+ // the index entry too made that add match nothing — the whole revert
1781
+ // failed with "pathspec did not match any files". A tracked file
1782
+ // missing from disk is exactly what `git add` records as deleted.
1783
+ await fs.rm(path.join(cwd, repoRelativePath), { force: true });
1784
+ }
1693
1785
  });
1694
1786
  }
1695
1787
  /** Fetch the two branches a CR spans so origin refs reflect the latest push. */