canopycms 0.0.67 → 0.0.68-int.93

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 (107) hide show
  1. package/dist/ai/handler.js +8 -0
  2. package/dist/api/admin-branch-health.js +12 -7
  3. package/dist/api/admin.d.ts +8 -8
  4. package/dist/api/branch-status.js +6 -2
  5. package/dist/api/client.d.ts +12 -0
  6. package/dist/api/client.js +35 -11
  7. package/dist/api/content.d.ts +6 -5
  8. package/dist/api/content.js +38 -39
  9. package/dist/api/entries.js +6 -8
  10. package/dist/api/github-sync.d.ts +10 -1
  11. package/dist/api/github-sync.js +20 -10
  12. package/dist/api/reference-options.js +1 -1
  13. package/dist/api/request-url.d.ts +8 -0
  14. package/dist/api/request-url.js +15 -0
  15. package/dist/api/resolve-references.js +2 -2
  16. package/dist/api/settings-helpers.d.ts +1 -1
  17. package/dist/api/settings-helpers.js +1 -4
  18. package/dist/authorization/content.d.ts +5 -4
  19. package/dist/authorization/content.js +5 -5
  20. package/dist/authorization/path.d.ts +11 -6
  21. package/dist/authorization/path.js +11 -6
  22. package/dist/authorization/types.d.ts +2 -2
  23. package/dist/branch-health.js +3 -3
  24. package/dist/branch-schema-cache.d.ts +5 -3
  25. package/dist/branch-schema-cache.js +29 -11
  26. package/dist/branch-workspace.js +2 -2
  27. package/dist/cli/cli.js +285 -168
  28. package/dist/cli/generate-ai-content.js +190 -109
  29. package/dist/cli/github-app-manifest.d.ts +4 -3
  30. package/dist/cli/github-app-manifest.js +4 -3
  31. package/dist/cli/init.js +15 -10
  32. package/dist/cli/sync.js +15 -13
  33. package/dist/config/schemas/config.d.ts +6 -3
  34. package/dist/config/schemas/config.js +3 -1
  35. package/dist/config/schemas/field.js +1 -0
  36. package/dist/config/types.d.ts +11 -2
  37. package/dist/config/validation.d.ts +6 -0
  38. package/dist/config/validation.js +37 -0
  39. package/dist/content-listing.d.ts +2 -2
  40. package/dist/content-listing.js +3 -3
  41. package/dist/content-reader.js +4 -4
  42. package/dist/content-store.d.ts +2 -0
  43. package/dist/content-store.js +2 -1
  44. package/dist/content-tree.js +1 -1
  45. package/dist/context.d.ts +16 -7
  46. package/dist/context.js +116 -67
  47. package/dist/editor/Editor.js +4 -4
  48. package/dist/editor/FormRenderer.js +20 -5
  49. package/dist/editor/admin/SystemHealthPanel.js +37 -6
  50. package/dist/editor/components/NoEditPermissionNotice.d.ts +10 -0
  51. package/dist/editor/components/NoEditPermissionNotice.js +17 -0
  52. package/dist/editor/hooks/useBranchesData.js +3 -1
  53. package/dist/editor/hooks/useDraftManager.d.ts +1 -1
  54. package/dist/editor/hooks/useDraftManager.js +2 -1
  55. package/dist/editor/hooks/useEntriesData.js +2 -2
  56. package/dist/editor/hooks/useEntryManager.js +17 -11
  57. package/dist/entry-schema-registry.js +2 -1
  58. package/dist/git-manager.d.ts +20 -0
  59. package/dist/git-manager.js +50 -4
  60. package/dist/github-service.d.ts +8 -0
  61. package/dist/github-service.js +5 -1
  62. package/dist/http/handler.js +24 -9
  63. package/dist/http/index.d.ts +2 -0
  64. package/dist/http/index.js +2 -0
  65. package/dist/http/router.d.ts +2 -0
  66. package/dist/http/router.js +2 -1
  67. package/dist/http/worker-not-ready.d.ts +9 -0
  68. package/dist/http/worker-not-ready.js +17 -0
  69. package/dist/operating-mode/client-unsafe-strategy.js +0 -6
  70. package/dist/operating-mode/types.d.ts +0 -3
  71. package/dist/paths/index.d.ts +1 -1
  72. package/dist/paths/index.js +1 -1
  73. package/dist/paths/normalize.d.ts +7 -0
  74. package/dist/paths/normalize.js +9 -0
  75. package/dist/reference-resolver.d.ts +3 -3
  76. package/dist/reference-resolver.js +3 -2
  77. package/dist/resolve-canopy-user.js +2 -1
  78. package/dist/services.d.ts +12 -5
  79. package/dist/services.js +56 -56
  80. package/dist/settings-workspace.js +36 -0
  81. package/dist/static/seo.d.ts +2 -14
  82. package/dist/static/seo.js +2 -25
  83. package/dist/submission-attribution.d.ts +73 -0
  84. package/dist/submission-attribution.js +221 -0
  85. package/dist/sync-core.js +7 -8
  86. package/dist/types.d.ts +23 -2
  87. package/dist/utils/content-write-lock.d.ts +3 -7
  88. package/dist/utils/content-write-lock.js +6 -4
  89. package/dist/utils/debug.d.ts +8 -0
  90. package/dist/utils/debug.js +10 -2
  91. package/dist/utils/git.d.ts +28 -0
  92. package/dist/utils/git.js +38 -0
  93. package/dist/utils/provisioning-lock.d.ts +15 -5
  94. package/dist/utils/provisioning-lock.js +31 -11
  95. package/dist/utils/request-timing.d.ts +25 -0
  96. package/dist/utils/request-timing.js +101 -0
  97. package/dist/utils/url-prefix.d.ts +15 -0
  98. package/dist/utils/url-prefix.js +26 -0
  99. package/dist/worker/canopy-state.d.ts +45 -0
  100. package/dist/worker/canopy-state.js +75 -0
  101. package/dist/worker/git-sync.d.ts +4 -2
  102. package/dist/worker/git-sync.js +111 -24
  103. package/dist/worker/provisioned-workspace.d.ts +35 -0
  104. package/dist/worker/provisioned-workspace.js +50 -0
  105. package/dist/worker/rebase.js +75 -12
  106. package/dist/worker/task-runner.js +39 -4
  107. package/package.json +1 -1
@@ -3,10 +3,10 @@ import { simpleGit } from 'simple-git';
3
3
  import { completeTask, dequeueTask, failTask, recoverOrphanedTasks, retryTask, } from '../task-queue/cms-task-queue.js';
4
4
  import { createOrUpdatePullRequest } from '../github-service.js';
5
5
  import { BranchMetadataFileManager, getBranchMetadataFileManager } from '../branch-metadata.js';
6
- import { sanitizeBranchName } from '../paths/branch-name.js';
6
+ import { sanitizeBranchName, RESERVED_SETTINGS_BRANCH_PREFIX } from '../paths/branch-name.js';
7
7
  import { gitNetworkChildEnv } from '../git-manager.js';
8
8
  import { getErrorMessage, redactCredentials } from '../utils/error.js';
9
- import { isNonFastForwardRejection, isStaleLeaseRejection } from '../utils/git.js';
9
+ import { isNonFastForwardRejection, isStaleLeaseRejection, workflowPushRefusalFile, } from '../utils/git.js';
10
10
  import { clearHistoryRewrittenMarker, readPublishedSha } from './history-rewrite.js';
11
11
  import { writeWorkerStatus } from '../task-queue/worker-status.js';
12
12
  import { workerLog, workerLogError } from './log.js';
@@ -90,6 +90,15 @@ function isRateLimitSignal403(err) {
90
90
  return false;
91
91
  }
92
92
  // Payload validation helpers — fail fast with clear errors instead of silent `as` casts
93
+ /**
94
+ * Whether `branch` carries the reserved settings-branch prefix. Matching on the prefix
95
+ * alone, never on a configured name, is what keeps a content branch out: branch creation
96
+ * rejects the prefix, while a configured name the worker and API disagree on could be a
97
+ * content branch's.
98
+ */
99
+ function isSettingsBranch(branch) {
100
+ return branch.startsWith(RESERVED_SETTINGS_BRANCH_PREFIX);
101
+ }
93
102
  function requireString(payload, key) {
94
103
  const val = payload[key];
95
104
  if (typeof val !== 'string')
@@ -282,6 +291,13 @@ export async function executeTask(ctx, task, signal) {
282
291
  if (sanitizeBranchName(branch) === ctx.sanitizedBaseBranch) {
283
292
  throw new PermanentTaskError(`Refusing to push-and-create-or-update-pr for "${branch}": it is the base branch -- submitting the base branch is never valid`);
284
293
  }
294
+ // The settings branch is an orphan with no history in common with the
295
+ // base, so GitHub 422s a PR for it: push it and stop.
296
+ if (isSettingsBranch(branch)) {
297
+ await ctx.pushBranchToGitHub(branch);
298
+ workerLog(`Pushed settings branch ${branch}; settings branches never get a PR`);
299
+ return { pushed: true };
300
+ }
285
301
  await ctx.pushBranchToGitHub(branch);
286
302
  const result = await createOrUpdatePullRequest({
287
303
  octokit: ctx.octokit(),
@@ -291,9 +307,9 @@ export async function executeTask(ctx, task, signal) {
291
307
  base,
292
308
  title: optionalString(payload, 'title', `Submit ${branch}`),
293
309
  body: optionalString(payload, 'body', ''),
294
- // Content submits (api/github-sync.ts) set this; settings-branch
295
- // syncs (services.ts) deliberately don't.
310
+ // Content submits (api/github-sync.ts) set both.
296
311
  markReadyIfDraft: payload.markReadyIfDraft === true,
312
+ mergeSectionIntoBody: payload.mergeSectionIntoBody === true,
297
313
  signal,
298
314
  });
299
315
  workerLog(result.created
@@ -415,6 +431,23 @@ async function updateBranchMetadataOnFailure(ctx, task, error) {
415
431
  workerLogError(`Failed to update failure metadata for ${branch}:`, err instanceof Error ? err.message : err);
416
432
  }
417
433
  }
434
+ /**
435
+ * Fail fast when GitHub refused the push for adding workflow content it does not already hold: the
436
+ * worker's credential deliberately lacks the workflows permission, so the identical push can never
437
+ * succeed. Rebasing onto a base that changed a workflow does not trigger it; a workflow edit made
438
+ * outside the editor, auto-merged by the rebase with a base change to the same file, does.
439
+ */
440
+ function throwIfWorkflowRefusal(branch, message) {
441
+ const file = workflowPushRefusalFile(message);
442
+ if (file === null)
443
+ return;
444
+ throw new PermanentTaskError(`Push refused for branch "${branch}": it would put a version of ${file} on GitHub that ` +
445
+ `GitHub does not already have, and this deployment's GitHub credential is deliberately not ` +
446
+ `allowed to change workflow files. Such a change usually comes from outside the editor, ` +
447
+ `such as a direct push to this branch. Nothing was pushed, and ` +
448
+ `retrying will not help until a developer with permission to change workflow files ` +
449
+ `resolves it on GitHub.`);
450
+ }
418
451
  export async function pushBranchToGitHub(ctx, branch) {
419
452
  const git = simpleGit({
420
453
  baseDir: ctx.remoteGitPath,
@@ -473,6 +506,7 @@ export async function pushBranchToGitHub(ctx, branch) {
473
506
  }
474
507
  catch (err) {
475
508
  const message = getErrorMessage(err);
509
+ throwIfWorkflowRefusal(branch, message);
476
510
  // A refused lease means GitHub is not at the commit we rewrote, so the
477
511
  // marker is stale -- routine, not exceptional: tasks are re-run after a
478
512
  // crash (recoverOrphanedTasks) and the marker survives any failure to
@@ -494,6 +528,7 @@ export async function pushBranchToGitHub(ctx, branch) {
494
528
  }
495
529
  catch (retryErr) {
496
530
  const retryMessage = getErrorMessage(retryErr);
531
+ throwIfWorkflowRefusal(branch, retryMessage);
497
532
  if (isNonFastForwardRejection(retryMessage)) {
498
533
  throw new PermanentTaskError(`Push rejected for branch "${branch}": GitHub's tip is neither the commit this ` +
499
534
  `deployment last published nor an ancestor of what it is pushing, so the branch ` +
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "//": "@codemirror/language, @lezer/highlight: workaround — @mdxeditor/editor uses cm6-theme-basic-light which peer-requires these but mdxeditor doesn't declare them as dependencies",
3
3
  "name": "canopycms",
4
- "version": "0.0.67",
4
+ "version": "0.0.68-int.93",
5
5
  "description": "CanopyCMS core package: schema-driven content, branch-aware editing, and editor UI for Next.js.",
6
6
  "license": "MIT",
7
7
  "repository": {