canopycms 0.0.68-int.98 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (688) hide show
  1. package/CHANGELOG.md +2131 -0
  2. package/README.md +47 -63
  3. package/dist/ai/generate.d.ts +5 -0
  4. package/dist/ai/generate.js +244 -115
  5. package/dist/ai/index.d.ts +1 -1
  6. package/dist/ai/json-to-markdown.d.ts +21 -1
  7. package/dist/ai/json-to-markdown.js +120 -57
  8. package/dist/ai/references.d.ts +72 -0
  9. package/dist/ai/references.js +223 -0
  10. package/dist/ai/resolve-branch.js +9 -2
  11. package/dist/ai/to-plain-text.d.ts +17 -8
  12. package/dist/ai/to-plain-text.js +18 -15
  13. package/dist/ai/types.d.ts +84 -3
  14. package/dist/api/admin-branch-health.d.ts +24 -1
  15. package/dist/api/admin-branch-health.js +52 -20
  16. package/dist/api/admin.d.ts +23 -5
  17. package/dist/api/admin.js +36 -1
  18. package/dist/api/assets.js +88 -78
  19. package/dist/api/branch-create-window.d.ts +12 -0
  20. package/dist/api/branch-create-window.js +13 -0
  21. package/dist/api/branch-merge.d.ts +1 -1
  22. package/dist/api/branch-merge.js +1 -1
  23. package/dist/api/branch-review.d.ts +3 -3
  24. package/dist/api/branch-review.js +16 -7
  25. package/dist/api/branch-status.d.ts +16 -6
  26. package/dist/api/branch-status.js +57 -12
  27. package/dist/api/branch-withdraw.d.ts +2 -2
  28. package/dist/api/branch-withdraw.js +8 -3
  29. package/dist/api/branch.d.ts +25 -12
  30. package/dist/api/branch.js +164 -103
  31. package/dist/api/client.d.ts +78 -58
  32. package/dist/api/client.js +150 -117
  33. package/dist/api/comments.d.ts +12 -3
  34. package/dist/api/comments.js +118 -9
  35. package/dist/api/content.d.ts +9 -9
  36. package/dist/api/content.js +131 -22
  37. package/dist/api/entries-constants.d.ts +14 -3
  38. package/dist/api/entries-constants.js +14 -3
  39. package/dist/api/entries.d.ts +40 -2
  40. package/dist/api/entries.js +102 -6
  41. package/dist/api/github-sync.d.ts +19 -0
  42. package/dist/api/github-sync.js +50 -3
  43. package/dist/api/groups.d.ts +4 -4
  44. package/dist/api/groups.js +2 -1
  45. package/dist/api/guards.js +23 -3
  46. package/dist/api/index.d.ts +3 -1
  47. package/dist/api/index.js +1 -0
  48. package/dist/api/permissions.d.ts +21 -2
  49. package/dist/api/permissions.js +50 -3
  50. package/dist/api/request-deadline.d.ts +59 -0
  51. package/dist/api/request-deadline.js +73 -0
  52. package/dist/api/resolve-references.js +8 -7
  53. package/dist/api/route-builder.d.ts +14 -0
  54. package/dist/api/route-builder.js +14 -1
  55. package/dist/api/schema.d.ts +11 -9
  56. package/dist/api/schema.js +2 -0
  57. package/dist/api/settings-helpers.d.ts +5 -1
  58. package/dist/api/settings-helpers.js +10 -2
  59. package/dist/api/types.d.ts +18 -0
  60. package/dist/api/users-constants.d.ts +6 -0
  61. package/dist/api/users-constants.js +6 -0
  62. package/dist/assets/asset-url.d.ts +28 -16
  63. package/dist/assets/asset-url.js +51 -25
  64. package/dist/assets/finalize.js +3 -0
  65. package/dist/assets/index.d.ts +1 -1
  66. package/dist/assets/materialize.d.ts +153 -0
  67. package/dist/assets/materialize.js +402 -0
  68. package/dist/assets/store-local.d.ts +19 -5
  69. package/dist/assets/store-local.js +69 -10
  70. package/dist/assets/store-s3.d.ts +38 -7
  71. package/dist/assets/store-s3.js +128 -22
  72. package/dist/assets/transform-directives.d.ts +52 -13
  73. package/dist/assets/transform-directives.js +87 -27
  74. package/dist/assets/transform.d.ts +3 -3
  75. package/dist/assets/transform.js +13 -8
  76. package/dist/assets/types.d.ts +31 -4
  77. package/dist/auth/cache.d.ts +1 -1
  78. package/dist/auth/cache.js +1 -1
  79. package/dist/auth/caching-auth-plugin.d.ts +2 -0
  80. package/dist/auth/caching-auth-plugin.js +12 -2
  81. package/dist/auth/file-based-auth-cache.d.ts +8 -0
  82. package/dist/auth/file-based-auth-cache.js +18 -8
  83. package/dist/auth/person-name.d.ts +5 -0
  84. package/dist/auth/person-name.js +8 -0
  85. package/dist/auth/plugin.d.ts +10 -1
  86. package/dist/auth/types.d.ts +2 -0
  87. package/dist/auth/user-metadata-lookup.d.ts +21 -0
  88. package/dist/auth/user-metadata-lookup.js +116 -0
  89. package/dist/authorization/branch.d.ts +1 -1
  90. package/dist/authorization/branch.js +12 -13
  91. package/dist/authorization/groups/schema.d.ts +4 -4
  92. package/dist/authorization/helpers.d.ts +8 -0
  93. package/dist/authorization/helpers.js +8 -0
  94. package/dist/authorization/index.d.ts +1 -1
  95. package/dist/authorization/index.js +1 -1
  96. package/dist/authorization/protected-branch.d.ts +5 -4
  97. package/dist/authorization/protected-branch.js +7 -5
  98. package/dist/branch-health.d.ts +35 -8
  99. package/dist/branch-health.js +54 -18
  100. package/dist/branch-metadata-error.d.ts +27 -0
  101. package/dist/branch-metadata-error.js +23 -0
  102. package/dist/branch-metadata-file.d.ts +205 -24
  103. package/dist/branch-metadata-file.js +126 -25
  104. package/dist/branch-metadata.d.ts +45 -6
  105. package/dist/branch-metadata.js +142 -50
  106. package/dist/branch-provisioning.d.ts +167 -0
  107. package/dist/branch-provisioning.js +501 -0
  108. package/dist/branch-registry.d.ts +8 -0
  109. package/dist/branch-registry.js +61 -9
  110. package/dist/branch-schema-cache.d.ts +29 -12
  111. package/dist/branch-schema-cache.js +64 -21
  112. package/dist/branch-sparse.d.ts +23 -0
  113. package/dist/branch-sparse.js +118 -0
  114. package/dist/branch-workspace.d.ts +42 -3
  115. package/dist/branch-workspace.js +239 -100
  116. package/dist/build/asset-refs.d.ts +94 -0
  117. package/dist/build/asset-refs.js +267 -0
  118. package/dist/build/generate-ai-content.js +5 -0
  119. package/dist/build/inline-flight.d.ts +37 -0
  120. package/dist/build/inline-flight.js +142 -0
  121. package/dist/cli/asset-refs.d.ts +52 -0
  122. package/dist/cli/asset-refs.js +194 -0
  123. package/dist/cli/cli.d.ts +15 -1
  124. package/dist/cli/cli.js +8543 -3193
  125. package/dist/cli/configured-asset-store.d.ts +12 -0
  126. package/dist/cli/configured-asset-store.js +46 -0
  127. package/dist/cli/generate-ai-content.js +4244 -1072
  128. package/dist/cli/init.js +217 -126
  129. package/dist/cli/project-detect.d.ts +2 -0
  130. package/dist/cli/project-detect.js +2 -0
  131. package/dist/cli/template-files/Dockerfile.cms.template +13 -5
  132. package/dist/cli/template-files/cms-stack.ts.template +16 -13
  133. package/dist/client.d.ts +1 -2
  134. package/dist/client.js +1 -2
  135. package/dist/comment-store.d.ts +25 -0
  136. package/dist/comment-store.js +43 -8
  137. package/dist/config/flatten.js +2 -0
  138. package/dist/config/helpers.js +2 -2
  139. package/dist/config/index.d.ts +1 -1
  140. package/dist/config/schemas/config.d.ts +12 -29
  141. package/dist/config/schemas/config.js +9 -12
  142. package/dist/config/schemas/field.d.ts +3 -0
  143. package/dist/config/schemas/field.js +58 -4
  144. package/dist/config/schemas/media.d.ts +4 -13
  145. package/dist/config/schemas/media.js +5 -8
  146. package/dist/config/schemas/url.d.ts +2 -20
  147. package/dist/config/schemas/url.js +2 -25
  148. package/dist/config/types.d.ts +116 -22
  149. package/dist/config/types.js +3 -9
  150. package/dist/config/validation.d.ts +25 -4
  151. package/dist/config/validation.js +116 -3
  152. package/dist/content-id-index.js +2 -2
  153. package/dist/content-index-generation.d.ts +1 -1
  154. package/dist/content-index-generation.js +1 -1
  155. package/dist/content-listing.d.ts +10 -1
  156. package/dist/content-listing.js +22 -5
  157. package/dist/content-reader.d.ts +9 -0
  158. package/dist/content-reader.js +16 -11
  159. package/dist/content-store.d.ts +75 -12
  160. package/dist/content-store.js +249 -86
  161. package/dist/content-tree.js +2 -2
  162. package/dist/context.js +5 -2
  163. package/dist/dangling-reference-log.d.ts +17 -0
  164. package/dist/dangling-reference-log.js +29 -0
  165. package/dist/dev-content-watcher.d.ts +1 -1
  166. package/dist/dev-content-watcher.js +1 -1
  167. package/dist/editor/BranchManager.d.ts +23 -7
  168. package/dist/editor/BranchManager.js +119 -54
  169. package/dist/editor/CanopyEditor.d.ts +1 -1
  170. package/dist/editor/CanopyEditor.js +1 -2
  171. package/dist/editor/CommentsPanel.d.ts +14 -0
  172. package/dist/editor/CommentsPanel.js +68 -43
  173. package/dist/editor/Editor.d.ts +11 -5
  174. package/dist/editor/Editor.js +891 -218
  175. package/dist/editor/EditorAuthGate.d.ts +7 -1
  176. package/dist/editor/EditorAuthGate.js +41 -9
  177. package/dist/editor/EntryNavigator.d.ts +22 -0
  178. package/dist/editor/EntryNavigator.js +353 -105
  179. package/dist/editor/FormHeader.d.ts +25 -0
  180. package/dist/editor/FormHeader.js +82 -0
  181. package/dist/editor/FormRenderer.d.ts +27 -3
  182. package/dist/editor/FormRenderer.js +171 -76
  183. package/dist/editor/PreviewFrame.d.ts +40 -0
  184. package/dist/editor/PreviewFrame.js +215 -0
  185. package/dist/editor/PreviewPane.d.ts +47 -0
  186. package/dist/editor/PreviewPane.js +147 -0
  187. package/dist/editor/PreviewToolbarTools.d.ts +22 -0
  188. package/dist/editor/PreviewToolbarTools.js +73 -0
  189. package/dist/editor/admin/SystemHealthPanel.d.ts +2 -1
  190. package/dist/editor/admin/SystemHealthPanel.js +163 -33
  191. package/dist/editor/admin/useSystemHealth.d.ts +18 -0
  192. package/dist/editor/admin/useSystemHealth.js +70 -1
  193. package/dist/editor/branch-status.d.ts +17 -0
  194. package/dist/editor/branch-status.js +29 -0
  195. package/dist/editor/canopy-path.d.ts +9 -6
  196. package/dist/editor/canopy-path.js +8 -11
  197. package/dist/editor/client-reference-resolver.d.ts +43 -16
  198. package/dist/editor/client-reference-resolver.js +155 -64
  199. package/dist/editor/comments/BranchComments.d.ts +1 -1
  200. package/dist/editor/comments/BranchComments.js +2 -2
  201. package/dist/editor/comments/CloseRefusedNotice.d.ts +4 -0
  202. package/dist/editor/comments/CloseRefusedNotice.js +7 -0
  203. package/dist/editor/comments/CommentThreadsPopover.d.ts +47 -0
  204. package/dist/editor/comments/CommentThreadsPopover.js +274 -0
  205. package/dist/editor/comments/CommentWriteAlert.d.ts +11 -0
  206. package/dist/editor/comments/CommentWriteAlert.js +13 -0
  207. package/dist/editor/comments/EntryComments.d.ts +10 -4
  208. package/dist/editor/comments/EntryComments.js +14 -17
  209. package/dist/editor/comments/FieldWrapper.d.ts +18 -4
  210. package/dist/editor/comments/FieldWrapper.js +62 -28
  211. package/dist/editor/comments/InlineCommentThread.d.ts +9 -2
  212. package/dist/editor/comments/InlineCommentThread.js +11 -47
  213. package/dist/editor/comments/ThreadCarousel.d.ts +1 -1
  214. package/dist/editor/comments/ThreadCarousel.js +18 -21
  215. package/dist/editor/comments/ThreadReplyControls.d.ts +28 -0
  216. package/dist/editor/comments/ThreadReplyControls.js +92 -0
  217. package/dist/editor/comments/field-comment-context.d.ts +14 -0
  218. package/dist/editor/comments/field-comment-context.js +14 -0
  219. package/dist/editor/comments/form-comments.d.ts +48 -0
  220. package/dist/editor/comments/form-comments.js +178 -0
  221. package/dist/editor/comments/item-anchor-copy.d.ts +6 -0
  222. package/dist/editor/comments/item-anchor-copy.js +6 -0
  223. package/dist/editor/comments/move-focus-if-unmoved.d.ts +6 -0
  224. package/dist/editor/comments/move-focus-if-unmoved.js +11 -0
  225. package/dist/editor/comments/popover-placement.d.ts +18 -0
  226. package/dist/editor/comments/popover-placement.js +58 -0
  227. package/dist/editor/comments/use-tracked-writes.d.ts +16 -0
  228. package/dist/editor/comments/use-tracked-writes.js +53 -0
  229. package/dist/editor/components/BranchAccessList.d.ts +15 -0
  230. package/dist/editor/components/BranchAccessList.js +52 -0
  231. package/dist/editor/components/BranchLockBanner.d.ts +22 -0
  232. package/dist/editor/components/BranchLockBanner.js +39 -0
  233. package/dist/editor/components/BranchPill.d.ts +32 -0
  234. package/dist/editor/components/BranchPill.js +33 -0
  235. package/dist/editor/components/BranchesDrawer.d.ts +11 -0
  236. package/dist/editor/components/BranchesDrawer.js +5 -0
  237. package/dist/editor/components/ConfirmDeleteModal.d.ts +6 -1
  238. package/dist/editor/components/ConfirmDeleteModal.js +3 -2
  239. package/dist/editor/components/DestructiveMenuItem.d.ts +7 -0
  240. package/dist/editor/components/DestructiveMenuItem.js +8 -0
  241. package/dist/editor/components/EditorCrashScreen.d.ts +17 -0
  242. package/dist/editor/components/EditorCrashScreen.js +22 -0
  243. package/dist/editor/components/EditorErrorBoundary.d.ts +38 -0
  244. package/dist/editor/components/EditorErrorBoundary.js +40 -0
  245. package/dist/editor/components/EditorHeader.d.ts +56 -106
  246. package/dist/editor/components/EditorHeader.js +130 -131
  247. package/dist/editor/components/EditorRail.d.ts +49 -0
  248. package/dist/editor/components/EditorRail.js +65 -0
  249. package/dist/editor/components/EntryBreadcrumb.d.ts +33 -0
  250. package/dist/editor/components/EntryBreadcrumb.js +56 -0
  251. package/dist/editor/components/EntryCreateModal.d.ts +12 -7
  252. package/dist/editor/components/EntryCreateModal.js +51 -57
  253. package/dist/editor/components/NoEditPermissionNotice.d.ts +6 -5
  254. package/dist/editor/components/NoEditPermissionNotice.js +5 -4
  255. package/dist/editor/components/QuickOpenPalette.d.ts +22 -0
  256. package/dist/editor/components/QuickOpenPalette.js +66 -0
  257. package/dist/editor/components/ReadOnlyDraftNotice.d.ts +11 -0
  258. package/dist/editor/components/ReadOnlyDraftNotice.js +12 -0
  259. package/dist/editor/components/ReasonedMenuItem.d.ts +15 -0
  260. package/dist/editor/components/ReasonedMenuItem.js +15 -0
  261. package/dist/editor/components/ReferencedByList.d.ts +11 -0
  262. package/dist/editor/components/ReferencedByList.js +28 -0
  263. package/dist/editor/components/RelativeTime.d.ts +10 -0
  264. package/dist/editor/components/RelativeTime.js +10 -0
  265. package/dist/editor/components/RenameEntryModal.d.ts +9 -1
  266. package/dist/editor/components/RenameEntryModal.js +19 -31
  267. package/dist/editor/components/RetryToastMessage.d.ts +9 -0
  268. package/dist/editor/components/RetryToastMessage.js +6 -0
  269. package/dist/editor/components/SaveAllResult.d.ts +25 -0
  270. package/dist/editor/components/SaveAllResult.js +86 -0
  271. package/dist/editor/components/SaveSplitButton.d.ts +30 -0
  272. package/dist/editor/components/SaveSplitButton.js +108 -0
  273. package/dist/editor/components/StagedChangesDrawer.d.ts +39 -0
  274. package/dist/editor/components/StagedChangesDrawer.js +92 -0
  275. package/dist/editor/components/UnavailableEntryNotice.d.ts +6 -0
  276. package/dist/editor/components/UnavailableEntryNotice.js +9 -0
  277. package/dist/editor/components/UnavailableTypeMessage.d.ts +6 -0
  278. package/dist/editor/components/UnavailableTypeMessage.js +9 -0
  279. package/dist/editor/components/UndoToastMessage.d.ts +18 -0
  280. package/dist/editor/components/UndoToastMessage.js +10 -0
  281. package/dist/editor/components/UserBadge.d.ts +2 -5
  282. package/dist/editor/components/UserBadge.js +62 -33
  283. package/dist/editor/components/ValidationSummary.d.ts +14 -0
  284. package/dist/editor/components/ValidationSummary.js +24 -0
  285. package/dist/editor/components/index.d.ts +2 -2
  286. package/dist/editor/components/index.js +2 -2
  287. package/dist/editor/context/ApiClientContext.d.ts +8 -2
  288. package/dist/editor/context/ApiClientContext.js +19 -8
  289. package/dist/editor/context/AssetContext.d.ts +13 -35
  290. package/dist/editor/context/AssetContext.js +12 -31
  291. package/dist/editor/context/EditorStateContext.d.ts +4 -4
  292. package/dist/editor/context/EditorStateContext.js +4 -4
  293. package/dist/editor/context/SWRProvider.d.ts +3 -3
  294. package/dist/editor/context/SiteMdxAllowContext.d.ts +4 -0
  295. package/dist/editor/context/SiteMdxAllowContext.js +7 -0
  296. package/dist/editor/context/index.d.ts +2 -1
  297. package/dist/editor/context/index.js +2 -1
  298. package/dist/editor/contrast.d.ts +19 -0
  299. package/dist/editor/contrast.js +41 -0
  300. package/dist/editor/copy.d.ts +18 -0
  301. package/dist/editor/copy.js +18 -0
  302. package/dist/editor/editor-config.js +16 -0
  303. package/dist/editor/editor-utils.d.ts +34 -8
  304. package/dist/editor/editor-utils.js +42 -20
  305. package/dist/editor/entry-search.d.ts +20 -0
  306. package/dist/editor/entry-search.js +34 -0
  307. package/dist/editor/field-breadcrumb.d.ts +12 -0
  308. package/dist/editor/field-breadcrumb.js +85 -0
  309. package/dist/editor/field-props.d.ts +86 -0
  310. package/dist/editor/field-props.js +27 -0
  311. package/dist/editor/field-target.d.ts +30 -0
  312. package/dist/editor/field-target.js +77 -0
  313. package/dist/editor/fields/BlockField.d.ts +12 -0
  314. package/dist/editor/fields/BlockField.js +89 -73
  315. package/dist/editor/fields/CodeField.d.ts +2 -0
  316. package/dist/editor/fields/CodeField.js +6 -2
  317. package/dist/editor/fields/DateTimeField.d.ts +4 -29
  318. package/dist/editor/fields/DateTimeField.js +79 -41
  319. package/dist/editor/fields/ExpandAllButton.d.ts +6 -0
  320. package/dist/editor/fields/ExpandAllButton.js +4 -0
  321. package/dist/editor/fields/FieldCrashFallback.d.ts +17 -0
  322. package/dist/editor/fields/FieldCrashFallback.js +30 -0
  323. package/dist/editor/fields/FieldLabel.d.ts +37 -0
  324. package/dist/editor/fields/FieldLabel.js +19 -0
  325. package/dist/editor/fields/ImageField.d.ts +4 -0
  326. package/dist/editor/fields/ImageField.js +29 -14
  327. package/dist/editor/fields/InlineGroupField.js +4 -3
  328. package/dist/editor/fields/ItemList.d.ts +42 -0
  329. package/dist/editor/fields/ItemList.js +130 -0
  330. package/dist/editor/fields/MarkdownField.d.ts +32 -0
  331. package/dist/editor/fields/MarkdownField.js +223 -46
  332. package/dist/editor/fields/MdxImageDialog.js +1 -1
  333. package/dist/editor/fields/NumberField.d.ts +2 -0
  334. package/dist/editor/fields/NumberField.js +8 -5
  335. package/dist/editor/fields/NumberListField.d.ts +2 -0
  336. package/dist/editor/fields/NumberListField.js +19 -16
  337. package/dist/editor/fields/ObjectField.d.ts +2 -7
  338. package/dist/editor/fields/ObjectField.js +15 -5
  339. package/dist/editor/fields/ObjectListField.d.ts +29 -0
  340. package/dist/editor/fields/ObjectListField.js +57 -0
  341. package/dist/editor/fields/ReferenceField.d.ts +2 -0
  342. package/dist/editor/fields/ReferenceField.js +34 -9
  343. package/dist/editor/fields/SelectField.d.ts +2 -0
  344. package/dist/editor/fields/SelectField.js +11 -2
  345. package/dist/editor/fields/StringListField.d.ts +4 -1
  346. package/dist/editor/fields/StringListField.js +22 -8
  347. package/dist/editor/fields/TextField.d.ts +2 -0
  348. package/dist/editor/fields/TextField.js +6 -2
  349. package/dist/editor/fields/ToggleField.d.ts +2 -0
  350. package/dist/editor/fields/ToggleField.js +8 -3
  351. package/dist/editor/fields/entry-link/InsertEntryLink.d.ts +1 -1
  352. package/dist/editor/fields/entry-link/InsertEntryLink.js +1 -1
  353. package/dist/editor/fields/form-expansion.d.ts +9 -0
  354. package/dist/editor/fields/form-expansion.js +2 -0
  355. package/dist/editor/fields/item-expansion.d.ts +15 -0
  356. package/dist/editor/fields/item-expansion.js +60 -0
  357. package/dist/editor/fields/list-item-keys.d.ts +8 -0
  358. package/dist/editor/fields/list-item-keys.js +50 -0
  359. package/dist/editor/fields/list-item-title.d.ts +20 -0
  360. package/dist/editor/fields/list-item-title.js +85 -0
  361. package/dist/editor/fields/markdown-export-options.d.ts +2 -0
  362. package/dist/editor/fields/markdown-export-options.js +8 -0
  363. package/dist/editor/fields/markdown-fidelity-visitors.d.ts +11 -0
  364. package/dist/editor/fields/markdown-fidelity-visitors.js +160 -0
  365. package/dist/editor/fields/mdx-jsx-support.d.ts +5 -1
  366. package/dist/editor/fields/mdx-jsx-support.js +157 -69
  367. package/dist/editor/fields/rich-text-failures.d.ts +5 -0
  368. package/dist/editor/fields/rich-text-failures.js +26 -0
  369. package/dist/editor/fields/toolbar-wrap.d.ts +7 -0
  370. package/dist/editor/fields/toolbar-wrap.js +35 -0
  371. package/dist/editor/form-outline.d.ts +13 -0
  372. package/dist/editor/form-outline.js +70 -0
  373. package/dist/editor/group-manager/GroupCard.d.ts +4 -1
  374. package/dist/editor/group-manager/GroupCard.js +12 -3
  375. package/dist/editor/group-manager/GroupForm.js +1 -1
  376. package/dist/editor/group-manager/InternalGroupsTab.d.ts +2 -1
  377. package/dist/editor/group-manager/InternalGroupsTab.js +4 -4
  378. package/dist/editor/group-manager/MemberList.d.ts +2 -1
  379. package/dist/editor/group-manager/MemberList.js +15 -4
  380. package/dist/editor/group-manager/hooks/useGroupState.d.ts +5 -0
  381. package/dist/editor/group-manager/hooks/useGroupState.js +30 -7
  382. package/dist/editor/group-manager/index.js +34 -5
  383. package/dist/editor/group-manager/types.d.ts +5 -2
  384. package/dist/editor/hooks/create-branch-request.d.ts +20 -0
  385. package/dist/editor/hooks/create-branch-request.js +54 -0
  386. package/dist/editor/hooks/save-all.d.ts +68 -0
  387. package/dist/editor/hooks/save-all.js +61 -0
  388. package/dist/editor/hooks/useBranchActions.d.ts +11 -1
  389. package/dist/editor/hooks/useBranchActions.js +42 -19
  390. package/dist/editor/hooks/useBranchManager.d.ts +21 -0
  391. package/dist/editor/hooks/useBranchManager.js +321 -125
  392. package/dist/editor/hooks/useBranchesData.d.ts +8 -4
  393. package/dist/editor/hooks/useBranchesData.js +9 -5
  394. package/dist/editor/hooks/useCommentSystem.d.ts +14 -2
  395. package/dist/editor/hooks/useCommentSystem.js +79 -55
  396. package/dist/editor/hooks/useCommentsData.d.ts +11 -7
  397. package/dist/editor/hooks/useCommentsData.js +20 -19
  398. package/dist/editor/hooks/useDraftManager.d.ts +77 -3
  399. package/dist/editor/hooks/useDraftManager.js +887 -94
  400. package/dist/editor/hooks/useEditorLayout.d.ts +53 -7
  401. package/dist/editor/hooks/useEditorLayout.js +98 -20
  402. package/dist/editor/hooks/useEntriesData.d.ts +2 -1
  403. package/dist/editor/hooks/useEntriesData.js +18 -4
  404. package/dist/editor/hooks/useEntryManager.d.ts +41 -2
  405. package/dist/editor/hooks/useEntryManager.js +227 -41
  406. package/dist/editor/hooks/useGroupManager.js +13 -16
  407. package/dist/editor/hooks/usePermissionManager.js +14 -6
  408. package/dist/editor/hooks/usePreviewMarks.d.ts +21 -0
  409. package/dist/editor/hooks/usePreviewMarks.js +33 -0
  410. package/dist/editor/hooks/useReferenceResolution.d.ts +10 -3
  411. package/dist/editor/hooks/useReferenceResolution.js +34 -177
  412. package/dist/editor/hooks/useSchemaManager.d.ts +25 -6
  413. package/dist/editor/hooks/useSchemaManager.js +97 -39
  414. package/dist/editor/hooks/useUserMetadata.d.ts +14 -4
  415. package/dist/editor/hooks/useUserMetadata.js +76 -47
  416. package/dist/editor/hooks/user-metadata-batcher.d.ts +8 -0
  417. package/dist/editor/hooks/user-metadata-batcher.js +33 -0
  418. package/dist/editor/media/AssetCard.d.ts +6 -7
  419. package/dist/editor/media/AssetCard.js +24 -31
  420. package/dist/editor/media/AssetListRow.d.ts +16 -0
  421. package/dist/editor/media/AssetListRow.js +41 -0
  422. package/dist/editor/media/CropStep.js +6 -1
  423. package/dist/editor/media/MediaLibrary.d.ts +4 -3
  424. package/dist/editor/media/MediaLibrary.js +11 -4
  425. package/dist/editor/media/MediaLibraryBody.d.ts +3 -3
  426. package/dist/editor/media/MediaLibraryBody.js +195 -80
  427. package/dist/editor/media/MediaLibrarySkeleton.d.ts +6 -0
  428. package/dist/editor/media/MediaLibrarySkeleton.js +14 -0
  429. package/dist/editor/media/crop-math.d.ts +3 -4
  430. package/dist/editor/media/crop-math.js +11 -22
  431. package/dist/editor/media/editor-image-src.d.ts +8 -0
  432. package/dist/editor/media/editor-image-src.js +10 -0
  433. package/dist/editor/media/format-bytes.d.ts +2 -0
  434. package/dist/editor/media/format-bytes.js +23 -0
  435. package/dist/editor/media/media-library-prefs.d.ts +23 -0
  436. package/dist/editor/media/media-library-prefs.js +49 -0
  437. package/dist/editor/media/media-library-view.d.ts +34 -0
  438. package/dist/editor/media/media-library-view.js +40 -0
  439. package/dist/editor/media/useAssetLibrary.d.ts +30 -0
  440. package/dist/editor/media/useAssetLibrary.js +126 -0
  441. package/dist/editor/media/useStableAssetOrder.d.ts +11 -0
  442. package/dist/editor/media/useStableAssetOrder.js +37 -0
  443. package/dist/editor/media/useThumbnailFailure.d.ts +6 -0
  444. package/dist/editor/media/useThumbnailFailure.js +16 -0
  445. package/dist/editor/permission-manager/GroupSelector.js +2 -2
  446. package/dist/editor/permission-manager/PermissionEditor.d.ts +1 -1
  447. package/dist/editor/permission-manager/PermissionEditor.js +15 -4
  448. package/dist/editor/permission-manager/PermissionLevelBadge.js +1 -1
  449. package/dist/editor/permission-manager/PermissionTree.d.ts +1 -1
  450. package/dist/editor/permission-manager/UserSelector.d.ts +1 -1
  451. package/dist/editor/permission-manager/UserSelector.js +3 -3
  452. package/dist/editor/permission-manager/index.js +12 -3
  453. package/dist/editor/permission-manager/types.d.ts +5 -2
  454. package/dist/editor/platform.d.ts +3 -0
  455. package/dist/editor/platform.js +9 -0
  456. package/dist/editor/preview-asset-base.d.ts +9 -0
  457. package/dist/editor/preview-asset-base.js +17 -0
  458. package/dist/editor/preview-bridge.d.ts +51 -27
  459. package/dist/editor/preview-bridge.js +103 -144
  460. package/dist/editor/preview-marks.d.ts +15 -0
  461. package/dist/editor/preview-marks.js +74 -0
  462. package/dist/editor/preview-path.d.ts +12 -0
  463. package/dist/editor/preview-path.js +45 -1
  464. package/dist/editor/preview-scale.d.ts +27 -0
  465. package/dist/editor/preview-scale.js +34 -0
  466. package/dist/editor/raw-asset-base.d.ts +5 -0
  467. package/dist/editor/raw-asset-base.js +14 -0
  468. package/dist/editor/relative-time.d.ts +4 -4
  469. package/dist/editor/relative-time.js +16 -8
  470. package/dist/editor/schema-editor/CollectionEditor.d.ts +20 -3
  471. package/dist/editor/schema-editor/CollectionEditor.js +361 -62
  472. package/dist/editor/schema-editor/EntryTypeEditor.d.ts +5 -1
  473. package/dist/editor/schema-editor/EntryTypeEditor.js +11 -6
  474. package/dist/editor/schema-editor/collection-draft.d.ts +22 -0
  475. package/dist/editor/schema-editor/collection-draft.js +40 -0
  476. package/dist/editor/schema-editor/index.d.ts +1 -1
  477. package/dist/editor/schema-label.d.ts +10 -0
  478. package/dist/editor/schema-label.js +17 -0
  479. package/dist/editor/settings-conflict.d.ts +5 -0
  480. package/dist/editor/settings-conflict.js +8 -0
  481. package/dist/editor/shell/ActivityRail.d.ts +37 -0
  482. package/dist/editor/shell/ActivityRail.js +91 -0
  483. package/dist/editor/shell/EditorShell.d.ts +17 -0
  484. package/dist/editor/shell/EditorShell.js +31 -0
  485. package/dist/editor/shell/PaneLayout.d.ts +28 -0
  486. package/dist/editor/shell/PaneLayout.js +116 -0
  487. package/dist/editor/shell/SidePanelHost.d.ts +35 -0
  488. package/dist/editor/shell/SidePanelHost.js +184 -0
  489. package/dist/editor/shell/TopBar.d.ts +12 -0
  490. package/dist/editor/shell/TopBar.js +14 -0
  491. package/dist/editor/shell/host-chrome.d.ts +16 -0
  492. package/dist/editor/shell/host-chrome.js +69 -0
  493. package/dist/editor/slug.d.ts +16 -0
  494. package/dist/editor/slug.js +43 -0
  495. package/dist/editor/theme.d.ts +2 -1
  496. package/dist/editor/theme.js +314 -13
  497. package/dist/editor/unanswered.d.ts +17 -0
  498. package/dist/editor/unanswered.js +26 -0
  499. package/dist/editor/unavailable-entry-type.d.ts +20 -0
  500. package/dist/editor/unavailable-entry-type.js +28 -0
  501. package/dist/editor/undo-removal.d.ts +57 -0
  502. package/dist/editor/undo-removal.js +163 -0
  503. package/dist/editor/user-display.d.ts +4 -0
  504. package/dist/editor/user-display.js +5 -0
  505. package/dist/editor/utils/confirm-modal.d.ts +8 -0
  506. package/dist/editor/utils/confirm-modal.js +12 -0
  507. package/dist/editor/utils/editor-errors.d.ts +19 -0
  508. package/dist/editor/utils/editor-errors.js +32 -0
  509. package/dist/editor/utils/focus-return.d.ts +56 -0
  510. package/dist/editor/utils/focus-return.js +106 -0
  511. package/dist/entry-link-resolver.d.ts +11 -1
  512. package/dist/entry-link-resolver.js +65 -5
  513. package/dist/entry-schema-registry.d.ts +3 -3
  514. package/dist/entry-schema-registry.js +7 -4
  515. package/dist/entry-schema.d.ts +49 -3
  516. package/dist/entry-schema.js +18 -0
  517. package/dist/git-manager.d.ts +172 -10
  518. package/dist/git-manager.js +449 -107
  519. package/dist/github-service.d.ts +39 -2
  520. package/dist/github-service.js +101 -7
  521. package/dist/http/handler.js +74 -9
  522. package/dist/http/types.d.ts +2 -0
  523. package/dist/http/worker-not-ready.d.ts +9 -4
  524. package/dist/http/worker-not-ready.js +59 -6
  525. package/dist/index.d.ts +2 -0
  526. package/dist/index.js +3 -0
  527. package/dist/item-keys.d.ts +46 -0
  528. package/dist/item-keys.js +235 -0
  529. package/dist/operating-mode/editor-mode-check.d.ts +15 -0
  530. package/dist/operating-mode/editor-mode-check.js +24 -0
  531. package/dist/operating-mode/mode-env.d.ts +13 -14
  532. package/dist/operating-mode/mode-env.js +13 -14
  533. package/dist/operating-mode/types.d.ts +2 -2
  534. package/dist/paths/branch.d.ts +0 -1
  535. package/dist/paths/branch.js +1 -8
  536. package/dist/paths/index.d.ts +1 -1
  537. package/dist/paths/index.js +1 -1
  538. package/dist/paths/validation.js +0 -2
  539. package/dist/preview.d.ts +8 -0
  540. package/dist/preview.js +7 -0
  541. package/dist/reference-resolver.js +1 -0
  542. package/dist/resolve-canopy-user.d.ts +1 -1
  543. package/dist/resolve-canopy-user.js +1 -1
  544. package/dist/schema/meta-loader.d.ts +18 -8
  545. package/dist/schema/meta-loader.js +42 -9
  546. package/dist/schema/registry-fingerprint.d.ts +14 -0
  547. package/dist/schema/registry-fingerprint.js +63 -0
  548. package/dist/schema/resolver.d.ts +7 -4
  549. package/dist/schema/resolver.js +7 -6
  550. package/dist/schema/schema-store.d.ts +7 -10
  551. package/dist/schema/schema-store.js +13 -11
  552. package/dist/schema/schema-unavailable-error.d.ts +11 -0
  553. package/dist/schema/schema-unavailable-error.js +15 -0
  554. package/dist/schema/types.d.ts +22 -0
  555. package/dist/schema-registry-record.d.ts +35 -0
  556. package/dist/schema-registry-record.js +134 -0
  557. package/dist/server.d.ts +79 -9
  558. package/dist/server.js +62 -8
  559. package/dist/services.d.ts +33 -5
  560. package/dist/services.js +155 -37
  561. package/dist/settings-workspace.d.ts +23 -3
  562. package/dist/settings-workspace.js +159 -45
  563. package/dist/stamp-on-publish.d.ts +36 -0
  564. package/dist/stamp-on-publish.js +71 -0
  565. package/dist/static/index.d.ts +58 -5
  566. package/dist/static/index.js +133 -3
  567. package/dist/static/seo.d.ts +5 -5
  568. package/dist/static/seo.js +5 -5
  569. package/dist/submission-attribution.d.ts +8 -0
  570. package/dist/submission-attribution.js +22 -0
  571. package/dist/system-users.d.ts +12 -0
  572. package/dist/system-users.js +12 -0
  573. package/dist/task-queue/cms-task-queue.d.ts +1 -1
  574. package/dist/task-queue/cms-task-queue.js +1 -1
  575. package/dist/task-queue/index.d.ts +1 -1
  576. package/dist/task-queue/index.js +1 -1
  577. package/dist/task-queue/task-queue.d.ts +6 -0
  578. package/dist/task-queue/task-queue.js +29 -0
  579. package/dist/task-queue/worker-status.d.ts +35 -9
  580. package/dist/task-queue/worker-status.js +84 -17
  581. package/dist/types.d.ts +90 -9
  582. package/dist/url-collision.js +3 -3
  583. package/dist/url-exclusivity-fixtures.d.ts +8 -1
  584. package/dist/url-exclusivity-fixtures.js +11 -1
  585. package/dist/user.js +2 -1
  586. package/dist/utils/atomic-write.js +2 -1
  587. package/dist/utils/base-branch.d.ts +13 -0
  588. package/dist/utils/base-branch.js +23 -0
  589. package/dist/utils/content-serialize.d.ts +15 -7
  590. package/dist/utils/content-serialize.js +353 -51
  591. package/dist/utils/content-write-lock.d.ts +6 -1
  592. package/dist/utils/content-write-lock.js +21 -6
  593. package/dist/utils/debug.d.ts +1 -1
  594. package/dist/utils/debug.js +5 -3
  595. package/dist/utils/error.js +13 -2
  596. package/dist/utils/escape-text.d.ts +7 -0
  597. package/dist/utils/escape-text.js +27 -0
  598. package/dist/utils/fs.d.ts +12 -4
  599. package/dist/utils/fs.js +18 -5
  600. package/dist/utils/git.d.ts +21 -1
  601. package/dist/utils/git.js +63 -8
  602. package/dist/utils/json-source-splice.d.ts +14 -0
  603. package/dist/utils/json-source-splice.js +120 -0
  604. package/dist/utils/markdown-body-splice.d.ts +39 -0
  605. package/dist/utils/markdown-body-splice.js +421 -0
  606. package/dist/utils/occ-json-write.js +18 -12
  607. package/dist/utils/provision-log.d.ts +25 -0
  608. package/dist/utils/provision-log.js +49 -0
  609. package/dist/utils/provisioning-lock.d.ts +32 -1
  610. package/dist/utils/provisioning-lock.js +78 -32
  611. package/dist/utils/sanitize-href.d.ts +9 -23
  612. package/dist/utils/sanitize-href.js +14 -28
  613. package/dist/utils/title-field.d.ts +10 -0
  614. package/dist/utils/title-field.js +47 -0
  615. package/dist/utils/yaml-source-splice.d.ts +58 -0
  616. package/dist/utils/yaml-source-splice.js +515 -0
  617. package/dist/validation/block-structural-keys.d.ts +1 -1
  618. package/dist/validation/block-structural-keys.js +1 -1
  619. package/dist/validation/deletion-checker.d.ts +21 -29
  620. package/dist/validation/deletion-checker.js +41 -117
  621. package/dist/validation/entry-validator.d.ts +6 -10
  622. package/dist/validation/entry-validator.js +19 -26
  623. package/dist/validation/field-traversal.d.ts +22 -0
  624. package/dist/validation/field-traversal.js +39 -8
  625. package/dist/validation/markdown-safety.d.ts +68 -0
  626. package/dist/validation/markdown-safety.js +596 -0
  627. package/dist/validation/mdx-allowlist.d.ts +55 -0
  628. package/dist/validation/mdx-allowlist.js +183 -0
  629. package/dist/validation/reference-validator.d.ts +2 -0
  630. package/dist/validation/reference-validator.js +3 -0
  631. package/dist/version.d.ts +1 -1
  632. package/dist/version.js +1 -1
  633. package/dist/worker/branch-policy.d.ts +124 -0
  634. package/dist/worker/branch-policy.js +243 -0
  635. package/dist/worker/bundle-header.d.ts +117 -0
  636. package/dist/worker/bundle-header.js +253 -0
  637. package/dist/worker/cms-worker.d.ts +236 -142
  638. package/dist/worker/cms-worker.js +772 -285
  639. package/dist/worker/gateway-egress.d.ts +43 -0
  640. package/dist/worker/gateway-egress.js +209 -0
  641. package/dist/worker/gateway-instance.d.ts +42 -0
  642. package/dist/worker/gateway-instance.js +129 -0
  643. package/dist/worker/git-process.d.ts +81 -0
  644. package/dist/worker/git-process.js +234 -0
  645. package/dist/worker/git-sync.d.ts +34 -17
  646. package/dist/worker/git-sync.js +394 -131
  647. package/dist/worker/github-auth.d.ts +9 -9
  648. package/dist/worker/github-auth.js +13 -15
  649. package/dist/worker/github-gateway-http.d.ts +62 -0
  650. package/dist/worker/github-gateway-http.js +977 -0
  651. package/dist/worker/github-gateway-wire.d.ts +590 -0
  652. package/dist/worker/github-gateway-wire.js +488 -0
  653. package/dist/worker/github-gateway.d.ts +238 -0
  654. package/dist/worker/github-gateway.js +726 -0
  655. package/dist/worker/github-mirror-upkeep.d.ts +75 -0
  656. package/dist/worker/github-mirror-upkeep.js +266 -0
  657. package/dist/worker/github-mirror.d.ts +364 -0
  658. package/dist/worker/github-mirror.js +1030 -0
  659. package/dist/worker/github-transfer.d.ts +56 -0
  660. package/dist/worker/github-transfer.js +444 -0
  661. package/dist/worker/history-rewrite.d.ts +4 -5
  662. package/dist/worker/history-rewrite.js +12 -17
  663. package/dist/worker/provisioned-workspace.d.ts +5 -5
  664. package/dist/worker/provisioned-workspace.js +5 -5
  665. package/dist/worker/rebase.d.ts +1 -1
  666. package/dist/worker/rebase.js +58 -54
  667. package/dist/worker/remote-git-maintenance.d.ts +3 -0
  668. package/dist/worker/remote-git-maintenance.js +12 -0
  669. package/dist/worker/schema-gate.d.ts +49 -0
  670. package/dist/worker/schema-gate.js +226 -0
  671. package/dist/worker/self-checks.d.ts +107 -0
  672. package/dist/worker/self-checks.js +358 -0
  673. package/dist/worker/shared-repo-git.d.ts +96 -0
  674. package/dist/worker/shared-repo-git.js +459 -0
  675. package/dist/worker/sparse-cone.d.ts +20 -0
  676. package/dist/worker/sparse-cone.js +136 -0
  677. package/dist/worker/stale-mirror.d.ts +82 -0
  678. package/dist/worker/stale-mirror.js +130 -0
  679. package/dist/worker/task-runner.d.ts +5 -3
  680. package/dist/worker/task-runner.js +287 -186
  681. package/dist/worker/worker-context.d.ts +36 -37
  682. package/package.json +35 -7
  683. package/dist/editor/EditorPanes.d.ts +0 -10
  684. package/dist/editor/EditorPanes.js +0 -98
  685. package/dist/editor/components/EditorFooter.d.ts +0 -11
  686. package/dist/editor/components/EditorFooter.js +0 -9
  687. package/dist/editor/components/EditorSidebar.d.ts +0 -67
  688. package/dist/editor/components/EditorSidebar.js +0 -22
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Scrub `token` from everything that leaves the gateway from now on: raw, and as the extraheader
3
+ * carries it, `base64("x-access-token:" + token)`, raw and URL-encoded. Shared by every gateway in
4
+ * the process, so a token one resolved is scrubbed from all of them.
5
+ */
6
+ export declare function registerLiveSecret(token: string): void;
7
+ /**
8
+ * Scrub `value` from everything that leaves the gateway from now on, raw and URL-encoded: a secret
9
+ * that is not a GitHub token (the auth provider's key). It shares {@link registerLiveSecret}'s
10
+ * store and cap, so a rotated key's predecessor stays scrubbed until the cap drops it, as a
11
+ * token's does.
12
+ */
13
+ export declare function registerSecretText(value: string): void;
14
+ /**
15
+ * Scrub each line of a PEM key's body from everything that leaves the gateway from now on, so the
16
+ * scrub survives JSON or log escaping, which split a PEM at its newlines. Lines split on real
17
+ * line breaks and on the literal `\n`, `\r\n` or `\r` (a key pasted into a single-line config
18
+ * field); the BEGIN/END lines and lines shorter than the secret floor are skipped. A key given as
19
+ * one base64 line (a base64-wrapped PEM) is one entry, and the PEM it wraps is registered too.
20
+ */
21
+ export declare function registerPrivateKey(pem: string): void;
22
+ /** `text` without any live token in any registered form, or anything `redactCredentials` finds. */
23
+ export declare function redactEgress(text: string): string;
24
+ /**
25
+ * An answer with every string in it (a Map's keys included) scrubbed of live tokens, never by
26
+ * pattern: the same object when nothing in it changed, else a copy. Plain data only: anything
27
+ * else (a stream) is returned as it is.
28
+ */
29
+ export declare function redactValue<T>(value: T): T;
30
+ /**
31
+ * `err` scrubbed for leaving the gateway: its message, stack and `stderr`, its `cause` chain, and
32
+ * an Octokit error's `response` and `request`. Scrubbed in place, so its class and the fields the
33
+ * task runner classifies on (`status`, `code`, `kind`) survive; a field that cannot be set (a
34
+ * DOMException's message) makes it a plain Error of the same name instead. Only fields that hold a secret are
35
+ * touched. A thrown string is scrubbed; anything else is returned as it is.
36
+ */
37
+ export declare function redactError(err: unknown, depth?: number): unknown;
38
+ /** The gateway's `workerLog`: one scrubbed, escaped line. */
39
+ export declare function gatewayLog(...args: unknown[]): void;
40
+ /** The gateway's `workerLogWarn`: one scrubbed, escaped line. */
41
+ export declare function gatewayLogWarn(...args: unknown[]): void;
42
+ /** The gateway's `workerLogError`: one scrubbed, escaped line. */
43
+ export declare function gatewayLogError(...args: unknown[]): void;
@@ -0,0 +1,209 @@
1
+ /**
2
+ * What leaves the GitHub gateway: every error it throws, every answer it returns and every line it
3
+ * logs goes through here, `github-service.ts`'s and Octokit's lines for it included (they are
4
+ * given {@link gatewayLogWarn} and {@link gatewayLogError}), except `openBundle`'s errors, which
5
+ * hold no secret. Each is scrubbed of every live token the gateway has resolved, in every form
6
+ * git's extraheader gives it, and of the auth provider's key and the App's private key, as exact
7
+ * strings. Errors and log lines are then scrubbed by
8
+ * `redactCredentials`'s patterns too; answers are not, because they are data the worker acts on,
9
+ * and a pattern would rewrite a GitHub branch named `chore/github_pat_rotation`. The
10
+ * exact scrub comes first and cannot be left to the patterns: one can stop part-way through a
11
+ * form beside another (at the `%` of a URL-encoded one) and leave its tail unmatchable. Each log
12
+ * line also has its non-printable characters escaped, since request fields (branch names, pull
13
+ * request text) and git's output (commit subjects) are attacker-chosen. The gateway process's own
14
+ * modules (secret reads, the termination watch) and `@octokit/auth-app` log through `workerLog`
15
+ * or the console, unscrubbed: none of their lines carries a secret's value.
16
+ */
17
+ import { getErrorMessage, redactCredentials } from '../utils/error.js';
18
+ import { escapeForLog } from '../utils/escape-text.js';
19
+ import { workerLog, workerLogError, workerLogWarn } from './log.js';
20
+ /** How many tokens are scrubbed: the current one and those it replaced. */
21
+ const MAX_LIVE_SECRETS = 32;
22
+ /** Shorter values are never scrubbed as exact strings: they would hit ordinary text. */
23
+ const MIN_SECRET_LENGTH = 8;
24
+ /** Each live token's forms, longest first; the most recently registered token last. */
25
+ const liveSecrets = new Map();
26
+ /**
27
+ * Scrub `token` from everything that leaves the gateway from now on: raw, and as the extraheader
28
+ * carries it, `base64("x-access-token:" + token)`, raw and URL-encoded. Shared by every gateway in
29
+ * the process, so a token one resolved is scrubbed from all of them.
30
+ */
31
+ export function registerLiveSecret(token) {
32
+ if (token.length < MIN_SECRET_LENGTH)
33
+ return;
34
+ const basic = Buffer.from(`x-access-token:${token}`).toString('base64');
35
+ liveSecrets.delete(token);
36
+ liveSecrets.set(token, [...new Set([token, basic, encodeURIComponent(basic)])].sort((a, b) => b.length - a.length));
37
+ for (const oldest of liveSecrets.keys()) {
38
+ if (liveSecrets.size <= MAX_LIVE_SECRETS)
39
+ break;
40
+ liveSecrets.delete(oldest);
41
+ }
42
+ }
43
+ /**
44
+ * Scrub `value` from everything that leaves the gateway from now on, raw and URL-encoded: a secret
45
+ * that is not a GitHub token (the auth provider's key). It shares {@link registerLiveSecret}'s
46
+ * store and cap, so a rotated key's predecessor stays scrubbed until the cap drops it, as a
47
+ * token's does.
48
+ */
49
+ export function registerSecretText(value) {
50
+ if (value.length < MIN_SECRET_LENGTH)
51
+ return;
52
+ liveSecrets.delete(value);
53
+ liveSecrets.set(value, [...new Set([value, encodeURIComponent(value)])].sort((a, b) => b.length - a.length));
54
+ for (const oldest of liveSecrets.keys()) {
55
+ if (liveSecrets.size <= MAX_LIVE_SECRETS)
56
+ break;
57
+ liveSecrets.delete(oldest);
58
+ }
59
+ }
60
+ /** How many private-key lines are scrubbed; the oldest are dropped past it. */
61
+ const MAX_PRIVATE_KEY_LINES = 1024;
62
+ /**
63
+ * The lines of every registered private key, in their own set: a PEM is about 27 lines and the
64
+ * token store holds {@link MAX_LIVE_SECRETS}, so sharing it would evict live tokens.
65
+ */
66
+ const privateKeyLines = new Set();
67
+ /** `privateKeyLines`, longest first; rebuilt when a key is registered. */
68
+ let privateKeyLinesLongestFirst = [];
69
+ /**
70
+ * Scrub each line of a PEM key's body from everything that leaves the gateway from now on, so the
71
+ * scrub survives JSON or log escaping, which split a PEM at its newlines. Lines split on real
72
+ * line breaks and on the literal `\n`, `\r\n` or `\r` (a key pasted into a single-line config
73
+ * field); the BEGIN/END lines and lines shorter than the secret floor are skipped. A key given as
74
+ * one base64 line (a base64-wrapped PEM) is one entry, and the PEM it wraps is registered too.
75
+ */
76
+ export function registerPrivateKey(pem) {
77
+ for (const raw of pem.split(/\r?\n|\r|(?:\\r)?\\n|\\r/)) {
78
+ const line = raw.trim();
79
+ if (line.length < MIN_SECRET_LENGTH || line.startsWith('-----'))
80
+ continue;
81
+ privateKeyLines.delete(line);
82
+ privateKeyLines.add(line);
83
+ // A base64-wrapped PEM: the key inside it is the one a decoding consumer holds.
84
+ const decoded = Buffer.from(line, 'base64').toString('utf8');
85
+ if (decoded.includes('-----BEGIN'))
86
+ registerPrivateKey(decoded);
87
+ }
88
+ for (const oldest of privateKeyLines) {
89
+ if (privateKeyLines.size <= MAX_PRIVATE_KEY_LINES)
90
+ break;
91
+ privateKeyLines.delete(oldest);
92
+ }
93
+ privateKeyLinesLongestFirst = [...privateKeyLines].sort((a, b) => b.length - a.length);
94
+ }
95
+ /** `text` without any live token or registered secret in any registered form. */
96
+ function redactLiveSecrets(text) {
97
+ let result = text;
98
+ for (const forms of liveSecrets.values()) {
99
+ for (const form of forms)
100
+ result = result.split(form).join('***');
101
+ }
102
+ for (const line of privateKeyLinesLongestFirst)
103
+ result = result.split(line).join('***');
104
+ return result;
105
+ }
106
+ /** `text` without any live token in any registered form, or anything `redactCredentials` finds. */
107
+ export function redactEgress(text) {
108
+ return redactCredentials(redactLiveSecrets(text));
109
+ }
110
+ /** The deepest a returned value is walked; anything deeper passes as it is. */
111
+ const MAX_DEPTH = 8;
112
+ /**
113
+ * An answer with every string in it (a Map's keys included) scrubbed of live tokens, never by
114
+ * pattern: the same object when nothing in it changed, else a copy. Plain data only: anything
115
+ * else (a stream) is returned as it is.
116
+ */
117
+ export function redactValue(value) {
118
+ return redactAny(value, 0, redactLiveSecrets);
119
+ }
120
+ function redactAny(value, depth, scrub) {
121
+ if (typeof value === 'string')
122
+ return scrub(value);
123
+ if (depth >= MAX_DEPTH || typeof value !== 'object' || value === null)
124
+ return value;
125
+ if (Array.isArray(value)) {
126
+ const items = value.map((item) => redactAny(item, depth + 1, scrub));
127
+ return items.every((item, i) => item === value[i]) ? value : items;
128
+ }
129
+ if (value instanceof Map) {
130
+ const before = [...value];
131
+ const after = before.map(([key, item]) => [
132
+ redactAny(key, depth + 1, scrub),
133
+ redactAny(item, depth + 1, scrub),
134
+ ]);
135
+ return after.every(([key, item], i) => key === before[i][0] && item === before[i][1])
136
+ ? value
137
+ : new Map(after);
138
+ }
139
+ if (Object.getPrototypeOf(value) !== Object.prototype)
140
+ return value;
141
+ const entries = Object.entries(value);
142
+ const redacted = entries.map(([key, item]) => [key, redactAny(item, depth + 1, scrub)]);
143
+ return redacted.every(([, item], i) => item === entries[i][1])
144
+ ? value
145
+ : Object.fromEntries(redacted);
146
+ }
147
+ /**
148
+ * `err` scrubbed for leaving the gateway: its message, stack and `stderr`, its `cause` chain, and
149
+ * an Octokit error's `response` and `request`. Scrubbed in place, so its class and the fields the
150
+ * task runner classifies on (`status`, `code`, `kind`) survive; a field that cannot be set (a
151
+ * DOMException's message) makes it a plain Error of the same name instead. Only fields that hold a secret are
152
+ * touched. A thrown string is scrubbed; anything else is returned as it is.
153
+ */
154
+ export function redactError(err, depth = 0) {
155
+ if (typeof err === 'string')
156
+ return redactEgress(err);
157
+ if (!(err instanceof Error) || depth >= MAX_DEPTH)
158
+ return err;
159
+ const fields = err;
160
+ const updates = [];
161
+ // `stderr`: a GitProcessError (worker/git-process.ts) carries git's own output beside its message.
162
+ for (const key of ['message', 'stack', 'stderr']) {
163
+ const value = fields[key];
164
+ if (typeof value === 'string' && redactEgress(value) !== value) {
165
+ updates.push([key, redactEgress(value)]);
166
+ }
167
+ }
168
+ for (const key of ['response', 'request']) {
169
+ const redacted = redactAny(fields[key], 0, redactEgress);
170
+ if (redacted !== fields[key])
171
+ updates.push([key, redacted]);
172
+ }
173
+ if (fields.cause !== undefined) {
174
+ const cause = redactError(fields.cause, depth + 1);
175
+ if (cause !== fields.cause)
176
+ updates.push(['cause', cause]);
177
+ }
178
+ try {
179
+ for (const [key, value] of updates) {
180
+ Object.defineProperty(fields, key, {
181
+ value,
182
+ writable: true,
183
+ configurable: true,
184
+ enumerable: Object.prototype.propertyIsEnumerable.call(fields, key),
185
+ });
186
+ }
187
+ return err;
188
+ }
189
+ catch {
190
+ const replacement = new Error(redactEgress(err.message));
191
+ replacement.name = err.name;
192
+ return replacement;
193
+ }
194
+ }
195
+ function logLine(args) {
196
+ return escapeForLog(redactEgress(args.map((arg) => (typeof arg === 'string' ? arg : getErrorMessage(arg))).join(' ')));
197
+ }
198
+ /** The gateway's `workerLog`: one scrubbed, escaped line. */
199
+ export function gatewayLog(...args) {
200
+ workerLog(logLine(args));
201
+ }
202
+ /** The gateway's `workerLogWarn`: one scrubbed, escaped line. */
203
+ export function gatewayLogWarn(...args) {
204
+ workerLogWarn(logLine(args));
205
+ }
206
+ /** The gateway's `workerLogError`: one scrubbed, escaped line. */
207
+ export function gatewayLogError(...args) {
208
+ workerLogError(logLine(args));
209
+ }
@@ -0,0 +1,42 @@
1
+ import type { GatewayTerminationNotice } from './github-gateway.js';
2
+ export interface GatewayInstanceOptions {
3
+ /**
4
+ * Resolves once the instance is being terminated. Started at the first `termination()` or
5
+ * `completeLifecycle()` call, once; a rejection is logged and the next call starts it again.
6
+ */
7
+ watchTermination?: () => Promise<GatewayTerminationNotice>;
8
+ /** Completes the Auto Scaling lifecycle action. Never rejects by contract: the provider logs its own failure. */
9
+ completeLifecycle?: () => Promise<void>;
10
+ /** Test seam: one `termination()` poll's wait (default {@link TERMINATION_POLL_WAIT_MS}). */
11
+ terminationPollWaitMs?: number;
12
+ }
13
+ /**
14
+ * The gateway's two operations on the instance itself, `termination` and `completeLifecycle`
15
+ * (see {@link GitHubGateway}). They need only the instance role, never the GitHub credential, so
16
+ * a gateway that failed to boot serves them too (canopycms-cdk `worker/gateway-run.ts`).
17
+ */
18
+ export declare class GatewayInstance {
19
+ private readonly options;
20
+ /** Whether the termination watch is running: started by a poll, and again by one after it failed. */
21
+ private terminationWatching;
22
+ /** The notice this gateway's own termination watch saw; null until it sees one. */
23
+ private terminationNotice;
24
+ /**
25
+ * The polls waiting for a notice, each removed when its poll ends. A set, not reactions on one
26
+ * long-lived promise: those would pile up, one per poll, for the instance's whole life.
27
+ */
28
+ private readonly terminationWaiters;
29
+ /** Whether the gateway's own watch has seen an Auto Scaling notice: what `completeLifecycle` requires. */
30
+ private sawAutoScalingNotice;
31
+ /** The one `completeLifecycle` provider call, which every call answers. */
32
+ private lifecycleCompletion;
33
+ constructor(options: GatewayInstanceOptions);
34
+ termination(signal?: AbortSignal): Promise<GatewayTerminationNotice | null>;
35
+ completeLifecycle(signal?: AbortSignal): Promise<void>;
36
+ /** Start the termination watch unless it runs or has seen a notice; a failure is logged, and the next poll starts it again. */
37
+ private startTerminationWatch;
38
+ /** The watch's notice, or null after `waitMs`; rejects with `signal`'s reason when it aborts first. */
39
+ private waitForTerminationNotice;
40
+ }
41
+ /** `promise`, unless `signal` aborts first, which ends only this wait. */
42
+ export declare function untilAborted<T>(promise: Promise<T>, signal?: AbortSignal): Promise<T>;
@@ -0,0 +1,129 @@
1
+ import { getErrorMessage } from '../utils/error.js';
2
+ import { gatewayLogError, gatewayLogWarn, redactEgress, redactError, redactValue, } from './gateway-egress.js';
3
+ /** How long one `termination()` poll waits for a notice before answering that none came. */
4
+ const TERMINATION_POLL_WAIT_MS = 25_000;
5
+ /**
6
+ * How long `completeLifecycle` watches for a notice it has not seen: one read of the instance's
7
+ * metadata, which a terminating instance answers at once.
8
+ */
9
+ const LIFECYCLE_NOTICE_WAIT_MS = 10_000;
10
+ /**
11
+ * The gateway's two operations on the instance itself, `termination` and `completeLifecycle`
12
+ * (see {@link GitHubGateway}). They need only the instance role, never the GitHub credential, so
13
+ * a gateway that failed to boot serves them too (canopycms-cdk `worker/gateway-run.ts`).
14
+ */
15
+ export class GatewayInstance {
16
+ constructor(options) {
17
+ this.options = options;
18
+ /** Whether the termination watch is running: started by a poll, and again by one after it failed. */
19
+ this.terminationWatching = false;
20
+ /** The notice this gateway's own termination watch saw; null until it sees one. */
21
+ this.terminationNotice = null;
22
+ /**
23
+ * The polls waiting for a notice, each removed when its poll ends. A set, not reactions on one
24
+ * long-lived promise: those would pile up, one per poll, for the instance's whole life.
25
+ */
26
+ this.terminationWaiters = new Set();
27
+ /** Whether the gateway's own watch has seen an Auto Scaling notice: what `completeLifecycle` requires. */
28
+ this.sawAutoScalingNotice = false;
29
+ /** The one `completeLifecycle` provider call, which every call answers. */
30
+ this.lifecycleCompletion = null;
31
+ }
32
+ async termination(signal) {
33
+ if (this.terminationNotice !== null)
34
+ return this.terminationNotice;
35
+ this.startTerminationWatch();
36
+ // A failed watch leaves the poll waiting its whole period, so a client polling in a loop is paced.
37
+ return this.waitForTerminationNotice(this.options.terminationPollWaitMs ?? TERMINATION_POLL_WAIT_MS, signal);
38
+ }
39
+ async completeLifecycle(signal) {
40
+ const complete = this.options.completeLifecycle;
41
+ if (complete === undefined) {
42
+ gatewayLogWarn('Nothing completes the Auto Scaling lifecycle action: no provider is configured');
43
+ return;
44
+ }
45
+ // Only an Auto Scaling notice this gateway's own watch observed opens it: a worker cannot be
46
+ // trusted to say the instance is terminating, and completing the action ends the instance. A
47
+ // gateway restarted after the worker had its notice has not watched yet, so it watches now,
48
+ // for a bounded wait, before it refuses.
49
+ if (!this.sawAutoScalingNotice) {
50
+ this.startTerminationWatch();
51
+ await this.waitForTerminationNotice(Math.min(this.options.terminationPollWaitMs ?? TERMINATION_POLL_WAIT_MS, LIFECYCLE_NOTICE_WAIT_MS), signal);
52
+ }
53
+ if (!this.sawAutoScalingNotice) {
54
+ throw new Error('The GitHub gateway has seen no Auto Scaling termination, so it will not complete the lifecycle action');
55
+ }
56
+ // `signal` ends only this caller's wait: a started CompleteLifecycleAction is not taken back.
57
+ try {
58
+ await untilAborted((this.lifecycleCompletion ??= complete()), signal);
59
+ }
60
+ catch (err) {
61
+ throw redactError(err);
62
+ }
63
+ }
64
+ /** Start the termination watch unless it runs or has seen a notice; a failure is logged, and the next poll starts it again. */
65
+ startTerminationWatch() {
66
+ const watchTermination = this.options.watchTermination;
67
+ if (watchTermination === undefined || this.terminationWatching)
68
+ return;
69
+ if (this.terminationNotice !== null)
70
+ return;
71
+ this.terminationWatching = true;
72
+ void (async () => watchTermination())().then((notice) => {
73
+ this.terminationWatching = false;
74
+ const scrubbed = redactValue(notice);
75
+ this.terminationNotice = scrubbed;
76
+ if (notice.kind === 'auto-scaling')
77
+ this.sawAutoScalingNotice = true;
78
+ for (const waiter of [...this.terminationWaiters])
79
+ waiter(scrubbed);
80
+ }, (err) => {
81
+ this.terminationWatching = false;
82
+ gatewayLogError('The termination watch failed:', redactEgress(getErrorMessage(err)));
83
+ });
84
+ }
85
+ /** The watch's notice, or null after `waitMs`; rejects with `signal`'s reason when it aborts first. */
86
+ waitForTerminationNotice(waitMs, signal) {
87
+ if (this.terminationNotice !== null)
88
+ return Promise.resolve(this.terminationNotice);
89
+ signal?.throwIfAborted();
90
+ return new Promise((resolve, reject) => {
91
+ const end = () => {
92
+ clearTimeout(timer);
93
+ this.terminationWaiters.delete(onNotice);
94
+ signal?.removeEventListener('abort', onAbort);
95
+ };
96
+ const onNotice = (notice) => {
97
+ end();
98
+ resolve(notice);
99
+ };
100
+ const onAbort = () => {
101
+ end();
102
+ reject(signal?.reason);
103
+ };
104
+ const timer = setTimeout(() => {
105
+ end();
106
+ resolve(null);
107
+ }, waitMs);
108
+ this.terminationWaiters.add(onNotice);
109
+ signal?.addEventListener('abort', onAbort, { once: true });
110
+ });
111
+ }
112
+ }
113
+ /** `promise`, unless `signal` aborts first, which ends only this wait. */
114
+ export async function untilAborted(promise, signal) {
115
+ if (signal === undefined)
116
+ return promise;
117
+ signal.throwIfAborted();
118
+ let onAbort = () => undefined;
119
+ const aborted = new Promise((_, reject) => {
120
+ onAbort = () => reject(signal.reason);
121
+ signal.addEventListener('abort', onAbort, { once: true });
122
+ });
123
+ try {
124
+ return await Promise.race([promise, aborted]);
125
+ }
126
+ finally {
127
+ signal.removeEventListener('abort', onAbort);
128
+ }
129
+ }
@@ -0,0 +1,81 @@
1
+ import { Readable } from 'node:stream';
2
+ /**
3
+ * git with its stdin or stdout as a stream, which simple-git cannot do: a bundle's way into
4
+ * `bundle unbundle -` and `fetch`, out of `bundle create -`, and `update-ref --stdin`'s
5
+ * transactions. The caller supplies the whole environment, config and working directory, so the
6
+ * pins of the repository it runs in apply here exactly as they do through simple-git
7
+ * (worker/shared-repo-git.ts, worker/github-mirror.ts).
8
+ *
9
+ * Bounded three ways: while git runs, killed after {@link GitProcessOptions.inactivityTimeoutMs}
10
+ * with no output and no input consumed, unless output it wrote is still waiting for the reader
11
+ * (git is then blocked on the reader, and the reader's own bounds end that wait; once git has
12
+ * exited 0, output still unread is the reader's to take, however slowly); killed when `signal`
13
+ * aborts; and holding at most {@link STDERR_CAP_BYTES} of stderr and `maxStdoutBytes` of captured stdout, so a process fed
14
+ * hostile bytes cannot make this one buffer without limit. A stop reaches everything git spawned:
15
+ * git runs in its own process group.
16
+ */
17
+ export interface GitProcessOptions {
18
+ /** The process's working directory, absolute. */
19
+ cwd: string;
20
+ /** The process's entire environment. */
21
+ env: Record<string, string>;
22
+ /** `-c` settings, given ahead of the subcommand. */
23
+ config?: readonly string[];
24
+ /** What git reads on stdin; without it stdin is closed at once. */
25
+ stdin?: Readable | string;
26
+ /**
27
+ * While git runs, killed when nothing is written to stdout or stderr, and nothing consumed from
28
+ * stdin, for this long. Not while what it wrote waits unread for the reader, nor after it exits
29
+ * 0: what it wrote is then the reader's.
30
+ */
31
+ inactivityTimeoutMs: number;
32
+ /**
33
+ * Killed when git has run this long, output or not: the bound for a command that writes nothing
34
+ * while it works (`repack`, `commit-graph write`), which an inactivity bound would kill.
35
+ */
36
+ deadlineMs?: number;
37
+ signal?: AbortSignal;
38
+ /** Told of each sign of life the inactivity bound counts: output written, input consumed. */
39
+ onActivity?: () => void;
40
+ }
41
+ /**
42
+ * git exited non-zero, by a signal, or was killed here; `message` is its stderr when it wrote any,
43
+ * after its stdout when `runGit` was asked for that (`stdoutInFailure`).
44
+ * @internal Exported for tests.
45
+ */
46
+ export declare class GitProcessError extends Error {
47
+ readonly exitCode: number | null;
48
+ readonly stderr: string;
49
+ constructor(message: string, exitCode: number | null, stderr: string);
50
+ }
51
+ /**
52
+ * The most stderr kept, from the start: git's diagnosis comes first.
53
+ * @internal Exported for tests.
54
+ */
55
+ export declare const STDERR_CAP_BYTES: number;
56
+ /** A git process with its stdout as a stream; see {@link spawnGit}. */
57
+ export interface GitProcess {
58
+ readonly stdout: Readable;
59
+ /**
60
+ * Settles once git has exited and its output is read or released; resolves only when git exited
61
+ * 0 on its own, its input source did not fail, and no stop came first.
62
+ */
63
+ readonly exited: Promise<void>;
64
+ /** Stop git now; `exited` then rejects. */
65
+ kill(reason: string): void;
66
+ }
67
+ /**
68
+ * Start `git <config> <args>` with stdout as a stream the caller must read or {@link GitProcess.kill}:
69
+ * git blocks on a full pipe, for as long as the reader holds back.
70
+ */
71
+ export declare function spawnGit(args: readonly string[], options: GitProcessOptions): GitProcess;
72
+ /**
73
+ * Run `git <config> <args>` to completion and resolve with its stdout, refusing more than
74
+ * `maxStdoutBytes` of it (default 64 MiB). With `stdoutInFailure`, a failure's message is what git
75
+ * printed to stdout and then its own message, as simple-git words one: `push --porcelain` prints
76
+ * the rejected ref's status, which callers classify, on stdout.
77
+ */
78
+ export declare function runGit(args: readonly string[], options: GitProcessOptions & {
79
+ maxStdoutBytes?: number;
80
+ stdoutInFailure?: boolean;
81
+ }): Promise<string>;