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
@@ -1,7 +1,7 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
- // The leaf, NOT './branch-metadata' — that module imports this one back, and
4
- // the pair was the package's only runtime import cycle. See branch-metadata-file.ts.
3
+ // The leaf, NOT './branch-metadata': that module imports this one back, so the
4
+ // pair would be a runtime import cycle. See branch-metadata-file.ts.
5
5
  import { readBranchMetadataFile } from './branch-metadata-file.js';
6
6
  import { isNotFoundError, getErrorMessage } from './utils/error.js';
7
7
  import { createDebugLogger } from './utils/debug.js';
@@ -13,10 +13,8 @@ import { bumpResourceGeneration, readResourceGeneration, isGenerationCurrent, }
13
13
  const log = createDebugLogger({ prefix: 'BranchRegistry' });
14
14
  // Registry files are stored directly in the branches root (not in a subdirectory)
15
15
  const REGISTRY_FILE = 'branches.json';
16
- // Legacy rename-based invalidation scheme's stale marker file. No longer written -
17
- // invalidate() now bumps the cross-process generation marker instead - but a
18
- // process upgraded mid-flight may find one left over from before the deploy, so
19
- // regenerate() opportunistically deletes it. Keep this name only for that cleanup.
16
+ // Retired stale-marker file, never written. Named only so regenerate() can
17
+ // delete one a mid-flight deploy left behind.
20
18
  const REGISTRY_STALE_FILE = 'branches.stale.json';
21
19
  const REGISTRY_TEMP_FILE = 'branches.tmp.json';
22
20
  const REGISTRY_VERSION = 2;
@@ -25,50 +23,18 @@ const RESOURCE = 'branch-registry';
25
23
  /** Throttle for the get() suspicious-miss backstop; mirrors content-store's FORCED_REFRESH_MIN_INTERVAL_MS. */
26
24
  const GET_MISS_REFRESH_MIN_INTERVAL_MS = 5000;
27
25
  /**
28
- * BranchRegistry is a read-only cache for fast branch listing.
29
- * Individual branch.json files are the source of truth.
26
+ * A read-only `branches.json` cache for fast branch listing; the individual
27
+ * branch.json files are the source of truth.
30
28
  *
31
- * ## Cross-process freshness (resource-generation.ts marker protocol)
29
+ * Freshness follows the generation-marker protocol owned by
30
+ * resource-generation.ts. This is that protocol's durable-snapshot consumer, so
31
+ * it carries both mitigations: invalidate() eager-regenerates on the mutating
32
+ * host right after its own bump, and get() has a throttled suspicious-miss
33
+ * backstop bounding how long a bad snapshot can hide a real branch.
32
34
  *
33
- * Several warm Lambda containers plus the EC2 worker can share one branch-clone
34
- * root over EFS, each with its own in-process cache of `branches.json`. There is
35
- * no shared memory and no cross-host file watching, so freshness is coordinated
36
- * via the generic on-disk generation marker in resource-generation.ts: every
37
- * snapshot embeds the marker token it was built against, and every read
38
- * cheaply re-checks the live marker before trusting the cached snapshot. See
39
- * that module's doc comment for the full protocol and residual staleness
40
- * windows (A/B/C/E).
41
- *
42
- * BranchRegistry is exactly the "durable snapshot consumer" case called out
43
- * there: a regeneration whose scan is served from stale NFS dentry/attribute
44
- * caches can record a FRESH token over STALE data (window E), and because the
45
- * result is written to `branches.json`, that staleness becomes durable and
46
- * shared with every other host that reads the marker - not just one process's
47
- * memory. Two mitigations close the practical gap:
48
- *
49
- * - invalidate() eager-regenerates immediately after its own bump. The
50
- * mutating host's own scan is necessarily coherent with the mutation it just
51
- * made (no NFS round trip was needed to observe its own write), so this
52
- * closes window (E) for the common case without waiting for some other host
53
- * to lazily pull the change.
54
- * - get() implements a suspicious-miss backstop: a branch that "should" exist
55
- * but is absent from the cached snapshot forces one fresh regeneration
56
- * (throttled), bounding how long a bad snapshot can hide a real branch.
57
- *
58
- * regenerate() also skips persisting a snapshot when the marker read itself
59
- * fails (`{ ok: false }`, e.g. unreadable for a non-ENOENT reason): a snapshot
60
- * embedding a token we cannot attribute to "matches this scan" would be
61
- * indistinguishable from a correctly-attributed one to every future reader, so
62
- * the safer behavior is to serve the fresh scan without writing it durably and
63
- * let the next read retry the marker.
64
- *
65
- * Design:
66
- * - list() returns the cached snapshot if its embedded generation token still
67
- * matches the live marker, regenerates from branch.json files otherwise
68
- * - invalidate() bumps the marker (durable, cross-process) and eager-regenerates
69
- * - Concurrent regeneration within one process is deduped to a single scan
70
- * (regenInFlight); across processes, regeneration is still safe since all
71
- * processes produce identical output from the same branch.json files
35
+ * Concurrent regeneration within one process is deduped to a single scan
36
+ * (regenInFlight); across processes it needs no coordination, since every
37
+ * process produces identical output from the same branch.json files.
72
38
  */
73
39
  export class BranchRegistry {
74
40
  constructor(root) {
@@ -97,10 +63,9 @@ export class BranchRegistry {
97
63
  }
98
64
  throw err;
99
65
  }
100
- // Strict version check: a truthy-only check would accept a persisted v1
101
- // snapshot (no `generation` field) left on EFS after a rolling deploy,
102
- // and `parsed.generation` would then be `undefined` rather than a real
103
- // token or explicit `null`, breaking the freshness comparison below.
66
+ // Strict version check, not truthiness: a snapshot from an older version
67
+ // left on EFS by a rolling deploy has no `generation` field, and an
68
+ // `undefined` token breaks the freshness comparison below.
104
69
  if (parsed.version !== REGISTRY_VERSION || !Array.isArray(parsed.branches)) {
105
70
  return await this.regenerate();
106
71
  }
@@ -111,15 +76,12 @@ export class BranchRegistry {
111
76
  return await this.regenerate();
112
77
  }
113
78
  /**
114
- * Returns a single branch by name. Uses cache if available.
79
+ * Returns a single branch by name, from the cached snapshot when it is fresh.
115
80
  *
116
- * Suspicious-miss backstop: if `name` isn't in the (possibly cached) list,
117
- * that's a signal the snapshot may be stale in the specific direction where
118
- * a branch that now exists is missing from it - force one fresh
119
- * regeneration and re-search before giving up, throttled per instance so a
120
- * genuinely-absent branch costs at most one extra scan per throttle window.
121
- * This bounds durable window-E staleness for the "branch exists but
122
- * snapshot predates it" direction; see the class doc comment.
81
+ * Suspicious-miss backstop: a `name` missing from the list is the signal that
82
+ * the snapshot may predate a branch that now exists, so force one fresh
83
+ * regeneration and re-search before giving up. Throttled per instance, so a
84
+ * genuinely-absent branch costs at most one extra scan per window.
123
85
  */
124
86
  async get(name) {
125
87
  const branches = await this.list();
@@ -139,23 +101,19 @@ export class BranchRegistry {
139
101
  return true;
140
102
  }
141
103
  /**
142
- * Marks the cache as stale for every process sharing this root by bumping
143
- * the cross-process generation marker, then eager-regenerates on this host
144
- * (see class doc comment for why). The bump must succeed: a swallowed
145
- * failure here would leave the registry stale indefinitely with no
146
- * bounding backstop, unlike a failed eager regen below, which only forgoes
147
- * closing window (E) early - the bump alone already restored correctness
148
- * for every future reader. A failed eager regen therefore must not fail the
149
- * caller's save/delete.
104
+ * Marks the cache stale for every process sharing this root by bumping the
105
+ * marker, then eager-regenerates on this host. The bump must succeed —
106
+ * swallowing that failure leaves the registry stale indefinitely with no
107
+ * backstop. A failed eager regen must NOT fail the caller's save/delete: the
108
+ * bump alone already restored correctness for every future reader.
150
109
  */
151
110
  async invalidate() {
152
111
  await bumpResourceGeneration(this.root, RESOURCE, { mustSucceed: true });
153
112
  try {
154
- // A scan already in flight (a concurrent list() on this shared
155
- // instance) captured the PRE-bump token and possibly pre-mutation
156
- // state; joining it via regenerate()'s dedup would skip the eager
157
- // post-bump scan this method exists for. Let it drain — its snapshot
158
- // self-describes as stale either way — then run a fresh scan.
113
+ // A scan already in flight captured the PRE-bump token and possibly
114
+ // pre-mutation state; joining it via regenerate()'s dedup would skip the
115
+ // eager post-bump scan this method exists for. Let it drain — its
116
+ // snapshot self-describes as stale either way — then scan fresh.
159
117
  if (this.regenInFlight)
160
118
  await this.regenInFlight.catch(() => { });
161
119
  await this.regenerate();
@@ -169,9 +127,8 @@ export class BranchRegistry {
169
127
  /**
170
128
  * Scans branch directories and rebuilds the cache, deduping concurrent
171
129
  * callers on this instance to a single underlying scan. Never loops waiting
172
- * for the snapshot's embedded token to match the marker - under a bump
173
- * storm that could livelock; a caller that wants the very latest state
174
- * after a concurrent bump should call list() again after this resolves.
130
+ * for the embedded token to match the marker — that livelocks under a bump
131
+ * storm; a caller wanting the very latest state calls list() again.
175
132
  */
176
133
  async regenerate() {
177
134
  if (this.regenInFlight)
@@ -191,16 +148,13 @@ export class BranchRegistry {
191
148
  // next probe instead of silently resurrecting stale data.
192
149
  const read = await readResourceGeneration(this.root, RESOURCE);
193
150
  const branches = await this.scanBranchDirectories();
194
- // Opportunistic cleanup of a stale file left by the old rename-based
195
- // invalidation scheme (e.g. a process upgraded mid-flight). Not load-bearing.
151
+ // Opportunistic cleanup of the retired stale-marker file. Not load-bearing.
196
152
  await fs.unlink(this.stalePath).catch(() => { });
197
153
  if (!read.ok) {
198
- // The marker couldn't be read for a reason other than "never bumped" -
199
- // we cannot attribute a token to this scan, and stamping the snapshot
200
- // with an unattributable token would make it indistinguishable from a
201
- // correctly-attributed one to every future reader on any host. Serve
202
- // the fresh scan result without persisting it; the next read retries
203
- // the marker read and, on success, regenerates and persists normally.
154
+ // The marker read failed for a reason other than "never bumped", so no
155
+ // token can be attributed to this scan, and a snapshot stamped with an
156
+ // unattributable one would look correctly attributed to every future
157
+ // reader on any host. Serve the fresh scan without persisting it.
204
158
  return branches;
205
159
  }
206
160
  const snapshot = {
@@ -208,8 +162,8 @@ export class BranchRegistry {
208
162
  branches,
209
163
  generation: read.token,
210
164
  };
211
- // Write to unique temp file first, then atomic rename.
212
- // Use random suffix to avoid conflicts between concurrent regenerations.
165
+ // Temp file then atomic rename; the random suffix keeps concurrent
166
+ // regenerations off each other's temp path.
213
167
  const uniqueTempPath = `${this.tempPath}.${Date.now()}.${Math.random().toString(36).slice(2)}`;
214
168
  await fs.mkdir(this.root, { recursive: true });
215
169
  await fs.writeFile(uniqueTempPath, JSON.stringify(snapshot, null, 2) + '\n', 'utf8');
@@ -217,7 +171,6 @@ export class BranchRegistry {
217
171
  await fs.rename(uniqueTempPath, this.registryPath);
218
172
  }
219
173
  catch (err) {
220
- // Clean up temp file if rename fails
221
174
  await fs.unlink(uniqueTempPath).catch(() => { });
222
175
  throw err;
223
176
  }
@@ -238,11 +191,10 @@ export class BranchRegistry {
238
191
  continue;
239
192
  }
240
193
  const branchRoot = path.join(this.root, entry.name);
241
- // Quarantine, don't propagate: one branch's corrupt/unreadable
242
- // branch.json must not take down the whole listing (a rethrow here
243
- // would 500 GET /branches for every branch). The broken branch just
244
- // drops out of the registry; it stays on disk for the admin
245
- // branch-health surface to report and repair.
194
+ // Quarantine, don't propagate: one branch's corrupt or unreadable
195
+ // branch.json must not take down the whole listing, which a rethrow
196
+ // would (500 on GET /branches, for every branch). The broken branch
197
+ // drops out of the registry and stays on disk for branch-health.
246
198
  let meta;
247
199
  try {
248
200
  meta = await readBranchMetadataFile(branchRoot);
@@ -261,7 +213,6 @@ export class BranchRegistry {
261
213
  }
262
214
  }
263
215
  catch (err) {
264
- // If root doesn't exist yet, return empty list
265
216
  if (isNotFoundError(err)) {
266
217
  return [];
267
218
  }
@@ -4,92 +4,32 @@ import type { OperatingMode } from './operating-mode/index.js';
4
4
  import type { EntrySchemaRegistry, SchemaResolutionResult } from './schema/types.js';
5
5
  /** resource-generation.ts resource key for the schema cache's marker. */
6
6
  export declare const SCHEMA_GENERATION_RESOURCE = "schema";
7
- /**
8
- * Schema cache structure stored in {branchRoot}/.canopy-meta/schema-cache.json
9
- */
7
+ /** @internal Exported for tests. */
10
8
  export interface BranchSchemaCacheEntry {
11
9
  version: number;
12
10
  schema: RootCollectionConfig;
13
11
  flatSchema: FlatSchemaItem[];
14
12
  cachedAt: string;
15
13
  /**
16
- * The resource-generation.ts marker token this snapshot was resolved
17
- * against, or null if it was built before any bump ever occurred on this
18
- * root. Compared against the live marker (via isGenerationCurrent) to
19
- * decide freshness. See the class doc comment.
14
+ * The marker token this snapshot was resolved against, or null when it was
15
+ * built before any bump on this root. Compared against the live marker (via
16
+ * isGenerationCurrent) to decide freshness.
20
17
  */
21
18
  generation: string | null;
22
19
  }
23
20
  /**
24
- * Manages per-branch schema caching with lazy loading and automatic
25
- * invalidation.
26
- *
27
- * ## Cross-process freshness (resource-generation.ts marker protocol)
28
- *
29
- * Several warm Lambda containers plus the EC2 worker can share one
30
- * branch-clone root over EFS, each with its own copy of
31
- * `schema-cache.json`. There is no shared memory and no cross-host file
32
- * watching, so freshness is coordinated via the generic on-disk generation
33
- * marker in resource-generation.ts: every cached snapshot embeds the marker
34
- * token it was resolved against, and every read cheaply re-checks the live
35
- * marker before trusting the cache. See that module's doc comment for the
36
- * full protocol and residual staleness windows (A/B/C/E).
37
- *
38
- * BranchSchemaCache is the "durable snapshot consumer" case called out there:
39
- * a resolve whose scan is served from stale NFS dentry/attribute caches can
40
- * record a FRESH token over STALE data (window E), and because the result is
41
- * written to `schema-cache.json`, that staleness becomes durable and shared
42
- * with every other host that reads the marker - not just one process's
43
- * memory. `loadFromCacheOrResolve` mitigates this the same way
44
- * BranchRegistry does:
45
- *
46
- * - The marker is captured strictly BEFORE `resolveFresh()` runs, and the
47
- * captured token (not one read after resolving) is what gets embedded in
48
- * the persisted snapshot. A bump landing mid-resolve therefore leaves the
49
- * embedded token older than the live marker, forcing a re-resolve on the
50
- * next read instead of silently resurrecting stale schema.
51
- * - A snapshot is only persisted when the marker read itself succeeded
52
- * (`{ ok: true }`). If the read fails for a reason other than "never
53
- * bumped", we cannot attribute a token to this resolve, and stamping the
54
- * snapshot with an unattributable token would make it indistinguishable
55
- * from a correctly-attributed one to every future reader. The fresh result
56
- * is still served to this caller; it just isn't written durably.
57
- * - invalidate() bumps the marker with `mustSucceed: true`: an explicit
58
- * invalidation (e.g. after a schema mutation) must not silently fail and
59
- * leave every reader confidently stale with no bounding backstop.
60
- * invalidate() itself does NOT eager-regenerate - it isn't given the
61
- * entrySchemaRegistry/contentRootName that resolveSchema needs. The
62
- * eager re-resolve (window-E mitigation, mirroring BranchRegistry's
63
- * eager regen) lives one level up in SchemaOps.invalidateSchemaCache()
64
- * (schema/schema-store.ts), which has those arguments and calls
65
- * {@link resolveAndPersist} (NOT getSchema()) right after invalidating -
66
- * so every SchemaOps mutation re-resolves on the mutating host via a scan
67
- * that is GUARANTEED to run, not merely likely to run. getSchema() would
68
- * be the wrong call here: its cache-read fast path can short-circuit
69
- * through a snapshot a DIFFERENT concurrent host just wrote (see
70
- * resolveAndPersist()'s doc comment for the exact race), silently
71
- * skipping the one scan this eager re-resolve exists to guarantee. (The
72
- * editor's follow-up schema GET is a separate Lambda invocation with no
73
- * container affinity, so it could not serve this purpose either.)
74
- * Callers of invalidate() that bypass SchemaOps (api/schema.ts's explicit
75
- * invalidate endpoint; the bulk-mutation bump in
76
- * invalidateBranchContentCaches) accept the lazy next-read regen.
77
- *
78
- * This is also why prod needs no mtime walk: the dev-only mtime check below
79
- * exists solely to catch hand edits to .collection.json made outside the CMS
80
- * (which bypass SchemaOps and therefore never bump the marker). Every
81
- * mutation path that matters in prod - SchemaOps writes, git working-tree
82
- * rewrites (checkout/merge/rebase/sync/migrate) - bumps the marker via
83
- * SchemaOps.invalidateSchemaCache() or the combined
84
- * invalidateBranchContentCaches() helper in content-index-generation.ts, so
85
- * the marker alone is a sufficient prod backstop.
21
+ * Per-branch schema cache: a file at {branchRoot}/.canopy-meta/schema-cache.json
22
+ * with no in-memory layer, so it stays coherent across Lambda invocations.
86
23
  *
87
- * Caching Strategy:
88
- * - File-based cache at {branchRoot}/.canopy-meta/schema-cache.json (no
89
- * in-memory layer - intentional: matches prod behavior and keeps cache
90
- * coherent across Lambda invocations)
91
- * - Invalidation: invalidate() bumps the cross-process generation marker;
92
- * every reader sharing this branchRoot re-resolves at its next access.
24
+ * Freshness follows the generation-marker protocol owned by
25
+ * resource-generation.ts, and this is one of that protocol's durable-snapshot
26
+ * consumers. Its eager re-resolve lives one level up, in
27
+ * `SchemaOps.invalidateSchemaCache()` (schema/schema-store.ts), because that is
28
+ * where the entrySchemaRegistry/contentRootName arguments {@link invalidate}
29
+ * lacks are available; it calls {@link resolveAndPersist}, never getSchema().
30
+ * Callers that bypass SchemaOps (api/schema.ts's invalidate endpoint, and the
31
+ * bulk git-op bump in invalidateBranchContentCaches) accept the lazy
32
+ * next-read regen instead.
93
33
  */
94
34
  export declare class BranchSchemaCache {
95
35
  /** Tracks when we last checked mtimes per contentRoot, to debounce rapid requests */
@@ -99,35 +39,23 @@ export declare class BranchSchemaCache {
99
39
  /**
100
40
  * Whether to skip the on-disk cache for this branchRoot.
101
41
  *
102
- * branchRoot equals the project root (process.cwd()) only in the synthetic
103
- * contexts used by static deployments and build phases — real branch roots are
104
- * always nested under the workspace (.canopy-dev/content-branches/<name> in dev,
105
- * <workspaceRoot>/content-branches/<name> in prod). Never write .canopy-meta/ at
106
- * the project root, regardless of which entrypoint produced the cwd branchRoot.
42
+ * Never write `.canopy-meta/` at the project root, whichever entrypoint
43
+ * produced the cwd branchRoot. branchRoot equals process.cwd() only in the
44
+ * synthetic contexts static deployments and build phases use; a real branch
45
+ * root is always nested under the workspace.
107
46
  */
108
47
  private skipDiskCache;
109
- /**
110
- * Get schema for a branch (loads from cache or resolves fresh).
111
- *
112
- * @param branchRoot - Root directory of the branch (e.g., .canopy-dev/content-branches/main)
113
- * @param entrySchemaRegistry - Map of schema names to field definitions
114
- * @param contentRootName - Name of content directory (e.g., "content") from config
115
- * @returns Resolved schema tree and flattened schema
116
- */
48
+ /** Get schema for a branch, from the cache when fresh, else resolved fresh. */
117
49
  getSchema(branchRoot: string, entrySchemaRegistry: EntrySchemaRegistry, contentRootName?: string): Promise<{
118
50
  schema: RootCollectionConfig;
119
51
  flatSchema: FlatSchemaItem[];
120
52
  }>;
121
53
  /**
122
- * Resolve the schema from disk. Wrapped in a protected method (rather than
123
- * calling the imported resolveSchema directly) so tests can subclass and
124
- * override with a deferred/blocking implementation to simulate cross-process
54
+ * Resolve the schema from disk. Protected rather than a direct resolveSchema
55
+ * call so tests can subclass and block it to simulate cross-process
125
56
  * interleavings — mirrors BranchRegistry's scanBranchDirectories() hook.
126
57
  */
127
58
  protected resolveFresh(contentRoot: string, entrySchemaRegistry: EntrySchemaRegistry): Promise<SchemaResolutionResult>;
128
- /**
129
- * Load schema from cache or resolve fresh if cache is missing or stale.
130
- */
131
59
  private loadFromCacheOrResolve;
132
60
  /**
133
61
  * Resolve the schema fresh from disk and persist it (subject to the
@@ -137,43 +65,25 @@ export declare class BranchSchemaCache {
137
65
  */
138
66
  private resolveFreshAndPersist;
139
67
  /**
140
- * Resolve the schema fresh from disk and persist it, SKIPPING the cache
141
- * read entirely -- unlike {@link getSchema}, which can short-circuit
142
- * through a cache HIT. That distinction matters for eager re-resolve after
143
- * invalidation (see {@link invalidate}'s doc comment and
144
- * `SchemaOps.invalidateSchemaCache()` in schema/schema-store.ts, the sole
145
- * intended caller): the whole point of an eager re-resolve is to guarantee
146
- * ONE scan that is coherent with the mutation this host just made. A plain
147
- * `getSchema()` call right after `invalidate()` is NOT that guarantee --
148
- * `getSchema()`'s cache-read fast path (`loadFromCacheOrResolve`) can still
149
- * return a snapshot written by a DIFFERENT, concurrent host: if that
150
- * foreign host's own eager re-resolve raced this one and embedded the
151
- * (now-current) marker token over ITS OWN stale-NFS-cache scan (the
152
- * window-E case this class's doc comment describes), this host's
153
- * `getSchema()` would happily accept that foreign snapshot as "current"
154
- * and skip the one scan this call was specifically trying to guarantee.
155
- * `resolveAndPersist()` never reads the cache file at all, so it cannot be
156
- * short-circuited that way.
68
+ * Resolve fresh from disk and persist, SKIPPING the cache read entirely.
69
+ * That is what makes it, and not {@link getSchema}, the right call for the
70
+ * eager re-resolve in `SchemaOps.invalidateSchemaCache()` (its sole intended
71
+ * caller): an eager re-resolve exists to guarantee ONE scan coherent with the
72
+ * mutation this host just made, and getSchema()'s cache-read fast path can
73
+ * instead return a snapshot a concurrent host wrote — possibly one embedding
74
+ * the now-current token over ITS own stale-NFS scan — skipping that scan.
157
75
  */
158
76
  resolveAndPersist(branchRoot: string, entrySchemaRegistry: EntrySchemaRegistry, contentRootName?: string): Promise<{
159
77
  schema: RootCollectionConfig;
160
78
  flatSchema: FlatSchemaItem[];
161
79
  }>;
162
80
  /**
163
- * Invalidate cache for a branch by bumping the cross-process generation
164
- * marker (resource-generation.ts). Every process sharing this branchRoot
165
- * will re-resolve at its next read.
166
- *
167
- * The bump must succeed: a swallowed failure here would leave the schema
168
- * cache stale indefinitely with no bounding backstop (unlike
169
- * BranchRegistry, there is no get-miss backstop for a resolved schema).
170
- *
171
- * No eager regeneration here (unlike BranchRegistry.invalidate()): this
172
- * method isn't given the entrySchemaRegistry/contentRootName resolveSchema
173
- * needs. See the class doc comment for why the mutating request's own
174
- * follow-up schema read closes the same window-E gap instead.
81
+ * Invalidate a branch's cache by bumping the marker; every process sharing
82
+ * this branchRoot re-resolves at its next read. The bump must succeed —
83
+ * swallowing that failure leaves the schema cache stale indefinitely, and
84
+ * unlike BranchRegistry there is no get-miss backstop for a resolved schema.
175
85
  *
176
- * @param branchRoot - Root directory of the branch
86
+ * No eager re-resolve here; it lives in SchemaOps (see the class doc).
177
87
  */
178
88
  invalidate(branchRoot: string): Promise<void>;
179
89
  }