canopycms 0.0.67-int.90 → 0.0.67

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 (539) hide show
  1. package/README.md +30 -3
  2. package/dist/ai/generate.js +1 -27
  3. package/dist/ai/handler.d.ts +0 -4
  4. package/dist/ai/handler.js +0 -11
  5. package/dist/ai/index.d.ts +1 -8
  6. package/dist/ai/index.js +1 -8
  7. package/dist/ai/json-to-markdown.js +15 -58
  8. package/dist/ai/resolve-branch.d.ts +2 -7
  9. package/dist/ai/resolve-branch.js +2 -8
  10. package/dist/ai/strip-mdx.d.ts +5 -13
  11. package/dist/ai/strip-mdx.js +5 -17
  12. package/dist/ai/to-plain-text.d.ts +10 -28
  13. package/dist/ai/to-plain-text.js +10 -28
  14. package/dist/ai/transform-components.d.ts +2 -4
  15. package/dist/ai/transform-components.js +8 -19
  16. package/dist/ai/types.d.ts +5 -10
  17. package/dist/api/admin-branch-health.d.ts +4 -12
  18. package/dist/api/admin-branch-health.js +26 -66
  19. package/dist/api/admin.d.ts +4 -12
  20. package/dist/api/admin.js +10 -26
  21. package/dist/api/assets.d.ts +0 -25
  22. package/dist/api/assets.js +50 -91
  23. package/dist/api/branch-merge.d.ts +1 -1
  24. package/dist/api/branch-merge.js +0 -2
  25. package/dist/api/branch-review.d.ts +0 -8
  26. package/dist/api/branch-review.js +0 -13
  27. package/dist/api/branch-status.d.ts +0 -3
  28. package/dist/api/branch-status.js +8 -33
  29. package/dist/api/branch-withdraw.d.ts +0 -1
  30. package/dist/api/branch-withdraw.js +6 -9
  31. package/dist/api/branch.d.ts +7 -12
  32. package/dist/api/branch.js +7 -44
  33. package/dist/api/client.d.ts +71 -224
  34. package/dist/api/client.js +82 -233
  35. package/dist/api/comments.d.ts +2 -4
  36. package/dist/api/comments.js +0 -17
  37. package/dist/api/content.d.ts +0 -6
  38. package/dist/api/content.js +66 -142
  39. package/dist/api/entries-constants.d.ts +5 -9
  40. package/dist/api/entries-constants.js +5 -9
  41. package/dist/api/entries.d.ts +8 -13
  42. package/dist/api/entries.js +20 -51
  43. package/dist/api/github-sync.d.ts +2 -4
  44. package/dist/api/github-sync.js +4 -8
  45. package/dist/api/groups.d.ts +3 -0
  46. package/dist/api/groups.js +8 -21
  47. package/dist/api/guards.d.ts +4 -16
  48. package/dist/api/guards.js +3 -22
  49. package/dist/api/index.d.ts +4 -4
  50. package/dist/api/permissions.d.ts +2 -0
  51. package/dist/api/permissions.js +18 -40
  52. package/dist/api/reference-options.d.ts +0 -1
  53. package/dist/api/reference-options.js +3 -11
  54. package/dist/api/request-body-hash.d.ts +12 -23
  55. package/dist/api/request-body-hash.js +12 -23
  56. package/dist/api/resolve-references.d.ts +0 -1
  57. package/dist/api/resolve-references.js +13 -28
  58. package/dist/api/route-builder.d.ts +3 -7
  59. package/dist/api/route-builder.js +1 -1
  60. package/dist/api/routes.d.ts +12 -0
  61. package/dist/api/routes.js +47 -0
  62. package/dist/api/schema.d.ts +23 -33
  63. package/dist/api/schema.js +20 -74
  64. package/dist/api/settings-helpers.js +4 -5
  65. package/dist/api/types.d.ts +0 -5
  66. package/dist/api/user.js +0 -5
  67. package/dist/api/validators.d.ts +14 -52
  68. package/dist/api/validators.js +14 -52
  69. package/dist/assets/asset-prefixes.d.ts +4 -8
  70. package/dist/assets/asset-prefixes.js +4 -8
  71. package/dist/assets/asset-src.d.ts +5 -22
  72. package/dist/assets/asset-src.js +5 -21
  73. package/dist/assets/factory.d.ts +1 -2
  74. package/dist/assets/factory.js +1 -2
  75. package/dist/assets/finalize.d.ts +3 -1
  76. package/dist/assets/finalize.js +3 -1
  77. package/dist/assets/index.d.ts +3 -3
  78. package/dist/assets/index.js +1 -1
  79. package/dist/assets/keys.d.ts +5 -3
  80. package/dist/assets/keys.js +6 -3
  81. package/dist/assets/pipeline.d.ts +3 -2
  82. package/dist/assets/pipeline.js +22 -56
  83. package/dist/assets/sharp-loader.d.ts +2 -10
  84. package/dist/assets/sharp-loader.js +2 -10
  85. package/dist/assets/store-local.d.ts +1 -2
  86. package/dist/assets/store-local.js +1 -2
  87. package/dist/assets/store-s3.d.ts +3 -4
  88. package/dist/assets/svg-sanitizer.d.ts +6 -14
  89. package/dist/assets/svg-sanitizer.js +6 -14
  90. package/dist/assets/transform-directives.d.ts +3 -4
  91. package/dist/assets/transform-directives.js +1 -1
  92. package/dist/assets/transform.d.ts +19 -30
  93. package/dist/assets/transform.js +18 -31
  94. package/dist/auth/cache.d.ts +2 -3
  95. package/dist/auth/cache.js +2 -3
  96. package/dist/auth/caching-auth-plugin.d.ts +11 -22
  97. package/dist/auth/caching-auth-plugin.js +12 -14
  98. package/dist/auth/context-helpers.d.ts +6 -20
  99. package/dist/auth/context-helpers.js +5 -17
  100. package/dist/auth/file-based-auth-cache.d.ts +10 -21
  101. package/dist/auth/file-based-auth-cache.js +23 -51
  102. package/dist/auth/plugin.d.ts +29 -61
  103. package/dist/auth/plugin.js +9 -13
  104. package/dist/auth/types.d.ts +11 -20
  105. package/dist/authorization/branch.d.ts +30 -49
  106. package/dist/authorization/branch.js +16 -42
  107. package/dist/authorization/content.d.ts +11 -40
  108. package/dist/authorization/content.js +13 -45
  109. package/dist/authorization/groups/index.d.ts +0 -3
  110. package/dist/authorization/groups/index.js +0 -3
  111. package/dist/authorization/groups/loader.d.ts +14 -28
  112. package/dist/authorization/groups/loader.js +14 -38
  113. package/dist/authorization/groups/schema.d.ts +0 -6
  114. package/dist/authorization/groups/schema.js +4 -7
  115. package/dist/authorization/helpers.d.ts +9 -28
  116. package/dist/authorization/helpers.js +9 -28
  117. package/dist/authorization/index.d.ts +3 -25
  118. package/dist/authorization/index.js +3 -35
  119. package/dist/authorization/path.d.ts +6 -13
  120. package/dist/authorization/path.js +8 -25
  121. package/dist/authorization/permissions/index.d.ts +0 -3
  122. package/dist/authorization/permissions/index.js +0 -3
  123. package/dist/authorization/permissions/loader.d.ts +14 -27
  124. package/dist/authorization/permissions/loader.js +14 -32
  125. package/dist/authorization/permissions/schema.d.ts +1 -6
  126. package/dist/authorization/permissions/schema.js +6 -13
  127. package/dist/authorization/protected-branch.d.ts +36 -65
  128. package/dist/authorization/protected-branch.js +29 -41
  129. package/dist/authorization/settings-file-store.d.ts +38 -81
  130. package/dist/authorization/settings-file-store.js +38 -79
  131. package/dist/authorization/types.d.ts +4 -26
  132. package/dist/authorization/types.js +0 -6
  133. package/dist/authorization/validation.d.ts +1 -23
  134. package/dist/authorization/validation.js +1 -24
  135. package/dist/branch-health.d.ts +39 -67
  136. package/dist/branch-health.js +27 -43
  137. package/dist/branch-metadata-file.d.ts +16 -32
  138. package/dist/branch-metadata-file.js +13 -26
  139. package/dist/branch-metadata.d.ts +49 -80
  140. package/dist/branch-metadata.js +57 -87
  141. package/dist/branch-registry.d.ts +26 -64
  142. package/dist/branch-registry.js +44 -93
  143. package/dist/branch-schema-cache.d.ts +34 -124
  144. package/dist/branch-schema-cache.js +49 -155
  145. package/dist/branch-workspace.d.ts +4 -4
  146. package/dist/branch-workspace.js +15 -19
  147. package/dist/build/generate-ai-content.d.ts +1 -0
  148. package/dist/build/generate-ai-content.js +12 -25
  149. package/dist/build-canopy.d.ts +17 -27
  150. package/dist/build-canopy.js +16 -23
  151. package/dist/build-mode.d.ts +25 -27
  152. package/dist/build-mode.js +25 -29
  153. package/dist/cli/cli.d.ts +15 -26
  154. package/dist/cli/cli.js +601 -978
  155. package/dist/cli/generate-ai-content.js +351 -628
  156. package/dist/cli/github-app-manifest.d.ts +84 -0
  157. package/dist/cli/github-app-manifest.js +161 -0
  158. package/dist/cli/init-github-app.d.ts +110 -444
  159. package/dist/cli/init-github-app.js +236 -773
  160. package/dist/cli/init.js +39 -80
  161. package/dist/cli/migrate.d.ts +13 -10
  162. package/dist/cli/migrate.js +22 -30
  163. package/dist/cli/project-detect.d.ts +17 -31
  164. package/dist/cli/project-detect.js +31 -42
  165. package/dist/cli/project-root.d.ts +4 -11
  166. package/dist/cli/project-root.js +4 -11
  167. package/dist/cli/prompt.d.ts +10 -0
  168. package/dist/cli/prompt.js +67 -0
  169. package/dist/cli/sync.d.ts +0 -8
  170. package/dist/cli/sync.js +8 -28
  171. package/dist/cli/template-files/middleware.ts.template +15 -29
  172. package/dist/cli/templates.d.ts +2 -12
  173. package/dist/cli/templates.js +4 -4
  174. package/dist/client.d.ts +1 -1
  175. package/dist/comment-store.d.ts +32 -53
  176. package/dist/comment-store.js +32 -52
  177. package/dist/config/flatten.d.ts +0 -3
  178. package/dist/config/flatten.js +2 -12
  179. package/dist/config/helpers.js +2 -2
  180. package/dist/config/index.d.ts +2 -2
  181. package/dist/config/index.js +1 -4
  182. package/dist/config/schemas/collection.d.ts +0 -8
  183. package/dist/config/schemas/collection.js +0 -10
  184. package/dist/config/schemas/config.d.ts +6 -78
  185. package/dist/config/schemas/config.js +38 -54
  186. package/dist/config/schemas/field.d.ts +2 -242
  187. package/dist/config/schemas/field.js +9 -20
  188. package/dist/config/schemas/media.js +1 -1
  189. package/dist/config/schemas/permissions.js +0 -2
  190. package/dist/config/schemas/url.d.ts +5 -6
  191. package/dist/config/schemas/url.js +5 -6
  192. package/dist/config/types.d.ts +45 -33
  193. package/dist/config/types.js +0 -1
  194. package/dist/config.d.ts +1 -8
  195. package/dist/config.js +1 -9
  196. package/dist/content-id-index.d.ts +76 -188
  197. package/dist/content-id-index.js +79 -230
  198. package/dist/content-index-generation.d.ts +27 -48
  199. package/dist/content-index-generation.js +35 -84
  200. package/dist/content-index-registry.d.ts +15 -24
  201. package/dist/content-index-registry.js +5 -9
  202. package/dist/content-listing.d.ts +64 -107
  203. package/dist/content-listing.js +68 -118
  204. package/dist/content-reader.d.ts +20 -29
  205. package/dist/content-reader.js +10 -18
  206. package/dist/content-store.d.ts +210 -336
  207. package/dist/content-store.js +413 -657
  208. package/dist/content-tree.d.ts +44 -86
  209. package/dist/content-tree.js +26 -54
  210. package/dist/context.d.ts +67 -94
  211. package/dist/context.js +53 -72
  212. package/dist/dev-content-watcher.d.ts +18 -18
  213. package/dist/dev-content-watcher.js +41 -44
  214. package/dist/editor/BranchManager.d.ts +3 -6
  215. package/dist/editor/BranchManager.js +24 -44
  216. package/dist/editor/CanopyEditor.js +5 -2
  217. package/dist/editor/CommentsPanel.js +0 -2
  218. package/dist/editor/Editor.js +19 -76
  219. package/dist/editor/EditorAuthGate.d.ts +27 -0
  220. package/dist/editor/EditorAuthGate.js +140 -0
  221. package/dist/editor/EntryNavigator.js +0 -20
  222. package/dist/editor/FormRenderer.d.ts +1 -2
  223. package/dist/editor/FormRenderer.js +8 -23
  224. package/dist/editor/admin/SystemHealthPanel.js +20 -37
  225. package/dist/editor/admin/useSystemHealth.d.ts +2 -3
  226. package/dist/editor/admin/useSystemHealth.js +10 -12
  227. package/dist/editor/client-reference-resolver.d.ts +2 -5
  228. package/dist/editor/client-reference-resolver.js +2 -19
  229. package/dist/editor/comments/BranchComments.js +0 -4
  230. package/dist/editor/comments/EntryComments.js +0 -4
  231. package/dist/editor/comments/FieldWrapper.js +0 -4
  232. package/dist/editor/comments/InlineCommentThread.js +0 -2
  233. package/dist/editor/comments/ThreadCarousel.d.ts +0 -58
  234. package/dist/editor/comments/ThreadCarousel.js +0 -12
  235. package/dist/editor/components/EditorFooter.d.ts +0 -8
  236. package/dist/editor/components/EditorFooter.js +0 -5
  237. package/dist/editor/components/EditorHeader.d.ts +0 -31
  238. package/dist/editor/components/EditorHeader.js +21 -71
  239. package/dist/editor/components/EditorSidebar.d.ts +0 -19
  240. package/dist/editor/components/EditorSidebar.js +0 -16
  241. package/dist/editor/components/EntryCreateModal.d.ts +4 -4
  242. package/dist/editor/components/EntryCreateModal.js +7 -22
  243. package/dist/editor/components/RenameEntryModal.js +0 -4
  244. package/dist/editor/components/UserBadge.js +0 -10
  245. package/dist/editor/components/index.js +0 -2
  246. package/dist/editor/context/ApiClientContext.d.ts +8 -7
  247. package/dist/editor/context/ApiClientContext.js +39 -11
  248. package/dist/editor/context/AssetContext.d.ts +7 -17
  249. package/dist/editor/context/AssetContext.js +7 -17
  250. package/dist/editor/context/EditorIdentityContext.d.ts +13 -0
  251. package/dist/editor/context/EditorIdentityContext.js +7 -0
  252. package/dist/editor/context/EditorStateContext.d.ts +10 -41
  253. package/dist/editor/context/EditorStateContext.js +7 -23
  254. package/dist/editor/context/SWRProvider.d.ts +3 -6
  255. package/dist/editor/context/index.d.ts +1 -20
  256. package/dist/editor/context/index.js +1 -20
  257. package/dist/editor/editor-utils.d.ts +8 -47
  258. package/dist/editor/editor-utils.js +19 -72
  259. package/dist/editor/fields/BlockField.d.ts +2 -2
  260. package/dist/editor/fields/BlockField.js +1 -2
  261. package/dist/editor/fields/CodeField.d.ts +0 -1
  262. package/dist/editor/fields/CodeField.js +0 -1
  263. package/dist/editor/fields/DateTimeField.d.ts +15 -22
  264. package/dist/editor/fields/DateTimeField.js +17 -26
  265. package/dist/editor/fields/ImageField.d.ts +2 -2
  266. package/dist/editor/fields/ImageField.js +8 -14
  267. package/dist/editor/fields/InlineGroupField.d.ts +0 -1
  268. package/dist/editor/fields/InlineGroupField.js +0 -1
  269. package/dist/editor/fields/MarkdownField.d.ts +0 -1
  270. package/dist/editor/fields/MarkdownField.js +6 -11
  271. package/dist/editor/fields/MdxImageDialog.d.ts +1 -1
  272. package/dist/editor/fields/MdxImageDialog.js +0 -1
  273. package/dist/editor/fields/NumberField.d.ts +9 -19
  274. package/dist/editor/fields/NumberField.js +11 -22
  275. package/dist/editor/fields/NumberListField.d.ts +7 -10
  276. package/dist/editor/fields/NumberListField.js +7 -10
  277. package/dist/editor/fields/ObjectField.d.ts +5 -8
  278. package/dist/editor/fields/ObjectField.js +0 -1
  279. package/dist/editor/fields/ReferenceField.d.ts +1 -1
  280. package/dist/editor/fields/ReferenceField.js +11 -16
  281. package/dist/editor/fields/SelectField.d.ts +2 -2
  282. package/dist/editor/fields/SelectField.js +0 -1
  283. package/dist/editor/fields/StringListField.d.ts +0 -4
  284. package/dist/editor/fields/StringListField.js +4 -9
  285. package/dist/editor/fields/TextField.d.ts +0 -1
  286. package/dist/editor/fields/TextField.js +0 -1
  287. package/dist/editor/fields/ToggleField.d.ts +0 -1
  288. package/dist/editor/fields/ToggleField.js +0 -1
  289. package/dist/editor/fields/entry-link/EntryLinkContext.js +2 -4
  290. package/dist/editor/fields/entry-link/InsertEntryLink.d.ts +0 -3
  291. package/dist/editor/fields/entry-link/InsertEntryLink.js +0 -4
  292. package/dist/editor/group-manager/ExternalGroupsTab.d.ts +0 -3
  293. package/dist/editor/group-manager/ExternalGroupsTab.js +0 -1
  294. package/dist/editor/group-manager/GroupCard.d.ts +0 -3
  295. package/dist/editor/group-manager/GroupForm.d.ts +0 -3
  296. package/dist/editor/group-manager/InternalGroupsTab.d.ts +0 -3
  297. package/dist/editor/group-manager/InternalGroupsTab.js +0 -2
  298. package/dist/editor/group-manager/MemberList.d.ts +0 -3
  299. package/dist/editor/group-manager/hooks/useExternalGroupSearch.d.ts +0 -3
  300. package/dist/editor/group-manager/hooks/useExternalGroupSearch.js +0 -3
  301. package/dist/editor/group-manager/hooks/useGroupState.d.ts +0 -3
  302. package/dist/editor/group-manager/hooks/useGroupState.js +0 -5
  303. package/dist/editor/group-manager/hooks/useUserSearch.d.ts +0 -3
  304. package/dist/editor/group-manager/hooks/useUserSearch.js +0 -3
  305. package/dist/editor/group-manager/index.d.ts +0 -6
  306. package/dist/editor/group-manager/index.js +0 -10
  307. package/dist/editor/group-manager/types.d.ts +2 -5
  308. package/dist/editor/group-manager/types.js +0 -3
  309. package/dist/editor/hooks/index.d.ts +6 -11
  310. package/dist/editor/hooks/index.js +6 -12
  311. package/dist/editor/hooks/useBranchActions.d.ts +0 -14
  312. package/dist/editor/hooks/useBranchActions.js +0 -22
  313. package/dist/editor/hooks/useBranchManager.d.ts +2 -48
  314. package/dist/editor/hooks/useBranchManager.js +4 -64
  315. package/dist/editor/hooks/useBranchesData.d.ts +7 -6
  316. package/dist/editor/hooks/useBranchesData.js +7 -6
  317. package/dist/editor/hooks/useCommentSystem.d.ts +0 -49
  318. package/dist/editor/hooks/useCommentSystem.js +1 -36
  319. package/dist/editor/hooks/useDraftManager.d.ts +2 -35
  320. package/dist/editor/hooks/useDraftManager.js +23 -64
  321. package/dist/editor/hooks/useEditorLayout.d.ts +0 -20
  322. package/dist/editor/hooks/useEditorLayout.js +0 -23
  323. package/dist/editor/hooks/useEntriesData.d.ts +1 -0
  324. package/dist/editor/hooks/useEntriesData.js +2 -3
  325. package/dist/editor/hooks/useEntryLinkResolution.d.ts +2 -2
  326. package/dist/editor/hooks/useEntryLinkResolution.js +2 -2
  327. package/dist/editor/hooks/useEntryManager.d.ts +2 -27
  328. package/dist/editor/hooks/useEntryManager.js +29 -78
  329. package/dist/editor/hooks/useGroupManager.d.ts +0 -21
  330. package/dist/editor/hooks/useGroupManager.js +0 -21
  331. package/dist/editor/hooks/usePermissionManager.d.ts +0 -20
  332. package/dist/editor/hooks/usePermissionManager.js +0 -20
  333. package/dist/editor/hooks/useReferenceResolution.d.ts +2 -33
  334. package/dist/editor/hooks/useReferenceResolution.js +1 -48
  335. package/dist/editor/hooks/useSchemaManager.d.ts +8 -27
  336. package/dist/editor/hooks/useSchemaManager.js +0 -19
  337. package/dist/editor/hooks/useUserContext.d.ts +2 -9
  338. package/dist/editor/hooks/useUserContext.js +10 -10
  339. package/dist/editor/hooks/useUserMetadata.d.ts +0 -2
  340. package/dist/editor/hooks/useUserMetadata.js +0 -3
  341. package/dist/editor/media/AssetCard.d.ts +0 -1
  342. package/dist/editor/media/AssetCard.js +1 -2
  343. package/dist/editor/media/CropStep.d.ts +0 -1
  344. package/dist/editor/media/CropStep.js +0 -1
  345. package/dist/editor/media/MediaLibrary.d.ts +1 -2
  346. package/dist/editor/media/MediaLibrary.js +1 -2
  347. package/dist/editor/media/MediaLibraryBody.d.ts +0 -1
  348. package/dist/editor/media/MediaLibraryBody.js +0 -1
  349. package/dist/editor/media/crop-math.d.ts +1 -1
  350. package/dist/editor/media/crop-math.js +1 -1
  351. package/dist/editor/permission-manager/GroupSelector.d.ts +0 -3
  352. package/dist/editor/permission-manager/PermissionEditor.d.ts +0 -4
  353. package/dist/editor/permission-manager/PermissionEditor.js +0 -1
  354. package/dist/editor/permission-manager/PermissionLevelBadge.d.ts +0 -7
  355. package/dist/editor/permission-manager/PermissionLevelBadge.js +0 -4
  356. package/dist/editor/permission-manager/PermissionTree.d.ts +0 -4
  357. package/dist/editor/permission-manager/UserSelector.d.ts +0 -3
  358. package/dist/editor/permission-manager/constants.d.ts +0 -3
  359. package/dist/editor/permission-manager/hooks/useGroupsAndUsers.d.ts +0 -3
  360. package/dist/editor/permission-manager/hooks/useGroupsAndUsers.js +0 -10
  361. package/dist/editor/permission-manager/hooks/usePermissionTree.d.ts +0 -14
  362. package/dist/editor/permission-manager/hooks/usePermissionTree.js +0 -11
  363. package/dist/editor/permission-manager/index.d.ts +0 -7
  364. package/dist/editor/permission-manager/index.js +0 -16
  365. package/dist/editor/permission-manager/types.d.ts +2 -12
  366. package/dist/editor/permission-manager/types.js +0 -3
  367. package/dist/editor/permission-manager/utils.d.ts +0 -28
  368. package/dist/editor/permission-manager/utils.js +9 -23
  369. package/dist/editor/preview-bridge.d.ts +5 -1
  370. package/dist/editor/preview-bridge.js +4 -4
  371. package/dist/editor/schema-editor/CollectionEditor.d.ts +0 -5
  372. package/dist/editor/schema-editor/CollectionEditor.js +9 -31
  373. package/dist/editor/schema-editor/EntryTypeEditor.d.ts +0 -6
  374. package/dist/editor/schema-editor/EntryTypeEditor.js +3 -24
  375. package/dist/editor/schema-editor/index.d.ts +0 -7
  376. package/dist/editor/schema-editor/index.js +0 -7
  377. package/dist/editor/utils/env.d.ts +3 -18
  378. package/dist/editor/utils/env.js +6 -25
  379. package/dist/entry-link-resolver.d.ts +13 -35
  380. package/dist/entry-link-resolver.js +20 -53
  381. package/dist/entry-schema-registry.d.ts +20 -60
  382. package/dist/entry-schema-registry.js +20 -69
  383. package/dist/entry-schema.d.ts +118 -223
  384. package/dist/entry-schema.js +46 -91
  385. package/dist/git-manager.d.ts +101 -200
  386. package/dist/git-manager.js +211 -384
  387. package/dist/github-service.d.ts +34 -75
  388. package/dist/github-service.js +37 -91
  389. package/dist/http/handler.d.ts +6 -37
  390. package/dist/http/handler.js +65 -120
  391. package/dist/http/router.d.ts +15 -32
  392. package/dist/http/router.js +34 -99
  393. package/dist/http/types.d.ts +15 -40
  394. package/dist/http/types.js +3 -7
  395. package/dist/id.d.ts +4 -10
  396. package/dist/id.js +4 -10
  397. package/dist/index.js +6 -9
  398. package/dist/operating-mode/client-safe-strategy.d.ts +7 -14
  399. package/dist/operating-mode/client-safe-strategy.js +8 -28
  400. package/dist/operating-mode/client-unsafe-strategy.d.ts +6 -16
  401. package/dist/operating-mode/client-unsafe-strategy.js +9 -34
  402. package/dist/operating-mode/client.d.ts +3 -10
  403. package/dist/operating-mode/client.js +3 -8
  404. package/dist/operating-mode/deployment-name-fixtures.d.ts +14 -18
  405. package/dist/operating-mode/deployment-name-fixtures.js +14 -18
  406. package/dist/operating-mode/deployment-name.d.ts +19 -29
  407. package/dist/operating-mode/deployment-name.js +29 -47
  408. package/dist/operating-mode/index.d.ts +4 -25
  409. package/dist/operating-mode/index.js +9 -31
  410. package/dist/operating-mode/mode-env.d.ts +32 -54
  411. package/dist/operating-mode/mode-env.js +36 -58
  412. package/dist/operating-mode/types.d.ts +24 -72
  413. package/dist/operating-mode/types.js +1 -7
  414. package/dist/paths/branch-name.d.ts +30 -40
  415. package/dist/paths/branch-name.js +30 -40
  416. package/dist/paths/branch.d.ts +4 -18
  417. package/dist/paths/branch.js +6 -22
  418. package/dist/paths/index.d.ts +2 -13
  419. package/dist/paths/index.js +3 -23
  420. package/dist/paths/normalize-server.d.ts +3 -15
  421. package/dist/paths/normalize-server.js +3 -15
  422. package/dist/paths/normalize.d.ts +13 -33
  423. package/dist/paths/normalize.js +13 -33
  424. package/dist/paths/resolve.d.ts +4 -17
  425. package/dist/paths/resolve.js +4 -22
  426. package/dist/paths/types.d.ts +12 -34
  427. package/dist/paths/types.js +5 -7
  428. package/dist/paths/validation.d.ts +22 -119
  429. package/dist/paths/validation.js +30 -148
  430. package/dist/reference-resolver.d.ts +0 -13
  431. package/dist/reference-resolver.js +0 -18
  432. package/dist/resolve-canopy-user.d.ts +16 -18
  433. package/dist/resolve-canopy-user.js +17 -26
  434. package/dist/resource-generation.d.ts +16 -25
  435. package/dist/resource-generation.js +34 -97
  436. package/dist/schema/meta-loader.d.ts +2 -14
  437. package/dist/schema/meta-loader.js +15 -64
  438. package/dist/schema/resolver.d.ts +1 -4
  439. package/dist/schema/resolver.js +1 -6
  440. package/dist/schema/schema-store-types.d.ts +0 -12
  441. package/dist/schema/schema-store.d.ts +61 -138
  442. package/dist/schema/schema-store.js +85 -282
  443. package/dist/schema/types.d.ts +0 -4
  444. package/dist/server.d.ts +62 -93
  445. package/dist/server.js +63 -94
  446. package/dist/services.d.ts +23 -47
  447. package/dist/services.js +55 -98
  448. package/dist/settings-workspace.d.ts +17 -30
  449. package/dist/settings-workspace.js +51 -81
  450. package/dist/static/index.d.ts +26 -52
  451. package/dist/static/index.js +33 -67
  452. package/dist/{worker/task-queue.d.ts → task-queue/cms-task-queue.d.ts} +7 -9
  453. package/dist/task-queue/cms-task-queue.js +13 -0
  454. package/dist/task-queue/task-queue-config.d.ts +3 -0
  455. package/dist/{worker → task-queue}/task-queue-config.js +1 -6
  456. package/dist/task-queue/task-queue.d.ts +16 -22
  457. package/dist/task-queue/task-queue.js +20 -44
  458. package/dist/task-queue/types.d.ts +0 -1
  459. package/dist/task-queue/worker-status.d.ts +35 -0
  460. package/dist/task-queue/worker-status.js +40 -0
  461. package/dist/types.d.ts +40 -51
  462. package/dist/url-collision.d.ts +26 -40
  463. package/dist/url-collision.js +47 -63
  464. package/dist/url-exclusivity-fixtures.d.ts +15 -20
  465. package/dist/url-exclusivity-fixtures.js +14 -19
  466. package/dist/url-path-resolver.d.ts +8 -16
  467. package/dist/url-path-resolver.js +19 -29
  468. package/dist/user.d.ts +8 -21
  469. package/dist/user.js +10 -19
  470. package/dist/utils/async-mutex.js +4 -6
  471. package/dist/utils/atomic-write.d.ts +2 -11
  472. package/dist/utils/atomic-write.js +2 -11
  473. package/dist/utils/body-field.d.ts +8 -15
  474. package/dist/utils/body-field.js +8 -15
  475. package/dist/utils/content-serialize.d.ts +18 -24
  476. package/dist/utils/content-serialize.js +109 -160
  477. package/dist/utils/content-write-lock.d.ts +51 -106
  478. package/dist/utils/content-write-lock.js +66 -111
  479. package/dist/utils/debug.d.ts +7 -23
  480. package/dist/utils/debug.js +7 -23
  481. package/dist/utils/entry-url.d.ts +11 -23
  482. package/dist/utils/entry-url.js +11 -26
  483. package/dist/utils/error.d.ts +25 -90
  484. package/dist/utils/error.js +60 -147
  485. package/dist/utils/flatten-group-fields.d.ts +5 -7
  486. package/dist/utils/flatten-group-fields.js +5 -7
  487. package/dist/utils/format.d.ts +1 -5
  488. package/dist/utils/format.js +1 -5
  489. package/dist/utils/fs.d.ts +3 -4
  490. package/dist/utils/fs.js +3 -4
  491. package/dist/utils/git.d.ts +52 -83
  492. package/dist/utils/git.js +79 -125
  493. package/dist/utils/logger.d.ts +35 -50
  494. package/dist/utils/logger.js +35 -52
  495. package/dist/utils/provisioning-lock.d.ts +23 -35
  496. package/dist/utils/provisioning-lock.js +49 -69
  497. package/dist/utils/sanitize-href.d.ts +5 -10
  498. package/dist/utils/sanitize-href.js +8 -18
  499. package/dist/utils/title-field.d.ts +17 -20
  500. package/dist/utils/title-field.js +18 -27
  501. package/dist/utils/typed-filename.d.ts +20 -48
  502. package/dist/utils/typed-filename.js +25 -61
  503. package/dist/utils/url-prefix.d.ts +3 -3
  504. package/dist/utils/url-prefix.js +3 -3
  505. package/dist/validation/block-structural-keys.d.ts +16 -31
  506. package/dist/validation/block-structural-keys.js +19 -29
  507. package/dist/validation/deletion-checker.d.ts +0 -34
  508. package/dist/validation/deletion-checker.js +1 -43
  509. package/dist/validation/entry-link-validator.d.ts +6 -13
  510. package/dist/validation/entry-link-validator.js +4 -13
  511. package/dist/validation/entry-type-reference-validator.d.ts +13 -18
  512. package/dist/validation/entry-type-reference-validator.js +13 -18
  513. package/dist/validation/entry-validator.d.ts +13 -25
  514. package/dist/validation/entry-validator.js +15 -32
  515. package/dist/validation/field-traversal.d.ts +3 -30
  516. package/dist/validation/field-traversal.js +1 -32
  517. package/dist/validation/reference-validator.d.ts +5 -24
  518. package/dist/validation/reference-validator.js +5 -30
  519. package/dist/worker/cms-worker.d.ts +172 -232
  520. package/dist/worker/cms-worker.js +241 -333
  521. package/dist/worker/git-sync.d.ts +32 -133
  522. package/dist/worker/git-sync.js +129 -191
  523. package/dist/worker/github-auth.d.ts +13 -19
  524. package/dist/worker/github-auth.js +13 -19
  525. package/dist/worker/history-rewrite.d.ts +53 -66
  526. package/dist/worker/history-rewrite.js +54 -60
  527. package/dist/worker/log.d.ts +24 -41
  528. package/dist/worker/log.js +25 -42
  529. package/dist/worker/rebase.d.ts +20 -110
  530. package/dist/worker/rebase.js +279 -354
  531. package/dist/worker/task-runner.d.ts +32 -66
  532. package/dist/worker/task-runner.js +126 -162
  533. package/dist/worker/worker-context.d.ts +41 -81
  534. package/package.json +4 -4
  535. package/dist/cli/template-files/middleware-clerk.ts.template +0 -37
  536. package/dist/worker/task-queue-config.d.ts +0 -8
  537. package/dist/worker/task-queue.js +0 -19
  538. package/dist/worker/worker-status.d.ts +0 -47
  539. package/dist/worker/worker-status.js +0 -52
@@ -4,49 +4,31 @@
4
4
  *
5
5
  * This is deliberately a *different* transform from `stripMdxImports`
6
6
  * (strip-mdx.ts): that one is tuned for AI/RAG consumption and intentionally
7
- * leaves JSX components intact, because their props often carry semantic
8
- * data a model can use. `toPlainText` has the opposite goal — it removes ALL
9
- * markup (JSX tags, JSX expressions, markdown syntax) and keeps only the
10
- * prose, so **paired custom components lose their tags but keep their
11
- * children's text**. That distinction is the whole reason this function
12
- * exists: a hand-rolled plaintext stripper that treats a paired component
13
- * like `<Callout>...</Callout>` as one opaque unit and deletes it wholesale
14
- * silently drops every word inside it from the search index. `toPlainText`
15
- * strips the `<Callout>`/`</Callout>` delimiters but keeps the sentence
16
- * between them.
7
+ * leaves JSX components intact. `toPlainText` has the opposite goal — it
8
+ * removes ALL markup (JSX tags, JSX expressions, markdown syntax) and keeps
9
+ * only the prose, so **paired custom components lose their tags but keep
10
+ * their children's text**: deleting a `<Callout>...</Callout>` wholesale
11
+ * would silently drop every word inside it from the search index.
17
12
  *
18
13
  * Pipeline (each step operates on the previous step's output):
19
14
  * 1. Strip YAML frontmatter (via `gray-matter`, the same parser
20
15
  * `content-store.ts` uses for `.md`/`.mdx` bodies).
21
16
  * 2. Strip `import`/`export` statements (via `stripMdxImports`), which also
22
17
  * protects fenced code blocks from every later step.
23
- * 3. Mask fenced code blocks and inline code spans, capturing their content
24
- * (fence markers / backticks are discarded, the code text is kept).
25
- * 4. Strip JSX/HTML tags — opening, closing, and self-closing — leaving
26
- * whatever text sits between them in place. This is a single global
27
- * replace, not a matched-pair walk: because we never need the tag name or
28
- * the children as a unit (unlike `applyComponentTransforms`, which calls
29
- * an adopter transform per component), deleting every tag occurrence and
30
- * leaving the surrounding text untouched handles nesting for free.
18
+ * 3. Mask fenced code blocks and inline code spans, capturing their content.
19
+ * 4. Strip JSX/HTML tags via a single global replace (see `TAG_RE` below).
31
20
  * 5. Strip JSX expressions (`{...}`, including nested braces) — these are
32
21
  * code, not prose.
33
- * 6. Strip common Markdown syntax: headings, emphasis/strikethrough, links
34
- * (keep the link text, drop the URL), images (keep alt text), blockquote
35
- * markers, list markers, and thematic breaks.
22
+ * 6. Strip common Markdown syntax (see `stripMarkdownSyntax` below).
36
23
  * 7. Restore the masked code from step 3 as plain text.
37
24
  * 8. Collapse whitespace: trim each line, collapse runs of blank lines,
38
- * trim the result. Paragraph breaks (single blank lines) are preserved —
39
- * this does not flatten the output to one line.
25
+ * trim the result. Paragraph breaks (single blank lines) are preserved.
40
26
  */
41
27
  /**
42
28
  * Convert MDX/Markdown body content to plain prose text.
43
29
  *
44
30
  * See the module doc above for the full pipeline and why this exists as a
45
- * distinct transform from `stripMdxImports`. In short: frontmatter, code
46
- * fences, inline code, JSX tags/expressions, and Markdown syntax are all
47
- * stripped down to their human-readable text — code content and link/image
48
- * text are kept, everything else is discarded. Paired custom components
49
- * lose only their tags; the prose between them survives.
31
+ * distinct transform from `stripMdxImports`.
50
32
  *
51
33
  * HTML/MDX comments (`<!-- ... -->`) are removed along with their contents:
52
34
  * an authoring note is text the author marked as not-for-readers, so it does
@@ -4,39 +4,25 @@
4
4
  *
5
5
  * This is deliberately a *different* transform from `stripMdxImports`
6
6
  * (strip-mdx.ts): that one is tuned for AI/RAG consumption and intentionally
7
- * leaves JSX components intact, because their props often carry semantic
8
- * data a model can use. `toPlainText` has the opposite goal — it removes ALL
9
- * markup (JSX tags, JSX expressions, markdown syntax) and keeps only the
10
- * prose, so **paired custom components lose their tags but keep their
11
- * children's text**. That distinction is the whole reason this function
12
- * exists: a hand-rolled plaintext stripper that treats a paired component
13
- * like `<Callout>...</Callout>` as one opaque unit and deletes it wholesale
14
- * silently drops every word inside it from the search index. `toPlainText`
15
- * strips the `<Callout>`/`</Callout>` delimiters but keeps the sentence
16
- * between them.
7
+ * leaves JSX components intact. `toPlainText` has the opposite goal — it
8
+ * removes ALL markup (JSX tags, JSX expressions, markdown syntax) and keeps
9
+ * only the prose, so **paired custom components lose their tags but keep
10
+ * their children's text**: deleting a `<Callout>...</Callout>` wholesale
11
+ * would silently drop every word inside it from the search index.
17
12
  *
18
13
  * Pipeline (each step operates on the previous step's output):
19
14
  * 1. Strip YAML frontmatter (via `gray-matter`, the same parser
20
15
  * `content-store.ts` uses for `.md`/`.mdx` bodies).
21
16
  * 2. Strip `import`/`export` statements (via `stripMdxImports`), which also
22
17
  * protects fenced code blocks from every later step.
23
- * 3. Mask fenced code blocks and inline code spans, capturing their content
24
- * (fence markers / backticks are discarded, the code text is kept).
25
- * 4. Strip JSX/HTML tags — opening, closing, and self-closing — leaving
26
- * whatever text sits between them in place. This is a single global
27
- * replace, not a matched-pair walk: because we never need the tag name or
28
- * the children as a unit (unlike `applyComponentTransforms`, which calls
29
- * an adopter transform per component), deleting every tag occurrence and
30
- * leaving the surrounding text untouched handles nesting for free.
18
+ * 3. Mask fenced code blocks and inline code spans, capturing their content.
19
+ * 4. Strip JSX/HTML tags via a single global replace (see `TAG_RE` below).
31
20
  * 5. Strip JSX expressions (`{...}`, including nested braces) — these are
32
21
  * code, not prose.
33
- * 6. Strip common Markdown syntax: headings, emphasis/strikethrough, links
34
- * (keep the link text, drop the URL), images (keep alt text), blockquote
35
- * markers, list markers, and thematic breaks.
22
+ * 6. Strip common Markdown syntax (see `stripMarkdownSyntax` below).
36
23
  * 7. Restore the masked code from step 3 as plain text.
37
24
  * 8. Collapse whitespace: trim each line, collapse runs of blank lines,
38
- * trim the result. Paragraph breaks (single blank lines) are preserved —
39
- * this does not flatten the output to one line.
25
+ * trim the result. Paragraph breaks (single blank lines) are preserved.
40
26
  */
41
27
  import matter from 'gray-matter';
42
28
  import { stripMdxImports } from './strip-mdx.js';
@@ -271,11 +257,7 @@ function collapseWhitespace(text) {
271
257
  * Convert MDX/Markdown body content to plain prose text.
272
258
  *
273
259
  * See the module doc above for the full pipeline and why this exists as a
274
- * distinct transform from `stripMdxImports`. In short: frontmatter, code
275
- * fences, inline code, JSX tags/expressions, and Markdown syntax are all
276
- * stripped down to their human-readable text — code content and link/image
277
- * text are kept, everything else is discarded. Paired custom components
278
- * lose only their tags; the prose between them survives.
260
+ * distinct transform from `stripMdxImports`.
279
261
  *
280
262
  * HTML/MDX comments (`<!-- ... -->`) are removed along with their contents:
281
263
  * an authoring note is text the author marked as not-for-readers, so it does
@@ -14,13 +14,11 @@ import type { ComponentProps, ComponentTransforms } from './types.js';
14
14
  * Parse JSX attribute string into a props object.
15
15
  *
16
16
  * Handles: `key="value"`, `key='value'`, `key={expr}`, and boolean `key` (→ "true").
17
+ * @internal Exported for tests.
17
18
  */
18
19
  export declare function parseComponentProps(attrString: string): ComponentProps;
19
20
  /**
20
- * Apply component transforms to a body string.
21
- *
22
21
  * For each registered component name, finds JSX tags in the body and calls
23
- * the corresponding transform function. Processes via convergence loop to
24
- * handle nesting (inner components first, outer on subsequent passes).
22
+ * the corresponding transform function.
25
23
  */
26
24
  export declare function applyComponentTransforms(body: string, transforms: ComponentTransforms): string;
@@ -13,12 +13,12 @@
13
13
  * Parse JSX attribute string into a props object.
14
14
  *
15
15
  * Handles: `key="value"`, `key='value'`, `key={expr}`, and boolean `key` (→ "true").
16
+ * @internal Exported for tests.
16
17
  */
17
18
  export function parseComponentProps(attrString) {
18
19
  const props = {};
19
20
  if (!attrString)
20
21
  return props;
21
- // Match attribute patterns: name="value", name='value', name={expr}, or bare name
22
22
  // eslint-disable-next-line security/detect-unsafe-regex
23
23
  const attrRegex = /(\w+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|\{([^}]*)\}))?/g;
24
24
  let match;
@@ -30,10 +30,6 @@ export function parseComponentProps(attrString) {
30
30
  }
31
31
  return props;
32
32
  }
33
- /**
34
- * Mask fenced code blocks so component transforms don't touch them.
35
- * Returns the masked string and a restore function.
36
- */
37
33
  /** Regex fragment matching JSX attribute content, skipping quoted strings containing '>'. */
38
34
  const ATTR_CONTENT = `(?:[^>"']|"[^"]*"|'[^']*')*`;
39
35
  const BLOCK_PREFIX = '<<CODEBLOCK';
@@ -50,12 +46,12 @@ function isFenceCloseLine(line, marker) {
50
46
  }
51
47
  /**
52
48
  * Mask fenced code blocks (` ``` `/`~~~`), capturing each block's raw text (fence lines
53
- * included) exactly as `maskCodeBlocks` used to via `/^(```|~~~).*\n[\s\S]*?\n\1\s*$/gm`.
49
+ * included).
54
50
  *
55
- * A hand-rolled line scan, not that regex: it is a polynomial-ReDoS shape (measured ~9s on
56
- * ~530KB of body text with many unclosed fence openers — an ordinary authoring accident, not a
57
- * crafted payload) that CodeQL and three review rounds both missed elsewhere in this package
58
- * (see `ai/to-plain-text.ts`'s identical fix). The lazy `[\s\S]*?` has no bound on how far it
51
+ * A hand-rolled line scan, not a lazy regex like `/^(```|~~~).*\n[\s\S]*?\n\1\s*$/gm`: that
52
+ * shape is a polynomial-ReDoS hazard (measured ~9s on ~530KB of body text with many unclosed
53
+ * fence openers — an ordinary authoring accident, not a crafted payload; see
54
+ * `ai/to-plain-text.ts`'s identical fix). The lazy `[\s\S]*?` has no bound on how far it
59
55
  * must scan looking for a closing `\1` that, for an unclosed fence, never arrives — it exhausts
60
56
  * to the end of the string before giving up on that starting line, and `/gm` retries the same
61
57
  * exhaustive scan at every subsequent fence-opener line.
@@ -118,9 +114,8 @@ function maskFencedCodeBlocks(body, blocks) {
118
114
  function maskCodeBlocks(body) {
119
115
  const blocks = [];
120
116
  const inlines = [];
121
- // 1. Mask fenced code blocks
122
117
  let masked = maskFencedCodeBlocks(body, blocks);
123
- // 2. Mask inline code spans (double-backtick first, then single-backtick)
118
+ // Mask inline code spans (double-backtick first, then single-backtick)
124
119
  masked = masked.replace(/``[^`]+``|`[^`]+`/g, (span) => {
125
120
  const idx = inlines.length;
126
121
  inlines.push(span);
@@ -137,17 +132,13 @@ function maskCodeBlocks(body) {
137
132
  };
138
133
  }
139
134
  /**
140
- * Apply component transforms to a body string.
141
- *
142
135
  * For each registered component name, finds JSX tags in the body and calls
143
- * the corresponding transform function. Processes via convergence loop to
144
- * handle nesting (inner components first, outer on subsequent passes).
136
+ * the corresponding transform function.
145
137
  */
146
138
  export function applyComponentTransforms(body, transforms) {
147
139
  const names = Object.keys(transforms);
148
140
  if (names.length === 0)
149
141
  return body;
150
- // Mask code blocks to protect them from transformation
151
142
  const { masked, restore } = maskCodeBlocks(body);
152
143
  let result = masked;
153
144
  const MAX_PASSES = 10;
@@ -175,7 +166,6 @@ export function applyComponentTransforms(body, transforms) {
175
166
  const openStart = openMatch.index;
176
167
  const openEnd = openStart + openMatch[0].length;
177
168
  const attrStr = openMatch[1]?.trim() ?? '';
178
- // Find matching close tag, accounting for nesting
179
169
  const closeTag = `</${name}>`;
180
170
  const closeIdx = findMatchingClose(result, openEnd, name, closeTag);
181
171
  if (closeIdx === -1)
@@ -207,7 +197,6 @@ export function applyComponentTransforms(body, transforms) {
207
197
  function findMatchingClose(body, startFrom, name, closeTag) {
208
198
  let depth = 1;
209
199
  const pos = startFrom;
210
- // Regex to find either an opening or closing tag for this component
211
200
  // eslint-disable-next-line security/detect-non-literal-regexp
212
201
  const tagRegex = new RegExp(`<${escapeRegex(name)}(?:\\s${ATTR_CONTENT})?>|<${escapeRegex(name)}(?:\\s${ATTR_CONTENT})?\\s*/>|${escapeRegex(closeTag)}`, 'g');
213
202
  tagRegex.lastIndex = pos;
@@ -216,16 +216,11 @@ export interface AIManifestBundle {
216
216
  /** Top-level manifest for AI content */
217
217
  export interface AIManifest {
218
218
  /**
219
- * When this content was generated, ISO-8601.
220
- *
221
- * OPTIONAL, and absent whenever the manifest carries a `buildId` and no usable
222
- * `SOURCE_DATE_EPOCH` (unset, blank, or malformed — a rejected value does not fall back to a
223
- * live clock, it leaves the field absent):
224
- * under build-once-promote one artifact is built once and may be served months later, so a
225
- * build clock describes the runner that produced it rather than the content, and anything
226
- * reading it as "how fresh is this?" is misled by design. An adopter who has declared a build
227
- * id has told us the date is not the identifying fact, so it is omitted rather than filled in
228
- * with something arbitrary. Present unconditionally when neither env var is set.
219
+ * When this content was generated, ISO-8601. Absent when the manifest carries a `buildId`
220
+ * and no usable `SOURCE_DATE_EPOCH` (unset, blank, or malformed values are never replaced
221
+ * with a live clock): under build-once-promote a build clock describes the runner, not the
222
+ * content, and is misleading read as freshness once `buildId` says the artifact — not the
223
+ * date — is the identifying fact. Present unconditionally when neither env var is set.
229
224
  */
230
225
  generated?: string;
231
226
  /**
@@ -19,13 +19,13 @@ export interface BranchHealthData {
19
19
  }
20
20
  /** Response type for GET /admin/branch-health */
21
21
  export type BranchHealthResponse = ApiResponse<BranchHealthData>;
22
- export interface PurgeBranchDirData {
22
+ interface PurgeBranchDirData {
23
23
  /** The dot-prefixed name the directory was renamed to, e.g. `.trash-foo-20260101T000000Z`. */
24
24
  trashedAs: string;
25
25
  }
26
26
  /** Response type for POST /admin/branch-dirs/:dirName/purge */
27
27
  export type PurgeBranchDirResponse = ApiResponse<PurgeBranchDirData>;
28
- export interface RepairBranchDirData {
28
+ interface RepairBranchDirData {
29
29
  branch: BranchMetadata;
30
30
  /** The archived corrupt file's name, e.g. `branch.json.corrupt-20260101T000000Z`. */
31
31
  archivedAs: string;
@@ -48,26 +48,18 @@ export interface RepairBranchDirData {
48
48
  }
49
49
  /** Response type for POST /admin/branch-dirs/:dirName/repair-metadata */
50
50
  export type RepairBranchDirResponse = ApiResponse<RepairBranchDirData>;
51
- export interface RepairedContentDuplicate {
51
+ interface RepairedContentDuplicate {
52
52
  id: string;
53
53
  /** The path that was kept (the deterministic winner) -- untouched by this repair. */
54
54
  keptPath: string;
55
55
  /** Archived names the quarantined duplicate(s) were renamed to, dot-prefixed so future scans skip them. */
56
56
  archivedAs: string[];
57
57
  }
58
- export interface RepairContentDuplicatesData {
58
+ interface RepairContentDuplicatesData {
59
59
  resolved: RepairedContentDuplicate[];
60
60
  }
61
61
  /** Response type for POST /admin/branch-dirs/:dirName/repair-content-duplicates */
62
62
  export type RepairContentDuplicatesResponse = ApiResponse<RepairContentDuplicatesData>;
63
- declare const branchDirParamsSchema: z.ZodObject<{
64
- dirName: z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
65
- }, "strip", z.ZodTypeAny, {
66
- dirName: string;
67
- }, {
68
- dirName: string;
69
- }>;
70
- export type BranchDirParams = z.infer<typeof branchDirParamsSchema>;
71
63
  /**
72
64
  * Exported routes, merged into ADMIN_ROUTES in admin.ts for a single
73
65
  * router/generate-client import.
@@ -15,7 +15,7 @@ import { z } from 'zod';
15
15
  import { simpleGit } from 'simple-git';
16
16
  import { BranchMetadataFileManager, getBranchMetadataFileManager } from '../branch-metadata.js';
17
17
  // Same constants the reader uses, rather than a second copy of the two string
18
- // literals -- they were declared independently here until 2026-08-23.
18
+ // literals.
19
19
  import { BRANCH_META_DIR, BRANCH_META_FILE } from '../branch-metadata-file.js';
20
20
  import { scanBranchHealth } from '../branch-health.js';
21
21
  import { ContentIdIndex } from '../content-id-index.js';
@@ -26,16 +26,10 @@ import { tryAcquireProvisioningLock } from '../utils/provisioning-lock.js';
26
26
  import { withContentWriteLock, ContentWriteLockBusyError, DEFAULT_CONTENT_WRITE_LOCK_WAIT_MS, } from '../utils/content-write-lock.js';
27
27
  import { getErrorMessage, isNodeError, isNotFoundError } from '../utils/error.js';
28
28
  import { defineEndpoint } from './route-builder.js';
29
- // ============================================================================
30
- // Constants
31
- // ============================================================================
32
29
  /** [H1] A fresh (< 5 min old) init lock blocks purge -- provisioning may be running. */
33
30
  const PROVISIONING_LOCK_FRESH_MS = 5 * 60_000;
34
31
  /** An orphan dir younger than this may still be a clone in progress; corrupt dirs are exempt. */
35
32
  const ORPHAN_YOUTH_THRESHOLD_MS = 15 * 60_000;
36
- // ============================================================================
37
- // Zod schemas
38
- // ============================================================================
39
33
  // Mirrors deleteTaskHandler's fileName pattern in admin.ts: conservative
40
34
  // charset plus explicit traversal/dot-prefix refinements (the regex alone
41
35
  // technically excludes '/' already, but the refinements keep intent explicit
@@ -46,9 +40,6 @@ const dirNameSchema = z
46
40
  .refine((v) => !v.includes('..'), { message: 'dirName must not contain ..' })
47
41
  .refine((v) => !v.startsWith('.'), { message: 'dirName must not be dot-prefixed' });
48
42
  const branchDirParamsSchema = z.object({ dirName: dirNameSchema });
49
- // ============================================================================
50
- // Shared helpers
51
- // ============================================================================
52
43
  /** Compact UTC stamp for trash/archive names: `YYYYMMDDTHHMMSSZ` (no colons -- portability). */
53
44
  function formatTrashStamp(date) {
54
45
  return date
@@ -77,9 +68,6 @@ class RepairPreconditionError extends Error {
77
68
  this.status = status;
78
69
  }
79
70
  }
80
- // ============================================================================
81
- // Handlers
82
- // ============================================================================
83
71
  const getBranchHealthHandler = async (_gc, ctx, _req) => {
84
72
  // Same derivation services.ts uses to construct the BranchRegistry --
85
73
  // admin handlers must agree with it or the scan silently looks at the
@@ -105,7 +93,7 @@ const getBranchHealthHandler = async (_gc, ctx, _req) => {
105
93
  * sweeps trash older than 30 days, see cleanupTrashedBranchDirs in
106
94
  * worker/rebase.ts).
107
95
  *
108
- * Safety rails (see the PR's design review for the finding IDs):
96
+ * Safety rails:
109
97
  * - [always] the base branch directory can never be purged.
110
98
  * - Server re-derives live/corrupt/orphan state itself -- never trusts the
111
99
  * client's view of the world.
@@ -131,7 +119,7 @@ const purgeBranchDirHandler = async (_gc, ctx, _req, params) => {
131
119
  if (!dirPath) {
132
120
  return { ok: false, status: 400, error: 'Invalid directory name' };
133
121
  }
134
- // [MEDIUM-1 rider] The directory must actually exist -- otherwise
122
+ // The directory must actually exist -- otherwise
135
123
  // withOccFileLock's `mkdir -p` below would CREATE it, and purge would
136
124
  // "succeed" with a phantom `.trash-*` entry for a directory that was
137
125
  // never there. Must run before anything below treats "no branch.json" as
@@ -238,50 +226,29 @@ const purgeBranchDirHandler = async (_gc, ctx, _req, params) => {
238
226
  };
239
227
  /**
240
228
  * Repair a corrupt branch.json by archiving it (forensics preserved as
241
- * `branch.json.corrupt-{STAMP}`, ignored by future scans since it doesn't
242
- * match the exact `branch.json` name) and recreating defaults via the
243
- * normal save() path. Unlike purge, the base branch IS a valid target here
244
- * -- a corrupt BASE branch.json is exactly the degraded-service scenario
245
- * this handler exists to fix.
229
+ * `branch.json.corrupt-{STAMP}`) and recreating defaults via save(). Unlike
230
+ * purge, the base branch IS a valid target -- a corrupt BASE branch.json is
231
+ * exactly the degraded-service scenario this handler exists to fix.
246
232
  *
247
- * [M4] Lock sequence: withOccFileLock is NOT reentrant, and save() takes it
248
- * internally, so the rename must happen and the lock must be RELEASED
249
- * (exiting the withOccFileLock callback) before save() runs -- calling
250
- * save() while still holding the lock would deadlock against itself.
233
+ * Lock sequence: withOccFileLock is NOT reentrant and save() takes its own
234
+ * hold, so the archive rename must complete and the lock must be RELEASED
235
+ * before save() runs, or save() would deadlock against itself. The
236
+ * provisioning lock stays held across the whole archive+save sequence, same
237
+ * order as purge (provisioning -> branch.json) so the two operations can
238
+ * never deadlock each other; without that hold, a concurrent purge could
239
+ * trash the directory mid-sequence and have save() resurrect a
240
+ * metadata-only ghost of it.
251
241
  *
252
- * The provisioning lock is held across the ENTIRE archive+save
253
- * sequence (acquired before withOccFileLock, released only after save()
254
- * completes), same lock order as purge (provisioning -> branch.json) so the
255
- * two can never deadlock against each other. Without this, a concurrent
256
- * purge could trash the directory in the window between this handler
257
- * releasing withOccFileLock (required before save(), per [M4] above) and
258
- * save() actually running -- save() would then resurrect a metadata-only
259
- * ghost of a directory purge just moved to trash.
260
- *
261
- * ## Reset, not recovered -- and why (August 2026 baseline review)
262
- *
263
- * save()'s defaults-merge sees no existing record once branch.json is
264
- * archived out of the way, so a `submitted` (write-locked) branch comes back
265
- * `editing` (unlocked), `access` ACLs are dropped to `{}`, and `createdBy`
266
- * becomes the ADMIN RUNNING THIS REPAIR, not the branch's real creator. This
267
- * handler deliberately does NOT attempt to recover those three fields from
268
- * the corrupt file, even though it is sometimes technically "partially
269
- * parseable" (e.g. valid JSON with a truncated tail, or a stray character
270
- * breaking otherwise-valid JSON): branch.json is written via
271
- * `writeOccJsonFile`, which is atomic (temp-file + rename/link, see
272
- * utils/occ-json-write.ts), so a genuinely corrupt file on disk is not
273
- * ordinary truncated-write debris -- it got that way some other, less
274
- * predictable way. `status`/`access` are security-adjacent (branch
275
- * protection and per-path ACLs); silently reinstating a best-effort guess
276
- * parsed out of a file that failed strict JSON.parse risks resurrecting
277
- * WRONG security state with no human review, which is worse than a clean,
278
- * clearly-reported reset. The archived file (`archivedAs`) is preserved
279
- * precisely so a human CAN recover the real values with full context (open
280
- * it, cross-check the GitHub PR, ask the editor) -- that is the safe
281
- * recovery path, not automation. What was missing before this fix was any
282
- * signal that a reset happened at all; the `reset` field on the response
283
- * closes that gap by always reporting the (new, defaulted) values for these
284
- * three fields, so the admin knows to re-apply the ACL and re-submit.
242
+ * Reset, not recovered: save()'s defaults-merge sees no existing record once
243
+ * branch.json is archived, so `status`/`access`/`createdBy` reset to
244
+ * `editing`/`{}`/the admin running this repair, even when the corrupt file
245
+ * is partially parseable. `status`/`access` are security-adjacent, and a
246
+ * genuinely corrupt branch.json (writes are atomic, so it didn't get that
247
+ * way from an ordinary truncated write) is not safe to best-effort-parse: a
248
+ * wrong guess with no human review is worse than a clean reset. The archived
249
+ * file lets a human recover the real values with full context instead. The
250
+ * response's `reset` field reports that a reset happened, so an admin never
251
+ * mistakes the new defaults for recovered data.
285
252
  */
286
253
  const repairBranchDirHandler = async (_gc, ctx, req, params) => {
287
254
  const baseRoot = getDefaultBranchBase(ctx.services.config.mode);
@@ -289,7 +256,7 @@ const repairBranchDirHandler = async (_gc, ctx, req, params) => {
289
256
  if (!dirPath) {
290
257
  return { ok: false, status: 400, error: 'Invalid directory name' };
291
258
  }
292
- // [MEDIUM-1 rider] Same stat guard as purge: the directory must actually
259
+ // Same stat guard as purge: the directory must actually
293
260
  // exist, otherwise withOccFileLock's `mkdir -p` below would CREATE it.
294
261
  const dirExists = await fs
295
262
  .stat(dirPath)
@@ -522,12 +489,8 @@ const repairContentDuplicatesHandler = async (_gc, ctx, _req, params) => {
522
489
  };
523
490
  }
524
491
  };
525
- // ============================================================================
526
- // Route definitions
527
- // ============================================================================
528
492
  /**
529
493
  * Branch directory health scan (healthy/corrupt-metadata/orphan)
530
- * GET /admin/branch-health
531
494
  */
532
495
  const getBranchHealth = defineEndpoint({
533
496
  namespace: 'admin',
@@ -542,7 +505,6 @@ const getBranchHealth = defineEndpoint({
542
505
  });
543
506
  /**
544
507
  * Purge a corrupt-metadata or orphan branch directory (reversible trash-rename)
545
- * POST /admin/branch-dirs/:dirName/purge
546
508
  */
547
509
  const purgeBranchDir = defineEndpoint({
548
510
  namespace: 'admin',
@@ -558,7 +520,6 @@ const purgeBranchDir = defineEndpoint({
558
520
  });
559
521
  /**
560
522
  * Repair a corrupt branch.json by archiving it and recreating defaults
561
- * POST /admin/branch-dirs/:dirName/repair-metadata
562
523
  */
563
524
  const repairBranchDir = defineEndpoint({
564
525
  namespace: 'admin',
@@ -586,9 +547,8 @@ const repairBranchDir = defineEndpoint({
586
547
  /**
587
548
  * Repair duplicate content IDs in a healthy branch's content tree by
588
549
  * archiving the quarantined (losing) file(s) with a dot-prefixed name --
589
- * see content-id-index.ts's "Duplicate-ID quarantine" section and
550
+ * see the `ContentIdIndex` class doc and
590
551
  * repairContentDuplicatesHandler's doc comment.
591
- * POST /admin/branch-dirs/:dirName/repair-content-duplicates
592
552
  */
593
553
  const repairContentDuplicates = defineEndpoint({
594
554
  namespace: 'admin',
@@ -7,11 +7,11 @@
7
7
  */
8
8
  import { z } from 'zod';
9
9
  import type { ApiResponse } from './types.js';
10
- import type { Task, QueueStats, CorruptTaskFile } from '../worker/task-queue.js';
10
+ import type { Task, QueueStats, CorruptTaskFile } from '../task-queue/cms-task-queue.js';
11
11
  import type { WorkerStatusReport } from '../types.js';
12
12
  import type { OperatingMode } from '../operating-mode/index.js';
13
13
  export type { BranchHealthResponse, PurgeBranchDirResponse, RepairBranchDirResponse, RepairContentDuplicatesResponse, } from './admin-branch-health.js';
14
- export type WorkerLivenessState = 'alive' | 'stale' | 'absent';
14
+ type WorkerLivenessState = 'alive' | 'stale' | 'absent';
15
15
  export interface WorkerLiveness {
16
16
  /**
17
17
  * 'absent' — the lock dir is removed on clean release, so this also covers
@@ -40,12 +40,12 @@ export interface AdminTasksData {
40
40
  }
41
41
  /** Response type for GET /admin/tasks/:status */
42
42
  export type AdminTasksResponse = ApiResponse<AdminTasksData>;
43
- export interface AdminRetryTaskData {
43
+ interface AdminRetryTaskData {
44
44
  newTaskId: string;
45
45
  }
46
46
  /** Response type for POST /admin/tasks/:taskId/retry */
47
47
  export type AdminRetryTaskResponse = ApiResponse<AdminRetryTaskData>;
48
- export interface AdminDeleteTaskData {
48
+ interface AdminDeleteTaskData {
49
49
  deleted: true;
50
50
  }
51
51
  /** Response type for DELETE /admin/tasks/:status/:fileName */
@@ -61,14 +61,6 @@ declare const listAdminTasksParamsSchema: z.ZodObject<{
61
61
  limit?: number | undefined;
62
62
  }>;
63
63
  export type ListAdminTasksParams = z.infer<typeof listAdminTasksParamsSchema>;
64
- declare const retryTaskParamsSchema: z.ZodObject<{
65
- taskId: z.ZodString;
66
- }, "strip", z.ZodTypeAny, {
67
- taskId: string;
68
- }, {
69
- taskId: string;
70
- }>;
71
- export type RetryTaskParams = z.infer<typeof retryTaskParamsSchema>;
72
64
  declare const deleteTaskParamsSchema: z.ZodObject<{
73
65
  status: z.ZodEnum<["pending", "failed", "corrupt"]>;
74
66
  fileName: z.ZodEffects<z.ZodString, string, string>;
package/dist/api/admin.js CHANGED
@@ -8,23 +8,20 @@
8
8
  import fs from 'node:fs/promises';
9
9
  import path from 'node:path';
10
10
  import { z } from 'zod';
11
- import { getQueueStats, listTasks, listCorruptTaskFiles, requeueFailedTask, } from '../worker/task-queue.js';
12
- import { getTaskQueueDir } from '../worker/task-queue-config.js';
13
- import { WORKER_STATUS_FILE } from '../worker/worker-status.js';
11
+ import { getQueueStats, listTasks, listCorruptTaskFiles, requeueFailedTask, } from '../task-queue/cms-task-queue.js';
12
+ import { getTaskQueueDir } from '../task-queue/task-queue-config.js';
13
+ import { WORKER_STATUS_FILE } from '../task-queue/worker-status.js';
14
14
  import { defineEndpoint } from './route-builder.js';
15
15
  import { getErrorMessage, isNotFoundError } from '../utils/error.js';
16
16
  import { ADMIN_BRANCH_HEALTH_ROUTES } from './admin-branch-health.js';
17
- // ============================================================================
18
- // Worker lock liveness
19
- // ============================================================================
20
17
  /**
21
- * 60_000 = DEFAULT_LOCK_STALE_MS in worker/cms-worker.ts, hardcoded here
22
- * rather than imported/threaded through config: an adopter overriding
23
- * `lockStaleMs` on their worker will skew this classification (documented
24
- * limitation — the observability endpoint doesn't know the worker's actual
25
- * config). +90_000 absorbs the EFS/NFS attribute-cache staleness window: a
26
- * freshly-refreshed heartbeat can still appear up to ~60s old to a reader on
27
- * a different host, since NFS clients cache file attributes.
18
+ * 60_000 = DEFAULT_LOCK_STALE_MS in worker/cms-worker.ts, hardcoded rather
19
+ * than threaded through config: an adopter who overrides `lockStaleMs` skews
20
+ * this classification (the endpoint doesn't know the worker's actual
21
+ * config). +90_000 absorbs the EFS/NFS attribute-cache staleness window (see
22
+ * docs/concurrency.md's "Residual staleness windows" (A)), large enough that
23
+ * a freshly-refreshed heartbeat won't misreport as stale to a reader on a
24
+ * different host.
28
25
  */
29
26
  const LIVENESS_THRESHOLD_MS = 60_000 + 90_000;
30
27
  const DEFAULT_ADMIN_TASKS_LIMIT = 50;
@@ -103,9 +100,6 @@ async function getOldestPendingAgeMs(taskDir) {
103
100
  }
104
101
  return oldestMtimeMs === undefined ? undefined : Math.max(0, Date.now() - oldestMtimeMs);
105
102
  }
106
- // ============================================================================
107
- // Zod Schemas for Validation
108
- // ============================================================================
109
103
  const adminTaskStatusSchema = z.enum(['pending', 'processing', 'completed', 'failed', 'corrupt']);
110
104
  const listAdminTasksParamsSchema = z.object({
111
105
  status: adminTaskStatusSchema,
@@ -129,9 +123,6 @@ const deleteTaskParamsSchema = z.object({
129
123
  .regex(/^[A-Za-z0-9._-]{1,120}\.json$/)
130
124
  .refine((v) => !v.includes('..'), { message: 'fileName must not contain ..' }),
131
125
  });
132
- // ============================================================================
133
- // Handlers
134
- // ============================================================================
135
126
  const getAdminStatusHandler = async (_gc, ctx, _req) => {
136
127
  const taskDir = getTaskQueueDir(ctx.services.config);
137
128
  try {
@@ -248,12 +239,8 @@ const deleteTaskHandler = async (_gc, ctx, _req, params) => {
248
239
  return { ok: false, status: 500, error: getErrorMessage(err) };
249
240
  }
250
241
  };
251
- // ============================================================================
252
- // Route Definitions with defineEndpoint
253
- // ============================================================================
254
242
  /**
255
243
  * Task queue stats + worker liveness snapshot
256
- * GET /admin/status
257
244
  */
258
245
  const getAdminStatus = defineEndpoint({
259
246
  namespace: 'admin',
@@ -274,7 +261,6 @@ const getAdminStatus = defineEndpoint({
274
261
  });
275
262
  /**
276
263
  * List task files for a given status (or quarantined corrupt/ files)
277
- * GET /admin/tasks/:status
278
264
  */
279
265
  const listAdminTasks = defineEndpoint({
280
266
  namespace: 'admin',
@@ -290,7 +276,6 @@ const listAdminTasks = defineEndpoint({
290
276
  });
291
277
  /**
292
278
  * Requeue a failed task as a fresh pending task
293
- * POST /admin/tasks/:taskId/retry
294
279
  */
295
280
  const retryTask = defineEndpoint({
296
281
  namespace: 'admin',
@@ -306,7 +291,6 @@ const retryTask = defineEndpoint({
306
291
  });
307
292
  /**
308
293
  * Delete a task file from pending/, failed/, or corrupt/
309
- * DELETE /admin/tasks/:status/:fileName
310
294
  */
311
295
  const deleteTask = defineEndpoint({
312
296
  namespace: 'admin',