canopycms 0.0.61 → 0.0.62

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 (184) hide show
  1. package/dist/ai/json-to-markdown.js +1 -2
  2. package/dist/ai/json-to-markdown.js.map +1 -1
  3. package/dist/api/__test__/mock-client.d.ts +5 -1
  4. package/dist/api/__test__/mock-client.d.ts.map +1 -1
  5. package/dist/api/__test__/mock-client.js +9 -2
  6. package/dist/api/__test__/mock-client.js.map +1 -1
  7. package/dist/api/admin-branch-health.d.ts +36 -1
  8. package/dist/api/admin-branch-health.d.ts.map +1 -1
  9. package/dist/api/admin-branch-health.js +176 -2
  10. package/dist/api/admin-branch-health.js.map +1 -1
  11. package/dist/api/admin.d.ts +8 -1
  12. package/dist/api/admin.d.ts.map +1 -1
  13. package/dist/api/admin.js.map +1 -1
  14. package/dist/api/branch.d.ts.map +1 -1
  15. package/dist/api/branch.js +16 -2
  16. package/dist/api/branch.js.map +1 -1
  17. package/dist/api/client.d.ts +5 -1
  18. package/dist/api/client.d.ts.map +1 -1
  19. package/dist/api/client.js +6 -0
  20. package/dist/api/client.js.map +1 -1
  21. package/dist/api/comments.d.ts +2 -2
  22. package/dist/api/content.d.ts +11 -5
  23. package/dist/api/content.d.ts.map +1 -1
  24. package/dist/api/content.js +79 -6
  25. package/dist/api/content.js.map +1 -1
  26. package/dist/api/entries.d.ts +10 -0
  27. package/dist/api/entries.d.ts.map +1 -1
  28. package/dist/api/entries.js +40 -15
  29. package/dist/api/entries.js.map +1 -1
  30. package/dist/api/schema.d.ts +4 -4
  31. package/dist/api/schema.d.ts.map +1 -1
  32. package/dist/api/schema.js +13 -13
  33. package/dist/api/schema.js.map +1 -1
  34. package/dist/assets/transform.d.ts.map +1 -1
  35. package/dist/assets/transform.js +19 -6
  36. package/dist/assets/transform.js.map +1 -1
  37. package/dist/branch-health.d.ts +13 -0
  38. package/dist/branch-health.d.ts.map +1 -1
  39. package/dist/branch-health.js +23 -0
  40. package/dist/branch-health.js.map +1 -1
  41. package/dist/cli/cli.js +858 -537
  42. package/dist/cli/generate-ai-content.js +760 -455
  43. package/dist/cli/init.js +25 -7
  44. package/dist/cli/template-files/Dockerfile.cms.template +19 -1
  45. package/dist/cli/template-files/canopycms.config.ts.template +7 -0
  46. package/dist/cli/template-files/cms-stack.ts.template +7 -1
  47. package/dist/client.d.ts +1 -0
  48. package/dist/client.d.ts.map +1 -1
  49. package/dist/client.js.map +1 -1
  50. package/dist/config/schemas/field.d.ts +15 -15
  51. package/dist/config/types.d.ts +2 -2
  52. package/dist/config/types.d.ts.map +1 -1
  53. package/dist/config/types.js +0 -1
  54. package/dist/config/types.js.map +1 -1
  55. package/dist/config/validation.d.ts +9 -0
  56. package/dist/config/validation.d.ts.map +1 -1
  57. package/dist/config/validation.js +14 -0
  58. package/dist/config/validation.js.map +1 -1
  59. package/dist/content-id-index.d.ts +97 -5
  60. package/dist/content-id-index.d.ts.map +1 -1
  61. package/dist/content-id-index.js +170 -18
  62. package/dist/content-id-index.js.map +1 -1
  63. package/dist/content-store.d.ts +81 -7
  64. package/dist/content-store.d.ts.map +1 -1
  65. package/dist/content-store.js +443 -258
  66. package/dist/content-store.js.map +1 -1
  67. package/dist/editor/BranchManager.d.ts.map +1 -1
  68. package/dist/editor/BranchManager.js +18 -6
  69. package/dist/editor/BranchManager.js.map +1 -1
  70. package/dist/editor/CanopyEditor.d.ts.map +1 -1
  71. package/dist/editor/CanopyEditor.js +2 -2
  72. package/dist/editor/CanopyEditor.js.map +1 -1
  73. package/dist/editor/CanopyEditorPage.d.ts +9 -1
  74. package/dist/editor/CanopyEditorPage.d.ts.map +1 -1
  75. package/dist/editor/CanopyEditorPage.js +9 -2
  76. package/dist/editor/CanopyEditorPage.js.map +1 -1
  77. package/dist/editor/Editor.d.ts +9 -1
  78. package/dist/editor/Editor.d.ts.map +1 -1
  79. package/dist/editor/Editor.js +58 -24
  80. package/dist/editor/Editor.js.map +1 -1
  81. package/dist/editor/FormRenderer.d.ts.map +1 -1
  82. package/dist/editor/FormRenderer.js +12 -0
  83. package/dist/editor/FormRenderer.js.map +1 -1
  84. package/dist/editor/admin/SystemHealthPanel.js +6 -2
  85. package/dist/editor/admin/SystemHealthPanel.js.map +1 -1
  86. package/dist/editor/components/EntryCreateModal.d.ts +9 -1
  87. package/dist/editor/components/EntryCreateModal.d.ts.map +1 -1
  88. package/dist/editor/components/EntryCreateModal.js +4 -1
  89. package/dist/editor/components/EntryCreateModal.js.map +1 -1
  90. package/dist/editor/fields/DateTimeField.d.ts +46 -0
  91. package/dist/editor/fields/DateTimeField.d.ts.map +1 -0
  92. package/dist/editor/fields/DateTimeField.js +66 -0
  93. package/dist/editor/fields/DateTimeField.js.map +1 -0
  94. package/dist/editor/fields/NumberField.d.ts +34 -0
  95. package/dist/editor/fields/NumberField.d.ts.map +1 -0
  96. package/dist/editor/fields/NumberField.js +53 -0
  97. package/dist/editor/fields/NumberField.js.map +1 -0
  98. package/dist/editor/fields/NumberListField.d.ts +25 -0
  99. package/dist/editor/fields/NumberListField.d.ts.map +1 -0
  100. package/dist/editor/fields/NumberListField.js +53 -0
  101. package/dist/editor/fields/NumberListField.js.map +1 -0
  102. package/dist/editor/hooks/useBranchManager.d.ts.map +1 -1
  103. package/dist/editor/hooks/useBranchManager.js +115 -26
  104. package/dist/editor/hooks/useBranchManager.js.map +1 -1
  105. package/dist/editor/hooks/useDraftManager.d.ts +8 -0
  106. package/dist/editor/hooks/useDraftManager.d.ts.map +1 -1
  107. package/dist/editor/hooks/useDraftManager.js +261 -21
  108. package/dist/editor/hooks/useDraftManager.js.map +1 -1
  109. package/dist/editor/hooks/useEntryManager.d.ts +21 -0
  110. package/dist/editor/hooks/useEntryManager.d.ts.map +1 -1
  111. package/dist/editor/hooks/useEntryManager.js +25 -2
  112. package/dist/editor/hooks/useEntryManager.js.map +1 -1
  113. package/dist/editor/theme.d.ts +8 -8
  114. package/dist/git-manager.d.ts +51 -7
  115. package/dist/git-manager.d.ts.map +1 -1
  116. package/dist/git-manager.js +105 -14
  117. package/dist/git-manager.js.map +1 -1
  118. package/dist/http/handler.d.ts.map +1 -1
  119. package/dist/http/handler.js +70 -27
  120. package/dist/http/handler.js.map +1 -1
  121. package/dist/http/router.d.ts.map +1 -1
  122. package/dist/http/router.js +40 -3
  123. package/dist/http/router.js.map +1 -1
  124. package/dist/operating-mode/deployment-name-fixtures.d.ts +29 -0
  125. package/dist/operating-mode/deployment-name-fixtures.d.ts.map +1 -0
  126. package/dist/operating-mode/deployment-name-fixtures.js +55 -0
  127. package/dist/operating-mode/deployment-name-fixtures.js.map +1 -0
  128. package/dist/operating-mode/deployment-name.d.ts +9 -0
  129. package/dist/operating-mode/deployment-name.d.ts.map +1 -1
  130. package/dist/operating-mode/deployment-name.js +9 -1
  131. package/dist/operating-mode/deployment-name.js.map +1 -1
  132. package/dist/operating-mode/index.d.ts +2 -1
  133. package/dist/operating-mode/index.d.ts.map +1 -1
  134. package/dist/operating-mode/index.js +4 -1
  135. package/dist/operating-mode/index.js.map +1 -1
  136. package/dist/operating-mode/mode-env.d.ts +58 -0
  137. package/dist/operating-mode/mode-env.d.ts.map +1 -0
  138. package/dist/operating-mode/mode-env.js +97 -0
  139. package/dist/operating-mode/mode-env.js.map +1 -0
  140. package/dist/resolve-canopy-user.d.ts +34 -0
  141. package/dist/resolve-canopy-user.d.ts.map +1 -0
  142. package/dist/resolve-canopy-user.js +55 -0
  143. package/dist/resolve-canopy-user.js.map +1 -0
  144. package/dist/schema/schema-store.d.ts +53 -2
  145. package/dist/schema/schema-store.d.ts.map +1 -1
  146. package/dist/schema/schema-store.js +92 -21
  147. package/dist/schema/schema-store.js.map +1 -1
  148. package/dist/server.d.ts +9 -0
  149. package/dist/server.d.ts.map +1 -1
  150. package/dist/server.js +9 -0
  151. package/dist/server.js.map +1 -1
  152. package/dist/services.d.ts.map +1 -1
  153. package/dist/services.js +40 -6
  154. package/dist/services.js.map +1 -1
  155. package/dist/settings-workspace.d.ts +40 -0
  156. package/dist/settings-workspace.d.ts.map +1 -1
  157. package/dist/settings-workspace.js +139 -151
  158. package/dist/settings-workspace.js.map +1 -1
  159. package/dist/types.d.ts +10 -0
  160. package/dist/types.d.ts.map +1 -1
  161. package/dist/utils/content-write-lock.d.ts +127 -0
  162. package/dist/utils/content-write-lock.d.ts.map +1 -0
  163. package/dist/utils/content-write-lock.js +170 -0
  164. package/dist/utils/content-write-lock.js.map +1 -0
  165. package/dist/utils/error.d.ts +1 -1
  166. package/dist/utils/error.js +1 -1
  167. package/dist/utils/git.d.ts +16 -0
  168. package/dist/utils/git.d.ts.map +1 -1
  169. package/dist/utils/git.js +22 -0
  170. package/dist/utils/git.js.map +1 -1
  171. package/dist/utils/sanitize-href.d.ts +28 -3
  172. package/dist/utils/sanitize-href.d.ts.map +1 -1
  173. package/dist/utils/sanitize-href.js +64 -6
  174. package/dist/utils/sanitize-href.js.map +1 -1
  175. package/dist/validation/entry-link-validator.d.ts +1 -1
  176. package/dist/validation/entry-link-validator.js +3 -3
  177. package/dist/validation/entry-link-validator.js.map +1 -1
  178. package/dist/validation/entry-validator.js +1 -1
  179. package/dist/validation/entry-validator.js.map +1 -1
  180. package/dist/worker/cms-worker.d.ts +13 -0
  181. package/dist/worker/cms-worker.d.ts.map +1 -1
  182. package/dist/worker/cms-worker.js +326 -264
  183. package/dist/worker/cms-worker.js.map +1 -1
  184. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/http/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAenD;;;;;;;;GAQG;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,oBAAoB,CAAC,CAAA;AAEhG;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAA;IACnD,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1B,OAAO,EAAE,aAAa,CAAA;IAEtB,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,KACtE;QACE,EAAE,EAAE,IAAI,CAAA;QACR,MAAM,CAAC,EAAE,OAAO,CAAA;QAChB,IAAI,CAAC,EAAE,OAAO,CAAA;KACf,GACD;QACE,EAAE,EAAE,KAAK,CAAA;QACT,KAAK,EAAE,MAAM,CAAA;KACd,CAAA;IACL;;;;;OAKG;IACH,UAAU,CAAC,EAAE,WAAW,CAAA;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,aAAa,CAAA;IACtB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAE9B,QAAQ,CAAC,EAAE,eAAe,CAAC,UAAU,CAAC,CAAA;IACtC,UAAU,CAAC,EAAE,eAAe,CAAC,YAAY,CAAC,CAAA;CAC3C;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,4BAA4B;IAC5B,QAAQ,CAAC,MAAM,EAAE,eAAe,EAAE,CAAA;IAElC,mEAAmE;IACnE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,GAAG,IAAI,CAAA;CAC7D;AA0HD;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,SAAS,eAAe,EAAE,EAClC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAAE,GACjB,UAAU,GAAG,IAAI,CA0BnB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,YAAY,CAOjD"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/http/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAenD;;;;;;;;GAQG;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,oBAAoB,CAAC,CAAA;AAEhG;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAA;IACnD,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1B,OAAO,EAAE,aAAa,CAAA;IAEtB,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,KACtE;QACE,EAAE,EAAE,IAAI,CAAA;QACR,MAAM,CAAC,EAAE,OAAO,CAAA;QAChB,IAAI,CAAC,EAAE,OAAO,CAAA;KACf,GACD;QACE,EAAE,EAAE,KAAK,CAAA;QACT,KAAK,EAAE,MAAM,CAAA;KACd,CAAA;IACL;;;;;OAKG;IACH,UAAU,CAAC,EAAE,WAAW,CAAA;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,aAAa,CAAA;IACtB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAE9B,QAAQ,CAAC,EAAE,eAAe,CAAC,UAAU,CAAC,CAAA;IACtC,UAAU,CAAC,EAAE,eAAe,CAAC,YAAY,CAAC,CAAA;CAC3C;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,4BAA4B;IAC5B,QAAQ,CAAC,MAAM,EAAE,eAAe,EAAE,CAAA;IAElC,mEAAmE;IACnE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,GAAG,IAAI,CAAA;CAC7D;AA+ID;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,SAAS,eAAe,EAAE,EAClC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAAE,GACjB,UAAU,GAAG,IAAI,CA6CnB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,YAAY,CAOjD"}
@@ -47,6 +47,15 @@ function buildCanopyRoutes() {
47
47
  /**
48
48
  * Match a route pattern against actual path segments.
49
49
  * Supports :param for single-segment params and ...slug for catch-all.
50
+ *
51
+ * Params are returned RAW (undecoded) here on purpose (C5): matching is
52
+ * purely structural (segment counts, static-segment equality) and must never
53
+ * throw. Decoding happens exactly once, uniformly for :param and catch-all
54
+ * alike, in matchRoute() below - after the winning route has been picked, so
55
+ * a malformed `%` escape is handled in a single place instead of aborting
56
+ * mid-match (which previously let a URIError from a bad :param escape to
57
+ * `decodeURIComponent` bubble all the way to http/handler.ts's top-level
58
+ * catch and surface as a 500).
50
59
  */
51
60
  const matchPattern = (pattern, actual) => {
52
61
  const params = {};
@@ -63,8 +72,8 @@ const matchPattern = (pattern, actual) => {
63
72
  if (!next)
64
73
  return null;
65
74
  if (part.startsWith(':')) {
66
- // Dynamic segment - extract param
67
- params[part.slice(1)] = decodeURIComponent(next);
75
+ // Dynamic segment - extract param (still raw; see decode note above)
76
+ params[part.slice(1)] = next;
68
77
  }
69
78
  else if (part !== next) {
70
79
  // Static segment - must match exactly
@@ -76,6 +85,17 @@ const matchPattern = (pattern, actual) => {
76
85
  return null;
77
86
  return { params };
78
87
  };
88
+ /**
89
+ * Synthetic handler for a request whose matched route params contain a
90
+ * malformed `%` escape sequence (C5) - e.g. a lone `%` or `%zz`. Reported as
91
+ * a 400 (the request is malformed), never registered in the real route
92
+ * table, and only ever reachable via matchRoute()'s decode step below.
93
+ */
94
+ const malformedPathHandler = async () => ({
95
+ ok: false,
96
+ status: 400,
97
+ error: 'Malformed URL-encoded path segment',
98
+ });
79
99
  /**
80
100
  * Specificity rank of a pattern segment. Higher wins.
81
101
  * A literal ("static") segment is more specific than a `:param`, which is
@@ -149,9 +169,26 @@ export function matchRoute(routes, method, segments) {
149
169
  }
150
170
  if (!best)
151
171
  return null;
172
+ // Decode every matched param exactly once, here - uniformly for :param and
173
+ // catch-all values alike (C5). A malformed escape must produce a 400, not
174
+ // an uncaught URIError that would otherwise reach http/handler.ts's
175
+ // top-level catch and get reported as a 500. Downstream consumers
176
+ // (Zod's logicalPathSchema/branchNameSchema etc. in each route's
177
+ // `validate`, and any handler-local re-check such as entries.ts's
178
+ // parseLogicalPath call) still run their own traversal validation against
179
+ // this same final decoded value - decoding centrally here does not skip
180
+ // that, it just removes the redundant second decode that used to run
181
+ // alongside it in a few handlers.
182
+ let decodedParams;
183
+ try {
184
+ decodedParams = Object.fromEntries(Object.entries(best.params).map(([key, value]) => [key, decodeURIComponent(value)]));
185
+ }
186
+ catch {
187
+ return { handler: malformedPathHandler, params: {} };
188
+ }
152
189
  return {
153
190
  handler: best.route.handler,
154
- params: best.params,
191
+ params: decodedParams,
155
192
  validate: best.route.validate, // Include validation function if present
156
193
  bodyFormat: best.route.bodyFormat,
157
194
  };
@@ -1 +1 @@
1
- {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/http/router.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/http/router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Shared deployment-name test fixture.
3
+ *
4
+ * The rule that decides whether a `deploymentName` is usable exists TWICE, by
5
+ * necessity: once at runtime (`deployment-name.ts`'s `isValidDeploymentName`)
6
+ * and once at synth time (`canopycms-cdk`'s `constructs/cms-service.ts`).
7
+ * `canopycms-cdk` publishes without a runtime dependency on `canopycms`, so
8
+ * the construct cannot import the real thing.
9
+ *
10
+ * The dangerous drift is asymmetric: a rule TIGHTENED at runtime but not at
11
+ * synth produces a stack that synths clean and then crash-loops the Lambda at
12
+ * boot — precisely what the synth guard exists to prevent. So both packages'
13
+ * suites assert against this one list, and `canopycms-cdk`'s suite additionally
14
+ * asserts that the construct's verdict matches this package's predicate for
15
+ * every name here. Add a case here when you change either copy of the rule.
16
+ *
17
+ * Deliberately dependency-free (plain arrays, no vitest import) so the CDK
18
+ * suite can import it across the package boundary without dragging anything
19
+ * along.
20
+ */
21
+ /** Names both copies of the rule must ACCEPT. */
22
+ export declare const VALID_DEPLOYMENT_NAMES: readonly ["prod", "staging", "acme-prod_2.1", "a", "9lives", "team.prod", "PROD", "x.locked"];
23
+ /**
24
+ * Names both copies of the rule must REJECT, each with the reason it exists —
25
+ * every entry is a value git itself would refuse as a ref component, or one
26
+ * that would corrupt the worker's `.env` heredoc.
27
+ */
28
+ export declare const INVALID_DEPLOYMENT_NAMES: readonly [readonly ["a slash (would add a ref hierarchy level)", "team/prod"], readonly ["whitespace", "my prod"], readonly ["a leading dash (parses as a git option)", "-prod"], readonly ["a git-forbidden character", "prod:1"], readonly ["dot-dot", "a..b"], readonly ["a leading dot", ".prod"], readonly ["a trailing dot", "prod."], readonly ["a .lock suffix", "prod.lock"], readonly ["a tilde", "prod~1"], readonly ["a caret", "prod^1"], readonly ["a question mark", "prod?"], readonly ["an asterisk", "prod*"], readonly ["an open bracket", "prod["], readonly ["a backslash", "prod\\1"], readonly ["the empty string", ""], readonly ["a newline (would inject a line into the worker .env)", "prod\nEVIL=1"]];
29
+ //# sourceMappingURL=deployment-name-fixtures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployment-name-fixtures.d.ts","sourceRoot":"","sources":["../../src/operating-mode/deployment-name-fixtures.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,iDAAiD;AACjD,eAAO,MAAM,sBAAsB,+FASzB,CAAA;AAEV;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,osBAiB3B,CAAA"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Shared deployment-name test fixture.
3
+ *
4
+ * The rule that decides whether a `deploymentName` is usable exists TWICE, by
5
+ * necessity: once at runtime (`deployment-name.ts`'s `isValidDeploymentName`)
6
+ * and once at synth time (`canopycms-cdk`'s `constructs/cms-service.ts`).
7
+ * `canopycms-cdk` publishes without a runtime dependency on `canopycms`, so
8
+ * the construct cannot import the real thing.
9
+ *
10
+ * The dangerous drift is asymmetric: a rule TIGHTENED at runtime but not at
11
+ * synth produces a stack that synths clean and then crash-loops the Lambda at
12
+ * boot — precisely what the synth guard exists to prevent. So both packages'
13
+ * suites assert against this one list, and `canopycms-cdk`'s suite additionally
14
+ * asserts that the construct's verdict matches this package's predicate for
15
+ * every name here. Add a case here when you change either copy of the rule.
16
+ *
17
+ * Deliberately dependency-free (plain arrays, no vitest import) so the CDK
18
+ * suite can import it across the package boundary without dragging anything
19
+ * along.
20
+ */
21
+ /** Names both copies of the rule must ACCEPT. */
22
+ export const VALID_DEPLOYMENT_NAMES = [
23
+ 'prod',
24
+ 'staging',
25
+ 'acme-prod_2.1',
26
+ 'a',
27
+ '9lives',
28
+ 'team.prod',
29
+ 'PROD',
30
+ 'x.locked',
31
+ ];
32
+ /**
33
+ * Names both copies of the rule must REJECT, each with the reason it exists —
34
+ * every entry is a value git itself would refuse as a ref component, or one
35
+ * that would corrupt the worker's `.env` heredoc.
36
+ */
37
+ export const INVALID_DEPLOYMENT_NAMES = [
38
+ ['a slash (would add a ref hierarchy level)', 'team/prod'],
39
+ ['whitespace', 'my prod'],
40
+ ['a leading dash (parses as a git option)', '-prod'],
41
+ ['a git-forbidden character', 'prod:1'],
42
+ ['dot-dot', 'a..b'],
43
+ ['a leading dot', '.prod'],
44
+ ['a trailing dot', 'prod.'],
45
+ ['a .lock suffix', 'prod.lock'],
46
+ ['a tilde', 'prod~1'],
47
+ ['a caret', 'prod^1'],
48
+ ['a question mark', 'prod?'],
49
+ ['an asterisk', 'prod*'],
50
+ ['an open bracket', 'prod['],
51
+ ['a backslash', 'prod\\1'],
52
+ ['the empty string', ''],
53
+ ['a newline (would inject a line into the worker .env)', 'prod\nEVIL=1'],
54
+ ];
55
+ //# sourceMappingURL=deployment-name-fixtures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployment-name-fixtures.js","sourceRoot":"","sources":["../../src/operating-mode/deployment-name-fixtures.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,iDAAiD;AACjD,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,MAAM;IACN,SAAS;IACT,eAAe;IACf,GAAG;IACH,QAAQ;IACR,WAAW;IACX,MAAM;IACN,UAAU;CACF,CAAA;AAEV;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,CAAC,2CAA2C,EAAE,WAAW,CAAC;IAC1D,CAAC,YAAY,EAAE,SAAS,CAAC;IACzB,CAAC,yCAAyC,EAAE,OAAO,CAAC;IACpD,CAAC,2BAA2B,EAAE,QAAQ,CAAC;IACvC,CAAC,SAAS,EAAE,MAAM,CAAC;IACnB,CAAC,eAAe,EAAE,OAAO,CAAC;IAC1B,CAAC,gBAAgB,EAAE,OAAO,CAAC;IAC3B,CAAC,gBAAgB,EAAE,WAAW,CAAC;IAC/B,CAAC,SAAS,EAAE,QAAQ,CAAC;IACrB,CAAC,SAAS,EAAE,QAAQ,CAAC;IACrB,CAAC,iBAAiB,EAAE,OAAO,CAAC;IAC5B,CAAC,aAAa,EAAE,OAAO,CAAC;IACxB,CAAC,iBAAiB,EAAE,OAAO,CAAC;IAC5B,CAAC,aAAa,EAAE,SAAS,CAAC;IAC1B,CAAC,kBAAkB,EAAE,EAAE,CAAC;IACxB,CAAC,sDAAsD,EAAE,cAAc,CAAC;CAChE,CAAA"}
@@ -22,6 +22,15 @@
22
22
  * `deploymentName` prop silently doing nothing — exactly the two-stacks-one-repo
23
23
  * case this feature exists to fix.
24
24
  */
25
+ /**
26
+ * Exported so `canopycms-cdk`'s suite can assert that its own synth-time copy
27
+ * of this rule (constructs/cms-service.ts) still agrees with this one. The
28
+ * construct itself must NOT import this: `canopycms-cdk` publishes without a
29
+ * runtime dependency on `canopycms`, so a source-level import would break the
30
+ * published construct. The drift check is therefore test-only — see
31
+ * `deployment-name-fixtures.ts`.
32
+ */
33
+ export declare const isValidDeploymentName: (name: string) => boolean;
25
34
  export declare function resolveDeploymentName(config: {
26
35
  deploymentName?: string;
27
36
  }, modeDefault: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"deployment-name.d.ts","sourceRoot":"","sources":["../../src/operating-mode/deployment-name.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AA4BH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,EACnC,WAAW,EAAE,MAAM,GAClB,MAAM,CAqCR"}
1
+ {"version":3,"file":"deployment-name.d.ts","sourceRoot":"","sources":["../../src/operating-mode/deployment-name.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAsBH;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,KAAG,OAI5B,CAAA;AAEzB,wBAAgB,qBAAqB,CACnC,MAAM,EAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,EACnC,WAAW,EAAE,MAAM,GAClB,MAAM,CAqCR"}
@@ -39,7 +39,15 @@ let warned = false;
39
39
  * git's own ref rules (git-check-ref-format), so they are excluded separately.
40
40
  */
41
41
  const VALID_DEPLOYMENT_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
42
- const isValidDeploymentName = (name) => VALID_DEPLOYMENT_NAME.test(name) &&
42
+ /**
43
+ * Exported so `canopycms-cdk`'s suite can assert that its own synth-time copy
44
+ * of this rule (constructs/cms-service.ts) still agrees with this one. The
45
+ * construct itself must NOT import this: `canopycms-cdk` publishes without a
46
+ * runtime dependency on `canopycms`, so a source-level import would break the
47
+ * published construct. The drift check is therefore test-only — see
48
+ * `deployment-name-fixtures.ts`.
49
+ */
50
+ export const isValidDeploymentName = (name) => VALID_DEPLOYMENT_NAME.test(name) &&
43
51
  !name.includes('..') &&
44
52
  !name.endsWith('.') &&
45
53
  !name.endsWith('.lock');
@@ -1 +1 @@
1
- {"version":3,"file":"deployment-name.js","sourceRoot":"","sources":["../../src/operating-mode/deployment-name.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAE/C,IAAI,MAAM,GAAG,KAAK,CAAA;AAElB;;;;;;;;;;;;;GAaG;AACH,MAAM,qBAAqB,GAAG,8BAA8B,CAAA;AAE5D,MAAM,qBAAqB,GAAG,CAAC,IAAY,EAAW,EAAE,CACtD,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC;IAChC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IACpB,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;IACnB,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;AAEzB,MAAM,UAAU,qBAAqB,CACnC,MAAmC,EACnC,WAAmB;IAEnB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,EAAE,IAAI,EAAE,CAAA;IAC9D,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,CAAA;IAEzC,IAAI,QAAQ,IAAI,WAAW,IAAI,QAAQ,KAAK,WAAW,IAAI,CAAC,MAAM,EAAE,CAAC;QACnE,yEAAyE;QACzE,wEAAwE;QACxE,yEAAyE;QACzE,0EAA0E;QAC1E,+DAA+D;QAC/D,4EAA4E;QAC5E,yEAAyE;QACzE,sBAAsB;QACtB,aAAa,CACX,0CAA0C,QAAQ,wCAAwC;YACxF,KAAK,WAAW,yEAAyE;YACzF,uFAAuF;YACvF,2CAA2C,CAC9C,CAAA;QACD,MAAM,GAAG,IAAI,CAAA;IACf,CAAC;IAED,MAAM,QAAQ,GAAG,QAAQ,IAAI,WAAW,IAAI,WAAW,CAAA;IACvD,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,QAAQ;YACrB,CAAC,CAAC,2BAA2B;YAC7B,CAAC,CAAC,WAAW;gBACX,CAAC,CAAC,uBAAuB;gBACzB,CAAC,CAAC,kBAAkB,CAAA;QACxB,MAAM,IAAI,KAAK,CACb,qCAAqC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,UAAU,MAAM,KAAK;YAChF,0FAA0F;YAC1F,0FAA0F;YAC1F,uDAAuD,CAC1D,CAAA;IACH,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC"}
1
+ {"version":3,"file":"deployment-name.js","sourceRoot":"","sources":["../../src/operating-mode/deployment-name.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAE/C,IAAI,MAAM,GAAG,KAAK,CAAA;AAElB;;;;;;;;;;;;;GAaG;AACH,MAAM,qBAAqB,GAAG,8BAA8B,CAAA;AAE5D;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,IAAY,EAAW,EAAE,CAC7D,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC;IAChC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IACpB,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;IACnB,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;AAEzB,MAAM,UAAU,qBAAqB,CACnC,MAAmC,EACnC,WAAmB;IAEnB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,EAAE,IAAI,EAAE,CAAA;IAC9D,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,CAAA;IAEzC,IAAI,QAAQ,IAAI,WAAW,IAAI,QAAQ,KAAK,WAAW,IAAI,CAAC,MAAM,EAAE,CAAC;QACnE,yEAAyE;QACzE,wEAAwE;QACxE,yEAAyE;QACzE,0EAA0E;QAC1E,+DAA+D;QAC/D,4EAA4E;QAC5E,yEAAyE;QACzE,sBAAsB;QACtB,aAAa,CACX,0CAA0C,QAAQ,wCAAwC;YACxF,KAAK,WAAW,yEAAyE;YACzF,uFAAuF;YACvF,2CAA2C,CAC9C,CAAA;QACD,MAAM,GAAG,IAAI,CAAA;IACf,CAAC;IAED,MAAM,QAAQ,GAAG,QAAQ,IAAI,WAAW,IAAI,WAAW,CAAA;IACvD,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,QAAQ;YACrB,CAAC,CAAC,2BAA2B;YAC7B,CAAC,CAAC,WAAW;gBACX,CAAC,CAAC,uBAAuB;gBACzB,CAAC,CAAC,kBAAkB,CAAA;QACxB,MAAM,IAAI,KAAK,CACb,qCAAqC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,UAAU,MAAM,KAAK;YAChF,0FAA0F;YAC1F,0FAA0F;YAC1F,uDAAuD,CAC1D,CAAA;IACH,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC"}
@@ -26,7 +26,8 @@
26
26
  */
27
27
  export { clientOperatingStrategy, clearClientStrategyCache } from './client-safe-strategy';
28
28
  export { operatingStrategy, clearStrategyCache } from './client-unsafe-strategy';
29
- export { resolveDeploymentName } from './deployment-name';
29
+ export { resolveDeploymentName, isValidDeploymentName } from './deployment-name';
30
+ export { resolveOperatingMode, SERVER_MODE_ENV_VAR, BROWSER_MODE_ENV_VAR } from './mode-env';
30
31
  export type OperatingMode = 'prod' | 'dev';
31
32
  export type { ClientSafeStrategy, ClientUnsafeStrategy, ResolveRemoteUrlOptions } from './types';
32
33
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/operating-mode/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAA;AAG1F,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AAIhF,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAEzD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,KAAK,CAAA;AAG1C,YAAY,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/operating-mode/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAA;AAG1F,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AAIhF,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAIhF,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAE5F,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,KAAK,CAAA;AAG1C,YAAY,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA"}
@@ -30,5 +30,8 @@ export { clientOperatingStrategy, clearClientStrategyCache } from './client-safe
30
30
  export { operatingStrategy, clearStrategyCache } from './client-unsafe-strategy.js';
31
31
  // Single resolution point for deploymentName (env > config > mode default) —
32
32
  // server-only (reads process.env), used by the strategies' getSettingsBranchName.
33
- export { resolveDeploymentName } from './deployment-name.js';
33
+ export { resolveDeploymentName, isValidDeploymentName } from './deployment-name.js';
34
+ // Single resolution point for `mode` (env > config.mode) — isomorphic, applied
35
+ // inside validateCanopyConfig so every config-authoring path gets it.
36
+ export { resolveOperatingMode, SERVER_MODE_ENV_VAR, BROWSER_MODE_ENV_VAR } from './mode-env.js';
34
37
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/operating-mode/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,6DAA6D;AAC7D,OAAO,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAA;AAE1F,wDAAwD;AACxD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AAEhF,6EAA6E;AAC7E,kFAAkF;AAClF,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/operating-mode/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,6DAA6D;AAC7D,OAAO,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAA;AAE1F,wDAAwD;AACxD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AAEhF,6EAA6E;AAC7E,kFAAkF;AAClF,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAEhF,+EAA+E;AAC/E,sEAAsE;AACtE,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Single resolution point for the operating `mode`.
3
+ *
4
+ * `mode` is required in `canopycms.config.ts` (SEC-C1) and that file lives in
5
+ * the adopter's repo — the SAME file is loaded by `next dev` locally, by
6
+ * `next build` inside the image builder, and by the deployed Lambda. Those
7
+ * three want different answers, so a literal in the config file cannot be
8
+ * right for all of them:
9
+ *
10
+ * - `next dev` must be `dev` (workspace at `<cwd>/.canopy-dev`).
11
+ * - `next build` must be `dev` too: prod-mode build reads would try to open
12
+ * a branch workspace on EFS that cannot exist in an image builder (see
13
+ * the note in `cli/template-files/Dockerfile.cms.template`).
14
+ * - The deployed Lambda must be `prod`: dev mode resolves the workspace to
15
+ * `<cwd>/.canopy-dev`, and Lambda's filesystem is read-only outside /tmp,
16
+ * so the first write fails with EROFS.
17
+ *
18
+ * Only a value resolved at RUN time can satisfy all three, which is why this
19
+ * is an environment override rather than a flag baked into the generated
20
+ * config file. `CANOPY_MODE` is the name the deployment templates already
21
+ * referred to; before this module existed nothing read it.
22
+ *
23
+ * Precedence (highest wins):
24
+ * 1. the environment value for the current runtime (see `readModeEnv`)
25
+ * 2. `config.mode` (the literal in `canopycms.config.ts`)
26
+ *
27
+ * ## Two variable names, on purpose
28
+ *
29
+ * Server code reads `CANOPY_MODE`, which the CDK construct stamps onto the
30
+ * Lambda (`CanopyCmsService` sets `CANOPY_MODE=prod`). It is deliberately NOT
31
+ * set during `next build`, so build-time content reads stay in dev mode.
32
+ *
33
+ * Browser code cannot read a runtime environment at all — the editor page
34
+ * imports `canopycms.config.ts` directly (`config.client()`), so the browser's
35
+ * copy of `mode` is whatever was inlined when the bundle was built. Next.js
36
+ * only inlines `NEXT_PUBLIC_*`, so the browser reads
37
+ * `NEXT_PUBLIC_CANOPY_MODE`, which the generated CDK stack passes as a Docker
38
+ * build arg. Both names must be spelled as literal `process.env.X` member
39
+ * expressions here or the bundler cannot substitute them.
40
+ *
41
+ * An unrecognized value throws rather than falling back. Falling back would
42
+ * turn a typo (`CANOPY_MODE=production`) into a silent dev-mode deployment
43
+ * running header-trusting dev auth semantics — the exact failure SEC-C1 made
44
+ * `mode` required to prevent.
45
+ */
46
+ import type { OperatingMode } from './types';
47
+ export declare const SERVER_MODE_ENV_VAR = "CANOPY_MODE";
48
+ export declare const BROWSER_MODE_ENV_VAR = "NEXT_PUBLIC_CANOPY_MODE";
49
+ /** Reset the once-per-process warning latch. Test-only. */
50
+ export declare function resetModeWarning(): void;
51
+ /**
52
+ * Resolve the effective operating mode from the environment and the config
53
+ * literal. Called from `validateCanopyConfig`, the one point every documented
54
+ * config-authoring path (`defineCanopyConfig`, `composeCanopyConfig`) funnels
55
+ * through.
56
+ */
57
+ export declare function resolveOperatingMode(configMode: OperatingMode): OperatingMode;
58
+ //# sourceMappingURL=mode-env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mode-env.d.ts","sourceRoot":"","sources":["../../src/operating-mode/mode-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE5C,eAAO,MAAM,mBAAmB,gBAAgB,CAAA;AAChD,eAAO,MAAM,oBAAoB,4BAA4B,CAAA;AAI7D,2DAA2D;AAC3D,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAkBD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,aAAa,GAAG,aAAa,CA0B7E"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Single resolution point for the operating `mode`.
3
+ *
4
+ * `mode` is required in `canopycms.config.ts` (SEC-C1) and that file lives in
5
+ * the adopter's repo — the SAME file is loaded by `next dev` locally, by
6
+ * `next build` inside the image builder, and by the deployed Lambda. Those
7
+ * three want different answers, so a literal in the config file cannot be
8
+ * right for all of them:
9
+ *
10
+ * - `next dev` must be `dev` (workspace at `<cwd>/.canopy-dev`).
11
+ * - `next build` must be `dev` too: prod-mode build reads would try to open
12
+ * a branch workspace on EFS that cannot exist in an image builder (see
13
+ * the note in `cli/template-files/Dockerfile.cms.template`).
14
+ * - The deployed Lambda must be `prod`: dev mode resolves the workspace to
15
+ * `<cwd>/.canopy-dev`, and Lambda's filesystem is read-only outside /tmp,
16
+ * so the first write fails with EROFS.
17
+ *
18
+ * Only a value resolved at RUN time can satisfy all three, which is why this
19
+ * is an environment override rather than a flag baked into the generated
20
+ * config file. `CANOPY_MODE` is the name the deployment templates already
21
+ * referred to; before this module existed nothing read it.
22
+ *
23
+ * Precedence (highest wins):
24
+ * 1. the environment value for the current runtime (see `readModeEnv`)
25
+ * 2. `config.mode` (the literal in `canopycms.config.ts`)
26
+ *
27
+ * ## Two variable names, on purpose
28
+ *
29
+ * Server code reads `CANOPY_MODE`, which the CDK construct stamps onto the
30
+ * Lambda (`CanopyCmsService` sets `CANOPY_MODE=prod`). It is deliberately NOT
31
+ * set during `next build`, so build-time content reads stay in dev mode.
32
+ *
33
+ * Browser code cannot read a runtime environment at all — the editor page
34
+ * imports `canopycms.config.ts` directly (`config.client()`), so the browser's
35
+ * copy of `mode` is whatever was inlined when the bundle was built. Next.js
36
+ * only inlines `NEXT_PUBLIC_*`, so the browser reads
37
+ * `NEXT_PUBLIC_CANOPY_MODE`, which the generated CDK stack passes as a Docker
38
+ * build arg. Both names must be spelled as literal `process.env.X` member
39
+ * expressions here or the bundler cannot substitute them.
40
+ *
41
+ * An unrecognized value throws rather than falling back. Falling back would
42
+ * turn a typo (`CANOPY_MODE=production`) into a silent dev-mode deployment
43
+ * running header-trusting dev auth semantics — the exact failure SEC-C1 made
44
+ * `mode` required to prevent.
45
+ */
46
+ import { canopyLogWarn } from '../utils/logger.js';
47
+ export const SERVER_MODE_ENV_VAR = 'CANOPY_MODE';
48
+ export const BROWSER_MODE_ENV_VAR = 'NEXT_PUBLIC_CANOPY_MODE';
49
+ let warned = false;
50
+ /** Reset the once-per-process warning latch. Test-only. */
51
+ export function resetModeWarning() {
52
+ warned = false;
53
+ }
54
+ /**
55
+ * The environment value for the current runtime, or undefined when unset.
56
+ *
57
+ * Guarded with `typeof process` because a non-Next bundler may leave no
58
+ * `process` shim in the browser at all; the member expressions themselves stay
59
+ * literal so Next's DefinePlugin substitution still applies.
60
+ */
61
+ function readModeEnv() {
62
+ if (typeof process === 'undefined' || typeof process.env === 'undefined')
63
+ return undefined;
64
+ const inBrowser = typeof window !== 'undefined';
65
+ const name = inBrowser ? BROWSER_MODE_ENV_VAR : SERVER_MODE_ENV_VAR;
66
+ const raw = inBrowser ? process.env.NEXT_PUBLIC_CANOPY_MODE : process.env.CANOPY_MODE;
67
+ const value = raw?.trim();
68
+ return value ? { name, value } : undefined;
69
+ }
70
+ /**
71
+ * Resolve the effective operating mode from the environment and the config
72
+ * literal. Called from `validateCanopyConfig`, the one point every documented
73
+ * config-authoring path (`defineCanopyConfig`, `composeCanopyConfig`) funnels
74
+ * through.
75
+ */
76
+ export function resolveOperatingMode(configMode) {
77
+ const env = readModeEnv();
78
+ if (!env)
79
+ return configMode;
80
+ if (env.value !== 'prod' && env.value !== 'dev') {
81
+ throw new Error(`CanopyCMS: invalid ${env.name}=${JSON.stringify(env.value)}. ` +
82
+ `It must be exactly "prod" or "dev". Refusing to fall back to the configured mode ` +
83
+ `(${JSON.stringify(configMode)}): a typo here would silently deploy dev auth semantics.`);
84
+ }
85
+ if (env.value !== configMode && !warned) {
86
+ // canopyLogWarn, not console.warn: shared modules can run inside the
87
+ // worker daemon, where an unprefixed line is folded into the previous
88
+ // CloudWatch event (see utils/logger.ts).
89
+ canopyLogWarn(`CanopyCMS: ${env.name}="${env.value}" overrides config.mode="${configMode}". ` +
90
+ `The environment wins by design — it is the per-deployment value, while ` +
91
+ `canopycms.config.ts is shared by local dev, the image build and the deployment. ` +
92
+ `See operating-mode/mode-env.ts.`);
93
+ warned = true;
94
+ }
95
+ return env.value;
96
+ }
97
+ //# sourceMappingURL=mode-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mode-env.js","sourceRoot":"","sources":["../../src/operating-mode/mode-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAG/C,MAAM,CAAC,MAAM,mBAAmB,GAAG,aAAa,CAAA;AAChD,MAAM,CAAC,MAAM,oBAAoB,GAAG,yBAAyB,CAAA;AAE7D,IAAI,MAAM,GAAG,KAAK,CAAA;AAElB,2DAA2D;AAC3D,MAAM,UAAU,gBAAgB;IAC9B,MAAM,GAAG,KAAK,CAAA;AAChB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,WAAW;IAClB,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,WAAW;QAAE,OAAO,SAAS,CAAA;IAC1F,MAAM,SAAS,GAAG,OAAO,MAAM,KAAK,WAAW,CAAA;IAC/C,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,mBAAmB,CAAA;IACnE,MAAM,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAA;IACrF,MAAM,KAAK,GAAG,GAAG,EAAE,IAAI,EAAE,CAAA;IACzB,OAAO,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;AAC5C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,UAAyB;IAC5D,MAAM,GAAG,GAAG,WAAW,EAAE,CAAA;IACzB,IAAI,CAAC,GAAG;QAAE,OAAO,UAAU,CAAA;IAE3B,IAAI,GAAG,CAAC,KAAK,KAAK,MAAM,IAAI,GAAG,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CACb,sBAAsB,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI;YAC7D,mFAAmF;YACnF,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,0DAA0D,CAC3F,CAAA;IACH,CAAC;IAED,IAAI,GAAG,CAAC,KAAK,KAAK,UAAU,IAAI,CAAC,MAAM,EAAE,CAAC;QACxC,qEAAqE;QACrE,sEAAsE;QACtE,0CAA0C;QAC1C,aAAa,CACX,cAAc,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,KAAK,4BAA4B,UAAU,KAAK;YAC7E,yEAAyE;YACzE,kFAAkF;YAClF,iCAAiC,CACpC,CAAA;QACD,MAAM,GAAG,IAAI,CAAA;IACf,CAAC;IAED,OAAO,GAAG,CAAC,KAAK,CAAA;AAClB,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { AuthenticationResult } from './auth/types';
2
+ import type { CanopyUser } from './user';
3
+ import type { OperatingMode } from './operating-mode';
4
+ /** Test-only: reset the once-per-process "no admins configured" warning latch. */
5
+ export declare function resetResolveCanopyUserWarningForTests(): void;
6
+ export interface ResolveCanopyUserDeps {
7
+ /**
8
+ * Resolves (and ensures) the settings workspace root. Internal groups are
9
+ * the single source of truth for group-based privileges and MUST be
10
+ * loaded from here — the same root `createContentAccessChecker`
11
+ * (authorization/content.ts) uses for path permissions — never from a
12
+ * content branch clone.
13
+ *
14
+ * Must THROW if the settings workspace cannot be ensured, matching
15
+ * `createContentAccessChecker`'s fail-loud contract: a caught error here
16
+ * and a silent fallback to an empty group list would read as "no
17
+ * privileges", which is a silent authorization change, not a safe
18
+ * degradation.
19
+ */
20
+ getSettingsBranchRoot: () => Promise<string>;
21
+ mode: OperatingMode;
22
+ bootstrapAdminIds: Set<string>;
23
+ }
24
+ /**
25
+ * Resolve the CanopyUser for a request: load internal groups from the
26
+ * settings workspace and merge them (plus bootstrap admins) into an
27
+ * authentication result via `authResultToCanopyUser`.
28
+ *
29
+ * Framework-agnostic: callers supply the already-computed `authResult` (from
30
+ * whatever auth-plugin invocation their transport uses) and a small deps
31
+ * bag drawn from `CanopyServices`.
32
+ */
33
+ export declare function resolveCanopyUser(authResult: AuthenticationResult, deps: ResolveCanopyUserDeps): Promise<CanopyUser>;
34
+ //# sourceMappingURL=resolve-canopy-user.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-canopy-user.d.ts","sourceRoot":"","sources":["../src/resolve-canopy-user.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAGxC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAKrD,kFAAkF;AAClF,wBAAgB,qCAAqC,IAAI,IAAI,CAE5D;AAED,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;;;;;OAYG;IACH,qBAAqB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;IAC5C,IAAI,EAAE,aAAa,CAAA;IACnB,iBAAiB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CAC/B;AAcD;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,oBAAoB,EAChC,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,UAAU,CAAC,CAOrB"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Shared "authenticate -> resolve internal groups -> merge into CanopyUser"
3
+ * pipeline.
4
+ *
5
+ * This used to be duplicated between `http/handler.ts` (the core API
6
+ * handler) and `canopycms-next`'s `context-wrapper.ts` (Next.js SSR user
7
+ * extraction) - including a module-level `warnedNoAdmins` flag in each copy.
8
+ * The duplication let the two drift: `http/handler.ts` loaded internal
9
+ * groups from the BASE BRANCH content clone's `groups.json`, which nothing
10
+ * in the product ever writes (writes go to the settings workspace via
11
+ * `mutateGroupsFile` - `api/groups.ts`), so group-based privileges never
12
+ * actually took effect. Consolidating the pipeline here means both callers
13
+ * read from the same place and cannot silently diverge again.
14
+ *
15
+ * canopyLogWarn, not console.warn: this module has no worker-specific logic,
16
+ * but nothing prevents it from becoming reachable from the worker's runtime
17
+ * import closure later, and the existing "no admins configured" warning is
18
+ * exactly the kind of operationally interesting line that must not be
19
+ * silently folded into an unrelated worker.log event (see utils/logger.ts).
20
+ */
21
+ import { canopyLogWarn } from './utils/logger.js';
22
+ import { authResultToCanopyUser } from './user.js';
23
+ import { loadInternalGroups, RESERVED_GROUPS } from './authorization/index.js';
24
+ /** Module-level, matching the pre-extraction behavior: warn at most once per process. */
25
+ let warnedNoAdmins = false;
26
+ /** Test-only: reset the once-per-process "no admins configured" warning latch. */
27
+ export function resetResolveCanopyUserWarningForTests() {
28
+ warnedNoAdmins = false;
29
+ }
30
+ function warnIfNoAdmins(internalGroups, bootstrapAdminIds) {
31
+ if (warnedNoAdmins)
32
+ return;
33
+ const adminsGroup = internalGroups.find((g) => g.id === RESERVED_GROUPS.ADMINS);
34
+ const hasAdmins = (adminsGroup?.members.length ?? 0) > 0 || bootstrapAdminIds.size > 0;
35
+ if (!hasAdmins) {
36
+ canopyLogWarn('CanopyCMS: No admin users configured. Set CANOPY_BOOTSTRAP_ADMIN_IDS or add members to the Admins group.');
37
+ }
38
+ warnedNoAdmins = true;
39
+ }
40
+ /**
41
+ * Resolve the CanopyUser for a request: load internal groups from the
42
+ * settings workspace and merge them (plus bootstrap admins) into an
43
+ * authentication result via `authResultToCanopyUser`.
44
+ *
45
+ * Framework-agnostic: callers supply the already-computed `authResult` (from
46
+ * whatever auth-plugin invocation their transport uses) and a small deps
47
+ * bag drawn from `CanopyServices`.
48
+ */
49
+ export async function resolveCanopyUser(authResult, deps) {
50
+ const settingsRoot = await deps.getSettingsBranchRoot();
51
+ const internalGroups = await loadInternalGroups(settingsRoot, deps.mode, deps.bootstrapAdminIds);
52
+ warnIfNoAdmins(internalGroups, deps.bootstrapAdminIds);
53
+ return authResultToCanopyUser(authResult, deps.bootstrapAdminIds, internalGroups);
54
+ }
55
+ //# sourceMappingURL=resolve-canopy-user.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-canopy-user.js","sourceRoot":"","sources":["../src/resolve-canopy-user.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAG9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAsB,MAAM,iBAAiB,CAAA;AAGzF,yFAAyF;AACzF,IAAI,cAAc,GAAG,KAAK,CAAA;AAE1B,kFAAkF;AAClF,MAAM,UAAU,qCAAqC;IACnD,cAAc,GAAG,KAAK,CAAA;AACxB,CAAC;AAqBD,SAAS,cAAc,CAAC,cAA+B,EAAE,iBAA8B;IACrF,IAAI,cAAc;QAAE,OAAM;IAC1B,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,eAAe,CAAC,MAAM,CAAC,CAAA;IAC/E,MAAM,SAAS,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,iBAAiB,CAAC,IAAI,GAAG,CAAC,CAAA;IACtF,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,aAAa,CACX,0GAA0G,CAC3G,CAAA;IACH,CAAC;IACD,cAAc,GAAG,IAAI,CAAA;AACvB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,UAAgC,EAChC,IAA2B;IAE3B,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,qBAAqB,EAAE,CAAA;IACvD,MAAM,cAAc,GAAG,MAAM,kBAAkB,CAAC,YAAY,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAA;IAEhG,cAAc,CAAC,cAAc,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAA;IAEtD,OAAO,sBAAsB,CAAC,UAAU,EAAE,IAAI,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAA;AACnF,CAAC"}