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.
- package/CHANGELOG.md +2131 -0
- package/README.md +47 -63
- package/dist/ai/generate.d.ts +5 -0
- package/dist/ai/generate.js +244 -115
- package/dist/ai/index.d.ts +1 -1
- package/dist/ai/json-to-markdown.d.ts +21 -1
- package/dist/ai/json-to-markdown.js +120 -57
- package/dist/ai/references.d.ts +72 -0
- package/dist/ai/references.js +223 -0
- package/dist/ai/resolve-branch.js +9 -2
- package/dist/ai/to-plain-text.d.ts +17 -8
- package/dist/ai/to-plain-text.js +18 -15
- package/dist/ai/types.d.ts +84 -3
- package/dist/api/admin-branch-health.d.ts +24 -1
- package/dist/api/admin-branch-health.js +52 -20
- package/dist/api/admin.d.ts +23 -5
- package/dist/api/admin.js +36 -1
- package/dist/api/assets.js +88 -78
- package/dist/api/branch-create-window.d.ts +12 -0
- package/dist/api/branch-create-window.js +13 -0
- package/dist/api/branch-merge.d.ts +1 -1
- package/dist/api/branch-merge.js +1 -1
- package/dist/api/branch-review.d.ts +3 -3
- package/dist/api/branch-review.js +16 -7
- package/dist/api/branch-status.d.ts +16 -6
- package/dist/api/branch-status.js +57 -12
- package/dist/api/branch-withdraw.d.ts +2 -2
- package/dist/api/branch-withdraw.js +8 -3
- package/dist/api/branch.d.ts +25 -12
- package/dist/api/branch.js +164 -103
- package/dist/api/client.d.ts +78 -58
- package/dist/api/client.js +150 -117
- package/dist/api/comments.d.ts +12 -3
- package/dist/api/comments.js +118 -9
- package/dist/api/content.d.ts +9 -9
- package/dist/api/content.js +131 -22
- package/dist/api/entries-constants.d.ts +14 -3
- package/dist/api/entries-constants.js +14 -3
- package/dist/api/entries.d.ts +40 -2
- package/dist/api/entries.js +102 -6
- package/dist/api/github-sync.d.ts +19 -0
- package/dist/api/github-sync.js +50 -3
- package/dist/api/groups.d.ts +4 -4
- package/dist/api/groups.js +2 -1
- package/dist/api/guards.js +23 -3
- package/dist/api/index.d.ts +3 -1
- package/dist/api/index.js +1 -0
- package/dist/api/permissions.d.ts +21 -2
- package/dist/api/permissions.js +50 -3
- package/dist/api/request-deadline.d.ts +59 -0
- package/dist/api/request-deadline.js +73 -0
- package/dist/api/resolve-references.js +8 -7
- package/dist/api/route-builder.d.ts +14 -0
- package/dist/api/route-builder.js +14 -1
- package/dist/api/schema.d.ts +11 -9
- package/dist/api/schema.js +2 -0
- package/dist/api/settings-helpers.d.ts +5 -1
- package/dist/api/settings-helpers.js +10 -2
- package/dist/api/types.d.ts +18 -0
- package/dist/api/users-constants.d.ts +6 -0
- package/dist/api/users-constants.js +6 -0
- package/dist/assets/asset-url.d.ts +28 -16
- package/dist/assets/asset-url.js +51 -25
- package/dist/assets/finalize.js +3 -0
- package/dist/assets/index.d.ts +1 -1
- package/dist/assets/materialize.d.ts +153 -0
- package/dist/assets/materialize.js +402 -0
- package/dist/assets/store-local.d.ts +19 -5
- package/dist/assets/store-local.js +69 -10
- package/dist/assets/store-s3.d.ts +38 -7
- package/dist/assets/store-s3.js +128 -22
- package/dist/assets/transform-directives.d.ts +52 -13
- package/dist/assets/transform-directives.js +87 -27
- package/dist/assets/transform.d.ts +3 -3
- package/dist/assets/transform.js +13 -8
- package/dist/assets/types.d.ts +31 -4
- package/dist/auth/cache.d.ts +1 -1
- package/dist/auth/cache.js +1 -1
- package/dist/auth/caching-auth-plugin.d.ts +2 -0
- package/dist/auth/caching-auth-plugin.js +12 -2
- package/dist/auth/file-based-auth-cache.d.ts +8 -0
- package/dist/auth/file-based-auth-cache.js +18 -8
- package/dist/auth/person-name.d.ts +5 -0
- package/dist/auth/person-name.js +8 -0
- package/dist/auth/plugin.d.ts +10 -1
- package/dist/auth/types.d.ts +2 -0
- package/dist/auth/user-metadata-lookup.d.ts +21 -0
- package/dist/auth/user-metadata-lookup.js +116 -0
- package/dist/authorization/branch.d.ts +1 -1
- package/dist/authorization/branch.js +12 -13
- package/dist/authorization/groups/schema.d.ts +4 -4
- package/dist/authorization/helpers.d.ts +8 -0
- package/dist/authorization/helpers.js +8 -0
- package/dist/authorization/index.d.ts +1 -1
- package/dist/authorization/index.js +1 -1
- package/dist/authorization/protected-branch.d.ts +5 -4
- package/dist/authorization/protected-branch.js +7 -5
- package/dist/branch-health.d.ts +35 -8
- package/dist/branch-health.js +54 -18
- package/dist/branch-metadata-error.d.ts +27 -0
- package/dist/branch-metadata-error.js +23 -0
- package/dist/branch-metadata-file.d.ts +205 -24
- package/dist/branch-metadata-file.js +126 -25
- package/dist/branch-metadata.d.ts +45 -6
- package/dist/branch-metadata.js +142 -50
- package/dist/branch-provisioning.d.ts +167 -0
- package/dist/branch-provisioning.js +501 -0
- package/dist/branch-registry.d.ts +8 -0
- package/dist/branch-registry.js +61 -9
- package/dist/branch-schema-cache.d.ts +29 -12
- package/dist/branch-schema-cache.js +64 -21
- package/dist/branch-sparse.d.ts +23 -0
- package/dist/branch-sparse.js +118 -0
- package/dist/branch-workspace.d.ts +42 -3
- package/dist/branch-workspace.js +239 -100
- package/dist/build/asset-refs.d.ts +94 -0
- package/dist/build/asset-refs.js +267 -0
- package/dist/build/generate-ai-content.js +5 -0
- package/dist/build/inline-flight.d.ts +37 -0
- package/dist/build/inline-flight.js +142 -0
- package/dist/cli/asset-refs.d.ts +52 -0
- package/dist/cli/asset-refs.js +194 -0
- package/dist/cli/cli.d.ts +15 -1
- package/dist/cli/cli.js +8543 -3193
- package/dist/cli/configured-asset-store.d.ts +12 -0
- package/dist/cli/configured-asset-store.js +46 -0
- package/dist/cli/generate-ai-content.js +4244 -1072
- package/dist/cli/init.js +217 -126
- package/dist/cli/project-detect.d.ts +2 -0
- package/dist/cli/project-detect.js +2 -0
- package/dist/cli/template-files/Dockerfile.cms.template +13 -5
- package/dist/cli/template-files/cms-stack.ts.template +16 -13
- package/dist/client.d.ts +1 -2
- package/dist/client.js +1 -2
- package/dist/comment-store.d.ts +25 -0
- package/dist/comment-store.js +43 -8
- package/dist/config/flatten.js +2 -0
- package/dist/config/helpers.js +2 -2
- package/dist/config/index.d.ts +1 -1
- package/dist/config/schemas/config.d.ts +12 -29
- package/dist/config/schemas/config.js +9 -12
- package/dist/config/schemas/field.d.ts +3 -0
- package/dist/config/schemas/field.js +58 -4
- package/dist/config/schemas/media.d.ts +4 -13
- package/dist/config/schemas/media.js +5 -8
- package/dist/config/schemas/url.d.ts +2 -20
- package/dist/config/schemas/url.js +2 -25
- package/dist/config/types.d.ts +116 -22
- package/dist/config/types.js +3 -9
- package/dist/config/validation.d.ts +25 -4
- package/dist/config/validation.js +116 -3
- package/dist/content-id-index.js +2 -2
- package/dist/content-index-generation.d.ts +1 -1
- package/dist/content-index-generation.js +1 -1
- package/dist/content-listing.d.ts +10 -1
- package/dist/content-listing.js +22 -5
- package/dist/content-reader.d.ts +9 -0
- package/dist/content-reader.js +16 -11
- package/dist/content-store.d.ts +75 -12
- package/dist/content-store.js +249 -86
- package/dist/content-tree.js +2 -2
- package/dist/context.js +5 -2
- package/dist/dangling-reference-log.d.ts +17 -0
- package/dist/dangling-reference-log.js +29 -0
- package/dist/dev-content-watcher.d.ts +1 -1
- package/dist/dev-content-watcher.js +1 -1
- package/dist/editor/BranchManager.d.ts +23 -7
- package/dist/editor/BranchManager.js +119 -54
- package/dist/editor/CanopyEditor.d.ts +1 -1
- package/dist/editor/CanopyEditor.js +1 -2
- package/dist/editor/CommentsPanel.d.ts +14 -0
- package/dist/editor/CommentsPanel.js +68 -43
- package/dist/editor/Editor.d.ts +11 -5
- package/dist/editor/Editor.js +891 -218
- package/dist/editor/EditorAuthGate.d.ts +7 -1
- package/dist/editor/EditorAuthGate.js +41 -9
- package/dist/editor/EntryNavigator.d.ts +22 -0
- package/dist/editor/EntryNavigator.js +353 -105
- package/dist/editor/FormHeader.d.ts +25 -0
- package/dist/editor/FormHeader.js +82 -0
- package/dist/editor/FormRenderer.d.ts +27 -3
- package/dist/editor/FormRenderer.js +171 -76
- package/dist/editor/PreviewFrame.d.ts +40 -0
- package/dist/editor/PreviewFrame.js +215 -0
- package/dist/editor/PreviewPane.d.ts +47 -0
- package/dist/editor/PreviewPane.js +147 -0
- package/dist/editor/PreviewToolbarTools.d.ts +22 -0
- package/dist/editor/PreviewToolbarTools.js +73 -0
- package/dist/editor/admin/SystemHealthPanel.d.ts +2 -1
- package/dist/editor/admin/SystemHealthPanel.js +163 -33
- package/dist/editor/admin/useSystemHealth.d.ts +18 -0
- package/dist/editor/admin/useSystemHealth.js +70 -1
- package/dist/editor/branch-status.d.ts +17 -0
- package/dist/editor/branch-status.js +29 -0
- package/dist/editor/canopy-path.d.ts +9 -6
- package/dist/editor/canopy-path.js +8 -11
- package/dist/editor/client-reference-resolver.d.ts +43 -16
- package/dist/editor/client-reference-resolver.js +155 -64
- package/dist/editor/comments/BranchComments.d.ts +1 -1
- package/dist/editor/comments/BranchComments.js +2 -2
- package/dist/editor/comments/CloseRefusedNotice.d.ts +4 -0
- package/dist/editor/comments/CloseRefusedNotice.js +7 -0
- package/dist/editor/comments/CommentThreadsPopover.d.ts +47 -0
- package/dist/editor/comments/CommentThreadsPopover.js +274 -0
- package/dist/editor/comments/CommentWriteAlert.d.ts +11 -0
- package/dist/editor/comments/CommentWriteAlert.js +13 -0
- package/dist/editor/comments/EntryComments.d.ts +10 -4
- package/dist/editor/comments/EntryComments.js +14 -17
- package/dist/editor/comments/FieldWrapper.d.ts +18 -4
- package/dist/editor/comments/FieldWrapper.js +62 -28
- package/dist/editor/comments/InlineCommentThread.d.ts +9 -2
- package/dist/editor/comments/InlineCommentThread.js +11 -47
- package/dist/editor/comments/ThreadCarousel.d.ts +1 -1
- package/dist/editor/comments/ThreadCarousel.js +18 -21
- package/dist/editor/comments/ThreadReplyControls.d.ts +28 -0
- package/dist/editor/comments/ThreadReplyControls.js +92 -0
- package/dist/editor/comments/field-comment-context.d.ts +14 -0
- package/dist/editor/comments/field-comment-context.js +14 -0
- package/dist/editor/comments/form-comments.d.ts +48 -0
- package/dist/editor/comments/form-comments.js +178 -0
- package/dist/editor/comments/item-anchor-copy.d.ts +6 -0
- package/dist/editor/comments/item-anchor-copy.js +6 -0
- package/dist/editor/comments/move-focus-if-unmoved.d.ts +6 -0
- package/dist/editor/comments/move-focus-if-unmoved.js +11 -0
- package/dist/editor/comments/popover-placement.d.ts +18 -0
- package/dist/editor/comments/popover-placement.js +58 -0
- package/dist/editor/comments/use-tracked-writes.d.ts +16 -0
- package/dist/editor/comments/use-tracked-writes.js +53 -0
- package/dist/editor/components/BranchAccessList.d.ts +15 -0
- package/dist/editor/components/BranchAccessList.js +52 -0
- package/dist/editor/components/BranchLockBanner.d.ts +22 -0
- package/dist/editor/components/BranchLockBanner.js +39 -0
- package/dist/editor/components/BranchPill.d.ts +32 -0
- package/dist/editor/components/BranchPill.js +33 -0
- package/dist/editor/components/BranchesDrawer.d.ts +11 -0
- package/dist/editor/components/BranchesDrawer.js +5 -0
- package/dist/editor/components/ConfirmDeleteModal.d.ts +6 -1
- package/dist/editor/components/ConfirmDeleteModal.js +3 -2
- package/dist/editor/components/DestructiveMenuItem.d.ts +7 -0
- package/dist/editor/components/DestructiveMenuItem.js +8 -0
- package/dist/editor/components/EditorCrashScreen.d.ts +17 -0
- package/dist/editor/components/EditorCrashScreen.js +22 -0
- package/dist/editor/components/EditorErrorBoundary.d.ts +38 -0
- package/dist/editor/components/EditorErrorBoundary.js +40 -0
- package/dist/editor/components/EditorHeader.d.ts +56 -106
- package/dist/editor/components/EditorHeader.js +130 -131
- package/dist/editor/components/EditorRail.d.ts +49 -0
- package/dist/editor/components/EditorRail.js +65 -0
- package/dist/editor/components/EntryBreadcrumb.d.ts +33 -0
- package/dist/editor/components/EntryBreadcrumb.js +56 -0
- package/dist/editor/components/EntryCreateModal.d.ts +12 -7
- package/dist/editor/components/EntryCreateModal.js +51 -57
- package/dist/editor/components/NoEditPermissionNotice.d.ts +6 -5
- package/dist/editor/components/NoEditPermissionNotice.js +5 -4
- package/dist/editor/components/QuickOpenPalette.d.ts +22 -0
- package/dist/editor/components/QuickOpenPalette.js +66 -0
- package/dist/editor/components/ReadOnlyDraftNotice.d.ts +11 -0
- package/dist/editor/components/ReadOnlyDraftNotice.js +12 -0
- package/dist/editor/components/ReasonedMenuItem.d.ts +15 -0
- package/dist/editor/components/ReasonedMenuItem.js +15 -0
- package/dist/editor/components/ReferencedByList.d.ts +11 -0
- package/dist/editor/components/ReferencedByList.js +28 -0
- package/dist/editor/components/RelativeTime.d.ts +10 -0
- package/dist/editor/components/RelativeTime.js +10 -0
- package/dist/editor/components/RenameEntryModal.d.ts +9 -1
- package/dist/editor/components/RenameEntryModal.js +19 -31
- package/dist/editor/components/RetryToastMessage.d.ts +9 -0
- package/dist/editor/components/RetryToastMessage.js +6 -0
- package/dist/editor/components/SaveAllResult.d.ts +25 -0
- package/dist/editor/components/SaveAllResult.js +86 -0
- package/dist/editor/components/SaveSplitButton.d.ts +30 -0
- package/dist/editor/components/SaveSplitButton.js +108 -0
- package/dist/editor/components/StagedChangesDrawer.d.ts +39 -0
- package/dist/editor/components/StagedChangesDrawer.js +92 -0
- package/dist/editor/components/UnavailableEntryNotice.d.ts +6 -0
- package/dist/editor/components/UnavailableEntryNotice.js +9 -0
- package/dist/editor/components/UnavailableTypeMessage.d.ts +6 -0
- package/dist/editor/components/UnavailableTypeMessage.js +9 -0
- package/dist/editor/components/UndoToastMessage.d.ts +18 -0
- package/dist/editor/components/UndoToastMessage.js +10 -0
- package/dist/editor/components/UserBadge.d.ts +2 -5
- package/dist/editor/components/UserBadge.js +62 -33
- package/dist/editor/components/ValidationSummary.d.ts +14 -0
- package/dist/editor/components/ValidationSummary.js +24 -0
- package/dist/editor/components/index.d.ts +2 -2
- package/dist/editor/components/index.js +2 -2
- package/dist/editor/context/ApiClientContext.d.ts +8 -2
- package/dist/editor/context/ApiClientContext.js +19 -8
- package/dist/editor/context/AssetContext.d.ts +13 -35
- package/dist/editor/context/AssetContext.js +12 -31
- package/dist/editor/context/EditorStateContext.d.ts +4 -4
- package/dist/editor/context/EditorStateContext.js +4 -4
- package/dist/editor/context/SWRProvider.d.ts +3 -3
- package/dist/editor/context/SiteMdxAllowContext.d.ts +4 -0
- package/dist/editor/context/SiteMdxAllowContext.js +7 -0
- package/dist/editor/context/index.d.ts +2 -1
- package/dist/editor/context/index.js +2 -1
- package/dist/editor/contrast.d.ts +19 -0
- package/dist/editor/contrast.js +41 -0
- package/dist/editor/copy.d.ts +18 -0
- package/dist/editor/copy.js +18 -0
- package/dist/editor/editor-config.js +16 -0
- package/dist/editor/editor-utils.d.ts +34 -8
- package/dist/editor/editor-utils.js +42 -20
- package/dist/editor/entry-search.d.ts +20 -0
- package/dist/editor/entry-search.js +34 -0
- package/dist/editor/field-breadcrumb.d.ts +12 -0
- package/dist/editor/field-breadcrumb.js +85 -0
- package/dist/editor/field-props.d.ts +86 -0
- package/dist/editor/field-props.js +27 -0
- package/dist/editor/field-target.d.ts +30 -0
- package/dist/editor/field-target.js +77 -0
- package/dist/editor/fields/BlockField.d.ts +12 -0
- package/dist/editor/fields/BlockField.js +89 -73
- package/dist/editor/fields/CodeField.d.ts +2 -0
- package/dist/editor/fields/CodeField.js +6 -2
- package/dist/editor/fields/DateTimeField.d.ts +4 -29
- package/dist/editor/fields/DateTimeField.js +79 -41
- package/dist/editor/fields/ExpandAllButton.d.ts +6 -0
- package/dist/editor/fields/ExpandAllButton.js +4 -0
- package/dist/editor/fields/FieldCrashFallback.d.ts +17 -0
- package/dist/editor/fields/FieldCrashFallback.js +30 -0
- package/dist/editor/fields/FieldLabel.d.ts +37 -0
- package/dist/editor/fields/FieldLabel.js +19 -0
- package/dist/editor/fields/ImageField.d.ts +4 -0
- package/dist/editor/fields/ImageField.js +29 -14
- package/dist/editor/fields/InlineGroupField.js +4 -3
- package/dist/editor/fields/ItemList.d.ts +42 -0
- package/dist/editor/fields/ItemList.js +130 -0
- package/dist/editor/fields/MarkdownField.d.ts +32 -0
- package/dist/editor/fields/MarkdownField.js +223 -46
- package/dist/editor/fields/MdxImageDialog.js +1 -1
- package/dist/editor/fields/NumberField.d.ts +2 -0
- package/dist/editor/fields/NumberField.js +8 -5
- package/dist/editor/fields/NumberListField.d.ts +2 -0
- package/dist/editor/fields/NumberListField.js +19 -16
- package/dist/editor/fields/ObjectField.d.ts +2 -7
- package/dist/editor/fields/ObjectField.js +15 -5
- package/dist/editor/fields/ObjectListField.d.ts +29 -0
- package/dist/editor/fields/ObjectListField.js +57 -0
- package/dist/editor/fields/ReferenceField.d.ts +2 -0
- package/dist/editor/fields/ReferenceField.js +34 -9
- package/dist/editor/fields/SelectField.d.ts +2 -0
- package/dist/editor/fields/SelectField.js +11 -2
- package/dist/editor/fields/StringListField.d.ts +4 -1
- package/dist/editor/fields/StringListField.js +22 -8
- package/dist/editor/fields/TextField.d.ts +2 -0
- package/dist/editor/fields/TextField.js +6 -2
- package/dist/editor/fields/ToggleField.d.ts +2 -0
- package/dist/editor/fields/ToggleField.js +8 -3
- package/dist/editor/fields/entry-link/InsertEntryLink.d.ts +1 -1
- package/dist/editor/fields/entry-link/InsertEntryLink.js +1 -1
- package/dist/editor/fields/form-expansion.d.ts +9 -0
- package/dist/editor/fields/form-expansion.js +2 -0
- package/dist/editor/fields/item-expansion.d.ts +15 -0
- package/dist/editor/fields/item-expansion.js +60 -0
- package/dist/editor/fields/list-item-keys.d.ts +8 -0
- package/dist/editor/fields/list-item-keys.js +50 -0
- package/dist/editor/fields/list-item-title.d.ts +20 -0
- package/dist/editor/fields/list-item-title.js +85 -0
- package/dist/editor/fields/markdown-export-options.d.ts +2 -0
- package/dist/editor/fields/markdown-export-options.js +8 -0
- package/dist/editor/fields/markdown-fidelity-visitors.d.ts +11 -0
- package/dist/editor/fields/markdown-fidelity-visitors.js +160 -0
- package/dist/editor/fields/mdx-jsx-support.d.ts +5 -1
- package/dist/editor/fields/mdx-jsx-support.js +157 -69
- package/dist/editor/fields/rich-text-failures.d.ts +5 -0
- package/dist/editor/fields/rich-text-failures.js +26 -0
- package/dist/editor/fields/toolbar-wrap.d.ts +7 -0
- package/dist/editor/fields/toolbar-wrap.js +35 -0
- package/dist/editor/form-outline.d.ts +13 -0
- package/dist/editor/form-outline.js +70 -0
- package/dist/editor/group-manager/GroupCard.d.ts +4 -1
- package/dist/editor/group-manager/GroupCard.js +12 -3
- package/dist/editor/group-manager/GroupForm.js +1 -1
- package/dist/editor/group-manager/InternalGroupsTab.d.ts +2 -1
- package/dist/editor/group-manager/InternalGroupsTab.js +4 -4
- package/dist/editor/group-manager/MemberList.d.ts +2 -1
- package/dist/editor/group-manager/MemberList.js +15 -4
- package/dist/editor/group-manager/hooks/useGroupState.d.ts +5 -0
- package/dist/editor/group-manager/hooks/useGroupState.js +30 -7
- package/dist/editor/group-manager/index.js +34 -5
- package/dist/editor/group-manager/types.d.ts +5 -2
- package/dist/editor/hooks/create-branch-request.d.ts +20 -0
- package/dist/editor/hooks/create-branch-request.js +54 -0
- package/dist/editor/hooks/save-all.d.ts +68 -0
- package/dist/editor/hooks/save-all.js +61 -0
- package/dist/editor/hooks/useBranchActions.d.ts +11 -1
- package/dist/editor/hooks/useBranchActions.js +42 -19
- package/dist/editor/hooks/useBranchManager.d.ts +21 -0
- package/dist/editor/hooks/useBranchManager.js +321 -125
- package/dist/editor/hooks/useBranchesData.d.ts +8 -4
- package/dist/editor/hooks/useBranchesData.js +9 -5
- package/dist/editor/hooks/useCommentSystem.d.ts +14 -2
- package/dist/editor/hooks/useCommentSystem.js +79 -55
- package/dist/editor/hooks/useCommentsData.d.ts +11 -7
- package/dist/editor/hooks/useCommentsData.js +20 -19
- package/dist/editor/hooks/useDraftManager.d.ts +77 -3
- package/dist/editor/hooks/useDraftManager.js +887 -94
- package/dist/editor/hooks/useEditorLayout.d.ts +53 -7
- package/dist/editor/hooks/useEditorLayout.js +98 -20
- package/dist/editor/hooks/useEntriesData.d.ts +2 -1
- package/dist/editor/hooks/useEntriesData.js +18 -4
- package/dist/editor/hooks/useEntryManager.d.ts +41 -2
- package/dist/editor/hooks/useEntryManager.js +227 -41
- package/dist/editor/hooks/useGroupManager.js +13 -16
- package/dist/editor/hooks/usePermissionManager.js +14 -6
- package/dist/editor/hooks/usePreviewMarks.d.ts +21 -0
- package/dist/editor/hooks/usePreviewMarks.js +33 -0
- package/dist/editor/hooks/useReferenceResolution.d.ts +10 -3
- package/dist/editor/hooks/useReferenceResolution.js +34 -177
- package/dist/editor/hooks/useSchemaManager.d.ts +25 -6
- package/dist/editor/hooks/useSchemaManager.js +97 -39
- package/dist/editor/hooks/useUserMetadata.d.ts +14 -4
- package/dist/editor/hooks/useUserMetadata.js +76 -47
- package/dist/editor/hooks/user-metadata-batcher.d.ts +8 -0
- package/dist/editor/hooks/user-metadata-batcher.js +33 -0
- package/dist/editor/media/AssetCard.d.ts +6 -7
- package/dist/editor/media/AssetCard.js +24 -31
- package/dist/editor/media/AssetListRow.d.ts +16 -0
- package/dist/editor/media/AssetListRow.js +41 -0
- package/dist/editor/media/CropStep.js +6 -1
- package/dist/editor/media/MediaLibrary.d.ts +4 -3
- package/dist/editor/media/MediaLibrary.js +11 -4
- package/dist/editor/media/MediaLibraryBody.d.ts +3 -3
- package/dist/editor/media/MediaLibraryBody.js +195 -80
- package/dist/editor/media/MediaLibrarySkeleton.d.ts +6 -0
- package/dist/editor/media/MediaLibrarySkeleton.js +14 -0
- package/dist/editor/media/crop-math.d.ts +3 -4
- package/dist/editor/media/crop-math.js +11 -22
- package/dist/editor/media/editor-image-src.d.ts +8 -0
- package/dist/editor/media/editor-image-src.js +10 -0
- package/dist/editor/media/format-bytes.d.ts +2 -0
- package/dist/editor/media/format-bytes.js +23 -0
- package/dist/editor/media/media-library-prefs.d.ts +23 -0
- package/dist/editor/media/media-library-prefs.js +49 -0
- package/dist/editor/media/media-library-view.d.ts +34 -0
- package/dist/editor/media/media-library-view.js +40 -0
- package/dist/editor/media/useAssetLibrary.d.ts +30 -0
- package/dist/editor/media/useAssetLibrary.js +126 -0
- package/dist/editor/media/useStableAssetOrder.d.ts +11 -0
- package/dist/editor/media/useStableAssetOrder.js +37 -0
- package/dist/editor/media/useThumbnailFailure.d.ts +6 -0
- package/dist/editor/media/useThumbnailFailure.js +16 -0
- package/dist/editor/permission-manager/GroupSelector.js +2 -2
- package/dist/editor/permission-manager/PermissionEditor.d.ts +1 -1
- package/dist/editor/permission-manager/PermissionEditor.js +15 -4
- package/dist/editor/permission-manager/PermissionLevelBadge.js +1 -1
- package/dist/editor/permission-manager/PermissionTree.d.ts +1 -1
- package/dist/editor/permission-manager/UserSelector.d.ts +1 -1
- package/dist/editor/permission-manager/UserSelector.js +3 -3
- package/dist/editor/permission-manager/index.js +12 -3
- package/dist/editor/permission-manager/types.d.ts +5 -2
- package/dist/editor/platform.d.ts +3 -0
- package/dist/editor/platform.js +9 -0
- package/dist/editor/preview-asset-base.d.ts +9 -0
- package/dist/editor/preview-asset-base.js +17 -0
- package/dist/editor/preview-bridge.d.ts +51 -27
- package/dist/editor/preview-bridge.js +103 -144
- package/dist/editor/preview-marks.d.ts +15 -0
- package/dist/editor/preview-marks.js +74 -0
- package/dist/editor/preview-path.d.ts +12 -0
- package/dist/editor/preview-path.js +45 -1
- package/dist/editor/preview-scale.d.ts +27 -0
- package/dist/editor/preview-scale.js +34 -0
- package/dist/editor/raw-asset-base.d.ts +5 -0
- package/dist/editor/raw-asset-base.js +14 -0
- package/dist/editor/relative-time.d.ts +4 -4
- package/dist/editor/relative-time.js +16 -8
- package/dist/editor/schema-editor/CollectionEditor.d.ts +20 -3
- package/dist/editor/schema-editor/CollectionEditor.js +361 -62
- package/dist/editor/schema-editor/EntryTypeEditor.d.ts +5 -1
- package/dist/editor/schema-editor/EntryTypeEditor.js +11 -6
- package/dist/editor/schema-editor/collection-draft.d.ts +22 -0
- package/dist/editor/schema-editor/collection-draft.js +40 -0
- package/dist/editor/schema-editor/index.d.ts +1 -1
- package/dist/editor/schema-label.d.ts +10 -0
- package/dist/editor/schema-label.js +17 -0
- package/dist/editor/settings-conflict.d.ts +5 -0
- package/dist/editor/settings-conflict.js +8 -0
- package/dist/editor/shell/ActivityRail.d.ts +37 -0
- package/dist/editor/shell/ActivityRail.js +91 -0
- package/dist/editor/shell/EditorShell.d.ts +17 -0
- package/dist/editor/shell/EditorShell.js +31 -0
- package/dist/editor/shell/PaneLayout.d.ts +28 -0
- package/dist/editor/shell/PaneLayout.js +116 -0
- package/dist/editor/shell/SidePanelHost.d.ts +35 -0
- package/dist/editor/shell/SidePanelHost.js +184 -0
- package/dist/editor/shell/TopBar.d.ts +12 -0
- package/dist/editor/shell/TopBar.js +14 -0
- package/dist/editor/shell/host-chrome.d.ts +16 -0
- package/dist/editor/shell/host-chrome.js +69 -0
- package/dist/editor/slug.d.ts +16 -0
- package/dist/editor/slug.js +43 -0
- package/dist/editor/theme.d.ts +2 -1
- package/dist/editor/theme.js +314 -13
- package/dist/editor/unanswered.d.ts +17 -0
- package/dist/editor/unanswered.js +26 -0
- package/dist/editor/unavailable-entry-type.d.ts +20 -0
- package/dist/editor/unavailable-entry-type.js +28 -0
- package/dist/editor/undo-removal.d.ts +57 -0
- package/dist/editor/undo-removal.js +163 -0
- package/dist/editor/user-display.d.ts +4 -0
- package/dist/editor/user-display.js +5 -0
- package/dist/editor/utils/confirm-modal.d.ts +8 -0
- package/dist/editor/utils/confirm-modal.js +12 -0
- package/dist/editor/utils/editor-errors.d.ts +19 -0
- package/dist/editor/utils/editor-errors.js +32 -0
- package/dist/editor/utils/focus-return.d.ts +56 -0
- package/dist/editor/utils/focus-return.js +106 -0
- package/dist/entry-link-resolver.d.ts +11 -1
- package/dist/entry-link-resolver.js +65 -5
- package/dist/entry-schema-registry.d.ts +3 -3
- package/dist/entry-schema-registry.js +7 -4
- package/dist/entry-schema.d.ts +49 -3
- package/dist/entry-schema.js +18 -0
- package/dist/git-manager.d.ts +172 -10
- package/dist/git-manager.js +449 -107
- package/dist/github-service.d.ts +39 -2
- package/dist/github-service.js +101 -7
- package/dist/http/handler.js +74 -9
- package/dist/http/types.d.ts +2 -0
- package/dist/http/worker-not-ready.d.ts +9 -4
- package/dist/http/worker-not-ready.js +59 -6
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/item-keys.d.ts +46 -0
- package/dist/item-keys.js +235 -0
- package/dist/operating-mode/editor-mode-check.d.ts +15 -0
- package/dist/operating-mode/editor-mode-check.js +24 -0
- package/dist/operating-mode/mode-env.d.ts +13 -14
- package/dist/operating-mode/mode-env.js +13 -14
- package/dist/operating-mode/types.d.ts +2 -2
- package/dist/paths/branch.d.ts +0 -1
- package/dist/paths/branch.js +1 -8
- package/dist/paths/index.d.ts +1 -1
- package/dist/paths/index.js +1 -1
- package/dist/paths/validation.js +0 -2
- package/dist/preview.d.ts +8 -0
- package/dist/preview.js +7 -0
- package/dist/reference-resolver.js +1 -0
- package/dist/resolve-canopy-user.d.ts +1 -1
- package/dist/resolve-canopy-user.js +1 -1
- package/dist/schema/meta-loader.d.ts +18 -8
- package/dist/schema/meta-loader.js +42 -9
- package/dist/schema/registry-fingerprint.d.ts +14 -0
- package/dist/schema/registry-fingerprint.js +63 -0
- package/dist/schema/resolver.d.ts +7 -4
- package/dist/schema/resolver.js +7 -6
- package/dist/schema/schema-store.d.ts +7 -10
- package/dist/schema/schema-store.js +13 -11
- package/dist/schema/schema-unavailable-error.d.ts +11 -0
- package/dist/schema/schema-unavailable-error.js +15 -0
- package/dist/schema/types.d.ts +22 -0
- package/dist/schema-registry-record.d.ts +35 -0
- package/dist/schema-registry-record.js +134 -0
- package/dist/server.d.ts +79 -9
- package/dist/server.js +62 -8
- package/dist/services.d.ts +33 -5
- package/dist/services.js +155 -37
- package/dist/settings-workspace.d.ts +23 -3
- package/dist/settings-workspace.js +159 -45
- package/dist/stamp-on-publish.d.ts +36 -0
- package/dist/stamp-on-publish.js +71 -0
- package/dist/static/index.d.ts +58 -5
- package/dist/static/index.js +133 -3
- package/dist/static/seo.d.ts +5 -5
- package/dist/static/seo.js +5 -5
- package/dist/submission-attribution.d.ts +8 -0
- package/dist/submission-attribution.js +22 -0
- package/dist/system-users.d.ts +12 -0
- package/dist/system-users.js +12 -0
- package/dist/task-queue/cms-task-queue.d.ts +1 -1
- package/dist/task-queue/cms-task-queue.js +1 -1
- package/dist/task-queue/index.d.ts +1 -1
- package/dist/task-queue/index.js +1 -1
- package/dist/task-queue/task-queue.d.ts +6 -0
- package/dist/task-queue/task-queue.js +29 -0
- package/dist/task-queue/worker-status.d.ts +35 -9
- package/dist/task-queue/worker-status.js +84 -17
- package/dist/types.d.ts +90 -9
- package/dist/url-collision.js +3 -3
- package/dist/url-exclusivity-fixtures.d.ts +8 -1
- package/dist/url-exclusivity-fixtures.js +11 -1
- package/dist/user.js +2 -1
- package/dist/utils/atomic-write.js +2 -1
- package/dist/utils/base-branch.d.ts +13 -0
- package/dist/utils/base-branch.js +23 -0
- package/dist/utils/content-serialize.d.ts +15 -7
- package/dist/utils/content-serialize.js +353 -51
- package/dist/utils/content-write-lock.d.ts +6 -1
- package/dist/utils/content-write-lock.js +21 -6
- package/dist/utils/debug.d.ts +1 -1
- package/dist/utils/debug.js +5 -3
- package/dist/utils/error.js +13 -2
- package/dist/utils/escape-text.d.ts +7 -0
- package/dist/utils/escape-text.js +27 -0
- package/dist/utils/fs.d.ts +12 -4
- package/dist/utils/fs.js +18 -5
- package/dist/utils/git.d.ts +21 -1
- package/dist/utils/git.js +63 -8
- package/dist/utils/json-source-splice.d.ts +14 -0
- package/dist/utils/json-source-splice.js +120 -0
- package/dist/utils/markdown-body-splice.d.ts +39 -0
- package/dist/utils/markdown-body-splice.js +421 -0
- package/dist/utils/occ-json-write.js +18 -12
- package/dist/utils/provision-log.d.ts +25 -0
- package/dist/utils/provision-log.js +49 -0
- package/dist/utils/provisioning-lock.d.ts +32 -1
- package/dist/utils/provisioning-lock.js +78 -32
- package/dist/utils/sanitize-href.d.ts +9 -23
- package/dist/utils/sanitize-href.js +14 -28
- package/dist/utils/title-field.d.ts +10 -0
- package/dist/utils/title-field.js +47 -0
- package/dist/utils/yaml-source-splice.d.ts +58 -0
- package/dist/utils/yaml-source-splice.js +515 -0
- package/dist/validation/block-structural-keys.d.ts +1 -1
- package/dist/validation/block-structural-keys.js +1 -1
- package/dist/validation/deletion-checker.d.ts +21 -29
- package/dist/validation/deletion-checker.js +41 -117
- package/dist/validation/entry-validator.d.ts +6 -10
- package/dist/validation/entry-validator.js +19 -26
- package/dist/validation/field-traversal.d.ts +22 -0
- package/dist/validation/field-traversal.js +39 -8
- package/dist/validation/markdown-safety.d.ts +68 -0
- package/dist/validation/markdown-safety.js +596 -0
- package/dist/validation/mdx-allowlist.d.ts +55 -0
- package/dist/validation/mdx-allowlist.js +183 -0
- package/dist/validation/reference-validator.d.ts +2 -0
- package/dist/validation/reference-validator.js +3 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker/branch-policy.d.ts +124 -0
- package/dist/worker/branch-policy.js +243 -0
- package/dist/worker/bundle-header.d.ts +117 -0
- package/dist/worker/bundle-header.js +253 -0
- package/dist/worker/cms-worker.d.ts +236 -142
- package/dist/worker/cms-worker.js +772 -285
- package/dist/worker/gateway-egress.d.ts +43 -0
- package/dist/worker/gateway-egress.js +209 -0
- package/dist/worker/gateway-instance.d.ts +42 -0
- package/dist/worker/gateway-instance.js +129 -0
- package/dist/worker/git-process.d.ts +81 -0
- package/dist/worker/git-process.js +234 -0
- package/dist/worker/git-sync.d.ts +34 -17
- package/dist/worker/git-sync.js +394 -131
- package/dist/worker/github-auth.d.ts +9 -9
- package/dist/worker/github-auth.js +13 -15
- package/dist/worker/github-gateway-http.d.ts +62 -0
- package/dist/worker/github-gateway-http.js +977 -0
- package/dist/worker/github-gateway-wire.d.ts +590 -0
- package/dist/worker/github-gateway-wire.js +488 -0
- package/dist/worker/github-gateway.d.ts +238 -0
- package/dist/worker/github-gateway.js +726 -0
- package/dist/worker/github-mirror-upkeep.d.ts +75 -0
- package/dist/worker/github-mirror-upkeep.js +266 -0
- package/dist/worker/github-mirror.d.ts +364 -0
- package/dist/worker/github-mirror.js +1030 -0
- package/dist/worker/github-transfer.d.ts +56 -0
- package/dist/worker/github-transfer.js +444 -0
- package/dist/worker/history-rewrite.d.ts +4 -5
- package/dist/worker/history-rewrite.js +12 -17
- package/dist/worker/provisioned-workspace.d.ts +5 -5
- package/dist/worker/provisioned-workspace.js +5 -5
- package/dist/worker/rebase.d.ts +1 -1
- package/dist/worker/rebase.js +58 -54
- package/dist/worker/remote-git-maintenance.d.ts +3 -0
- package/dist/worker/remote-git-maintenance.js +12 -0
- package/dist/worker/schema-gate.d.ts +49 -0
- package/dist/worker/schema-gate.js +226 -0
- package/dist/worker/self-checks.d.ts +107 -0
- package/dist/worker/self-checks.js +358 -0
- package/dist/worker/shared-repo-git.d.ts +96 -0
- package/dist/worker/shared-repo-git.js +459 -0
- package/dist/worker/sparse-cone.d.ts +20 -0
- package/dist/worker/sparse-cone.js +136 -0
- package/dist/worker/stale-mirror.d.ts +82 -0
- package/dist/worker/stale-mirror.js +130 -0
- package/dist/worker/task-runner.d.ts +5 -3
- package/dist/worker/task-runner.js +287 -186
- package/dist/worker/worker-context.d.ts +36 -37
- package/package.json +35 -7
- package/dist/editor/EditorPanes.d.ts +0 -10
- package/dist/editor/EditorPanes.js +0 -98
- package/dist/editor/components/EditorFooter.d.ts +0 -11
- package/dist/editor/components/EditorFooter.js +0 -9
- package/dist/editor/components/EditorSidebar.d.ts +0 -67
- package/dist/editor/components/EditorSidebar.js +0 -22
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import net from 'node:net';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { getErrorMessage, isNodeError } from '../utils/error.js';
|
|
5
|
+
/** The instance metadata service's IPv4 address; the launch template sets no IPv6 endpoint. */
|
|
6
|
+
const IMDS_HOST = '169.254.169.254';
|
|
7
|
+
/** How long the IMDS connect may take before it counts as unreachable. */
|
|
8
|
+
const IMDS_CONNECT_TIMEOUT_MS = 1_000;
|
|
9
|
+
/** Connect failures that prove no route: no network, or no IPv4 sockets at all. */
|
|
10
|
+
const NO_ROUTE_CODES = new Set(['ENETUNREACH', 'EAFNOSUPPORT']);
|
|
11
|
+
/**
|
|
12
|
+
* The variables that hold a secret, or name one (ARNs, JSON fields), and belong to the gateway:
|
|
13
|
+
* CanopyCMS's GitHub and Clerk settings.
|
|
14
|
+
*/
|
|
15
|
+
const SECRET_ENV_PATTERN = /^(?:CANOPYCMS_GITHUB_TOKEN|CANOPYCMS_GITHUB_APP_|CLERK_SECRET_KEY)/;
|
|
16
|
+
/**
|
|
17
|
+
* The conventional credential variables: GitHub tokens (`GITHUB_BOT_TOKEN` is canopycms's default
|
|
18
|
+
* `githubTokenEnvVar`) and the AWS SDK's static credentials. The worker's git reads none (its
|
|
19
|
+
* environment is git-manager.ts's allowlist), but code that becomes the worker reads its
|
|
20
|
+
* environment. Exact names, so a look-alike such as `GITHUB_TOKEN_PATH` passes.
|
|
21
|
+
* `CLERK_JWT_KEY` is not here: it is a public verification key.
|
|
22
|
+
*/
|
|
23
|
+
const AMBIENT_CREDENTIAL_ENV_NAMES = new Set([
|
|
24
|
+
'GH_TOKEN',
|
|
25
|
+
'GITHUB_TOKEN',
|
|
26
|
+
'GITHUB_BOT_TOKEN',
|
|
27
|
+
'AWS_ACCESS_KEY_ID',
|
|
28
|
+
'AWS_SECRET_ACCESS_KEY',
|
|
29
|
+
'AWS_SESSION_TOKEN',
|
|
30
|
+
'AWS_SECURITY_TOKEN',
|
|
31
|
+
]);
|
|
32
|
+
/** The worker unit's checks, in the plan's order. */
|
|
33
|
+
export async function workerSelfChecks(environment = {}) {
|
|
34
|
+
return [
|
|
35
|
+
await imdsUnreachable(environment),
|
|
36
|
+
await onlyLoopback(environment),
|
|
37
|
+
await procShowsOnlyOwnProcesses(environment),
|
|
38
|
+
await homeIsEmpty(environment),
|
|
39
|
+
noSecretsInEnv(environment),
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
/** The gateway unit's checks. */
|
|
43
|
+
export async function gatewaySelfChecks(environment = {}) {
|
|
44
|
+
return [
|
|
45
|
+
await efsUnreadable(environment),
|
|
46
|
+
await corePatternNotPiped(environment),
|
|
47
|
+
await coreLimitZero(environment),
|
|
48
|
+
...(environment.listenFd === undefined ? [] : [await socketAccessIsOthers(environment)]),
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
/** Throw one error naming every failed check, or return. */
|
|
52
|
+
export function assertSelfChecks(results) {
|
|
53
|
+
const failed = results.filter((result) => !result.ok);
|
|
54
|
+
if (failed.length === 0)
|
|
55
|
+
return;
|
|
56
|
+
throw new Error(`Refusing to start: ${failed.map((result) => `${result.check}: ${result.detail}`).join('; ')}`);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A TCP connect to IMDS fails with no route (`ENETUNREACH`, or `EAFNOSUPPORT` under
|
|
60
|
+
* `RestrictAddressFamilies=AF_UNIX`) or times out. Any other outcome, a refusal included, means a
|
|
61
|
+
* route exists.
|
|
62
|
+
* @internal Exported for tests.
|
|
63
|
+
*/
|
|
64
|
+
export async function imdsUnreachable(environment = {}) {
|
|
65
|
+
const connect = environment.connect ?? tcpConnect;
|
|
66
|
+
const outcome = await connect(IMDS_HOST, 80, IMDS_CONNECT_TIMEOUT_MS);
|
|
67
|
+
if (outcome === 'timeout' || (outcome !== 'connected' && NO_ROUTE_CODES.has(outcome.code))) {
|
|
68
|
+
return {
|
|
69
|
+
check: 'imds',
|
|
70
|
+
ok: true,
|
|
71
|
+
detail: outcome === 'timeout' ? 'timed out' : outcome.code,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
check: 'imds',
|
|
76
|
+
ok: false,
|
|
77
|
+
detail: `the worker unit can reach the instance metadata service (${outcome === 'connected' ? 'connected' : outcome.code}), ` +
|
|
78
|
+
'so the process split protects nothing',
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* `/proc/self/net/dev` lists only `lo`: `PrivateNetwork=` took effect. Not `/sys/class/net`, which
|
|
83
|
+
* `PrivateNetwork=` does not remount, so it shows the host's interfaces even inside the cut.
|
|
84
|
+
* @internal Exported for tests.
|
|
85
|
+
*/
|
|
86
|
+
export async function onlyLoopback(environment = {}) {
|
|
87
|
+
const file = path.join(rootOf(environment), 'proc', 'self', 'net', 'dev');
|
|
88
|
+
let text;
|
|
89
|
+
try {
|
|
90
|
+
text = await fs.readFile(file, 'utf8');
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
return {
|
|
94
|
+
check: 'network-namespace',
|
|
95
|
+
ok: false,
|
|
96
|
+
detail: `cannot read ${file}: ${getErrorMessage(err)}`,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
const interfaces = text
|
|
100
|
+
.split('\n')
|
|
101
|
+
.slice(2)
|
|
102
|
+
.map((line) => line.split(':')[0]?.trim() ?? '')
|
|
103
|
+
.filter((name) => name !== '');
|
|
104
|
+
const ok = interfaces.length === 1 && interfaces[0] === 'lo';
|
|
105
|
+
return {
|
|
106
|
+
check: 'network-namespace',
|
|
107
|
+
ok,
|
|
108
|
+
detail: ok
|
|
109
|
+
? 'only lo'
|
|
110
|
+
: `the worker unit sees network interfaces besides lo (${interfaces.join(', ')}): it is not in a private network namespace`,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Every process `/proc` lists is this uid's: `ProtectProc=invisible` took effect.
|
|
115
|
+
* @internal Exported for tests.
|
|
116
|
+
*/
|
|
117
|
+
export async function procShowsOnlyOwnProcesses(environment = {}) {
|
|
118
|
+
const proc = path.join(rootOf(environment), 'proc');
|
|
119
|
+
const uid = environment.uid ?? process.getuid?.();
|
|
120
|
+
if (uid === undefined) {
|
|
121
|
+
return { check: 'proc', ok: false, detail: 'this platform has no process uid to compare' };
|
|
122
|
+
}
|
|
123
|
+
let entries;
|
|
124
|
+
try {
|
|
125
|
+
entries = await fs.readdir(proc);
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
return { check: 'proc', ok: false, detail: `cannot list ${proc}: ${getErrorMessage(err)}` };
|
|
129
|
+
}
|
|
130
|
+
const others = [];
|
|
131
|
+
for (const entry of entries.filter((name) => /^\d+$/.test(name))) {
|
|
132
|
+
try {
|
|
133
|
+
const stat = await fs.stat(path.join(proc, entry));
|
|
134
|
+
if (stat.uid !== uid)
|
|
135
|
+
others.push(`${entry} (uid ${stat.uid})`);
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
// A process that exited between the listing and the stat.
|
|
139
|
+
if (!(isNodeError(err) && err.code === 'ENOENT')) {
|
|
140
|
+
others.push(`${entry} (${getErrorMessage(err)})`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const ok = others.length === 0;
|
|
145
|
+
return {
|
|
146
|
+
check: 'proc',
|
|
147
|
+
ok,
|
|
148
|
+
detail: ok
|
|
149
|
+
? `only uid ${uid}`
|
|
150
|
+
: `the worker unit sees other users' processes: ${others.slice(0, 5).join(', ')}`,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* `/home` is empty: `ProtectHome=tmpfs`'s always-observable effect. `/run/user`, which it also
|
|
155
|
+
* hides, is empty anyway whenever nobody is logged in.
|
|
156
|
+
* @internal Exported for tests.
|
|
157
|
+
*/
|
|
158
|
+
export async function homeIsEmpty(environment = {}) {
|
|
159
|
+
const home = path.join(rootOf(environment), 'home');
|
|
160
|
+
try {
|
|
161
|
+
const entries = await fs.readdir(home);
|
|
162
|
+
return {
|
|
163
|
+
check: 'home',
|
|
164
|
+
ok: entries.length === 0,
|
|
165
|
+
detail: entries.length === 0
|
|
166
|
+
? 'empty'
|
|
167
|
+
: `the worker unit sees ${home}'s entries: ProtectHome=tmpfs did not apply`,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
catch (err) {
|
|
171
|
+
return { check: 'home', ok: false, detail: `cannot list ${home}: ${getErrorMessage(err)}` };
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* No GitHub or Clerk secret, nor the ARN or JSON field naming one, is in the worker's environment:
|
|
176
|
+
* they belong to the gateway's env file. Nor is a conventional credential variable (a GitHub token,
|
|
177
|
+
* the AWS SDK's static credentials). Names only are reported.
|
|
178
|
+
* @internal Exported for tests.
|
|
179
|
+
*/
|
|
180
|
+
export function noSecretsInEnv(environment = {}) {
|
|
181
|
+
const env = environment.env ?? process.env;
|
|
182
|
+
const found = Object.keys(env)
|
|
183
|
+
.filter((key) => env[key] !== undefined &&
|
|
184
|
+
(SECRET_ENV_PATTERN.test(key) || AMBIENT_CREDENTIAL_ENV_NAMES.has(key)))
|
|
185
|
+
.sort();
|
|
186
|
+
const ok = found.length === 0;
|
|
187
|
+
return {
|
|
188
|
+
check: 'secrets-in-env',
|
|
189
|
+
ok,
|
|
190
|
+
detail: ok
|
|
191
|
+
? 'none'
|
|
192
|
+
: `the worker unit's environment holds ${found.join(', ')}, which the worker must not hold`,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* The gateway cannot list `/mnt/efs`: `InaccessiblePaths=/mnt/efs` took effect.
|
|
197
|
+
* @internal Exported for tests.
|
|
198
|
+
*/
|
|
199
|
+
export async function efsUnreadable(environment = {}) {
|
|
200
|
+
const efs = path.join(rootOf(environment), 'mnt', 'efs');
|
|
201
|
+
try {
|
|
202
|
+
await fs.readdir(efs);
|
|
203
|
+
}
|
|
204
|
+
catch (err) {
|
|
205
|
+
// Denied is the directive at work. Absent (a unit without `RequiresMountsFor=`, started before
|
|
206
|
+
// the mount) or any other failure proves nothing: a mount made later could still reach it.
|
|
207
|
+
const code = isNodeError(err) ? err.code : undefined;
|
|
208
|
+
const denied = code === 'EACCES' || code === 'EPERM';
|
|
209
|
+
return {
|
|
210
|
+
check: 'efs-unreadable',
|
|
211
|
+
ok: denied,
|
|
212
|
+
detail: denied
|
|
213
|
+
? (code ?? '')
|
|
214
|
+
: `cannot tell that ${efs} is inaccessible: ${getErrorMessage(err)}`,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
return {
|
|
218
|
+
check: 'efs-unreadable',
|
|
219
|
+
ok: false,
|
|
220
|
+
detail: `the GitHub gateway can read ${efs}, where the CMS Lambda writes`,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* `kernel.core_pattern` does not begin with `|`: a piped pattern would hand a crashing gateway
|
|
225
|
+
* git's memory (the credential file's contents) to a helper.
|
|
226
|
+
* @internal Exported for tests.
|
|
227
|
+
*/
|
|
228
|
+
export async function corePatternNotPiped(environment = {}) {
|
|
229
|
+
const file = path.join(rootOf(environment), 'proc', 'sys', 'kernel', 'core_pattern');
|
|
230
|
+
try {
|
|
231
|
+
const pattern = (await fs.readFile(file, 'utf8')).trim();
|
|
232
|
+
const ok = !pattern.startsWith('|');
|
|
233
|
+
return {
|
|
234
|
+
check: 'core-pattern',
|
|
235
|
+
ok,
|
|
236
|
+
detail: ok ? pattern : `kernel.core_pattern pipes core dumps to a program (${pattern})`,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
catch (err) {
|
|
240
|
+
return {
|
|
241
|
+
check: 'core-pattern',
|
|
242
|
+
ok: false,
|
|
243
|
+
detail: `cannot read ${file}: ${getErrorMessage(err)}`,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* `/proc/self/limits` shows a zero core limit, soft and hard: `LimitCORE=0` took effect.
|
|
249
|
+
* @internal Exported for tests.
|
|
250
|
+
*/
|
|
251
|
+
export async function coreLimitZero(environment = {}) {
|
|
252
|
+
const file = path.join(rootOf(environment), 'proc', 'self', 'limits');
|
|
253
|
+
let text;
|
|
254
|
+
try {
|
|
255
|
+
text = await fs.readFile(file, 'utf8');
|
|
256
|
+
}
|
|
257
|
+
catch (err) {
|
|
258
|
+
return {
|
|
259
|
+
check: 'core-limit',
|
|
260
|
+
ok: false,
|
|
261
|
+
detail: `cannot read ${file}: ${getErrorMessage(err)}`,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
const line = text.split('\n').find((row) => row.startsWith('Max core file size'));
|
|
265
|
+
const [soft, hard] = line?.slice('Max core file size'.length).trim().split(/\s+/) ?? [];
|
|
266
|
+
const ok = soft === '0' && hard === '0';
|
|
267
|
+
return {
|
|
268
|
+
check: 'core-limit',
|
|
269
|
+
ok,
|
|
270
|
+
detail: ok
|
|
271
|
+
? 'zero'
|
|
272
|
+
: `the core file size limit is ${soft ?? '?'} (soft) and ${hard ?? '?'} (hard), not zero`,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* The socket systemd passed is one only another user (and root) can connect to: its node is not
|
|
277
|
+
* this process's uid, and grants no group or other access. Whoever owns it is the worker, so a
|
|
278
|
+
* gateway running as that user (a unit without `User=canopy-github`) would hand the worker its
|
|
279
|
+
* own environment and memory. A socket's own descriptor reports the creating process (systemd,
|
|
280
|
+
* root), not the node's owner, so the node is found by the socket's inode in
|
|
281
|
+
* `/proc/self/net/unix`.
|
|
282
|
+
* @internal Exported for tests.
|
|
283
|
+
*/
|
|
284
|
+
export async function socketAccessIsOthers(environment = {}) {
|
|
285
|
+
const fail = (detail) => ({ check: 'socket-access', ok: false, detail });
|
|
286
|
+
const uid = environment.uid ?? process.getuid?.();
|
|
287
|
+
if (uid === undefined)
|
|
288
|
+
return fail('this platform has no process uid to compare');
|
|
289
|
+
const fd = environment.listenFd ?? 3;
|
|
290
|
+
const proc = path.join(rootOf(environment), 'proc', 'self');
|
|
291
|
+
let socketPath;
|
|
292
|
+
try {
|
|
293
|
+
const inode = (await fs.stat(path.join(proc, 'fd', String(fd)))).ino;
|
|
294
|
+
const table = await fs.readFile(path.join(proc, 'net', 'unix'), 'utf8');
|
|
295
|
+
// Num RefCount Protocol Flags Type St Inode Path; the path is absent for an unbound socket.
|
|
296
|
+
for (const line of table.split('\n').slice(1)) {
|
|
297
|
+
const fields = line.trim().split(/\s+/);
|
|
298
|
+
if (fields[6] === String(inode) && fields.length > 7)
|
|
299
|
+
socketPath = fields.slice(7).join(' ');
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
catch (err) {
|
|
303
|
+
return fail(`cannot find the socket on descriptor ${fd}: ${getErrorMessage(err)}`);
|
|
304
|
+
}
|
|
305
|
+
if (socketPath === undefined || !path.isAbsolute(socketPath)) {
|
|
306
|
+
return fail(`the socket on descriptor ${fd} is not bound to a path`);
|
|
307
|
+
}
|
|
308
|
+
let node;
|
|
309
|
+
try {
|
|
310
|
+
node = await fs.lstat(socketPath);
|
|
311
|
+
}
|
|
312
|
+
catch (err) {
|
|
313
|
+
return fail(`cannot read ${socketPath}: ${getErrorMessage(err)}`);
|
|
314
|
+
}
|
|
315
|
+
if (!node.isSocket())
|
|
316
|
+
return fail(`${socketPath} is not a socket`);
|
|
317
|
+
if (node.uid === uid) {
|
|
318
|
+
return fail(`the GitHub gateway runs as uid ${uid}, which owns its socket ${socketPath} and so is the ` +
|
|
319
|
+
"worker's user: give the gateway unit User=canopy-github");
|
|
320
|
+
}
|
|
321
|
+
if ((node.mode & 0o077) !== 0) {
|
|
322
|
+
return fail(`${socketPath} has mode ${(node.mode & 0o777).toString(8)}, so users besides its owner can ` +
|
|
323
|
+
'reach the gateway: give the socket unit SocketMode=0600');
|
|
324
|
+
}
|
|
325
|
+
return { check: 'socket-access', ok: true, detail: `${socketPath} is uid ${node.uid}'s alone` };
|
|
326
|
+
}
|
|
327
|
+
function rootOf(environment) {
|
|
328
|
+
return environment.root ?? '/';
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* One TCP connect, as the IMDS check makes it.
|
|
332
|
+
* @internal Exported for tests.
|
|
333
|
+
*/
|
|
334
|
+
export function tcpConnect(host, port, timeoutMs) {
|
|
335
|
+
return new Promise((resolve) => {
|
|
336
|
+
let socket;
|
|
337
|
+
try {
|
|
338
|
+
socket = net.connect({ host, port });
|
|
339
|
+
}
|
|
340
|
+
catch (err) {
|
|
341
|
+
resolve({ code: isNodeError(err) && err.code !== undefined ? err.code : 'ERROR' });
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
const timer = setTimeout(() => {
|
|
345
|
+
socket.destroy();
|
|
346
|
+
resolve('timeout');
|
|
347
|
+
}, timeoutMs);
|
|
348
|
+
socket.once('connect', () => {
|
|
349
|
+
clearTimeout(timer);
|
|
350
|
+
socket.destroy();
|
|
351
|
+
resolve('connected');
|
|
352
|
+
});
|
|
353
|
+
socket.once('error', (err) => {
|
|
354
|
+
clearTimeout(timer);
|
|
355
|
+
resolve({ code: isNodeError(err) && err.code !== undefined ? err.code : 'ERROR' });
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { type SimpleGit, type SimpleGitOptions } from 'simple-git';
|
|
2
|
+
export type SharedRepoKind = 'bare' | 'worktree';
|
|
3
|
+
/**
|
|
4
|
+
* The pins alone, without the environment {@link sharedRepoGit} adds (an explicit `GIT_DIR`, no
|
|
5
|
+
* lazy fetches), which every worker git in a shared repository needs too.
|
|
6
|
+
* @internal Exported for tests.
|
|
7
|
+
*/
|
|
8
|
+
export declare function sharedRepoGitOptions(kind: SharedRepoKind): Pick<SimpleGitOptions, 'config' | 'unsafe'>;
|
|
9
|
+
/**
|
|
10
|
+
* A worker git instance in the shared repository at `repoPath` (the bare repository itself, or a
|
|
11
|
+
* clone's working tree), with the pins applied. The repository is named outright, as
|
|
12
|
+
* {@link assertSharedRepoConfig} names it, so both read the same config: discovery would take a
|
|
13
|
+
* planted `remote.git/.git`, or a `.git` above a clone whose own was removed. A clone's working
|
|
14
|
+
* tree is named too, which also overrides `core.worktree`.
|
|
15
|
+
*
|
|
16
|
+
* `options` are the caller's own (`timeout`, `abort`), applied under the pins. The child env is
|
|
17
|
+
* `gitChildEnv`'s: every shared-repository operation is local.
|
|
18
|
+
*/
|
|
19
|
+
export declare function sharedRepoGit(repoPath: string, kind: SharedRepoKind, options?: Partial<SimpleGitOptions>): SimpleGit;
|
|
20
|
+
/** simple-git options for the worker's private GitHub mirror. */
|
|
21
|
+
export declare function mirrorGitOptions(): Pick<SimpleGitOptions, 'config' | 'unsafe'>;
|
|
22
|
+
/** {@link mirrorGitOptions}'s pins, for a git the mirror runs without simple-git (worker/git-process.ts). */
|
|
23
|
+
export declare function mirrorPins(): string[];
|
|
24
|
+
/**
|
|
25
|
+
* The pins of a quarantine repository, where the GitHub gateway takes in a pushed bundle
|
|
26
|
+
* (worker/github-mirror.ts): the mirror's, without `core.alternateRefsCommand=true`. That pin
|
|
27
|
+
* guards an alternates file the Lambda can write; a quarantine's names the mirror and is written
|
|
28
|
+
* by the gateway. With it, the fetch's connectivity check could not stop at the mirror's heads and
|
|
29
|
+
* would walk the mirror's whole history for every push.
|
|
30
|
+
*/
|
|
31
|
+
export declare function quarantinePins(): string[];
|
|
32
|
+
/**
|
|
33
|
+
* {@link sharedRepoGit}'s pins, environment and working directory, for a git run through
|
|
34
|
+
* worker/git-process.ts: one whose stdin or stdout is a stream.
|
|
35
|
+
*/
|
|
36
|
+
export declare function sharedRepoProcessOptions(repoPath: string, kind: SharedRepoKind): {
|
|
37
|
+
cwd: string;
|
|
38
|
+
env: Record<string, string>;
|
|
39
|
+
config: string[];
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* `--upload-pack` for a fetch FROM `remote.git` into a clone.
|
|
43
|
+
* @internal Exported for tests.
|
|
44
|
+
*/
|
|
45
|
+
export declare function pinnedUploadPack(): string;
|
|
46
|
+
/**
|
|
47
|
+
* `--receive-pack` for a push INTO `remote.git`. Without it the push runs remote.git's own hooks
|
|
48
|
+
* as the worker. The `receive.deny*` pins keep a planted setting from blocking the forced update
|
|
49
|
+
* that publishes a rewritten history (worker/history-rewrite.ts).
|
|
50
|
+
*/
|
|
51
|
+
export declare function pinnedReceivePack(): string;
|
|
52
|
+
/**
|
|
53
|
+
* Fetch `branch` from `remote.git` into the clone `git` runs in, through
|
|
54
|
+
* {@link pinnedUploadPack}. The result is in FETCH_HEAD only.
|
|
55
|
+
*/
|
|
56
|
+
export declare function fetchFromRemoteGit(git: SimpleGit, remoteGitPath: string, branch: string): Promise<void>;
|
|
57
|
+
/** @internal Exported for tests. */
|
|
58
|
+
export interface UnexpectedConfigKey {
|
|
59
|
+
key: string;
|
|
60
|
+
/** The file git read it from, absolute. */
|
|
61
|
+
file: string;
|
|
62
|
+
}
|
|
63
|
+
/** Every refusal to run git in a shared repository, so a caller can tell one from git's own errors. */
|
|
64
|
+
export declare class SharedRepoRefusalError extends Error {
|
|
65
|
+
constructor(message: string);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* A shared repository whose own config holds a key CanopyCMS never writes.
|
|
69
|
+
* @internal Exported for tests.
|
|
70
|
+
*/
|
|
71
|
+
export declare class UntrustedRepoConfigError extends SharedRepoRefusalError {
|
|
72
|
+
readonly repoPath: string;
|
|
73
|
+
readonly keys: readonly UnexpectedConfigKey[];
|
|
74
|
+
constructor(repoPath: string, keys: readonly UnexpectedConfigKey[]);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Refuse a shared repository whose own config (with its includes, and `config.worktree`) holds a
|
|
78
|
+
* key outside {@link ALLOWED_REPO_CONFIG_KEYS}, or a submodule with a repository in it. Throws
|
|
79
|
+
* {@link UntrustedRepoConfigError} for a key. A config git cannot read, or does not finish reading,
|
|
80
|
+
* is also refused, with git's own message for a bad line, which names the line but not its content.
|
|
81
|
+
*
|
|
82
|
+
* `repoPath` is the bare repository itself for `bare`, the working tree for `worktree`.
|
|
83
|
+
*/
|
|
84
|
+
export declare function assertSharedRepoConfig(repoPath: string, kind: SharedRepoKind, options?: {
|
|
85
|
+
timeoutMs?: number;
|
|
86
|
+
}): Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* Refuse a rebase or fast-forward from `from` to `to` in `clone` that would bring in a submodule
|
|
89
|
+
* at a path where a repository already sits, as one planted ahead of it would.
|
|
90
|
+
*/
|
|
91
|
+
export declare function assertNoIncomingSubmodules(git: SimpleGit, clone: string, from: string, to: string): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Arguments for every worker `git status` in a clone. On the command line, unlike in config, the
|
|
94
|
+
* setting outranks a `.gitmodules` entry's own `ignore`.
|
|
95
|
+
*/
|
|
96
|
+
export declare const SHARED_REPO_STATUS_ARGS: readonly string[];
|