@kywi-software/core 0.14.0 → 0.15.1

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 (633) hide show
  1. package/AGENT-PATTERNS.md +200 -17
  2. package/README.md +38 -12
  3. package/dist/admin/audience-editor.d.ts +2 -0
  4. package/dist/admin/audience-editor.d.ts.map +1 -1
  5. package/dist/admin/audience-editor.js +4 -2
  6. package/dist/admin/audience-editor.js.map +1 -1
  7. package/dist/admin/chrome.d.ts.map +1 -1
  8. package/dist/admin/chrome.js +6 -7
  9. package/dist/admin/chrome.js.map +1 -1
  10. package/dist/admin/condition-builder.d.ts.map +1 -1
  11. package/dist/admin/condition-builder.js +16 -3
  12. package/dist/admin/condition-builder.js.map +1 -1
  13. package/dist/admin/field-components.d.ts.map +1 -1
  14. package/dist/admin/field-components.js +27 -1
  15. package/dist/admin/field-components.js.map +1 -1
  16. package/dist/admin/form-helpers.d.ts.map +1 -1
  17. package/dist/admin/form-helpers.js +6 -1
  18. package/dist/admin/form-helpers.js.map +1 -1
  19. package/dist/admin/layout-editor/chrome-env.d.ts +35 -0
  20. package/dist/admin/layout-editor/chrome-env.d.ts.map +1 -0
  21. package/dist/admin/layout-editor/chrome-env.js +13 -0
  22. package/dist/admin/layout-editor/chrome-env.js.map +1 -0
  23. package/dist/admin/layout-editor/component-actions.d.ts +58 -7
  24. package/dist/admin/layout-editor/component-actions.d.ts.map +1 -1
  25. package/dist/admin/layout-editor/component-actions.js +131 -5
  26. package/dist/admin/layout-editor/component-actions.js.map +1 -1
  27. package/dist/admin/layout-editor/component-fork.d.ts +4 -4
  28. package/dist/admin/layout-editor/component-fork.d.ts.map +1 -1
  29. package/dist/admin/layout-editor/component-fork.js +76 -10
  30. package/dist/admin/layout-editor/component-fork.js.map +1 -1
  31. package/dist/admin/layout-editor/component-picker-field.d.ts +17 -3
  32. package/dist/admin/layout-editor/component-picker-field.d.ts.map +1 -1
  33. package/dist/admin/layout-editor/component-picker-field.js +5 -2
  34. package/dist/admin/layout-editor/component-picker-field.js.map +1 -1
  35. package/dist/admin/layout-editor/drag-feedback.d.ts +25 -1
  36. package/dist/admin/layout-editor/drag-feedback.d.ts.map +1 -1
  37. package/dist/admin/layout-editor/drag-feedback.js +9 -0
  38. package/dist/admin/layout-editor/drag-feedback.js.map +1 -1
  39. package/dist/admin/layout-editor/drag-utils.d.ts +103 -5
  40. package/dist/admin/layout-editor/drag-utils.d.ts.map +1 -1
  41. package/dist/admin/layout-editor/drag-utils.js +131 -4
  42. package/dist/admin/layout-editor/drag-utils.js.map +1 -1
  43. package/dist/admin/layout-editor/editor-canvas.d.ts +11 -0
  44. package/dist/admin/layout-editor/editor-canvas.d.ts.map +1 -1
  45. package/dist/admin/layout-editor/editor-canvas.js +134 -20
  46. package/dist/admin/layout-editor/editor-canvas.js.map +1 -1
  47. package/dist/admin/layout-editor/editor-dialog.d.ts +58 -3
  48. package/dist/admin/layout-editor/editor-dialog.d.ts.map +1 -1
  49. package/dist/admin/layout-editor/editor-dialog.js +71 -9
  50. package/dist/admin/layout-editor/editor-dialog.js.map +1 -1
  51. package/dist/admin/layout-editor/editor-state.d.ts +119 -0
  52. package/dist/admin/layout-editor/editor-state.d.ts.map +1 -1
  53. package/dist/admin/layout-editor/editor-state.js +188 -6
  54. package/dist/admin/layout-editor/editor-state.js.map +1 -1
  55. package/dist/admin/layout-editor/editor-toolbar.d.ts +10 -1
  56. package/dist/admin/layout-editor/editor-toolbar.d.ts.map +1 -1
  57. package/dist/admin/layout-editor/editor-toolbar.js +2 -2
  58. package/dist/admin/layout-editor/editor-toolbar.js.map +1 -1
  59. package/dist/admin/layout-editor/editor.css +216 -8
  60. package/dist/admin/layout-editor/inline-text.d.ts +15 -1
  61. package/dist/admin/layout-editor/inline-text.d.ts.map +1 -1
  62. package/dist/admin/layout-editor/inline-text.js +30 -2
  63. package/dist/admin/layout-editor/inline-text.js.map +1 -1
  64. package/dist/admin/layout-editor/layout-editor.d.ts +21 -16
  65. package/dist/admin/layout-editor/layout-editor.d.ts.map +1 -1
  66. package/dist/admin/layout-editor/layout-editor.js +40 -17
  67. package/dist/admin/layout-editor/layout-editor.js.map +1 -1
  68. package/dist/admin/layout-editor/linked-component-notes.d.ts +88 -0
  69. package/dist/admin/layout-editor/linked-component-notes.d.ts.map +1 -0
  70. package/dist/admin/layout-editor/linked-component-notes.js +88 -0
  71. package/dist/admin/layout-editor/linked-component-notes.js.map +1 -0
  72. package/dist/admin/layout-editor/module-overlay.d.ts +23 -4
  73. package/dist/admin/layout-editor/module-overlay.d.ts.map +1 -1
  74. package/dist/admin/layout-editor/module-overlay.js +56 -10
  75. package/dist/admin/layout-editor/module-overlay.js.map +1 -1
  76. package/dist/admin/layout-editor/module-variant-container-config.d.ts.map +1 -1
  77. package/dist/admin/layout-editor/module-variant-container-config.js +9 -2
  78. package/dist/admin/layout-editor/module-variant-container-config.js.map +1 -1
  79. package/dist/admin/layout-editor/module-variant-container-panel.d.ts +75 -0
  80. package/dist/admin/layout-editor/module-variant-container-panel.d.ts.map +1 -0
  81. package/dist/admin/layout-editor/module-variant-container-panel.js +29 -0
  82. package/dist/admin/layout-editor/module-variant-container-panel.js.map +1 -0
  83. package/dist/admin/layout-editor/node-lookup.d.ts.map +1 -1
  84. package/dist/admin/layout-editor/node-lookup.js +33 -3
  85. package/dist/admin/layout-editor/node-lookup.js.map +1 -1
  86. package/dist/admin/layout-editor/overlay-shell.d.ts.map +1 -1
  87. package/dist/admin/layout-editor/overlay-shell.js +19 -4
  88. package/dist/admin/layout-editor/overlay-shell.js.map +1 -1
  89. package/dist/admin/layout-editor/props-panel.d.ts +28 -11
  90. package/dist/admin/layout-editor/props-panel.d.ts.map +1 -1
  91. package/dist/admin/layout-editor/props-panel.js +75 -125
  92. package/dist/admin/layout-editor/props-panel.js.map +1 -1
  93. package/dist/admin/layout-editor/section-variant-container-config.d.ts.map +1 -1
  94. package/dist/admin/layout-editor/section-variant-container-config.js +11 -2
  95. package/dist/admin/layout-editor/section-variant-container-config.js.map +1 -1
  96. package/dist/admin/layout-editor/use-chrome-flip.d.ts +99 -11
  97. package/dist/admin/layout-editor/use-chrome-flip.d.ts.map +1 -1
  98. package/dist/admin/layout-editor/use-chrome-flip.js +268 -97
  99. package/dist/admin/layout-editor/use-chrome-flip.js.map +1 -1
  100. package/dist/admin/layout-editor/use-component-connect.d.ts +13 -0
  101. package/dist/admin/layout-editor/use-component-connect.d.ts.map +1 -1
  102. package/dist/admin/layout-editor/use-component-connect.js +116 -20
  103. package/dist/admin/layout-editor/use-component-connect.js.map +1 -1
  104. package/dist/admin/layout-editor/use-component-fork.d.ts +49 -19
  105. package/dist/admin/layout-editor/use-component-fork.d.ts.map +1 -1
  106. package/dist/admin/layout-editor/use-component-fork.js +28 -19
  107. package/dist/admin/layout-editor/use-component-fork.js.map +1 -1
  108. package/dist/admin/layout-editor/use-component-library.d.ts +4 -4
  109. package/dist/admin/layout-editor/use-component-library.d.ts.map +1 -1
  110. package/dist/admin/layout-editor/use-component-library.js +1 -1
  111. package/dist/admin/layout-editor/use-component-library.js.map +1 -1
  112. package/dist/admin/layout-editor/use-editor-dnd.d.ts +10 -0
  113. package/dist/admin/layout-editor/use-editor-dnd.d.ts.map +1 -1
  114. package/dist/admin/layout-editor/use-editor-dnd.js +234 -14
  115. package/dist/admin/layout-editor/use-editor-dnd.js.map +1 -1
  116. package/dist/admin/layout-editor/variant-container-config.d.ts.map +1 -1
  117. package/dist/admin/layout-editor/variant-container-config.js +1 -1
  118. package/dist/admin/layout-editor/variant-container-config.js.map +1 -1
  119. package/dist/admin/layout-editor/variant-editor.d.ts +16 -15
  120. package/dist/admin/layout-editor/variant-editor.d.ts.map +1 -1
  121. package/dist/admin/layout-editor/variant-editor.js +16 -5
  122. package/dist/admin/layout-editor/variant-editor.js.map +1 -1
  123. package/dist/admin/primitives.d.ts.map +1 -1
  124. package/dist/admin/primitives.js +1 -1
  125. package/dist/admin/primitives.js.map +1 -1
  126. package/dist/admin/registry.d.ts +12 -0
  127. package/dist/admin/registry.d.ts.map +1 -1
  128. package/dist/admin/registry.js +12 -0
  129. package/dist/admin/registry.js.map +1 -1
  130. package/dist/admin/rule-tester.d.ts +1 -0
  131. package/dist/admin/rule-tester.d.ts.map +1 -1
  132. package/dist/admin/rule-tester.js +7 -4
  133. package/dist/admin/rule-tester.js.map +1 -1
  134. package/dist/admin/server.d.ts +10 -1
  135. package/dist/admin/server.d.ts.map +1 -1
  136. package/dist/admin/server.js +4 -1
  137. package/dist/admin/server.js.map +1 -1
  138. package/dist/admin/signal-options.d.ts +17 -0
  139. package/dist/admin/signal-options.d.ts.map +1 -1
  140. package/dist/admin/signal-options.js +28 -0
  141. package/dist/admin/signal-options.js.map +1 -1
  142. package/dist/admin/site-switcher.d.ts +16 -3
  143. package/dist/admin/site-switcher.d.ts.map +1 -1
  144. package/dist/admin/site-switcher.js +18 -3
  145. package/dist/admin/site-switcher.js.map +1 -1
  146. package/dist/admin/styles/admin.css +0 -3
  147. package/dist/admin/surface-matcher.d.ts +6 -2
  148. package/dist/admin/surface-matcher.d.ts.map +1 -1
  149. package/dist/admin/surface-matcher.js +42 -5
  150. package/dist/admin/surface-matcher.js.map +1 -1
  151. package/dist/admin/surfaces/audiences/audiences-data.d.ts +5 -0
  152. package/dist/admin/surfaces/audiences/audiences-data.d.ts.map +1 -1
  153. package/dist/admin/surfaces/audiences/audiences-data.js +3 -0
  154. package/dist/admin/surfaces/audiences/audiences-data.js.map +1 -1
  155. package/dist/admin/surfaces/components/components-data.d.ts +31 -11
  156. package/dist/admin/surfaces/components/components-data.d.ts.map +1 -1
  157. package/dist/admin/surfaces/components/components-data.js +17 -4
  158. package/dist/admin/surfaces/components/components-data.js.map +1 -1
  159. package/dist/admin/surfaces/components/components-list.d.ts.map +1 -1
  160. package/dist/admin/surfaces/components/components-list.js +20 -7
  161. package/dist/admin/surfaces/components/components-list.js.map +1 -1
  162. package/dist/admin/surfaces/components/definition-canvas.d.ts +11 -3
  163. package/dist/admin/surfaces/components/definition-canvas.d.ts.map +1 -1
  164. package/dist/admin/surfaces/components/definition-canvas.js +138 -17
  165. package/dist/admin/surfaces/components/definition-canvas.js.map +1 -1
  166. package/dist/admin/surfaces/dashboard/dashboard-index.d.ts.map +1 -1
  167. package/dist/admin/surfaces/dashboard/dashboard-index.js +2 -2
  168. package/dist/admin/surfaces/dashboard/dashboard-index.js.map +1 -1
  169. package/dist/admin/surfaces/layouts/layout-editor-client.d.ts.map +1 -1
  170. package/dist/admin/surfaces/layouts/layout-editor-client.js +12 -11
  171. package/dist/admin/surfaces/layouts/layout-editor-client.js.map +1 -1
  172. package/dist/admin/surfaces/menus/menu-editor.d.ts.map +1 -1
  173. package/dist/admin/surfaces/menus/menu-editor.js +17 -4
  174. package/dist/admin/surfaces/menus/menu-editor.js.map +1 -1
  175. package/dist/admin/surfaces/menus/menu-tree.d.ts +18 -4
  176. package/dist/admin/surfaces/menus/menu-tree.d.ts.map +1 -1
  177. package/dist/admin/surfaces/menus/menu-tree.js +18 -3
  178. package/dist/admin/surfaces/menus/menu-tree.js.map +1 -1
  179. package/dist/admin/surfaces/menus/menus-data.d.ts +18 -0
  180. package/dist/admin/surfaces/menus/menus-data.d.ts.map +1 -1
  181. package/dist/admin/surfaces/menus/menus-data.js +4 -0
  182. package/dist/admin/surfaces/menus/menus-data.js.map +1 -1
  183. package/dist/admin/surfaces/menus/menus-list.d.ts.map +1 -1
  184. package/dist/admin/surfaces/menus/menus-list.js +2 -12
  185. package/dist/admin/surfaces/menus/menus-list.js.map +1 -1
  186. package/dist/admin/surfaces/users/users-data.d.ts +14 -0
  187. package/dist/admin/surfaces/users/users-data.d.ts.map +1 -1
  188. package/dist/admin/surfaces/users/users-data.js +19 -0
  189. package/dist/admin/surfaces/users/users-data.js.map +1 -1
  190. package/dist/admin/surfaces/users/users-detail.d.ts.map +1 -1
  191. package/dist/admin/surfaces/users/users-detail.js +40 -4
  192. package/dist/admin/surfaces/users/users-detail.js.map +1 -1
  193. package/dist/admin/surfaces/users/users-new.d.ts.map +1 -1
  194. package/dist/admin/surfaces/users/users-new.js +8 -5
  195. package/dist/admin/surfaces/users/users-new.js.map +1 -1
  196. package/dist/admin/user-form.d.ts +10 -1
  197. package/dist/admin/user-form.d.ts.map +1 -1
  198. package/dist/admin/user-form.js +2 -2
  199. package/dist/admin/user-form.js.map +1 -1
  200. package/dist/api/admin-features-routes.js +2 -2
  201. package/dist/api/admin-features-routes.js.map +1 -1
  202. package/dist/api/api-key-routes.js +2 -2
  203. package/dist/api/api-key-routes.js.map +1 -1
  204. package/dist/api/audience-preview-routes.d.ts +7 -0
  205. package/dist/api/audience-preview-routes.d.ts.map +1 -1
  206. package/dist/api/audience-preview-routes.js +4 -4
  207. package/dist/api/audience-preview-routes.js.map +1 -1
  208. package/dist/api/audience-routes.d.ts +7 -0
  209. package/dist/api/audience-routes.d.ts.map +1 -1
  210. package/dist/api/audience-routes.js +31 -19
  211. package/dist/api/audience-routes.js.map +1 -1
  212. package/dist/api/audience-runtime-routes.d.ts +23 -0
  213. package/dist/api/audience-runtime-routes.d.ts.map +1 -1
  214. package/dist/api/audience-runtime-routes.js +511 -25
  215. package/dist/api/audience-runtime-routes.js.map +1 -1
  216. package/dist/api/auth-routes.d.ts.map +1 -1
  217. package/dist/api/auth-routes.js +10 -4
  218. package/dist/api/auth-routes.js.map +1 -1
  219. package/dist/api/auth.d.ts +1 -0
  220. package/dist/api/auth.d.ts.map +1 -1
  221. package/dist/api/auth.js +43 -3
  222. package/dist/api/auth.js.map +1 -1
  223. package/dist/api/ax-routes.d.ts.map +1 -1
  224. package/dist/api/ax-routes.js +7 -3
  225. package/dist/api/ax-routes.js.map +1 -1
  226. package/dist/api/bulk-routes.d.ts.map +1 -1
  227. package/dist/api/bulk-routes.js +7 -7
  228. package/dist/api/bulk-routes.js.map +1 -1
  229. package/dist/api/category-routes.js +6 -6
  230. package/dist/api/category-routes.js.map +1 -1
  231. package/dist/api/changeset-routes.js +2 -2
  232. package/dist/api/changeset-routes.js.map +1 -1
  233. package/dist/api/comment-routes.js +12 -12
  234. package/dist/api/comment-routes.js.map +1 -1
  235. package/dist/api/component-routes.d.ts +25 -0
  236. package/dist/api/component-routes.d.ts.map +1 -1
  237. package/dist/api/component-routes.js +44 -19
  238. package/dist/api/component-routes.js.map +1 -1
  239. package/dist/api/config-routes.js +4 -4
  240. package/dist/api/config-routes.js.map +1 -1
  241. package/dist/api/content-permission-routes.js +2 -2
  242. package/dist/api/content-permission-routes.js.map +1 -1
  243. package/dist/api/content-routes.d.ts.map +1 -1
  244. package/dist/api/content-routes.js +21 -16
  245. package/dist/api/content-routes.js.map +1 -1
  246. package/dist/api/content-type-routes.js +3 -3
  247. package/dist/api/content-type-routes.js.map +1 -1
  248. package/dist/api/dashboard-routes.js +1 -1
  249. package/dist/api/dashboard-routes.js.map +1 -1
  250. package/dist/api/experiment-routes.d.ts +7 -0
  251. package/dist/api/experiment-routes.d.ts.map +1 -1
  252. package/dist/api/experiment-routes.js +10 -10
  253. package/dist/api/experiment-routes.js.map +1 -1
  254. package/dist/api/experiment-runtime-routes.d.ts +6 -0
  255. package/dist/api/experiment-runtime-routes.d.ts.map +1 -1
  256. package/dist/api/experiment-runtime-routes.js +47 -11
  257. package/dist/api/experiment-runtime-routes.js.map +1 -1
  258. package/dist/api/extension-routes.js +4 -4
  259. package/dist/api/extension-routes.js.map +1 -1
  260. package/dist/api/feed-routes.d.ts +2 -2
  261. package/dist/api/feed-routes.js +5 -5
  262. package/dist/api/feed-routes.js.map +1 -1
  263. package/dist/api/form-routes.js +6 -6
  264. package/dist/api/form-routes.js.map +1 -1
  265. package/dist/api/graphql/resolvers.d.ts +1 -1
  266. package/dist/api/graphql/resolvers.d.ts.map +1 -1
  267. package/dist/api/graphql/resolvers.js +68 -33
  268. package/dist/api/graphql/resolvers.js.map +1 -1
  269. package/dist/api/group-routes.js +9 -9
  270. package/dist/api/group-routes.js.map +1 -1
  271. package/dist/api/index.d.ts +1 -0
  272. package/dist/api/index.d.ts.map +1 -1
  273. package/dist/api/index.js +43 -7
  274. package/dist/api/index.js.map +1 -1
  275. package/dist/api/layout-routes.d.ts +19 -1
  276. package/dist/api/layout-routes.d.ts.map +1 -1
  277. package/dist/api/layout-routes.js +92 -8
  278. package/dist/api/layout-routes.js.map +1 -1
  279. package/dist/api/layout-write-guard.d.ts +3 -2
  280. package/dist/api/layout-write-guard.d.ts.map +1 -1
  281. package/dist/api/layout-write-guard.js +12 -4
  282. package/dist/api/layout-write-guard.js.map +1 -1
  283. package/dist/api/media-routes.d.ts.map +1 -1
  284. package/dist/api/media-routes.js +100 -35
  285. package/dist/api/media-routes.js.map +1 -1
  286. package/dist/api/menu-routes.d.ts +9 -1
  287. package/dist/api/menu-routes.d.ts.map +1 -1
  288. package/dist/api/menu-routes.js +46 -12
  289. package/dist/api/menu-routes.js.map +1 -1
  290. package/dist/api/nav-routes.d.ts +6 -0
  291. package/dist/api/nav-routes.d.ts.map +1 -1
  292. package/dist/api/nav-routes.js +25 -4
  293. package/dist/api/nav-routes.js.map +1 -1
  294. package/dist/api/oauth-routes.js +2 -2
  295. package/dist/api/oauth-routes.js.map +1 -1
  296. package/dist/api/openapi.d.ts.map +1 -1
  297. package/dist/api/openapi.js +82 -34
  298. package/dist/api/openapi.js.map +1 -1
  299. package/dist/api/pagination.d.ts +10 -0
  300. package/dist/api/pagination.d.ts.map +1 -1
  301. package/dist/api/pagination.js +7 -1
  302. package/dist/api/pagination.js.map +1 -1
  303. package/dist/api/response.d.ts +29 -0
  304. package/dist/api/response.d.ts.map +1 -1
  305. package/dist/api/response.js +23 -3
  306. package/dist/api/response.js.map +1 -1
  307. package/dist/api/search-routes.d.ts.map +1 -1
  308. package/dist/api/search-routes.js +19 -5
  309. package/dist/api/search-routes.js.map +1 -1
  310. package/dist/api/section-template-routes.d.ts.map +1 -1
  311. package/dist/api/section-template-routes.js +37 -20
  312. package/dist/api/section-template-routes.js.map +1 -1
  313. package/dist/api/site-admin-routes.d.ts +10 -1
  314. package/dist/api/site-admin-routes.d.ts.map +1 -1
  315. package/dist/api/site-admin-routes.js +21 -1
  316. package/dist/api/site-admin-routes.js.map +1 -1
  317. package/dist/api/site-context.d.ts +35 -5
  318. package/dist/api/site-context.d.ts.map +1 -1
  319. package/dist/api/site-context.js +21 -6
  320. package/dist/api/site-context.js.map +1 -1
  321. package/dist/api/site-routes.js +2 -2
  322. package/dist/api/site-routes.js.map +1 -1
  323. package/dist/api/tag-routes.d.ts.map +1 -1
  324. package/dist/api/tag-routes.js +5 -5
  325. package/dist/api/tag-routes.js.map +1 -1
  326. package/dist/api/translation-routes.js +5 -5
  327. package/dist/api/translation-routes.js.map +1 -1
  328. package/dist/api/user-routes.d.ts.map +1 -1
  329. package/dist/api/user-routes.js +136 -21
  330. package/dist/api/user-routes.js.map +1 -1
  331. package/dist/api/version-routes.js +2 -2
  332. package/dist/api/version-routes.js.map +1 -1
  333. package/dist/api/webhook-routes.js +8 -8
  334. package/dist/api/webhook-routes.js.map +1 -1
  335. package/dist/api/workflow-routes.d.ts.map +1 -1
  336. package/dist/api/workflow-routes.js +23 -14
  337. package/dist/api/workflow-routes.js.map +1 -1
  338. package/dist/audiences/collectors/identity.d.ts +14 -1
  339. package/dist/audiences/collectors/identity.d.ts.map +1 -1
  340. package/dist/audiences/collectors/identity.js +16 -3
  341. package/dist/audiences/collectors/identity.js.map +1 -1
  342. package/dist/audiences/collectors/index.d.ts +16 -2
  343. package/dist/audiences/collectors/index.d.ts.map +1 -1
  344. package/dist/audiences/collectors/index.js +29 -5
  345. package/dist/audiences/collectors/index.js.map +1 -1
  346. package/dist/audiences/collectors/pinned-audience.d.ts +28 -2
  347. package/dist/audiences/collectors/pinned-audience.d.ts.map +1 -1
  348. package/dist/audiences/collectors/pinned-audience.js +35 -5
  349. package/dist/audiences/collectors/pinned-audience.js.map +1 -1
  350. package/dist/audiences/collectors/selfid.d.ts +25 -0
  351. package/dist/audiences/collectors/selfid.d.ts.map +1 -0
  352. package/dist/audiences/collectors/selfid.js +46 -0
  353. package/dist/audiences/collectors/selfid.js.map +1 -0
  354. package/dist/audiences/collectors/session.d.ts +41 -0
  355. package/dist/audiences/collectors/session.d.ts.map +1 -0
  356. package/dist/audiences/collectors/session.js +50 -0
  357. package/dist/audiences/collectors/session.js.map +1 -0
  358. package/dist/audiences/collectors/utm.d.ts +15 -1
  359. package/dist/audiences/collectors/utm.d.ts.map +1 -1
  360. package/dist/audiences/collectors/utm.js +16 -2
  361. package/dist/audiences/collectors/utm.js.map +1 -1
  362. package/dist/audiences/consent-config.d.ts +21 -0
  363. package/dist/audiences/consent-config.d.ts.map +1 -0
  364. package/dist/audiences/consent-config.js +15 -0
  365. package/dist/audiences/consent-config.js.map +1 -0
  366. package/dist/audiences/consent-startup.d.ts +39 -0
  367. package/dist/audiences/consent-startup.d.ts.map +1 -0
  368. package/dist/audiences/consent-startup.js +105 -0
  369. package/dist/audiences/consent-startup.js.map +1 -0
  370. package/dist/audiences/consent.d.ts +205 -0
  371. package/dist/audiences/consent.d.ts.map +1 -0
  372. package/dist/audiences/consent.js +335 -0
  373. package/dist/audiences/consent.js.map +1 -0
  374. package/dist/audiences/cookies.d.ts +21 -0
  375. package/dist/audiences/cookies.d.ts.map +1 -1
  376. package/dist/audiences/cookies.js +26 -0
  377. package/dist/audiences/cookies.js.map +1 -1
  378. package/dist/audiences/engine.d.ts +7 -0
  379. package/dist/audiences/engine.d.ts.map +1 -1
  380. package/dist/audiences/engine.js +7 -2
  381. package/dist/audiences/engine.js.map +1 -1
  382. package/dist/audiences/entry-page.d.ts +89 -0
  383. package/dist/audiences/entry-page.d.ts.map +1 -0
  384. package/dist/audiences/entry-page.js +116 -0
  385. package/dist/audiences/entry-page.js.map +1 -0
  386. package/dist/audiences/evaluator/instant-match.d.ts.map +1 -1
  387. package/dist/audiences/evaluator/instant-match.js +7 -0
  388. package/dist/audiences/evaluator/instant-match.js.map +1 -1
  389. package/dist/audiences/index.d.ts +6 -2
  390. package/dist/audiences/index.d.ts.map +1 -1
  391. package/dist/audiences/index.js +12 -2
  392. package/dist/audiences/index.js.map +1 -1
  393. package/dist/audiences/queries.d.ts +16 -0
  394. package/dist/audiences/queries.d.ts.map +1 -1
  395. package/dist/audiences/queries.js +28 -1
  396. package/dist/audiences/queries.js.map +1 -1
  397. package/dist/audiences/schema.d.ts +17 -0
  398. package/dist/audiences/schema.d.ts.map +1 -1
  399. package/dist/audiences/schema.js +7 -0
  400. package/dist/audiences/schema.js.map +1 -1
  401. package/dist/audiences/server-eval.d.ts +32 -1
  402. package/dist/audiences/server-eval.d.ts.map +1 -1
  403. package/dist/audiences/server-eval.js +35 -3
  404. package/dist/audiences/server-eval.js.map +1 -1
  405. package/dist/audiences/ssr.d.ts +18 -1
  406. package/dist/audiences/ssr.d.ts.map +1 -1
  407. package/dist/audiences/ssr.js +18 -1
  408. package/dist/audiences/ssr.js.map +1 -1
  409. package/dist/audiences/types.d.ts +22 -1
  410. package/dist/audiences/types.d.ts.map +1 -1
  411. package/dist/audiences/types.js +1 -0
  412. package/dist/audiences/types.js.map +1 -1
  413. package/dist/audiences/utm-persistence.d.ts +20 -7
  414. package/dist/audiences/utm-persistence.d.ts.map +1 -1
  415. package/dist/audiences/utm-persistence.js +20 -7
  416. package/dist/audiences/utm-persistence.js.map +1 -1
  417. package/dist/auth/roles.d.ts +11 -0
  418. package/dist/auth/roles.d.ts.map +1 -1
  419. package/dist/auth/roles.js +13 -0
  420. package/dist/auth/roles.js.map +1 -1
  421. package/dist/auth/tokens.d.ts +7 -0
  422. package/dist/auth/tokens.d.ts.map +1 -1
  423. package/dist/auth/tokens.js +24 -2
  424. package/dist/auth/tokens.js.map +1 -1
  425. package/dist/ax/content-source.d.ts +10 -2
  426. package/dist/ax/content-source.d.ts.map +1 -1
  427. package/dist/ax/content-source.js +81 -5
  428. package/dist/ax/content-source.js.map +1 -1
  429. package/dist/ax/effective-body.d.ts +28 -0
  430. package/dist/ax/effective-body.d.ts.map +1 -0
  431. package/dist/ax/effective-body.js +47 -0
  432. package/dist/ax/effective-body.js.map +1 -0
  433. package/dist/ax/index.d.ts +3 -1
  434. package/dist/ax/index.d.ts.map +1 -1
  435. package/dist/ax/index.js +2 -0
  436. package/dist/ax/index.js.map +1 -1
  437. package/dist/ax/jsonld.d.ts +31 -1
  438. package/dist/ax/jsonld.d.ts.map +1 -1
  439. package/dist/ax/jsonld.js +35 -22
  440. package/dist/ax/jsonld.js.map +1 -1
  441. package/dist/ax/layout-to-html.d.ts +127 -0
  442. package/dist/ax/layout-to-html.d.ts.map +1 -0
  443. package/dist/ax/layout-to-html.js +545 -0
  444. package/dist/ax/layout-to-html.js.map +1 -0
  445. package/dist/ax/llms-full-txt.d.ts +3 -1
  446. package/dist/ax/llms-full-txt.d.ts.map +1 -1
  447. package/dist/ax/llms-full-txt.js +5 -2
  448. package/dist/ax/llms-full-txt.js.map +1 -1
  449. package/dist/ax/page-markdown.d.ts +10 -2
  450. package/dist/ax/page-markdown.d.ts.map +1 -1
  451. package/dist/ax/page-markdown.js +16 -3
  452. package/dist/ax/page-markdown.js.map +1 -1
  453. package/dist/ax/summary.d.ts +4 -0
  454. package/dist/ax/summary.d.ts.map +1 -1
  455. package/dist/ax/summary.js +6 -1
  456. package/dist/ax/summary.js.map +1 -1
  457. package/dist/ax/types.d.ts +24 -0
  458. package/dist/ax/types.d.ts.map +1 -1
  459. package/dist/cache/content-invalidation.d.ts.map +1 -1
  460. package/dist/cache/content-invalidation.js +11 -0
  461. package/dist/cache/content-invalidation.js.map +1 -1
  462. package/dist/config/types.d.ts +43 -0
  463. package/dist/config/types.d.ts.map +1 -1
  464. package/dist/config/types.js.map +1 -1
  465. package/dist/config/validate.d.ts.map +1 -1
  466. package/dist/config/validate.js +3 -0
  467. package/dist/config/validate.js.map +1 -1
  468. package/dist/db/apply-snapshot.d.ts +25 -0
  469. package/dist/db/apply-snapshot.d.ts.map +1 -1
  470. package/dist/db/apply-snapshot.js +48 -16
  471. package/dist/db/apply-snapshot.js.map +1 -1
  472. package/dist/db/ax-queries.d.ts +6 -0
  473. package/dist/db/ax-queries.d.ts.map +1 -1
  474. package/dist/db/ax-queries.js +6 -0
  475. package/dist/db/ax-queries.js.map +1 -1
  476. package/dist/db/component-instance-queries.d.ts +79 -19
  477. package/dist/db/component-instance-queries.d.ts.map +1 -1
  478. package/dist/db/component-instance-queries.js +266 -83
  479. package/dist/db/component-instance-queries.js.map +1 -1
  480. package/dist/db/component-queries.d.ts +1 -16
  481. package/dist/db/component-queries.d.ts.map +1 -1
  482. package/dist/db/component-queries.js +7 -56
  483. package/dist/db/component-queries.js.map +1 -1
  484. package/dist/db/content-queries.d.ts.map +1 -1
  485. package/dist/db/content-queries.js +9 -2
  486. package/dist/db/content-queries.js.map +1 -1
  487. package/dist/db/extension-queries.d.ts +2 -2
  488. package/dist/db/feed-queries.d.ts +3 -3
  489. package/dist/db/index.d.ts +1 -0
  490. package/dist/db/index.d.ts.map +1 -1
  491. package/dist/db/index.js +1 -0
  492. package/dist/db/index.js.map +1 -1
  493. package/dist/db/layout-queries.d.ts +21 -3
  494. package/dist/db/layout-queries.d.ts.map +1 -1
  495. package/dist/db/layout-queries.js +14 -6
  496. package/dist/db/layout-queries.js.map +1 -1
  497. package/dist/db/menu-queries.d.ts +69 -5
  498. package/dist/db/menu-queries.d.ts.map +1 -1
  499. package/dist/db/menu-queries.js +120 -13
  500. package/dist/db/menu-queries.js.map +1 -1
  501. package/dist/db/search-queries.d.ts.map +1 -1
  502. package/dist/db/search-queries.js +24 -1
  503. package/dist/db/search-queries.js.map +1 -1
  504. package/dist/db/section-template-queries.d.ts +62 -0
  505. package/dist/db/section-template-queries.d.ts.map +1 -0
  506. package/dist/db/section-template-queries.js +178 -0
  507. package/dist/db/section-template-queries.js.map +1 -0
  508. package/dist/db/site-plugin-queries.d.ts +2 -2
  509. package/dist/db/tree-queries.d.ts.map +1 -1
  510. package/dist/db/tree-queries.js +5 -0
  511. package/dist/db/tree-queries.js.map +1 -1
  512. package/dist/db/webhook-queries.d.ts +3 -3
  513. package/dist/db/workflow-queries.d.ts.map +1 -1
  514. package/dist/db/workflow-queries.js +5 -20
  515. package/dist/db/workflow-queries.js.map +1 -1
  516. package/dist/experiments/runtime.d.ts +21 -3
  517. package/dist/experiments/runtime.d.ts.map +1 -1
  518. package/dist/experiments/runtime.js +21 -3
  519. package/dist/experiments/runtime.js.map +1 -1
  520. package/dist/hooks/ax-invalidation.d.ts.map +1 -1
  521. package/dist/hooks/ax-invalidation.js +4 -0
  522. package/dist/hooks/ax-invalidation.js.map +1 -1
  523. package/dist/layout/component-refs.d.ts +90 -2
  524. package/dist/layout/component-refs.d.ts.map +1 -1
  525. package/dist/layout/component-refs.js +293 -16
  526. package/dist/layout/component-refs.js.map +1 -1
  527. package/dist/layout/index.d.ts +7 -4
  528. package/dist/layout/index.d.ts.map +1 -1
  529. package/dist/layout/index.js +6 -3
  530. package/dist/layout/index.js.map +1 -1
  531. package/dist/layout/legacy-variant-container.d.ts +123 -0
  532. package/dist/layout/legacy-variant-container.d.ts.map +1 -0
  533. package/dist/layout/legacy-variant-container.js +397 -0
  534. package/dist/layout/legacy-variant-container.js.map +1 -0
  535. package/dist/layout/module-permissions.d.ts.map +1 -1
  536. package/dist/layout/module-permissions.js +26 -38
  537. package/dist/layout/module-permissions.js.map +1 -1
  538. package/dist/layout/modules-extended.d.ts +28 -1
  539. package/dist/layout/modules-extended.d.ts.map +1 -1
  540. package/dist/layout/modules-extended.js +73 -1
  541. package/dist/layout/modules-extended.js.map +1 -1
  542. package/dist/layout/modules.d.ts.map +1 -1
  543. package/dist/layout/modules.js +9 -1
  544. package/dist/layout/modules.js.map +1 -1
  545. package/dist/layout/personalization.d.ts +83 -0
  546. package/dist/layout/personalization.d.ts.map +1 -1
  547. package/dist/layout/personalization.js +250 -4
  548. package/dist/layout/personalization.js.map +1 -1
  549. package/dist/layout/registry.d.ts.map +1 -1
  550. package/dist/layout/registry.js +20 -0
  551. package/dist/layout/registry.js.map +1 -1
  552. package/dist/layout/renderer.d.ts +29 -2
  553. package/dist/layout/renderer.d.ts.map +1 -1
  554. package/dist/layout/renderer.js +23 -6
  555. package/dist/layout/renderer.js.map +1 -1
  556. package/dist/layout/seed-defaults.d.ts +45 -0
  557. package/dist/layout/seed-defaults.d.ts.map +1 -0
  558. package/dist/layout/seed-defaults.js +75 -0
  559. package/dist/layout/seed-defaults.js.map +1 -0
  560. package/dist/layout/types.d.ts +17 -0
  561. package/dist/layout/types.d.ts.map +1 -1
  562. package/dist/layout/types.js +7 -0
  563. package/dist/layout/types.js.map +1 -1
  564. package/dist/layout/walk.d.ts +14 -0
  565. package/dist/layout/walk.d.ts.map +1 -0
  566. package/dist/layout/walk.js +49 -0
  567. package/dist/layout/walk.js.map +1 -0
  568. package/dist/media/index.d.ts +1 -1
  569. package/dist/media/index.d.ts.map +1 -1
  570. package/dist/media/index.js +1 -1
  571. package/dist/media/index.js.map +1 -1
  572. package/dist/media/inline-risk.d.ts +26 -0
  573. package/dist/media/inline-risk.d.ts.map +1 -0
  574. package/dist/media/inline-risk.js +142 -0
  575. package/dist/media/inline-risk.js.map +1 -0
  576. package/dist/media/upload-allowlist.d.ts +23 -0
  577. package/dist/media/upload-allowlist.d.ts.map +1 -1
  578. package/dist/media/upload-allowlist.js +29 -0
  579. package/dist/media/upload-allowlist.js.map +1 -1
  580. package/dist/nav/builder.d.ts.map +1 -1
  581. package/dist/nav/builder.js +15 -3
  582. package/dist/nav/builder.js.map +1 -1
  583. package/dist/nav/index.d.ts +1 -1
  584. package/dist/nav/index.d.ts.map +1 -1
  585. package/dist/nav/index.js +1 -1
  586. package/dist/nav/index.js.map +1 -1
  587. package/dist/nav/menu-resolver.d.ts +11 -0
  588. package/dist/nav/menu-resolver.d.ts.map +1 -1
  589. package/dist/nav/menu-resolver.js +49 -9
  590. package/dist/nav/menu-resolver.js.map +1 -1
  591. package/dist/nav/paths.d.ts +37 -0
  592. package/dist/nav/paths.d.ts.map +1 -0
  593. package/dist/nav/paths.js +48 -0
  594. package/dist/nav/paths.js.map +1 -0
  595. package/dist/nav/types.d.ts +6 -0
  596. package/dist/nav/types.d.ts.map +1 -1
  597. package/dist/nav/url-resolver.d.ts +1 -5
  598. package/dist/nav/url-resolver.d.ts.map +1 -1
  599. package/dist/nav/url-resolver.js +6 -12
  600. package/dist/nav/url-resolver.js.map +1 -1
  601. package/dist/schema/base.d.ts +24 -4
  602. package/dist/schema/base.d.ts.map +1 -1
  603. package/dist/schema/base.js +17 -4
  604. package/dist/schema/base.js.map +1 -1
  605. package/dist/schema/components.d.ts +90 -9
  606. package/dist/schema/components.d.ts.map +1 -1
  607. package/dist/schema/components.js +113 -22
  608. package/dist/schema/components.js.map +1 -1
  609. package/dist/schema/mysql-tables.d.ts +5775 -48
  610. package/dist/schema/mysql-tables.d.ts.map +1 -1
  611. package/dist/schema/mysql-tables.js +622 -46
  612. package/dist/schema/mysql-tables.js.map +1 -1
  613. package/dist/scope/jsonld.d.ts +18 -3
  614. package/dist/scope/jsonld.d.ts.map +1 -1
  615. package/dist/scope/jsonld.js +6 -4
  616. package/dist/scope/jsonld.js.map +1 -1
  617. package/dist/scope/kywi-form.d.ts +11 -0
  618. package/dist/scope/kywi-form.d.ts.map +1 -1
  619. package/dist/scope/kywi-form.js +11 -1
  620. package/dist/scope/kywi-form.js.map +1 -1
  621. package/dist/scope/kywi-wizard-form.d.ts.map +1 -1
  622. package/dist/scope/kywi-wizard-form.js +76 -2
  623. package/dist/scope/kywi-wizard-form.js.map +1 -1
  624. package/dist/scope/sticky-offset.d.ts +34 -13
  625. package/dist/scope/sticky-offset.d.ts.map +1 -1
  626. package/dist/scope/sticky-offset.js +236 -43
  627. package/dist/scope/sticky-offset.js.map +1 -1
  628. package/dist/site/styles.css +61 -15
  629. package/dist/versioning/scheduler.d.ts +28 -0
  630. package/dist/versioning/scheduler.d.ts.map +1 -1
  631. package/dist/versioning/scheduler.js +50 -3
  632. package/dist/versioning/scheduler.js.map +1 -1
  633. package/package.json +12 -2
@@ -1,5 +1,7 @@
1
1
  import { getActiveAudiences } from './queries.js';
2
2
  import { createAudienceEngine } from './engine.js';
3
+ import { buildSetCookieHeader, COOKIE_MAX_AGE, COOKIE_NAMES } from './cookies.js';
4
+ import { entryPageCookieValue } from './entry-page.js';
3
5
  /**
4
6
  * Server-side audience evaluation for a public request.
5
7
  *
@@ -11,13 +13,43 @@ import { createAudienceEngine } from './engine.js';
11
13
  *
12
14
  * This is the single server seam the public rendering path calls, so audience
13
15
  * evaluation happens exactly once per page render.
16
+ *
17
+ * `opts.requireConsent` is `theme.personalization.requireConsent` (kywi-cms#91),
18
+ * and it MUST be passed by any host whose theme might set it — omitted, the gate
19
+ * defaults on, which is right for a site relying on Kywi's own banner and wrong
20
+ * for one that turned the gate off. This seam used to drop the flag entirely, so
21
+ * an external-CMP site had its server collectors ignoring `kywi_utm`,
22
+ * `kywi_visitor`, `kywi_known` and `kywi_audience` while the middleware and the
23
+ * runtime routes read them: personalization that worked on the client and
24
+ * reverted on the next server render. `kywi_optout` is `essential` and is
25
+ * unaffected either way — turning the consent gate off never turns off a
26
+ * visitor's suppression preference.
14
27
  */
15
- export async function evaluateActiveAudiences(db, siteId, request) {
28
+ export async function evaluateActiveAudiences(db, siteId, request, opts = {}) {
16
29
  const audiences = await getActiveAudiences(db, siteId);
17
- const result = await createAudienceEngine({ audiences }).evaluate({ request });
30
+ // Built conditionally: under `exactOptionalPropertyTypes` an explicit
31
+ // `undefined` is not the same as an absent key.
32
+ const engineConfig = opts.requireConsent === undefined
33
+ ? { audiences }
34
+ : { audiences, requireConsent: opts.requireConsent };
35
+ const result = await createAudienceEngine(engineConfig).evaluate({ request });
18
36
  const winningAudience = result.winningAudienceId
19
37
  ? (audiences.find((a) => a.id === result.winningAudienceId) ?? null)
20
38
  : null;
21
- return { result, audiences, winningAudience };
39
+ // The entry page is recorded on the first request of the session only — and
40
+ // only for a consenting visitor, since `kywi_entry` is a `personalization`
41
+ // cookie (kywi-cms#91/#196). `entryPageCookieValue` applies both rules.
42
+ const entryValue = entryPageCookieValue(request.url, {
43
+ ...opts,
44
+ cookieHeader: request.headers.get('cookie'),
45
+ // Only a document request may name the entry page — a subresource that
46
+ // happens to come first would poison it (kywi-cms#196, review item 6).
47
+ secFetchDest: request.headers.get('sec-fetch-dest'),
48
+ accept: request.headers.get('accept'),
49
+ });
50
+ const setCookieHeaders = entryValue
51
+ ? [buildSetCookieHeader(COOKIE_NAMES.ENTRY, entryValue, COOKIE_MAX_AGE.ENTRY, { httpOnly: false })]
52
+ : [];
53
+ return { result, audiences, winningAudience, setCookieHeaders };
22
54
  }
23
55
  //# sourceMappingURL=server-eval.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"server-eval.js","sourceRoot":"","sources":["../../src/audiences/server-eval.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAiBlD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,EAAU,EACV,MAAc,EACd,OAAgB;IAEhB,MAAM,SAAS,GAAG,MAAM,kBAAkB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;IACtD,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC,CAAA;IAC9E,MAAM,eAAe,GAAG,MAAM,CAAC,iBAAiB;QAC9C,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,iBAAiB,CAAC,IAAI,IAAI,CAAC;QACpE,CAAC,CAAC,IAAI,CAAA;IACR,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,CAAA;AAC/C,CAAC"}
1
+ {"version":3,"file":"server-eval.js","sourceRoot":"","sources":["../../src/audiences/server-eval.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAElD,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAoCtD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,EAAU,EACV,MAAc,EACd,OAAgB,EAChB,OAA2B,EAAE;IAE7B,MAAM,SAAS,GAAG,MAAM,kBAAkB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;IACtD,sEAAsE;IACtE,gDAAgD;IAChD,MAAM,YAAY,GAChB,IAAI,CAAC,cAAc,KAAK,SAAS;QAC/B,CAAC,CAAC,EAAE,SAAS,EAAE;QACf,CAAC,CAAC,EAAE,SAAS,EAAE,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,CAAA;IACxD,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC,CAAA;IAC7E,MAAM,eAAe,GAAG,MAAM,CAAC,iBAAiB;QAC9C,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,iBAAiB,CAAC,IAAI,IAAI,CAAC;QACpE,CAAC,CAAC,IAAI,CAAA;IACR,4EAA4E;IAC5E,2EAA2E;IAC3E,wEAAwE;IACxE,MAAM,UAAU,GAAG,oBAAoB,CAAC,OAAO,CAAC,GAAG,EAAE;QACnD,GAAG,IAAI;QACP,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC3C,uEAAuE;QACvE,uEAAuE;QACvE,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;QACnD,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;KACtC,CAAC,CAAA;IACF,MAAM,gBAAgB,GAAG,UAAU;QACjC,CAAC,CAAC,CAAC,oBAAoB,CAAC,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,cAAc,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;QACnG,CAAC,CAAC,EAAE,CAAA;IACN,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,gBAAgB,EAAE,CAAA;AACjE,CAAC"}
@@ -1,4 +1,21 @@
1
+ import { type ConsentGateOptions } from './consent.js';
1
2
  import type { VisitorSignals } from './types.js';
2
3
  export declare function readSignalsFromRequest(cookieHeader: string | null, secret: string): Promise<VisitorSignals | null>;
3
- export declare function writeSignalsToResponse(signals: VisitorSignals, secret: string): Promise<string>;
4
+ /**
5
+ * Build the `Set-Cookie` header that persists this request's resolved signals,
6
+ * or `null` when the visitor has not consented to personalization.
7
+ *
8
+ * `kywi_signals` is a `personalization` cookie (`audiences/consent.ts` owns the
9
+ * category map), so the caller must hand over the request's `Cookie` header for
10
+ * the gate to read the decision from — kywi-cms#91. Omitting it fails closed,
11
+ * as does an undecided visitor: nothing breaks, the request still resolves its
12
+ * audiences and renders, the resolution simply is not carried to the next one,
13
+ * so the visitor keeps getting the default content until they accept.
14
+ *
15
+ * Pass `requireConsent: false` (from `theme.personalization.requireConsent`) to
16
+ * turn the gate off for a site whose consent lives in external tooling.
17
+ */
18
+ export declare function writeSignalsToResponse(signals: VisitorSignals, secret: string, options?: {
19
+ cookieHeader?: string | null;
20
+ } & ConsentGateOptions): Promise<string | null>;
4
21
  //# sourceMappingURL=ssr.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ssr.d.ts","sourceRoot":"","sources":["../../src/audiences/ssr.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD,wBAAsB,sBAAsB,CAC1C,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAOhC;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAGjB"}
1
+ {"version":3,"file":"ssr.d.ts","sourceRoot":"","sources":["../../src/audiences/ssr.ts"],"names":[],"mappings":"AACA,OAAO,EAAyB,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAC7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD,wBAAsB,sBAAsB,CAC1C,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAOhC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,kBAAuB,GAClE,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIxB"}
@@ -1,4 +1,5 @@
1
1
  import { signSignals, verifySignals, parseCookies, buildSetCookieHeader, COOKIE_NAMES, COOKIE_MAX_AGE } from './cookies.js';
2
+ import { cookieAllowedByHeader } from './consent.js';
2
3
  export async function readSignalsFromRequest(cookieHeader, secret) {
3
4
  if (!cookieHeader)
4
5
  return null;
@@ -9,7 +10,23 @@ export async function readSignalsFromRequest(cookieHeader, secret) {
9
10
  const payload = await verifySignals(token, secret);
10
11
  return payload;
11
12
  }
12
- export async function writeSignalsToResponse(signals, secret) {
13
+ /**
14
+ * Build the `Set-Cookie` header that persists this request's resolved signals,
15
+ * or `null` when the visitor has not consented to personalization.
16
+ *
17
+ * `kywi_signals` is a `personalization` cookie (`audiences/consent.ts` owns the
18
+ * category map), so the caller must hand over the request's `Cookie` header for
19
+ * the gate to read the decision from — kywi-cms#91. Omitting it fails closed,
20
+ * as does an undecided visitor: nothing breaks, the request still resolves its
21
+ * audiences and renders, the resolution simply is not carried to the next one,
22
+ * so the visitor keeps getting the default content until they accept.
23
+ *
24
+ * Pass `requireConsent: false` (from `theme.personalization.requireConsent`) to
25
+ * turn the gate off for a site whose consent lives in external tooling.
26
+ */
27
+ export async function writeSignalsToResponse(signals, secret, options = {}) {
28
+ if (!cookieAllowedByHeader(COOKIE_NAMES.SIGNALS, options.cookieHeader, options))
29
+ return null;
13
30
  const token = await signSignals(signals, secret);
14
31
  return buildSetCookieHeader(COOKIE_NAMES.SIGNALS, token, COOKIE_MAX_AGE.SIGNALS);
15
32
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ssr.js","sourceRoot":"","sources":["../../src/audiences/ssr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAG3H,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,YAA2B,EAC3B,MAAc;IAEd,IAAI,CAAC,YAAY;QAAE,OAAO,IAAI,CAAA;IAC9B,MAAM,OAAO,GAAG,YAAY,CAAC,YAAY,CAAC,CAAA;IAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;IAC/C,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IACvB,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IAClD,OAAO,OAAgC,CAAA;AACzC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,OAAuB,EACvB,MAAc;IAEd,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IAChD,OAAO,oBAAoB,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,CAAA;AAClF,CAAC"}
1
+ {"version":3,"file":"ssr.js","sourceRoot":"","sources":["../../src/audiences/ssr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC3H,OAAO,EAAE,qBAAqB,EAA2B,MAAM,cAAc,CAAA;AAG7E,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,YAA2B,EAC3B,MAAc;IAEd,IAAI,CAAC,YAAY;QAAE,OAAO,IAAI,CAAA;IAC9B,MAAM,OAAO,GAAG,YAAY,CAAC,YAAY,CAAC,CAAA;IAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;IAC/C,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IACvB,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IAClD,OAAO,OAAgC,CAAA;AACzC,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,OAAuB,EACvB,MAAc,EACd,UAAiE,EAAE;IAEnE,IAAI,CAAC,qBAAqB,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC;QAAE,OAAO,IAAI,CAAA;IAC5F,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IAChD,OAAO,oBAAoB,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,CAAA;AAClF,CAAC"}
@@ -22,6 +22,14 @@ export interface VisitorSignals {
22
22
  categoryScores: Record<string, number>;
23
23
  totalScore: number;
24
24
  };
25
+ /**
26
+ * Every query parameter on the request being served, as the `query.<param>`
27
+ * signal family (kywi-cms#196). Not stored and never gated — like the URL's
28
+ * own `utm_*` params these are the content of this request, so a campaign link
29
+ * (`/developers?from=marketer`) is a one-line rule that fires on the very
30
+ * request that carries it.
31
+ */
32
+ query: Record<string, string>;
25
33
  selfId: Record<string, string>;
26
34
  identity: {
27
35
  visitorId: string;
@@ -56,6 +64,19 @@ export interface Audience {
56
64
  status: AudienceStatus;
57
65
  conditionGroups: ConditionGroup[];
58
66
  scoreThreshold: number | null;
67
+ /**
68
+ * The audience's NAME may be listed to the public by
69
+ * `GET /api/v1/kywi/audiences`, so a page can offer the visitor a choice
70
+ * ("What brings you here?") without an admin token (kywi-cms#200). Off by
71
+ * default — an audience is an internal segment definition until someone
72
+ * deliberately publishes its name.
73
+ *
74
+ * Optional because this shape is also parsed from payloads written before the
75
+ * column existed (an audience list serialized into a page, a fixture); absent
76
+ * reads as false everywhere, and the public listing filters in SQL rather than
77
+ * trusting this field.
78
+ */
79
+ public?: boolean;
59
80
  createdAt: Date;
60
81
  updatedAt: Date;
61
82
  }
@@ -74,7 +95,7 @@ export interface InstantMatchCondition {
74
95
  operator: InstantOperator;
75
96
  value: string | string[];
76
97
  }
77
- export type InstantSignalRef = 'utm.source' | 'utm.medium' | 'utm.campaign' | 'utm.term' | 'utm.content' | 'referrer.domain' | 'referrer.sourceType' | `selfId.${string}` | `adapter.${string}` | 'identity.isKnown' | 'session.entryPage' | 'session.pagesVisited';
98
+ export type InstantSignalRef = 'utm.source' | 'utm.medium' | 'utm.campaign' | 'utm.term' | 'utm.content' | 'referrer.domain' | 'referrer.sourceType' | `selfId.${string}` | `adapter.${string}` | 'identity.isKnown' | 'session.entryPage' | 'session.pagesVisited' | `query.${string}`;
78
99
  export type InstantOperator = 'equals' | 'not_equals' | 'contains' | 'starts_with' | 'matches_glob' | 'is_one_of' | 'is_true' | 'is_false' | 'gte' | 'lte';
79
100
  export interface ScoreContributionCondition {
80
101
  type: 'score';
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/audiences/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/audiences/types.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@ export function createEmptySignals() {
6
6
  referrer: { raw: null, domain: null, sourceType: 'direct' },
7
7
  session: { pageViewCount: 0, totalPageViews: 0, sessionDuration: 0, entryPage: '/', pagesVisited: [] },
8
8
  behavioral: { categoryScores: {}, totalScore: 0 },
9
+ query: {},
9
10
  selfId: {},
10
11
  identity: { visitorId: '', isKnown: false, maLeadId: null },
11
12
  adapters: {},
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/audiences/types.ts"],"names":[],"mappings":"AAAA,gFAAgF;AA0KhF,gFAAgF;AAEhF,MAAM,UAAU,kBAAkB;IAChC,OAAO;QACL,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE;QAC9E,QAAQ,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE;QAC3D,OAAO,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,YAAY,EAAE,EAAE,EAAE;QACtG,UAAU,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE;QACjD,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE;QAC3D,QAAQ,EAAE,EAAE;QACZ,IAAI,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,iBAAiB,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE;KAC7F,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/audiences/types.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAgMhF,gFAAgF;AAEhF,MAAM,UAAU,kBAAkB;IAChC,OAAO;QACL,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE;QAC9E,QAAQ,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE;QAC3D,OAAO,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,YAAY,EAAE,EAAE,EAAE;QACtG,UAAU,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE;QACjD,KAAK,EAAE,EAAE;QACT,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE;QAC3D,QAAQ,EAAE,EAAE;QACZ,IAAI,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,iBAAiB,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE;KAC7F,CAAA;AACH,CAAC"}
@@ -20,13 +20,14 @@
20
20
  * leaves any existing cookie untouched — ordinary navigation never clobbers a
21
21
  * persisted campaign.
22
22
  *
23
- * EDGE-SAFE LEAF MODULE: this file has NO imports (and therefore no transitive
24
- * DB dependency), because it is imported from Next.js edge middleware — where
25
- * core's DB-backed code (drizzle/postgres) cannot run. Keep it dependency-free.
26
- * It is published as its own export entry (`@kywi-software/core/audiences/
27
- * utm-persistence`) so importing it never drags in the DB-backed `audiences`
28
- * barrel.
23
+ * EDGE-SAFE LEAF MODULE: this file's only import is `./consent.js`, which is
24
+ * itself a zero-import leaf, because it is imported from Next.js edge
25
+ * middleware — where core's DB-backed code (drizzle/postgres) cannot run. Keep
26
+ * it dependency-free beyond that. It is published as its own export entry
27
+ * (`@kywi-software/core/audiences/utm-persistence`) so importing it never drags
28
+ * in the DB-backed `audiences` barrel.
29
29
  */
30
+ import { type ConsentGateOptions } from './consent.js';
30
31
  /**
31
32
  * Cookie name `collectUtm` reads (mirrors `COOKIE_NAMES.UTM` in
32
33
  * `audiences/cookies.ts`). Kept as a literal here so this leaf module imports
@@ -41,6 +42,18 @@ export declare const UTM_COOKIE = "kywi_utm";
41
42
  * The JSON shape mirrors what `collectUtm` parses: `{ source, medium, campaign,
42
43
  * term, content }` with only the present keys. Empty `utm_*` values are treated
43
44
  * as absent, and a malformed URL yields `null`.
45
+ *
46
+ * Also `null` when the visitor has not consented to personalization
47
+ * (kywi-cms#91): `kywi_utm` is a `personalization` cookie in the category map
48
+ * `./consent.js` owns. Pass the request's `Cookie` header so the gate can read
49
+ * the decision; omitting it fails closed, as does an undecided visitor. The
50
+ * campaign then simply does not survive the visitor's next navigation — the
51
+ * landing request itself still matches on its own `utm_*` params, so a campaign
52
+ * page still renders its campaign content. Pass `requireConsent: false` (from
53
+ * `theme.personalization.requireConsent`) to turn the gate off for a site whose
54
+ * consent lives in external tooling.
44
55
  */
45
- export declare function utmCookieValue(url: string): string | null;
56
+ export declare function utmCookieValue(url: string, options?: {
57
+ cookieHeader?: string | null;
58
+ } & ConsentGateOptions): string | null;
46
59
  //# sourceMappingURL=utm-persistence.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utm-persistence.d.ts","sourceRoot":"","sources":["../../src/audiences/utm-persistence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,aAAa,CAAA;AAUpC;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAazD"}
1
+ {"version":3,"file":"utm-persistence.d.ts","sourceRoot":"","sources":["../../src/audiences/utm-persistence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAyB,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAE7E;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,aAAa,CAAA;AAUpC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,kBAAuB,GAClE,MAAM,GAAG,IAAI,CAcf"}
@@ -20,13 +20,14 @@
20
20
  * leaves any existing cookie untouched — ordinary navigation never clobbers a
21
21
  * persisted campaign.
22
22
  *
23
- * EDGE-SAFE LEAF MODULE: this file has NO imports (and therefore no transitive
24
- * DB dependency), because it is imported from Next.js edge middleware — where
25
- * core's DB-backed code (drizzle/postgres) cannot run. Keep it dependency-free.
26
- * It is published as its own export entry (`@kywi-software/core/audiences/
27
- * utm-persistence`) so importing it never drags in the DB-backed `audiences`
28
- * barrel.
23
+ * EDGE-SAFE LEAF MODULE: this file's only import is `./consent.js`, which is
24
+ * itself a zero-import leaf, because it is imported from Next.js edge
25
+ * middleware — where core's DB-backed code (drizzle/postgres) cannot run. Keep
26
+ * it dependency-free beyond that. It is published as its own export entry
27
+ * (`@kywi-software/core/audiences/utm-persistence`) so importing it never drags
28
+ * in the DB-backed `audiences` barrel.
29
29
  */
30
+ import { cookieAllowedByHeader } from './consent.js';
30
31
  /**
31
32
  * Cookie name `collectUtm` reads (mirrors `COOKIE_NAMES.UTM` in
32
33
  * `audiences/cookies.ts`). Kept as a literal here so this leaf module imports
@@ -48,8 +49,20 @@ const UTM_KEYS = [
48
49
  * The JSON shape mirrors what `collectUtm` parses: `{ source, medium, campaign,
49
50
  * term, content }` with only the present keys. Empty `utm_*` values are treated
50
51
  * as absent, and a malformed URL yields `null`.
52
+ *
53
+ * Also `null` when the visitor has not consented to personalization
54
+ * (kywi-cms#91): `kywi_utm` is a `personalization` cookie in the category map
55
+ * `./consent.js` owns. Pass the request's `Cookie` header so the gate can read
56
+ * the decision; omitting it fails closed, as does an undecided visitor. The
57
+ * campaign then simply does not survive the visitor's next navigation — the
58
+ * landing request itself still matches on its own `utm_*` params, so a campaign
59
+ * page still renders its campaign content. Pass `requireConsent: false` (from
60
+ * `theme.personalization.requireConsent`) to turn the gate off for a site whose
61
+ * consent lives in external tooling.
51
62
  */
52
- export function utmCookieValue(url) {
63
+ export function utmCookieValue(url, options = {}) {
64
+ if (!cookieAllowedByHeader(UTM_COOKIE, options.cookieHeader, options))
65
+ return null;
53
66
  let params;
54
67
  try {
55
68
  params = new URL(url).searchParams;
@@ -1 +1 @@
1
- {"version":3,"file":"utm-persistence.js","sourceRoot":"","sources":["../../src/audiences/utm-persistence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAAA;AAEpC,MAAM,QAAQ,GAAG;IACf,CAAC,YAAY,EAAE,QAAQ,CAAC;IACxB,CAAC,YAAY,EAAE,QAAQ,CAAC;IACxB,CAAC,cAAc,EAAE,UAAU,CAAC;IAC5B,CAAC,UAAU,EAAE,MAAM,CAAC;IACpB,CAAC,aAAa,EAAE,SAAS,CAAC;CAClB,CAAA;AAEV;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,IAAI,MAAuB,CAAA;IAC3B,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,YAAY,CAAA;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;IACD,MAAM,GAAG,GAA2B,EAAE,CAAA;IACtC,KAAK,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,QAAQ,EAAE,CAAC;QACpC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAC/B,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;IACtD,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AACjE,CAAC"}
1
+ {"version":3,"file":"utm-persistence.js","sourceRoot":"","sources":["../../src/audiences/utm-persistence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,qBAAqB,EAA2B,MAAM,cAAc,CAAA;AAE7E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAAA;AAEpC,MAAM,QAAQ,GAAG;IACf,CAAC,YAAY,EAAE,QAAQ,CAAC;IACxB,CAAC,YAAY,EAAE,QAAQ,CAAC;IACxB,CAAC,cAAc,EAAE,UAAU,CAAC;IAC5B,CAAC,UAAU,EAAE,MAAM,CAAC;IACpB,CAAC,aAAa,EAAE,SAAS,CAAC;CAClB,CAAA;AAEV;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,cAAc,CAC5B,GAAW,EACX,UAAiE,EAAE;IAEnE,IAAI,CAAC,qBAAqB,CAAC,UAAU,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC;QAAE,OAAO,IAAI,CAAA;IAClF,IAAI,MAAuB,CAAA;IAC3B,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,YAAY,CAAA;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;IACD,MAAM,GAAG,GAA2B,EAAE,CAAA;IACtC,KAAK,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,QAAQ,EAAE,CAAC;QACpC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAC/B,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;IACtD,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AACjE,CAAC"}
@@ -2,6 +2,17 @@ export declare const KYWI_ROLES: readonly ["superAdmin", "siteAdmin", "editor",
2
2
  export type KywiRole = (typeof KYWI_ROLES)[number];
3
3
  export type ContentAction = 'read' | 'write' | 'publish' | 'delete';
4
4
  export declare function hasMinRole(userRole: string, requiredRole: string): boolean;
5
+ /**
6
+ * True when `callerRole` sits STRICTLY ABOVE `targetRole` in the ladder — the
7
+ * strict counterpart of {@link hasMinRole}, which is inclusive of equal rank.
8
+ *
9
+ * The two express different rails (kywi-cms#175). Forcing a password reset on a
10
+ * peer is a temporary, self-serviceable nudge, so `hasMinRole` (equal-or-lower)
11
+ * is the right gate; SETTING a peer's password is a lateral account takeover,
12
+ * so that one needs this strict form. Unknown roles fall to level 0 on both
13
+ * sides, which fails closed here (0 > 0 is false).
14
+ */
15
+ export declare function outranks(callerRole: string, targetRole: string): boolean;
5
16
  export declare function canAccessContent(role: string, action: ContentAction): boolean;
6
17
  /**
7
18
  * API-key scope → the MAXIMUM role that scope grants. A key's scopes act as a
@@ -1 +1 @@
1
- {"version":3,"file":"roles.d.ts","sourceRoot":"","sources":["../../src/auth/roles.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,4EAA6E,CAAA;AACpG,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAA;AAClD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAA;AAkBnE,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAE1E;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAE7E;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAM1D,CAAA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAc/E"}
1
+ {"version":3,"file":"roles.d.ts","sourceRoot":"","sources":["../../src/auth/roles.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,4EAA6E,CAAA;AACpG,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAA;AAClD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAA;AAkBnE,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAE1E;AAED;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAExE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAE7E;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAM1D,CAAA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAc/E"}
@@ -16,6 +16,19 @@ const ACTION_MIN_ROLE = {
16
16
  export function hasMinRole(userRole, requiredRole) {
17
17
  return (ROLE_LEVEL[userRole] ?? 0) >= (ROLE_LEVEL[requiredRole] ?? 0);
18
18
  }
19
+ /**
20
+ * True when `callerRole` sits STRICTLY ABOVE `targetRole` in the ladder — the
21
+ * strict counterpart of {@link hasMinRole}, which is inclusive of equal rank.
22
+ *
23
+ * The two express different rails (kywi-cms#175). Forcing a password reset on a
24
+ * peer is a temporary, self-serviceable nudge, so `hasMinRole` (equal-or-lower)
25
+ * is the right gate; SETTING a peer's password is a lateral account takeover,
26
+ * so that one needs this strict form. Unknown roles fall to level 0 on both
27
+ * sides, which fails closed here (0 > 0 is false).
28
+ */
29
+ export function outranks(callerRole, targetRole) {
30
+ return (ROLE_LEVEL[callerRole] ?? 0) > (ROLE_LEVEL[targetRole] ?? 0);
31
+ }
19
32
  export function canAccessContent(role, action) {
20
33
  return hasMinRole(role, ACTION_MIN_ROLE[action]);
21
34
  }
@@ -1 +1 @@
1
- {"version":3,"file":"roles.js","sourceRoot":"","sources":["../../src/auth/roles.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAU,CAAA;AAIpG,MAAM,UAAU,GAA2B;IACzC,UAAU,EAAE,GAAG;IACf,SAAS,EAAE,EAAE;IACb,MAAM,EAAE,EAAE;IACV,MAAM,EAAE,EAAE;IACV,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,CAAC;CACR,CAAA;AAED,MAAM,eAAe,GAAkC;IACrD,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,QAAQ;IACf,OAAO,EAAE,QAAQ;IACjB,MAAM,EAAE,WAAW;CACpB,CAAA;AAED,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAE,YAAoB;IAC/D,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAA;AACvE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,MAAqB;IAClE,OAAO,UAAU,CAAC,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC,CAAA;AAClD,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAA6B;IAC7D,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,QAAQ;IACf,OAAO,EAAE,QAAQ;IACjB,KAAK,EAAE,WAAW;IAClB,SAAS,EAAE,WAAW;CACvB,CAAA;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,SAAiB,EAAE,MAAgB;IACrE,IAAI,YAAY,GAAG,CAAC,CAAA;IACpB,IAAI,WAAW,GAAG,MAAM,CAAA;IACxB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAA;QACzC,IAAI,CAAC,IAAI;YAAE,SAAQ;QACnB,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACnC,IAAI,KAAK,GAAG,YAAY,EAAE,CAAC;YACzB,YAAY,GAAG,KAAK,CAAA;YACpB,WAAW,GAAG,IAAI,CAAA;QACpB,CAAC;IACH,CAAC;IACD,MAAM,UAAU,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;IAC7C,OAAO,UAAU,IAAI,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAA;AAC7D,CAAC"}
1
+ {"version":3,"file":"roles.js","sourceRoot":"","sources":["../../src/auth/roles.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAU,CAAA;AAIpG,MAAM,UAAU,GAA2B;IACzC,UAAU,EAAE,GAAG;IACf,SAAS,EAAE,EAAE;IACb,MAAM,EAAE,EAAE;IACV,MAAM,EAAE,EAAE;IACV,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,CAAC;CACR,CAAA;AAED,MAAM,eAAe,GAAkC;IACrD,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,QAAQ;IACf,OAAO,EAAE,QAAQ;IACjB,MAAM,EAAE,WAAW;CACpB,CAAA;AAED,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAE,YAAoB;IAC/D,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAA;AACvE,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,QAAQ,CAAC,UAAkB,EAAE,UAAkB;IAC7D,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAA;AACtE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,MAAqB;IAClE,OAAO,UAAU,CAAC,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC,CAAA;AAClD,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAA6B;IAC7D,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,QAAQ;IACf,OAAO,EAAE,QAAQ;IACjB,KAAK,EAAE,WAAW;IAClB,SAAS,EAAE,WAAW;CACvB,CAAA;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,SAAiB,EAAE,MAAgB;IACrE,IAAI,YAAY,GAAG,CAAC,CAAA;IACpB,IAAI,WAAW,GAAG,MAAM,CAAA;IACxB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAA;QACzC,IAAI,CAAC,IAAI;YAAE,SAAQ;QACnB,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACnC,IAAI,KAAK,GAAG,YAAY,EAAE,CAAC;YACzB,YAAY,GAAG,KAAK,CAAA;YACpB,WAAW,GAAG,IAAI,CAAA;QACpB,CAAC;IACH,CAAC;IACD,MAAM,UAAU,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;IAC7C,OAAO,UAAU,IAAI,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAA;AAC7D,CAAC"}
@@ -1,4 +1,11 @@
1
1
  import type { UserContext } from '../config/types.js';
2
+ /**
3
+ * Maximum number of site UUIDs embedded in an access token's `sites` claim
4
+ * (kywi-cms#74). Beyond this the claim is dropped and the token carries a
5
+ * `sitesOverflow` marker instead; `resolveAuth` then resolves the real list
6
+ * from the DB, once per request.
7
+ */
8
+ export declare const SITES_CLAIM_MAX = 50;
2
9
  export declare function issueAccessToken(user: UserContext, secret: string): Promise<string>;
3
10
  export declare function issueRefreshToken(userId: string, secret: string): Promise<string>;
4
11
  //# sourceMappingURL=tokens.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/auth/tokens.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAErD,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBzF;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOvF"}
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/auth/tokens.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAErD;;;;;GAKG;AACH,eAAO,MAAM,eAAe,KAAK,CAAA;AAEjC,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiCzF;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOvF"}
@@ -1,4 +1,11 @@
1
1
  import { SignJWT } from 'jose';
2
+ /**
3
+ * Maximum number of site UUIDs embedded in an access token's `sites` claim
4
+ * (kywi-cms#74). Beyond this the claim is dropped and the token carries a
5
+ * `sitesOverflow` marker instead; `resolveAuth` then resolves the real list
6
+ * from the DB, once per request.
7
+ */
8
+ export const SITES_CLAIM_MAX = 50;
2
9
  export async function issueAccessToken(user, secret) {
3
10
  const key = new TextEncoder().encode(secret);
4
11
  // Embed per-site membership (#73) as the `sites` claim so authorization needs
@@ -12,8 +19,23 @@ export async function issueAccessToken(user, secret) {
12
19
  groups: user.groups,
13
20
  type: 'access',
14
21
  };
15
- if (user.siteMemberships !== undefined)
16
- claims.sites = user.siteMemberships;
22
+ // kywi-cms#74 — cap the claim. A site UUID costs ~37 bytes before base64, so
23
+ // a user in hundreds of sites would inflate the Authorization header of every
24
+ // request they ever make. Past SITES_CLAIM_MAX, drop the list and set a
25
+ // `sitesOverflow` marker instead: `resolveAuth` reads the marker and resolves
26
+ // the real memberships from the DB (memoized per request), which is the same
27
+ // lookup API-key auth already does on every call. Tokens at or under the cap
28
+ // are unchanged, so the common install never pays for the DB round-trip.
29
+ //
30
+ // The marker is deliberately NOT "unknown memberships": an absent `sites`
31
+ // claim already means that. It exists so an overflowed token is
32
+ // distinguishable from a pre-#73 token in logs and in future readers.
33
+ if (user.siteMemberships !== undefined) {
34
+ if (user.siteMemberships.length > SITES_CLAIM_MAX)
35
+ claims.sitesOverflow = true;
36
+ else
37
+ claims.sites = user.siteMemberships;
38
+ }
17
39
  return new SignJWT(claims)
18
40
  .setProtectedHeader({ alg: 'HS256' })
19
41
  .setIssuedAt()
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/auth/tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAG9B,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAiB,EAAE,MAAc;IACtE,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAC5C,8EAA8E;IAC9E,8EAA8E;IAC9E,yEAAyE;IACzE,6EAA6E;IAC7E,wEAAwE;IACxE,MAAM,MAAM,GAA4B;QACtC,GAAG,EAAE,IAAI,CAAC,EAAE;QACZ,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,IAAI,EAAE,QAAQ;KACf,CAAA;IACD,IAAI,IAAI,CAAC,eAAe,KAAK,SAAS;QAAE,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,eAAe,CAAA;IAC3E,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;SACvB,kBAAkB,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;SACpC,WAAW,EAAE;SACb,iBAAiB,CAAC,KAAK,CAAC;SACxB,IAAI,CAAC,GAAG,CAAC,CAAA;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAc,EAAE,MAAc;IACpE,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAC5C,OAAO,IAAI,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;SACjD,kBAAkB,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;SACpC,WAAW,EAAE;SACb,iBAAiB,CAAC,IAAI,CAAC;SACvB,IAAI,CAAC,GAAG,CAAC,CAAA;AACd,CAAC"}
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/auth/tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAG9B;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAA;AAEjC,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAiB,EAAE,MAAc;IACtE,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAC5C,8EAA8E;IAC9E,8EAA8E;IAC9E,yEAAyE;IACzE,6EAA6E;IAC7E,wEAAwE;IACxE,MAAM,MAAM,GAA4B;QACtC,GAAG,EAAE,IAAI,CAAC,EAAE;QACZ,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,IAAI,EAAE,QAAQ;KACf,CAAA;IACD,6EAA6E;IAC7E,8EAA8E;IAC9E,wEAAwE;IACxE,8EAA8E;IAC9E,6EAA6E;IAC7E,6EAA6E;IAC7E,yEAAyE;IACzE,EAAE;IACF,0EAA0E;IAC1E,gEAAgE;IAChE,sEAAsE;IACtE,IAAI,IAAI,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;QACvC,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,GAAG,eAAe;YAAE,MAAM,CAAC,aAAa,GAAG,IAAI,CAAA;;YACzE,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,eAAe,CAAA;IAC1C,CAAC;IACD,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;SACvB,kBAAkB,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;SACpC,WAAW,EAAE;SACb,iBAAiB,CAAC,KAAK,CAAC;SACxB,IAAI,CAAC,GAAG,CAAC,CAAA;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAc,EAAE,MAAc;IACpE,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAC5C,OAAO,IAAI,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;SACjD,kBAAkB,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;SACpC,WAAW,EAAE;SACb,iBAAiB,CAAC,IAAI,CAAC;SACvB,IAAI,CAAC,GAAG,CAAC,CAAA;AACd,CAAC"}
@@ -9,8 +9,16 @@ import type { AxContentSource } from './types.js';
9
9
  * generators need. Fixtures implement the same interface for unit tests, so the
10
10
  * generators never depend on a database.
11
11
  *
12
- * @param config reserved for future curation the DB source may need; currently
13
- * the source derives everything it needs from the DB directly.
12
+ * It is also where the LAYOUT PROJECTION is computed (kywi-cms#195). A page
13
+ * built in the layout editor keeps its copy in `layout`, and serializing that
14
+ * faithfully needs two things only this layer has: the site's module registry
15
+ * (so CUSTOM modules serialize from their declared prop schema) and its saved
16
+ * component definitions (so a linked placement projects what it renders). The
17
+ * result rides on the node as `layoutHtml`, which keeps every generator pure and
18
+ * synchronous — a fixture that supplies a `body` or a plain `layout` still
19
+ * exercises the same code.
20
+ *
21
+ * @param config supplies `modules` for the registry. Omitted → built-ins only.
14
22
  */
15
23
  export declare function createDbAxContentSource(db: KywiDb, config?: KywiConfig): AxContentSource;
16
24
  //# sourceMappingURL=content-source.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"content-source.d.ts","sourceRoot":"","sources":["../../src/ax/content-source.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,KAAK,EAAE,eAAe,EAAc,MAAM,YAAY,CAAA;AAE7D;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,eAAe,CAiBxF"}
1
+ {"version":3,"file":"content-source.d.ts","sourceRoot":"","sources":["../../src/ax/content-source.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,KAAK,EAAiB,eAAe,EAAc,MAAM,YAAY,CAAA;AAE5E;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,eAAe,CA0CxF"}
@@ -1,5 +1,9 @@
1
1
  import { listPublishedForAx } from '../db/ax-queries.js';
2
2
  import { getSiteById } from '../db/site-queries.js';
3
+ import { listComponents } from '../db/component-queries.js';
4
+ import { componentDetachSource } from '../layout/component-refs.js';
5
+ import { createModuleRegistry } from '../layout/registry.js';
6
+ import { withLayoutHtml } from './effective-body.js';
3
7
  /**
4
8
  * Production `AxContentSource` — the single read path backing every generator.
5
9
  *
@@ -8,14 +12,47 @@ import { getSiteById } from '../db/site-queries.js';
8
12
  * generators need. Fixtures implement the same interface for unit tests, so the
9
13
  * generators never depend on a database.
10
14
  *
11
- * @param config reserved for future curation the DB source may need; currently
12
- * the source derives everything it needs from the DB directly.
15
+ * It is also where the LAYOUT PROJECTION is computed (kywi-cms#195). A page
16
+ * built in the layout editor keeps its copy in `layout`, and serializing that
17
+ * faithfully needs two things only this layer has: the site's module registry
18
+ * (so CUSTOM modules serialize from their declared prop schema) and its saved
19
+ * component definitions (so a linked placement projects what it renders). The
20
+ * result rides on the node as `layoutHtml`, which keeps every generator pure and
21
+ * synchronous — a fixture that supplies a `body` or a plain `layout` still
22
+ * exercises the same code.
23
+ *
24
+ * @param config supplies `modules` for the registry. Omitted → built-ins only.
13
25
  */
14
26
  export function createDbAxContentSource(db, config) {
15
- void config;
27
+ const registry = createModuleRegistry(config?.modules ?? []);
28
+ async function projectionOpts(siteId) {
29
+ return { modules: registry, resolveComponent: await buildComponentResolver(db, siteId) };
30
+ }
16
31
  return {
17
- listForSite(siteId) {
18
- return listPublishedForAx(db, siteId);
32
+ async listForSite(siteId) {
33
+ const nodes = await listPublishedForAx(db, siteId);
34
+ // Only pay for the components read when something would actually use it.
35
+ if (!nodes.some(needsLayoutProjection))
36
+ return nodes;
37
+ const opts = await projectionOpts(siteId);
38
+ return nodes.map(node => (needsLayoutProjection(node) ? withLayoutHtml(node, opts) : node));
39
+ },
40
+ /**
41
+ * One node by slug, projecting ONE layout.
42
+ *
43
+ * `/<path>.md` used to call `listForSite` and `.find()` the node it wanted,
44
+ * which projected every page's layout — on an uncached route — to answer for
45
+ * one (kywi-cms#195 review). The read is still the same single query; only
46
+ * the projection is narrowed.
47
+ */
48
+ async getForSite(siteId, slug) {
49
+ const nodes = await listPublishedForAx(db, siteId);
50
+ const node = nodes.find(n => n.slug === slug);
51
+ if (!node)
52
+ return null;
53
+ if (!needsLayoutProjection(node))
54
+ return node;
55
+ return withLayoutHtml(node, await projectionOpts(siteId));
19
56
  },
20
57
  async getSiteMeta(siteId) {
21
58
  const site = await getSiteById(db, siteId);
@@ -30,4 +67,43 @@ export function createDbAxContentSource(db, config) {
30
67
  },
31
68
  };
32
69
  }
70
+ function needsLayoutProjection(node) {
71
+ // A node the editor marked "exclude from search & AX" is filtered out of every
72
+ // surface that would read the projection, so building it is pure cost — and on
73
+ // a site that excludes most of its tree, it is the cost that decides whether
74
+ // the components read happens at all.
75
+ if (node.excludeFromSearch === true)
76
+ return false;
77
+ if (typeof node.body === 'string' && node.body.trim())
78
+ return false;
79
+ return Boolean(node['layout']);
80
+ }
81
+ /**
82
+ * One read of the site's components, indexed by id AND by name, projected
83
+ * through {@link componentDetachSource} — the same projection the renderer and
84
+ * detach use, so the AX corpus shows what a placement actually draws.
85
+ *
86
+ * Name doubles as the `component` module's `slug` prop: `kywi_components` has no
87
+ * slug column, and a placement written before ids were stored addresses its
88
+ * target by name.
89
+ */
90
+ async function buildComponentResolver(db, siteId) {
91
+ const byId = new Map();
92
+ const byName = new Map();
93
+ const rows = await listComponents(db, siteId);
94
+ for (const row of rows) {
95
+ const source = componentDetachSource(row);
96
+ byId.set(row.id, source);
97
+ if (row.name && !byName.has(row.name))
98
+ byName.set(row.name, source);
99
+ }
100
+ return ({ componentId, slug }) => {
101
+ if (componentId) {
102
+ const byIdHit = byId.get(componentId);
103
+ if (byIdHit)
104
+ return byIdHit;
105
+ }
106
+ return slug ? byName.get(slug) ?? null : null;
107
+ };
108
+ }
33
109
  //# sourceMappingURL=content-source.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"content-source.js","sourceRoot":"","sources":["../../src/ax/content-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAKnD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,uBAAuB,CAAC,EAAU,EAAE,MAAmB;IACrE,KAAK,MAAM,CAAA;IACX,OAAO;QACL,WAAW,CAAC,MAAc;YACxB,OAAO,kBAAkB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;QACvC,CAAC;QACD,KAAK,CAAC,WAAW,CAAC,MAAc;YAC9B,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;YAC1C,IAAI,CAAC,IAAI;gBAAE,OAAO,IAAI,CAAA;YACtB,OAAO;gBACL,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,aAAa,EAAE,IAAI,CAAC,aAAa;aAClC,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"content-source.js","sourceRoot":"","sources":["../../src/ax/content-source.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { LayoutToHtmlOptions } from './layout-to-html.js';
2
+ import type { AxContentNode } from './types.js';
3
+ /**
4
+ * THE one answer to "what is this node's body copy", for every AX surface
5
+ * (kywi-cms#195).
6
+ *
7
+ * Resolution order:
8
+ * 1. the stored `body` column, when it holds anything — an article written in
9
+ * the rich-text field is already the whole page;
10
+ * 2. `layoutHtml`, the layout projection the AX CONTENT SOURCE precomputed
11
+ * (it is the only layer that can hand `layoutToHtml` the site's module
12
+ * registry and its saved component definitions);
13
+ * 3. a direct {@link layoutToHtml} of the node's stored `layout`, so a node
14
+ * handed straight to a generator — per-page JSON-LD reads the node the
15
+ * public page rendered, not one this module's source produced — still
16
+ * exports every built-in module's copy.
17
+ *
18
+ * Returns `''` when the node has neither, leaving each caller's own fallback
19
+ * (`summary`, `metaDescription`) exactly where it was.
20
+ */
21
+ export declare function effectiveBodyHtml(node: AxContentNode, opts?: LayoutToHtmlOptions): string;
22
+ /**
23
+ * Attach {@link AxContentNode.layoutHtml} to a node whose `body` is empty, using
24
+ * the registry/component resolver the caller has. A node with a body, or with no
25
+ * layout, is returned untouched — the projection would never be read.
26
+ */
27
+ export declare function withLayoutHtml(node: AxContentNode, opts: LayoutToHtmlOptions): AxContentNode;
28
+ //# sourceMappingURL=effective-body.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effective-body.d.ts","sourceRoot":"","sources":["../../src/ax/effective-body.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE,mBAAmB,GAAG,MAAM,CAMzF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,mBAAmB,GAAG,aAAa,CAM5F"}