canopycms 0.0.68-int.98 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (688) hide show
  1. package/CHANGELOG.md +2131 -0
  2. package/README.md +47 -63
  3. package/dist/ai/generate.d.ts +5 -0
  4. package/dist/ai/generate.js +244 -115
  5. package/dist/ai/index.d.ts +1 -1
  6. package/dist/ai/json-to-markdown.d.ts +21 -1
  7. package/dist/ai/json-to-markdown.js +120 -57
  8. package/dist/ai/references.d.ts +72 -0
  9. package/dist/ai/references.js +223 -0
  10. package/dist/ai/resolve-branch.js +9 -2
  11. package/dist/ai/to-plain-text.d.ts +17 -8
  12. package/dist/ai/to-plain-text.js +18 -15
  13. package/dist/ai/types.d.ts +84 -3
  14. package/dist/api/admin-branch-health.d.ts +24 -1
  15. package/dist/api/admin-branch-health.js +52 -20
  16. package/dist/api/admin.d.ts +23 -5
  17. package/dist/api/admin.js +36 -1
  18. package/dist/api/assets.js +88 -78
  19. package/dist/api/branch-create-window.d.ts +12 -0
  20. package/dist/api/branch-create-window.js +13 -0
  21. package/dist/api/branch-merge.d.ts +1 -1
  22. package/dist/api/branch-merge.js +1 -1
  23. package/dist/api/branch-review.d.ts +3 -3
  24. package/dist/api/branch-review.js +16 -7
  25. package/dist/api/branch-status.d.ts +16 -6
  26. package/dist/api/branch-status.js +57 -12
  27. package/dist/api/branch-withdraw.d.ts +2 -2
  28. package/dist/api/branch-withdraw.js +8 -3
  29. package/dist/api/branch.d.ts +25 -12
  30. package/dist/api/branch.js +164 -103
  31. package/dist/api/client.d.ts +78 -58
  32. package/dist/api/client.js +150 -117
  33. package/dist/api/comments.d.ts +12 -3
  34. package/dist/api/comments.js +118 -9
  35. package/dist/api/content.d.ts +9 -9
  36. package/dist/api/content.js +131 -22
  37. package/dist/api/entries-constants.d.ts +14 -3
  38. package/dist/api/entries-constants.js +14 -3
  39. package/dist/api/entries.d.ts +40 -2
  40. package/dist/api/entries.js +102 -6
  41. package/dist/api/github-sync.d.ts +19 -0
  42. package/dist/api/github-sync.js +50 -3
  43. package/dist/api/groups.d.ts +4 -4
  44. package/dist/api/groups.js +2 -1
  45. package/dist/api/guards.js +23 -3
  46. package/dist/api/index.d.ts +3 -1
  47. package/dist/api/index.js +1 -0
  48. package/dist/api/permissions.d.ts +21 -2
  49. package/dist/api/permissions.js +50 -3
  50. package/dist/api/request-deadline.d.ts +59 -0
  51. package/dist/api/request-deadline.js +73 -0
  52. package/dist/api/resolve-references.js +8 -7
  53. package/dist/api/route-builder.d.ts +14 -0
  54. package/dist/api/route-builder.js +14 -1
  55. package/dist/api/schema.d.ts +11 -9
  56. package/dist/api/schema.js +2 -0
  57. package/dist/api/settings-helpers.d.ts +5 -1
  58. package/dist/api/settings-helpers.js +10 -2
  59. package/dist/api/types.d.ts +18 -0
  60. package/dist/api/users-constants.d.ts +6 -0
  61. package/dist/api/users-constants.js +6 -0
  62. package/dist/assets/asset-url.d.ts +28 -16
  63. package/dist/assets/asset-url.js +51 -25
  64. package/dist/assets/finalize.js +3 -0
  65. package/dist/assets/index.d.ts +1 -1
  66. package/dist/assets/materialize.d.ts +153 -0
  67. package/dist/assets/materialize.js +402 -0
  68. package/dist/assets/store-local.d.ts +19 -5
  69. package/dist/assets/store-local.js +69 -10
  70. package/dist/assets/store-s3.d.ts +38 -7
  71. package/dist/assets/store-s3.js +128 -22
  72. package/dist/assets/transform-directives.d.ts +52 -13
  73. package/dist/assets/transform-directives.js +87 -27
  74. package/dist/assets/transform.d.ts +3 -3
  75. package/dist/assets/transform.js +13 -8
  76. package/dist/assets/types.d.ts +31 -4
  77. package/dist/auth/cache.d.ts +1 -1
  78. package/dist/auth/cache.js +1 -1
  79. package/dist/auth/caching-auth-plugin.d.ts +2 -0
  80. package/dist/auth/caching-auth-plugin.js +12 -2
  81. package/dist/auth/file-based-auth-cache.d.ts +8 -0
  82. package/dist/auth/file-based-auth-cache.js +18 -8
  83. package/dist/auth/person-name.d.ts +5 -0
  84. package/dist/auth/person-name.js +8 -0
  85. package/dist/auth/plugin.d.ts +10 -1
  86. package/dist/auth/types.d.ts +2 -0
  87. package/dist/auth/user-metadata-lookup.d.ts +21 -0
  88. package/dist/auth/user-metadata-lookup.js +116 -0
  89. package/dist/authorization/branch.d.ts +1 -1
  90. package/dist/authorization/branch.js +12 -13
  91. package/dist/authorization/groups/schema.d.ts +4 -4
  92. package/dist/authorization/helpers.d.ts +8 -0
  93. package/dist/authorization/helpers.js +8 -0
  94. package/dist/authorization/index.d.ts +1 -1
  95. package/dist/authorization/index.js +1 -1
  96. package/dist/authorization/protected-branch.d.ts +5 -4
  97. package/dist/authorization/protected-branch.js +7 -5
  98. package/dist/branch-health.d.ts +35 -8
  99. package/dist/branch-health.js +54 -18
  100. package/dist/branch-metadata-error.d.ts +27 -0
  101. package/dist/branch-metadata-error.js +23 -0
  102. package/dist/branch-metadata-file.d.ts +205 -24
  103. package/dist/branch-metadata-file.js +126 -25
  104. package/dist/branch-metadata.d.ts +45 -6
  105. package/dist/branch-metadata.js +142 -50
  106. package/dist/branch-provisioning.d.ts +167 -0
  107. package/dist/branch-provisioning.js +501 -0
  108. package/dist/branch-registry.d.ts +8 -0
  109. package/dist/branch-registry.js +61 -9
  110. package/dist/branch-schema-cache.d.ts +29 -12
  111. package/dist/branch-schema-cache.js +64 -21
  112. package/dist/branch-sparse.d.ts +23 -0
  113. package/dist/branch-sparse.js +118 -0
  114. package/dist/branch-workspace.d.ts +42 -3
  115. package/dist/branch-workspace.js +239 -100
  116. package/dist/build/asset-refs.d.ts +94 -0
  117. package/dist/build/asset-refs.js +267 -0
  118. package/dist/build/generate-ai-content.js +5 -0
  119. package/dist/build/inline-flight.d.ts +37 -0
  120. package/dist/build/inline-flight.js +142 -0
  121. package/dist/cli/asset-refs.d.ts +52 -0
  122. package/dist/cli/asset-refs.js +194 -0
  123. package/dist/cli/cli.d.ts +15 -1
  124. package/dist/cli/cli.js +8543 -3193
  125. package/dist/cli/configured-asset-store.d.ts +12 -0
  126. package/dist/cli/configured-asset-store.js +46 -0
  127. package/dist/cli/generate-ai-content.js +4244 -1072
  128. package/dist/cli/init.js +217 -126
  129. package/dist/cli/project-detect.d.ts +2 -0
  130. package/dist/cli/project-detect.js +2 -0
  131. package/dist/cli/template-files/Dockerfile.cms.template +13 -5
  132. package/dist/cli/template-files/cms-stack.ts.template +16 -13
  133. package/dist/client.d.ts +1 -2
  134. package/dist/client.js +1 -2
  135. package/dist/comment-store.d.ts +25 -0
  136. package/dist/comment-store.js +43 -8
  137. package/dist/config/flatten.js +2 -0
  138. package/dist/config/helpers.js +2 -2
  139. package/dist/config/index.d.ts +1 -1
  140. package/dist/config/schemas/config.d.ts +12 -29
  141. package/dist/config/schemas/config.js +9 -12
  142. package/dist/config/schemas/field.d.ts +3 -0
  143. package/dist/config/schemas/field.js +58 -4
  144. package/dist/config/schemas/media.d.ts +4 -13
  145. package/dist/config/schemas/media.js +5 -8
  146. package/dist/config/schemas/url.d.ts +2 -20
  147. package/dist/config/schemas/url.js +2 -25
  148. package/dist/config/types.d.ts +116 -22
  149. package/dist/config/types.js +3 -9
  150. package/dist/config/validation.d.ts +25 -4
  151. package/dist/config/validation.js +116 -3
  152. package/dist/content-id-index.js +2 -2
  153. package/dist/content-index-generation.d.ts +1 -1
  154. package/dist/content-index-generation.js +1 -1
  155. package/dist/content-listing.d.ts +10 -1
  156. package/dist/content-listing.js +22 -5
  157. package/dist/content-reader.d.ts +9 -0
  158. package/dist/content-reader.js +16 -11
  159. package/dist/content-store.d.ts +75 -12
  160. package/dist/content-store.js +249 -86
  161. package/dist/content-tree.js +2 -2
  162. package/dist/context.js +5 -2
  163. package/dist/dangling-reference-log.d.ts +17 -0
  164. package/dist/dangling-reference-log.js +29 -0
  165. package/dist/dev-content-watcher.d.ts +1 -1
  166. package/dist/dev-content-watcher.js +1 -1
  167. package/dist/editor/BranchManager.d.ts +23 -7
  168. package/dist/editor/BranchManager.js +119 -54
  169. package/dist/editor/CanopyEditor.d.ts +1 -1
  170. package/dist/editor/CanopyEditor.js +1 -2
  171. package/dist/editor/CommentsPanel.d.ts +14 -0
  172. package/dist/editor/CommentsPanel.js +68 -43
  173. package/dist/editor/Editor.d.ts +11 -5
  174. package/dist/editor/Editor.js +891 -218
  175. package/dist/editor/EditorAuthGate.d.ts +7 -1
  176. package/dist/editor/EditorAuthGate.js +41 -9
  177. package/dist/editor/EntryNavigator.d.ts +22 -0
  178. package/dist/editor/EntryNavigator.js +353 -105
  179. package/dist/editor/FormHeader.d.ts +25 -0
  180. package/dist/editor/FormHeader.js +82 -0
  181. package/dist/editor/FormRenderer.d.ts +27 -3
  182. package/dist/editor/FormRenderer.js +171 -76
  183. package/dist/editor/PreviewFrame.d.ts +40 -0
  184. package/dist/editor/PreviewFrame.js +215 -0
  185. package/dist/editor/PreviewPane.d.ts +47 -0
  186. package/dist/editor/PreviewPane.js +147 -0
  187. package/dist/editor/PreviewToolbarTools.d.ts +22 -0
  188. package/dist/editor/PreviewToolbarTools.js +73 -0
  189. package/dist/editor/admin/SystemHealthPanel.d.ts +2 -1
  190. package/dist/editor/admin/SystemHealthPanel.js +163 -33
  191. package/dist/editor/admin/useSystemHealth.d.ts +18 -0
  192. package/dist/editor/admin/useSystemHealth.js +70 -1
  193. package/dist/editor/branch-status.d.ts +17 -0
  194. package/dist/editor/branch-status.js +29 -0
  195. package/dist/editor/canopy-path.d.ts +9 -6
  196. package/dist/editor/canopy-path.js +8 -11
  197. package/dist/editor/client-reference-resolver.d.ts +43 -16
  198. package/dist/editor/client-reference-resolver.js +155 -64
  199. package/dist/editor/comments/BranchComments.d.ts +1 -1
  200. package/dist/editor/comments/BranchComments.js +2 -2
  201. package/dist/editor/comments/CloseRefusedNotice.d.ts +4 -0
  202. package/dist/editor/comments/CloseRefusedNotice.js +7 -0
  203. package/dist/editor/comments/CommentThreadsPopover.d.ts +47 -0
  204. package/dist/editor/comments/CommentThreadsPopover.js +274 -0
  205. package/dist/editor/comments/CommentWriteAlert.d.ts +11 -0
  206. package/dist/editor/comments/CommentWriteAlert.js +13 -0
  207. package/dist/editor/comments/EntryComments.d.ts +10 -4
  208. package/dist/editor/comments/EntryComments.js +14 -17
  209. package/dist/editor/comments/FieldWrapper.d.ts +18 -4
  210. package/dist/editor/comments/FieldWrapper.js +62 -28
  211. package/dist/editor/comments/InlineCommentThread.d.ts +9 -2
  212. package/dist/editor/comments/InlineCommentThread.js +11 -47
  213. package/dist/editor/comments/ThreadCarousel.d.ts +1 -1
  214. package/dist/editor/comments/ThreadCarousel.js +18 -21
  215. package/dist/editor/comments/ThreadReplyControls.d.ts +28 -0
  216. package/dist/editor/comments/ThreadReplyControls.js +92 -0
  217. package/dist/editor/comments/field-comment-context.d.ts +14 -0
  218. package/dist/editor/comments/field-comment-context.js +14 -0
  219. package/dist/editor/comments/form-comments.d.ts +48 -0
  220. package/dist/editor/comments/form-comments.js +178 -0
  221. package/dist/editor/comments/item-anchor-copy.d.ts +6 -0
  222. package/dist/editor/comments/item-anchor-copy.js +6 -0
  223. package/dist/editor/comments/move-focus-if-unmoved.d.ts +6 -0
  224. package/dist/editor/comments/move-focus-if-unmoved.js +11 -0
  225. package/dist/editor/comments/popover-placement.d.ts +18 -0
  226. package/dist/editor/comments/popover-placement.js +58 -0
  227. package/dist/editor/comments/use-tracked-writes.d.ts +16 -0
  228. package/dist/editor/comments/use-tracked-writes.js +53 -0
  229. package/dist/editor/components/BranchAccessList.d.ts +15 -0
  230. package/dist/editor/components/BranchAccessList.js +52 -0
  231. package/dist/editor/components/BranchLockBanner.d.ts +22 -0
  232. package/dist/editor/components/BranchLockBanner.js +39 -0
  233. package/dist/editor/components/BranchPill.d.ts +32 -0
  234. package/dist/editor/components/BranchPill.js +33 -0
  235. package/dist/editor/components/BranchesDrawer.d.ts +11 -0
  236. package/dist/editor/components/BranchesDrawer.js +5 -0
  237. package/dist/editor/components/ConfirmDeleteModal.d.ts +6 -1
  238. package/dist/editor/components/ConfirmDeleteModal.js +3 -2
  239. package/dist/editor/components/DestructiveMenuItem.d.ts +7 -0
  240. package/dist/editor/components/DestructiveMenuItem.js +8 -0
  241. package/dist/editor/components/EditorCrashScreen.d.ts +17 -0
  242. package/dist/editor/components/EditorCrashScreen.js +22 -0
  243. package/dist/editor/components/EditorErrorBoundary.d.ts +38 -0
  244. package/dist/editor/components/EditorErrorBoundary.js +40 -0
  245. package/dist/editor/components/EditorHeader.d.ts +56 -106
  246. package/dist/editor/components/EditorHeader.js +130 -131
  247. package/dist/editor/components/EditorRail.d.ts +49 -0
  248. package/dist/editor/components/EditorRail.js +65 -0
  249. package/dist/editor/components/EntryBreadcrumb.d.ts +33 -0
  250. package/dist/editor/components/EntryBreadcrumb.js +56 -0
  251. package/dist/editor/components/EntryCreateModal.d.ts +12 -7
  252. package/dist/editor/components/EntryCreateModal.js +51 -57
  253. package/dist/editor/components/NoEditPermissionNotice.d.ts +6 -5
  254. package/dist/editor/components/NoEditPermissionNotice.js +5 -4
  255. package/dist/editor/components/QuickOpenPalette.d.ts +22 -0
  256. package/dist/editor/components/QuickOpenPalette.js +66 -0
  257. package/dist/editor/components/ReadOnlyDraftNotice.d.ts +11 -0
  258. package/dist/editor/components/ReadOnlyDraftNotice.js +12 -0
  259. package/dist/editor/components/ReasonedMenuItem.d.ts +15 -0
  260. package/dist/editor/components/ReasonedMenuItem.js +15 -0
  261. package/dist/editor/components/ReferencedByList.d.ts +11 -0
  262. package/dist/editor/components/ReferencedByList.js +28 -0
  263. package/dist/editor/components/RelativeTime.d.ts +10 -0
  264. package/dist/editor/components/RelativeTime.js +10 -0
  265. package/dist/editor/components/RenameEntryModal.d.ts +9 -1
  266. package/dist/editor/components/RenameEntryModal.js +19 -31
  267. package/dist/editor/components/RetryToastMessage.d.ts +9 -0
  268. package/dist/editor/components/RetryToastMessage.js +6 -0
  269. package/dist/editor/components/SaveAllResult.d.ts +25 -0
  270. package/dist/editor/components/SaveAllResult.js +86 -0
  271. package/dist/editor/components/SaveSplitButton.d.ts +30 -0
  272. package/dist/editor/components/SaveSplitButton.js +108 -0
  273. package/dist/editor/components/StagedChangesDrawer.d.ts +39 -0
  274. package/dist/editor/components/StagedChangesDrawer.js +92 -0
  275. package/dist/editor/components/UnavailableEntryNotice.d.ts +6 -0
  276. package/dist/editor/components/UnavailableEntryNotice.js +9 -0
  277. package/dist/editor/components/UnavailableTypeMessage.d.ts +6 -0
  278. package/dist/editor/components/UnavailableTypeMessage.js +9 -0
  279. package/dist/editor/components/UndoToastMessage.d.ts +18 -0
  280. package/dist/editor/components/UndoToastMessage.js +10 -0
  281. package/dist/editor/components/UserBadge.d.ts +2 -5
  282. package/dist/editor/components/UserBadge.js +62 -33
  283. package/dist/editor/components/ValidationSummary.d.ts +14 -0
  284. package/dist/editor/components/ValidationSummary.js +24 -0
  285. package/dist/editor/components/index.d.ts +2 -2
  286. package/dist/editor/components/index.js +2 -2
  287. package/dist/editor/context/ApiClientContext.d.ts +8 -2
  288. package/dist/editor/context/ApiClientContext.js +19 -8
  289. package/dist/editor/context/AssetContext.d.ts +13 -35
  290. package/dist/editor/context/AssetContext.js +12 -31
  291. package/dist/editor/context/EditorStateContext.d.ts +4 -4
  292. package/dist/editor/context/EditorStateContext.js +4 -4
  293. package/dist/editor/context/SWRProvider.d.ts +3 -3
  294. package/dist/editor/context/SiteMdxAllowContext.d.ts +4 -0
  295. package/dist/editor/context/SiteMdxAllowContext.js +7 -0
  296. package/dist/editor/context/index.d.ts +2 -1
  297. package/dist/editor/context/index.js +2 -1
  298. package/dist/editor/contrast.d.ts +19 -0
  299. package/dist/editor/contrast.js +41 -0
  300. package/dist/editor/copy.d.ts +18 -0
  301. package/dist/editor/copy.js +18 -0
  302. package/dist/editor/editor-config.js +16 -0
  303. package/dist/editor/editor-utils.d.ts +34 -8
  304. package/dist/editor/editor-utils.js +42 -20
  305. package/dist/editor/entry-search.d.ts +20 -0
  306. package/dist/editor/entry-search.js +34 -0
  307. package/dist/editor/field-breadcrumb.d.ts +12 -0
  308. package/dist/editor/field-breadcrumb.js +85 -0
  309. package/dist/editor/field-props.d.ts +86 -0
  310. package/dist/editor/field-props.js +27 -0
  311. package/dist/editor/field-target.d.ts +30 -0
  312. package/dist/editor/field-target.js +77 -0
  313. package/dist/editor/fields/BlockField.d.ts +12 -0
  314. package/dist/editor/fields/BlockField.js +89 -73
  315. package/dist/editor/fields/CodeField.d.ts +2 -0
  316. package/dist/editor/fields/CodeField.js +6 -2
  317. package/dist/editor/fields/DateTimeField.d.ts +4 -29
  318. package/dist/editor/fields/DateTimeField.js +79 -41
  319. package/dist/editor/fields/ExpandAllButton.d.ts +6 -0
  320. package/dist/editor/fields/ExpandAllButton.js +4 -0
  321. package/dist/editor/fields/FieldCrashFallback.d.ts +17 -0
  322. package/dist/editor/fields/FieldCrashFallback.js +30 -0
  323. package/dist/editor/fields/FieldLabel.d.ts +37 -0
  324. package/dist/editor/fields/FieldLabel.js +19 -0
  325. package/dist/editor/fields/ImageField.d.ts +4 -0
  326. package/dist/editor/fields/ImageField.js +29 -14
  327. package/dist/editor/fields/InlineGroupField.js +4 -3
  328. package/dist/editor/fields/ItemList.d.ts +42 -0
  329. package/dist/editor/fields/ItemList.js +130 -0
  330. package/dist/editor/fields/MarkdownField.d.ts +32 -0
  331. package/dist/editor/fields/MarkdownField.js +223 -46
  332. package/dist/editor/fields/MdxImageDialog.js +1 -1
  333. package/dist/editor/fields/NumberField.d.ts +2 -0
  334. package/dist/editor/fields/NumberField.js +8 -5
  335. package/dist/editor/fields/NumberListField.d.ts +2 -0
  336. package/dist/editor/fields/NumberListField.js +19 -16
  337. package/dist/editor/fields/ObjectField.d.ts +2 -7
  338. package/dist/editor/fields/ObjectField.js +15 -5
  339. package/dist/editor/fields/ObjectListField.d.ts +29 -0
  340. package/dist/editor/fields/ObjectListField.js +57 -0
  341. package/dist/editor/fields/ReferenceField.d.ts +2 -0
  342. package/dist/editor/fields/ReferenceField.js +34 -9
  343. package/dist/editor/fields/SelectField.d.ts +2 -0
  344. package/dist/editor/fields/SelectField.js +11 -2
  345. package/dist/editor/fields/StringListField.d.ts +4 -1
  346. package/dist/editor/fields/StringListField.js +22 -8
  347. package/dist/editor/fields/TextField.d.ts +2 -0
  348. package/dist/editor/fields/TextField.js +6 -2
  349. package/dist/editor/fields/ToggleField.d.ts +2 -0
  350. package/dist/editor/fields/ToggleField.js +8 -3
  351. package/dist/editor/fields/entry-link/InsertEntryLink.d.ts +1 -1
  352. package/dist/editor/fields/entry-link/InsertEntryLink.js +1 -1
  353. package/dist/editor/fields/form-expansion.d.ts +9 -0
  354. package/dist/editor/fields/form-expansion.js +2 -0
  355. package/dist/editor/fields/item-expansion.d.ts +15 -0
  356. package/dist/editor/fields/item-expansion.js +60 -0
  357. package/dist/editor/fields/list-item-keys.d.ts +8 -0
  358. package/dist/editor/fields/list-item-keys.js +50 -0
  359. package/dist/editor/fields/list-item-title.d.ts +20 -0
  360. package/dist/editor/fields/list-item-title.js +85 -0
  361. package/dist/editor/fields/markdown-export-options.d.ts +2 -0
  362. package/dist/editor/fields/markdown-export-options.js +8 -0
  363. package/dist/editor/fields/markdown-fidelity-visitors.d.ts +11 -0
  364. package/dist/editor/fields/markdown-fidelity-visitors.js +160 -0
  365. package/dist/editor/fields/mdx-jsx-support.d.ts +5 -1
  366. package/dist/editor/fields/mdx-jsx-support.js +157 -69
  367. package/dist/editor/fields/rich-text-failures.d.ts +5 -0
  368. package/dist/editor/fields/rich-text-failures.js +26 -0
  369. package/dist/editor/fields/toolbar-wrap.d.ts +7 -0
  370. package/dist/editor/fields/toolbar-wrap.js +35 -0
  371. package/dist/editor/form-outline.d.ts +13 -0
  372. package/dist/editor/form-outline.js +70 -0
  373. package/dist/editor/group-manager/GroupCard.d.ts +4 -1
  374. package/dist/editor/group-manager/GroupCard.js +12 -3
  375. package/dist/editor/group-manager/GroupForm.js +1 -1
  376. package/dist/editor/group-manager/InternalGroupsTab.d.ts +2 -1
  377. package/dist/editor/group-manager/InternalGroupsTab.js +4 -4
  378. package/dist/editor/group-manager/MemberList.d.ts +2 -1
  379. package/dist/editor/group-manager/MemberList.js +15 -4
  380. package/dist/editor/group-manager/hooks/useGroupState.d.ts +5 -0
  381. package/dist/editor/group-manager/hooks/useGroupState.js +30 -7
  382. package/dist/editor/group-manager/index.js +34 -5
  383. package/dist/editor/group-manager/types.d.ts +5 -2
  384. package/dist/editor/hooks/create-branch-request.d.ts +20 -0
  385. package/dist/editor/hooks/create-branch-request.js +54 -0
  386. package/dist/editor/hooks/save-all.d.ts +68 -0
  387. package/dist/editor/hooks/save-all.js +61 -0
  388. package/dist/editor/hooks/useBranchActions.d.ts +11 -1
  389. package/dist/editor/hooks/useBranchActions.js +42 -19
  390. package/dist/editor/hooks/useBranchManager.d.ts +21 -0
  391. package/dist/editor/hooks/useBranchManager.js +321 -125
  392. package/dist/editor/hooks/useBranchesData.d.ts +8 -4
  393. package/dist/editor/hooks/useBranchesData.js +9 -5
  394. package/dist/editor/hooks/useCommentSystem.d.ts +14 -2
  395. package/dist/editor/hooks/useCommentSystem.js +79 -55
  396. package/dist/editor/hooks/useCommentsData.d.ts +11 -7
  397. package/dist/editor/hooks/useCommentsData.js +20 -19
  398. package/dist/editor/hooks/useDraftManager.d.ts +77 -3
  399. package/dist/editor/hooks/useDraftManager.js +887 -94
  400. package/dist/editor/hooks/useEditorLayout.d.ts +53 -7
  401. package/dist/editor/hooks/useEditorLayout.js +98 -20
  402. package/dist/editor/hooks/useEntriesData.d.ts +2 -1
  403. package/dist/editor/hooks/useEntriesData.js +18 -4
  404. package/dist/editor/hooks/useEntryManager.d.ts +41 -2
  405. package/dist/editor/hooks/useEntryManager.js +227 -41
  406. package/dist/editor/hooks/useGroupManager.js +13 -16
  407. package/dist/editor/hooks/usePermissionManager.js +14 -6
  408. package/dist/editor/hooks/usePreviewMarks.d.ts +21 -0
  409. package/dist/editor/hooks/usePreviewMarks.js +33 -0
  410. package/dist/editor/hooks/useReferenceResolution.d.ts +10 -3
  411. package/dist/editor/hooks/useReferenceResolution.js +34 -177
  412. package/dist/editor/hooks/useSchemaManager.d.ts +25 -6
  413. package/dist/editor/hooks/useSchemaManager.js +97 -39
  414. package/dist/editor/hooks/useUserMetadata.d.ts +14 -4
  415. package/dist/editor/hooks/useUserMetadata.js +76 -47
  416. package/dist/editor/hooks/user-metadata-batcher.d.ts +8 -0
  417. package/dist/editor/hooks/user-metadata-batcher.js +33 -0
  418. package/dist/editor/media/AssetCard.d.ts +6 -7
  419. package/dist/editor/media/AssetCard.js +24 -31
  420. package/dist/editor/media/AssetListRow.d.ts +16 -0
  421. package/dist/editor/media/AssetListRow.js +41 -0
  422. package/dist/editor/media/CropStep.js +6 -1
  423. package/dist/editor/media/MediaLibrary.d.ts +4 -3
  424. package/dist/editor/media/MediaLibrary.js +11 -4
  425. package/dist/editor/media/MediaLibraryBody.d.ts +3 -3
  426. package/dist/editor/media/MediaLibraryBody.js +195 -80
  427. package/dist/editor/media/MediaLibrarySkeleton.d.ts +6 -0
  428. package/dist/editor/media/MediaLibrarySkeleton.js +14 -0
  429. package/dist/editor/media/crop-math.d.ts +3 -4
  430. package/dist/editor/media/crop-math.js +11 -22
  431. package/dist/editor/media/editor-image-src.d.ts +8 -0
  432. package/dist/editor/media/editor-image-src.js +10 -0
  433. package/dist/editor/media/format-bytes.d.ts +2 -0
  434. package/dist/editor/media/format-bytes.js +23 -0
  435. package/dist/editor/media/media-library-prefs.d.ts +23 -0
  436. package/dist/editor/media/media-library-prefs.js +49 -0
  437. package/dist/editor/media/media-library-view.d.ts +34 -0
  438. package/dist/editor/media/media-library-view.js +40 -0
  439. package/dist/editor/media/useAssetLibrary.d.ts +30 -0
  440. package/dist/editor/media/useAssetLibrary.js +126 -0
  441. package/dist/editor/media/useStableAssetOrder.d.ts +11 -0
  442. package/dist/editor/media/useStableAssetOrder.js +37 -0
  443. package/dist/editor/media/useThumbnailFailure.d.ts +6 -0
  444. package/dist/editor/media/useThumbnailFailure.js +16 -0
  445. package/dist/editor/permission-manager/GroupSelector.js +2 -2
  446. package/dist/editor/permission-manager/PermissionEditor.d.ts +1 -1
  447. package/dist/editor/permission-manager/PermissionEditor.js +15 -4
  448. package/dist/editor/permission-manager/PermissionLevelBadge.js +1 -1
  449. package/dist/editor/permission-manager/PermissionTree.d.ts +1 -1
  450. package/dist/editor/permission-manager/UserSelector.d.ts +1 -1
  451. package/dist/editor/permission-manager/UserSelector.js +3 -3
  452. package/dist/editor/permission-manager/index.js +12 -3
  453. package/dist/editor/permission-manager/types.d.ts +5 -2
  454. package/dist/editor/platform.d.ts +3 -0
  455. package/dist/editor/platform.js +9 -0
  456. package/dist/editor/preview-asset-base.d.ts +9 -0
  457. package/dist/editor/preview-asset-base.js +17 -0
  458. package/dist/editor/preview-bridge.d.ts +51 -27
  459. package/dist/editor/preview-bridge.js +103 -144
  460. package/dist/editor/preview-marks.d.ts +15 -0
  461. package/dist/editor/preview-marks.js +74 -0
  462. package/dist/editor/preview-path.d.ts +12 -0
  463. package/dist/editor/preview-path.js +45 -1
  464. package/dist/editor/preview-scale.d.ts +27 -0
  465. package/dist/editor/preview-scale.js +34 -0
  466. package/dist/editor/raw-asset-base.d.ts +5 -0
  467. package/dist/editor/raw-asset-base.js +14 -0
  468. package/dist/editor/relative-time.d.ts +4 -4
  469. package/dist/editor/relative-time.js +16 -8
  470. package/dist/editor/schema-editor/CollectionEditor.d.ts +20 -3
  471. package/dist/editor/schema-editor/CollectionEditor.js +361 -62
  472. package/dist/editor/schema-editor/EntryTypeEditor.d.ts +5 -1
  473. package/dist/editor/schema-editor/EntryTypeEditor.js +11 -6
  474. package/dist/editor/schema-editor/collection-draft.d.ts +22 -0
  475. package/dist/editor/schema-editor/collection-draft.js +40 -0
  476. package/dist/editor/schema-editor/index.d.ts +1 -1
  477. package/dist/editor/schema-label.d.ts +10 -0
  478. package/dist/editor/schema-label.js +17 -0
  479. package/dist/editor/settings-conflict.d.ts +5 -0
  480. package/dist/editor/settings-conflict.js +8 -0
  481. package/dist/editor/shell/ActivityRail.d.ts +37 -0
  482. package/dist/editor/shell/ActivityRail.js +91 -0
  483. package/dist/editor/shell/EditorShell.d.ts +17 -0
  484. package/dist/editor/shell/EditorShell.js +31 -0
  485. package/dist/editor/shell/PaneLayout.d.ts +28 -0
  486. package/dist/editor/shell/PaneLayout.js +116 -0
  487. package/dist/editor/shell/SidePanelHost.d.ts +35 -0
  488. package/dist/editor/shell/SidePanelHost.js +184 -0
  489. package/dist/editor/shell/TopBar.d.ts +12 -0
  490. package/dist/editor/shell/TopBar.js +14 -0
  491. package/dist/editor/shell/host-chrome.d.ts +16 -0
  492. package/dist/editor/shell/host-chrome.js +69 -0
  493. package/dist/editor/slug.d.ts +16 -0
  494. package/dist/editor/slug.js +43 -0
  495. package/dist/editor/theme.d.ts +2 -1
  496. package/dist/editor/theme.js +314 -13
  497. package/dist/editor/unanswered.d.ts +17 -0
  498. package/dist/editor/unanswered.js +26 -0
  499. package/dist/editor/unavailable-entry-type.d.ts +20 -0
  500. package/dist/editor/unavailable-entry-type.js +28 -0
  501. package/dist/editor/undo-removal.d.ts +57 -0
  502. package/dist/editor/undo-removal.js +163 -0
  503. package/dist/editor/user-display.d.ts +4 -0
  504. package/dist/editor/user-display.js +5 -0
  505. package/dist/editor/utils/confirm-modal.d.ts +8 -0
  506. package/dist/editor/utils/confirm-modal.js +12 -0
  507. package/dist/editor/utils/editor-errors.d.ts +19 -0
  508. package/dist/editor/utils/editor-errors.js +32 -0
  509. package/dist/editor/utils/focus-return.d.ts +56 -0
  510. package/dist/editor/utils/focus-return.js +106 -0
  511. package/dist/entry-link-resolver.d.ts +11 -1
  512. package/dist/entry-link-resolver.js +65 -5
  513. package/dist/entry-schema-registry.d.ts +3 -3
  514. package/dist/entry-schema-registry.js +7 -4
  515. package/dist/entry-schema.d.ts +49 -3
  516. package/dist/entry-schema.js +18 -0
  517. package/dist/git-manager.d.ts +172 -10
  518. package/dist/git-manager.js +449 -107
  519. package/dist/github-service.d.ts +39 -2
  520. package/dist/github-service.js +101 -7
  521. package/dist/http/handler.js +74 -9
  522. package/dist/http/types.d.ts +2 -0
  523. package/dist/http/worker-not-ready.d.ts +9 -4
  524. package/dist/http/worker-not-ready.js +59 -6
  525. package/dist/index.d.ts +2 -0
  526. package/dist/index.js +3 -0
  527. package/dist/item-keys.d.ts +46 -0
  528. package/dist/item-keys.js +235 -0
  529. package/dist/operating-mode/editor-mode-check.d.ts +15 -0
  530. package/dist/operating-mode/editor-mode-check.js +24 -0
  531. package/dist/operating-mode/mode-env.d.ts +13 -14
  532. package/dist/operating-mode/mode-env.js +13 -14
  533. package/dist/operating-mode/types.d.ts +2 -2
  534. package/dist/paths/branch.d.ts +0 -1
  535. package/dist/paths/branch.js +1 -8
  536. package/dist/paths/index.d.ts +1 -1
  537. package/dist/paths/index.js +1 -1
  538. package/dist/paths/validation.js +0 -2
  539. package/dist/preview.d.ts +8 -0
  540. package/dist/preview.js +7 -0
  541. package/dist/reference-resolver.js +1 -0
  542. package/dist/resolve-canopy-user.d.ts +1 -1
  543. package/dist/resolve-canopy-user.js +1 -1
  544. package/dist/schema/meta-loader.d.ts +18 -8
  545. package/dist/schema/meta-loader.js +42 -9
  546. package/dist/schema/registry-fingerprint.d.ts +14 -0
  547. package/dist/schema/registry-fingerprint.js +63 -0
  548. package/dist/schema/resolver.d.ts +7 -4
  549. package/dist/schema/resolver.js +7 -6
  550. package/dist/schema/schema-store.d.ts +7 -10
  551. package/dist/schema/schema-store.js +13 -11
  552. package/dist/schema/schema-unavailable-error.d.ts +11 -0
  553. package/dist/schema/schema-unavailable-error.js +15 -0
  554. package/dist/schema/types.d.ts +22 -0
  555. package/dist/schema-registry-record.d.ts +35 -0
  556. package/dist/schema-registry-record.js +134 -0
  557. package/dist/server.d.ts +79 -9
  558. package/dist/server.js +62 -8
  559. package/dist/services.d.ts +33 -5
  560. package/dist/services.js +155 -37
  561. package/dist/settings-workspace.d.ts +23 -3
  562. package/dist/settings-workspace.js +159 -45
  563. package/dist/stamp-on-publish.d.ts +36 -0
  564. package/dist/stamp-on-publish.js +71 -0
  565. package/dist/static/index.d.ts +58 -5
  566. package/dist/static/index.js +133 -3
  567. package/dist/static/seo.d.ts +5 -5
  568. package/dist/static/seo.js +5 -5
  569. package/dist/submission-attribution.d.ts +8 -0
  570. package/dist/submission-attribution.js +22 -0
  571. package/dist/system-users.d.ts +12 -0
  572. package/dist/system-users.js +12 -0
  573. package/dist/task-queue/cms-task-queue.d.ts +1 -1
  574. package/dist/task-queue/cms-task-queue.js +1 -1
  575. package/dist/task-queue/index.d.ts +1 -1
  576. package/dist/task-queue/index.js +1 -1
  577. package/dist/task-queue/task-queue.d.ts +6 -0
  578. package/dist/task-queue/task-queue.js +29 -0
  579. package/dist/task-queue/worker-status.d.ts +35 -9
  580. package/dist/task-queue/worker-status.js +84 -17
  581. package/dist/types.d.ts +90 -9
  582. package/dist/url-collision.js +3 -3
  583. package/dist/url-exclusivity-fixtures.d.ts +8 -1
  584. package/dist/url-exclusivity-fixtures.js +11 -1
  585. package/dist/user.js +2 -1
  586. package/dist/utils/atomic-write.js +2 -1
  587. package/dist/utils/base-branch.d.ts +13 -0
  588. package/dist/utils/base-branch.js +23 -0
  589. package/dist/utils/content-serialize.d.ts +15 -7
  590. package/dist/utils/content-serialize.js +353 -51
  591. package/dist/utils/content-write-lock.d.ts +6 -1
  592. package/dist/utils/content-write-lock.js +21 -6
  593. package/dist/utils/debug.d.ts +1 -1
  594. package/dist/utils/debug.js +5 -3
  595. package/dist/utils/error.js +13 -2
  596. package/dist/utils/escape-text.d.ts +7 -0
  597. package/dist/utils/escape-text.js +27 -0
  598. package/dist/utils/fs.d.ts +12 -4
  599. package/dist/utils/fs.js +18 -5
  600. package/dist/utils/git.d.ts +21 -1
  601. package/dist/utils/git.js +63 -8
  602. package/dist/utils/json-source-splice.d.ts +14 -0
  603. package/dist/utils/json-source-splice.js +120 -0
  604. package/dist/utils/markdown-body-splice.d.ts +39 -0
  605. package/dist/utils/markdown-body-splice.js +421 -0
  606. package/dist/utils/occ-json-write.js +18 -12
  607. package/dist/utils/provision-log.d.ts +25 -0
  608. package/dist/utils/provision-log.js +49 -0
  609. package/dist/utils/provisioning-lock.d.ts +32 -1
  610. package/dist/utils/provisioning-lock.js +78 -32
  611. package/dist/utils/sanitize-href.d.ts +9 -23
  612. package/dist/utils/sanitize-href.js +14 -28
  613. package/dist/utils/title-field.d.ts +10 -0
  614. package/dist/utils/title-field.js +47 -0
  615. package/dist/utils/yaml-source-splice.d.ts +58 -0
  616. package/dist/utils/yaml-source-splice.js +515 -0
  617. package/dist/validation/block-structural-keys.d.ts +1 -1
  618. package/dist/validation/block-structural-keys.js +1 -1
  619. package/dist/validation/deletion-checker.d.ts +21 -29
  620. package/dist/validation/deletion-checker.js +41 -117
  621. package/dist/validation/entry-validator.d.ts +6 -10
  622. package/dist/validation/entry-validator.js +19 -26
  623. package/dist/validation/field-traversal.d.ts +22 -0
  624. package/dist/validation/field-traversal.js +39 -8
  625. package/dist/validation/markdown-safety.d.ts +68 -0
  626. package/dist/validation/markdown-safety.js +596 -0
  627. package/dist/validation/mdx-allowlist.d.ts +55 -0
  628. package/dist/validation/mdx-allowlist.js +183 -0
  629. package/dist/validation/reference-validator.d.ts +2 -0
  630. package/dist/validation/reference-validator.js +3 -0
  631. package/dist/version.d.ts +1 -1
  632. package/dist/version.js +1 -1
  633. package/dist/worker/branch-policy.d.ts +124 -0
  634. package/dist/worker/branch-policy.js +243 -0
  635. package/dist/worker/bundle-header.d.ts +117 -0
  636. package/dist/worker/bundle-header.js +253 -0
  637. package/dist/worker/cms-worker.d.ts +236 -142
  638. package/dist/worker/cms-worker.js +772 -285
  639. package/dist/worker/gateway-egress.d.ts +43 -0
  640. package/dist/worker/gateway-egress.js +209 -0
  641. package/dist/worker/gateway-instance.d.ts +42 -0
  642. package/dist/worker/gateway-instance.js +129 -0
  643. package/dist/worker/git-process.d.ts +81 -0
  644. package/dist/worker/git-process.js +234 -0
  645. package/dist/worker/git-sync.d.ts +34 -17
  646. package/dist/worker/git-sync.js +394 -131
  647. package/dist/worker/github-auth.d.ts +9 -9
  648. package/dist/worker/github-auth.js +13 -15
  649. package/dist/worker/github-gateway-http.d.ts +62 -0
  650. package/dist/worker/github-gateway-http.js +977 -0
  651. package/dist/worker/github-gateway-wire.d.ts +590 -0
  652. package/dist/worker/github-gateway-wire.js +488 -0
  653. package/dist/worker/github-gateway.d.ts +238 -0
  654. package/dist/worker/github-gateway.js +726 -0
  655. package/dist/worker/github-mirror-upkeep.d.ts +75 -0
  656. package/dist/worker/github-mirror-upkeep.js +266 -0
  657. package/dist/worker/github-mirror.d.ts +364 -0
  658. package/dist/worker/github-mirror.js +1030 -0
  659. package/dist/worker/github-transfer.d.ts +56 -0
  660. package/dist/worker/github-transfer.js +444 -0
  661. package/dist/worker/history-rewrite.d.ts +4 -5
  662. package/dist/worker/history-rewrite.js +12 -17
  663. package/dist/worker/provisioned-workspace.d.ts +5 -5
  664. package/dist/worker/provisioned-workspace.js +5 -5
  665. package/dist/worker/rebase.d.ts +1 -1
  666. package/dist/worker/rebase.js +58 -54
  667. package/dist/worker/remote-git-maintenance.d.ts +3 -0
  668. package/dist/worker/remote-git-maintenance.js +12 -0
  669. package/dist/worker/schema-gate.d.ts +49 -0
  670. package/dist/worker/schema-gate.js +226 -0
  671. package/dist/worker/self-checks.d.ts +107 -0
  672. package/dist/worker/self-checks.js +358 -0
  673. package/dist/worker/shared-repo-git.d.ts +96 -0
  674. package/dist/worker/shared-repo-git.js +459 -0
  675. package/dist/worker/sparse-cone.d.ts +20 -0
  676. package/dist/worker/sparse-cone.js +136 -0
  677. package/dist/worker/stale-mirror.d.ts +82 -0
  678. package/dist/worker/stale-mirror.js +130 -0
  679. package/dist/worker/task-runner.d.ts +5 -3
  680. package/dist/worker/task-runner.js +287 -186
  681. package/dist/worker/worker-context.d.ts +36 -37
  682. package/package.json +35 -7
  683. package/dist/editor/EditorPanes.d.ts +0 -10
  684. package/dist/editor/EditorPanes.js +0 -98
  685. package/dist/editor/components/EditorFooter.d.ts +0 -11
  686. package/dist/editor/components/EditorFooter.js +0 -9
  687. package/dist/editor/components/EditorSidebar.d.ts +0 -67
  688. package/dist/editor/components/EditorSidebar.js +0 -22
@@ -6,13 +6,33 @@ import { type DuplicateContentId } from './content-id-index.js';
6
6
  * Without it two stuck states have no in-product recovery, and prod admins have
7
7
  * no filesystem access to see them: a branch dir whose `.canopy-meta/branch.json`
8
8
  * is corrupt (the registry drops it silently) and an orphan dir with no
9
- * `branch.json` at all (a partial delete crash — see `api/branch.ts`).
9
+ * `branch.json` at all (a clone or delete killed in place, until the worker
10
+ * quarantines it — see branch-provisioning.ts).
10
11
  *
11
12
  * `scanBranchHealth` mirrors the registry's own directory-listing rules (skip
12
13
  * non-directories and dot-prefixed names) so the two never disagree about what
13
14
  * counts as missing.
14
15
  */
15
16
  type BranchHealthKind = 'healthy' | 'corrupt-metadata' | 'orphan';
17
+ /**
18
+ * An orphan younger than this may still be a clone in progress: admin purge refuses it and the
19
+ * worker does not quarantine it. Corrupt-metadata dirs are exempt.
20
+ */
21
+ export declare const ORPHAN_YOUTH_THRESHOLD_MS: number;
22
+ /**
23
+ * One healthy branch's duplicate-content-ID scan (see content-id-index.ts).
24
+ * `unknown` means the scan did not finish — it failed, or the request's time
25
+ * budget ran out first — and must never be read as `none`.
26
+ */
27
+ export type DuplicateIdScan = {
28
+ state: 'none';
29
+ } | {
30
+ state: 'found';
31
+ duplicates: DuplicateContentId[];
32
+ } | {
33
+ state: 'unknown';
34
+ reason: 'failed' | 'out-of-time';
35
+ };
16
36
  export interface BranchHealthEntry {
17
37
  dirName: string;
18
38
  kind: BranchHealthKind;
@@ -21,19 +41,19 @@ export interface BranchHealthEntry {
21
41
  /** healthy only */
22
42
  branch?: BranchMetadata;
23
43
  /**
24
- * healthy only, non-empty only: duplicate content IDs in this branch's
25
- * content tree (see content-id-index.ts). The branch stays usable — only the
26
- * quarantined IDs degrade, dropping out of ID-based lookups and refusing
27
- * saves (`DuplicateContentIdError`, a 409 naming the repair action) rather
28
- * than mutating an ambiguous target.
44
+ * healthy only, and only when the caller asked for the duplicate-ID scan: see
45
+ * {@link DuplicateIdScan}. The branch stays usable while IDs are duplicated —
46
+ * only the quarantined IDs degrade, dropping out of ID-based lookups and
47
+ * refusing saves (`DuplicateContentIdError`) rather than mutating an
48
+ * ambiguous target.
29
49
  */
30
- duplicateContentIds?: DuplicateContentId[];
50
+ duplicateIdScan?: DuplicateIdScan;
31
51
  /**
32
52
  * healthy only, true only: this clone has an interrupted rebase on disk
33
53
  * (`.git/rebase-merge` / `.git/rebase-apply`).
34
54
  *
35
55
  * Advisory on `healthy` rather than its own `BranchHealthKind`, like
36
- * `duplicateContentIds`: the metadata is intact and the state is usually
56
+ * `duplicateIdScan`: the metadata is intact and the state is usually
37
57
  * transient, since the worker's sync loop aborts an interrupted rebase at the
38
58
  * top of its next per-branch pass. The flag buys visibility in the window
39
59
  * before that, where the branch otherwise scans as plain `healthy` while
@@ -74,9 +94,16 @@ export interface BranchHealthEntry {
74
94
  * metadata must not take down the whole scan, as in the registry's quarantine.
75
95
  * A missing `baseRoot` returns `[]`, so the admin endpoint can call this
76
96
  * without a pre-existence check.
97
+ *
98
+ * `duplicateIdScan` opts in to the per-branch duplicate-ID scan, which shares
99
+ * one `budgetMs` across every healthy branch, scanned in turn; a branch
100
+ * reached after the budget is spent reports `unknown`/`out-of-time`.
77
101
  */
78
102
  export declare function scanBranchHealth(baseRoot: string, opts: {
79
103
  baseBranchName: string;
80
104
  contentRootName?: string;
105
+ duplicateIdScan?: {
106
+ budgetMs: number;
107
+ };
81
108
  }): Promise<BranchHealthEntry[]>;
82
109
  export {};
@@ -6,6 +6,11 @@ import { sanitizeBranchName } from './paths/branch-name.js';
6
6
  import { getErrorMessage, isNodeError, isNotFoundError } from './utils/error.js';
7
7
  import { isRebaseInProgress } from './utils/git.js';
8
8
  import { branchProvisioningLockName } from './utils/provisioning-lock.js';
9
+ /**
10
+ * An orphan younger than this may still be a clone in progress: admin purge refuses it and the
11
+ * worker does not quarantine it. Corrupt-metadata dirs are exempt.
12
+ */
13
+ export const ORPHAN_YOUTH_THRESHOLD_MS = 15 * 60_000;
9
14
  /**
10
15
  * The provisioning lock marker's path for a branch directory.
11
16
  *
@@ -39,20 +44,41 @@ async function readMetaMtime(branchRoot) {
39
44
  }
40
45
  }
41
46
  /**
42
- * Scan a healthy branch's content tree for duplicate embedded IDs (see
43
- * content-id-index.ts). Never throws: one branch's unreadable content tree must
44
- * not take down the whole health scan. Costs a full recursive readdir — the
45
- * same class of cost as a ContentStore's first-access warm-up, fine for an
46
- * admin-triggered scan and not for a hot path.
47
+ * Scan a healthy branch's content tree for duplicate embedded IDs, giving up
48
+ * when `budget` runs out. Never throws: one branch's unreadable content tree
49
+ * must not take down the whole health scan. Costs a full recursive readdir, so
50
+ * it runs only on request and under a budget. A readdir cannot be cancelled: a
51
+ * scan that misses the deadline keeps running unobserved until it settles.
47
52
  */
48
- async function scanDuplicateContentIds(branchRoot, contentRootName) {
53
+ async function scanDuplicateContentIds(branchRoot, contentRootName, budget) {
54
+ const remainingMs = budget.deadline - Date.now();
55
+ if (budget.spent || remainingMs <= 0) {
56
+ budget.spent = true;
57
+ return { state: 'unknown', reason: 'out-of-time' };
58
+ }
59
+ const scan = (async () => {
60
+ try {
61
+ const idIndex = new ContentIdIndex(branchRoot);
62
+ await idIndex.buildFromFilenames(contentRootName);
63
+ const duplicates = idIndex.getDuplicateIds();
64
+ return duplicates.length ? { state: 'found', duplicates } : { state: 'none' };
65
+ }
66
+ catch {
67
+ return { state: 'unknown', reason: 'failed' };
68
+ }
69
+ })();
70
+ let timer;
71
+ const outOfTime = new Promise((resolve) => {
72
+ timer = setTimeout(() => {
73
+ budget.spent = true;
74
+ resolve({ state: 'unknown', reason: 'out-of-time' });
75
+ }, remainingMs);
76
+ });
49
77
  try {
50
- const idIndex = new ContentIdIndex(branchRoot);
51
- await idIndex.buildFromFilenames(contentRootName);
52
- return idIndex.getDuplicateIds();
78
+ return await Promise.race([scan, outOfTime]);
53
79
  }
54
- catch {
55
- return [];
80
+ finally {
81
+ clearTimeout(timer);
56
82
  }
57
83
  }
58
84
  /**
@@ -61,8 +87,15 @@ async function scanDuplicateContentIds(branchRoot, contentRootName) {
61
87
  * metadata must not take down the whole scan, as in the registry's quarantine.
62
88
  * A missing `baseRoot` returns `[]`, so the admin endpoint can call this
63
89
  * without a pre-existence check.
90
+ *
91
+ * `duplicateIdScan` opts in to the per-branch duplicate-ID scan, which shares
92
+ * one `budgetMs` across every healthy branch, scanned in turn; a branch
93
+ * reached after the budget is spent reports `unknown`/`out-of-time`.
64
94
  */
65
95
  export async function scanBranchHealth(baseRoot, opts) {
96
+ const duplicateScanBudget = opts.duplicateIdScan
97
+ ? { deadline: Date.now() + opts.duplicateIdScan.budgetMs, spent: false }
98
+ : undefined;
66
99
  const resolvedRoot = path.resolve(baseRoot);
67
100
  const sanitizedBaseBranchName = sanitizeBranchName(opts.baseBranchName);
68
101
  const contentRootName = opts.contentRootName ?? 'content';
@@ -95,13 +128,14 @@ export async function scanBranchHealth(baseRoot, opts) {
95
128
  }
96
129
  if (loadErr) {
97
130
  // Every loadOnly failure lands here — BranchMetadataCorruptError for bad
98
- // JSON, EACCES/EISDIR and the rest for everything else — since all of
99
- // them need admin attention and none may throw out of the scan.
131
+ // JSON or a failed schema check, EACCES/EISDIR and the rest for
132
+ // everything else — since all of them need admin attention and none may
133
+ // throw out of the scan.
100
134
  //
101
135
  // [REDACT] parseError reaches the browser through the admin branch-health
102
136
  // endpoint, so it must never carry the absolute workspace path.
103
- // BranchMetadataCorruptError's `parseCause` is the path-free JSON.parse
104
- // message for exactly this, while its `message` embeds branchRoot and is
137
+ // BranchMetadataCorruptError's `parseCause` is the path-free cause
138
+ // for exactly this, while its `message` embeds branchRoot and is
105
139
  // for server logs only. Node errors embed the path in `message` too, so
106
140
  // only their `code` is safe to surface.
107
141
  const parseError = loadErr instanceof BranchMetadataCorruptError
@@ -124,8 +158,10 @@ export async function scanBranchHealth(baseRoot, opts) {
124
158
  continue;
125
159
  }
126
160
  if (meta) {
127
- const [duplicateContentIds, rebaseInProgress] = await Promise.all([
128
- scanDuplicateContentIds(branchRoot, contentRootName),
161
+ const [duplicateIdScan, rebaseInProgress] = await Promise.all([
162
+ duplicateScanBudget === undefined
163
+ ? undefined
164
+ : scanDuplicateContentIds(branchRoot, contentRootName, duplicateScanBudget),
129
165
  isRebaseInProgress(branchRoot),
130
166
  ]);
131
167
  entries.push({
@@ -133,7 +169,7 @@ export async function scanBranchHealth(baseRoot, opts) {
133
169
  kind: 'healthy',
134
170
  ...(isBaseBranch ? { isBaseBranch } : {}),
135
171
  branch: meta.branch,
136
- ...(duplicateContentIds.length ? { duplicateContentIds } : {}),
172
+ ...(duplicateIdScan ? { duplicateIdScan } : {}),
137
173
  ...(rebaseInProgress ? { rebaseInProgress } : {}),
138
174
  });
139
175
  continue;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The corrupt-`branch.json` error and what the API says about it. Free of
3
+ * node built-ins, so the API guards, which the client bundle reaches, can
4
+ * recognize the error without pulling in the reader (branch-metadata-file.ts).
5
+ */
6
+ /** What the editor API answers for a branch whose branch.json is corrupt. */
7
+ export declare const BRANCH_METADATA_CORRUPT_MESSAGE = "This branch's metadata file is damaged, so the branch can't be opened or edited. An admin can repair it in System health.";
8
+ /**
9
+ * branch.json exists but is not valid JSON, or fails the schema in branch-metadata-file.ts.
10
+ * Distinguished from provisioning and IO failures so callers can degrade instead
11
+ * of failing hard: the registry scan quarantines the branch, the API answers
12
+ * {@link BRANCH_METADATA_CORRUPT_MESSAGE}, and the request handler keeps serving
13
+ * (with empty internal groups) when the BASE branch is the corrupt one —
14
+ * otherwise the admin recovery surface is unreachable exactly when it is needed.
15
+ */
16
+ export declare class BranchMetadataCorruptError extends Error {
17
+ readonly branchRoot: string;
18
+ /**
19
+ * [REDACT] What is wrong with the file, with no embedded path: the JSON.parse
20
+ * failure, or the fields that failed the schema.
21
+ * `message` above keeps the `branchRoot`-qualified text for server logs;
22
+ * `parseCause` is the one callers surface to clients (branch-health.ts's
23
+ * `parseError`), so no scan leaks the absolute workspace path.
24
+ */
25
+ readonly parseCause: string;
26
+ constructor(branchRoot: string, cause: string);
27
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The corrupt-`branch.json` error and what the API says about it. Free of
3
+ * node built-ins, so the API guards, which the client bundle reaches, can
4
+ * recognize the error without pulling in the reader (branch-metadata-file.ts).
5
+ */
6
+ /** What the editor API answers for a branch whose branch.json is corrupt. */
7
+ export const BRANCH_METADATA_CORRUPT_MESSAGE = "This branch's metadata file is damaged, so the branch can't be opened or edited. An admin can repair it in System health.";
8
+ /**
9
+ * branch.json exists but is not valid JSON, or fails the schema in branch-metadata-file.ts.
10
+ * Distinguished from provisioning and IO failures so callers can degrade instead
11
+ * of failing hard: the registry scan quarantines the branch, the API answers
12
+ * {@link BRANCH_METADATA_CORRUPT_MESSAGE}, and the request handler keeps serving
13
+ * (with empty internal groups) when the BASE branch is the corrupt one —
14
+ * otherwise the admin recovery surface is unreachable exactly when it is needed.
15
+ */
16
+ export class BranchMetadataCorruptError extends Error {
17
+ constructor(branchRoot, cause) {
18
+ super(`Corrupt branch metadata in '${branchRoot}': ${cause}`);
19
+ this.name = 'BranchMetadataCorruptError';
20
+ this.branchRoot = branchRoot;
21
+ this.parseCause = cause;
22
+ }
23
+ }
@@ -1,12 +1,16 @@
1
1
  /**
2
2
  * Reading `branch.json` — the file format, nothing else.
3
3
  *
4
- * Deliberately a LEAF, importing only node built-ins, a type, and the error
5
- * helper. That is what keeps `branch-registry.ts` (which reads every branch's
4
+ * Deliberately a LEAF, importing only node built-ins, zod, types, and the error
5
+ * modules. That is what keeps `branch-registry.ts` (which reads every branch's
6
6
  * `branch.json`) out of a runtime import cycle with `branch-metadata.ts` (which
7
7
  * writes it and then invalidates the registry cache).
8
8
  */
9
+ import { z } from 'zod';
10
+ import type { ContentId } from './paths/types.js';
9
11
  import type { BranchMetadata } from './types.js';
12
+ import { BranchMetadataCorruptError } from './branch-metadata-error.js';
13
+ export { BranchMetadataCorruptError };
10
14
  export declare const BRANCH_META_DIR = ".canopy-meta";
11
15
  export declare const BRANCH_META_FILE = "branch.json";
12
16
  export interface BranchMetadataFile {
@@ -15,28 +19,205 @@ export interface BranchMetadataFile {
15
19
  writeId?: string;
16
20
  branch: BranchMetadata;
17
21
  }
22
+ /** The `branch` object, also embedded in the registry snapshot (branch-registry.ts). */
23
+ export declare const branchMetadataSchema: z.ZodObject<{
24
+ name: z.ZodString;
25
+ title: z.ZodOptional<z.ZodString>;
26
+ description: z.ZodOptional<z.ZodString>;
27
+ status: z.ZodNativeEnum<{
28
+ editing: "editing";
29
+ submitted: "submitted";
30
+ approved: "approved";
31
+ archived: "archived";
32
+ }>;
33
+ access: z.ZodObject<{
34
+ allowedUsers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
35
+ allowedGroups: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
36
+ managerOrAdminAllowed: z.ZodOptional<z.ZodBoolean>;
37
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
38
+ allowedUsers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
39
+ allowedGroups: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
40
+ managerOrAdminAllowed: z.ZodOptional<z.ZodBoolean>;
41
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
42
+ allowedUsers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
43
+ allowedGroups: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
44
+ managerOrAdminAllowed: z.ZodOptional<z.ZodBoolean>;
45
+ }, z.ZodTypeAny, "passthrough">>;
46
+ createdBy: z.ZodDefault<z.ZodString>;
47
+ createdAt: z.ZodDefault<z.ZodString>;
48
+ updatedAt: z.ZodDefault<z.ZodString>;
49
+ baseBranch: z.ZodOptional<z.ZodString>;
50
+ pullRequestUrl: z.ZodOptional<z.ZodString>;
51
+ pullRequestNumber: z.ZodOptional<z.ZodNumber>;
52
+ submittedAt: z.ZodOptional<z.ZodString>;
53
+ pushedToGitHubAt: z.ZodOptional<z.ZodString>;
54
+ syncStatus: z.ZodOptional<z.ZodNativeEnum<{
55
+ synced: "synced";
56
+ "pending-sync": "pending-sync";
57
+ "sync-failed": "sync-failed";
58
+ }>>;
59
+ conflictStatus: z.ZodOptional<z.ZodNativeEnum<{
60
+ clean: "clean";
61
+ "conflicts-detected": "conflicts-detected";
62
+ }>>;
63
+ conflictFiles: z.ZodOptional<z.ZodArray<z.ZodType<ContentId, z.ZodTypeDef, ContentId>, "many">>;
64
+ pullRequestState: z.ZodOptional<z.ZodNativeEnum<{
65
+ open: "open";
66
+ closed: "closed";
67
+ merged: "merged";
68
+ }>>;
69
+ mergedAt: z.ZodOptional<z.ZodString>;
70
+ rebaseFailure: z.ZodOptional<z.ZodObject<{
71
+ message: z.ZodString;
72
+ firstAt: z.ZodString;
73
+ lastAt: z.ZodString;
74
+ }, "strip", z.ZodTypeAny, {
75
+ message: string;
76
+ firstAt: string;
77
+ lastAt: string;
78
+ }, {
79
+ message: string;
80
+ firstAt: string;
81
+ lastAt: string;
82
+ }>>;
83
+ historyRewrittenFrom: z.ZodOptional<z.ZodString>;
84
+ syncFailureReason: z.ZodOptional<z.ZodString>;
85
+ editors: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
86
+ uncommittedEditors: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
87
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
88
+ name: z.ZodString;
89
+ title: z.ZodOptional<z.ZodString>;
90
+ description: z.ZodOptional<z.ZodString>;
91
+ status: z.ZodNativeEnum<{
92
+ editing: "editing";
93
+ submitted: "submitted";
94
+ approved: "approved";
95
+ archived: "archived";
96
+ }>;
97
+ access: z.ZodObject<{
98
+ allowedUsers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
99
+ allowedGroups: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
100
+ managerOrAdminAllowed: z.ZodOptional<z.ZodBoolean>;
101
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
102
+ allowedUsers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
103
+ allowedGroups: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
104
+ managerOrAdminAllowed: z.ZodOptional<z.ZodBoolean>;
105
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
106
+ allowedUsers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
107
+ allowedGroups: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
108
+ managerOrAdminAllowed: z.ZodOptional<z.ZodBoolean>;
109
+ }, z.ZodTypeAny, "passthrough">>;
110
+ createdBy: z.ZodDefault<z.ZodString>;
111
+ createdAt: z.ZodDefault<z.ZodString>;
112
+ updatedAt: z.ZodDefault<z.ZodString>;
113
+ baseBranch: z.ZodOptional<z.ZodString>;
114
+ pullRequestUrl: z.ZodOptional<z.ZodString>;
115
+ pullRequestNumber: z.ZodOptional<z.ZodNumber>;
116
+ submittedAt: z.ZodOptional<z.ZodString>;
117
+ pushedToGitHubAt: z.ZodOptional<z.ZodString>;
118
+ syncStatus: z.ZodOptional<z.ZodNativeEnum<{
119
+ synced: "synced";
120
+ "pending-sync": "pending-sync";
121
+ "sync-failed": "sync-failed";
122
+ }>>;
123
+ conflictStatus: z.ZodOptional<z.ZodNativeEnum<{
124
+ clean: "clean";
125
+ "conflicts-detected": "conflicts-detected";
126
+ }>>;
127
+ conflictFiles: z.ZodOptional<z.ZodArray<z.ZodType<ContentId, z.ZodTypeDef, ContentId>, "many">>;
128
+ pullRequestState: z.ZodOptional<z.ZodNativeEnum<{
129
+ open: "open";
130
+ closed: "closed";
131
+ merged: "merged";
132
+ }>>;
133
+ mergedAt: z.ZodOptional<z.ZodString>;
134
+ rebaseFailure: z.ZodOptional<z.ZodObject<{
135
+ message: z.ZodString;
136
+ firstAt: z.ZodString;
137
+ lastAt: z.ZodString;
138
+ }, "strip", z.ZodTypeAny, {
139
+ message: string;
140
+ firstAt: string;
141
+ lastAt: string;
142
+ }, {
143
+ message: string;
144
+ firstAt: string;
145
+ lastAt: string;
146
+ }>>;
147
+ historyRewrittenFrom: z.ZodOptional<z.ZodString>;
148
+ syncFailureReason: z.ZodOptional<z.ZodString>;
149
+ editors: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
150
+ uncommittedEditors: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
151
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
152
+ name: z.ZodString;
153
+ title: z.ZodOptional<z.ZodString>;
154
+ description: z.ZodOptional<z.ZodString>;
155
+ status: z.ZodNativeEnum<{
156
+ editing: "editing";
157
+ submitted: "submitted";
158
+ approved: "approved";
159
+ archived: "archived";
160
+ }>;
161
+ access: z.ZodObject<{
162
+ allowedUsers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
163
+ allowedGroups: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
164
+ managerOrAdminAllowed: z.ZodOptional<z.ZodBoolean>;
165
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
166
+ allowedUsers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
167
+ allowedGroups: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
168
+ managerOrAdminAllowed: z.ZodOptional<z.ZodBoolean>;
169
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
170
+ allowedUsers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
171
+ allowedGroups: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
172
+ managerOrAdminAllowed: z.ZodOptional<z.ZodBoolean>;
173
+ }, z.ZodTypeAny, "passthrough">>;
174
+ createdBy: z.ZodDefault<z.ZodString>;
175
+ createdAt: z.ZodDefault<z.ZodString>;
176
+ updatedAt: z.ZodDefault<z.ZodString>;
177
+ baseBranch: z.ZodOptional<z.ZodString>;
178
+ pullRequestUrl: z.ZodOptional<z.ZodString>;
179
+ pullRequestNumber: z.ZodOptional<z.ZodNumber>;
180
+ submittedAt: z.ZodOptional<z.ZodString>;
181
+ pushedToGitHubAt: z.ZodOptional<z.ZodString>;
182
+ syncStatus: z.ZodOptional<z.ZodNativeEnum<{
183
+ synced: "synced";
184
+ "pending-sync": "pending-sync";
185
+ "sync-failed": "sync-failed";
186
+ }>>;
187
+ conflictStatus: z.ZodOptional<z.ZodNativeEnum<{
188
+ clean: "clean";
189
+ "conflicts-detected": "conflicts-detected";
190
+ }>>;
191
+ conflictFiles: z.ZodOptional<z.ZodArray<z.ZodType<ContentId, z.ZodTypeDef, ContentId>, "many">>;
192
+ pullRequestState: z.ZodOptional<z.ZodNativeEnum<{
193
+ open: "open";
194
+ closed: "closed";
195
+ merged: "merged";
196
+ }>>;
197
+ mergedAt: z.ZodOptional<z.ZodString>;
198
+ rebaseFailure: z.ZodOptional<z.ZodObject<{
199
+ message: z.ZodString;
200
+ firstAt: z.ZodString;
201
+ lastAt: z.ZodString;
202
+ }, "strip", z.ZodTypeAny, {
203
+ message: string;
204
+ firstAt: string;
205
+ lastAt: string;
206
+ }, {
207
+ message: string;
208
+ firstAt: string;
209
+ lastAt: string;
210
+ }>>;
211
+ historyRewrittenFrom: z.ZodOptional<z.ZodString>;
212
+ syncFailureReason: z.ZodOptional<z.ZodString>;
213
+ editors: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
214
+ uncommittedEditors: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
215
+ }, z.ZodTypeAny, "passthrough">>;
18
216
  /**
19
- * branch.json exists but is not valid JSON. Distinguished from provisioning and
20
- * IO failures so callers can degrade instead of failing hard: the registry scan
21
- * quarantines the branch, and the request handler keeps serving (with empty
22
- * internal groups) when the BASE branch is the corrupt one — otherwise the
23
- * admin recovery surface is unreachable exactly when it is needed.
24
- */
25
- export declare class BranchMetadataCorruptError extends Error {
26
- readonly branchRoot: string;
27
- /**
28
- * [REDACT] The raw JSON.parse failure message, with no embedded path.
29
- * `message` above keeps the `branchRoot`-qualified text for server logs;
30
- * `parseCause` is the one callers surface to clients (branch-health.ts's
31
- * `parseError`), so no scan leaks the absolute workspace path.
32
- */
33
- readonly parseCause: string;
34
- constructor(branchRoot: string, cause: string);
35
- }
36
- /**
37
- * Read and parse `branch.json`, with no locking, no OCC and no side effects.
38
- * Callers distinguish three outcomes: `null` when the file does not exist (an
39
- * un-provisioned or non-branch directory), `BranchMetadataCorruptError` on
40
- * malformed JSON, and every other IO failure rethrown unchanged.
217
+ * Read, parse and validate `branch.json`, with no locking, no OCC and no side
218
+ * effects. Callers distinguish three outcomes: `null` when the file does not
219
+ * exist (an un-provisioned or non-branch directory),
220
+ * `BranchMetadataCorruptError` on malformed JSON or a failed schema check, and
221
+ * every other IO failure rethrown unchanged.
41
222
  */
42
223
  export declare function readBranchMetadataFile(branchRoot: string): Promise<BranchMetadataFile | null>;