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
@@ -2,8 +2,7 @@
2
2
  * Instantiate the configured AssetStore from a site's `media` config.
3
3
  *
4
4
  * This is the one place that turns the (currently-unconsumed) `media` config
5
- * into a real store — see .claude/future-tasks/assets-media-system.md for why
6
- * this was previously dead configuration.
5
+ * into a real store — see .claude/future-tasks/resolved/assets-media-system.md.
7
6
  */
8
7
  import { LocalAssetStore } from './store-local.js';
9
8
  import { S3AssetStore } from './store-s3.js';
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import { type FinalizeInput, type FinalizeRejection } from './pipeline.js';
7
7
  import type { AssetMeta, AssetStore } from './types.js';
8
+ /** @internal Exported for tests. */
8
9
  export declare function isValidStagingKey(key: string): boolean;
9
10
  export type FinalizeAssetResult = {
10
11
  ok: true;
@@ -20,10 +21,11 @@ export type FinalizeAssetResult = {
20
21
  * point for an asset's existence, so a crash between `putOriginal` and here
21
22
  * leaves only orphaned (harmless, content-addressed) blobs, never a meta
22
23
  * record pointing at a missing blob.
24
+ * @internal Exported for tests.
23
25
  */
24
26
  export declare function finalizeAsset(store: AssetStore, input: FinalizeInput): Promise<FinalizeAssetResult>;
25
27
  /**
26
- * Finalize a previously-staged upload: read the staged bytes, run
28
+ * Finalize a staged upload: read the staged bytes, run
27
29
  * `finalizeAsset`, and best-effort delete the staging object regardless of
28
30
  * outcome (success OR pipeline rejection - a rejected upload's staged bytes
29
31
  * are just as much litter as an accepted one's).
@@ -14,6 +14,7 @@ import { ASSET_PREFIXES } from './keys.js';
14
14
  * prefixes must parameterize this check if that escape hatch is ever used.
15
15
  */
16
16
  const STAGING_UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
17
+ /** @internal Exported for tests. */
17
18
  export function isValidStagingKey(key) {
18
19
  const prefix = `${ASSET_PREFIXES.staging}/`;
19
20
  return key.startsWith(prefix) && STAGING_UUID_PATTERN.test(key.slice(prefix.length));
@@ -28,6 +29,7 @@ export function isValidStagingKey(key) {
28
29
  * point for an asset's existence, so a crash between `putOriginal` and here
29
30
  * leaves only orphaned (harmless, content-addressed) blobs, never a meta
30
31
  * record pointing at a missing blob.
32
+ * @internal Exported for tests.
31
33
  */
32
34
  export async function finalizeAsset(store, input) {
33
35
  const result = await runFinalizePipeline(input);
@@ -52,7 +54,7 @@ export async function finalizeAsset(store, input) {
52
54
  return { ok: true, meta };
53
55
  }
54
56
  /**
55
- * Finalize a previously-staged upload: read the staged bytes, run
57
+ * Finalize a staged upload: read the staged bytes, run
56
58
  * `finalizeAsset`, and best-effort delete the staging object regardless of
57
59
  * outcome (success OR pipeline rejection - a rejected upload's staged bytes
58
60
  * are just as much litter as an accepted one's).
@@ -10,10 +10,10 @@ export { ASSET_PREFIXES, createKeyBuilders, hashBytes, metaKey, metaPrefix, orig
10
10
  export { LocalAssetStore, type LocalAssetStoreOptions } from './store-local.js';
11
11
  export { S3AssetStore, type S3AssetStoreOptions } from './store-s3.js';
12
12
  export { createAssetStore } from './factory.js';
13
- export { ALLOWED_UPLOAD_CONTENT_TYPES, runFinalizePipeline, type FinalizeInput, type FinalizePublicObject, type FinalizeResult, type FinalizeRejection, type FinalizeSuccess, } from './pipeline.js';
13
+ export { ALLOWED_UPLOAD_CONTENT_TYPES, runFinalizePipeline, type FinalizeInput, type FinalizeResult, type FinalizeRejection, } from './pipeline.js';
14
14
  export { finalizeAsset, finalizeStagedUpload, type FinalizeAssetResult } from './finalize.js';
15
15
  export { sanitizeSvg } from './svg-sanitizer.js';
16
- export { assetSrc, IDENTITY_TRANSFORM_DIRECTIVE } from './asset-src.js';
17
- export { formatDirectives, isAllowedTransformWidth, isValidCropRect, parseTransformPath, type CropRect, type IdentityDirectives, type OutputFormat, type ParsedTransformPath, type ParseTransformPathResult, type ResizeDirectives, type TransformDirectives, } from './transform-directives.js';
16
+ export { assetSrc } from './asset-src.js';
17
+ export { formatDirectives, isAllowedTransformWidth, isValidCropRect, parseTransformPath, type CropRect, type OutputFormat, type ParsedTransformPath, type ParseTransformPathResult, type TransformDirectives, } from './transform-directives.js';
18
18
  export { applyTransform, type ApplyTransformInput, type TransformResult } from './transform.js';
19
19
  export { assetUrl, assetSrcSet, type AssetRef, type AssetUrlOptions } from './asset-url.js';
@@ -12,7 +12,7 @@ export { createAssetStore } from './factory.js';
12
12
  export { ALLOWED_UPLOAD_CONTENT_TYPES, runFinalizePipeline, } from './pipeline.js';
13
13
  export { finalizeAsset, finalizeStagedUpload } from './finalize.js';
14
14
  export { sanitizeSvg } from './svg-sanitizer.js';
15
- export { assetSrc, IDENTITY_TRANSFORM_DIRECTIVE } from './asset-src.js';
15
+ export { assetSrc } from './asset-src.js';
16
16
  export { formatDirectives, isAllowedTransformWidth, isValidCropRect, parseTransformPath, } from './transform-directives.js';
17
17
  export { applyTransform } from './transform.js';
18
18
  export { assetUrl, assetSrcSet } from './asset-url.js';
@@ -3,7 +3,7 @@
3
3
  * here — keeps this file trivially unit-testable and safe to reason about for
4
4
  * path-traversal / header-injection concerns.
5
5
  *
6
- * Bucket-prefix layout (see .claude/future-tasks/assets-media-system.md):
6
+ * Bucket-prefix layout (see .claude/future-tasks/resolved/assets-media-system.md):
7
7
  * asset-originals/{hash32}.{ext} private; full-fidelity originals
8
8
  * asset-staging/{uuid} presigned-POST target
9
9
  * asset-meta/{hash32}.json private; filename/uploader/dims/mime
@@ -45,11 +45,13 @@ export declare function slugifyFilename(name: string): {
45
45
  */
46
46
  export declare function createKeyBuilders(prefixes?: AssetPrefixes): {
47
47
  originalKey: (hash32: string, ext: string) => string;
48
- /** Prefix used to look up an original by hash32 alone (extension unknown ahead of time). */
48
+ /** Prefix for looking up an original by hash32 alone (extension unknown ahead of time). */
49
49
  originalPrefix: (hash32: string) => string;
50
50
  stagingKey: (uuid: string) => string;
51
51
  metaKey: (hash32: string) => string;
52
52
  metaPrefix: () => string;
53
53
  publicKey: (hash32: string, slug: string, ext: string) => string;
54
54
  };
55
- export declare const originalKey: (hash32: string, ext: string) => string, originalPrefix: (hash32: string) => string, stagingKey: (uuid: string) => string, metaKey: (hash32: string) => string, metaPrefix: () => string, publicKey: (hash32: string, slug: string, ext: string) => string;
55
+ export declare const originalKey: (hash32: string, ext: string) => string, stagingKey: (uuid: string) => string, metaKey: (hash32: string) => string, publicKey: (hash32: string, slug: string, ext: string) => string;
56
+ /** @internal Exported for tests. */
57
+ export declare const originalPrefix: (hash32: string) => string, metaPrefix: () => string;
@@ -3,7 +3,7 @@
3
3
  * here — keeps this file trivially unit-testable and safe to reason about for
4
4
  * path-traversal / header-injection concerns.
5
5
  *
6
- * Bucket-prefix layout (see .claude/future-tasks/assets-media-system.md):
6
+ * Bucket-prefix layout (see .claude/future-tasks/resolved/assets-media-system.md):
7
7
  * asset-originals/{hash32}.{ext} private; full-fidelity originals
8
8
  * asset-staging/{uuid} presigned-POST target
9
9
  * asset-meta/{hash32}.json private; filename/uploader/dims/mime
@@ -76,7 +76,7 @@ export function slugifyFilename(name) {
76
76
  export function createKeyBuilders(prefixes = ASSET_PREFIXES) {
77
77
  return {
78
78
  originalKey: (hash32, ext) => `${prefixes.originals}/${hash32}.${ext}`,
79
- /** Prefix used to look up an original by hash32 alone (extension unknown ahead of time). */
79
+ /** Prefix for looking up an original by hash32 alone (extension unknown ahead of time). */
80
80
  originalPrefix: (hash32) => `${prefixes.originals}/${hash32}.`,
81
81
  stagingKey: (uuid) => `${prefixes.staging}/${uuid}`,
82
82
  metaKey: (hash32) => `${prefixes.meta}/${hash32}.json`,
@@ -84,4 +84,7 @@ export function createKeyBuilders(prefixes = ASSET_PREFIXES) {
84
84
  publicKey: (hash32, slug, ext) => `${prefixes.public}/${hash32}/${slug}.${ext}`,
85
85
  };
86
86
  }
87
- export const { originalKey, originalPrefix, stagingKey, metaKey, metaPrefix, publicKey } = createKeyBuilders();
87
+ const keyBuilders = createKeyBuilders();
88
+ export const { originalKey, stagingKey, metaKey, publicKey } = keyBuilders;
89
+ /** @internal Exported for tests. */
90
+ export const { originalPrefix, metaPrefix } = keyBuilders;
@@ -19,14 +19,14 @@ export interface FinalizeInput {
19
19
  filename: string;
20
20
  uploadedBy?: string;
21
21
  }
22
- export interface FinalizePublicObject {
22
+ interface FinalizePublicObject {
23
23
  key: string;
24
24
  data: Uint8Array;
25
25
  contentType: string;
26
26
  contentDisposition: string;
27
27
  cacheControl: string;
28
28
  }
29
- export interface FinalizeSuccess {
29
+ interface FinalizeSuccess {
30
30
  ok: true;
31
31
  meta: AssetMeta;
32
32
  /** Canonical bytes to persist as the original - sanitized bytes for svg, untouched otherwise. */
@@ -57,3 +57,4 @@ export type FinalizeResult = FinalizeSuccess | FinalizeRejection;
57
57
  * stricter sanitizer version) cannot desync a stored hash from its content.
58
58
  */
59
59
  export declare function runFinalizePipeline(input: FinalizeInput): Promise<FinalizeResult>;
60
+ export {};
@@ -114,67 +114,33 @@ const DECODE_CHECK_SIZE = 8;
114
114
  */
115
115
  const UNDECODABLE_RASTER_ERROR = 'This image could not be decoded - it may be corrupt or truncated. Try re-exporting it and uploading again.';
116
116
  /**
117
- * Force a REAL pixel decode of a raster upload, catching the defect
118
- * `computeDimensions` above (header-only, explicitly non-fatal) cannot: a
119
- * corrupt PNG IDAT / truncated JPEG scan / etc. still carries a perfectly
120
- * valid IHDR/SOF, so `file-type`/`image-size` both accept bytes that the
121
- * transform engine's real sharp/libvips decoder (transform.ts's
122
- * `applyTransform`) later refuses - with a raw "vipspng: libpng read error"
123
- * - by which point the asset has already "uploaded successfully" and renders
124
- * broken everywhere it's shown. This makes finalize use the same decoder
125
- * transform.ts does, before the bytes are ever persisted, instead of only
126
- * discovering the mismatch at render time.
117
+ * Force a real pixel decode of a raster upload: `computeDimensions` above is header-only, so
118
+ * a corrupt PNG IDAT / truncated JPEG scan with a valid IHDR/SOF passes it, then fails at
119
+ * transform.ts's real sharp/libvips decode later - "uploads fine, renders broken". This runs
120
+ * the same decoder before the bytes are ever persisted, not just at render time.
127
121
  *
128
- * `.resize()` to a tiny output - NOT `.metadata()` - is what makes this a
129
- * real test: `metadata()` only reads header fields, exactly what
130
- * `computeDimensions` above already does and exactly what fails to catch
131
- * this class of bug. libvips cannot compute a resized pixel buffer without
132
- * fully decoding the source, so a corrupt IDAT/scan still throws here even
133
- * though it would not throw from a header-only read. The output itself is
134
- * immediately discarded - decode is the expensive, unavoidable part of this
135
- * check; encoding an 8x8 buffer is not.
122
+ * `.resize()` to a tiny output, not `.metadata()`: libvips cannot compute a resized pixel
123
+ * buffer without fully decoding the source, so a corrupt IDAT/scan throws here even though a
124
+ * header-only read would not. The 8x8 output is discarded; decode is the expensive part.
136
125
  *
137
- * ANIMATION: sharp defaults to `pages: 1`, i.e. frame 0 only. That is not
138
- * enough to mirror `applyTransform`, which reads
139
- * `min(totalPages, MAX_ANIMATED_FRAMES)` frames - a GIF/WebP whose frame 0 is
140
- * clean but whose frame 3 is corrupt passed this check and then threw
141
- * `gifload_buffer: Invalid frame data` at transform time, which is the very
142
- * "accepted at upload, unrenderable at render" state this function exists to
143
- * prevent, just moved from single-frame to animated sources. So the page
144
- * count is probed and passed through, with the SAME cap constant transform.ts
145
- * uses (both import it from transform-directives.ts) - which also means the
146
- * two sides ignore the same frames past the cap, so a many-hundred-frame
147
- * source cannot produce a disagreement either.
126
+ * ANIMATION: sharp defaults to `pages: 1` (frame 0 only), which is not enough to mirror
127
+ * `applyTransform`, so the real page count is probed first and read as
128
+ * `min(totalPages, MAX_ANIMATED_FRAMES)` - the SAME cap constant transform.ts uses (both
129
+ * import it from transform-directives.ts), so the two decoders never disagree on which
130
+ * frames past the cap they ignore. The probe is required, not optional: `pages` is a fixed
131
+ * request, not an upper bound, and a value exceeding the source's real page count makes sharp
132
+ * throw "bad page number" (transform.ts documents the same constraint at its call site).
148
133
  *
149
- * The probe is a separate, deliberate step rather than a guess: sharp's
150
- * `pages` is a fixed request, not an upper bound, so a value EXCEEDING the
151
- * source's real page count makes it throw "bad page number" (transform.ts
152
- * documents the same constraint at its own call site). A metadata-only probe
153
- * costs effectively nothing - it is a header read, not a decode.
154
- *
155
- * `limitInputPixels: MAX_INPUT_PIXELS` reuses transform.ts's own
156
- * decompression-bomb cap (imported above, not redefined) so this validation
157
- * step cannot itself become a bomb vector on a header that lied about its
158
- * dimensions - in practice the pixel-count check in the caller below already
159
- * rejects those before this function is ever reached, but the cap is cheap
160
- * insurance against relying on that ordering. Note the caller's check reads
161
- * single-frame dimensions from `image-size`, so for animated sources it is
162
- * `limitInputPixels` here (which sees the full multi-page strip) that bounds
163
- * total decoded pixels - exactly as it does in transform.ts.
134
+ * `limitInputPixels: MAX_INPUT_PIXELS` reuses transform.ts's own decompression-bomb cap so
135
+ * this validation step cannot itself become a bomb vector. The caller's own pixel-count check
136
+ * (below) already rejects oversized single-frame dims from `image-size` before this runs, but
137
+ * for animated sources only this multi-page `limitInputPixels` bounds total decoded pixels.
164
138
  *
165
139
  * Fails OPEN vs. fails CLOSED, deliberately different failure modes:
166
- * - sharp itself cannot be loaded (native binary missing for this
167
- * platform/architecture, e.g. a cross-arch build) - there is no decoder
168
- * available in this environment at all, which is an environment problem,
169
- * not a fact about the uploaded file. Log it and let the upload through
170
- * unvalidated (the pre-fix behavior) rather than failing every raster
171
- * upload because of a deployment issue.
172
- * - sharp loads fine but its decoder REJECTS the bytes - that IS a fact
173
- * about this specific file, and an actionable one. Return false so the
174
- * caller rejects the upload. A throw from the page-count probe counts as
175
- * this case, not the one above: the module loaded, so an unreadable header
176
- * is again a fact about the file, and `applyTransform` would reject the
177
- * same bytes from its own probe with the same 422.
140
+ * - sharp cannot be loaded at all (missing/wrong-arch native binary) - an environment
141
+ * problem, not a fact about the file. Log it and let the upload through unvalidated.
142
+ * - sharp loads but its decoder REJECTS the bytes (including a page-count-probe throw) -
143
+ * that IS a fact about this file. Return false so the caller rejects the upload.
178
144
  */
179
145
  async function rasterIsDecodable(data) {
180
146
  // `loadSharp()` has already logged the load failure once for the process;
@@ -6,16 +6,8 @@
6
6
  *
7
7
  * Why lazily. sharp is a native addon, and loading it dlopens libvips. A
8
8
  * static `import sharp from 'sharp'` makes importing the MODULE GRAPH load
9
- * libvips. With sharp external, as in an adopter's Next 16 standalone build,
10
- * Turbopack wraps it in an async module that awaits the load when the graph is
11
- * evaluated (cms-image-build-epic.md in `.claude/future-tasks/`, "Every route
12
- * loads sharp"). transform.ts is reachable from `canopycms/server` and, through
13
- * api/assets.ts, from `canopycms/http` and so from `canopycms-next`, which a
14
- * host app's root layout can import (that adopter's did). When the libvips
15
- * `.so` was missing from its standalone output, that one static import turned
16
- * it into a 500 on every on-demand route, 404s included, and defeated
17
- * pipeline.ts's deliberate fail-open. Loaded on first use, a missing binary
18
- * affects only the image operations that need it.
9
+ * libvips. Loaded on first use, a missing binary affects only the image
10
+ * operations that need it.
19
11
  *
20
12
  * Memoized INCLUDING a rejection: a failed dlopen does not heal inside a
21
13
  * running process, so a retry would only pay for the failure again and log
@@ -6,16 +6,8 @@
6
6
  *
7
7
  * Why lazily. sharp is a native addon, and loading it dlopens libvips. A
8
8
  * static `import sharp from 'sharp'` makes importing the MODULE GRAPH load
9
- * libvips. With sharp external, as in an adopter's Next 16 standalone build,
10
- * Turbopack wraps it in an async module that awaits the load when the graph is
11
- * evaluated (cms-image-build-epic.md in `.claude/future-tasks/`, "Every route
12
- * loads sharp"). transform.ts is reachable from `canopycms/server` and, through
13
- * api/assets.ts, from `canopycms/http` and so from `canopycms-next`, which a
14
- * host app's root layout can import (that adopter's did). When the libvips
15
- * `.so` was missing from its standalone output, that one static import turned
16
- * it into a 500 on every on-demand route, 404s included, and defeated
17
- * pipeline.ts's deliberate fail-open. Loaded on first use, a missing binary
18
- * affects only the image operations that need it.
9
+ * libvips. Loaded on first use, a missing binary affects only the image
10
+ * operations that need it.
19
11
  *
20
12
  * Memoized INCLUDING a rejection: a failed dlopen does not heal inside a
21
13
  * running process, so a retry would only pay for the failure again and log
@@ -17,8 +17,7 @@ export declare class LocalAssetStore implements AssetStore {
17
17
  /**
18
18
  * Resolve a store key to an absolute filesystem path, guarding against
19
19
  * escape from the root. Keys are internally generated (never taken
20
- * verbatim from user input), but this guard is kept as defense-in-depth
21
- * (ported from the v1 LocalAssetStore).
20
+ * verbatim from user input), but this guard is kept as defense-in-depth.
22
21
  *
23
22
  * A naive `resolved.startsWith(root)` check would let a sibling directory
24
23
  * that merely shares the root's name as a prefix (e.g. root `.../assets`,
@@ -21,8 +21,7 @@ export class LocalAssetStore {
21
21
  /**
22
22
  * Resolve a store key to an absolute filesystem path, guarding against
23
23
  * escape from the root. Keys are internally generated (never taken
24
- * verbatim from user input), but this guard is kept as defense-in-depth
25
- * (ported from the v1 LocalAssetStore).
24
+ * verbatim from user input), but this guard is kept as defense-in-depth.
26
25
  *
27
26
  * A naive `resolved.startsWith(root)` check would let a sibling directory
28
27
  * that merely shares the root's name as a prefix (e.g. root `.../assets`,
@@ -16,10 +16,9 @@ export interface S3AssetStoreOptions {
16
16
  * returns. Absolute http(s) URL or a site-relative path. See `mediaSchema`'s s3 branch for
17
17
  * what this is for; see `isHttpUrlOrSameOriginPath` for what is accepted.
18
18
  *
19
- * This is NOT the `publicBaseUrl` that used to live on this interface and was deleted for
20
- * looking like the store emitted prefixed URLs. Nothing is joined onto this value and it is
21
- * never rendered or stored — it is the endpoint the browser posts to, and it is returned to
22
- * the client inside the presign response rather than in the client config.
19
+ * Not a public base URL: nothing is joined onto it and it is never rendered or stored -
20
+ * it is the endpoint the browser posts to, returned to the client inside the presign
21
+ * response rather than in the client config.
23
22
  */
24
23
  uploadUrl?: string;
25
24
  /** Override the default bucket-prefix layout (rarely needed). */
@@ -1,20 +1,12 @@
1
1
  /**
2
2
  * SVG sanitization. Server-only - never import from client/editor code.
3
3
  *
4
- * Sanitizer choice: the design record (.claude/future-tasks/assets-media-system.md)
5
- * suggested `dompurify` + a lightweight DOM shim (e.g. `linkedom`) in place of the
6
- * heavier `jsdom`. In practice that pairing is unsafe: DOMPurify's own README warns
7
- * that immature DOM shims can cause it to fail in ways that produce an XSS hole even
8
- * when DOMPurify itself behaves correctly, and that is exactly what was reproduced
9
- * here - `createDOMPurify(linkedomWindow).sanitize(dirtySvg)` returned the INPUT
10
- * UNCHANGED (a `<script>`, `onload=`, and `<foreignObject>` all survived), because
11
- * linkedom's window has no `NodeFilter` global and DOMPurify silently no-ops when it
12
- * doesn't recognize the environment as supported. That is a dangerous failure mode
13
- * for a security boundary, so this module uses `sanitize-html` instead: it works
14
- * directly on the parser tree (htmlparser2, no DOM shim to be incomplete), is
15
- * actively maintained, and - verified empirically - correctly strips scripts, event
16
- * handler attributes, and `foreignObject` while preserving a valid, still-parseable
17
- * SVG document.
4
+ * Sanitizer choice: `dompurify` + a DOM shim (e.g. `linkedom`) is unsafe here - DOMPurify
5
+ * silently returns its input unchanged when the DOM shim lacks globals it expects (linkedom
6
+ * has no `NodeFilter`), producing an XSS hole with no error raised. This module uses
7
+ * `sanitize-html` instead: it works directly on the parser tree (htmlparser2, no DOM shim to
8
+ * be incomplete) and strips scripts, event handler attributes, and `foreignObject` while
9
+ * preserving a valid, still-parseable SVG document.
18
10
  *
19
11
  * Allowlist-based (not blocklist): only elements/attributes known to be safe survive.
20
12
  * `href`/`xlink:href` are further restricted to local fragment references (`#...`) so
@@ -1,20 +1,12 @@
1
1
  /**
2
2
  * SVG sanitization. Server-only - never import from client/editor code.
3
3
  *
4
- * Sanitizer choice: the design record (.claude/future-tasks/assets-media-system.md)
5
- * suggested `dompurify` + a lightweight DOM shim (e.g. `linkedom`) in place of the
6
- * heavier `jsdom`. In practice that pairing is unsafe: DOMPurify's own README warns
7
- * that immature DOM shims can cause it to fail in ways that produce an XSS hole even
8
- * when DOMPurify itself behaves correctly, and that is exactly what was reproduced
9
- * here - `createDOMPurify(linkedomWindow).sanitize(dirtySvg)` returned the INPUT
10
- * UNCHANGED (a `<script>`, `onload=`, and `<foreignObject>` all survived), because
11
- * linkedom's window has no `NodeFilter` global and DOMPurify silently no-ops when it
12
- * doesn't recognize the environment as supported. That is a dangerous failure mode
13
- * for a security boundary, so this module uses `sanitize-html` instead: it works
14
- * directly on the parser tree (htmlparser2, no DOM shim to be incomplete), is
15
- * actively maintained, and - verified empirically - correctly strips scripts, event
16
- * handler attributes, and `foreignObject` while preserving a valid, still-parseable
17
- * SVG document.
4
+ * Sanitizer choice: `dompurify` + a DOM shim (e.g. `linkedom`) is unsafe here - DOMPurify
5
+ * silently returns its input unchanged when the DOM shim lacks globals it expects (linkedom
6
+ * has no `NodeFilter`), producing an XSS hole with no error raised. This module uses
7
+ * `sanitize-html` instead: it works directly on the parser tree (htmlparser2, no DOM shim to
8
+ * be incomplete) and strips scripts, event handler attributes, and `foreignObject` while
9
+ * preserving a valid, still-parseable SVG document.
18
10
  *
19
11
  * Allowlist-based (not blocklist): only elements/attributes known to be safe survive.
20
12
  * `href`/`xlink:href` are further restricted to local fragment references (`#...`) so
@@ -32,11 +32,11 @@ export interface CropRect {
32
32
  readonly h: number;
33
33
  }
34
34
  /** Identity ('orig'): EXIF-strip only, no resize/format/quality change. */
35
- export interface IdentityDirectives {
35
+ interface IdentityDirectives {
36
36
  readonly identity: true;
37
37
  }
38
38
  /** Non-identity directive set - every field optional, but at least one is present. */
39
- export interface ResizeDirectives {
39
+ interface ResizeDirectives {
40
40
  readonly identity: false;
41
41
  readonly width?: number;
42
42
  readonly format?: OutputFormat;
@@ -89,8 +89,6 @@ export declare const MAX_INPUT_PIXELS: number;
89
89
  export declare const MAX_ANIMATED_FRAMES = 60;
90
90
  /** True if `width` is on the allowlist: a multiple of 160 in [160, 4096]. */
91
91
  export declare function isAllowedTransformWidth(width: number): boolean;
92
- /** True if `quality` is on the allowlist: a multiple of 5 in [30, 95]. */
93
- export declare function isAllowedTransformQuality(quality: number): boolean;
94
92
  /**
95
93
  * True when x, y, w, h describe a valid normalized crop rect: all four values
96
94
  * finite and in [0,1], w and h strictly positive, and the rect fits within
@@ -112,3 +110,4 @@ export declare function parseTransformPath(segments: readonly string[]): ParseTr
112
110
  * cache key. Order is fixed alphabetically by key: c, f, q, w.
113
111
  */
114
112
  export declare function formatDirectives(directives: TransformDirectives): string;
113
+ export {};
@@ -96,7 +96,7 @@ function parseWidth(value) {
96
96
  return isAllowedTransformWidth(n) ? n : null;
97
97
  }
98
98
  /** True if `quality` is on the allowlist: a multiple of 5 in [30, 95]. */
99
- export function isAllowedTransformQuality(quality) {
99
+ function isAllowedTransformQuality(quality) {
100
100
  return (Number.isInteger(quality) &&
101
101
  quality >= MIN_QUALITY &&
102
102
  quality <= MAX_QUALITY &&
@@ -1,38 +1,25 @@
1
1
  /**
2
- * The shared transform engine: applies a parsed `TransformDirectives` to
3
- * source image bytes with sharp. Server-only - never import this from
4
- * client/editor code (this is why it lives in its own file, separate from
5
- * the dependency-free transform-directives.ts). Used by the dev-mode lazy
6
- * `/assets/t/*` emulation in api/assets.ts and, unchanged, by the prod
7
- * transform Lambda (packages/canopycms-cdk/lambda/asset-transform).
2
+ * The shared transform engine: applies a parsed `TransformDirectives` to source image bytes
3
+ * with sharp. Server-only - never import this from client/editor code (kept in its own file,
4
+ * separate from the dependency-free transform-directives.ts). Used by the dev-mode lazy
5
+ * `/assets/t/*` emulation in api/assets.ts and, unchanged, by the prod transform Lambda
6
+ * (packages/canopycms-cdk/lambda/asset-transform).
8
7
  *
9
- * sharp is imported for its TYPES only and loaded on first use through
10
- * `loadSharp()` (sharp-loader.ts), so importing this module never loads
11
- * libvips. That matters because this module sits in the import graph of
12
- * `canopycms/server` and `canopycms/http`: see sharp-loader.ts for the
13
- * adopter outage a static import caused, and eslint.config.mjs for the rule
14
- * that keeps it from coming back.
8
+ * sharp is imported for its TYPES only and loaded on first use through `loadSharp()`
9
+ * (sharp-loader.ts), so importing this module never loads libvips - see sharp-loader.ts for
10
+ * why, and eslint.config.mjs for the rule that keeps a static import from coming back.
15
11
  *
16
- * Pipeline: a cheap metadata-only probe (`limitInputPixels: MAX_INPUT_PIXELS`,
17
- * decompression-bomb defense #1) learns the real page count, so animated
18
- * GIF/WebP frames can be capped at `MAX_ANIMATED_FRAMES` (decompression-bomb
19
- * defense #2) without exceeding it and making sharp throw -> load for real
20
- * with `{ pages: min(totalPages, MAX_ANIMATED_FRAMES), limitInputPixels }` ->
21
- * `.rotate()` with no args (bakes EXIF orientation into pixels,
22
- * dropping the orientation tag) -> optional crop via `.extract()` -> optional
23
- * `.resize({ width, withoutEnlargement: true })` (never upscales) -> encode.
12
+ * Pipeline: metadata probe learns the page count (decompression-bomb defenses #1/#2) -> real
13
+ * load capped at `min(totalPages, MAX_ANIMATED_FRAMES)` -> `.rotate()` (bakes EXIF orientation
14
+ * into pixels) -> optional crop/resize (never upscales) -> encode.
24
15
  *
25
- * Identity (`orig`) and any request that omits an explicit `f=` format
26
- * re-encode through the SOURCE format rather than a fixed one: this is what
27
- * guarantees EXIF/GPS gets stripped even when no other change is requested
28
- * (sharp strips metadata by default on re-encode - `withMetadata()` is never
29
- * called here, which would undo that).
16
+ * Identity (`orig`) and any request that omits an explicit `f=` format re-encode through the
17
+ * SOURCE format rather than a fixed one: this is what guarantees EXIF/GPS gets stripped even
18
+ * when no other change is requested (sharp strips metadata by default on re-encode -
19
+ * `withMetadata()` is never called here, which would undo that).
30
20
  *
31
- * GIF has no EXIF segment (EXIF is a JPEG/TIFF APP1 marker; GIF has no such
32
- * extension block), so an identity GIF has nothing to strip - it is still
33
- * re-encoded through sharp's `.gif()` (verified: current sharp bundles cgif
34
- * and re-encodes multi-frame GIFs through the `{ animated: true }` input
35
- * path with no extra native dependency) purely for pipeline uniformity, not
21
+ * GIF has no EXIF segment (EXIF is a JPEG/TIFF APP1 marker), so an identity GIF has nothing to
22
+ * strip - it is still re-encoded through sharp's `.gif()` purely for pipeline uniformity, not
36
23
  * because GIF needs stripping.
37
24
  */
38
25
  import { type TransformDirectives } from './transform-directives.js';
@@ -41,12 +28,14 @@ export interface ApplyTransformInput {
41
28
  /** Source extension (lowercased file-type ext, e.g. 'png' | 'jpg' | 'webp' | 'gif'). */
42
29
  ext: string;
43
30
  }
31
+ /** @internal Exported for tests. */
44
32
  export interface TransformSuccess {
45
33
  ok: true;
46
34
  data: Uint8Array;
47
35
  contentType: string;
48
36
  ext: string;
49
37
  }
38
+ /** @internal Exported for tests. */
50
39
  export interface TransformRejection {
51
40
  ok: false;
52
41
  /** 400: unsupported input; 413: output too large; 422: sharp failed to process the input. */
@@ -1,38 +1,25 @@
1
1
  /**
2
- * The shared transform engine: applies a parsed `TransformDirectives` to
3
- * source image bytes with sharp. Server-only - never import this from
4
- * client/editor code (this is why it lives in its own file, separate from
5
- * the dependency-free transform-directives.ts). Used by the dev-mode lazy
6
- * `/assets/t/*` emulation in api/assets.ts and, unchanged, by the prod
7
- * transform Lambda (packages/canopycms-cdk/lambda/asset-transform).
2
+ * The shared transform engine: applies a parsed `TransformDirectives` to source image bytes
3
+ * with sharp. Server-only - never import this from client/editor code (kept in its own file,
4
+ * separate from the dependency-free transform-directives.ts). Used by the dev-mode lazy
5
+ * `/assets/t/*` emulation in api/assets.ts and, unchanged, by the prod transform Lambda
6
+ * (packages/canopycms-cdk/lambda/asset-transform).
8
7
  *
9
- * sharp is imported for its TYPES only and loaded on first use through
10
- * `loadSharp()` (sharp-loader.ts), so importing this module never loads
11
- * libvips. That matters because this module sits in the import graph of
12
- * `canopycms/server` and `canopycms/http`: see sharp-loader.ts for the
13
- * adopter outage a static import caused, and eslint.config.mjs for the rule
14
- * that keeps it from coming back.
8
+ * sharp is imported for its TYPES only and loaded on first use through `loadSharp()`
9
+ * (sharp-loader.ts), so importing this module never loads libvips - see sharp-loader.ts for
10
+ * why, and eslint.config.mjs for the rule that keeps a static import from coming back.
15
11
  *
16
- * Pipeline: a cheap metadata-only probe (`limitInputPixels: MAX_INPUT_PIXELS`,
17
- * decompression-bomb defense #1) learns the real page count, so animated
18
- * GIF/WebP frames can be capped at `MAX_ANIMATED_FRAMES` (decompression-bomb
19
- * defense #2) without exceeding it and making sharp throw -> load for real
20
- * with `{ pages: min(totalPages, MAX_ANIMATED_FRAMES), limitInputPixels }` ->
21
- * `.rotate()` with no args (bakes EXIF orientation into pixels,
22
- * dropping the orientation tag) -> optional crop via `.extract()` -> optional
23
- * `.resize({ width, withoutEnlargement: true })` (never upscales) -> encode.
12
+ * Pipeline: metadata probe learns the page count (decompression-bomb defenses #1/#2) -> real
13
+ * load capped at `min(totalPages, MAX_ANIMATED_FRAMES)` -> `.rotate()` (bakes EXIF orientation
14
+ * into pixels) -> optional crop/resize (never upscales) -> encode.
24
15
  *
25
- * Identity (`orig`) and any request that omits an explicit `f=` format
26
- * re-encode through the SOURCE format rather than a fixed one: this is what
27
- * guarantees EXIF/GPS gets stripped even when no other change is requested
28
- * (sharp strips metadata by default on re-encode - `withMetadata()` is never
29
- * called here, which would undo that).
16
+ * Identity (`orig`) and any request that omits an explicit `f=` format re-encode through the
17
+ * SOURCE format rather than a fixed one: this is what guarantees EXIF/GPS gets stripped even
18
+ * when no other change is requested (sharp strips metadata by default on re-encode -
19
+ * `withMetadata()` is never called here, which would undo that).
30
20
  *
31
- * GIF has no EXIF segment (EXIF is a JPEG/TIFF APP1 marker; GIF has no such
32
- * extension block), so an identity GIF has nothing to strip - it is still
33
- * re-encoded through sharp's `.gif()` (verified: current sharp bundles cgif
34
- * and re-encodes multi-frame GIFs through the `{ animated: true }` input
35
- * path with no extra native dependency) purely for pipeline uniformity, not
21
+ * GIF has no EXIF segment (EXIF is a JPEG/TIFF APP1 marker), so an identity GIF has nothing to
22
+ * strip - it is still re-encoded through sharp's `.gif()` purely for pipeline uniformity, not
36
23
  * because GIF needs stripping.
37
24
  */
38
25
  import { getErrorMessage } from '../utils/error.js';
@@ -109,7 +96,7 @@ function encode(pipeline, format, quality) {
109
96
  }
110
97
  /**
111
98
  * Re-encode through the source container format - used for identity and for
112
- * requests that omit `f=`. `quality` (C3) is honoured here exactly like
99
+ * requests that omit `f=`. `quality` is honoured here exactly like
113
100
  * `encode()` does for an explicit `f=`, so a `q=` directive without `f=` is
114
101
  * never silently dropped - the cache key (`formatDirectives` in
115
102
  * transform-directives.ts) already includes `q=` unconditionally, so the
@@ -1,7 +1,6 @@
1
1
  /**
2
- * Server-only auth cache exports.
3
- * These use node:fs/promises and must NOT be imported in client bundles.
4
- * Use 'canopycms/auth/cache' as the import path.
2
+ * Server-only: these use node:fs/promises and must NOT reach a client bundle.
3
+ * Import them as 'canopycms/auth/cache'.
5
4
  */
6
5
  export { FileBasedAuthCache, writeAuthCacheSnapshot } from './file-based-auth-cache.js';
7
6
  export { CachingAuthPlugin } from './caching-auth-plugin.js';
@@ -1,7 +1,6 @@
1
1
  /**
2
- * Server-only auth cache exports.
3
- * These use node:fs/promises and must NOT be imported in client bundles.
4
- * Use 'canopycms/auth/cache' as the import path.
2
+ * Server-only: these use node:fs/promises and must NOT reach a client bundle.
3
+ * Import them as 'canopycms/auth/cache'.
5
4
  */
6
5
  export { FileBasedAuthCache, writeAuthCacheSnapshot } from './file-based-auth-cache.js';
7
6
  export { CachingAuthPlugin } from './caching-auth-plugin.js';