@kywi-software/core 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (508) hide show
  1. package/AGENT-PATTERNS.md +153 -17
  2. package/README.md +38 -12
  3. package/dist/admin/chrome.d.ts.map +1 -1
  4. package/dist/admin/chrome.js +57 -8
  5. package/dist/admin/chrome.js.map +1 -1
  6. package/dist/admin/field-components.d.ts.map +1 -1
  7. package/dist/admin/field-components.js +27 -1
  8. package/dist/admin/field-components.js.map +1 -1
  9. package/dist/admin/form-helpers.d.ts.map +1 -1
  10. package/dist/admin/form-helpers.js +6 -1
  11. package/dist/admin/form-helpers.js.map +1 -1
  12. package/dist/admin/index.d.ts +1 -1
  13. package/dist/admin/index.d.ts.map +1 -1
  14. package/dist/admin/index.js +1 -1
  15. package/dist/admin/index.js.map +1 -1
  16. package/dist/admin/layout-editor/chrome-env.d.ts +35 -0
  17. package/dist/admin/layout-editor/chrome-env.d.ts.map +1 -0
  18. package/dist/admin/layout-editor/chrome-env.js +13 -0
  19. package/dist/admin/layout-editor/chrome-env.js.map +1 -0
  20. package/dist/admin/layout-editor/component-actions.d.ts +58 -7
  21. package/dist/admin/layout-editor/component-actions.d.ts.map +1 -1
  22. package/dist/admin/layout-editor/component-actions.js +131 -5
  23. package/dist/admin/layout-editor/component-actions.js.map +1 -1
  24. package/dist/admin/layout-editor/component-fork.d.ts +4 -4
  25. package/dist/admin/layout-editor/component-fork.d.ts.map +1 -1
  26. package/dist/admin/layout-editor/component-fork.js +76 -10
  27. package/dist/admin/layout-editor/component-fork.js.map +1 -1
  28. package/dist/admin/layout-editor/component-picker-field.d.ts +17 -3
  29. package/dist/admin/layout-editor/component-picker-field.d.ts.map +1 -1
  30. package/dist/admin/layout-editor/component-picker-field.js +5 -2
  31. package/dist/admin/layout-editor/component-picker-field.js.map +1 -1
  32. package/dist/admin/layout-editor/drag-feedback.d.ts +25 -1
  33. package/dist/admin/layout-editor/drag-feedback.d.ts.map +1 -1
  34. package/dist/admin/layout-editor/drag-feedback.js +9 -0
  35. package/dist/admin/layout-editor/drag-feedback.js.map +1 -1
  36. package/dist/admin/layout-editor/drag-utils.d.ts +103 -5
  37. package/dist/admin/layout-editor/drag-utils.d.ts.map +1 -1
  38. package/dist/admin/layout-editor/drag-utils.js +131 -4
  39. package/dist/admin/layout-editor/drag-utils.js.map +1 -1
  40. package/dist/admin/layout-editor/editor-canvas.d.ts +11 -0
  41. package/dist/admin/layout-editor/editor-canvas.d.ts.map +1 -1
  42. package/dist/admin/layout-editor/editor-canvas.js +134 -20
  43. package/dist/admin/layout-editor/editor-canvas.js.map +1 -1
  44. package/dist/admin/layout-editor/editor-dialog.d.ts +58 -3
  45. package/dist/admin/layout-editor/editor-dialog.d.ts.map +1 -1
  46. package/dist/admin/layout-editor/editor-dialog.js +71 -9
  47. package/dist/admin/layout-editor/editor-dialog.js.map +1 -1
  48. package/dist/admin/layout-editor/editor-state.d.ts +119 -0
  49. package/dist/admin/layout-editor/editor-state.d.ts.map +1 -1
  50. package/dist/admin/layout-editor/editor-state.js +188 -6
  51. package/dist/admin/layout-editor/editor-state.js.map +1 -1
  52. package/dist/admin/layout-editor/editor-toolbar.d.ts +10 -1
  53. package/dist/admin/layout-editor/editor-toolbar.d.ts.map +1 -1
  54. package/dist/admin/layout-editor/editor-toolbar.js +2 -2
  55. package/dist/admin/layout-editor/editor-toolbar.js.map +1 -1
  56. package/dist/admin/layout-editor/editor.css +216 -8
  57. package/dist/admin/layout-editor/inline-text.d.ts +15 -1
  58. package/dist/admin/layout-editor/inline-text.d.ts.map +1 -1
  59. package/dist/admin/layout-editor/inline-text.js +30 -2
  60. package/dist/admin/layout-editor/inline-text.js.map +1 -1
  61. package/dist/admin/layout-editor/layout-editor.d.ts +21 -16
  62. package/dist/admin/layout-editor/layout-editor.d.ts.map +1 -1
  63. package/dist/admin/layout-editor/layout-editor.js +40 -17
  64. package/dist/admin/layout-editor/layout-editor.js.map +1 -1
  65. package/dist/admin/layout-editor/linked-component-notes.d.ts +88 -0
  66. package/dist/admin/layout-editor/linked-component-notes.d.ts.map +1 -0
  67. package/dist/admin/layout-editor/linked-component-notes.js +88 -0
  68. package/dist/admin/layout-editor/linked-component-notes.js.map +1 -0
  69. package/dist/admin/layout-editor/module-overlay.d.ts +23 -4
  70. package/dist/admin/layout-editor/module-overlay.d.ts.map +1 -1
  71. package/dist/admin/layout-editor/module-overlay.js +56 -10
  72. package/dist/admin/layout-editor/module-overlay.js.map +1 -1
  73. package/dist/admin/layout-editor/module-variant-container-config.d.ts.map +1 -1
  74. package/dist/admin/layout-editor/module-variant-container-config.js +9 -2
  75. package/dist/admin/layout-editor/module-variant-container-config.js.map +1 -1
  76. package/dist/admin/layout-editor/module-variant-container-panel.d.ts +75 -0
  77. package/dist/admin/layout-editor/module-variant-container-panel.d.ts.map +1 -0
  78. package/dist/admin/layout-editor/module-variant-container-panel.js +29 -0
  79. package/dist/admin/layout-editor/module-variant-container-panel.js.map +1 -0
  80. package/dist/admin/layout-editor/node-lookup.d.ts.map +1 -1
  81. package/dist/admin/layout-editor/node-lookup.js +33 -3
  82. package/dist/admin/layout-editor/node-lookup.js.map +1 -1
  83. package/dist/admin/layout-editor/overlay-shell.d.ts.map +1 -1
  84. package/dist/admin/layout-editor/overlay-shell.js +19 -4
  85. package/dist/admin/layout-editor/overlay-shell.js.map +1 -1
  86. package/dist/admin/layout-editor/props-panel.d.ts +28 -11
  87. package/dist/admin/layout-editor/props-panel.d.ts.map +1 -1
  88. package/dist/admin/layout-editor/props-panel.js +75 -125
  89. package/dist/admin/layout-editor/props-panel.js.map +1 -1
  90. package/dist/admin/layout-editor/section-variant-container-config.d.ts.map +1 -1
  91. package/dist/admin/layout-editor/section-variant-container-config.js +11 -2
  92. package/dist/admin/layout-editor/section-variant-container-config.js.map +1 -1
  93. package/dist/admin/layout-editor/use-chrome-flip.d.ts +99 -11
  94. package/dist/admin/layout-editor/use-chrome-flip.d.ts.map +1 -1
  95. package/dist/admin/layout-editor/use-chrome-flip.js +268 -97
  96. package/dist/admin/layout-editor/use-chrome-flip.js.map +1 -1
  97. package/dist/admin/layout-editor/use-component-connect.d.ts +13 -0
  98. package/dist/admin/layout-editor/use-component-connect.d.ts.map +1 -1
  99. package/dist/admin/layout-editor/use-component-connect.js +116 -20
  100. package/dist/admin/layout-editor/use-component-connect.js.map +1 -1
  101. package/dist/admin/layout-editor/use-component-fork.d.ts +49 -19
  102. package/dist/admin/layout-editor/use-component-fork.d.ts.map +1 -1
  103. package/dist/admin/layout-editor/use-component-fork.js +28 -19
  104. package/dist/admin/layout-editor/use-component-fork.js.map +1 -1
  105. package/dist/admin/layout-editor/use-component-library.d.ts +4 -4
  106. package/dist/admin/layout-editor/use-component-library.d.ts.map +1 -1
  107. package/dist/admin/layout-editor/use-component-library.js +1 -1
  108. package/dist/admin/layout-editor/use-component-library.js.map +1 -1
  109. package/dist/admin/layout-editor/use-editor-dnd.d.ts +10 -0
  110. package/dist/admin/layout-editor/use-editor-dnd.d.ts.map +1 -1
  111. package/dist/admin/layout-editor/use-editor-dnd.js +234 -14
  112. package/dist/admin/layout-editor/use-editor-dnd.js.map +1 -1
  113. package/dist/admin/layout-editor/variant-container-config.d.ts.map +1 -1
  114. package/dist/admin/layout-editor/variant-container-config.js +1 -1
  115. package/dist/admin/layout-editor/variant-container-config.js.map +1 -1
  116. package/dist/admin/layout-editor/variant-editor.d.ts +16 -15
  117. package/dist/admin/layout-editor/variant-editor.d.ts.map +1 -1
  118. package/dist/admin/layout-editor/variant-editor.js +16 -5
  119. package/dist/admin/layout-editor/variant-editor.js.map +1 -1
  120. package/dist/admin/primitives.d.ts.map +1 -1
  121. package/dist/admin/primitives.js +1 -1
  122. package/dist/admin/primitives.js.map +1 -1
  123. package/dist/admin/registry.d.ts +24 -2
  124. package/dist/admin/registry.d.ts.map +1 -1
  125. package/dist/admin/registry.js +27 -0
  126. package/dist/admin/registry.js.map +1 -1
  127. package/dist/admin/server.d.ts +10 -1
  128. package/dist/admin/server.d.ts.map +1 -1
  129. package/dist/admin/server.js +4 -1
  130. package/dist/admin/server.js.map +1 -1
  131. package/dist/admin/site-switcher.d.ts +16 -3
  132. package/dist/admin/site-switcher.d.ts.map +1 -1
  133. package/dist/admin/site-switcher.js +18 -3
  134. package/dist/admin/site-switcher.js.map +1 -1
  135. package/dist/admin/styles/admin.css +0 -3
  136. package/dist/admin/surface-matcher.d.ts +6 -2
  137. package/dist/admin/surface-matcher.d.ts.map +1 -1
  138. package/dist/admin/surface-matcher.js +42 -5
  139. package/dist/admin/surface-matcher.js.map +1 -1
  140. package/dist/admin/surfaces/account/account-password.d.ts +3 -0
  141. package/dist/admin/surfaces/account/account-password.d.ts.map +1 -0
  142. package/dist/admin/surfaces/account/account-password.js +58 -0
  143. package/dist/admin/surfaces/account/account-password.js.map +1 -0
  144. package/dist/admin/surfaces/components/components-data.d.ts +31 -11
  145. package/dist/admin/surfaces/components/components-data.d.ts.map +1 -1
  146. package/dist/admin/surfaces/components/components-data.js +17 -4
  147. package/dist/admin/surfaces/components/components-data.js.map +1 -1
  148. package/dist/admin/surfaces/components/components-list.d.ts.map +1 -1
  149. package/dist/admin/surfaces/components/components-list.js +20 -7
  150. package/dist/admin/surfaces/components/components-list.js.map +1 -1
  151. package/dist/admin/surfaces/components/definition-canvas.d.ts +11 -3
  152. package/dist/admin/surfaces/components/definition-canvas.d.ts.map +1 -1
  153. package/dist/admin/surfaces/components/definition-canvas.js +138 -17
  154. package/dist/admin/surfaces/components/definition-canvas.js.map +1 -1
  155. package/dist/admin/surfaces/dashboard/dashboard-index.d.ts.map +1 -1
  156. package/dist/admin/surfaces/dashboard/dashboard-index.js +2 -2
  157. package/dist/admin/surfaces/dashboard/dashboard-index.js.map +1 -1
  158. package/dist/admin/surfaces/layouts/layout-editor-client.d.ts.map +1 -1
  159. package/dist/admin/surfaces/layouts/layout-editor-client.js +12 -11
  160. package/dist/admin/surfaces/layouts/layout-editor-client.js.map +1 -1
  161. package/dist/admin/surfaces/login.d.ts.map +1 -1
  162. package/dist/admin/surfaces/login.js +13 -1
  163. package/dist/admin/surfaces/login.js.map +1 -1
  164. package/dist/admin/surfaces/menus/menu-editor.d.ts.map +1 -1
  165. package/dist/admin/surfaces/menus/menu-editor.js +17 -4
  166. package/dist/admin/surfaces/menus/menu-editor.js.map +1 -1
  167. package/dist/admin/surfaces/menus/menu-tree.d.ts +18 -4
  168. package/dist/admin/surfaces/menus/menu-tree.d.ts.map +1 -1
  169. package/dist/admin/surfaces/menus/menu-tree.js +18 -3
  170. package/dist/admin/surfaces/menus/menu-tree.js.map +1 -1
  171. package/dist/admin/surfaces/menus/menus-data.d.ts +18 -0
  172. package/dist/admin/surfaces/menus/menus-data.d.ts.map +1 -1
  173. package/dist/admin/surfaces/menus/menus-data.js +4 -0
  174. package/dist/admin/surfaces/menus/menus-data.js.map +1 -1
  175. package/dist/admin/surfaces/menus/menus-list.d.ts.map +1 -1
  176. package/dist/admin/surfaces/menus/menus-list.js +2 -12
  177. package/dist/admin/surfaces/menus/menus-list.js.map +1 -1
  178. package/dist/admin/surfaces/settings/admin-features.d.ts.map +1 -1
  179. package/dist/admin/surfaces/settings/admin-features.js +12 -1
  180. package/dist/admin/surfaces/settings/admin-features.js.map +1 -1
  181. package/dist/admin/surfaces/users/users-data.d.ts +16 -0
  182. package/dist/admin/surfaces/users/users-data.d.ts.map +1 -1
  183. package/dist/admin/surfaces/users/users-data.js +19 -0
  184. package/dist/admin/surfaces/users/users-data.js.map +1 -1
  185. package/dist/admin/surfaces/users/users-detail.d.ts.map +1 -1
  186. package/dist/admin/surfaces/users/users-detail.js +87 -6
  187. package/dist/admin/surfaces/users/users-detail.js.map +1 -1
  188. package/dist/admin/surfaces/users/users-new.d.ts.map +1 -1
  189. package/dist/admin/surfaces/users/users-new.js +9 -5
  190. package/dist/admin/surfaces/users/users-new.js.map +1 -1
  191. package/dist/admin/user-form.d.ts +13 -2
  192. package/dist/admin/user-form.d.ts.map +1 -1
  193. package/dist/admin/user-form.js +3 -2
  194. package/dist/admin/user-form.js.map +1 -1
  195. package/dist/api/admin-features-routes.js +2 -2
  196. package/dist/api/admin-features-routes.js.map +1 -1
  197. package/dist/api/audience-preview-routes.d.ts +7 -0
  198. package/dist/api/audience-preview-routes.d.ts.map +1 -1
  199. package/dist/api/audience-preview-routes.js +4 -4
  200. package/dist/api/audience-preview-routes.js.map +1 -1
  201. package/dist/api/audience-routes.d.ts +7 -0
  202. package/dist/api/audience-routes.d.ts.map +1 -1
  203. package/dist/api/audience-routes.js +21 -15
  204. package/dist/api/audience-routes.js.map +1 -1
  205. package/dist/api/audience-runtime-routes.d.ts +6 -0
  206. package/dist/api/audience-runtime-routes.d.ts.map +1 -1
  207. package/dist/api/audience-runtime-routes.js +38 -3
  208. package/dist/api/audience-runtime-routes.js.map +1 -1
  209. package/dist/api/auth-routes.d.ts.map +1 -1
  210. package/dist/api/auth-routes.js +33 -4
  211. package/dist/api/auth-routes.js.map +1 -1
  212. package/dist/api/auth.d.ts +1 -0
  213. package/dist/api/auth.d.ts.map +1 -1
  214. package/dist/api/auth.js +43 -3
  215. package/dist/api/auth.js.map +1 -1
  216. package/dist/api/bulk-routes.d.ts.map +1 -1
  217. package/dist/api/bulk-routes.js +7 -7
  218. package/dist/api/bulk-routes.js.map +1 -1
  219. package/dist/api/category-routes.js +3 -3
  220. package/dist/api/category-routes.js.map +1 -1
  221. package/dist/api/comment-routes.js +8 -8
  222. package/dist/api/comment-routes.js.map +1 -1
  223. package/dist/api/component-routes.d.ts +25 -0
  224. package/dist/api/component-routes.d.ts.map +1 -1
  225. package/dist/api/component-routes.js +41 -16
  226. package/dist/api/component-routes.js.map +1 -1
  227. package/dist/api/content-routes.js +13 -13
  228. package/dist/api/content-routes.js.map +1 -1
  229. package/dist/api/dashboard-routes.js +1 -1
  230. package/dist/api/dashboard-routes.js.map +1 -1
  231. package/dist/api/experiment-routes.d.ts +7 -0
  232. package/dist/api/experiment-routes.d.ts.map +1 -1
  233. package/dist/api/experiment-routes.js +8 -8
  234. package/dist/api/experiment-routes.js.map +1 -1
  235. package/dist/api/experiment-runtime-routes.d.ts +6 -0
  236. package/dist/api/experiment-runtime-routes.d.ts.map +1 -1
  237. package/dist/api/experiment-runtime-routes.js +47 -11
  238. package/dist/api/experiment-runtime-routes.js.map +1 -1
  239. package/dist/api/feed-routes.d.ts +2 -2
  240. package/dist/api/feed-routes.js +3 -3
  241. package/dist/api/feed-routes.js.map +1 -1
  242. package/dist/api/form-routes.js +4 -4
  243. package/dist/api/form-routes.js.map +1 -1
  244. package/dist/api/graphql/resolvers.d.ts +1 -1
  245. package/dist/api/graphql/resolvers.d.ts.map +1 -1
  246. package/dist/api/graphql/resolvers.js +68 -33
  247. package/dist/api/graphql/resolvers.js.map +1 -1
  248. package/dist/api/group-routes.js +6 -6
  249. package/dist/api/group-routes.js.map +1 -1
  250. package/dist/api/index.d.ts +10 -0
  251. package/dist/api/index.d.ts.map +1 -1
  252. package/dist/api/index.js +97 -7
  253. package/dist/api/index.js.map +1 -1
  254. package/dist/api/layout-routes.d.ts.map +1 -1
  255. package/dist/api/layout-routes.js +27 -3
  256. package/dist/api/layout-routes.js.map +1 -1
  257. package/dist/api/media-routes.d.ts.map +1 -1
  258. package/dist/api/media-routes.js +50 -26
  259. package/dist/api/media-routes.js.map +1 -1
  260. package/dist/api/menu-routes.d.ts +9 -1
  261. package/dist/api/menu-routes.d.ts.map +1 -1
  262. package/dist/api/menu-routes.js +44 -10
  263. package/dist/api/menu-routes.js.map +1 -1
  264. package/dist/api/nav-routes.d.ts +6 -0
  265. package/dist/api/nav-routes.d.ts.map +1 -1
  266. package/dist/api/nav-routes.js +24 -3
  267. package/dist/api/nav-routes.js.map +1 -1
  268. package/dist/api/openapi.d.ts.map +1 -1
  269. package/dist/api/openapi.js +68 -33
  270. package/dist/api/openapi.js.map +1 -1
  271. package/dist/api/password-gate.d.ts +23 -0
  272. package/dist/api/password-gate.d.ts.map +1 -0
  273. package/dist/api/password-gate.js +41 -0
  274. package/dist/api/password-gate.js.map +1 -0
  275. package/dist/api/password-reset-routes.d.ts.map +1 -1
  276. package/dist/api/password-reset-routes.js +13 -6
  277. package/dist/api/password-reset-routes.js.map +1 -1
  278. package/dist/api/search-routes.js +2 -2
  279. package/dist/api/search-routes.js.map +1 -1
  280. package/dist/api/section-template-routes.d.ts.map +1 -1
  281. package/dist/api/section-template-routes.js +35 -18
  282. package/dist/api/section-template-routes.js.map +1 -1
  283. package/dist/api/site-admin-routes.d.ts +10 -1
  284. package/dist/api/site-admin-routes.d.ts.map +1 -1
  285. package/dist/api/site-admin-routes.js +21 -1
  286. package/dist/api/site-admin-routes.js.map +1 -1
  287. package/dist/api/site-context.d.ts +35 -5
  288. package/dist/api/site-context.d.ts.map +1 -1
  289. package/dist/api/site-context.js +21 -6
  290. package/dist/api/site-context.js.map +1 -1
  291. package/dist/api/tag-routes.js +3 -3
  292. package/dist/api/tag-routes.js.map +1 -1
  293. package/dist/api/translation-routes.js +5 -5
  294. package/dist/api/translation-routes.js.map +1 -1
  295. package/dist/api/user-routes.d.ts +4 -0
  296. package/dist/api/user-routes.d.ts.map +1 -1
  297. package/dist/api/user-routes.js +240 -17
  298. package/dist/api/user-routes.js.map +1 -1
  299. package/dist/api/webhook-routes.js +5 -5
  300. package/dist/api/webhook-routes.js.map +1 -1
  301. package/dist/api/workflow-routes.js +8 -8
  302. package/dist/api/workflow-routes.js.map +1 -1
  303. package/dist/audiences/collectors/identity.d.ts +14 -1
  304. package/dist/audiences/collectors/identity.d.ts.map +1 -1
  305. package/dist/audiences/collectors/identity.js +16 -3
  306. package/dist/audiences/collectors/identity.js.map +1 -1
  307. package/dist/audiences/collectors/index.d.ts +12 -2
  308. package/dist/audiences/collectors/index.d.ts.map +1 -1
  309. package/dist/audiences/collectors/index.js +16 -5
  310. package/dist/audiences/collectors/index.js.map +1 -1
  311. package/dist/audiences/collectors/pinned-audience.d.ts +28 -2
  312. package/dist/audiences/collectors/pinned-audience.d.ts.map +1 -1
  313. package/dist/audiences/collectors/pinned-audience.js +35 -5
  314. package/dist/audiences/collectors/pinned-audience.js.map +1 -1
  315. package/dist/audiences/collectors/utm.d.ts +15 -1
  316. package/dist/audiences/collectors/utm.d.ts.map +1 -1
  317. package/dist/audiences/collectors/utm.js +16 -2
  318. package/dist/audiences/collectors/utm.js.map +1 -1
  319. package/dist/audiences/consent-config.d.ts +21 -0
  320. package/dist/audiences/consent-config.d.ts.map +1 -0
  321. package/dist/audiences/consent-config.js +15 -0
  322. package/dist/audiences/consent-config.js.map +1 -0
  323. package/dist/audiences/consent-startup.d.ts +39 -0
  324. package/dist/audiences/consent-startup.d.ts.map +1 -0
  325. package/dist/audiences/consent-startup.js +105 -0
  326. package/dist/audiences/consent-startup.js.map +1 -0
  327. package/dist/audiences/consent.d.ts +192 -0
  328. package/dist/audiences/consent.d.ts.map +1 -0
  329. package/dist/audiences/consent.js +322 -0
  330. package/dist/audiences/consent.js.map +1 -0
  331. package/dist/audiences/engine.d.ts +7 -0
  332. package/dist/audiences/engine.d.ts.map +1 -1
  333. package/dist/audiences/engine.js +6 -2
  334. package/dist/audiences/engine.js.map +1 -1
  335. package/dist/audiences/index.d.ts +3 -0
  336. package/dist/audiences/index.d.ts.map +1 -1
  337. package/dist/audiences/index.js +6 -0
  338. package/dist/audiences/index.js.map +1 -1
  339. package/dist/audiences/server-eval.d.ts +13 -1
  340. package/dist/audiences/server-eval.d.ts.map +1 -1
  341. package/dist/audiences/server-eval.js +18 -2
  342. package/dist/audiences/server-eval.js.map +1 -1
  343. package/dist/audiences/ssr.d.ts +18 -1
  344. package/dist/audiences/ssr.d.ts.map +1 -1
  345. package/dist/audiences/ssr.js +18 -1
  346. package/dist/audiences/ssr.js.map +1 -1
  347. package/dist/audiences/utm-persistence.d.ts +20 -7
  348. package/dist/audiences/utm-persistence.d.ts.map +1 -1
  349. package/dist/audiences/utm-persistence.js +20 -7
  350. package/dist/audiences/utm-persistence.js.map +1 -1
  351. package/dist/auth/roles.d.ts +11 -0
  352. package/dist/auth/roles.d.ts.map +1 -1
  353. package/dist/auth/roles.js +13 -0
  354. package/dist/auth/roles.js.map +1 -1
  355. package/dist/auth/tokens.d.ts +7 -0
  356. package/dist/auth/tokens.d.ts.map +1 -1
  357. package/dist/auth/tokens.js +24 -2
  358. package/dist/auth/tokens.js.map +1 -1
  359. package/dist/config/types.d.ts +50 -0
  360. package/dist/config/types.d.ts.map +1 -1
  361. package/dist/config/types.js.map +1 -1
  362. package/dist/config/validate.d.ts.map +1 -1
  363. package/dist/config/validate.js +3 -0
  364. package/dist/config/validate.js.map +1 -1
  365. package/dist/db/apply-snapshot.d.ts +18 -0
  366. package/dist/db/apply-snapshot.d.ts.map +1 -1
  367. package/dist/db/apply-snapshot.js +41 -16
  368. package/dist/db/apply-snapshot.js.map +1 -1
  369. package/dist/db/component-instance-queries.d.ts +79 -19
  370. package/dist/db/component-instance-queries.d.ts.map +1 -1
  371. package/dist/db/component-instance-queries.js +266 -83
  372. package/dist/db/component-instance-queries.js.map +1 -1
  373. package/dist/db/component-queries.d.ts +1 -16
  374. package/dist/db/component-queries.d.ts.map +1 -1
  375. package/dist/db/component-queries.js +7 -56
  376. package/dist/db/component-queries.js.map +1 -1
  377. package/dist/db/content-queries.d.ts.map +1 -1
  378. package/dist/db/content-queries.js +1 -2
  379. package/dist/db/content-queries.js.map +1 -1
  380. package/dist/db/extension-queries.d.ts +2 -2
  381. package/dist/db/feed-queries.d.ts +3 -3
  382. package/dist/db/index.d.ts +1 -0
  383. package/dist/db/index.d.ts.map +1 -1
  384. package/dist/db/index.js +1 -0
  385. package/dist/db/index.js.map +1 -1
  386. package/dist/db/layout-queries.d.ts +2 -1
  387. package/dist/db/layout-queries.d.ts.map +1 -1
  388. package/dist/db/layout-queries.js +3 -3
  389. package/dist/db/layout-queries.js.map +1 -1
  390. package/dist/db/menu-queries.d.ts +69 -5
  391. package/dist/db/menu-queries.d.ts.map +1 -1
  392. package/dist/db/menu-queries.js +120 -13
  393. package/dist/db/menu-queries.js.map +1 -1
  394. package/dist/db/section-template-queries.d.ts +62 -0
  395. package/dist/db/section-template-queries.d.ts.map +1 -0
  396. package/dist/db/section-template-queries.js +178 -0
  397. package/dist/db/section-template-queries.js.map +1 -0
  398. package/dist/db/site-plugin-queries.d.ts +2 -2
  399. package/dist/db/tree-queries.d.ts.map +1 -1
  400. package/dist/db/tree-queries.js +5 -0
  401. package/dist/db/tree-queries.js.map +1 -1
  402. package/dist/db/user-queries.d.ts +28 -1
  403. package/dist/db/user-queries.d.ts.map +1 -1
  404. package/dist/db/user-queries.js +49 -1
  405. package/dist/db/user-queries.js.map +1 -1
  406. package/dist/db/webhook-queries.d.ts +3 -3
  407. package/dist/db/workflow-queries.d.ts.map +1 -1
  408. package/dist/db/workflow-queries.js +5 -20
  409. package/dist/db/workflow-queries.js.map +1 -1
  410. package/dist/experiments/runtime.d.ts +21 -3
  411. package/dist/experiments/runtime.d.ts.map +1 -1
  412. package/dist/experiments/runtime.js +21 -3
  413. package/dist/experiments/runtime.js.map +1 -1
  414. package/dist/host/index.d.ts +1 -0
  415. package/dist/host/index.d.ts.map +1 -1
  416. package/dist/host/index.js +12 -0
  417. package/dist/host/index.js.map +1 -1
  418. package/dist/layout/component-refs.d.ts +90 -2
  419. package/dist/layout/component-refs.d.ts.map +1 -1
  420. package/dist/layout/component-refs.js +293 -16
  421. package/dist/layout/component-refs.js.map +1 -1
  422. package/dist/layout/index.d.ts +4 -3
  423. package/dist/layout/index.d.ts.map +1 -1
  424. package/dist/layout/index.js +3 -2
  425. package/dist/layout/index.js.map +1 -1
  426. package/dist/layout/legacy-variant-container.d.ts +123 -0
  427. package/dist/layout/legacy-variant-container.d.ts.map +1 -0
  428. package/dist/layout/legacy-variant-container.js +397 -0
  429. package/dist/layout/legacy-variant-container.js.map +1 -0
  430. package/dist/layout/module-permissions.d.ts.map +1 -1
  431. package/dist/layout/module-permissions.js +25 -1
  432. package/dist/layout/module-permissions.js.map +1 -1
  433. package/dist/layout/modules-extended.d.ts +28 -1
  434. package/dist/layout/modules-extended.d.ts.map +1 -1
  435. package/dist/layout/modules-extended.js +73 -1
  436. package/dist/layout/modules-extended.js.map +1 -1
  437. package/dist/layout/modules.d.ts.map +1 -1
  438. package/dist/layout/modules.js +9 -1
  439. package/dist/layout/modules.js.map +1 -1
  440. package/dist/layout/personalization.d.ts +83 -0
  441. package/dist/layout/personalization.d.ts.map +1 -1
  442. package/dist/layout/personalization.js +250 -4
  443. package/dist/layout/personalization.js.map +1 -1
  444. package/dist/layout/registry.d.ts.map +1 -1
  445. package/dist/layout/registry.js +20 -0
  446. package/dist/layout/registry.js.map +1 -1
  447. package/dist/layout/renderer.d.ts +29 -2
  448. package/dist/layout/renderer.d.ts.map +1 -1
  449. package/dist/layout/renderer.js +23 -6
  450. package/dist/layout/renderer.js.map +1 -1
  451. package/dist/layout/types.d.ts +17 -0
  452. package/dist/layout/types.d.ts.map +1 -1
  453. package/dist/layout/types.js +7 -0
  454. package/dist/layout/types.js.map +1 -1
  455. package/dist/media/inline-risk.d.ts +26 -0
  456. package/dist/media/inline-risk.d.ts.map +1 -0
  457. package/dist/media/inline-risk.js +142 -0
  458. package/dist/media/inline-risk.js.map +1 -0
  459. package/dist/nav/builder.d.ts.map +1 -1
  460. package/dist/nav/builder.js +15 -3
  461. package/dist/nav/builder.js.map +1 -1
  462. package/dist/nav/index.d.ts +1 -1
  463. package/dist/nav/index.d.ts.map +1 -1
  464. package/dist/nav/index.js +1 -1
  465. package/dist/nav/index.js.map +1 -1
  466. package/dist/nav/menu-resolver.d.ts +11 -0
  467. package/dist/nav/menu-resolver.d.ts.map +1 -1
  468. package/dist/nav/menu-resolver.js +49 -9
  469. package/dist/nav/menu-resolver.js.map +1 -1
  470. package/dist/nav/paths.d.ts +37 -0
  471. package/dist/nav/paths.d.ts.map +1 -0
  472. package/dist/nav/paths.js +48 -0
  473. package/dist/nav/paths.js.map +1 -0
  474. package/dist/nav/types.d.ts +6 -0
  475. package/dist/nav/types.d.ts.map +1 -1
  476. package/dist/nav/url-resolver.d.ts +1 -5
  477. package/dist/nav/url-resolver.d.ts.map +1 -1
  478. package/dist/nav/url-resolver.js +6 -12
  479. package/dist/nav/url-resolver.js.map +1 -1
  480. package/dist/schema/base.d.ts +41 -4
  481. package/dist/schema/base.d.ts.map +1 -1
  482. package/dist/schema/base.js +23 -4
  483. package/dist/schema/base.js.map +1 -1
  484. package/dist/schema/components.d.ts +90 -9
  485. package/dist/schema/components.d.ts.map +1 -1
  486. package/dist/schema/components.js +113 -22
  487. package/dist/schema/components.js.map +1 -1
  488. package/dist/schema/mysql-tables.d.ts +5775 -48
  489. package/dist/schema/mysql-tables.d.ts.map +1 -1
  490. package/dist/schema/mysql-tables.js +621 -46
  491. package/dist/schema/mysql-tables.js.map +1 -1
  492. package/dist/scope/kywi-form.d.ts +11 -0
  493. package/dist/scope/kywi-form.d.ts.map +1 -1
  494. package/dist/scope/kywi-form.js +11 -1
  495. package/dist/scope/kywi-form.js.map +1 -1
  496. package/dist/scope/kywi-wizard-form.d.ts.map +1 -1
  497. package/dist/scope/kywi-wizard-form.js +76 -2
  498. package/dist/scope/kywi-wizard-form.js.map +1 -1
  499. package/dist/scope/sticky-offset.d.ts +34 -13
  500. package/dist/scope/sticky-offset.d.ts.map +1 -1
  501. package/dist/scope/sticky-offset.js +236 -43
  502. package/dist/scope/sticky-offset.js.map +1 -1
  503. package/dist/site/styles.css +61 -15
  504. package/dist/versioning/scheduler.d.ts +28 -0
  505. package/dist/versioning/scheduler.d.ts.map +1 -1
  506. package/dist/versioning/scheduler.js +50 -3
  507. package/dist/versioning/scheduler.js.map +1 -1
  508. package/package.json +7 -2
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Startup checks for the cookie-consent gate (kywi-cms#91).
3
+ *
4
+ * Two failure modes are invisible at runtime and expensive to discover later:
5
+ *
6
+ * 1. The config flag and its edge mirror disagree. `middleware.ts` runs on the
7
+ * edge and cannot read `kywi.config.ts`, so `requireConsent` is mirrored as
8
+ * `KYWI_REQUIRE_CONSENT`. If the two drift, the middleware and the API
9
+ * disagree about whether a visitor may be tracked — one writes
10
+ * `kywi_visitor`, the other refuses to read it — and nothing anywhere says
11
+ * so. That is a misconfiguration, and it fails the deploy.
12
+ *
13
+ * 2. Consent is required and no page offers a way to give it. Every
14
+ * personalization cookie is then permanently suppressed: audiences,
15
+ * experiments and UTM attribution quietly do nothing, and the site looks
16
+ * broken rather than gated. That is a WARNING, not an error — a site may
17
+ * legitimately have no personalization at all — but it must be said out
18
+ * loud, once, rather than left for someone to debug.
19
+ */
20
+ import { sql } from 'drizzle-orm';
21
+ /** The env var mirroring `theme.personalization.requireConsent` for edge middleware. */
22
+ export const REQUIRE_CONSENT_ENV = 'KYWI_REQUIRE_CONSENT';
23
+ /** How `middleware.ts` reads the mirror: anything but the literal "false" is true. */
24
+ export function requireConsentFromEnv(env = process.env) {
25
+ return env[REQUIRE_CONSENT_ENV] !== 'false';
26
+ }
27
+ /**
28
+ * Fail startup when the config flag and its edge mirror disagree.
29
+ *
30
+ * Deliberately a throw and not a warning: the two halves of one setting pointing
31
+ * opposite ways is never intentional, and the resulting behaviour (cookies
32
+ * written by the edge that the API then declines to read, or vice versa) is
33
+ * exactly the kind of bug that survives to production because nothing is
34
+ * visibly broken.
35
+ */
36
+ export function assertConsentEnvAgreement(requireConsentFromConfig, env = process.env) {
37
+ const fromEnv = requireConsentFromEnv(env);
38
+ if (fromEnv === requireConsentFromConfig)
39
+ return;
40
+ const raw = env[REQUIRE_CONSENT_ENV];
41
+ throw new Error(`Cookie-consent misconfiguration: theme.personalization.requireConsent is ` +
42
+ `${requireConsentFromConfig} but ${REQUIRE_CONSENT_ENV} is ` +
43
+ `${raw === undefined ? 'unset (which means true)' : JSON.stringify(raw)}.\n` +
44
+ ` Next.js edge middleware cannot read kywi.config.ts, so it mirrors that flag ` +
45
+ `through ${REQUIRE_CONSENT_ENV}. While they disagree, the middleware and the API ` +
46
+ `disagree about whether a visitor may be tracked.\n` +
47
+ ` Set both, or neither: ${REQUIRE_CONSENT_ENV}=false alongside ` +
48
+ `personalization: { requireConsent: false }, or remove both.`);
49
+ }
50
+ const NO_BANNER_WARNING = '[kywi] Cookie consent is required (theme.personalization.requireConsent) but no ' +
51
+ 'page or layout places the `cookieConsent` module, so no visitor can ever grant it. ' +
52
+ 'Every personalization cookie stays suppressed: audiences, A/B bucketing and UTM ' +
53
+ 'attribution will resolve to default content for everyone. Place the module, or set ' +
54
+ 'personalization: { requireConsent: false } if consent is collected by external tooling.';
55
+ /**
56
+ * Build the once-only "consent required, but nothing asks for it" check.
57
+ *
58
+ * Returns a function safe to call on every request: it runs at most once, never
59
+ * awaits (the first request does not pay for it), and swallows every error. A
60
+ * warning that could break a page, or add latency to the hot path, would not be
61
+ * worth having.
62
+ *
63
+ * The check is a `::text LIKE` prefilter — the same shape
64
+ * `checkAudienceDeletionSafety` uses — looking for anything that mentions the
65
+ * module type at all. Over-matching is fine here: a false negative (staying
66
+ * quiet) is the safe direction for an advisory warning.
67
+ *
68
+ * It reads BOTH places a module can be placed: `kywi_content.layout` and
69
+ * `kywi_section_templates.definition`. A banner composed from a blueprint is a
70
+ * banner, and scanning pages alone told a site that builds every page that way
71
+ * that consent could never be granted — while the banner was on screen.
72
+ */
73
+ export function createConsentBannerCheck(deps) {
74
+ const warn = deps.warn ?? ((m) => console.warn(m));
75
+ let started = false;
76
+ return () => {
77
+ if (started || !deps.requireConsent)
78
+ return;
79
+ started = true;
80
+ void (async () => {
81
+ try {
82
+ const rows = await deps.db.execute(sql `
83
+ SELECT 1 AS found
84
+ FROM kywi_content
85
+ WHERE layout IS NOT NULL
86
+ AND layout::text LIKE ${'%"cookieConsent"%'}
87
+ UNION ALL
88
+ SELECT 1 AS found
89
+ FROM kywi_section_templates
90
+ WHERE definition IS NOT NULL
91
+ AND definition::text LIKE ${'%"cookieConsent"%'}
92
+ LIMIT 1
93
+ `);
94
+ if (rows.length === 0)
95
+ warn(NO_BANNER_WARNING);
96
+ }
97
+ catch {
98
+ // No content table yet (a fresh install mid-migration), a dialect that
99
+ // cannot cast, a transient connection failure — none of that is worth
100
+ // failing or logging a request over. Silence is the safe direction.
101
+ }
102
+ })();
103
+ };
104
+ }
105
+ //# sourceMappingURL=consent-startup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consent-startup.js","sourceRoot":"","sources":["../../src/audiences/consent-startup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAGjC,wFAAwF;AACxF,MAAM,CAAC,MAAM,mBAAmB,GAAG,sBAAsB,CAAA;AAEzD,sFAAsF;AACtF,MAAM,UAAU,qBAAqB,CAAC,MAA0C,OAAO,CAAC,GAAG;IACzF,OAAO,GAAG,CAAC,mBAAmB,CAAC,KAAK,OAAO,CAAA;AAC7C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,yBAAyB,CACvC,wBAAiC,EACjC,MAA0C,OAAO,CAAC,GAAG;IAErD,MAAM,OAAO,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAA;IAC1C,IAAI,OAAO,KAAK,wBAAwB;QAAE,OAAM;IAChD,MAAM,GAAG,GAAG,GAAG,CAAC,mBAAmB,CAAC,CAAA;IACpC,MAAM,IAAI,KAAK,CACb,2EAA2E;QACzE,GAAG,wBAAwB,QAAQ,mBAAmB,MAAM;QAC5D,GAAG,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK;QAC5E,gFAAgF;QAChF,WAAW,mBAAmB,oDAAoD;QAClF,oDAAoD;QACpD,2BAA2B,mBAAmB,mBAAmB;QACjE,6DAA6D,CAChE,CAAA;AACH,CAAC;AAED,MAAM,iBAAiB,GACrB,kFAAkF;IAClF,qFAAqF;IACrF,kFAAkF;IAClF,qFAAqF;IACrF,yFAAyF,CAAA;AAE3F;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAIxC;IACC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IAC1D,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,OAAO,GAAG,EAAE;QACV,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,cAAc;YAAE,OAAM;QAC3C,OAAO,GAAG,IAAI,CAAA;QACd,KAAK,CAAC,KAAK,IAAI,EAAE;YACf,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,OAAO,CAChC,GAAG,CAAA;;;;sCAIyB,mBAAmB;;;;;0CAKf,mBAAmB;;WAElD,CACF,CAAA;gBACD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;oBAAE,IAAI,CAAC,iBAAiB,CAAC,CAAA;YAChD,CAAC;YAAC,MAAM,CAAC;gBACP,uEAAuE;gBACvE,sEAAsE;gBACtE,oEAAoE;YACtE,CAAC;QACH,CAAC,CAAC,EAAE,CAAA;IACN,CAAC,CAAA;AACH,CAAC"}
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Cookie consent — the category map, and the gate every optional cookie write
3
+ * passes through (kywi-cms#91).
4
+ *
5
+ * Before this module the `cookieConsent` layout module and the `kywi_consent`
6
+ * cookie were two halves of a feature that never met: the banner's buttons had
7
+ * no handlers, and no cookie-writing code path ever asked whether the visitor
8
+ * had consented. This file is the join. It owns three things:
9
+ *
10
+ * 1. `COOKIE_CONSENT_CATEGORY` — the SINGLE SOURCE OF TRUTH mapping every
11
+ * cookie the engine writes to the consent category it needs. Nothing else
12
+ * in the codebase may decide a cookie's category.
13
+ * 2. `cookieAllowed()` / `consentAllows()` — the gate. Every optional cookie
14
+ * write calls one of these first.
15
+ * 3. The browser-side read/write of the `kywi_consent` cookie itself, used by
16
+ * the `cookieConsent` layout module's buttons.
17
+ *
18
+ * ── Category decisions (owner-set) ──────────────────────────────────────────
19
+ *
20
+ * necessary / `essential` — always allowed, never gated:
21
+ * `kywi_consent` the consent record itself
22
+ * `kywi_optout` the personalization opt-out flag: a *suppression*
23
+ * preference. Blocking a visitor from recording "stop
24
+ * personalizing me" until they consent to cookies would
25
+ * be perverse, so this is necessary by construction.
26
+ * `kywi_preview_init` admin preview hand-off, not visitor tracking.
27
+ *
28
+ * `personalization` — gated:
29
+ * `kywi_visitor` visitor id, incl. experiment bucketing / exposure
30
+ * `kywi_signals` the signed server-resolved audience signals
31
+ * `kywi_utm` campaign attribution carried across navigation
32
+ * `kywi_audience` the audience the RUNTIME resolved and remembered. A pin
33
+ * the visitor chose by hand in the transparency panel is
34
+ * `essential` instead — see the `source` discussion in
35
+ * `api/audience-runtime-routes.ts`
36
+ * `kywi_known` adapter-pushed known-identity flag
37
+ *
38
+ * Auth/session cookies (the admin's access + refresh cookies, CSRF) are
39
+ * `essential` by definition and deliberately never routed through this gate —
40
+ * they carry no tracking and the admin cannot function without them.
41
+ *
42
+ * ── Undecided means not consented ───────────────────────────────────────────
43
+ *
44
+ * A visitor who has not answered the banner has a null `ConsentState`, and
45
+ * `consentAllows(null, 'personalization')` is FALSE. This matches `hasConsent()`
46
+ * in `@kywi-software/js` and is the compliance-correct default. The consequence
47
+ * is deliberate: until a visitor accepts, personalization cookies are not
48
+ * written and pages degrade to their default (unpersonalized) content. Nothing
49
+ * fails — the request still resolves, the visitor id is still minted for the
50
+ * duration of that request, it just is not persisted.
51
+ *
52
+ * An unmapped cookie name is denied rather than allowed, so adding a new cookie
53
+ * without classifying it here fails closed. A core test asserts every name in
54
+ * `COOKIE_NAMES` appears in the map, so that failure surfaces at test time.
55
+ *
56
+ * ── The escape hatch: personalization.requireConsent ────────────────────────
57
+ *
58
+ * `theme.personalization.requireConsent` (kywi.config.ts) DEFAULTS TO TRUE — the
59
+ * compliant behaviour above. Setting it to `false` turns this gate off entirely:
60
+ * every category reads as allowed, decided or not, and the cookie writes behave
61
+ * as they did before kywi-cms#91. That is for a site whose consent is collected
62
+ * by external tooling (a third-party CMP) which suppresses cookies its own way;
63
+ * the site takes responsibility for compliance, and Kywi stops second-guessing
64
+ * it. It is NOT a way to opt out of consent — turning it off on a site with no
65
+ * other consent mechanism is the non-compliant configuration this issue existed
66
+ * to fix.
67
+ *
68
+ * Every gate function takes the flag through a `ConsentGateOptions` bag rather
69
+ * than reading config itself, because this module must stay dependency-free
70
+ * (see below). `personalizationRequiresConsent()` in `./consent-config.ts`
71
+ * resolves it from a `KywiConfig`; the edge middleware, which cannot import an
72
+ * app's config at all, mirrors it with `KYWI_REQUIRE_CONSENT=false`.
73
+ *
74
+ * EDGE-SAFE LEAF MODULE: this file imports nothing, so it can be pulled into
75
+ * Next.js edge middleware (where core's DB-backed code cannot run) and into
76
+ * `audiences/utm-persistence.ts`, which has the same constraint. It is
77
+ * published as its own export entry (`@kywi-software/core/audiences/consent`).
78
+ * Keep it dependency-free. The browser-only helpers guard on `document`, so
79
+ * importing this on the server or the edge is safe.
80
+ */
81
+ /** The cookie the visitor's consent decision is stored in. */
82
+ export declare const CONSENT_COOKIE = "kywi_consent";
83
+ /** 1 year, in seconds — how long a consent decision is remembered. */
84
+ export declare const CONSENT_MAX_AGE: number;
85
+ /** The cookie an audience pin lives in. */
86
+ export declare const AUDIENCE_PIN_COOKIE = "kywi_audience";
87
+ /**
88
+ * The `kywi_audience` value prefix marking a pin the visitor chose BY HAND in
89
+ * the transparency panel, as opposed to one the runtime remembered on its own.
90
+ *
91
+ * Owned here, in the zero-import leaf, because both halves of the feature need
92
+ * it and neither can import the other: `collectors/pinned-audience.ts` encodes
93
+ * and decodes with it, and `clearDeniedCookies` below must recognise it to avoid
94
+ * sweeping away a preference it is supposed to honour.
95
+ */
96
+ export declare const SWITCHER_PIN_PREFIX = "switcher:";
97
+ export type ConsentCategory = 'essential' | 'analytics' | 'marketing' | 'personalization';
98
+ /** Shared tail argument of every gate function. */
99
+ export interface ConsentGateOptions {
100
+ /**
101
+ * `theme.personalization.requireConsent`. Defaults to true. When explicitly
102
+ * `false` the gate is off and every category reads as allowed — the
103
+ * external-CMP escape hatch described in the file header.
104
+ */
105
+ requireConsent?: boolean;
106
+ }
107
+ export interface ConsentState {
108
+ essential: boolean;
109
+ analytics: boolean;
110
+ marketing: boolean;
111
+ personalization: boolean;
112
+ }
113
+ /**
114
+ * Every cookie the engine writes → the consent category it requires.
115
+ * The single source of truth; see the file header for the reasoning behind
116
+ * each classification.
117
+ */
118
+ export declare const COOKIE_CONSENT_CATEGORY: {
119
+ readonly kywi_consent: "essential";
120
+ readonly kywi_optout: "essential";
121
+ readonly kywi_preview_init: "essential";
122
+ readonly kywi_signals: "personalization";
123
+ readonly kywi_visitor: "personalization";
124
+ readonly kywi_utm: "personalization";
125
+ readonly kywi_audience: "personalization";
126
+ readonly kywi_known: "personalization";
127
+ };
128
+ /**
129
+ * The consent category `cookieName` requires, or `null` when the name is not
130
+ * classified. An unclassified cookie is denied by `cookieAllowed`.
131
+ */
132
+ export declare function consentCategoryFor(cookieName: string): ConsentCategory | null;
133
+ /** Parse a raw `kywi_consent` cookie value. Returns null when absent/malformed. */
134
+ export declare function parseConsentValue(raw: string | null | undefined): ConsentState | null;
135
+ /**
136
+ * Read the consent decision out of a request's `Cookie` header.
137
+ * Returns null when the header is absent or carries no usable decision.
138
+ *
139
+ * A header can legitimately carry the same cookie name twice — most often a
140
+ * `Path=/` cookie shadowed by a narrower one from an earlier deploy. Taking the
141
+ * first match and giving up if it will not parse would throw away a perfectly
142
+ * good decision sitting right behind a corrupt one, so keep looking.
143
+ */
144
+ export declare function readConsentFromCookieHeader(header: string | null | undefined): ConsentState | null;
145
+ /**
146
+ * Is `category` granted by `state`? `essential` is always granted — necessary
147
+ * cookies need no consent. Every other category requires an explicit `true`,
148
+ * so an undecided visitor (null state) grants nothing.
149
+ */
150
+ export declare function consentAllows(state: ConsentState | null, category: ConsentCategory, options?: ConsentGateOptions): boolean;
151
+ /**
152
+ * The gate: may `cookieName` be written given `state`? Unclassified cookie
153
+ * names fail closed — unless the gate itself is off.
154
+ */
155
+ export declare function cookieAllowed(cookieName: string, state: ConsentState | null, options?: ConsentGateOptions): boolean;
156
+ /** Convenience for request handlers: gate `cookieName` against a `Cookie` header. */
157
+ export declare function cookieAllowedByHeader(cookieName: string, header: string | null | undefined, options?: ConsentGateOptions): boolean;
158
+ /** Every cookie name classified into `category`. */
159
+ export declare function cookiesInCategory(category: ConsentCategory): string[];
160
+ /**
161
+ * Delete every cookie whose category `state` does not grant, and return the
162
+ * names deleted.
163
+ *
164
+ * Refusing to WRITE new cookies is only half of "Reject All" — a visitor who
165
+ * accepted last month and rejects today is still carrying a `kywi_visitor` id,
166
+ * and a gate that only blocks writes would keep reading it forever. So a
167
+ * decision revokes as well as denies (kywi-cms#91).
168
+ *
169
+ * `kywi_signals` is HttpOnly and cannot be removed from script; the attempt is
170
+ * harmless and the server stops writing it, after which it expires on its own
171
+ * 60-second horizon. The server-side read paths ALSO ignore personalization
172
+ * cookies whenever the gate denies, so a cookie script cannot clear is inert
173
+ * either way.
174
+ *
175
+ * No-op off the browser.
176
+ */
177
+ export declare function clearDeniedCookies(state: ConsentState | null): string[];
178
+ /** Read the visitor's consent decision from `document.cookie`, or null. */
179
+ export declare function getConsentState(): ConsentState | null;
180
+ /**
181
+ * Record a consent decision. `essential` is always forced true — the visitor
182
+ * cannot decline necessary cookies, and the banner renders that checkbox
183
+ * checked and disabled to say so. Returns the state written.
184
+ *
185
+ * Any category the decision denies is REVOKED at the same time: see
186
+ * `clearDeniedCookies`. Rejecting is not just "stop writing", it is "and delete
187
+ * what you already wrote".
188
+ */
189
+ export declare function setConsent(prefs: Partial<Omit<ConsentState, 'essential'>>): ConsentState;
190
+ /** Has the visitor granted `category`? See `consentAllows` for the semantics. */
191
+ export declare function hasConsent(category: ConsentCategory, options?: ConsentGateOptions): boolean;
192
+ //# sourceMappingURL=consent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consent.d.ts","sourceRoot":"","sources":["../../src/audiences/consent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AAEH,8DAA8D;AAC9D,eAAO,MAAM,cAAc,iBAAiB,CAAA;AAE5C,sEAAsE;AACtE,eAAO,MAAM,eAAe,QAAkB,CAAA;AAE9C,2CAA2C;AAC3C,eAAO,MAAM,mBAAmB,kBAAkB,CAAA;AAElD;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,cAAc,CAAA;AAE9C,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,iBAAiB,CAAA;AAEzF,mDAAmD;AACnD,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;IAClB,eAAe,EAAE,OAAO,CAAA;CACzB;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;CASgB,CAAA;AAEpD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAE7E;AAED,mFAAmF;AACnF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,YAAY,GAAG,IAAI,CAsBrF;AAED;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,YAAY,GAAG,IAAI,CAWlG;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,YAAY,GAAG,IAAI,EAC1B,QAAQ,EAAE,eAAe,EACzB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAKT;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,YAAY,GAAG,IAAI,EAC1B,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAOT;AAED,qFAAqF;AACrF,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACjC,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAET;AAED,oDAAoD;AACpD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,EAAE,CAIrE;AAID;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,GAAG,MAAM,EAAE,CAUvE;AAsCD,2EAA2E;AAC3E,wBAAgB,eAAe,IAAI,YAAY,GAAG,IAAI,CAGrD;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,GAAG,YAAY,CAiBxF;AAED,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAE/F"}
@@ -0,0 +1,322 @@
1
+ /**
2
+ * Cookie consent — the category map, and the gate every optional cookie write
3
+ * passes through (kywi-cms#91).
4
+ *
5
+ * Before this module the `cookieConsent` layout module and the `kywi_consent`
6
+ * cookie were two halves of a feature that never met: the banner's buttons had
7
+ * no handlers, and no cookie-writing code path ever asked whether the visitor
8
+ * had consented. This file is the join. It owns three things:
9
+ *
10
+ * 1. `COOKIE_CONSENT_CATEGORY` — the SINGLE SOURCE OF TRUTH mapping every
11
+ * cookie the engine writes to the consent category it needs. Nothing else
12
+ * in the codebase may decide a cookie's category.
13
+ * 2. `cookieAllowed()` / `consentAllows()` — the gate. Every optional cookie
14
+ * write calls one of these first.
15
+ * 3. The browser-side read/write of the `kywi_consent` cookie itself, used by
16
+ * the `cookieConsent` layout module's buttons.
17
+ *
18
+ * ── Category decisions (owner-set) ──────────────────────────────────────────
19
+ *
20
+ * necessary / `essential` — always allowed, never gated:
21
+ * `kywi_consent` the consent record itself
22
+ * `kywi_optout` the personalization opt-out flag: a *suppression*
23
+ * preference. Blocking a visitor from recording "stop
24
+ * personalizing me" until they consent to cookies would
25
+ * be perverse, so this is necessary by construction.
26
+ * `kywi_preview_init` admin preview hand-off, not visitor tracking.
27
+ *
28
+ * `personalization` — gated:
29
+ * `kywi_visitor` visitor id, incl. experiment bucketing / exposure
30
+ * `kywi_signals` the signed server-resolved audience signals
31
+ * `kywi_utm` campaign attribution carried across navigation
32
+ * `kywi_audience` the audience the RUNTIME resolved and remembered. A pin
33
+ * the visitor chose by hand in the transparency panel is
34
+ * `essential` instead — see the `source` discussion in
35
+ * `api/audience-runtime-routes.ts`
36
+ * `kywi_known` adapter-pushed known-identity flag
37
+ *
38
+ * Auth/session cookies (the admin's access + refresh cookies, CSRF) are
39
+ * `essential` by definition and deliberately never routed through this gate —
40
+ * they carry no tracking and the admin cannot function without them.
41
+ *
42
+ * ── Undecided means not consented ───────────────────────────────────────────
43
+ *
44
+ * A visitor who has not answered the banner has a null `ConsentState`, and
45
+ * `consentAllows(null, 'personalization')` is FALSE. This matches `hasConsent()`
46
+ * in `@kywi-software/js` and is the compliance-correct default. The consequence
47
+ * is deliberate: until a visitor accepts, personalization cookies are not
48
+ * written and pages degrade to their default (unpersonalized) content. Nothing
49
+ * fails — the request still resolves, the visitor id is still minted for the
50
+ * duration of that request, it just is not persisted.
51
+ *
52
+ * An unmapped cookie name is denied rather than allowed, so adding a new cookie
53
+ * without classifying it here fails closed. A core test asserts every name in
54
+ * `COOKIE_NAMES` appears in the map, so that failure surfaces at test time.
55
+ *
56
+ * ── The escape hatch: personalization.requireConsent ────────────────────────
57
+ *
58
+ * `theme.personalization.requireConsent` (kywi.config.ts) DEFAULTS TO TRUE — the
59
+ * compliant behaviour above. Setting it to `false` turns this gate off entirely:
60
+ * every category reads as allowed, decided or not, and the cookie writes behave
61
+ * as they did before kywi-cms#91. That is for a site whose consent is collected
62
+ * by external tooling (a third-party CMP) which suppresses cookies its own way;
63
+ * the site takes responsibility for compliance, and Kywi stops second-guessing
64
+ * it. It is NOT a way to opt out of consent — turning it off on a site with no
65
+ * other consent mechanism is the non-compliant configuration this issue existed
66
+ * to fix.
67
+ *
68
+ * Every gate function takes the flag through a `ConsentGateOptions` bag rather
69
+ * than reading config itself, because this module must stay dependency-free
70
+ * (see below). `personalizationRequiresConsent()` in `./consent-config.ts`
71
+ * resolves it from a `KywiConfig`; the edge middleware, which cannot import an
72
+ * app's config at all, mirrors it with `KYWI_REQUIRE_CONSENT=false`.
73
+ *
74
+ * EDGE-SAFE LEAF MODULE: this file imports nothing, so it can be pulled into
75
+ * Next.js edge middleware (where core's DB-backed code cannot run) and into
76
+ * `audiences/utm-persistence.ts`, which has the same constraint. It is
77
+ * published as its own export entry (`@kywi-software/core/audiences/consent`).
78
+ * Keep it dependency-free. The browser-only helpers guard on `document`, so
79
+ * importing this on the server or the edge is safe.
80
+ */
81
+ /** The cookie the visitor's consent decision is stored in. */
82
+ export const CONSENT_COOKIE = 'kywi_consent';
83
+ /** 1 year, in seconds — how long a consent decision is remembered. */
84
+ export const CONSENT_MAX_AGE = 365 * 24 * 3600;
85
+ /** The cookie an audience pin lives in. */
86
+ export const AUDIENCE_PIN_COOKIE = 'kywi_audience';
87
+ /**
88
+ * The `kywi_audience` value prefix marking a pin the visitor chose BY HAND in
89
+ * the transparency panel, as opposed to one the runtime remembered on its own.
90
+ *
91
+ * Owned here, in the zero-import leaf, because both halves of the feature need
92
+ * it and neither can import the other: `collectors/pinned-audience.ts` encodes
93
+ * and decodes with it, and `clearDeniedCookies` below must recognise it to avoid
94
+ * sweeping away a preference it is supposed to honour.
95
+ */
96
+ export const SWITCHER_PIN_PREFIX = 'switcher:';
97
+ /**
98
+ * Every cookie the engine writes → the consent category it requires.
99
+ * The single source of truth; see the file header for the reasoning behind
100
+ * each classification.
101
+ */
102
+ export const COOKIE_CONSENT_CATEGORY = {
103
+ kywi_consent: 'essential',
104
+ kywi_optout: 'essential',
105
+ kywi_preview_init: 'essential',
106
+ kywi_signals: 'personalization',
107
+ kywi_visitor: 'personalization',
108
+ kywi_utm: 'personalization',
109
+ kywi_audience: 'personalization',
110
+ kywi_known: 'personalization',
111
+ };
112
+ /**
113
+ * The consent category `cookieName` requires, or `null` when the name is not
114
+ * classified. An unclassified cookie is denied by `cookieAllowed`.
115
+ */
116
+ export function consentCategoryFor(cookieName) {
117
+ return COOKIE_CONSENT_CATEGORY[cookieName] ?? null;
118
+ }
119
+ /** Parse a raw `kywi_consent` cookie value. Returns null when absent/malformed. */
120
+ export function parseConsentValue(raw) {
121
+ if (!raw)
122
+ return null;
123
+ let text = raw;
124
+ try {
125
+ text = decodeURIComponent(raw);
126
+ }
127
+ catch {
128
+ /* malformed escape — fall through with the raw value */
129
+ }
130
+ let parsed;
131
+ try {
132
+ parsed = JSON.parse(text);
133
+ }
134
+ catch {
135
+ return null;
136
+ }
137
+ if (typeof parsed !== 'object' || parsed === null)
138
+ return null;
139
+ const obj = parsed;
140
+ return {
141
+ essential: true,
142
+ analytics: obj.analytics === true,
143
+ marketing: obj.marketing === true,
144
+ personalization: obj.personalization === true,
145
+ };
146
+ }
147
+ /**
148
+ * Read the consent decision out of a request's `Cookie` header.
149
+ * Returns null when the header is absent or carries no usable decision.
150
+ *
151
+ * A header can legitimately carry the same cookie name twice — most often a
152
+ * `Path=/` cookie shadowed by a narrower one from an earlier deploy. Taking the
153
+ * first match and giving up if it will not parse would throw away a perfectly
154
+ * good decision sitting right behind a corrupt one, so keep looking.
155
+ */
156
+ export function readConsentFromCookieHeader(header) {
157
+ if (!header)
158
+ return null;
159
+ for (const pair of header.split(';')) {
160
+ const trimmed = pair.trim();
161
+ const eqIdx = trimmed.indexOf('=');
162
+ if (eqIdx < 0)
163
+ continue;
164
+ if (trimmed.slice(0, eqIdx) !== CONSENT_COOKIE)
165
+ continue;
166
+ const state = parseConsentValue(trimmed.slice(eqIdx + 1));
167
+ if (state)
168
+ return state;
169
+ }
170
+ return null;
171
+ }
172
+ /**
173
+ * Is `category` granted by `state`? `essential` is always granted — necessary
174
+ * cookies need no consent. Every other category requires an explicit `true`,
175
+ * so an undecided visitor (null state) grants nothing.
176
+ */
177
+ export function consentAllows(state, category, options = {}) {
178
+ if (options.requireConsent === false)
179
+ return true;
180
+ if (category === 'essential')
181
+ return true;
182
+ if (!state)
183
+ return false;
184
+ return state[category] === true;
185
+ }
186
+ /**
187
+ * The gate: may `cookieName` be written given `state`? Unclassified cookie
188
+ * names fail closed — unless the gate itself is off.
189
+ */
190
+ export function cookieAllowed(cookieName, state, options = {}) {
191
+ // With the gate off there is nothing to classify against — the site's own
192
+ // tooling decides, including for a cookie this map has never heard of.
193
+ if (options.requireConsent === false)
194
+ return true;
195
+ const category = consentCategoryFor(cookieName);
196
+ if (category === null)
197
+ return false;
198
+ return consentAllows(state, category);
199
+ }
200
+ /** Convenience for request handlers: gate `cookieName` against a `Cookie` header. */
201
+ export function cookieAllowedByHeader(cookieName, header, options = {}) {
202
+ return cookieAllowed(cookieName, readConsentFromCookieHeader(header), options);
203
+ }
204
+ /** Every cookie name classified into `category`. */
205
+ export function cookiesInCategory(category) {
206
+ return Object.entries(COOKIE_CONSENT_CATEGORY)
207
+ .filter(([, c]) => c === category)
208
+ .map(([name]) => name);
209
+ }
210
+ /* ── browser side: the cookieConsent module's read/write ─────────────────── */
211
+ /**
212
+ * Delete every cookie whose category `state` does not grant, and return the
213
+ * names deleted.
214
+ *
215
+ * Refusing to WRITE new cookies is only half of "Reject All" — a visitor who
216
+ * accepted last month and rejects today is still carrying a `kywi_visitor` id,
217
+ * and a gate that only blocks writes would keep reading it forever. So a
218
+ * decision revokes as well as denies (kywi-cms#91).
219
+ *
220
+ * `kywi_signals` is HttpOnly and cannot be removed from script; the attempt is
221
+ * harmless and the server stops writing it, after which it expires on its own
222
+ * 60-second horizon. The server-side read paths ALSO ignore personalization
223
+ * cookies whenever the gate denies, so a cookie script cannot clear is inert
224
+ * either way.
225
+ *
226
+ * No-op off the browser.
227
+ */
228
+ export function clearDeniedCookies(state) {
229
+ if (typeof document === 'undefined')
230
+ return [];
231
+ const deleted = [];
232
+ for (const [name, category] of Object.entries(COOKIE_CONSENT_CATEGORY)) {
233
+ if (consentAllows(state, category))
234
+ continue;
235
+ if (isDeliberatePreference(name, rawCookie(name)))
236
+ continue;
237
+ document.cookie = `${name}=; Path=/; Max-Age=0`;
238
+ deleted.push(name);
239
+ }
240
+ return deleted;
241
+ }
242
+ /** The raw (decoded) value of one cookie, or undefined. Browser-only. */
243
+ function rawCookie(name) {
244
+ if (typeof document === 'undefined')
245
+ return undefined;
246
+ for (const pair of document.cookie.split(';')) {
247
+ const trimmed = pair.trim();
248
+ const eqIdx = trimmed.indexOf('=');
249
+ if (eqIdx < 0 || trimmed.slice(0, eqIdx) !== name)
250
+ continue;
251
+ const raw = trimmed.slice(eqIdx + 1);
252
+ if (raw === '')
253
+ return undefined;
254
+ try {
255
+ return decodeURIComponent(raw);
256
+ }
257
+ catch {
258
+ return raw;
259
+ }
260
+ }
261
+ return undefined;
262
+ }
263
+ /**
264
+ * Does this cookie's CURRENT VALUE mark it as an explicit visitor preference
265
+ * that outranks its category?
266
+ *
267
+ * `kywi_audience` is the one cookie whose category depends on how it was
268
+ * written: automatic ("remember what I resolved") is `personalization`, but an
269
+ * audience the visitor picked by hand in the transparency panel is `essential`,
270
+ * on the same argument as `kywi_optout`. The category map is static and cannot
271
+ * express that, so the sweep asks the value.
272
+ *
273
+ * Without this, rejecting personalization would delete a choice the visitor made
274
+ * deliberately and which the server is under orders to keep honouring — the
275
+ * revocation would quietly undo the exemption.
276
+ */
277
+ function isDeliberatePreference(name, value) {
278
+ if (name !== AUDIENCE_PIN_COOKIE || value === undefined)
279
+ return false;
280
+ // The prefix alone is not a pin — `switcher:` with no id decodes to nothing
281
+ // (parseAudiencePin rejects it), so exempting it would strand a cookie nobody
282
+ // will ever honour.
283
+ return value.startsWith(SWITCHER_PIN_PREFIX) && value.length > SWITCHER_PIN_PREFIX.length;
284
+ }
285
+ /** Read the visitor's consent decision from `document.cookie`, or null. */
286
+ export function getConsentState() {
287
+ if (typeof document === 'undefined')
288
+ return null;
289
+ return readConsentFromCookieHeader(document.cookie);
290
+ }
291
+ /**
292
+ * Record a consent decision. `essential` is always forced true — the visitor
293
+ * cannot decline necessary cookies, and the banner renders that checkbox
294
+ * checked and disabled to say so. Returns the state written.
295
+ *
296
+ * Any category the decision denies is REVOKED at the same time: see
297
+ * `clearDeniedCookies`. Rejecting is not just "stop writing", it is "and delete
298
+ * what you already wrote".
299
+ */
300
+ export function setConsent(prefs) {
301
+ const state = {
302
+ essential: true,
303
+ analytics: prefs.analytics === true,
304
+ marketing: prefs.marketing === true,
305
+ personalization: prefs.personalization === true,
306
+ };
307
+ if (typeof document !== 'undefined') {
308
+ document.cookie =
309
+ `${CONSENT_COOKIE}=${encodeURIComponent(JSON.stringify(state))}` +
310
+ `; Path=/; Max-Age=${CONSENT_MAX_AGE}; SameSite=Lax`;
311
+ // A decision REVOKES as well as denies: cookies from an earlier, more
312
+ // permissive answer are removed here rather than lingering until they
313
+ // expire. Written first so the consent record survives its own sweep.
314
+ clearDeniedCookies(state);
315
+ }
316
+ return state;
317
+ }
318
+ /** Has the visitor granted `category`? See `consentAllows` for the semantics. */
319
+ export function hasConsent(category, options = {}) {
320
+ return consentAllows(getConsentState(), category, options);
321
+ }
322
+ //# sourceMappingURL=consent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consent.js","sourceRoot":"","sources":["../../src/audiences/consent.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,13 @@
1
1
  import type { VisitorContext, AudienceResult, Audience } from './types.js';
2
2
  export interface AudienceEngineConfig {
3
3
  audiences: Audience[];
4
+ /**
5
+ * `theme.personalization.requireConsent` (kywi-cms#91). Defaults to true —
6
+ * personalization cookies are neither written nor READ for a visitor who has
7
+ * not consented, so a stale id from an earlier "accept" cannot keep resolving
8
+ * them after they reject.
9
+ */
10
+ requireConsent?: boolean;
4
11
  }
5
12
  export interface AudienceEngine {
6
13
  evaluate(context: VisitorContext): Promise<AudienceResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/audiences/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAM1F,MAAM,WAAW,oBAAoB;IAAG,SAAS,EAAE,QAAQ,EAAE,CAAA;CAAE;AAC/D,MAAM,WAAW,cAAc;IAAG,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAAA;CAAE;AAe9F,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,GAAG,cAAc,CA4BjF"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/audiences/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAM1F,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AACD,MAAM,WAAW,cAAc;IAAG,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAAA;CAAE;AAe9F,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,GAAG,cAAc,CAiCjF"}