@open-mercato/core 0.8.1-develop.7296.1.2111d779db → 0.9.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 (2352) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/AGENTS.md +4 -5
  3. package/dist/generated/entities/availability_policy/index.js +41 -0
  4. package/dist/generated/entities/availability_policy/index.js.map +7 -0
  5. package/dist/generated/entities/communication_channel/index.js +3 -1
  6. package/dist/generated/entities/communication_channel/index.js.map +2 -2
  7. package/dist/generated/entities/customer_email_conversation_share/index.js +21 -0
  8. package/dist/generated/entities/customer_email_conversation_share/index.js.map +7 -0
  9. package/dist/generated/entities/customer_group/index.js +33 -0
  10. package/dist/generated/entities/customer_group/index.js.map +7 -0
  11. package/dist/generated/entities/customer_group_membership/index.js +29 -0
  12. package/dist/generated/entities/customer_group_membership/index.js.map +7 -0
  13. package/dist/generated/entities/customer_group_terms/index.js +33 -0
  14. package/dist/generated/entities/customer_group_terms/index.js.map +7 -0
  15. package/dist/generated/entities/customer_interaction/index.js +2 -0
  16. package/dist/generated/entities/customer_interaction/index.js.map +2 -2
  17. package/dist/generated/entities/form/index.js +35 -0
  18. package/dist/generated/entities/form/index.js.map +7 -0
  19. package/dist/generated/entities/form_access_audit/index.js +21 -0
  20. package/dist/generated/entities/form_access_audit/index.js.map +7 -0
  21. package/dist/generated/entities/form_attachment/index.js +29 -0
  22. package/dist/generated/entities/form_attachment/index.js.map +7 -0
  23. package/dist/generated/entities/form_consent_record/index.js +37 -0
  24. package/dist/generated/entities/form_consent_record/index.js.map +7 -0
  25. package/dist/generated/entities/form_distribution/index.js +47 -0
  26. package/dist/generated/entities/form_distribution/index.js.map +7 -0
  27. package/dist/generated/entities/form_invitation/index.js +49 -0
  28. package/dist/generated/entities/form_invitation/index.js.map +7 -0
  29. package/dist/generated/entities/form_submission/index.js +39 -0
  30. package/dist/generated/entities/form_submission/index.js.map +7 -0
  31. package/dist/generated/entities/form_submission_actor/index.js +23 -0
  32. package/dist/generated/entities/form_submission_actor/index.js.map +7 -0
  33. package/dist/generated/entities/form_submission_revision/index.js +29 -0
  34. package/dist/generated/entities/form_submission_revision/index.js.map +7 -0
  35. package/dist/generated/entities/form_version/index.js +37 -0
  36. package/dist/generated/entities/form_version/index.js.map +7 -0
  37. package/dist/generated/entities/forms_encryption_key/index.js +15 -0
  38. package/dist/generated/entities/forms_encryption_key/index.js.map +7 -0
  39. package/dist/generated/entities.ids.generated.js +27 -2
  40. package/dist/generated/entities.ids.generated.js.map +2 -2
  41. package/dist/generated/entity-fields-registry.js +269 -0
  42. package/dist/generated/entity-fields-registry.js.map +2 -2
  43. package/dist/helpers/integration/communicationChannelsFixtures.js +16 -0
  44. package/dist/helpers/integration/communicationChannelsFixtures.js.map +2 -2
  45. package/dist/helpers/integration/customerGroupsFixtures.js +88 -0
  46. package/dist/helpers/integration/customerGroupsFixtures.js.map +7 -0
  47. package/dist/helpers/integration/formsFixtures.js +448 -0
  48. package/dist/helpers/integration/formsFixtures.js.map +7 -0
  49. package/dist/modules/api_docs/api/get/version.js +19 -7
  50. package/dist/modules/api_docs/api/get/version.js.map +2 -2
  51. package/dist/modules/api_keys/api/keys/route.js +74 -169
  52. package/dist/modules/api_keys/api/keys/route.js.map +2 -2
  53. package/dist/modules/api_keys/backend/api-keys/create/page.js +1 -1
  54. package/dist/modules/api_keys/backend/api-keys/create/page.js.map +2 -2
  55. package/dist/modules/api_keys/commands/keys.js +140 -0
  56. package/dist/modules/api_keys/commands/keys.js.map +7 -0
  57. package/dist/modules/api_keys/services/apiKeyService.js +72 -43
  58. package/dist/modules/api_keys/services/apiKeyService.js.map +2 -2
  59. package/dist/modules/attachments/api/file/[id]/route.js +9 -2
  60. package/dist/modules/attachments/api/file/[id]/route.js.map +2 -2
  61. package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js +6 -2
  62. package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js.map +2 -2
  63. package/dist/modules/attachments/api/route.js +10 -4
  64. package/dist/modules/attachments/api/route.js.map +2 -2
  65. package/dist/modules/attachments/components/AttachmentLibrary.js +16 -6
  66. package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
  67. package/dist/modules/attachments/lib/access.js +1 -3
  68. package/dist/modules/attachments/lib/access.js.map +2 -2
  69. package/dist/modules/attachments/lib/requestScope.js +13 -4
  70. package/dist/modules/attachments/lib/requestScope.js.map +2 -2
  71. package/dist/modules/audit_logs/api/audit-logs/actions/export/route.js +6 -1
  72. package/dist/modules/audit_logs/api/audit-logs/actions/export/route.js.map +2 -2
  73. package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js +36 -6
  74. package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js.map +3 -3
  75. package/dist/modules/audit_logs/api/audit-logs/actions/route.js +6 -1
  76. package/dist/modules/audit_logs/api/audit-logs/actions/route.js.map +2 -2
  77. package/dist/modules/audit_logs/api/audit-logs/actions/undo/route.js +34 -4
  78. package/dist/modules/audit_logs/api/audit-logs/actions/undo/route.js.map +2 -2
  79. package/dist/modules/audit_logs/data/validators.js +1 -0
  80. package/dist/modules/audit_logs/data/validators.js.map +2 -2
  81. package/dist/modules/audit_logs/lib/actorSubject.js +65 -0
  82. package/dist/modules/audit_logs/lib/actorSubject.js.map +7 -0
  83. package/dist/modules/audit_logs/lib/replayAuthorization.js +41 -0
  84. package/dist/modules/audit_logs/lib/replayAuthorization.js.map +7 -0
  85. package/dist/modules/audit_logs/services/actionLogService.js +162 -39
  86. package/dist/modules/audit_logs/services/actionLogService.js.map +3 -3
  87. package/dist/modules/auth/api/features.js +1 -1
  88. package/dist/modules/auth/api/features.js.map +2 -2
  89. package/dist/modules/auth/cli.js +29 -17
  90. package/dist/modules/auth/cli.js.map +2 -2
  91. package/dist/modules/auth/commands/acl.js +25 -36
  92. package/dist/modules/auth/commands/acl.js.map +2 -2
  93. package/dist/modules/auth/commands/interceptors.js +22 -0
  94. package/dist/modules/auth/commands/interceptors.js.map +7 -0
  95. package/dist/modules/auth/commands/roles.js +421 -147
  96. package/dist/modules/auth/commands/roles.js.map +2 -2
  97. package/dist/modules/auth/commands/users.js +543 -69
  98. package/dist/modules/auth/commands/users.js.map +2 -2
  99. package/dist/modules/auth/lib/authorizationStateLocks.js +249 -0
  100. package/dist/modules/auth/lib/authorizationStateLocks.js.map +7 -0
  101. package/dist/modules/auth/lib/commandReplay.js +144 -0
  102. package/dist/modules/auth/lib/commandReplay.js.map +7 -0
  103. package/dist/modules/auth/lib/executionPrincipal.js +32 -25
  104. package/dist/modules/auth/lib/executionPrincipal.js.map +2 -2
  105. package/dist/modules/auth/lib/grantChecks.js +7 -2
  106. package/dist/modules/auth/lib/grantChecks.js.map +2 -2
  107. package/dist/modules/auth/lib/setup-app.js +85 -49
  108. package/dist/modules/auth/lib/setup-app.js.map +2 -2
  109. package/dist/modules/auth/lib/tokenHash.js +13 -1
  110. package/dist/modules/auth/lib/tokenHash.js.map +2 -2
  111. package/dist/modules/auth/services/rbacService.js +386 -5
  112. package/dist/modules/auth/services/rbacService.js.map +3 -3
  113. package/dist/modules/availability/acl.js +16 -0
  114. package/dist/modules/availability/acl.js.map +7 -0
  115. package/dist/modules/availability/api/check/route.js +115 -0
  116. package/dist/modules/availability/api/check/route.js.map +7 -0
  117. package/dist/modules/availability/api/openapi.js +27 -0
  118. package/dist/modules/availability/api/openapi.js.map +7 -0
  119. package/dist/modules/availability/api/policies/resolve-preview/route.js +72 -0
  120. package/dist/modules/availability/api/policies/resolve-preview/route.js.map +7 -0
  121. package/dist/modules/availability/api/policies/route.js +203 -0
  122. package/dist/modules/availability/api/policies/route.js.map +7 -0
  123. package/dist/modules/availability/backend/availability/check/page.js +186 -0
  124. package/dist/modules/availability/backend/availability/check/page.js.map +7 -0
  125. package/dist/modules/availability/backend/availability/check/page.meta.js +16 -0
  126. package/dist/modules/availability/backend/availability/check/page.meta.js.map +7 -0
  127. package/dist/modules/availability/backend/availability/policies/ResolutionPreviewPanel.js +83 -0
  128. package/dist/modules/availability/backend/availability/policies/ResolutionPreviewPanel.js.map +7 -0
  129. package/dist/modules/availability/backend/availability/policies/ScopeFields.js +53 -0
  130. package/dist/modules/availability/backend/availability/policies/ScopeFields.js.map +7 -0
  131. package/dist/modules/availability/backend/availability/policies/StockManagedField.js +32 -0
  132. package/dist/modules/availability/backend/availability/policies/StockManagedField.js.map +7 -0
  133. package/dist/modules/availability/backend/availability/policies/[id]/page.js +168 -0
  134. package/dist/modules/availability/backend/availability/policies/[id]/page.js.map +7 -0
  135. package/dist/modules/availability/backend/availability/policies/[id]/page.meta.js +12 -0
  136. package/dist/modules/availability/backend/availability/policies/[id]/page.meta.js.map +7 -0
  137. package/dist/modules/availability/backend/availability/policies/create/page.js +122 -0
  138. package/dist/modules/availability/backend/availability/policies/create/page.js.map +7 -0
  139. package/dist/modules/availability/backend/availability/policies/create/page.meta.js +12 -0
  140. package/dist/modules/availability/backend/availability/policies/create/page.meta.js.map +7 -0
  141. package/dist/modules/availability/backend/availability/policies/formGroups.js +77 -0
  142. package/dist/modules/availability/backend/availability/policies/formGroups.js.map +7 -0
  143. package/dist/modules/availability/backend/availability/policies/page.js +207 -0
  144. package/dist/modules/availability/backend/availability/policies/page.js.map +7 -0
  145. package/dist/modules/availability/backend/availability/policies/page.meta.js +16 -0
  146. package/dist/modules/availability/backend/availability/policies/page.meta.js.map +7 -0
  147. package/dist/modules/availability/backend/availability/policies/policyPayload.js +28 -0
  148. package/dist/modules/availability/backend/availability/policies/policyPayload.js.map +7 -0
  149. package/dist/modules/availability/commands/policies.js +364 -0
  150. package/dist/modules/availability/commands/policies.js.map +7 -0
  151. package/dist/modules/availability/commands/scope.js +19 -0
  152. package/dist/modules/availability/commands/scope.js.map +7 -0
  153. package/dist/modules/availability/data/entities.js +94 -0
  154. package/dist/modules/availability/data/entities.js.map +7 -0
  155. package/dist/modules/availability/data/validators.js +59 -0
  156. package/dist/modules/availability/data/validators.js.map +7 -0
  157. package/dist/modules/availability/di.js +50 -0
  158. package/dist/modules/availability/di.js.map +7 -0
  159. package/dist/modules/availability/events.js +18 -0
  160. package/dist/modules/availability/events.js.map +7 -0
  161. package/dist/modules/availability/index.js +15 -0
  162. package/dist/modules/availability/index.js.map +7 -0
  163. package/dist/modules/availability/lib/catalogTarget.js +42 -0
  164. package/dist/modules/availability/lib/catalogTarget.js.map +7 -0
  165. package/dist/modules/availability/lib/organizationScope.js +33 -0
  166. package/dist/modules/availability/lib/organizationScope.js.map +7 -0
  167. package/dist/modules/availability/lib/policyResolution.js +150 -0
  168. package/dist/modules/availability/lib/policyResolution.js.map +7 -0
  169. package/dist/modules/availability/lib/tryResolve.js +11 -0
  170. package/dist/modules/availability/lib/tryResolve.js.map +7 -0
  171. package/dist/modules/availability/migrations/Migration20260922095844_availability.js +16 -0
  172. package/dist/modules/availability/migrations/Migration20260922095844_availability.js.map +7 -0
  173. package/dist/modules/availability/migrations/Migration20260930120000_availability.js +20 -0
  174. package/dist/modules/availability/migrations/Migration20260930120000_availability.js.map +7 -0
  175. package/dist/modules/availability/setup.js +12 -0
  176. package/dist/modules/availability/setup.js.map +7 -0
  177. package/dist/modules/catalog/api/categories/bulk-create/route.js +124 -0
  178. package/dist/modules/catalog/api/categories/bulk-create/route.js.map +7 -0
  179. package/dist/modules/catalog/api/categories/route.js +56 -8
  180. package/dist/modules/catalog/api/categories/route.js.map +2 -2
  181. package/dist/modules/catalog/api/products/bulk-create/route.js +124 -0
  182. package/dist/modules/catalog/api/products/bulk-create/route.js.map +7 -0
  183. package/dist/modules/catalog/api/products/route.js +55 -31
  184. package/dist/modules/catalog/api/products/route.js.map +3 -3
  185. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +3 -6
  186. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  187. package/dist/modules/catalog/backend/catalog/products/create/page.js +12 -4
  188. package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
  189. package/dist/modules/catalog/commands/categories.js +1 -0
  190. package/dist/modules/catalog/commands/categories.js.map +2 -2
  191. package/dist/modules/catalog/commands/products.js +5 -2
  192. package/dist/modules/catalog/commands/products.js.map +2 -2
  193. package/dist/modules/catalog/components/PriceKindSettings.js +5 -19
  194. package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
  195. package/dist/modules/catalog/components/prices/PriceScopeSelectors.js +2 -2
  196. package/dist/modules/catalog/components/prices/PriceScopeSelectors.js.map +2 -2
  197. package/dist/modules/catalog/components/products/ProductUomSection.js +26 -29
  198. package/dist/modules/catalog/components/products/ProductUomSection.js.map +2 -2
  199. package/dist/modules/catalog/components/products/productForm.js +3 -2
  200. package/dist/modules/catalog/components/products/productForm.js.map +2 -2
  201. package/dist/modules/catalog/data/validators.js +15 -0
  202. package/dist/modules/catalog/data/validators.js.map +2 -2
  203. package/dist/modules/catalog/di.js +3 -2
  204. package/dist/modules/catalog/di.js.map +2 -2
  205. package/dist/modules/catalog/events.js +9 -3
  206. package/dist/modules/catalog/events.js.map +2 -2
  207. package/dist/modules/catalog/lib/bulkCreateCategories.js +237 -0
  208. package/dist/modules/catalog/lib/bulkCreateCategories.js.map +7 -0
  209. package/dist/modules/catalog/lib/bulkCreateCheckpoint.js +82 -0
  210. package/dist/modules/catalog/lib/bulkCreateCheckpoint.js.map +7 -0
  211. package/dist/modules/catalog/lib/bulkCreateMutationGuards.js +39 -0
  212. package/dist/modules/catalog/lib/bulkCreateMutationGuards.js.map +7 -0
  213. package/dist/modules/catalog/lib/bulkCreateProducts.js +241 -0
  214. package/dist/modules/catalog/lib/bulkCreateProducts.js.map +7 -0
  215. package/dist/modules/catalog/lib/bulkDelete.js +10 -11
  216. package/dist/modules/catalog/lib/bulkDelete.js.map +2 -2
  217. package/dist/modules/catalog/lib/catalogQueue.js +14 -0
  218. package/dist/modules/catalog/lib/catalogQueue.js.map +7 -0
  219. package/dist/modules/catalog/lib/currencyOptions.js +25 -0
  220. package/dist/modules/catalog/lib/currencyOptions.js.map +7 -0
  221. package/dist/modules/catalog/lib/productSearch.js +8 -0
  222. package/dist/modules/catalog/lib/productSearch.js.map +7 -0
  223. package/dist/modules/catalog/lib/seeds.js +2 -42
  224. package/dist/modules/catalog/lib/seeds.js.map +2 -2
  225. package/dist/modules/catalog/lib/unitLabels.js +53 -0
  226. package/dist/modules/catalog/lib/unitLabels.js.map +7 -0
  227. package/dist/modules/catalog/migrations/Migration20260914120000.js +29 -0
  228. package/dist/modules/catalog/migrations/Migration20260914120000.js.map +7 -0
  229. package/dist/modules/catalog/migrations/Migration20260914120100.js +28 -0
  230. package/dist/modules/catalog/migrations/Migration20260914120100.js.map +7 -0
  231. package/dist/modules/catalog/workers/catalog-category-bulk-create.js +40 -0
  232. package/dist/modules/catalog/workers/catalog-category-bulk-create.js.map +7 -0
  233. package/dist/modules/catalog/workers/catalog-product-bulk-create.js +40 -0
  234. package/dist/modules/catalog/workers/catalog-product-bulk-create.js.map +7 -0
  235. package/dist/modules/communication_channels/acl.js +8 -0
  236. package/dist/modules/communication_channels/acl.js.map +2 -2
  237. package/dist/modules/communication_channels/api/get/me/channels/route.js +4 -0
  238. package/dist/modules/communication_channels/api/get/me/channels/route.js.map +2 -2
  239. package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js +22 -0
  240. package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js.map +2 -2
  241. package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js +4 -4
  242. package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js.map +2 -2
  243. package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js +2 -1
  244. package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js.map +2 -2
  245. package/dist/modules/communication_channels/api/post/test-seed/route.js +90 -20
  246. package/dist/modules/communication_channels/api/post/test-seed/route.js.map +3 -3
  247. package/dist/modules/communication_channels/api/put/channels/[id]/visibility/route.js +137 -0
  248. package/dist/modules/communication_channels/api/put/channels/[id]/visibility/route.js.map +7 -0
  249. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +175 -107
  250. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +2 -2
  251. package/dist/modules/communication_channels/commands/ingest-inbound-message.js +2 -1
  252. package/dist/modules/communication_channels/commands/ingest-inbound-message.js.map +2 -2
  253. package/dist/modules/communication_channels/commands/set-channel-visibility.js +88 -0
  254. package/dist/modules/communication_channels/commands/set-channel-visibility.js.map +7 -0
  255. package/dist/modules/communication_channels/data/enrichers.js +18 -9
  256. package/dist/modules/communication_channels/data/enrichers.js.map +2 -2
  257. package/dist/modules/communication_channels/data/entities.js +4 -0
  258. package/dist/modules/communication_channels/data/entities.js.map +2 -2
  259. package/dist/modules/communication_channels/di.js +9 -1
  260. package/dist/modules/communication_channels/di.js.map +2 -2
  261. package/dist/modules/communication_channels/events.js +7 -0
  262. package/dist/modules/communication_channels/events.js.map +2 -2
  263. package/dist/modules/communication_channels/index.js +1 -1
  264. package/dist/modules/communication_channels/index.js.map +1 -1
  265. package/dist/modules/communication_channels/lib/access-control.js +2 -1
  266. package/dist/modules/communication_channels/lib/access-control.js.map +2 -2
  267. package/dist/modules/communication_channels/lib/channel-thread-access.js +60 -0
  268. package/dist/modules/communication_channels/lib/channel-thread-access.js.map +7 -0
  269. package/dist/modules/communication_channels/lib/credential-refresh.js +11 -2
  270. package/dist/modules/communication_channels/lib/credential-refresh.js.map +2 -2
  271. package/dist/modules/communication_channels/lib/inbound-message-origin.js +18 -0
  272. package/dist/modules/communication_channels/lib/inbound-message-origin.js.map +7 -0
  273. package/dist/modules/communication_channels/lib/oauth-state.js +37 -0
  274. package/dist/modules/communication_channels/lib/oauth-state.js.map +2 -2
  275. package/dist/modules/communication_channels/lib/outbound-delivery-intent.js +12 -0
  276. package/dist/modules/communication_channels/lib/outbound-delivery-intent.js.map +7 -0
  277. package/dist/modules/communication_channels/lib/send-as-user.js +1 -1
  278. package/dist/modules/communication_channels/lib/send-as-user.js.map +2 -2
  279. package/dist/modules/communication_channels/migrations/Migration20260825141000_communication_channels.js +14 -0
  280. package/dist/modules/communication_channels/migrations/Migration20260825141000_communication_channels.js.map +7 -0
  281. package/dist/modules/communication_channels/setup.js +6 -2
  282. package/dist/modules/communication_channels/setup.js.map +2 -2
  283. package/dist/modules/communication_channels/subscribers/outbound-bridge.js +8 -2
  284. package/dist/modules/communication_channels/subscribers/outbound-bridge.js.map +2 -2
  285. package/dist/modules/communication_channels/workers/gmail-history-sync.js +1 -1
  286. package/dist/modules/communication_channels/workers/gmail-history-sync.js.map +2 -2
  287. package/dist/modules/communication_channels/workers/poll-channel.js +1 -1
  288. package/dist/modules/communication_channels/workers/poll-channel.js.map +2 -2
  289. package/dist/modules/communication_channels/workers/reaction-processor.js +2 -2
  290. package/dist/modules/communication_channels/workers/reaction-processor.js.map +2 -2
  291. package/dist/modules/configs/api/upgrade-actions/route.js +2 -1
  292. package/dist/modules/configs/api/upgrade-actions/route.js.map +2 -2
  293. package/dist/modules/configs/cli.js +2 -2
  294. package/dist/modules/configs/cli.js.map +2 -2
  295. package/dist/modules/configs/lib/upgrade-actions.js +28 -6
  296. package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
  297. package/dist/modules/configs/services/upgradeActionsService.js +44 -30
  298. package/dist/modules/configs/services/upgradeActionsService.js.map +2 -2
  299. package/dist/modules/currencies/api/currencies/route.js +11 -5
  300. package/dist/modules/currencies/api/currencies/route.js.map +2 -2
  301. package/dist/modules/currencies/api/exchange-rates/route.js +11 -5
  302. package/dist/modules/currencies/api/exchange-rates/route.js.map +2 -2
  303. package/dist/modules/customer_accounts/api/admin/users/[id]/sessions/[sessionId].js +78 -0
  304. package/dist/modules/customer_accounts/api/admin/users/[id]/sessions/[sessionId].js.map +7 -0
  305. package/dist/modules/customer_groups/acl.js +14 -0
  306. package/dist/modules/customer_groups/acl.js.map +7 -0
  307. package/dist/modules/customer_groups/api/customer-groups/[id]/terms/route.js +266 -0
  308. package/dist/modules/customer_groups/api/customer-groups/[id]/terms/route.js.map +7 -0
  309. package/dist/modules/customer_groups/api/customer-groups/crud.js +473 -0
  310. package/dist/modules/customer_groups/api/customer-groups/crud.js.map +7 -0
  311. package/dist/modules/customer_groups/api/customer-groups/explain-terms/route.js +143 -0
  312. package/dist/modules/customer_groups/api/customer-groups/explain-terms/route.js.map +7 -0
  313. package/dist/modules/customer_groups/api/customer-groups/memberships/crud.js +383 -0
  314. package/dist/modules/customer_groups/api/customer-groups/memberships/crud.js.map +7 -0
  315. package/dist/modules/customer_groups/api/customer-groups/memberships/route.js +66 -0
  316. package/dist/modules/customer_groups/api/customer-groups/memberships/route.js.map +7 -0
  317. package/dist/modules/customer_groups/api/customer-groups/price-kinds/route.js +90 -0
  318. package/dist/modules/customer_groups/api/customer-groups/price-kinds/route.js.map +7 -0
  319. package/dist/modules/customer_groups/api/customer-groups/reconcile/adopt/route.js +133 -0
  320. package/dist/modules/customer_groups/api/customer-groups/reconcile/adopt/route.js.map +7 -0
  321. package/dist/modules/customer_groups/api/customer-groups/reconcile/route.js +80 -0
  322. package/dist/modules/customer_groups/api/customer-groups/reconcile/route.js.map +7 -0
  323. package/dist/modules/customer_groups/api/customer-groups/reorder/route.js +127 -0
  324. package/dist/modules/customer_groups/api/customer-groups/reorder/route.js.map +7 -0
  325. package/dist/modules/customer_groups/api/customer-groups/route.js +62 -0
  326. package/dist/modules/customer_groups/api/customer-groups/route.js.map +7 -0
  327. package/dist/modules/customer_groups/api/openapi.js +27 -0
  328. package/dist/modules/customer_groups/api/openapi.js.map +7 -0
  329. package/dist/modules/customer_groups/backend/customer-groups/[id]/edit/page.js +328 -0
  330. package/dist/modules/customer_groups/backend/customer-groups/[id]/edit/page.js.map +7 -0
  331. package/dist/modules/customer_groups/backend/customer-groups/[id]/edit/page.meta.js +16 -0
  332. package/dist/modules/customer_groups/backend/customer-groups/[id]/edit/page.meta.js.map +7 -0
  333. package/dist/modules/customer_groups/backend/customer-groups/create/page.js +249 -0
  334. package/dist/modules/customer_groups/backend/customer-groups/create/page.js.map +7 -0
  335. package/dist/modules/customer_groups/backend/customer-groups/create/page.meta.js +27 -0
  336. package/dist/modules/customer_groups/backend/customer-groups/create/page.meta.js.map +7 -0
  337. package/dist/modules/customer_groups/backend/customer-groups/orphans/page.js +139 -0
  338. package/dist/modules/customer_groups/backend/customer-groups/orphans/page.js.map +7 -0
  339. package/dist/modules/customer_groups/backend/customer-groups/orphans/page.meta.js +16 -0
  340. package/dist/modules/customer_groups/backend/customer-groups/orphans/page.meta.js.map +7 -0
  341. package/dist/modules/customer_groups/backend/customer-groups/page.js +368 -0
  342. package/dist/modules/customer_groups/backend/customer-groups/page.js.map +7 -0
  343. package/dist/modules/customer_groups/backend/customer-groups/page.meta.js +15 -0
  344. package/dist/modules/customer_groups/backend/customer-groups/page.meta.js.map +7 -0
  345. package/dist/modules/customer_groups/cli.js +72 -0
  346. package/dist/modules/customer_groups/cli.js.map +7 -0
  347. package/dist/modules/customer_groups/commands/reorderGroups.js +96 -0
  348. package/dist/modules/customer_groups/commands/reorderGroups.js.map +7 -0
  349. package/dist/modules/customer_groups/components/CustomerGroupDefaultField.js +41 -0
  350. package/dist/modules/customer_groups/components/CustomerGroupDefaultField.js.map +7 -0
  351. package/dist/modules/customer_groups/components/CustomerGroupParentField.js +156 -0
  352. package/dist/modules/customer_groups/components/CustomerGroupParentField.js.map +7 -0
  353. package/dist/modules/customer_groups/components/CustomerGroupTermsPriceKindField.js +94 -0
  354. package/dist/modules/customer_groups/components/CustomerGroupTermsPriceKindField.js.map +7 -0
  355. package/dist/modules/customer_groups/components/CustomerGroupTermsSection.js +199 -0
  356. package/dist/modules/customer_groups/components/CustomerGroupTermsSection.js.map +7 -0
  357. package/dist/modules/customer_groups/components/GroupPickerField.js +116 -0
  358. package/dist/modules/customer_groups/components/GroupPickerField.js.map +7 -0
  359. package/dist/modules/customer_groups/components/OrphanBanner.js +75 -0
  360. package/dist/modules/customer_groups/components/OrphanBanner.js.map +7 -0
  361. package/dist/modules/customer_groups/components/customerGroupTree.js +57 -0
  362. package/dist/modules/customer_groups/components/customerGroupTree.js.map +7 -0
  363. package/dist/modules/customer_groups/data/entities.js +226 -0
  364. package/dist/modules/customer_groups/data/entities.js.map +7 -0
  365. package/dist/modules/customer_groups/data/validators.js +153 -0
  366. package/dist/modules/customer_groups/data/validators.js.map +7 -0
  367. package/dist/modules/customer_groups/di.js +20 -0
  368. package/dist/modules/customer_groups/di.js.map +7 -0
  369. package/dist/modules/customer_groups/events.js +22 -0
  370. package/dist/modules/customer_groups/events.js.map +7 -0
  371. package/dist/modules/customer_groups/index.js +15 -0
  372. package/dist/modules/customer_groups/index.js.map +7 -0
  373. package/dist/modules/customer_groups/lib/createConflictRecheck.js +29 -0
  374. package/dist/modules/customer_groups/lib/createConflictRecheck.js.map +7 -0
  375. package/dist/modules/customer_groups/lib/customerScope.js +81 -0
  376. package/dist/modules/customer_groups/lib/customerScope.js.map +7 -0
  377. package/dist/modules/customer_groups/lib/groupEvents.js +31 -0
  378. package/dist/modules/customer_groups/lib/groupEvents.js.map +7 -0
  379. package/dist/modules/customer_groups/lib/priceKindScope.js +50 -0
  380. package/dist/modules/customer_groups/lib/priceKindScope.js.map +7 -0
  381. package/dist/modules/customer_groups/lib/reconcile.js +161 -0
  382. package/dist/modules/customer_groups/lib/reconcile.js.map +7 -0
  383. package/dist/modules/customer_groups/migrations/Migration20260922095316_customer_groups.js +27 -0
  384. package/dist/modules/customer_groups/migrations/Migration20260922095316_customer_groups.js.map +7 -0
  385. package/dist/modules/customer_groups/migrations/Migration20260922103033_customer_groups.js +19 -0
  386. package/dist/modules/customer_groups/migrations/Migration20260922103033_customer_groups.js.map +7 -0
  387. package/dist/modules/customer_groups/migrations/Migration20260922105444_customer_groups.js +19 -0
  388. package/dist/modules/customer_groups/migrations/Migration20260922105444_customer_groups.js.map +7 -0
  389. package/dist/modules/customer_groups/migrations/Migration20260923193330_customer_groups.js +19 -0
  390. package/dist/modules/customer_groups/migrations/Migration20260923193330_customer_groups.js.map +7 -0
  391. package/dist/modules/customer_groups/migrations/Migration20260929083000_customer_groups.js +20 -0
  392. package/dist/modules/customer_groups/migrations/Migration20260929083000_customer_groups.js.map +7 -0
  393. package/dist/modules/customer_groups/services/customerGroupsService.js +190 -0
  394. package/dist/modules/customer_groups/services/customerGroupsService.js.map +7 -0
  395. package/dist/modules/customer_groups/setup.js +13 -0
  396. package/dist/modules/customer_groups/setup.js.map +7 -0
  397. package/dist/modules/customer_groups/widgets/injection/group-picker-field/widget.js +31 -0
  398. package/dist/modules/customer_groups/widgets/injection/group-picker-field/widget.js.map +7 -0
  399. package/dist/modules/customer_groups/widgets/injection/person-groups-explain-terms.js +166 -0
  400. package/dist/modules/customer_groups/widgets/injection/person-groups-explain-terms.js.map +7 -0
  401. package/dist/modules/customer_groups/widgets/injection/person-groups-tab/widget.js +17 -0
  402. package/dist/modules/customer_groups/widgets/injection/person-groups-tab/widget.js.map +7 -0
  403. package/dist/modules/customer_groups/widgets/injection/person-groups-tab.js +457 -0
  404. package/dist/modules/customer_groups/widgets/injection/person-groups-tab.js.map +7 -0
  405. package/dist/modules/customer_groups/widgets/injection-table.js +33 -0
  406. package/dist/modules/customer_groups/widgets/injection-table.js.map +7 -0
  407. package/dist/modules/customers/acl.js +13 -0
  408. package/dist/modules/customers/acl.js.map +2 -2
  409. package/dist/modules/customers/api/activities/route.js +9 -1
  410. package/dist/modules/customers/api/activities/route.js.map +2 -2
  411. package/dist/modules/customers/api/companies/[id]/people/route.js +2 -1
  412. package/dist/modules/customers/api/companies/[id]/people/route.js.map +2 -2
  413. package/dist/modules/customers/api/companies/[id]/route.js +19 -7
  414. package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
  415. package/dist/modules/customers/api/deals/[id]/companies/route.js +2 -1
  416. package/dist/modules/customers/api/deals/[id]/companies/route.js.map +2 -2
  417. package/dist/modules/customers/api/deals/[id]/people/route.js +2 -1
  418. package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
  419. package/dist/modules/customers/api/deals/map/route.js +7 -2
  420. package/dist/modules/customers/api/deals/map/route.js.map +2 -2
  421. package/dist/modules/customers/api/dictionaries/context.js +2 -1
  422. package/dist/modules/customers/api/dictionaries/context.js.map +2 -2
  423. package/dist/modules/customers/api/entity-roles-factory.js +3 -2
  424. package/dist/modules/customers/api/entity-roles-factory.js.map +2 -2
  425. package/dist/modules/customers/api/interactions/[id]/visibility/route.js +2 -1
  426. package/dist/modules/customers/api/interactions/[id]/visibility/route.js.map +2 -2
  427. package/dist/modules/customers/api/interactions/cancel/route.js +2 -1
  428. package/dist/modules/customers/api/interactions/cancel/route.js.map +2 -2
  429. package/dist/modules/customers/api/interactions/complete/route.js +2 -1
  430. package/dist/modules/customers/api/interactions/complete/route.js.map +2 -2
  431. package/dist/modules/customers/api/interactions/conflicts/route.js +10 -6
  432. package/dist/modules/customers/api/interactions/conflicts/route.js.map +2 -2
  433. package/dist/modules/customers/api/interactions/counts/route.js +24 -4
  434. package/dist/modules/customers/api/interactions/counts/route.js.map +2 -2
  435. package/dist/modules/customers/api/interactions/route.js +31 -8
  436. package/dist/modules/customers/api/interactions/route.js.map +2 -2
  437. package/dist/modules/customers/api/labels/assign/route.js +2 -1
  438. package/dist/modules/customers/api/labels/assign/route.js.map +2 -2
  439. package/dist/modules/customers/api/labels/route.js +3 -2
  440. package/dist/modules/customers/api/labels/route.js.map +2 -2
  441. package/dist/modules/customers/api/labels/unassign/route.js +2 -1
  442. package/dist/modules/customers/api/labels/unassign/route.js.map +2 -2
  443. package/dist/modules/customers/api/people/[id]/companies/context.js +7 -2
  444. package/dist/modules/customers/api/people/[id]/companies/context.js.map +2 -2
  445. package/dist/modules/customers/api/people/[id]/email-share/route.js +218 -0
  446. package/dist/modules/customers/api/people/[id]/email-share/route.js.map +7 -0
  447. package/dist/modules/customers/api/people/[id]/email-threads/route.js +11 -2
  448. package/dist/modules/customers/api/people/[id]/email-threads/route.js.map +2 -2
  449. package/dist/modules/customers/api/people/[id]/emails/route.js +2 -1
  450. package/dist/modules/customers/api/people/[id]/emails/route.js.map +2 -2
  451. package/dist/modules/customers/api/people/[id]/route.js +20 -19
  452. package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
  453. package/dist/modules/customers/api/people/check-phone/route.js +2 -1
  454. package/dist/modules/customers/api/people/check-phone/route.js.map +2 -2
  455. package/dist/modules/customers/api/pipeline-stages/reorder/route.js +3 -2
  456. package/dist/modules/customers/api/pipeline-stages/reorder/route.js.map +2 -2
  457. package/dist/modules/customers/api/pipeline-stages/route.js +3 -3
  458. package/dist/modules/customers/api/pipeline-stages/route.js.map +2 -2
  459. package/dist/modules/customers/api/pipelines/route.js +3 -3
  460. package/dist/modules/customers/api/pipelines/route.js.map +2 -2
  461. package/dist/modules/customers/api/settings/address-format/route.js +2 -1
  462. package/dist/modules/customers/api/settings/address-format/route.js.map +2 -2
  463. package/dist/modules/customers/api/settings/dictionary-sort-modes/route.js +2 -1
  464. package/dist/modules/customers/api/settings/dictionary-sort-modes/route.js.map +2 -2
  465. package/dist/modules/customers/api/settings/stuck-threshold/route.js +2 -1
  466. package/dist/modules/customers/api/settings/stuck-threshold/route.js.map +2 -2
  467. package/dist/modules/customers/api/tags/assign/route.js +2 -1
  468. package/dist/modules/customers/api/tags/assign/route.js.map +2 -2
  469. package/dist/modules/customers/api/tags/unassign/route.js +2 -1
  470. package/dist/modules/customers/api/tags/unassign/route.js.map +2 -2
  471. package/dist/modules/customers/backend/customers/companies/[id]/page.js +4 -2
  472. package/dist/modules/customers/backend/customers/companies/[id]/page.js.map +2 -2
  473. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.js +6 -2
  474. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.js.map +2 -2
  475. package/dist/modules/customers/backend/customers/deals/[id]/page.js +6 -1
  476. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  477. package/dist/modules/customers/backend/customers/deals/components/ReassignOwnerDialog.js +93 -0
  478. package/dist/modules/customers/backend/customers/deals/components/ReassignOwnerDialog.js.map +7 -0
  479. package/dist/modules/customers/backend/customers/deals/page.js +111 -1
  480. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  481. package/dist/modules/customers/backend/customers/people/[id]/page.js +4 -2
  482. package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
  483. package/dist/modules/customers/commands/addresses.js +83 -15
  484. package/dist/modules/customers/commands/addresses.js.map +2 -2
  485. package/dist/modules/customers/commands/companies.js +24 -5
  486. package/dist/modules/customers/commands/companies.js.map +2 -2
  487. package/dist/modules/customers/commands/emailConversationShares.js +177 -0
  488. package/dist/modules/customers/commands/emailConversationShares.js.map +7 -0
  489. package/dist/modules/customers/commands/index.js +1 -0
  490. package/dist/modules/customers/commands/index.js.map +2 -2
  491. package/dist/modules/customers/commands/interactions.js +48 -23
  492. package/dist/modules/customers/commands/interactions.js.map +3 -3
  493. package/dist/modules/customers/commands/people.js +3 -2
  494. package/dist/modules/customers/commands/people.js.map +2 -2
  495. package/dist/modules/customers/commands/shared.js +4 -0
  496. package/dist/modules/customers/commands/shared.js.map +2 -2
  497. package/dist/modules/customers/components/calendar/types.js.map +1 -1
  498. package/dist/modules/customers/components/detail/CompanyPeopleSection.js +3 -11
  499. package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
  500. package/dist/modules/customers/components/detail/DealForm.js +66 -2
  501. package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
  502. package/dist/modules/customers/components/detail/DealOwnerSelect.js +96 -0
  503. package/dist/modules/customers/components/detail/DealOwnerSelect.js.map +7 -0
  504. package/dist/modules/customers/components/detail/DealsSection.js +8 -14
  505. package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
  506. package/dist/modules/customers/components/detail/PersonEmailShareControl.js +190 -0
  507. package/dist/modules/customers/components/detail/PersonEmailShareControl.js.map +7 -0
  508. package/dist/modules/customers/components/detail/PersonEmailThreadsTab.js +17 -0
  509. package/dist/modules/customers/components/detail/PersonEmailThreadsTab.js.map +2 -2
  510. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +5 -2
  511. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
  512. package/dist/modules/customers/components/detail/create/CreateDealForm.js +19 -0
  513. package/dist/modules/customers/components/detail/create/CreateDealForm.js.map +2 -2
  514. package/dist/modules/customers/components/detail/create/DealDetailsFields.js +11 -0
  515. package/dist/modules/customers/components/detail/create/DealDetailsFields.js.map +2 -2
  516. package/dist/modules/customers/components/detail/create/DealSectionCard.js +2 -2
  517. package/dist/modules/customers/components/detail/create/DealSectionCard.js.map +2 -2
  518. package/dist/modules/customers/components/detail/create/dealFormTypes.js +1 -0
  519. package/dist/modules/customers/components/detail/create/dealFormTypes.js.map +2 -2
  520. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js +1 -1
  521. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
  522. package/dist/modules/customers/components/formConfig.js +2 -0
  523. package/dist/modules/customers/components/formConfig.js.map +2 -2
  524. package/dist/modules/customers/components/linking/LinkEntityDialog.js +8 -0
  525. package/dist/modules/customers/components/linking/LinkEntityDialog.js.map +2 -2
  526. package/dist/modules/customers/data/enrichers.js +40 -2
  527. package/dist/modules/customers/data/enrichers.js.map +2 -2
  528. package/dist/modules/customers/data/entities.js +56 -0
  529. package/dist/modules/customers/data/entities.js.map +2 -2
  530. package/dist/modules/customers/data/validators.js +11 -0
  531. package/dist/modules/customers/data/validators.js.map +2 -2
  532. package/dist/modules/customers/events.js +6 -1
  533. package/dist/modules/customers/events.js.map +2 -2
  534. package/dist/modules/customers/lib/assignableStaff.js +14 -0
  535. package/dist/modules/customers/lib/assignableStaff.js.map +2 -2
  536. package/dist/modules/customers/lib/calendar/editorPayload.js +17 -13
  537. package/dist/modules/customers/lib/calendar/editorPayload.js.map +2 -2
  538. package/dist/modules/customers/lib/calendar/mapItem.js +1 -0
  539. package/dist/modules/customers/lib/calendar/mapItem.js.map +2 -2
  540. package/dist/modules/customers/lib/conversationShares.js +126 -0
  541. package/dist/modules/customers/lib/conversationShares.js.map +7 -0
  542. package/dist/modules/customers/lib/dealsOrganizationScope.js +5 -3
  543. package/dist/modules/customers/lib/dealsOrganizationScope.js.map +2 -2
  544. package/dist/modules/customers/lib/interactionRequestContext.js +2 -1
  545. package/dist/modules/customers/lib/interactionRequestContext.js.map +2 -2
  546. package/dist/modules/customers/lib/link-channel-message-handler.js +19 -9
  547. package/dist/modules/customers/lib/link-channel-message-handler.js.map +2 -2
  548. package/dist/modules/customers/lib/personDetailCacheTags.js +32 -0
  549. package/dist/modules/customers/lib/personDetailCacheTags.js.map +7 -0
  550. package/dist/modules/customers/lib/personEmailThreads.js +26 -5
  551. package/dist/modules/customers/lib/personEmailThreads.js.map +2 -2
  552. package/dist/modules/customers/lib/reassignDealOwner.js +25 -0
  553. package/dist/modules/customers/lib/reassignDealOwner.js.map +7 -0
  554. package/dist/modules/customers/lib/userNames.js +26 -0
  555. package/dist/modules/customers/lib/userNames.js.map +7 -0
  556. package/dist/modules/customers/lib/visibilityFilter.js +70 -2
  557. package/dist/modules/customers/lib/visibilityFilter.js.map +2 -2
  558. package/dist/modules/customers/migrations/Migration20260825120000_customers.js +18 -0
  559. package/dist/modules/customers/migrations/Migration20260825120000_customers.js.map +7 -0
  560. package/dist/modules/customers/migrations/Migration20260825140000_customers.js +27 -0
  561. package/dist/modules/customers/migrations/Migration20260825140000_customers.js.map +7 -0
  562. package/dist/modules/customers/setup.js +1 -0
  563. package/dist/modules/customers/setup.js.map +2 -2
  564. package/dist/modules/customers/subscribers/channel-visibility-changed.js +16 -0
  565. package/dist/modules/customers/subscribers/channel-visibility-changed.js.map +7 -0
  566. package/dist/modules/dashboards/api/widgets/data/batch/route.js +3 -8
  567. package/dist/modules/dashboards/api/widgets/data/batch/route.js.map +2 -2
  568. package/dist/modules/dashboards/api/widgets/data/route.js +10 -15
  569. package/dist/modules/dashboards/api/widgets/data/route.js.map +2 -2
  570. package/dist/modules/dashboards/lib/aggregations.js +1 -1
  571. package/dist/modules/dashboards/lib/aggregations.js.map +2 -2
  572. package/dist/modules/dashboards/lib/widgetScope.js +2 -7
  573. package/dist/modules/dashboards/lib/widgetScope.js.map +2 -2
  574. package/dist/modules/data_sync/api/runs/[id]/cancel.js +4 -1
  575. package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +2 -2
  576. package/dist/modules/data_sync/backend/data-sync/page.js +497 -329
  577. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  578. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js +248 -113
  579. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js.map +3 -3
  580. package/dist/modules/data_sync/components/useDataSyncRunAccess.js +17 -0
  581. package/dist/modules/data_sync/components/useDataSyncRunAccess.js.map +7 -0
  582. package/dist/modules/data_sync/lib/resume-point.js +21 -0
  583. package/dist/modules/data_sync/lib/resume-point.js.map +7 -0
  584. package/dist/modules/data_sync/lib/start-run.js +52 -2
  585. package/dist/modules/data_sync/lib/start-run.js.map +2 -2
  586. package/dist/modules/data_sync/lib/sync-run-service.js +22 -33
  587. package/dist/modules/data_sync/lib/sync-run-service.js.map +3 -3
  588. package/dist/modules/devices/api/[id]/route.js +3 -2
  589. package/dist/modules/devices/api/[id]/route.js.map +2 -2
  590. package/dist/modules/devices/api/admin/devices/route.js +2 -1
  591. package/dist/modules/devices/api/admin/devices/route.js.map +2 -2
  592. package/dist/modules/devices/api/route.js +2 -1
  593. package/dist/modules/devices/api/route.js.map +2 -2
  594. package/dist/modules/dictionaries/api/[dictionaryId]/route.js.map +2 -2
  595. package/dist/modules/dictionaries/api/context.js +2 -1
  596. package/dist/modules/dictionaries/api/context.js.map +2 -2
  597. package/dist/modules/dictionaries/api/route.js +4 -0
  598. package/dist/modules/dictionaries/api/route.js.map +2 -2
  599. package/dist/modules/dictionaries/components/DictionariesManager.js +101 -89
  600. package/dist/modules/dictionaries/components/DictionariesManager.js.map +2 -2
  601. package/dist/modules/dictionaries/data/validators.js +3 -1
  602. package/dist/modules/dictionaries/data/validators.js.map +2 -2
  603. package/dist/modules/directory/api/organization-branding/route.js +10 -1
  604. package/dist/modules/directory/api/organization-branding/route.js.map +2 -2
  605. package/dist/modules/directory/api/organizations/route.js +1 -1
  606. package/dist/modules/directory/api/organizations/route.js.map +1 -1
  607. package/dist/modules/directory/backend/directory/branding/page.js +17 -4
  608. package/dist/modules/directory/backend/directory/branding/page.js.map +3 -3
  609. package/dist/modules/directory/commands/organizations.js +136 -74
  610. package/dist/modules/directory/commands/organizations.js.map +2 -2
  611. package/dist/modules/directory/lib/hierarchy.js +19 -1
  612. package/dist/modules/directory/lib/hierarchy.js.map +2 -2
  613. package/dist/modules/directory/utils/organizationScope.js +66 -12
  614. package/dist/modules/directory/utils/organizationScope.js.map +2 -2
  615. package/dist/modules/directory/utils/organizationScopeFilter.js +7 -4
  616. package/dist/modules/directory/utils/organizationScopeFilter.js.map +2 -2
  617. package/dist/modules/directory/utils/organizationScopeGuard.js +6 -2
  618. package/dist/modules/directory/utils/organizationScopeGuard.js.map +2 -2
  619. package/dist/modules/entities/api/encryption.js +68 -25
  620. package/dist/modules/entities/api/encryption.js.map +2 -2
  621. package/dist/modules/entities/api/records.js +9 -8
  622. package/dist/modules/entities/api/records.js.map +2 -2
  623. package/dist/modules/entities/cli.js +33 -22
  624. package/dist/modules/entities/cli.js.map +2 -2
  625. package/dist/modules/entities/data/entities.js +8 -0
  626. package/dist/modules/entities/data/entities.js.map +2 -2
  627. package/dist/modules/entities/lib/definition-scope.js +3 -1
  628. package/dist/modules/entities/lib/definition-scope.js.map +2 -2
  629. package/dist/modules/entities/lib/encryption-maps.js +117 -0
  630. package/dist/modules/entities/lib/encryption-maps.js.map +7 -0
  631. package/dist/modules/entities/lib/helpers.js +30 -6
  632. package/dist/modules/entities/lib/helpers.js.map +2 -2
  633. package/dist/modules/entities/migrations/Migration20260910120000.js +17 -0
  634. package/dist/modules/entities/migrations/Migration20260910120000.js.map +7 -0
  635. package/dist/modules/entities/migrations/Migration20261004120000_encryption_map_scope_uniqueness.js +130 -0
  636. package/dist/modules/entities/migrations/Migration20261004120000_encryption_map_scope_uniqueness.js.map +7 -0
  637. package/dist/modules/eudr/api/dashboard/widgets/compliance-overview/route.js +2 -1
  638. package/dist/modules/eudr/api/dashboard/widgets/compliance-overview/route.js.map +2 -2
  639. package/dist/modules/eudr/api/plots/import/route.js +2 -1
  640. package/dist/modules/eudr/api/plots/import/route.js.map +2 -2
  641. package/dist/modules/eudr/api/product-mappings/suggestions/apply/route.js +2 -1
  642. package/dist/modules/eudr/api/product-mappings/suggestions/apply/route.js.map +2 -2
  643. package/dist/modules/eudr/api/product-mappings/suggestions/route.js +2 -1
  644. package/dist/modules/eudr/api/product-mappings/suggestions/route.js.map +2 -2
  645. package/dist/modules/eudr/api/reports/annual/route.js +2 -1
  646. package/dist/modules/eudr/api/reports/annual/route.js.map +2 -2
  647. package/dist/modules/eudr/api/statements/[id]/export/route.js +2 -1
  648. package/dist/modules/eudr/api/statements/[id]/export/route.js.map +2 -2
  649. package/dist/modules/eudr/api/statements/[id]/readiness/route.js +2 -1
  650. package/dist/modules/eudr/api/statements/[id]/readiness/route.js.map +2 -2
  651. package/dist/modules/eudr/api/suppliers/compliance/route.js +2 -1
  652. package/dist/modules/eudr/api/suppliers/compliance/route.js.map +2 -2
  653. package/dist/modules/feature_toggles/commands/global.js +13 -13
  654. package/dist/modules/feature_toggles/commands/global.js.map +2 -2
  655. package/dist/modules/feature_toggles/lib/feature-flag-check.js +8 -2
  656. package/dist/modules/feature_toggles/lib/feature-flag-check.js.map +2 -2
  657. package/dist/modules/forms/acl.js +14 -0
  658. package/dist/modules/forms/acl.js.map +7 -0
  659. package/dist/modules/forms/api/[id]/analytics/route.js +113 -0
  660. package/dist/modules/forms/api/[id]/analytics/route.js.map +7 -0
  661. package/dist/modules/forms/api/[id]/distributions/route.js +176 -0
  662. package/dist/modules/forms/api/[id]/distributions/route.js.map +7 -0
  663. package/dist/modules/forms/api/[id]/route.js +225 -0
  664. package/dist/modules/forms/api/[id]/route.js.map +7 -0
  665. package/dist/modules/forms/api/[id]/run/context/route.js +115 -0
  666. package/dist/modules/forms/api/[id]/run/context/route.js.map +7 -0
  667. package/dist/modules/forms/api/[id]/run/submissions/route.js +109 -0
  668. package/dist/modules/forms/api/[id]/run/submissions/route.js.map +7 -0
  669. package/dist/modules/forms/api/[id]/submissions/route.js +83 -0
  670. package/dist/modules/forms/api/[id]/submissions/route.js.map +7 -0
  671. package/dist/modules/forms/api/[id]/theme-logo/route.js +117 -0
  672. package/dist/modules/forms/api/[id]/theme-logo/route.js.map +7 -0
  673. package/dist/modules/forms/api/[id]/versions/[versionId]/diff/route.js +125 -0
  674. package/dist/modules/forms/api/[id]/versions/[versionId]/diff/route.js.map +7 -0
  675. package/dist/modules/forms/api/[id]/versions/[versionId]/publish/route.js +99 -0
  676. package/dist/modules/forms/api/[id]/versions/[versionId]/publish/route.js.map +7 -0
  677. package/dist/modules/forms/api/[id]/versions/[versionId]/route.js +176 -0
  678. package/dist/modules/forms/api/[id]/versions/[versionId]/route.js.map +7 -0
  679. package/dist/modules/forms/api/[id]/versions/fork/route.js +92 -0
  680. package/dist/modules/forms/api/[id]/versions/fork/route.js.map +7 -0
  681. package/dist/modules/forms/api/attachment-helpers.js +111 -0
  682. package/dist/modules/forms/api/attachment-helpers.js.map +7 -0
  683. package/dist/modules/forms/api/by-key/[key]/active/route.js +140 -0
  684. package/dist/modules/forms/api/by-key/[key]/active/route.js.map +7 -0
  685. package/dist/modules/forms/api/distributions/[distributionId]/invitations/[invitationId]/route.js +84 -0
  686. package/dist/modules/forms/api/distributions/[distributionId]/invitations/[invitationId]/route.js.map +7 -0
  687. package/dist/modules/forms/api/distributions/[distributionId]/invitations/[invitationId]/send/route.js +88 -0
  688. package/dist/modules/forms/api/distributions/[distributionId]/invitations/[invitationId]/send/route.js.map +7 -0
  689. package/dist/modules/forms/api/distributions/[distributionId]/invitations/route.js +183 -0
  690. package/dist/modules/forms/api/distributions/[distributionId]/invitations/route.js.map +7 -0
  691. package/dist/modules/forms/api/distributions/[distributionId]/route.js +191 -0
  692. package/dist/modules/forms/api/distributions/[distributionId]/route.js.map +7 -0
  693. package/dist/modules/forms/api/form-submissions/[id]/attachments/route.js +91 -0
  694. package/dist/modules/forms/api/form-submissions/[id]/attachments/route.js.map +7 -0
  695. package/dist/modules/forms/api/form-submissions/[id]/resume-token/route.js +110 -0
  696. package/dist/modules/forms/api/form-submissions/[id]/resume-token/route.js.map +7 -0
  697. package/dist/modules/forms/api/form-submissions/[id]/route.js +146 -0
  698. package/dist/modules/forms/api/form-submissions/[id]/route.js.map +7 -0
  699. package/dist/modules/forms/api/form-submissions/[id]/submit/route.js +74 -0
  700. package/dist/modules/forms/api/form-submissions/[id]/submit/route.js.map +7 -0
  701. package/dist/modules/forms/api/form-submissions/by-subject/[subject_type]/[subject_id]/route.js +76 -0
  702. package/dist/modules/forms/api/form-submissions/by-subject/[subject_type]/[subject_id]/route.js.map +7 -0
  703. package/dist/modules/forms/api/form-submissions/route.js +113 -0
  704. package/dist/modules/forms/api/form-submissions/route.js.map +7 -0
  705. package/dist/modules/forms/api/helpers.js +124 -0
  706. package/dist/modules/forms/api/helpers.js.map +7 -0
  707. package/dist/modules/forms/api/public/distributions/[slug]/embed-policy/route.js +47 -0
  708. package/dist/modules/forms/api/public/distributions/[slug]/embed-policy/route.js.map +7 -0
  709. package/dist/modules/forms/api/public/distributions/[slug]/route.js +81 -0
  710. package/dist/modules/forms/api/public/distributions/[slug]/route.js.map +7 -0
  711. package/dist/modules/forms/api/public/embed-loader/route.js +116 -0
  712. package/dist/modules/forms/api/public/embed-loader/route.js.map +7 -0
  713. package/dist/modules/forms/api/public/invitations/[token]/route.js +87 -0
  714. package/dist/modules/forms/api/public/invitations/[token]/route.js.map +7 -0
  715. package/dist/modules/forms/api/public/rate-limit.js +54 -0
  716. package/dist/modules/forms/api/public/rate-limit.js.map +7 -0
  717. package/dist/modules/forms/api/public/start/route.js +142 -0
  718. package/dist/modules/forms/api/public/start/route.js.map +7 -0
  719. package/dist/modules/forms/api/public/submissions/[id]/attachments/[attachmentId]/route.js +67 -0
  720. package/dist/modules/forms/api/public/submissions/[id]/attachments/[attachmentId]/route.js.map +7 -0
  721. package/dist/modules/forms/api/public/submissions/[id]/attachments/route.js +85 -0
  722. package/dist/modules/forms/api/public/submissions/[id]/attachments/route.js.map +7 -0
  723. package/dist/modules/forms/api/public/submissions/[id]/pdf/route.js +72 -0
  724. package/dist/modules/forms/api/public/submissions/[id]/pdf/route.js.map +7 -0
  725. package/dist/modules/forms/api/public/submissions/[id]/route.js +154 -0
  726. package/dist/modules/forms/api/public/submissions/[id]/route.js.map +7 -0
  727. package/dist/modules/forms/api/public/submissions/[id]/submit/route.js +127 -0
  728. package/dist/modules/forms/api/public/submissions/[id]/submit/route.js.map +7 -0
  729. package/dist/modules/forms/api/route.js +216 -0
  730. package/dist/modules/forms/api/route.js.map +7 -0
  731. package/dist/modules/forms/api/runtime-helpers.js +149 -0
  732. package/dist/modules/forms/api/runtime-helpers.js.map +7 -0
  733. package/dist/modules/forms/api/subjects/[subjectType]/[subjectId]/consents/route.js +137 -0
  734. package/dist/modules/forms/api/subjects/[subjectType]/[subjectId]/consents/route.js.map +7 -0
  735. package/dist/modules/forms/api/subjects/[subjectType]/[subjectId]/export/route.js +101 -0
  736. package/dist/modules/forms/api/subjects/[subjectType]/[subjectId]/export/route.js.map +7 -0
  737. package/dist/modules/forms/api/submissions/[submissionId]/access-audit/route.js +76 -0
  738. package/dist/modules/forms/api/submissions/[submissionId]/access-audit/route.js.map +7 -0
  739. package/dist/modules/forms/api/submissions/[submissionId]/actors/[actorId]/route.js +56 -0
  740. package/dist/modules/forms/api/submissions/[submissionId]/actors/[actorId]/route.js.map +7 -0
  741. package/dist/modules/forms/api/submissions/[submissionId]/actors/route.js +76 -0
  742. package/dist/modules/forms/api/submissions/[submissionId]/actors/route.js.map +7 -0
  743. package/dist/modules/forms/api/submissions/[submissionId]/anonymize/route.js +107 -0
  744. package/dist/modules/forms/api/submissions/[submissionId]/anonymize/route.js.map +7 -0
  745. package/dist/modules/forms/api/submissions/[submissionId]/attachments/[attachmentId]/route.js +73 -0
  746. package/dist/modules/forms/api/submissions/[submissionId]/attachments/[attachmentId]/route.js.map +7 -0
  747. package/dist/modules/forms/api/submissions/[submissionId]/export/route.js +90 -0
  748. package/dist/modules/forms/api/submissions/[submissionId]/export/route.js.map +7 -0
  749. package/dist/modules/forms/api/submissions/[submissionId]/pdf/route.js +91 -0
  750. package/dist/modules/forms/api/submissions/[submissionId]/pdf/route.js.map +7 -0
  751. package/dist/modules/forms/api/submissions/[submissionId]/reopen/route.js +55 -0
  752. package/dist/modules/forms/api/submissions/[submissionId]/reopen/route.js.map +7 -0
  753. package/dist/modules/forms/api/submissions/[submissionId]/revisions/route.js +61 -0
  754. package/dist/modules/forms/api/submissions/[submissionId]/revisions/route.js.map +7 -0
  755. package/dist/modules/forms/api/submissions/[submissionId]/route.js +75 -0
  756. package/dist/modules/forms/api/submissions/[submissionId]/route.js.map +7 -0
  757. package/dist/modules/forms/backend/forms/[id]/FormStudio.js +2811 -0
  758. package/dist/modules/forms/backend/forms/[id]/FormStudio.js.map +7 -0
  759. package/dist/modules/forms/backend/forms/[id]/analytics/page.js +214 -0
  760. package/dist/modules/forms/backend/forms/[id]/analytics/page.js.map +7 -0
  761. package/dist/modules/forms/backend/forms/[id]/analytics/page.meta.js +19 -0
  762. package/dist/modules/forms/backend/forms/[id]/analytics/page.meta.js.map +7 -0
  763. package/dist/modules/forms/backend/forms/[id]/distributions/page.js +12 -0
  764. package/dist/modules/forms/backend/forms/[id]/distributions/page.js.map +7 -0
  765. package/dist/modules/forms/backend/forms/[id]/distributions/page.meta.js +19 -0
  766. package/dist/modules/forms/backend/forms/[id]/distributions/page.meta.js.map +7 -0
  767. package/dist/modules/forms/backend/forms/[id]/history/page.js +152 -0
  768. package/dist/modules/forms/backend/forms/[id]/history/page.js.map +7 -0
  769. package/dist/modules/forms/backend/forms/[id]/history/page.meta.js +15 -0
  770. package/dist/modules/forms/backend/forms/[id]/history/page.meta.js.map +7 -0
  771. package/dist/modules/forms/backend/forms/[id]/page.js +13 -0
  772. package/dist/modules/forms/backend/forms/[id]/page.js.map +7 -0
  773. package/dist/modules/forms/backend/forms/[id]/page.meta.js +15 -0
  774. package/dist/modules/forms/backend/forms/[id]/page.meta.js.map +7 -0
  775. package/dist/modules/forms/backend/forms/[id]/studio/YesNoRow.js +51 -0
  776. package/dist/modules/forms/backend/forms/[id]/studio/YesNoRow.js.map +7 -0
  777. package/dist/modules/forms/backend/forms/[id]/studio/autosave-guard.js +21 -0
  778. package/dist/modules/forms/backend/forms/[id]/studio/autosave-guard.js.map +7 -0
  779. package/dist/modules/forms/backend/forms/[id]/studio/canvas/DragOverlayCard.js +18 -0
  780. package/dist/modules/forms/backend/forms/[id]/studio/canvas/DragOverlayCard.js.map +7 -0
  781. package/dist/modules/forms/backend/forms/[id]/studio/canvas/DropIndicator.js +41 -0
  782. package/dist/modules/forms/backend/forms/[id]/studio/canvas/DropIndicator.js.map +7 -0
  783. package/dist/modules/forms/backend/forms/[id]/studio/canvas/FieldRow.js +277 -0
  784. package/dist/modules/forms/backend/forms/[id]/studio/canvas/FieldRow.js.map +7 -0
  785. package/dist/modules/forms/backend/forms/[id]/studio/canvas/FormCanvas.js +196 -0
  786. package/dist/modules/forms/backend/forms/[id]/studio/canvas/FormCanvas.js.map +7 -0
  787. package/dist/modules/forms/backend/forms/[id]/studio/canvas/GridSlot.js +151 -0
  788. package/dist/modules/forms/backend/forms/[id]/studio/canvas/GridSlot.js.map +7 -0
  789. package/dist/modules/forms/backend/forms/[id]/studio/canvas/SectionContainer.js +340 -0
  790. package/dist/modules/forms/backend/forms/[id]/studio/canvas/SectionContainer.js.map +7 -0
  791. package/dist/modules/forms/backend/forms/[id]/studio/canvas/grid-collision.js +24 -0
  792. package/dist/modules/forms/backend/forms/[id]/studio/canvas/grid-collision.js.map +7 -0
  793. package/dist/modules/forms/backend/forms/[id]/studio/canvas/keyboard-coordinates.js +91 -0
  794. package/dist/modules/forms/backend/forms/[id]/studio/canvas/keyboard-coordinates.js.map +7 -0
  795. package/dist/modules/forms/backend/forms/[id]/studio/canvas/overlay-size.js +11 -0
  796. package/dist/modules/forms/backend/forms/[id]/studio/canvas/overlay-size.js.map +7 -0
  797. package/dist/modules/forms/backend/forms/[id]/studio/canvas/resize-math.js +27 -0
  798. package/dist/modules/forms/backend/forms/[id]/studio/canvas/resize-math.js.map +7 -0
  799. package/dist/modules/forms/backend/forms/[id]/studio/canvas/row-layout.js +80 -0
  800. package/dist/modules/forms/backend/forms/[id]/studio/canvas/row-layout.js.map +7 -0
  801. package/dist/modules/forms/backend/forms/[id]/studio/logic/ConditionBuilder.js +210 -0
  802. package/dist/modules/forms/backend/forms/[id]/studio/logic/ConditionBuilder.js.map +7 -0
  803. package/dist/modules/forms/backend/forms/[id]/studio/logic/HiddenFieldsPanel.js +91 -0
  804. package/dist/modules/forms/backend/forms/[id]/studio/logic/HiddenFieldsPanel.js.map +7 -0
  805. package/dist/modules/forms/backend/forms/[id]/studio/logic/JumpsEditor.js +201 -0
  806. package/dist/modules/forms/backend/forms/[id]/studio/logic/JumpsEditor.js.map +7 -0
  807. package/dist/modules/forms/backend/forms/[id]/studio/logic/RecallTokenPicker.js +66 -0
  808. package/dist/modules/forms/backend/forms/[id]/studio/logic/RecallTokenPicker.js.map +7 -0
  809. package/dist/modules/forms/backend/forms/[id]/studio/logic/VariablesPanel.js +223 -0
  810. package/dist/modules/forms/backend/forms/[id]/studio/logic/VariablesPanel.js.map +7 -0
  811. package/dist/modules/forms/backend/forms/[id]/studio/logic/condition-model.js +151 -0
  812. package/dist/modules/forms/backend/forms/[id]/studio/logic/condition-model.js.map +7 -0
  813. package/dist/modules/forms/backend/forms/[id]/studio/lucide-icons.js +88 -0
  814. package/dist/modules/forms/backend/forms/[id]/studio/lucide-icons.js.map +7 -0
  815. package/dist/modules/forms/backend/forms/[id]/studio/palette/FormAppearancePanel.js +493 -0
  816. package/dist/modules/forms/backend/forms/[id]/studio/palette/FormAppearancePanel.js.map +7 -0
  817. package/dist/modules/forms/backend/forms/[id]/studio/palette/FormPalettePanel.js +44 -0
  818. package/dist/modules/forms/backend/forms/[id]/studio/palette/FormPalettePanel.js.map +7 -0
  819. package/dist/modules/forms/backend/forms/[id]/studio/palette/InputParametersTab.js +350 -0
  820. package/dist/modules/forms/backend/forms/[id]/studio/palette/InputParametersTab.js.map +7 -0
  821. package/dist/modules/forms/backend/forms/[id]/studio/palette/PaletteCard.js +40 -0
  822. package/dist/modules/forms/backend/forms/[id]/studio/palette/PaletteCard.js.map +7 -0
  823. package/dist/modules/forms/backend/forms/[id]/studio/palette/RolesEditor.js +202 -0
  824. package/dist/modules/forms/backend/forms/[id]/studio/palette/RolesEditor.js.map +7 -0
  825. package/dist/modules/forms/backend/forms/[id]/studio/palette/entries.js +66 -0
  826. package/dist/modules/forms/backend/forms/[id]/studio/palette/entries.js.map +7 -0
  827. package/dist/modules/forms/backend/forms/[id]/studio/preview/PreviewSurface.js +1200 -0
  828. package/dist/modules/forms/backend/forms/[id]/studio/preview/PreviewSurface.js.map +7 -0
  829. package/dist/modules/forms/backend/forms/[id]/studio/preview/ViewportFrame.js +34 -0
  830. package/dist/modules/forms/backend/forms/[id]/studio/preview/ViewportFrame.js.map +7 -0
  831. package/dist/modules/forms/backend/forms/[id]/studio/recall.js +76 -0
  832. package/dist/modules/forms/backend/forms/[id]/studio/recall.js.map +7 -0
  833. package/dist/modules/forms/backend/forms/[id]/studio/schema-helpers.js +1693 -0
  834. package/dist/modules/forms/backend/forms/[id]/studio/schema-helpers.js.map +7 -0
  835. package/dist/modules/forms/backend/forms/[id]/studio/style/BackgroundControl.js +127 -0
  836. package/dist/modules/forms/backend/forms/[id]/studio/style/BackgroundControl.js.map +7 -0
  837. package/dist/modules/forms/backend/forms/[id]/studio/style/ColorControl.js +181 -0
  838. package/dist/modules/forms/backend/forms/[id]/studio/style/ColorControl.js.map +7 -0
  839. package/dist/modules/forms/backend/forms/[id]/studio/style/contrast.js +75 -0
  840. package/dist/modules/forms/backend/forms/[id]/studio/style/contrast.js.map +7 -0
  841. package/dist/modules/forms/backend/forms/[id]/studio/style/presets.js +91 -0
  842. package/dist/modules/forms/backend/forms/[id]/studio/style/presets.js.map +7 -0
  843. package/dist/modules/forms/backend/forms/[id]/studio/type-label.js +11 -0
  844. package/dist/modules/forms/backend/forms/[id]/studio/type-label.js.map +7 -0
  845. package/dist/modules/forms/backend/forms/[id]/studio/types.js +1 -0
  846. package/dist/modules/forms/backend/forms/[id]/studio/types.js.map +7 -0
  847. package/dist/modules/forms/backend/forms/[id]/studio/undo-controller.js +43 -0
  848. package/dist/modules/forms/backend/forms/[id]/studio/undo-controller.js.map +7 -0
  849. package/dist/modules/forms/backend/forms/[id]/studio/validation/FileConstraintsEditor.js +74 -0
  850. package/dist/modules/forms/backend/forms/[id]/studio/validation/FileConstraintsEditor.js.map +7 -0
  851. package/dist/modules/forms/backend/forms/[id]/studio/validation/GroupConfigEditor.js +134 -0
  852. package/dist/modules/forms/backend/forms/[id]/studio/validation/GroupConfigEditor.js.map +7 -0
  853. package/dist/modules/forms/backend/forms/[id]/studio/validation/LengthRangeEditor.js +61 -0
  854. package/dist/modules/forms/backend/forms/[id]/studio/validation/LengthRangeEditor.js.map +7 -0
  855. package/dist/modules/forms/backend/forms/[id]/studio/validation/MatrixColumnsEditor.js +149 -0
  856. package/dist/modules/forms/backend/forms/[id]/studio/validation/MatrixColumnsEditor.js.map +7 -0
  857. package/dist/modules/forms/backend/forms/[id]/studio/validation/MatrixRowsEditor.js +168 -0
  858. package/dist/modules/forms/backend/forms/[id]/studio/validation/MatrixRowsEditor.js.map +7 -0
  859. package/dist/modules/forms/backend/forms/[id]/studio/validation/MessageOverridesEditor.js +64 -0
  860. package/dist/modules/forms/backend/forms/[id]/studio/validation/MessageOverridesEditor.js.map +7 -0
  861. package/dist/modules/forms/backend/forms/[id]/studio/validation/NpsAnchorsEditor.js +52 -0
  862. package/dist/modules/forms/backend/forms/[id]/studio/validation/NpsAnchorsEditor.js.map +7 -0
  863. package/dist/modules/forms/backend/forms/[id]/studio/validation/NumberRangeEditor.js +59 -0
  864. package/dist/modules/forms/backend/forms/[id]/studio/validation/NumberRangeEditor.js.map +7 -0
  865. package/dist/modules/forms/backend/forms/[id]/studio/validation/OpinionIconSelect.js +31 -0
  866. package/dist/modules/forms/backend/forms/[id]/studio/validation/OpinionIconSelect.js.map +7 -0
  867. package/dist/modules/forms/backend/forms/[id]/studio/validation/PatternEditor.js +105 -0
  868. package/dist/modules/forms/backend/forms/[id]/studio/validation/PatternEditor.js.map +7 -0
  869. package/dist/modules/forms/backend/forms/[id]/studio/validation/RankingExhaustiveSwitch.js +15 -0
  870. package/dist/modules/forms/backend/forms/[id]/studio/validation/RankingExhaustiveSwitch.js.map +7 -0
  871. package/dist/modules/forms/backend/forms/[id]/studio/validation/SignatureConfigEditor.js +75 -0
  872. package/dist/modules/forms/backend/forms/[id]/studio/validation/SignatureConfigEditor.js.map +7 -0
  873. package/dist/modules/forms/backend/forms/[id]/studio/validation/ValidationPanel.js +293 -0
  874. package/dist/modules/forms/backend/forms/[id]/studio/validation/ValidationPanel.js.map +7 -0
  875. package/dist/modules/forms/backend/forms/[id]/submissions/components/RowBadges.js +42 -0
  876. package/dist/modules/forms/backend/forms/[id]/submissions/components/RowBadges.js.map +7 -0
  877. package/dist/modules/forms/backend/forms/[id]/submissions/components/SubmissionDrawer.js +473 -0
  878. package/dist/modules/forms/backend/forms/[id]/submissions/components/SubmissionDrawer.js.map +7 -0
  879. package/dist/modules/forms/backend/forms/[id]/submissions/components/formSummary.js +9 -0
  880. package/dist/modules/forms/backend/forms/[id]/submissions/components/formSummary.js.map +7 -0
  881. package/dist/modules/forms/backend/forms/[id]/submissions/page.js +205 -0
  882. package/dist/modules/forms/backend/forms/[id]/submissions/page.js.map +7 -0
  883. package/dist/modules/forms/backend/forms/[id]/submissions/page.meta.js +12 -0
  884. package/dist/modules/forms/backend/forms/[id]/submissions/page.meta.js.map +7 -0
  885. package/dist/modules/forms/backend/forms/create/page.js +101 -0
  886. package/dist/modules/forms/backend/forms/create/page.js.map +7 -0
  887. package/dist/modules/forms/backend/forms/create/page.meta.js +15 -0
  888. package/dist/modules/forms/backend/forms/create/page.meta.js.map +7 -0
  889. package/dist/modules/forms/backend/forms/page.js +227 -0
  890. package/dist/modules/forms/backend/forms/page.js.map +7 -0
  891. package/dist/modules/forms/backend/forms/page.meta.js +33 -0
  892. package/dist/modules/forms/backend/forms/page.meta.js.map +7 -0
  893. package/dist/modules/forms/commands/distribution.js +421 -0
  894. package/dist/modules/forms/commands/distribution.js.map +7 -0
  895. package/dist/modules/forms/commands/form-version.js +645 -0
  896. package/dist/modules/forms/commands/form-version.js.map +7 -0
  897. package/dist/modules/forms/commands/form.js +411 -0
  898. package/dist/modules/forms/commands/form.js.map +7 -0
  899. package/dist/modules/forms/commands/index.js +11 -0
  900. package/dist/modules/forms/commands/index.js.map +7 -0
  901. package/dist/modules/forms/commands/invitation.js +333 -0
  902. package/dist/modules/forms/commands/invitation.js.map +7 -0
  903. package/dist/modules/forms/commands/shared.js +151 -0
  904. package/dist/modules/forms/commands/shared.js.map +7 -0
  905. package/dist/modules/forms/commands/submission.js +139 -0
  906. package/dist/modules/forms/commands/submission.js.map +7 -0
  907. package/dist/modules/forms/data/entities.js +654 -0
  908. package/dist/modules/forms/data/entities.js.map +7 -0
  909. package/dist/modules/forms/data/validators.js +254 -0
  910. package/dist/modules/forms/data/validators.js.map +7 -0
  911. package/dist/modules/forms/di.js +199 -0
  912. package/dist/modules/forms/di.js.map +7 -0
  913. package/dist/modules/forms/encryption.js +15 -0
  914. package/dist/modules/forms/encryption.js.map +7 -0
  915. package/dist/modules/forms/events-payloads.js +81 -0
  916. package/dist/modules/forms/events-payloads.js.map +7 -0
  917. package/dist/modules/forms/events.js +33 -0
  918. package/dist/modules/forms/events.js.map +7 -0
  919. package/dist/modules/forms/extension-points.js +36 -0
  920. package/dist/modules/forms/extension-points.js.map +7 -0
  921. package/dist/modules/forms/frontend/[orgSlug]/portal/forms/[key]/page.js +33 -0
  922. package/dist/modules/forms/frontend/[orgSlug]/portal/forms/[key]/page.js.map +7 -0
  923. package/dist/modules/forms/frontend/[orgSlug]/portal/forms/[key]/page.meta.js +11 -0
  924. package/dist/modules/forms/frontend/[orgSlug]/portal/forms/[key]/page.meta.js.map +7 -0
  925. package/dist/modules/forms/frontend/[orgSlug]/portal/submissions/[id]/continue/page.js +41 -0
  926. package/dist/modules/forms/frontend/[orgSlug]/portal/submissions/[id]/continue/page.js.map +7 -0
  927. package/dist/modules/forms/frontend/[orgSlug]/portal/submissions/[id]/continue/page.meta.js +11 -0
  928. package/dist/modules/forms/frontend/[orgSlug]/portal/submissions/[id]/continue/page.meta.js.map +7 -0
  929. package/dist/modules/forms/frontend/embed/[slug]/page.js +105 -0
  930. package/dist/modules/forms/frontend/embed/[slug]/page.js.map +7 -0
  931. package/dist/modules/forms/frontend/embed/[slug]/page.meta.js +11 -0
  932. package/dist/modules/forms/frontend/embed/[slug]/page.meta.js.map +7 -0
  933. package/dist/modules/forms/frontend/f/[slug]/page.js +12 -0
  934. package/dist/modules/forms/frontend/f/[slug]/page.js.map +7 -0
  935. package/dist/modules/forms/frontend/f/[slug]/page.meta.js +11 -0
  936. package/dist/modules/forms/frontend/f/[slug]/page.meta.js.map +7 -0
  937. package/dist/modules/forms/frontend/forms/[id]/run/page.js +62 -0
  938. package/dist/modules/forms/frontend/forms/[id]/run/page.js.map +7 -0
  939. package/dist/modules/forms/frontend/forms/[id]/run/page.meta.js +11 -0
  940. package/dist/modules/forms/frontend/forms/[id]/run/page.meta.js.map +7 -0
  941. package/dist/modules/forms/frontend/i/[token]/page.js +12 -0
  942. package/dist/modules/forms/frontend/i/[token]/page.js.map +7 -0
  943. package/dist/modules/forms/frontend/i/[token]/page.meta.js +11 -0
  944. package/dist/modules/forms/frontend/i/[token]/page.meta.js.map +7 -0
  945. package/dist/modules/forms/index.js +20 -0
  946. package/dist/modules/forms/index.js.map +7 -0
  947. package/dist/modules/forms/lib/embed-frame-policy.js +68 -0
  948. package/dist/modules/forms/lib/embed-frame-policy.js.map +7 -0
  949. package/dist/modules/forms/lib/form-definition-slicing.js +38 -0
  950. package/dist/modules/forms/lib/form-definition-slicing.js.map +7 -0
  951. package/dist/modules/forms/lib/log-redaction.js +38 -0
  952. package/dist/modules/forms/lib/log-redaction.js.map +7 -0
  953. package/dist/modules/forms/lib/navigable-url.js +24 -0
  954. package/dist/modules/forms/lib/navigable-url.js.map +7 -0
  955. package/dist/modules/forms/lib/retention.js +20 -0
  956. package/dist/modules/forms/lib/retention.js.map +7 -0
  957. package/dist/modules/forms/lib/runtime-principal.js +59 -0
  958. package/dist/modules/forms/lib/runtime-principal.js.map +7 -0
  959. package/dist/modules/forms/migrations/Migration20260508135459_forms.js +17 -0
  960. package/dist/modules/forms/migrations/Migration20260508135459_forms.js.map +7 -0
  961. package/dist/modules/forms/migrations/Migration20260508140932_forms.js +23 -0
  962. package/dist/modules/forms/migrations/Migration20260508140932_forms.js.map +7 -0
  963. package/dist/modules/forms/migrations/Migration20260508155737_forms.js +15 -0
  964. package/dist/modules/forms/migrations/Migration20260508155737_forms.js.map +7 -0
  965. package/dist/modules/forms/migrations/Migration20260520120000_forms.js +23 -0
  966. package/dist/modules/forms/migrations/Migration20260520120000_forms.js.map +7 -0
  967. package/dist/modules/forms/migrations/Migration20260521090000_forms.js +13 -0
  968. package/dist/modules/forms/migrations/Migration20260521090000_forms.js.map +7 -0
  969. package/dist/modules/forms/migrations/Migration20260521120000_forms.js +17 -0
  970. package/dist/modules/forms/migrations/Migration20260521120000_forms.js.map +7 -0
  971. package/dist/modules/forms/runner/FormRunner.js +786 -0
  972. package/dist/modules/forms/runner/FormRunner.js.map +7 -0
  973. package/dist/modules/forms/runner/MatrixField.js +150 -0
  974. package/dist/modules/forms/runner/MatrixField.js.map +7 -0
  975. package/dist/modules/forms/runner/RankingField.js +131 -0
  976. package/dist/modules/forms/runner/RankingField.js.map +7 -0
  977. package/dist/modules/forms/runner/ScaleField.js +78 -0
  978. package/dist/modules/forms/runner/ScaleField.js.map +7 -0
  979. package/dist/modules/forms/runner/SignatureField.js +132 -0
  980. package/dist/modules/forms/runner/SignatureField.js.map +7 -0
  981. package/dist/modules/forms/runner/tamper-check.js +85 -0
  982. package/dist/modules/forms/runner/tamper-check.js.map +7 -0
  983. package/dist/modules/forms/schema/address-countries.js +43 -0
  984. package/dist/modules/forms/schema/address-countries.js.map +7 -0
  985. package/dist/modules/forms/schema/field-type-patterns.js +15 -0
  986. package/dist/modules/forms/schema/field-type-patterns.js.map +7 -0
  987. package/dist/modules/forms/schema/field-type-registry-advanced.js +32 -0
  988. package/dist/modules/forms/schema/field-type-registry-advanced.js.map +7 -0
  989. package/dist/modules/forms/schema/field-type-registry.js +625 -0
  990. package/dist/modules/forms/schema/field-type-registry.js.map +7 -0
  991. package/dist/modules/forms/schema/file-field.js +64 -0
  992. package/dist/modules/forms/schema/file-field.js.map +7 -0
  993. package/dist/modules/forms/schema/group-field.js +143 -0
  994. package/dist/modules/forms/schema/group-field.js.map +7 -0
  995. package/dist/modules/forms/schema/jsonlogic-grammar.js +66 -0
  996. package/dist/modules/forms/schema/jsonlogic-grammar.js.map +7 -0
  997. package/dist/modules/forms/schema/jsonschema-extensions.js +739 -0
  998. package/dist/modules/forms/schema/jsonschema-extensions.js.map +7 -0
  999. package/dist/modules/forms/schema/layout-catalog.js +38 -0
  1000. package/dist/modules/forms/schema/layout-catalog.js.map +7 -0
  1001. package/dist/modules/forms/schema/signature-field.js +67 -0
  1002. package/dist/modules/forms/schema/signature-field.js.map +7 -0
  1003. package/dist/modules/forms/schema/style-extensions.js +77 -0
  1004. package/dist/modules/forms/schema/style-extensions.js.map +7 -0
  1005. package/dist/modules/forms/schema/style-validators.js +181 -0
  1006. package/dist/modules/forms/schema/style-validators.js.map +7 -0
  1007. package/dist/modules/forms/services/access-audit-logger.js +179 -0
  1008. package/dist/modules/forms/services/access-audit-logger.js.map +7 -0
  1009. package/dist/modules/forms/services/analytics-service.js +306 -0
  1010. package/dist/modules/forms/services/analytics-service.js.map +7 -0
  1011. package/dist/modules/forms/services/anonymize-service.js +123 -0
  1012. package/dist/modules/forms/services/anonymize-service.js.map +7 -0
  1013. package/dist/modules/forms/services/attachment-service.js +123 -0
  1014. package/dist/modules/forms/services/attachment-service.js.map +7 -0
  1015. package/dist/modules/forms/services/captcha-verifier.js +76 -0
  1016. package/dist/modules/forms/services/captcha-verifier.js.map +7 -0
  1017. package/dist/modules/forms/services/consent-record-service.js +96 -0
  1018. package/dist/modules/forms/services/consent-record-service.js.map +7 -0
  1019. package/dist/modules/forms/services/distribution-service.js +366 -0
  1020. package/dist/modules/forms/services/distribution-service.js.map +7 -0
  1021. package/dist/modules/forms/services/distribution-token.js +93 -0
  1022. package/dist/modules/forms/services/distribution-token.js.map +7 -0
  1023. package/dist/modules/forms/services/encryption-service.js +328 -0
  1024. package/dist/modules/forms/services/encryption-service.js.map +7 -0
  1025. package/dist/modules/forms/services/export-service.js +210 -0
  1026. package/dist/modules/forms/services/export-service.js.map +7 -0
  1027. package/dist/modules/forms/services/field-validation-service.js +168 -0
  1028. package/dist/modules/forms/services/field-validation-service.js.map +7 -0
  1029. package/dist/modules/forms/services/form-logic-evaluator.js +517 -0
  1030. package/dist/modules/forms/services/form-logic-evaluator.js.map +7 -0
  1031. package/dist/modules/forms/services/form-version-compiler.js +518 -0
  1032. package/dist/modules/forms/services/form-version-compiler.js.map +7 -0
  1033. package/dist/modules/forms/services/form-version-differ.js +89 -0
  1034. package/dist/modules/forms/services/form-version-differ.js.map +7 -0
  1035. package/dist/modules/forms/services/jsonlogic-evaluator.js +171 -0
  1036. package/dist/modules/forms/services/jsonlogic-evaluator.js.map +7 -0
  1037. package/dist/modules/forms/services/pdf-snapshot-service.js +526 -0
  1038. package/dist/modules/forms/services/pdf-snapshot-service.js.map +7 -0
  1039. package/dist/modules/forms/services/prefill-resolver.js +53 -0
  1040. package/dist/modules/forms/services/prefill-resolver.js.map +7 -0
  1041. package/dist/modules/forms/services/role-policy-service.js +55 -0
  1042. package/dist/modules/forms/services/role-policy-service.js.map +7 -0
  1043. package/dist/modules/forms/services/style-compiler.js +234 -0
  1044. package/dist/modules/forms/services/style-compiler.js.map +7 -0
  1045. package/dist/modules/forms/services/submission-service.js +858 -0
  1046. package/dist/modules/forms/services/submission-service.js.map +7 -0
  1047. package/dist/modules/forms/services/upload-scanner.js +9 -0
  1048. package/dist/modules/forms/services/upload-scanner.js.map +7 -0
  1049. package/dist/modules/forms/services/upload-validation.js +54 -0
  1050. package/dist/modules/forms/services/upload-validation.js.map +7 -0
  1051. package/dist/modules/forms/services/visibility-resolver.js +30 -0
  1052. package/dist/modules/forms/services/visibility-resolver.js.map +7 -0
  1053. package/dist/modules/forms/setup.js +18 -0
  1054. package/dist/modules/forms/setup.js.map +7 -0
  1055. package/dist/modules/forms/subscribers/forms-consent-projector.js +58 -0
  1056. package/dist/modules/forms/subscribers/forms-consent-projector.js.map +7 -0
  1057. package/dist/modules/forms/subscribers/forms-pdf-snapshot.js +68 -0
  1058. package/dist/modules/forms/subscribers/forms-pdf-snapshot.js.map +7 -0
  1059. package/dist/modules/forms/subscribers/forms-webhook-bridge-anonymized.js +29 -0
  1060. package/dist/modules/forms/subscribers/forms-webhook-bridge-anonymized.js.map +7 -0
  1061. package/dist/modules/forms/subscribers/forms-webhook-bridge.js +35 -0
  1062. package/dist/modules/forms/subscribers/forms-webhook-bridge.js.map +7 -0
  1063. package/dist/modules/forms/subscribers/invitation-email.js +100 -0
  1064. package/dist/modules/forms/subscribers/invitation-email.js.map +7 -0
  1065. package/dist/modules/forms/translations.js +10 -0
  1066. package/dist/modules/forms/translations.js.map +7 -0
  1067. package/dist/modules/forms/ui/admin/forms/[id]/distributions/CreateDistributionDialog.js +376 -0
  1068. package/dist/modules/forms/ui/admin/forms/[id]/distributions/CreateDistributionDialog.js.map +7 -0
  1069. package/dist/modules/forms/ui/admin/forms/[id]/distributions/DistributionsPanel.js +313 -0
  1070. package/dist/modules/forms/ui/admin/forms/[id]/distributions/DistributionsPanel.js.map +7 -0
  1071. package/dist/modules/forms/ui/admin/forms/[id]/distributions/EmbedSettingsDialog.js +263 -0
  1072. package/dist/modules/forms/ui/admin/forms/[id]/distributions/EmbedSettingsDialog.js.map +7 -0
  1073. package/dist/modules/forms/ui/admin/forms/[id]/distributions/RecipientsTable.js +373 -0
  1074. package/dist/modules/forms/ui/admin/forms/[id]/distributions/RecipientsTable.js.map +7 -0
  1075. package/dist/modules/forms/ui/public/EmbeddedForm.js +166 -0
  1076. package/dist/modules/forms/ui/public/EmbeddedForm.js.map +7 -0
  1077. package/dist/modules/forms/ui/public/FormRunner.js +359 -0
  1078. package/dist/modules/forms/ui/public/FormRunner.js.map +7 -0
  1079. package/dist/modules/forms/ui/public/FormTrigger.js +45 -0
  1080. package/dist/modules/forms/ui/public/FormTrigger.js.map +7 -0
  1081. package/dist/modules/forms/ui/public/PublicFormRunnerPage.js +14 -0
  1082. package/dist/modules/forms/ui/public/PublicFormRunnerPage.js.map +7 -0
  1083. package/dist/modules/forms/ui/public/components/CompletionScreen.js +55 -0
  1084. package/dist/modules/forms/ui/public/components/CompletionScreen.js.map +7 -0
  1085. package/dist/modules/forms/ui/public/components/LocaleSwitch.js +28 -0
  1086. package/dist/modules/forms/ui/public/components/LocaleSwitch.js.map +7 -0
  1087. package/dist/modules/forms/ui/public/components/ResumeGate.js +52 -0
  1088. package/dist/modules/forms/ui/public/components/ResumeGate.js.map +7 -0
  1089. package/dist/modules/forms/ui/public/components/ReviewStep.js +90 -0
  1090. package/dist/modules/forms/ui/public/components/ReviewStep.js.map +7 -0
  1091. package/dist/modules/forms/ui/public/components/SaveIndicator.js +65 -0
  1092. package/dist/modules/forms/ui/public/components/SaveIndicator.js.map +7 -0
  1093. package/dist/modules/forms/ui/public/components/SectionStepper.js +52 -0
  1094. package/dist/modules/forms/ui/public/components/SectionStepper.js.map +7 -0
  1095. package/dist/modules/forms/ui/public/index.js +38 -0
  1096. package/dist/modules/forms/ui/public/index.js.map +7 -0
  1097. package/dist/modules/forms/ui/public/renderers/index.js +737 -0
  1098. package/dist/modules/forms/ui/public/renderers/index.js.map +7 -0
  1099. package/dist/modules/forms/ui/public/state/logic-derivation.js +42 -0
  1100. package/dist/modules/forms/ui/public/state/logic-derivation.js.map +7 -0
  1101. package/dist/modules/forms/ui/public/state/runtime-client.js +306 -0
  1102. package/dist/modules/forms/ui/public/state/runtime-client.js.map +7 -0
  1103. package/dist/modules/forms/ui/public/state/useAutosave.js +64 -0
  1104. package/dist/modules/forms/ui/public/state/useAutosave.js.map +7 -0
  1105. package/dist/modules/forms/ui/public/state/useFormRunner.js +394 -0
  1106. package/dist/modules/forms/ui/public/state/useFormRunner.js.map +7 -0
  1107. package/dist/modules/forms/ui/public/style/LogoHeader.js +33 -0
  1108. package/dist/modules/forms/ui/public/style/LogoHeader.js.map +7 -0
  1109. package/dist/modules/forms/ui/public/style/applyStyle.js +12 -0
  1110. package/dist/modules/forms/ui/public/style/applyStyle.js.map +7 -0
  1111. package/dist/modules/forms/ui/public/types.js +18 -0
  1112. package/dist/modules/forms/ui/public/types.js.map +7 -0
  1113. package/dist/modules/forms/widgets/injection/access-audit-panel/widget.js +100 -0
  1114. package/dist/modules/forms/widgets/injection/access-audit-panel/widget.js.map +7 -0
  1115. package/dist/modules/forms/widgets/injection/anonymize-button/widget.js +148 -0
  1116. package/dist/modules/forms/widgets/injection/anonymize-button/widget.js.map +7 -0
  1117. package/dist/modules/forms/widgets/injection/audit-format.js +33 -0
  1118. package/dist/modules/forms/widgets/injection/audit-format.js.map +7 -0
  1119. package/dist/modules/forms/widgets/injection/context.js +5 -0
  1120. package/dist/modules/forms/widgets/injection/context.js.map +7 -0
  1121. package/dist/modules/forms/widgets/injection/embedded-form/widget.js +52 -0
  1122. package/dist/modules/forms/widgets/injection/embedded-form/widget.js.map +7 -0
  1123. package/dist/modules/forms/widgets/injection/pdf-download-button/widget.js +83 -0
  1124. package/dist/modules/forms/widgets/injection/pdf-download-button/widget.js.map +7 -0
  1125. package/dist/modules/forms/widgets/injection/self-audit-footer/widget.js +38 -0
  1126. package/dist/modules/forms/widgets/injection/self-audit-footer/widget.js.map +7 -0
  1127. package/dist/modules/forms/widgets/injection-table.js +32 -0
  1128. package/dist/modules/forms/widgets/injection-table.js.map +7 -0
  1129. package/dist/modules/forms/workers/pdf-snapshot.js +60 -0
  1130. package/dist/modules/forms/workers/pdf-snapshot.js.map +7 -0
  1131. package/dist/modules/forms/workers/retention-purge.js +112 -0
  1132. package/dist/modules/forms/workers/retention-purge.js.map +7 -0
  1133. package/dist/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.js +7 -1
  1134. package/dist/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.js.map +2 -2
  1135. package/dist/modules/inbox_ops/data/validators.js +2 -2
  1136. package/dist/modules/inbox_ops/data/validators.js.map +2 -2
  1137. package/dist/modules/inbox_ops/lib/llmProvider.js +5 -1
  1138. package/dist/modules/inbox_ops/lib/llmProvider.js.map +2 -2
  1139. package/dist/modules/inbox_ops/widgets/notifications/ProposalCreatedRenderer.js +2 -2
  1140. package/dist/modules/inbox_ops/widgets/notifications/ProposalCreatedRenderer.js.map +2 -2
  1141. package/dist/modules/integrations/di.js +3 -1
  1142. package/dist/modules/integrations/di.js.map +2 -2
  1143. package/dist/modules/integrations/lib/credentials-service.js +29 -36
  1144. package/dist/modules/integrations/lib/credentials-service.js.map +2 -2
  1145. package/dist/modules/messages/api/[id]/attachments/route.js +7 -3
  1146. package/dist/modules/messages/api/[id]/attachments/route.js.map +2 -2
  1147. package/dist/modules/messages/api/[id]/forward-preview/route.js +4 -3
  1148. package/dist/modules/messages/api/[id]/forward-preview/route.js.map +2 -2
  1149. package/dist/modules/messages/api/[id]/route.js +29 -3
  1150. package/dist/modules/messages/api/[id]/route.js.map +2 -2
  1151. package/dist/modules/messages/api/route.js +91 -2
  1152. package/dist/modules/messages/api/route.js.map +2 -2
  1153. package/dist/modules/messages/commands/messages.js +40 -6
  1154. package/dist/modules/messages/commands/messages.js.map +2 -2
  1155. package/dist/modules/messages/components/ComposeMessagePageClient.js +24 -1
  1156. package/dist/modules/messages/components/ComposeMessagePageClient.js.map +2 -2
  1157. package/dist/modules/messages/data/validators.js +11 -1
  1158. package/dist/modules/messages/data/validators.js.map +2 -2
  1159. package/dist/modules/messages/lib/channelThreadAccess.js +30 -0
  1160. package/dist/modules/messages/lib/channelThreadAccess.js.map +7 -0
  1161. package/dist/modules/messages/lib/composeSenderDelegation.js +87 -0
  1162. package/dist/modules/messages/lib/composeSenderDelegation.js.map +7 -0
  1163. package/dist/modules/messages/lib/composeSenderOptions.js +24 -0
  1164. package/dist/modules/messages/lib/composeSenderOptions.js.map +7 -0
  1165. package/dist/modules/messages/lib/email-sender.js +1 -11
  1166. package/dist/modules/messages/lib/email-sender.js.map +2 -2
  1167. package/dist/modules/messages/lib/forwarding.js +4 -4
  1168. package/dist/modules/messages/lib/forwarding.js.map +2 -2
  1169. package/dist/modules/messages/lib/markdownEmailBody.js +15 -0
  1170. package/dist/modules/messages/lib/markdownEmailBody.js.map +7 -0
  1171. package/dist/modules/messages/lib/messageSourceEntityTypes.js +7 -0
  1172. package/dist/modules/messages/lib/messageSourceEntityTypes.js.map +7 -0
  1173. package/dist/modules/messages/lib/routeHelpers.js +43 -0
  1174. package/dist/modules/messages/lib/routeHelpers.js.map +2 -2
  1175. package/dist/modules/messages/subscribers/message-notification.js +30 -1
  1176. package/dist/modules/messages/subscribers/message-notification.js.map +2 -2
  1177. package/dist/modules/notifications/api/[id]/action/route.js +2 -1
  1178. package/dist/modules/notifications/api/[id]/action/route.js.map +2 -2
  1179. package/dist/modules/notifications/api/openapi.js +2 -1
  1180. package/dist/modules/notifications/api/openapi.js.map +2 -2
  1181. package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js +47 -28
  1182. package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js.map +2 -2
  1183. package/dist/modules/notifications/lib/deliveryConfig.js +27 -2
  1184. package/dist/modules/notifications/lib/deliveryConfig.js.map +2 -2
  1185. package/dist/modules/notifications/lib/notificationMapper.js +3 -1
  1186. package/dist/modules/notifications/lib/notificationMapper.js.map +2 -2
  1187. package/dist/modules/notifications/lib/safeHref.js +4 -0
  1188. package/dist/modules/notifications/lib/safeHref.js.map +2 -2
  1189. package/dist/modules/planner/api/availability-date-specific.js +2 -1
  1190. package/dist/modules/planner/api/availability-date-specific.js.map +2 -2
  1191. package/dist/modules/planner/api/availability-weekly.js +2 -1
  1192. package/dist/modules/planner/api/availability-weekly.js.map +2 -2
  1193. package/dist/modules/progress/api/active/route.js +14 -2
  1194. package/dist/modules/progress/api/active/route.js.map +2 -2
  1195. package/dist/modules/progress/api/jobs/[id]/route.js +38 -22
  1196. package/dist/modules/progress/api/jobs/[id]/route.js.map +2 -2
  1197. package/dist/modules/progress/api/jobs/route.js +20 -6
  1198. package/dist/modules/progress/api/jobs/route.js.map +2 -2
  1199. package/dist/modules/progress/api/requestScope.js +32 -0
  1200. package/dist/modules/progress/api/requestScope.js.map +7 -0
  1201. package/dist/modules/progress/lib/organizationScope.js +10 -0
  1202. package/dist/modules/progress/lib/organizationScope.js.map +7 -0
  1203. package/dist/modules/progress/lib/progressService.js.map +2 -2
  1204. package/dist/modules/progress/lib/progressServiceImpl.js +48 -15
  1205. package/dist/modules/progress/lib/progressServiceImpl.js.map +2 -2
  1206. package/dist/modules/push_notifications/api/custom-send/route.js +4 -1
  1207. package/dist/modules/push_notifications/api/custom-send/route.js.map +2 -2
  1208. package/dist/modules/query_index/api/status.js +5 -3
  1209. package/dist/modules/query_index/api/status.js.map +2 -2
  1210. package/dist/modules/query_index/di.js +2 -1
  1211. package/dist/modules/query_index/di.js.map +2 -2
  1212. package/dist/modules/query_index/lib/engine.js +2 -1
  1213. package/dist/modules/query_index/lib/engine.js.map +2 -2
  1214. package/dist/modules/query_index/lib/request-encryption.js +16 -0
  1215. package/dist/modules/query_index/lib/request-encryption.js.map +7 -0
  1216. package/dist/modules/query_index/lib/search-tokens.js +31 -1
  1217. package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
  1218. package/dist/modules/resources/api/resources/tags/assign/route.js +2 -1
  1219. package/dist/modules/resources/api/resources/tags/assign/route.js.map +2 -2
  1220. package/dist/modules/resources/api/resources/tags/unassign/route.js +2 -1
  1221. package/dist/modules/resources/api/resources/tags/unassign/route.js.map +2 -2
  1222. package/dist/modules/resources/commands/activities.js +2 -2
  1223. package/dist/modules/resources/commands/activities.js.map +2 -2
  1224. package/dist/modules/sales/api/document-history/route.js +5 -1
  1225. package/dist/modules/sales/api/document-history/route.js.map +2 -2
  1226. package/dist/modules/sales/api/document-numbers/route.js +2 -1
  1227. package/dist/modules/sales/api/document-numbers/route.js.map +2 -2
  1228. package/dist/modules/sales/api/quotes/convert/route.js +2 -1
  1229. package/dist/modules/sales/api/quotes/convert/route.js.map +2 -2
  1230. package/dist/modules/sales/api/quotes/send/route.js +2 -1
  1231. package/dist/modules/sales/api/quotes/send/route.js.map +2 -2
  1232. package/dist/modules/sales/api/settings/document-numbers/route.js +7 -1
  1233. package/dist/modules/sales/api/settings/document-numbers/route.js.map +2 -2
  1234. package/dist/modules/sales/api/settings/order-editing/route.js +7 -1
  1235. package/dist/modules/sales/api/settings/order-editing/route.js.map +2 -2
  1236. package/dist/modules/sales/commands/documents.js +354 -138
  1237. package/dist/modules/sales/commands/documents.js.map +3 -3
  1238. package/dist/modules/sales/commands/payments.js +2 -1
  1239. package/dist/modules/sales/commands/payments.js.map +2 -2
  1240. package/dist/modules/sales/commands/settings.js +25 -5
  1241. package/dist/modules/sales/commands/settings.js.map +2 -2
  1242. package/dist/modules/sales/commands/shipments.js +2 -1
  1243. package/dist/modules/sales/commands/shipments.js.map +2 -2
  1244. package/dist/modules/sales/components/DocumentNumberSettings.js +32 -21
  1245. package/dist/modules/sales/components/DocumentNumberSettings.js.map +2 -2
  1246. package/dist/modules/sales/components/documents/ItemsSection.js +49 -11
  1247. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  1248. package/dist/modules/sales/lib/lineSnapshots.js +19 -0
  1249. package/dist/modules/sales/lib/lineSnapshots.js.map +2 -2
  1250. package/dist/modules/sales/setup.js +4 -4
  1251. package/dist/modules/sales/setup.js.map +2 -2
  1252. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js +2 -2
  1253. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js.map +2 -2
  1254. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js +2 -2
  1255. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js.map +2 -2
  1256. package/dist/modules/staff/api/leave-requests/accept/route.js +2 -1
  1257. package/dist/modules/staff/api/leave-requests/accept/route.js.map +2 -2
  1258. package/dist/modules/staff/api/leave-requests/reject/route.js +2 -1
  1259. package/dist/modules/staff/api/leave-requests/reject/route.js.map +2 -2
  1260. package/dist/modules/staff/api/leave-requests.js +2 -1
  1261. package/dist/modules/staff/api/leave-requests.js.map +2 -2
  1262. package/dist/modules/staff/api/team-members/self/route.js +2 -1
  1263. package/dist/modules/staff/api/team-members/self/route.js.map +2 -2
  1264. package/dist/modules/staff/api/team-members/tags/assign/route.js +2 -1
  1265. package/dist/modules/staff/api/team-members/tags/assign/route.js.map +2 -2
  1266. package/dist/modules/staff/api/team-members/tags/unassign/route.js +2 -1
  1267. package/dist/modules/staff/api/team-members/tags/unassign/route.js.map +2 -2
  1268. package/dist/modules/staff/api/timesheets/_shared/withTimesheetInterceptors.js +12 -11
  1269. package/dist/modules/staff/api/timesheets/_shared/withTimesheetInterceptors.js.map +2 -2
  1270. package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js +2 -1
  1271. package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js.map +2 -2
  1272. package/dist/modules/staff/api/timesheets/my-projects/route.js +2 -1
  1273. package/dist/modules/staff/api/timesheets/my-projects/route.js.map +2 -2
  1274. package/dist/modules/staff/api/timesheets/my-work/route.js +2 -1
  1275. package/dist/modules/staff/api/timesheets/my-work/route.js.map +2 -2
  1276. package/dist/modules/staff/api/timesheets/projects/kpis/route.js +2 -1
  1277. package/dist/modules/staff/api/timesheets/projects/kpis/route.js.map +2 -2
  1278. package/dist/modules/staff/api/timesheets/reports/[id]/close/route.js +2 -1
  1279. package/dist/modules/staff/api/timesheets/reports/[id]/close/route.js.map +2 -2
  1280. package/dist/modules/staff/api/timesheets/reports/[id]/export/route.js +3 -2
  1281. package/dist/modules/staff/api/timesheets/reports/[id]/export/route.js.map +2 -2
  1282. package/dist/modules/staff/api/timesheets/reports/[id]/sheet/route.js +3 -2
  1283. package/dist/modules/staff/api/timesheets/reports/[id]/sheet/route.js.map +2 -2
  1284. package/dist/modules/staff/api/timesheets/reports/[id]/unlock/route.js +3 -2
  1285. package/dist/modules/staff/api/timesheets/reports/[id]/unlock/route.js.map +2 -2
  1286. package/dist/modules/staff/api/timesheets/reports/preview/route.js +2 -1
  1287. package/dist/modules/staff/api/timesheets/reports/preview/route.js.map +2 -2
  1288. package/dist/modules/staff/api/timesheets/reports/shared.js +2 -1
  1289. package/dist/modules/staff/api/timesheets/reports/shared.js.map +2 -2
  1290. package/dist/modules/staff/api/timesheets/settings/reapply-rounding/route.js +2 -1
  1291. package/dist/modules/staff/api/timesheets/settings/reapply-rounding/route.js.map +2 -2
  1292. package/dist/modules/staff/api/timesheets/tags/entry-assignments/route.js +2 -1
  1293. package/dist/modules/staff/api/timesheets/tags/entry-assignments/route.js.map +2 -2
  1294. package/dist/modules/staff/api/timesheets/tags/task-assignments/route.js +2 -1
  1295. package/dist/modules/staff/api/timesheets/tags/task-assignments/route.js.map +2 -2
  1296. package/dist/modules/staff/api/timesheets/tasks/[id]/comments/route.js +2 -1
  1297. package/dist/modules/staff/api/timesheets/tasks/[id]/comments/route.js.map +2 -2
  1298. package/dist/modules/staff/api/timesheets/tasks/[id]/status/route.js +2 -1
  1299. package/dist/modules/staff/api/timesheets/tasks/[id]/status/route.js.map +2 -2
  1300. package/dist/modules/staff/api/timesheets/time-entries/[id]/duplicate/route.js +3 -2
  1301. package/dist/modules/staff/api/timesheets/time-entries/[id]/duplicate/route.js.map +2 -2
  1302. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js +2 -1
  1303. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js.map +2 -2
  1304. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js +2 -1
  1305. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js.map +2 -2
  1306. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js +2 -1
  1307. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js.map +2 -2
  1308. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js +2 -1
  1309. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js.map +2 -2
  1310. package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js +2 -1
  1311. package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js.map +2 -2
  1312. package/dist/modules/staff/api/timesheets/time-entries/copy-day/route.js +3 -2
  1313. package/dist/modules/staff/api/timesheets/time-entries/copy-day/route.js.map +2 -2
  1314. package/dist/modules/staff/api/timesheets/time-entries/overlaps/route.js +2 -1
  1315. package/dist/modules/staff/api/timesheets/time-entries/overlaps/route.js.map +2 -2
  1316. package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js +3 -2
  1317. package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js.map +2 -2
  1318. package/dist/modules/staff/api/timesheets/time-projects/[id]/change-currency/route.js +3 -2
  1319. package/dist/modules/staff/api/timesheets/time-projects/[id]/change-currency/route.js.map +2 -2
  1320. package/dist/modules/staff/api/timesheets/time-projects/route.js +2 -1
  1321. package/dist/modules/staff/api/timesheets/time-projects/route.js.map +2 -2
  1322. package/dist/modules/staff/commands/activities.js +2 -2
  1323. package/dist/modules/staff/commands/activities.js.map +2 -2
  1324. package/dist/modules/staff/commands/timesheets-entries.js.map +2 -2
  1325. package/dist/modules/staff/commands/timesheets-reports.js +55 -14
  1326. package/dist/modules/staff/commands/timesheets-reports.js.map +2 -2
  1327. package/dist/modules/staff/lib/timesheets-reports/buildReportSheet.js +2 -1
  1328. package/dist/modules/staff/lib/timesheets-reports/buildReportSheet.js.map +2 -2
  1329. package/dist/modules/staff/lib/timesheets-reports/loadReportData.js +32 -3
  1330. package/dist/modules/staff/lib/timesheets-reports/loadReportData.js.map +2 -2
  1331. package/dist/modules/staff/lib/timesheets-reports/reportPeriod.js +16 -0
  1332. package/dist/modules/staff/lib/timesheets-reports/reportPeriod.js.map +7 -0
  1333. package/dist/modules/staff/lib/timesheets-ui/CalendarPicker.js +15 -10
  1334. package/dist/modules/staff/lib/timesheets-ui/CalendarPicker.js.map +2 -2
  1335. package/dist/modules/sync_excel/api/import/route.js +35 -12
  1336. package/dist/modules/sync_excel/api/import/route.js.map +2 -2
  1337. package/dist/modules/sync_excel/api/upload/route.js +29 -4
  1338. package/dist/modules/sync_excel/api/upload/route.js.map +2 -2
  1339. package/dist/modules/translations/api/context.js +2 -1
  1340. package/dist/modules/translations/api/context.js.map +2 -2
  1341. package/dist/modules/warranty_claims/api/ai/assess/route.js +2 -1
  1342. package/dist/modules/warranty_claims/api/ai/assess/route.js.map +2 -2
  1343. package/dist/modules/warranty_claims/api/ai/draft-reply/route.js +2 -1
  1344. package/dist/modules/warranty_claims/api/ai/draft-reply/route.js.map +2 -2
  1345. package/dist/modules/warranty_claims/api/ai/suggest/route.js +2 -1
  1346. package/dist/modules/warranty_claims/api/ai/suggest/route.js.map +2 -2
  1347. package/dist/modules/warranty_claims/api/assign/route.js +2 -1
  1348. package/dist/modules/warranty_claims/api/assign/route.js.map +2 -2
  1349. package/dist/modules/warranty_claims/api/credit-memo/route.js +2 -1
  1350. package/dist/modules/warranty_claims/api/credit-memo/route.js.map +2 -2
  1351. package/dist/modules/warranty_claims/api/entitlement/route.js +2 -1
  1352. package/dist/modules/warranty_claims/api/entitlement/route.js.map +2 -2
  1353. package/dist/modules/warranty_claims/api/events/route.js +2 -1
  1354. package/dist/modules/warranty_claims/api/events/route.js.map +2 -2
  1355. package/dist/modules/warranty_claims/api/external/claims/route.js +2 -1
  1356. package/dist/modules/warranty_claims/api/external/claims/route.js.map +2 -2
  1357. package/dist/modules/warranty_claims/api/receiving/route.js +2 -1
  1358. package/dist/modules/warranty_claims/api/receiving/route.js.map +2 -2
  1359. package/dist/modules/warranty_claims/api/replacement-order/route.js +2 -1
  1360. package/dist/modules/warranty_claims/api/replacement-order/route.js.map +2 -2
  1361. package/dist/modules/warranty_claims/api/return-label/route.js +2 -1
  1362. package/dist/modules/warranty_claims/api/return-label/route.js.map +2 -2
  1363. package/dist/modules/warranty_claims/api/risk/route.js +2 -1
  1364. package/dist/modules/warranty_claims/api/risk/route.js.map +2 -2
  1365. package/dist/modules/warranty_claims/api/sales-return/route.js +2 -1
  1366. package/dist/modules/warranty_claims/api/sales-return/route.js.map +2 -2
  1367. package/dist/modules/warranty_claims/api/settings-general/route.js +2 -1
  1368. package/dist/modules/warranty_claims/api/settings-general/route.js.map +2 -2
  1369. package/dist/modules/warranty_claims/api/stats/route.js +9 -5
  1370. package/dist/modules/warranty_claims/api/stats/route.js.map +2 -2
  1371. package/dist/modules/warranty_claims/api/submit/route.js +2 -1
  1372. package/dist/modules/warranty_claims/api/submit/route.js.map +2 -2
  1373. package/dist/modules/warranty_claims/api/transition/route.js +2 -1
  1374. package/dist/modules/warranty_claims/api/transition/route.js.map +2 -2
  1375. package/dist/modules/warranty_claims/api/vendor-recovery/route.js +2 -1
  1376. package/dist/modules/warranty_claims/api/vendor-recovery/route.js.map +2 -2
  1377. package/dist/modules/warranty_claims/api/vendor-recovery-suggestions/route.js +2 -1
  1378. package/dist/modules/warranty_claims/api/vendor-recovery-suggestions/route.js.map +2 -2
  1379. package/dist/modules/warranty_claims/widgets/notifications/WarrantyClaimNotificationRenderer.js +1 -1
  1380. package/dist/modules/warranty_claims/widgets/notifications/WarrantyClaimNotificationRenderer.js.map +2 -2
  1381. package/dist/modules/wms/api/dashboard/operational/route.js +2 -1
  1382. package/dist/modules/wms/api/dashboard/operational/route.js.map +2 -2
  1383. package/dist/modules/wms/api/inventory/cycle-count/route.js +1 -0
  1384. package/dist/modules/wms/api/inventory/cycle-count/route.js.map +2 -2
  1385. package/dist/modules/wms/api/inventory/helpers.js +2 -1
  1386. package/dist/modules/wms/api/inventory/helpers.js.map +2 -2
  1387. package/dist/modules/wms/api/inventory/import/helpers.js +2 -1
  1388. package/dist/modules/wms/api/inventory/import/helpers.js.map +2 -2
  1389. package/dist/modules/wms/api/sales-orders/[salesOrderId]/warehouse-assignment/route.js +2 -1
  1390. package/dist/modules/wms/api/sales-orders/[salesOrderId]/warehouse-assignment/route.js.map +2 -2
  1391. package/dist/modules/wms/commands/inventory-actions.js +39 -1
  1392. package/dist/modules/wms/commands/inventory-actions.js.map +2 -2
  1393. package/dist/modules/wms/components/backend/CycleCountWizardDialog.js +14 -1
  1394. package/dist/modules/wms/components/backend/CycleCountWizardDialog.js.map +2 -2
  1395. package/dist/modules/wms/di.js +5 -0
  1396. package/dist/modules/wms/di.js.map +2 -2
  1397. package/dist/modules/wms/lib/availabilityCache.js +86 -0
  1398. package/dist/modules/wms/lib/availabilityCache.js.map +7 -0
  1399. package/dist/modules/wms/lib/availabilityCalculation.js +212 -0
  1400. package/dist/modules/wms/lib/availabilityCalculation.js.map +7 -0
  1401. package/dist/modules/wms/lib/availabilityProvider.js +24 -0
  1402. package/dist/modules/wms/lib/availabilityProvider.js.map +7 -0
  1403. package/dist/modules/wms/lib/loadOperationalDashboard.js +42 -5
  1404. package/dist/modules/wms/lib/loadOperationalDashboard.js.map +2 -2
  1405. package/dist/modules/wms/lib/lowStockBalanceFilter.js +23 -10
  1406. package/dist/modules/wms/lib/lowStockBalanceFilter.js.map +2 -2
  1407. package/dist/modules/wms/lib/sqlInClause.js +9 -0
  1408. package/dist/modules/wms/lib/sqlInClause.js.map +7 -0
  1409. package/dist/modules/wms/lib/tryResolve.js +11 -0
  1410. package/dist/modules/wms/lib/tryResolve.js.map +7 -0
  1411. package/dist/modules/wms/subscribers/invalidate-availability-cache-policy.js +14 -0
  1412. package/dist/modules/wms/subscribers/invalidate-availability-cache-policy.js.map +7 -0
  1413. package/dist/modules/wms/subscribers/invalidate-availability-cache-profile.js +14 -0
  1414. package/dist/modules/wms/subscribers/invalidate-availability-cache-profile.js.map +7 -0
  1415. package/dist/modules/wms/subscribers/invalidate-availability-cache.js +16 -0
  1416. package/dist/modules/wms/subscribers/invalidate-availability-cache.js.map +7 -0
  1417. package/dist/modules/wms/widgets/notifications/WmsLowStockRenderer.js +2 -2
  1418. package/dist/modules/wms/widgets/notifications/WmsLowStockRenderer.js.map +2 -2
  1419. package/dist/modules/wms/widgets/notifications/WmsReservationShortfallRenderer.js +4 -3
  1420. package/dist/modules/wms/widgets/notifications/WmsReservationShortfallRenderer.js.map +2 -2
  1421. package/dist/modules/workflows/api/commands/route.js +4 -1
  1422. package/dist/modules/workflows/api/commands/route.js.map +2 -2
  1423. package/dist/modules/workflows/api/definitions/[id]/callers/route.js +4 -1
  1424. package/dist/modules/workflows/api/definitions/[id]/callers/route.js.map +2 -2
  1425. package/dist/modules/workflows/api/definitions/[id]/context-schema/route.js +4 -2
  1426. package/dist/modules/workflows/api/definitions/[id]/context-schema/route.js.map +2 -2
  1427. package/dist/modules/workflows/api/definitions/[id]/customize/route.js +4 -1
  1428. package/dist/modules/workflows/api/definitions/[id]/customize/route.js.map +2 -2
  1429. package/dist/modules/workflows/api/definitions/[id]/draft/route.js +6 -1
  1430. package/dist/modules/workflows/api/definitions/[id]/draft/route.js.map +2 -2
  1431. package/dist/modules/workflows/api/definitions/[id]/publish/route.js +6 -1
  1432. package/dist/modules/workflows/api/definitions/[id]/publish/route.js.map +2 -2
  1433. package/dist/modules/workflows/api/definitions/[id]/reset-to-code/route.js +4 -1
  1434. package/dist/modules/workflows/api/definitions/[id]/reset-to-code/route.js.map +2 -2
  1435. package/dist/modules/workflows/api/definitions/[id]/route.js +5 -3
  1436. package/dist/modules/workflows/api/definitions/[id]/route.js.map +2 -2
  1437. package/dist/modules/workflows/api/definitions/[id]/test-step/route.js +4 -2
  1438. package/dist/modules/workflows/api/definitions/[id]/test-step/route.js.map +2 -2
  1439. package/dist/modules/workflows/api/definitions/generate/route.js +4 -1
  1440. package/dist/modules/workflows/api/definitions/generate/route.js.map +2 -2
  1441. package/dist/modules/workflows/api/definitions/route.js +4 -2
  1442. package/dist/modules/workflows/api/definitions/route.js.map +2 -2
  1443. package/dist/modules/workflows/api/endpoints/route.js +4 -1
  1444. package/dist/modules/workflows/api/endpoints/route.js.map +2 -2
  1445. package/dist/modules/workflows/api/functions/route.js +4 -1
  1446. package/dist/modules/workflows/api/functions/route.js.map +2 -2
  1447. package/dist/modules/workflows/api/grantable-features/route.js +2 -1
  1448. package/dist/modules/workflows/api/grantable-features/route.js.map +2 -2
  1449. package/dist/modules/workflows/api/instances/[id]/advance/route.js +4 -1
  1450. package/dist/modules/workflows/api/instances/[id]/advance/route.js.map +2 -2
  1451. package/dist/modules/workflows/api/instances/[id]/cancel/route.js +4 -1
  1452. package/dist/modules/workflows/api/instances/[id]/cancel/route.js.map +2 -2
  1453. package/dist/modules/workflows/api/instances/[id]/context/route.js +2 -1
  1454. package/dist/modules/workflows/api/instances/[id]/context/route.js.map +2 -2
  1455. package/dist/modules/workflows/api/instances/[id]/rerun-step/route.js +4 -1
  1456. package/dist/modules/workflows/api/instances/[id]/rerun-step/route.js.map +2 -2
  1457. package/dist/modules/workflows/api/instances/[id]/retry/route.js +4 -1
  1458. package/dist/modules/workflows/api/instances/[id]/retry/route.js.map +2 -2
  1459. package/dist/modules/workflows/api/instances/[id]/signal/route.js +4 -1
  1460. package/dist/modules/workflows/api/instances/[id]/signal/route.js.map +2 -2
  1461. package/dist/modules/workflows/api/instances/[id]/step-through/route.js +4 -2
  1462. package/dist/modules/workflows/api/instances/[id]/step-through/route.js.map +2 -2
  1463. package/dist/modules/workflows/api/instances/route.js +4 -2
  1464. package/dist/modules/workflows/api/instances/route.js.map +2 -2
  1465. package/dist/modules/workflows/api/instances/validate-start/route.js +4 -1
  1466. package/dist/modules/workflows/api/instances/validate-start/route.js.map +2 -2
  1467. package/dist/modules/workflows/api/rule-usage/route.js +4 -1
  1468. package/dist/modules/workflows/api/rule-usage/route.js.map +2 -2
  1469. package/dist/modules/workflows/api/signals/route.js +4 -1
  1470. package/dist/modules/workflows/api/signals/route.js.map +2 -2
  1471. package/dist/modules/workflows/api/tasks/[id]/claim/route.js +4 -1
  1472. package/dist/modules/workflows/api/tasks/[id]/claim/route.js.map +2 -2
  1473. package/dist/modules/workflows/api/tasks/[id]/complete/route.js +4 -1
  1474. package/dist/modules/workflows/api/tasks/[id]/complete/route.js.map +2 -2
  1475. package/dist/modules/workflows/api/tasks/[id]/reassign/route.js +2 -1
  1476. package/dist/modules/workflows/api/tasks/[id]/reassign/route.js.map +2 -2
  1477. package/dist/modules/workflows/api/tasks/[id]/unclaim/route.js +4 -1
  1478. package/dist/modules/workflows/api/tasks/[id]/unclaim/route.js.map +2 -2
  1479. package/dist/modules/workflows/api/templates/route.js +4 -1
  1480. package/dist/modules/workflows/api/templates/route.js.map +2 -2
  1481. package/dist/modules/workflows/api/work-inbox/next/route.js +4 -1
  1482. package/dist/modules/workflows/api/work-inbox/next/route.js.map +2 -2
  1483. package/dist/modules/workflows/lib/activity-executor.js +87 -20
  1484. package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
  1485. package/dist/modules/workflows/lib/activity-types.js +4 -4
  1486. package/dist/modules/workflows/lib/activity-types.js.map +2 -2
  1487. package/dist/modules/workflows/lib/activity-worker-handler.js +16 -11
  1488. package/dist/modules/workflows/lib/activity-worker-handler.js.map +2 -2
  1489. package/dist/modules/workflows/lib/event-trigger-service.js +8 -1
  1490. package/dist/modules/workflows/lib/event-trigger-service.js.map +2 -2
  1491. package/dist/modules/workflows/lib/step-handler.js +4 -4
  1492. package/dist/modules/workflows/lib/step-handler.js.map +2 -2
  1493. package/dist/test-utils/transactionalEntityManagerDouble.js +37 -0
  1494. package/dist/test-utils/transactionalEntityManagerDouble.js.map +7 -0
  1495. package/generated/entities/availability_policy/index.ts +19 -0
  1496. package/generated/entities/communication_channel/index.ts +1 -0
  1497. package/generated/entities/customer_email_conversation_share/index.ts +9 -0
  1498. package/generated/entities/customer_group/index.ts +15 -0
  1499. package/generated/entities/customer_group_membership/index.ts +13 -0
  1500. package/generated/entities/customer_group_terms/index.ts +15 -0
  1501. package/generated/entities/customer_interaction/index.ts +1 -0
  1502. package/generated/entities/form/index.ts +16 -0
  1503. package/generated/entities/form_access_audit/index.ts +9 -0
  1504. package/generated/entities/form_attachment/index.ts +13 -0
  1505. package/generated/entities/form_consent_record/index.ts +17 -0
  1506. package/generated/entities/form_distribution/index.ts +22 -0
  1507. package/generated/entities/form_invitation/index.ts +23 -0
  1508. package/generated/entities/form_submission/index.ts +18 -0
  1509. package/generated/entities/form_submission_actor/index.ts +10 -0
  1510. package/generated/entities/form_submission_revision/index.ts +13 -0
  1511. package/generated/entities/form_version/index.ts +17 -0
  1512. package/generated/entities/forms_encryption_key/index.ts +6 -0
  1513. package/generated/entities.ids.generated.ts +27 -2
  1514. package/generated/entity-fields-registry.ts +269 -0
  1515. package/package.json +19 -9
  1516. package/src/helpers/integration/communicationChannelsFixtures.ts +43 -0
  1517. package/src/helpers/integration/customerGroupsFixtures.ts +171 -0
  1518. package/src/helpers/integration/formsFixtures.ts +757 -0
  1519. package/src/modules/api_docs/api/get/version.ts +28 -11
  1520. package/src/modules/api_keys/api/keys/route.ts +89 -199
  1521. package/src/modules/api_keys/backend/api-keys/create/page.tsx +2 -2
  1522. package/src/modules/api_keys/commands/keys.ts +172 -0
  1523. package/src/modules/api_keys/i18n/de.json +1 -0
  1524. package/src/modules/api_keys/i18n/en.json +1 -0
  1525. package/src/modules/api_keys/i18n/es.json +1 -0
  1526. package/src/modules/api_keys/i18n/ko.json +1 -0
  1527. package/src/modules/api_keys/i18n/pl.json +1 -0
  1528. package/src/modules/api_keys/services/apiKeyService.ts +82 -49
  1529. package/src/modules/attachments/api/file/[id]/route.ts +9 -4
  1530. package/src/modules/attachments/api/image/[id]/[[...slug]]/route.ts +6 -4
  1531. package/src/modules/attachments/api/route.ts +10 -4
  1532. package/src/modules/attachments/components/AttachmentLibrary.tsx +16 -5
  1533. package/src/modules/attachments/lib/access.ts +1 -3
  1534. package/src/modules/attachments/lib/requestScope.ts +35 -3
  1535. package/src/modules/audit_logs/api/audit-logs/actions/export/route.ts +6 -1
  1536. package/src/modules/audit_logs/api/audit-logs/actions/redo/route.ts +41 -6
  1537. package/src/modules/audit_logs/api/audit-logs/actions/route.ts +6 -1
  1538. package/src/modules/audit_logs/api/audit-logs/actions/undo/route.ts +39 -4
  1539. package/src/modules/audit_logs/data/validators.ts +1 -0
  1540. package/src/modules/audit_logs/lib/actorSubject.ts +82 -0
  1541. package/src/modules/audit_logs/lib/replayAuthorization.ts +61 -0
  1542. package/src/modules/audit_logs/services/actionLogService.ts +191 -47
  1543. package/src/modules/auth/api/features.ts +1 -1
  1544. package/src/modules/auth/cli.ts +31 -17
  1545. package/src/modules/auth/commands/acl.ts +26 -36
  1546. package/src/modules/auth/commands/interceptors.ts +23 -0
  1547. package/src/modules/auth/commands/roles.ts +475 -148
  1548. package/src/modules/auth/commands/users.ts +693 -81
  1549. package/src/modules/auth/i18n/de.json +22 -0
  1550. package/src/modules/auth/i18n/en.json +22 -0
  1551. package/src/modules/auth/i18n/es.json +22 -0
  1552. package/src/modules/auth/i18n/ko.json +22 -0
  1553. package/src/modules/auth/i18n/pl.json +22 -0
  1554. package/src/modules/auth/lib/authorizationStateLocks.ts +340 -0
  1555. package/src/modules/auth/lib/commandReplay.ts +194 -0
  1556. package/src/modules/auth/lib/executionPrincipal.ts +36 -28
  1557. package/src/modules/auth/lib/grantChecks.ts +10 -2
  1558. package/src/modules/auth/lib/setup-app.ts +97 -50
  1559. package/src/modules/auth/lib/tokenHash.ts +16 -1
  1560. package/src/modules/auth/services/rbacService.ts +578 -6
  1561. package/src/modules/availability/acl.ts +12 -0
  1562. package/src/modules/availability/api/check/route.ts +136 -0
  1563. package/src/modules/availability/api/openapi.ts +28 -0
  1564. package/src/modules/availability/api/policies/resolve-preview/route.ts +83 -0
  1565. package/src/modules/availability/api/policies/route.ts +243 -0
  1566. package/src/modules/availability/backend/availability/check/page.meta.ts +12 -0
  1567. package/src/modules/availability/backend/availability/check/page.tsx +226 -0
  1568. package/src/modules/availability/backend/availability/policies/ResolutionPreviewPanel.tsx +112 -0
  1569. package/src/modules/availability/backend/availability/policies/ScopeFields.tsx +55 -0
  1570. package/src/modules/availability/backend/availability/policies/StockManagedField.tsx +37 -0
  1571. package/src/modules/availability/backend/availability/policies/[id]/page.meta.ts +8 -0
  1572. package/src/modules/availability/backend/availability/policies/[id]/page.tsx +202 -0
  1573. package/src/modules/availability/backend/availability/policies/create/page.meta.ts +8 -0
  1574. package/src/modules/availability/backend/availability/policies/create/page.tsx +134 -0
  1575. package/src/modules/availability/backend/availability/policies/formGroups.ts +83 -0
  1576. package/src/modules/availability/backend/availability/policies/page.meta.ts +12 -0
  1577. package/src/modules/availability/backend/availability/policies/page.tsx +232 -0
  1578. package/src/modules/availability/backend/availability/policies/policyPayload.ts +29 -0
  1579. package/src/modules/availability/commands/policies.ts +430 -0
  1580. package/src/modules/availability/commands/scope.ts +26 -0
  1581. package/src/modules/availability/data/entities.ts +93 -0
  1582. package/src/modules/availability/data/validators.ts +87 -0
  1583. package/src/modules/availability/di.ts +68 -0
  1584. package/src/modules/availability/events.ts +17 -0
  1585. package/src/modules/availability/i18n/de.json +93 -0
  1586. package/src/modules/availability/i18n/en.json +93 -0
  1587. package/src/modules/availability/i18n/es.json +93 -0
  1588. package/src/modules/availability/i18n/ko.json +93 -0
  1589. package/src/modules/availability/i18n/pl.json +93 -0
  1590. package/src/modules/availability/index.ts +13 -0
  1591. package/src/modules/availability/lib/catalogTarget.ts +72 -0
  1592. package/src/modules/availability/lib/organizationScope.ts +55 -0
  1593. package/src/modules/availability/lib/policyResolution.ts +289 -0
  1594. package/src/modules/availability/lib/tryResolve.ts +8 -0
  1595. package/src/modules/availability/migrations/.snapshot-open-mercato.json +375 -0
  1596. package/src/modules/availability/migrations/Migration20260922095844_availability.ts +13 -0
  1597. package/src/modules/availability/migrations/Migration20260930120000_availability.ts +22 -0
  1598. package/src/modules/availability/setup.ts +10 -0
  1599. package/src/modules/catalog/api/categories/bulk-create/route.ts +133 -0
  1600. package/src/modules/catalog/api/categories/route.ts +70 -8
  1601. package/src/modules/catalog/api/products/bulk-create/route.ts +133 -0
  1602. package/src/modules/catalog/api/products/route.ts +55 -24
  1603. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +9 -16
  1604. package/src/modules/catalog/backend/catalog/products/create/page.tsx +16 -10
  1605. package/src/modules/catalog/commands/categories.ts +1 -0
  1606. package/src/modules/catalog/commands/products.ts +11 -7
  1607. package/src/modules/catalog/components/PriceKindSettings.tsx +6 -20
  1608. package/src/modules/catalog/components/prices/PriceScopeSelectors.tsx +2 -2
  1609. package/src/modules/catalog/components/products/ProductUomSection.tsx +26 -37
  1610. package/src/modules/catalog/components/products/productForm.ts +6 -4
  1611. package/src/modules/catalog/data/validators.ts +22 -0
  1612. package/src/modules/catalog/di.ts +2 -1
  1613. package/src/modules/catalog/events.ts +9 -3
  1614. package/src/modules/catalog/i18n/de.json +40 -0
  1615. package/src/modules/catalog/i18n/en.json +40 -0
  1616. package/src/modules/catalog/i18n/es.json +40 -0
  1617. package/src/modules/catalog/i18n/ko.json +40 -0
  1618. package/src/modules/catalog/i18n/pl.json +40 -0
  1619. package/src/modules/catalog/lib/bulkCreateCategories.ts +349 -0
  1620. package/src/modules/catalog/lib/bulkCreateCheckpoint.ts +176 -0
  1621. package/src/modules/catalog/lib/bulkCreateMutationGuards.ts +62 -0
  1622. package/src/modules/catalog/lib/bulkCreateProducts.ts +340 -0
  1623. package/src/modules/catalog/lib/bulkDelete.ts +10 -14
  1624. package/src/modules/catalog/lib/catalogQueue.ts +14 -0
  1625. package/src/modules/catalog/lib/currencyOptions.ts +28 -0
  1626. package/src/modules/catalog/lib/productSearch.ts +16 -0
  1627. package/src/modules/catalog/lib/seeds.ts +2 -43
  1628. package/src/modules/catalog/lib/unitLabels.ts +52 -0
  1629. package/src/modules/catalog/migrations/Migration20260914120000.ts +51 -0
  1630. package/src/modules/catalog/migrations/Migration20260914120100.ts +50 -0
  1631. package/src/modules/catalog/workers/catalog-category-bulk-create.ts +48 -0
  1632. package/src/modules/catalog/workers/catalog-product-bulk-create.ts +48 -0
  1633. package/src/modules/communication_channels/acl.ts +8 -0
  1634. package/src/modules/communication_channels/api/get/me/channels/route.ts +4 -0
  1635. package/src/modules/communication_channels/api/get/oauth/[provider]/callback/route.ts +23 -0
  1636. package/src/modules/communication_channels/api/post/channels/[id]/import-history/route.ts +3 -4
  1637. package/src/modules/communication_channels/api/post/channels/[id]/test-send/route.ts +9 -1
  1638. package/src/modules/communication_channels/api/post/test-seed/route.ts +109 -24
  1639. package/src/modules/communication_channels/api/put/channels/[id]/visibility/route.ts +165 -0
  1640. package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +247 -129
  1641. package/src/modules/communication_channels/commands/ingest-inbound-message.ts +2 -1
  1642. package/src/modules/communication_channels/commands/set-channel-visibility.ts +138 -0
  1643. package/src/modules/communication_channels/data/enrichers.ts +42 -19
  1644. package/src/modules/communication_channels/data/entities.ts +21 -0
  1645. package/src/modules/communication_channels/di.ts +9 -0
  1646. package/src/modules/communication_channels/events.ts +7 -0
  1647. package/src/modules/communication_channels/i18n/de.json +13 -3
  1648. package/src/modules/communication_channels/i18n/en.json +13 -3
  1649. package/src/modules/communication_channels/i18n/es.json +13 -3
  1650. package/src/modules/communication_channels/i18n/ko.json +13 -3
  1651. package/src/modules/communication_channels/i18n/pl.json +13 -3
  1652. package/src/modules/communication_channels/index.ts +1 -1
  1653. package/src/modules/communication_channels/lib/access-control.ts +4 -1
  1654. package/src/modules/communication_channels/lib/adapter.ts +16 -6
  1655. package/src/modules/communication_channels/lib/channel-thread-access.ts +133 -0
  1656. package/src/modules/communication_channels/lib/credential-refresh.ts +27 -5
  1657. package/src/modules/communication_channels/lib/inbound-message-origin.ts +62 -0
  1658. package/src/modules/communication_channels/lib/oauth-state.ts +96 -1
  1659. package/src/modules/communication_channels/lib/outbound-delivery-intent.ts +57 -0
  1660. package/src/modules/communication_channels/lib/send-as-user.ts +2 -2
  1661. package/src/modules/communication_channels/migrations/.snapshot-open-mercato.json +18 -1
  1662. package/src/modules/communication_channels/migrations/Migration20260825141000_communication_channels.ts +22 -0
  1663. package/src/modules/communication_channels/setup.ts +4 -0
  1664. package/src/modules/communication_channels/subscribers/outbound-bridge.ts +34 -9
  1665. package/src/modules/communication_channels/workers/gmail-history-sync.ts +1 -1
  1666. package/src/modules/communication_channels/workers/poll-channel.ts +1 -1
  1667. package/src/modules/communication_channels/workers/reaction-processor.ts +2 -2
  1668. package/src/modules/configs/api/upgrade-actions/route.ts +2 -1
  1669. package/src/modules/configs/cli.ts +2 -2
  1670. package/src/modules/configs/i18n/de.json +2 -0
  1671. package/src/modules/configs/i18n/en.json +2 -0
  1672. package/src/modules/configs/i18n/es.json +2 -0
  1673. package/src/modules/configs/i18n/ko.json +2 -0
  1674. package/src/modules/configs/i18n/pl.json +2 -0
  1675. package/src/modules/configs/lib/upgrade-actions.ts +29 -6
  1676. package/src/modules/configs/services/upgradeActionsService.ts +45 -30
  1677. package/src/modules/currencies/api/currencies/route.ts +11 -5
  1678. package/src/modules/currencies/api/exchange-rates/route.ts +11 -5
  1679. package/src/modules/customer_accounts/AGENTS.md +1 -0
  1680. package/src/modules/customer_accounts/api/admin/users/[id]/sessions/[sessionId].ts +89 -0
  1681. package/src/modules/customer_groups/acl.ts +10 -0
  1682. package/src/modules/customer_groups/api/customer-groups/[id]/terms/route.ts +355 -0
  1683. package/src/modules/customer_groups/api/customer-groups/crud.ts +627 -0
  1684. package/src/modules/customer_groups/api/customer-groups/explain-terms/route.ts +195 -0
  1685. package/src/modules/customer_groups/api/customer-groups/memberships/crud.ts +525 -0
  1686. package/src/modules/customer_groups/api/customer-groups/memberships/route.ts +65 -0
  1687. package/src/modules/customer_groups/api/customer-groups/price-kinds/route.ts +99 -0
  1688. package/src/modules/customer_groups/api/customer-groups/reconcile/adopt/route.ts +150 -0
  1689. package/src/modules/customer_groups/api/customer-groups/reconcile/route.ts +90 -0
  1690. package/src/modules/customer_groups/api/customer-groups/reorder/route.ts +147 -0
  1691. package/src/modules/customer_groups/api/customer-groups/route.ts +65 -0
  1692. package/src/modules/customer_groups/api/openapi.ts +28 -0
  1693. package/src/modules/customer_groups/backend/customer-groups/[id]/edit/page.meta.ts +12 -0
  1694. package/src/modules/customer_groups/backend/customer-groups/[id]/edit/page.tsx +392 -0
  1695. package/src/modules/customer_groups/backend/customer-groups/create/page.meta.ts +25 -0
  1696. package/src/modules/customer_groups/backend/customer-groups/create/page.tsx +279 -0
  1697. package/src/modules/customer_groups/backend/customer-groups/orphans/page.meta.ts +12 -0
  1698. package/src/modules/customer_groups/backend/customer-groups/orphans/page.tsx +216 -0
  1699. package/src/modules/customer_groups/backend/customer-groups/page.meta.ts +11 -0
  1700. package/src/modules/customer_groups/backend/customer-groups/page.tsx +484 -0
  1701. package/src/modules/customer_groups/cli.ts +87 -0
  1702. package/src/modules/customer_groups/commands/reorderGroups.ts +163 -0
  1703. package/src/modules/customer_groups/components/CustomerGroupDefaultField.tsx +55 -0
  1704. package/src/modules/customer_groups/components/CustomerGroupParentField.tsx +194 -0
  1705. package/src/modules/customer_groups/components/CustomerGroupTermsPriceKindField.tsx +112 -0
  1706. package/src/modules/customer_groups/components/CustomerGroupTermsSection.tsx +277 -0
  1707. package/src/modules/customer_groups/components/GroupPickerField.tsx +142 -0
  1708. package/src/modules/customer_groups/components/OrphanBanner.tsx +92 -0
  1709. package/src/modules/customer_groups/components/customerGroupTree.ts +84 -0
  1710. package/src/modules/customer_groups/data/entities.ts +244 -0
  1711. package/src/modules/customer_groups/data/validators.ts +232 -0
  1712. package/src/modules/customer_groups/di.ts +25 -0
  1713. package/src/modules/customer_groups/events.ts +22 -0
  1714. package/src/modules/customer_groups/i18n/de.json +199 -0
  1715. package/src/modules/customer_groups/i18n/en.json +199 -0
  1716. package/src/modules/customer_groups/i18n/es.json +199 -0
  1717. package/src/modules/customer_groups/i18n/ko.json +199 -0
  1718. package/src/modules/customer_groups/i18n/pl.json +199 -0
  1719. package/src/modules/customer_groups/index.ts +13 -0
  1720. package/src/modules/customer_groups/lib/createConflictRecheck.ts +39 -0
  1721. package/src/modules/customer_groups/lib/customerScope.ts +145 -0
  1722. package/src/modules/customer_groups/lib/groupEvents.ts +50 -0
  1723. package/src/modules/customer_groups/lib/priceKindScope.ts +65 -0
  1724. package/src/modules/customer_groups/lib/reconcile.ts +299 -0
  1725. package/src/modules/customer_groups/migrations/.snapshot-open-mercato.json +905 -0
  1726. package/src/modules/customer_groups/migrations/Migration20260922095316_customer_groups.ts +26 -0
  1727. package/src/modules/customer_groups/migrations/Migration20260922103033_customer_groups.ts +22 -0
  1728. package/src/modules/customer_groups/migrations/Migration20260922105444_customer_groups.ts +17 -0
  1729. package/src/modules/customer_groups/migrations/Migration20260923193330_customer_groups.ts +20 -0
  1730. package/src/modules/customer_groups/migrations/Migration20260929083000_customer_groups.ts +21 -0
  1731. package/src/modules/customer_groups/services/customerGroupsService.ts +358 -0
  1732. package/src/modules/customer_groups/setup.ts +11 -0
  1733. package/src/modules/customer_groups/widgets/injection/group-picker-field/widget.ts +41 -0
  1734. package/src/modules/customer_groups/widgets/injection/person-groups-explain-terms.tsx +227 -0
  1735. package/src/modules/customer_groups/widgets/injection/person-groups-tab/widget.ts +21 -0
  1736. package/src/modules/customer_groups/widgets/injection/person-groups-tab.tsx +573 -0
  1737. package/src/modules/customer_groups/widgets/injection-table.ts +35 -0
  1738. package/src/modules/customers/acl.ts +13 -0
  1739. package/src/modules/customers/api/activities/route.ts +10 -0
  1740. package/src/modules/customers/api/companies/[id]/people/route.ts +2 -1
  1741. package/src/modules/customers/api/companies/[id]/route.ts +20 -6
  1742. package/src/modules/customers/api/deals/[id]/companies/route.ts +2 -1
  1743. package/src/modules/customers/api/deals/[id]/people/route.ts +2 -1
  1744. package/src/modules/customers/api/deals/map/route.ts +11 -10
  1745. package/src/modules/customers/api/dictionaries/context.ts +2 -1
  1746. package/src/modules/customers/api/entity-roles-factory.ts +3 -2
  1747. package/src/modules/customers/api/interactions/[id]/visibility/route.ts +2 -1
  1748. package/src/modules/customers/api/interactions/cancel/route.ts +2 -1
  1749. package/src/modules/customers/api/interactions/complete/route.ts +2 -1
  1750. package/src/modules/customers/api/interactions/conflicts/route.ts +10 -10
  1751. package/src/modules/customers/api/interactions/counts/route.ts +25 -7
  1752. package/src/modules/customers/api/interactions/route.ts +34 -10
  1753. package/src/modules/customers/api/labels/assign/route.ts +2 -1
  1754. package/src/modules/customers/api/labels/route.ts +3 -2
  1755. package/src/modules/customers/api/labels/unassign/route.ts +2 -1
  1756. package/src/modules/customers/api/people/[id]/companies/context.ts +11 -2
  1757. package/src/modules/customers/api/people/[id]/email-share/route.ts +276 -0
  1758. package/src/modules/customers/api/people/[id]/email-threads/route.ts +14 -1
  1759. package/src/modules/customers/api/people/[id]/emails/route.ts +2 -1
  1760. package/src/modules/customers/api/people/[id]/route.ts +31 -22
  1761. package/src/modules/customers/api/people/check-phone/route.ts +2 -1
  1762. package/src/modules/customers/api/pipeline-stages/reorder/route.ts +3 -2
  1763. package/src/modules/customers/api/pipeline-stages/route.ts +3 -3
  1764. package/src/modules/customers/api/pipelines/route.ts +3 -3
  1765. package/src/modules/customers/api/settings/address-format/route.ts +2 -1
  1766. package/src/modules/customers/api/settings/dictionary-sort-modes/route.ts +2 -1
  1767. package/src/modules/customers/api/settings/stuck-threshold/route.ts +2 -1
  1768. package/src/modules/customers/api/tags/assign/route.ts +2 -1
  1769. package/src/modules/customers/api/tags/unassign/route.ts +2 -1
  1770. package/src/modules/customers/backend/customers/companies/[id]/page.tsx +4 -2
  1771. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.ts +10 -6
  1772. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +6 -1
  1773. package/src/modules/customers/backend/customers/deals/components/ReassignOwnerDialog.tsx +115 -0
  1774. package/src/modules/customers/backend/customers/deals/page.tsx +121 -1
  1775. package/src/modules/customers/backend/customers/people/[id]/page.tsx +4 -2
  1776. package/src/modules/customers/commands/addresses.ts +117 -15
  1777. package/src/modules/customers/commands/companies.ts +26 -5
  1778. package/src/modules/customers/commands/emailConversationShares.ts +261 -0
  1779. package/src/modules/customers/commands/index.ts +1 -0
  1780. package/src/modules/customers/commands/interactions.ts +61 -21
  1781. package/src/modules/customers/commands/people.ts +3 -2
  1782. package/src/modules/customers/commands/shared.ts +4 -0
  1783. package/src/modules/customers/components/calendar/types.ts +1 -1
  1784. package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +3 -11
  1785. package/src/modules/customers/components/detail/DealForm.tsx +111 -2
  1786. package/src/modules/customers/components/detail/DealOwnerSelect.tsx +161 -0
  1787. package/src/modules/customers/components/detail/DealsSection.tsx +8 -14
  1788. package/src/modules/customers/components/detail/PersonEmailShareControl.tsx +273 -0
  1789. package/src/modules/customers/components/detail/PersonEmailThreadsTab.tsx +26 -0
  1790. package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +10 -2
  1791. package/src/modules/customers/components/detail/create/CreateDealForm.tsx +30 -0
  1792. package/src/modules/customers/components/detail/create/DealDetailsFields.tsx +12 -0
  1793. package/src/modules/customers/components/detail/create/DealSectionCard.tsx +7 -2
  1794. package/src/modules/customers/components/detail/create/dealFormTypes.ts +3 -0
  1795. package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +16 -4
  1796. package/src/modules/customers/components/formConfig.tsx +3 -0
  1797. package/src/modules/customers/components/linking/LinkEntityDialog.tsx +8 -0
  1798. package/src/modules/customers/data/enrichers.ts +64 -5
  1799. package/src/modules/customers/data/entities.ts +105 -1
  1800. package/src/modules/customers/data/validators.ts +22 -0
  1801. package/src/modules/customers/events.ts +5 -0
  1802. package/src/modules/customers/i18n/de.json +28 -5
  1803. package/src/modules/customers/i18n/en.json +23 -0
  1804. package/src/modules/customers/i18n/es.json +23 -0
  1805. package/src/modules/customers/i18n/ko.json +23 -0
  1806. package/src/modules/customers/i18n/pl.json +23 -0
  1807. package/src/modules/customers/lib/assignableStaff.ts +17 -0
  1808. package/src/modules/customers/lib/calendar/editorPayload.ts +20 -13
  1809. package/src/modules/customers/lib/calendar/mapItem.ts +1 -0
  1810. package/src/modules/customers/lib/conversationShares.ts +250 -0
  1811. package/src/modules/customers/lib/dealsOrganizationScope.ts +5 -3
  1812. package/src/modules/customers/lib/interactionRequestContext.ts +2 -1
  1813. package/src/modules/customers/lib/link-channel-message-handler.ts +27 -4
  1814. package/src/modules/customers/lib/personDetailCacheTags.ts +68 -0
  1815. package/src/modules/customers/lib/personEmailThreads.ts +61 -6
  1816. package/src/modules/customers/lib/reassignDealOwner.ts +51 -0
  1817. package/src/modules/customers/lib/userNames.ts +39 -0
  1818. package/src/modules/customers/lib/visibilityFilter.ts +170 -3
  1819. package/src/modules/customers/migrations/.snapshot-open-mercato.json +240 -0
  1820. package/src/modules/customers/migrations/Migration20260825120000_customers.ts +19 -0
  1821. package/src/modules/customers/migrations/Migration20260825140000_customers.ts +41 -0
  1822. package/src/modules/customers/setup.ts +1 -0
  1823. package/src/modules/customers/subscribers/channel-visibility-changed.ts +50 -0
  1824. package/src/modules/dashboards/api/widgets/data/batch/route.ts +3 -8
  1825. package/src/modules/dashboards/api/widgets/data/route.ts +12 -18
  1826. package/src/modules/dashboards/lib/aggregations.ts +1 -1
  1827. package/src/modules/dashboards/lib/widgetScope.ts +2 -7
  1828. package/src/modules/data_sync/AGENTS.md +35 -1
  1829. package/src/modules/data_sync/api/runs/[id]/cancel.ts +5 -1
  1830. package/src/modules/data_sync/backend/data-sync/page.tsx +292 -19
  1831. package/src/modules/data_sync/backend/data-sync/runs/[id]/page.tsx +205 -21
  1832. package/src/modules/data_sync/components/useDataSyncRunAccess.ts +27 -0
  1833. package/src/modules/data_sync/i18n/de.json +24 -0
  1834. package/src/modules/data_sync/i18n/en.json +24 -0
  1835. package/src/modules/data_sync/i18n/es.json +24 -0
  1836. package/src/modules/data_sync/i18n/ko.json +24 -0
  1837. package/src/modules/data_sync/i18n/pl.json +24 -0
  1838. package/src/modules/data_sync/lib/adapter.ts +37 -0
  1839. package/src/modules/data_sync/lib/resume-point.ts +63 -0
  1840. package/src/modules/data_sync/lib/start-run.ts +61 -2
  1841. package/src/modules/data_sync/lib/sync-run-service.ts +27 -34
  1842. package/src/modules/devices/api/[id]/route.ts +3 -2
  1843. package/src/modules/devices/api/admin/devices/route.ts +2 -1
  1844. package/src/modules/devices/api/route.ts +2 -1
  1845. package/src/modules/dictionaries/api/[dictionaryId]/route.ts +3 -5
  1846. package/src/modules/dictionaries/api/context.ts +2 -1
  1847. package/src/modules/dictionaries/api/route.ts +4 -0
  1848. package/src/modules/dictionaries/components/DictionariesManager.tsx +12 -4
  1849. package/src/modules/dictionaries/data/validators.ts +9 -1
  1850. package/src/modules/dictionaries/i18n/de.json +3 -3
  1851. package/src/modules/dictionaries/i18n/en.json +3 -3
  1852. package/src/modules/dictionaries/i18n/es.json +3 -3
  1853. package/src/modules/dictionaries/i18n/ko.json +3 -3
  1854. package/src/modules/dictionaries/i18n/pl.json +3 -3
  1855. package/src/modules/directory/api/organization-branding/route.ts +10 -1
  1856. package/src/modules/directory/api/organizations/route.ts +1 -1
  1857. package/src/modules/directory/backend/directory/branding/page.tsx +24 -2
  1858. package/src/modules/directory/commands/organizations.ts +173 -80
  1859. package/src/modules/directory/i18n/de.json +1 -0
  1860. package/src/modules/directory/i18n/en.json +1 -0
  1861. package/src/modules/directory/i18n/es.json +1 -0
  1862. package/src/modules/directory/i18n/ko.json +1 -0
  1863. package/src/modules/directory/i18n/pl.json +1 -0
  1864. package/src/modules/directory/lib/hierarchy.ts +22 -1
  1865. package/src/modules/directory/utils/organizationScope.ts +102 -15
  1866. package/src/modules/directory/utils/organizationScopeFilter.ts +6 -3
  1867. package/src/modules/directory/utils/organizationScopeGuard.ts +9 -5
  1868. package/src/modules/entities/api/encryption.ts +73 -27
  1869. package/src/modules/entities/api/records.ts +9 -8
  1870. package/src/modules/entities/cli.ts +46 -24
  1871. package/src/modules/entities/data/entities.ts +15 -0
  1872. package/src/modules/entities/lib/definition-scope.ts +5 -1
  1873. package/src/modules/entities/lib/encryption-maps.ts +164 -0
  1874. package/src/modules/entities/lib/helpers.ts +95 -8
  1875. package/src/modules/entities/migrations/.snapshot-open-mercato.json +21 -0
  1876. package/src/modules/entities/migrations/.snapshot-openmercato.json +12 -0
  1877. package/src/modules/entities/migrations/Migration20260910120000.ts +42 -0
  1878. package/src/modules/entities/migrations/Migration20261004120000_encryption_map_scope_uniqueness.ts +130 -0
  1879. package/src/modules/eudr/api/dashboard/widgets/compliance-overview/route.ts +2 -1
  1880. package/src/modules/eudr/api/plots/import/route.ts +2 -1
  1881. package/src/modules/eudr/api/product-mappings/suggestions/apply/route.ts +2 -1
  1882. package/src/modules/eudr/api/product-mappings/suggestions/route.ts +2 -1
  1883. package/src/modules/eudr/api/reports/annual/route.ts +2 -1
  1884. package/src/modules/eudr/api/statements/[id]/export/route.ts +2 -1
  1885. package/src/modules/eudr/api/statements/[id]/readiness/route.ts +2 -1
  1886. package/src/modules/eudr/api/suppliers/compliance/route.ts +2 -1
  1887. package/src/modules/eudr/i18n/de.json +1 -0
  1888. package/src/modules/eudr/i18n/en.json +1 -0
  1889. package/src/modules/eudr/i18n/es.json +1 -0
  1890. package/src/modules/eudr/i18n/ko.json +1 -0
  1891. package/src/modules/eudr/i18n/pl.json +1 -0
  1892. package/src/modules/feature_toggles/commands/global.ts +18 -15
  1893. package/src/modules/feature_toggles/lib/feature-flag-check.ts +8 -3
  1894. package/src/modules/forms/acl.ts +10 -0
  1895. package/src/modules/forms/api/[id]/analytics/route.ts +137 -0
  1896. package/src/modules/forms/api/[id]/distributions/route.ts +192 -0
  1897. package/src/modules/forms/api/[id]/route.ts +245 -0
  1898. package/src/modules/forms/api/[id]/run/context/route.ts +142 -0
  1899. package/src/modules/forms/api/[id]/run/submissions/route.ts +147 -0
  1900. package/src/modules/forms/api/[id]/submissions/route.ts +100 -0
  1901. package/src/modules/forms/api/[id]/theme-logo/route.ts +147 -0
  1902. package/src/modules/forms/api/[id]/versions/[versionId]/diff/route.ts +137 -0
  1903. package/src/modules/forms/api/[id]/versions/[versionId]/publish/route.ts +108 -0
  1904. package/src/modules/forms/api/[id]/versions/[versionId]/route.ts +200 -0
  1905. package/src/modules/forms/api/[id]/versions/fork/route.ts +98 -0
  1906. package/src/modules/forms/api/attachment-helpers.ts +160 -0
  1907. package/src/modules/forms/api/by-key/[key]/active/route.ts +165 -0
  1908. package/src/modules/forms/api/distributions/[distributionId]/invitations/[invitationId]/route.ts +92 -0
  1909. package/src/modules/forms/api/distributions/[distributionId]/invitations/[invitationId]/send/route.ts +96 -0
  1910. package/src/modules/forms/api/distributions/[distributionId]/invitations/route.ts +207 -0
  1911. package/src/modules/forms/api/distributions/[distributionId]/route.ts +213 -0
  1912. package/src/modules/forms/api/form-submissions/[id]/attachments/route.ts +114 -0
  1913. package/src/modules/forms/api/form-submissions/[id]/resume-token/route.ts +140 -0
  1914. package/src/modules/forms/api/form-submissions/[id]/route.ts +176 -0
  1915. package/src/modules/forms/api/form-submissions/[id]/submit/route.ts +91 -0
  1916. package/src/modules/forms/api/form-submissions/by-subject/[subject_type]/[subject_id]/route.ts +93 -0
  1917. package/src/modules/forms/api/form-submissions/route.ts +133 -0
  1918. package/src/modules/forms/api/helpers.ts +175 -0
  1919. package/src/modules/forms/api/public/distributions/[slug]/embed-policy/route.ts +74 -0
  1920. package/src/modules/forms/api/public/distributions/[slug]/route.ts +101 -0
  1921. package/src/modules/forms/api/public/embed-loader/route.ts +136 -0
  1922. package/src/modules/forms/api/public/invitations/[token]/route.ts +107 -0
  1923. package/src/modules/forms/api/public/rate-limit.ts +69 -0
  1924. package/src/modules/forms/api/public/start/route.ts +195 -0
  1925. package/src/modules/forms/api/public/submissions/[id]/attachments/[attachmentId]/route.ts +86 -0
  1926. package/src/modules/forms/api/public/submissions/[id]/attachments/route.ts +108 -0
  1927. package/src/modules/forms/api/public/submissions/[id]/pdf/route.ts +96 -0
  1928. package/src/modules/forms/api/public/submissions/[id]/route.ts +189 -0
  1929. package/src/modules/forms/api/public/submissions/[id]/submit/route.ts +159 -0
  1930. package/src/modules/forms/api/route.ts +240 -0
  1931. package/src/modules/forms/api/runtime-helpers.ts +208 -0
  1932. package/src/modules/forms/api/subjects/[subjectType]/[subjectId]/consents/route.ts +178 -0
  1933. package/src/modules/forms/api/subjects/[subjectType]/[subjectId]/export/route.ts +135 -0
  1934. package/src/modules/forms/api/submissions/[submissionId]/access-audit/route.ts +100 -0
  1935. package/src/modules/forms/api/submissions/[submissionId]/actors/[actorId]/route.ts +70 -0
  1936. package/src/modules/forms/api/submissions/[submissionId]/actors/route.ts +92 -0
  1937. package/src/modules/forms/api/submissions/[submissionId]/anonymize/route.ts +134 -0
  1938. package/src/modules/forms/api/submissions/[submissionId]/attachments/[attachmentId]/route.ts +90 -0
  1939. package/src/modules/forms/api/submissions/[submissionId]/export/route.ts +111 -0
  1940. package/src/modules/forms/api/submissions/[submissionId]/pdf/route.ts +118 -0
  1941. package/src/modules/forms/api/submissions/[submissionId]/reopen/route.ts +69 -0
  1942. package/src/modules/forms/api/submissions/[submissionId]/revisions/route.ts +75 -0
  1943. package/src/modules/forms/api/submissions/[submissionId]/route.ts +90 -0
  1944. package/src/modules/forms/backend/forms/[id]/FormStudio.tsx +3269 -0
  1945. package/src/modules/forms/backend/forms/[id]/analytics/page.meta.ts +15 -0
  1946. package/src/modules/forms/backend/forms/[id]/analytics/page.tsx +289 -0
  1947. package/src/modules/forms/backend/forms/[id]/distributions/page.meta.ts +15 -0
  1948. package/src/modules/forms/backend/forms/[id]/distributions/page.tsx +16 -0
  1949. package/src/modules/forms/backend/forms/[id]/history/page.meta.ts +11 -0
  1950. package/src/modules/forms/backend/forms/[id]/history/page.tsx +229 -0
  1951. package/src/modules/forms/backend/forms/[id]/page.meta.ts +11 -0
  1952. package/src/modules/forms/backend/forms/[id]/page.tsx +17 -0
  1953. package/src/modules/forms/backend/forms/[id]/studio/YesNoRow.tsx +65 -0
  1954. package/src/modules/forms/backend/forms/[id]/studio/autosave-guard.ts +25 -0
  1955. package/src/modules/forms/backend/forms/[id]/studio/canvas/DragOverlayCard.tsx +24 -0
  1956. package/src/modules/forms/backend/forms/[id]/studio/canvas/DropIndicator.tsx +36 -0
  1957. package/src/modules/forms/backend/forms/[id]/studio/canvas/FieldRow.tsx +308 -0
  1958. package/src/modules/forms/backend/forms/[id]/studio/canvas/FormCanvas.tsx +265 -0
  1959. package/src/modules/forms/backend/forms/[id]/studio/canvas/GridSlot.tsx +176 -0
  1960. package/src/modules/forms/backend/forms/[id]/studio/canvas/SectionContainer.tsx +473 -0
  1961. package/src/modules/forms/backend/forms/[id]/studio/canvas/grid-collision.ts +25 -0
  1962. package/src/modules/forms/backend/forms/[id]/studio/canvas/keyboard-coordinates.ts +128 -0
  1963. package/src/modules/forms/backend/forms/[id]/studio/canvas/overlay-size.ts +15 -0
  1964. package/src/modules/forms/backend/forms/[id]/studio/canvas/resize-math.ts +36 -0
  1965. package/src/modules/forms/backend/forms/[id]/studio/canvas/row-layout.ts +110 -0
  1966. package/src/modules/forms/backend/forms/[id]/studio/logic/ConditionBuilder.tsx +264 -0
  1967. package/src/modules/forms/backend/forms/[id]/studio/logic/HiddenFieldsPanel.tsx +121 -0
  1968. package/src/modules/forms/backend/forms/[id]/studio/logic/JumpsEditor.tsx +237 -0
  1969. package/src/modules/forms/backend/forms/[id]/studio/logic/RecallTokenPicker.tsx +87 -0
  1970. package/src/modules/forms/backend/forms/[id]/studio/logic/VariablesPanel.tsx +260 -0
  1971. package/src/modules/forms/backend/forms/[id]/studio/logic/condition-model.ts +207 -0
  1972. package/src/modules/forms/backend/forms/[id]/studio/lucide-icons.ts +87 -0
  1973. package/src/modules/forms/backend/forms/[id]/studio/palette/FormAppearancePanel.tsx +561 -0
  1974. package/src/modules/forms/backend/forms/[id]/studio/palette/FormPalettePanel.tsx +52 -0
  1975. package/src/modules/forms/backend/forms/[id]/studio/palette/InputParametersTab.tsx +378 -0
  1976. package/src/modules/forms/backend/forms/[id]/studio/palette/PaletteCard.tsx +40 -0
  1977. package/src/modules/forms/backend/forms/[id]/studio/palette/RolesEditor.tsx +225 -0
  1978. package/src/modules/forms/backend/forms/[id]/studio/palette/entries.ts +102 -0
  1979. package/src/modules/forms/backend/forms/[id]/studio/preview/PreviewSurface.tsx +1459 -0
  1980. package/src/modules/forms/backend/forms/[id]/studio/preview/ViewportFrame.tsx +49 -0
  1981. package/src/modules/forms/backend/forms/[id]/studio/recall.ts +0 -0
  1982. package/src/modules/forms/backend/forms/[id]/studio/schema-helpers.ts +2525 -0
  1983. package/src/modules/forms/backend/forms/[id]/studio/style/BackgroundControl.tsx +137 -0
  1984. package/src/modules/forms/backend/forms/[id]/studio/style/ColorControl.tsx +257 -0
  1985. package/src/modules/forms/backend/forms/[id]/studio/style/contrast.ts +114 -0
  1986. package/src/modules/forms/backend/forms/[id]/studio/style/presets.ts +104 -0
  1987. package/src/modules/forms/backend/forms/[id]/studio/type-label.ts +13 -0
  1988. package/src/modules/forms/backend/forms/[id]/studio/types.ts +31 -0
  1989. package/src/modules/forms/backend/forms/[id]/studio/undo-controller.ts +52 -0
  1990. package/src/modules/forms/backend/forms/[id]/studio/validation/FileConstraintsEditor.tsx +89 -0
  1991. package/src/modules/forms/backend/forms/[id]/studio/validation/GroupConfigEditor.tsx +167 -0
  1992. package/src/modules/forms/backend/forms/[id]/studio/validation/LengthRangeEditor.tsx +67 -0
  1993. package/src/modules/forms/backend/forms/[id]/studio/validation/MatrixColumnsEditor.tsx +166 -0
  1994. package/src/modules/forms/backend/forms/[id]/studio/validation/MatrixRowsEditor.tsx +184 -0
  1995. package/src/modules/forms/backend/forms/[id]/studio/validation/MessageOverridesEditor.tsx +83 -0
  1996. package/src/modules/forms/backend/forms/[id]/studio/validation/NpsAnchorsEditor.tsx +60 -0
  1997. package/src/modules/forms/backend/forms/[id]/studio/validation/NumberRangeEditor.tsx +65 -0
  1998. package/src/modules/forms/backend/forms/[id]/studio/validation/OpinionIconSelect.tsx +46 -0
  1999. package/src/modules/forms/backend/forms/[id]/studio/validation/PatternEditor.tsx +122 -0
  2000. package/src/modules/forms/backend/forms/[id]/studio/validation/RankingExhaustiveSwitch.tsx +28 -0
  2001. package/src/modules/forms/backend/forms/[id]/studio/validation/SignatureConfigEditor.tsx +84 -0
  2002. package/src/modules/forms/backend/forms/[id]/studio/validation/ValidationPanel.tsx +369 -0
  2003. package/src/modules/forms/backend/forms/[id]/submissions/components/RowBadges.ts +56 -0
  2004. package/src/modules/forms/backend/forms/[id]/submissions/components/SubmissionDrawer.tsx +605 -0
  2005. package/src/modules/forms/backend/forms/[id]/submissions/components/formSummary.ts +19 -0
  2006. package/src/modules/forms/backend/forms/[id]/submissions/page.meta.ts +10 -0
  2007. package/src/modules/forms/backend/forms/[id]/submissions/page.tsx +252 -0
  2008. package/src/modules/forms/backend/forms/create/page.meta.ts +11 -0
  2009. package/src/modules/forms/backend/forms/create/page.tsx +113 -0
  2010. package/src/modules/forms/backend/forms/page.meta.ts +31 -0
  2011. package/src/modules/forms/backend/forms/page.tsx +269 -0
  2012. package/src/modules/forms/commands/distribution.ts +506 -0
  2013. package/src/modules/forms/commands/form-version.ts +811 -0
  2014. package/src/modules/forms/commands/form.ts +477 -0
  2015. package/src/modules/forms/commands/index.ts +18 -0
  2016. package/src/modules/forms/commands/invitation.ts +428 -0
  2017. package/src/modules/forms/commands/shared.ts +261 -0
  2018. package/src/modules/forms/commands/submission.ts +216 -0
  2019. package/src/modules/forms/data/entities.ts +686 -0
  2020. package/src/modules/forms/data/validators.ts +483 -0
  2021. package/src/modules/forms/di.ts +246 -0
  2022. package/src/modules/forms/encryption.ts +31 -0
  2023. package/src/modules/forms/events-payloads.ts +103 -0
  2024. package/src/modules/forms/events.ts +50 -0
  2025. package/src/modules/forms/extension-points.ts +41 -0
  2026. package/src/modules/forms/frontend/[orgSlug]/portal/forms/[key]/page.meta.ts +9 -0
  2027. package/src/modules/forms/frontend/[orgSlug]/portal/forms/[key]/page.tsx +45 -0
  2028. package/src/modules/forms/frontend/[orgSlug]/portal/submissions/[id]/continue/page.meta.ts +9 -0
  2029. package/src/modules/forms/frontend/[orgSlug]/portal/submissions/[id]/continue/page.tsx +56 -0
  2030. package/src/modules/forms/frontend/embed/[slug]/page.meta.ts +42 -0
  2031. package/src/modules/forms/frontend/embed/[slug]/page.tsx +171 -0
  2032. package/src/modules/forms/frontend/f/[slug]/page.meta.ts +9 -0
  2033. package/src/modules/forms/frontend/f/[slug]/page.tsx +10 -0
  2034. package/src/modules/forms/frontend/forms/[id]/run/page.meta.ts +17 -0
  2035. package/src/modules/forms/frontend/forms/[id]/run/page.tsx +83 -0
  2036. package/src/modules/forms/frontend/i/[token]/page.meta.ts +9 -0
  2037. package/src/modules/forms/frontend/i/[token]/page.tsx +10 -0
  2038. package/src/modules/forms/i18n/de.json +821 -0
  2039. package/src/modules/forms/i18n/en.json +821 -0
  2040. package/src/modules/forms/i18n/es.json +821 -0
  2041. package/src/modules/forms/i18n/ko.json +821 -0
  2042. package/src/modules/forms/i18n/pl.json +821 -0
  2043. package/src/modules/forms/index.ts +18 -0
  2044. package/src/modules/forms/lib/embed-frame-policy.ts +144 -0
  2045. package/src/modules/forms/lib/form-definition-slicing.ts +54 -0
  2046. package/src/modules/forms/lib/log-redaction.ts +91 -0
  2047. package/src/modules/forms/lib/navigable-url.ts +57 -0
  2048. package/src/modules/forms/lib/retention.ts +73 -0
  2049. package/src/modules/forms/lib/runtime-principal.ts +101 -0
  2050. package/src/modules/forms/migrations/.snapshot-open-mercato.json +3185 -0
  2051. package/src/modules/forms/migrations/Migration20260508135459_forms.ts +17 -0
  2052. package/src/modules/forms/migrations/Migration20260508140932_forms.ts +26 -0
  2053. package/src/modules/forms/migrations/Migration20260508155737_forms.ts +15 -0
  2054. package/src/modules/forms/migrations/Migration20260520120000_forms.ts +26 -0
  2055. package/src/modules/forms/migrations/Migration20260521090000_forms.ts +15 -0
  2056. package/src/modules/forms/migrations/Migration20260521120000_forms.ts +21 -0
  2057. package/src/modules/forms/runner/FormRunner.tsx +924 -0
  2058. package/src/modules/forms/runner/MatrixField.tsx +210 -0
  2059. package/src/modules/forms/runner/RankingField.tsx +207 -0
  2060. package/src/modules/forms/runner/ScaleField.tsx +102 -0
  2061. package/src/modules/forms/runner/SignatureField.tsx +158 -0
  2062. package/src/modules/forms/runner/tamper-check.ts +131 -0
  2063. package/src/modules/forms/schema/address-countries.ts +60 -0
  2064. package/src/modules/forms/schema/field-type-patterns.ts +21 -0
  2065. package/src/modules/forms/schema/field-type-registry-advanced.ts +58 -0
  2066. package/src/modules/forms/schema/field-type-registry.ts +819 -0
  2067. package/src/modules/forms/schema/file-field.ts +102 -0
  2068. package/src/modules/forms/schema/group-field.ts +235 -0
  2069. package/src/modules/forms/schema/jsonlogic-grammar.ts +95 -0
  2070. package/src/modules/forms/schema/jsonschema-extensions.ts +1060 -0
  2071. package/src/modules/forms/schema/layout-catalog.ts +68 -0
  2072. package/src/modules/forms/schema/signature-field.ts +120 -0
  2073. package/src/modules/forms/schema/style-extensions.ts +194 -0
  2074. package/src/modules/forms/schema/style-validators.ts +252 -0
  2075. package/src/modules/forms/services/access-audit-logger.ts +275 -0
  2076. package/src/modules/forms/services/analytics-service.ts +498 -0
  2077. package/src/modules/forms/services/anonymize-service.ts +177 -0
  2078. package/src/modules/forms/services/attachment-service.ts +223 -0
  2079. package/src/modules/forms/services/captcha-verifier.ts +156 -0
  2080. package/src/modules/forms/services/consent-record-service.ts +162 -0
  2081. package/src/modules/forms/services/distribution-service.ts +509 -0
  2082. package/src/modules/forms/services/distribution-token.ts +153 -0
  2083. package/src/modules/forms/services/encryption-service.ts +500 -0
  2084. package/src/modules/forms/services/export-service.ts +360 -0
  2085. package/src/modules/forms/services/field-validation-service.ts +300 -0
  2086. package/src/modules/forms/services/form-logic-evaluator.ts +718 -0
  2087. package/src/modules/forms/services/form-version-compiler.ts +829 -0
  2088. package/src/modules/forms/services/form-version-differ.ts +143 -0
  2089. package/src/modules/forms/services/jsonlogic-evaluator.ts +228 -0
  2090. package/src/modules/forms/services/pdf-snapshot-service.ts +782 -0
  2091. package/src/modules/forms/services/prefill-resolver.ts +125 -0
  2092. package/src/modules/forms/services/role-policy-service.ts +90 -0
  2093. package/src/modules/forms/services/style-compiler.ts +378 -0
  2094. package/src/modules/forms/services/submission-service.ts +1259 -0
  2095. package/src/modules/forms/services/upload-scanner.ts +36 -0
  2096. package/src/modules/forms/services/upload-validation.ts +94 -0
  2097. package/src/modules/forms/services/visibility-resolver.ts +63 -0
  2098. package/src/modules/forms/setup.ts +16 -0
  2099. package/src/modules/forms/subscribers/forms-consent-projector.ts +100 -0
  2100. package/src/modules/forms/subscribers/forms-pdf-snapshot.ts +112 -0
  2101. package/src/modules/forms/subscribers/forms-webhook-bridge-anonymized.ts +36 -0
  2102. package/src/modules/forms/subscribers/forms-webhook-bridge.ts +56 -0
  2103. package/src/modules/forms/subscribers/invitation-email.ts +180 -0
  2104. package/src/modules/forms/translations.ts +14 -0
  2105. package/src/modules/forms/ui/admin/forms/[id]/distributions/CreateDistributionDialog.tsx +401 -0
  2106. package/src/modules/forms/ui/admin/forms/[id]/distributions/DistributionsPanel.tsx +381 -0
  2107. package/src/modules/forms/ui/admin/forms/[id]/distributions/EmbedSettingsDialog.tsx +332 -0
  2108. package/src/modules/forms/ui/admin/forms/[id]/distributions/RecipientsTable.tsx +460 -0
  2109. package/src/modules/forms/ui/public/EmbeddedForm.tsx +248 -0
  2110. package/src/modules/forms/ui/public/FormRunner.tsx +491 -0
  2111. package/src/modules/forms/ui/public/FormTrigger.tsx +80 -0
  2112. package/src/modules/forms/ui/public/PublicFormRunnerPage.tsx +34 -0
  2113. package/src/modules/forms/ui/public/components/CompletionScreen.tsx +97 -0
  2114. package/src/modules/forms/ui/public/components/LocaleSwitch.tsx +42 -0
  2115. package/src/modules/forms/ui/public/components/ResumeGate.tsx +61 -0
  2116. package/src/modules/forms/ui/public/components/ReviewStep.tsx +153 -0
  2117. package/src/modules/forms/ui/public/components/SaveIndicator.tsx +69 -0
  2118. package/src/modules/forms/ui/public/components/SectionStepper.tsx +60 -0
  2119. package/src/modules/forms/ui/public/index.ts +48 -0
  2120. package/src/modules/forms/ui/public/renderers/index.tsx +889 -0
  2121. package/src/modules/forms/ui/public/state/logic-derivation.ts +91 -0
  2122. package/src/modules/forms/ui/public/state/runtime-client.ts +495 -0
  2123. package/src/modules/forms/ui/public/state/useAutosave.ts +97 -0
  2124. package/src/modules/forms/ui/public/state/useFormRunner.ts +547 -0
  2125. package/src/modules/forms/ui/public/style/LogoHeader.tsx +43 -0
  2126. package/src/modules/forms/ui/public/style/applyStyle.ts +26 -0
  2127. package/src/modules/forms/ui/public/types.ts +228 -0
  2128. package/src/modules/forms/widgets/injection/access-audit-panel/widget.tsx +144 -0
  2129. package/src/modules/forms/widgets/injection/anonymize-button/widget.tsx +177 -0
  2130. package/src/modules/forms/widgets/injection/audit-format.ts +60 -0
  2131. package/src/modules/forms/widgets/injection/context.ts +24 -0
  2132. package/src/modules/forms/widgets/injection/embedded-form/widget.tsx +102 -0
  2133. package/src/modules/forms/widgets/injection/pdf-download-button/widget.tsx +111 -0
  2134. package/src/modules/forms/widgets/injection/self-audit-footer/widget.tsx +56 -0
  2135. package/src/modules/forms/widgets/injection-table.ts +54 -0
  2136. package/src/modules/forms/workers/pdf-snapshot.ts +110 -0
  2137. package/src/modules/forms/workers/retention-purge.ts +169 -0
  2138. package/src/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.ts +7 -1
  2139. package/src/modules/inbox_ops/data/validators.ts +2 -1
  2140. package/src/modules/inbox_ops/lib/llmProvider.ts +11 -0
  2141. package/src/modules/inbox_ops/widgets/notifications/ProposalCreatedRenderer.tsx +2 -2
  2142. package/src/modules/integrations/di.ts +5 -1
  2143. package/src/modules/integrations/lib/credentials-service.ts +45 -36
  2144. package/src/modules/messages/api/[id]/attachments/route.ts +12 -3
  2145. package/src/modules/messages/api/[id]/forward-preview/route.ts +9 -3
  2146. package/src/modules/messages/api/[id]/route.ts +83 -4
  2147. package/src/modules/messages/api/route.ts +123 -2
  2148. package/src/modules/messages/commands/messages.ts +81 -7
  2149. package/src/modules/messages/components/ComposeMessagePageClient.tsx +29 -1
  2150. package/src/modules/messages/data/validators.ts +10 -0
  2151. package/src/modules/messages/i18n/de.json +8 -0
  2152. package/src/modules/messages/i18n/en.json +8 -0
  2153. package/src/modules/messages/i18n/es.json +8 -0
  2154. package/src/modules/messages/i18n/ko.json +8 -0
  2155. package/src/modules/messages/i18n/pl.json +8 -0
  2156. package/src/modules/messages/lib/channelThreadAccess.ts +101 -0
  2157. package/src/modules/messages/lib/composeSenderDelegation.ts +182 -0
  2158. package/src/modules/messages/lib/composeSenderOptions.ts +56 -0
  2159. package/src/modules/messages/lib/email-sender.ts +1 -17
  2160. package/src/modules/messages/lib/forwarding.ts +17 -2
  2161. package/src/modules/messages/lib/markdownEmailBody.ts +25 -0
  2162. package/src/modules/messages/lib/messageSourceEntityTypes.ts +12 -0
  2163. package/src/modules/messages/lib/routeHelpers.ts +92 -0
  2164. package/src/modules/messages/subscribers/message-notification.ts +47 -1
  2165. package/src/modules/notifications/AGENTS.md +1 -1
  2166. package/src/modules/notifications/api/[id]/action/route.ts +2 -1
  2167. package/src/modules/notifications/api/openapi.ts +1 -0
  2168. package/src/modules/notifications/frontend/NotificationSettingsPageClient.tsx +77 -48
  2169. package/src/modules/notifications/i18n/de.json +1 -0
  2170. package/src/modules/notifications/i18n/en.json +1 -0
  2171. package/src/modules/notifications/i18n/es.json +1 -0
  2172. package/src/modules/notifications/i18n/ko.json +1 -0
  2173. package/src/modules/notifications/i18n/pl.json +1 -0
  2174. package/src/modules/notifications/lib/deliveryConfig.ts +31 -2
  2175. package/src/modules/notifications/lib/notificationMapper.ts +2 -0
  2176. package/src/modules/notifications/lib/safeHref.ts +7 -0
  2177. package/src/modules/planner/api/availability-date-specific.ts +2 -1
  2178. package/src/modules/planner/api/availability-weekly.ts +2 -1
  2179. package/src/modules/progress/AGENTS.md +2 -0
  2180. package/src/modules/progress/api/active/route.ts +14 -2
  2181. package/src/modules/progress/api/jobs/[id]/route.ts +44 -27
  2182. package/src/modules/progress/api/jobs/route.ts +22 -8
  2183. package/src/modules/progress/api/requestScope.ts +43 -0
  2184. package/src/modules/progress/lib/organizationScope.ts +17 -0
  2185. package/src/modules/progress/lib/progressService.ts +3 -2
  2186. package/src/modules/progress/lib/progressServiceImpl.ts +63 -14
  2187. package/src/modules/push_notifications/api/custom-send/route.ts +4 -1
  2188. package/src/modules/push_notifications/i18n/de.json +1 -0
  2189. package/src/modules/push_notifications/i18n/en.json +1 -0
  2190. package/src/modules/push_notifications/i18n/es.json +1 -0
  2191. package/src/modules/push_notifications/i18n/ko.json +1 -0
  2192. package/src/modules/push_notifications/i18n/pl.json +1 -0
  2193. package/src/modules/query_index/api/status.ts +4 -9
  2194. package/src/modules/query_index/di.ts +2 -1
  2195. package/src/modules/query_index/lib/engine.ts +2 -0
  2196. package/src/modules/query_index/lib/request-encryption.ts +31 -0
  2197. package/src/modules/query_index/lib/search-tokens.ts +42 -1
  2198. package/src/modules/resources/api/resources/tags/assign/route.ts +2 -1
  2199. package/src/modules/resources/api/resources/tags/unassign/route.ts +2 -1
  2200. package/src/modules/resources/commands/activities.ts +2 -2
  2201. package/src/modules/sales/api/document-history/route.ts +5 -1
  2202. package/src/modules/sales/api/document-numbers/route.ts +2 -1
  2203. package/src/modules/sales/api/quotes/convert/route.ts +2 -1
  2204. package/src/modules/sales/api/quotes/send/route.ts +2 -1
  2205. package/src/modules/sales/api/settings/document-numbers/route.ts +7 -1
  2206. package/src/modules/sales/api/settings/order-editing/route.ts +7 -1
  2207. package/src/modules/sales/commands/documents.ts +451 -131
  2208. package/src/modules/sales/commands/payments.ts +2 -1
  2209. package/src/modules/sales/commands/settings.ts +34 -6
  2210. package/src/modules/sales/commands/shipments.ts +2 -1
  2211. package/src/modules/sales/components/DocumentNumberSettings.tsx +41 -28
  2212. package/src/modules/sales/components/documents/ItemsSection.tsx +58 -13
  2213. package/src/modules/sales/i18n/de.json +2 -0
  2214. package/src/modules/sales/i18n/en.json +2 -0
  2215. package/src/modules/sales/i18n/es.json +2 -0
  2216. package/src/modules/sales/i18n/ko.json +2 -0
  2217. package/src/modules/sales/i18n/pl.json +2 -0
  2218. package/src/modules/sales/lib/lineSnapshots.ts +36 -0
  2219. package/src/modules/sales/setup.ts +4 -4
  2220. package/src/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.tsx +2 -2
  2221. package/src/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.tsx +2 -2
  2222. package/src/modules/staff/api/leave-requests/accept/route.ts +2 -1
  2223. package/src/modules/staff/api/leave-requests/reject/route.ts +2 -1
  2224. package/src/modules/staff/api/leave-requests.ts +2 -1
  2225. package/src/modules/staff/api/team-members/self/route.ts +2 -1
  2226. package/src/modules/staff/api/team-members/tags/assign/route.ts +2 -1
  2227. package/src/modules/staff/api/team-members/tags/unassign/route.ts +2 -1
  2228. package/src/modules/staff/api/timesheets/_shared/withTimesheetInterceptors.ts +16 -16
  2229. package/src/modules/staff/api/timesheets/my-projects/[projectId]/route.ts +2 -1
  2230. package/src/modules/staff/api/timesheets/my-projects/route.ts +2 -1
  2231. package/src/modules/staff/api/timesheets/my-work/route.ts +2 -1
  2232. package/src/modules/staff/api/timesheets/projects/kpis/route.ts +2 -1
  2233. package/src/modules/staff/api/timesheets/reports/[id]/close/route.ts +2 -1
  2234. package/src/modules/staff/api/timesheets/reports/[id]/export/route.ts +3 -2
  2235. package/src/modules/staff/api/timesheets/reports/[id]/sheet/route.ts +3 -2
  2236. package/src/modules/staff/api/timesheets/reports/[id]/unlock/route.ts +3 -2
  2237. package/src/modules/staff/api/timesheets/reports/preview/route.ts +2 -1
  2238. package/src/modules/staff/api/timesheets/reports/shared.ts +2 -1
  2239. package/src/modules/staff/api/timesheets/settings/reapply-rounding/route.ts +2 -1
  2240. package/src/modules/staff/api/timesheets/tags/entry-assignments/route.ts +2 -1
  2241. package/src/modules/staff/api/timesheets/tags/task-assignments/route.ts +2 -1
  2242. package/src/modules/staff/api/timesheets/tasks/[id]/comments/route.ts +2 -1
  2243. package/src/modules/staff/api/timesheets/tasks/[id]/status/route.ts +2 -1
  2244. package/src/modules/staff/api/timesheets/time-entries/[id]/duplicate/route.ts +3 -2
  2245. package/src/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.ts +2 -1
  2246. package/src/modules/staff/api/timesheets/time-entries/[id]/segments/route.ts +2 -1
  2247. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.ts +2 -1
  2248. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.ts +2 -1
  2249. package/src/modules/staff/api/timesheets/time-entries/bulk/route.ts +2 -1
  2250. package/src/modules/staff/api/timesheets/time-entries/copy-day/route.ts +3 -2
  2251. package/src/modules/staff/api/timesheets/time-entries/overlaps/route.ts +2 -1
  2252. package/src/modules/staff/api/timesheets/time-entries/start-timer/route.ts +3 -2
  2253. package/src/modules/staff/api/timesheets/time-projects/[id]/change-currency/route.ts +3 -2
  2254. package/src/modules/staff/api/timesheets/time-projects/route.ts +2 -1
  2255. package/src/modules/staff/commands/activities.ts +2 -2
  2256. package/src/modules/staff/commands/timesheets-entries.ts +3 -2
  2257. package/src/modules/staff/commands/timesheets-reports.ts +88 -15
  2258. package/src/modules/staff/lib/timesheets-reports/buildReportSheet.ts +1 -0
  2259. package/src/modules/staff/lib/timesheets-reports/loadReportData.ts +69 -8
  2260. package/src/modules/staff/lib/timesheets-reports/reportPeriod.ts +18 -0
  2261. package/src/modules/staff/lib/timesheets-ui/CalendarPicker.tsx +21 -10
  2262. package/src/modules/sync_excel/api/import/route.ts +40 -12
  2263. package/src/modules/sync_excel/api/upload/route.ts +34 -4
  2264. package/src/modules/translations/api/context.ts +2 -1
  2265. package/src/modules/warranty_claims/api/ai/assess/route.ts +2 -1
  2266. package/src/modules/warranty_claims/api/ai/draft-reply/route.ts +2 -1
  2267. package/src/modules/warranty_claims/api/ai/suggest/route.ts +2 -1
  2268. package/src/modules/warranty_claims/api/assign/route.ts +2 -1
  2269. package/src/modules/warranty_claims/api/credit-memo/route.ts +2 -1
  2270. package/src/modules/warranty_claims/api/entitlement/route.ts +2 -1
  2271. package/src/modules/warranty_claims/api/events/route.ts +2 -1
  2272. package/src/modules/warranty_claims/api/external/claims/route.ts +2 -1
  2273. package/src/modules/warranty_claims/api/receiving/route.ts +2 -1
  2274. package/src/modules/warranty_claims/api/replacement-order/route.ts +2 -1
  2275. package/src/modules/warranty_claims/api/return-label/route.ts +2 -1
  2276. package/src/modules/warranty_claims/api/risk/route.ts +2 -1
  2277. package/src/modules/warranty_claims/api/sales-return/route.ts +2 -1
  2278. package/src/modules/warranty_claims/api/settings-general/route.ts +2 -1
  2279. package/src/modules/warranty_claims/api/stats/route.ts +11 -11
  2280. package/src/modules/warranty_claims/api/submit/route.ts +2 -1
  2281. package/src/modules/warranty_claims/api/transition/route.ts +2 -1
  2282. package/src/modules/warranty_claims/api/vendor-recovery/route.ts +2 -1
  2283. package/src/modules/warranty_claims/api/vendor-recovery-suggestions/route.ts +2 -1
  2284. package/src/modules/warranty_claims/i18n/de.json +1 -0
  2285. package/src/modules/warranty_claims/i18n/en.json +1 -0
  2286. package/src/modules/warranty_claims/i18n/es.json +1 -0
  2287. package/src/modules/warranty_claims/i18n/ko.json +1 -0
  2288. package/src/modules/warranty_claims/i18n/pl.json +1 -0
  2289. package/src/modules/warranty_claims/widgets/notifications/WarrantyClaimNotificationRenderer.tsx +1 -1
  2290. package/src/modules/wms/api/dashboard/operational/route.ts +2 -1
  2291. package/src/modules/wms/api/inventory/cycle-count/route.ts +1 -0
  2292. package/src/modules/wms/api/inventory/helpers.ts +2 -1
  2293. package/src/modules/wms/api/inventory/import/helpers.ts +2 -1
  2294. package/src/modules/wms/api/sales-orders/[salesOrderId]/warehouse-assignment/route.ts +2 -1
  2295. package/src/modules/wms/commands/inventory-actions.ts +45 -1
  2296. package/src/modules/wms/components/backend/CycleCountWizardDialog.tsx +14 -1
  2297. package/src/modules/wms/di.ts +6 -0
  2298. package/src/modules/wms/i18n/de.json +2 -0
  2299. package/src/modules/wms/i18n/en.json +2 -0
  2300. package/src/modules/wms/i18n/es.json +2 -0
  2301. package/src/modules/wms/i18n/ko.json +2 -0
  2302. package/src/modules/wms/i18n/pl.json +2 -0
  2303. package/src/modules/wms/lib/availabilityCache.ts +137 -0
  2304. package/src/modules/wms/lib/availabilityCalculation.ts +351 -0
  2305. package/src/modules/wms/lib/availabilityProvider.ts +47 -0
  2306. package/src/modules/wms/lib/loadOperationalDashboard.ts +51 -3
  2307. package/src/modules/wms/lib/lowStockBalanceFilter.ts +23 -10
  2308. package/src/modules/wms/lib/sqlInClause.ts +21 -0
  2309. package/src/modules/wms/lib/tryResolve.ts +8 -0
  2310. package/src/modules/wms/subscribers/invalidate-availability-cache-policy.ts +18 -0
  2311. package/src/modules/wms/subscribers/invalidate-availability-cache-profile.ts +18 -0
  2312. package/src/modules/wms/subscribers/invalidate-availability-cache.ts +30 -0
  2313. package/src/modules/wms/widgets/notifications/WmsLowStockRenderer.tsx +2 -2
  2314. package/src/modules/wms/widgets/notifications/WmsReservationShortfallRenderer.tsx +4 -3
  2315. package/src/modules/workflows/AGENTS.md +7 -5
  2316. package/src/modules/workflows/api/commands/route.ts +4 -1
  2317. package/src/modules/workflows/api/definitions/[id]/callers/route.ts +4 -1
  2318. package/src/modules/workflows/api/definitions/[id]/context-schema/route.ts +4 -2
  2319. package/src/modules/workflows/api/definitions/[id]/customize/route.ts +4 -1
  2320. package/src/modules/workflows/api/definitions/[id]/draft/route.ts +6 -1
  2321. package/src/modules/workflows/api/definitions/[id]/publish/route.ts +10 -1
  2322. package/src/modules/workflows/api/definitions/[id]/reset-to-code/route.ts +4 -1
  2323. package/src/modules/workflows/api/definitions/[id]/route.ts +5 -3
  2324. package/src/modules/workflows/api/definitions/[id]/test-step/route.ts +4 -2
  2325. package/src/modules/workflows/api/definitions/generate/route.ts +4 -1
  2326. package/src/modules/workflows/api/definitions/route.ts +4 -2
  2327. package/src/modules/workflows/api/endpoints/route.ts +4 -1
  2328. package/src/modules/workflows/api/functions/route.ts +4 -1
  2329. package/src/modules/workflows/api/grantable-features/route.ts +2 -1
  2330. package/src/modules/workflows/api/instances/[id]/advance/route.ts +4 -1
  2331. package/src/modules/workflows/api/instances/[id]/cancel/route.ts +4 -1
  2332. package/src/modules/workflows/api/instances/[id]/context/route.ts +2 -1
  2333. package/src/modules/workflows/api/instances/[id]/rerun-step/route.ts +4 -1
  2334. package/src/modules/workflows/api/instances/[id]/retry/route.ts +4 -1
  2335. package/src/modules/workflows/api/instances/[id]/signal/route.ts +4 -1
  2336. package/src/modules/workflows/api/instances/[id]/step-through/route.ts +4 -2
  2337. package/src/modules/workflows/api/instances/route.ts +4 -2
  2338. package/src/modules/workflows/api/instances/validate-start/route.ts +4 -1
  2339. package/src/modules/workflows/api/rule-usage/route.ts +4 -1
  2340. package/src/modules/workflows/api/signals/route.ts +4 -1
  2341. package/src/modules/workflows/api/tasks/[id]/claim/route.ts +4 -1
  2342. package/src/modules/workflows/api/tasks/[id]/complete/route.ts +4 -1
  2343. package/src/modules/workflows/api/tasks/[id]/reassign/route.ts +2 -1
  2344. package/src/modules/workflows/api/tasks/[id]/unclaim/route.ts +4 -1
  2345. package/src/modules/workflows/api/templates/route.ts +4 -1
  2346. package/src/modules/workflows/api/work-inbox/next/route.ts +4 -1
  2347. package/src/modules/workflows/lib/activity-executor.ts +125 -28
  2348. package/src/modules/workflows/lib/activity-types.ts +8 -4
  2349. package/src/modules/workflows/lib/activity-worker-handler.ts +16 -12
  2350. package/src/modules/workflows/lib/event-trigger-service.ts +18 -2
  2351. package/src/modules/workflows/lib/step-handler.ts +13 -8
  2352. package/src/test-utils/transactionalEntityManagerDouble.ts +51 -0
@@ -0,0 +1,2525 @@
1
+ /**
2
+ * Visual Builder schema-helpers — pure, deterministic mutations on the
3
+ * studio's `FormSchema` view of an `x-om-*` form definition.
4
+ *
5
+ * Phase B (`.ai/specs/2026-05-10-forms-visual-builder.md`) wires drag-and-drop
6
+ * onto `FormStudio.tsx`. Every drag-end mutation goes through these helpers
7
+ * so the canvas, undo (Phase F), and tests share one source of truth.
8
+ *
9
+ * Constraints:
10
+ * - Helpers MUST return a deeply cloned schema — callers compose updates on
11
+ * the returned value without aliasing into React state.
12
+ * - Helpers MUST validate the OM extension payload via the existing
13
+ * `OM_FIELD_VALIDATORS` / `OM_ROOT_VALIDATORS` before returning. Validation
14
+ * failures throw `SchemaHelperError` with a human-readable message; the
15
+ * autosave guard surfaces the i18n key `forms.studio.autosave.invalidSchema`.
16
+ * - Object key insertion order is canonical: helpers rebuild `properties`
17
+ * from `fieldKeys` so `Object.entries(properties)` matches the visible
18
+ * canvas order (Decision 8a + § "Object.entries ordering invariant").
19
+ */
20
+
21
+ import {
22
+ OM_FIELD_KEYWORDS,
23
+ OM_FIELD_VALIDATORS,
24
+ OM_ROOT_KEYWORDS,
25
+ OM_ROOT_VALIDATORS,
26
+ validateOmCrossKeyword,
27
+ type OmFieldKeyword,
28
+ type OmRootKeyword,
29
+ } from '../../../../schema/jsonschema-extensions'
30
+ import { validateOmTheme } from '../../../../schema/style-validators'
31
+ import type { OmFieldStyle, OmSectionStyle, OmTheme } from '../../../../schema/style-extensions'
32
+
33
+ export type FieldNode = {
34
+ type: string | string[]
35
+ 'x-om-type': string
36
+ 'x-om-label'?: { [locale: string]: string }
37
+ 'x-om-help'?: { [locale: string]: string }
38
+ 'x-om-editable-by'?: string[]
39
+ 'x-om-visible-to'?: string[]
40
+ 'x-om-sensitive'?: boolean
41
+ 'x-om-pattern'?: string
42
+ 'x-om-min-length'?: number
43
+ 'x-om-max-length'?: number
44
+ 'x-om-validation-messages'?: { [locale: string]: { [rule: string]: string } }
45
+ 'x-om-ranking-exhaustive'?: boolean
46
+ 'x-om-matrix-rows'?: Array<{
47
+ key: string
48
+ label: { [locale: string]: string }
49
+ multiple?: boolean
50
+ required?: boolean
51
+ }>
52
+ 'x-om-matrix-columns'?: Array<{
53
+ value: string
54
+ label: { [locale: string]: string }
55
+ }>
56
+ 'x-om-accept'?: string[]
57
+ 'x-om-max-size-bytes'?: number
58
+ 'x-om-multiple'?: boolean
59
+ 'x-om-consent-clause'?: { [locale: string]: string }
60
+ 'x-om-signature-modes'?: Array<'drawn' | 'typed'>
61
+ 'x-om-min-items'?: number
62
+ 'x-om-max-items'?: number
63
+ /** W8 / FD-1 — logical prefill attribute key (e.g. `"name"`, `"email"`). */
64
+ 'x-om-prefill'?: string
65
+ [key: string]: unknown
66
+ }
67
+
68
+ export type SectionNode = {
69
+ key: string
70
+ title: { [locale: string]: string }
71
+ fieldKeys: string[]
72
+ kind?: 'page' | 'section' | 'ending'
73
+ columns?: 1 | 2 | 3 | 4
74
+ gap?: 'sm' | 'md' | 'lg'
75
+ divider?: boolean
76
+ hideTitle?: boolean
77
+ style?: OmSectionStyle
78
+ 'x-om-visibility-if'?: unknown
79
+ 'x-om-redirect-url'?: string | null
80
+ [key: string]: unknown
81
+ }
82
+
83
+ /** Sentinel section key used by the lenient orphan render (Decision 4c). */
84
+ export const UNGROUPED_SECTION_KEY = '__ungrouped__'
85
+
86
+ export type FormSchema = {
87
+ type: 'object'
88
+ 'x-om-roles'?: string[]
89
+ 'x-om-default-actor-role'?: string
90
+ 'x-om-sections'?: SectionNode[]
91
+ /** W8 / INT-5 — answer→consumer-target mapping (`{ [fieldKey]: targetPath }`). */
92
+ 'x-om-answer-mappings'?: { [fieldKey: string]: string }
93
+ properties: Record<string, FieldNode>
94
+ required?: string[]
95
+ [key: string]: unknown
96
+ }
97
+
98
+ export class SchemaHelperError extends Error {
99
+ readonly code: string
100
+ readonly path: string[]
101
+ constructor(message: string, code: string, path: string[] = []) {
102
+ super(message)
103
+ this.name = 'SchemaHelperError'
104
+ this.code = code
105
+ this.path = path
106
+ }
107
+ }
108
+
109
+ const FIELD_TYPE_TO_JSON_TYPE: Record<string, string> = {
110
+ text: 'string',
111
+ textarea: 'string',
112
+ number: 'number',
113
+ integer: 'integer',
114
+ boolean: 'boolean',
115
+ yes_no: 'boolean',
116
+ yes_no_buttons: 'boolean',
117
+ date: 'string',
118
+ datetime: 'string',
119
+ select_one: 'string',
120
+ select_many: 'array',
121
+ scale: 'integer',
122
+ info_block: 'string',
123
+ // Tier-2 — Phase B (`.ai/specs/2026-05-14-forms-tier-2-question-palette.md`).
124
+ email: 'string',
125
+ phone: 'string',
126
+ website: 'string',
127
+ // Tier-2 — Phase C: address is a composite object with required sub-fields.
128
+ address: 'object',
129
+ // Tier-2 — Phase D: NPS + opinion_scale are integers (range constraints
130
+ // live in `x-om-min/x-om-max` for opinion_scale; nps has fixed 0..10).
131
+ nps: 'integer',
132
+ opinion_scale: 'integer',
133
+ // Tier-2 — Phase E: ranking persists as an array of option-value strings in
134
+ // user-chosen order.
135
+ ranking: 'array',
136
+ // Tier-2 — Phase F: matrix persists as a Record<rowKey, string | string[]>.
137
+ matrix: 'object',
138
+ // W4 — file persists as an array of attachment-reference objects.
139
+ file: 'array',
140
+ // W6 — group (repeatable) persists as an array of objects (one per entry).
141
+ group: 'array',
142
+ }
143
+
144
+ /**
145
+ * Per-type initializer hook for `addFieldFromPalette`. When a type wants to
146
+ * persist additional JSON Schema structure (`properties` / `required` /
147
+ * `additionalProperties`) beyond the generic `{ type, x-om-type, x-om-label,
148
+ * x-om-editable-by }` shape, register it here. The initializer receives the
149
+ * newly-built node, mutates it in place, and returns it (the helper deep-
150
+ * clones the schema before calling so callers never observe shared refs).
151
+ *
152
+ * Phase C — `address` seeds a JSON Schema fragment with the canonical sub-
153
+ * property map per Decision 1 (single field key, value is the JSON object).
154
+ */
155
+ const FIELD_TYPE_NODE_INITIALIZER: Record<string, (node: FieldNode) => FieldNode> = {
156
+ select_one: (node) => {
157
+ node['x-om-options'] = []
158
+ return node
159
+ },
160
+ select_many: (node) => {
161
+ node.items = { type: 'string' }
162
+ node['x-om-options'] = []
163
+ return node
164
+ },
165
+ address: (node) => {
166
+ node.properties = {
167
+ street1: { type: 'string' },
168
+ street2: { type: 'string' },
169
+ city: { type: 'string' },
170
+ region: { type: 'string' },
171
+ postalCode: { type: 'string' },
172
+ country: { type: 'string' },
173
+ }
174
+ node.required = ['street1', 'city', 'country']
175
+ node.additionalProperties = false
176
+ return node
177
+ },
178
+ // Tier-2 Phase E — ranking persists as `string[]` (an ordered list of option
179
+ // values). The JSON Schema `items` constraint pins each entry's type so AJV
180
+ // rejects non-string entries; the `x-om-options` map seeds the empty array
181
+ // so authors immediately see the option editor.
182
+ ranking: (node) => {
183
+ node.items = { type: 'string' }
184
+ node['x-om-options'] = []
185
+ return node
186
+ },
187
+ // Tier-2 Phase F — matrix seeds empty rows / columns + locks unknown sub-keys.
188
+ matrix: (node) => {
189
+ node.additionalProperties = false
190
+ node['x-om-matrix-rows'] = []
191
+ node['x-om-matrix-columns'] = []
192
+ return node
193
+ },
194
+ // W4 — file persists an array of attachment-reference objects; `items`
195
+ // pins each entry to an object so AJV rejects scalars in the array.
196
+ file: (node) => {
197
+ node.items = { type: 'object' }
198
+ node['x-om-accept'] = []
199
+ node['x-om-multiple'] = false
200
+ return node
201
+ },
202
+ // W2 — signature persists an object value (mode + image/typedName +
203
+ // affirmed + signedAt + clauseSha256). Seed an empty consent clause map so
204
+ // the author immediately sees the clause editor.
205
+ signature: (node) => {
206
+ node.additionalProperties = false
207
+ node['x-om-consent-clause'] = {}
208
+ return node
209
+ },
210
+ // W6 — group (repeatable) persists as an array of objects. Seed `items`
211
+ // with a JSON-Schema object fragment carrying one starter sub-field so the
212
+ // author immediately sees the sub-field editor. Native `items.properties` /
213
+ // `required` / `additionalProperties:false` let AJV enforce the sub-field
214
+ // shape server-side (the submission service validates via `compiled.ajv`).
215
+ group: (node) => {
216
+ node.items = {
217
+ type: 'object',
218
+ additionalProperties: false,
219
+ properties: {
220
+ field_1: {
221
+ type: 'string',
222
+ 'x-om-type': 'text',
223
+ 'x-om-label': { en: 'New sub-field' },
224
+ },
225
+ },
226
+ required: [],
227
+ }
228
+ return node
229
+ },
230
+ }
231
+
232
+ const FIELD_KEY_PATTERN = /^field_(\d+)$/
233
+
234
+ export function deepClone<T>(value: T): T {
235
+ return JSON.parse(JSON.stringify(value)) as T
236
+ }
237
+
238
+ /**
239
+ * Generates the next `field_<n>` key per Decision 21a — `1 + max numeric
240
+ * suffix in properties`. Non-numeric keys (custom-edited or legacy) are
241
+ * ignored so they never collide with the auto-generated stream.
242
+ */
243
+ export function nextFieldKey(properties: Record<string, unknown>): string {
244
+ let maxSuffix = 0
245
+ for (const key of Object.keys(properties)) {
246
+ const match = FIELD_KEY_PATTERN.exec(key)
247
+ if (!match) continue
248
+ const value = Number.parseInt(match[1], 10)
249
+ if (Number.isFinite(value) && value > maxSuffix) maxSuffix = value
250
+ }
251
+ return `field_${maxSuffix + 1}`
252
+ }
253
+
254
+ /**
255
+ * Generates the next `section_<n>` key per Decision 21c. Section keys are
256
+ * globally unique within `x-om-sections`.
257
+ */
258
+ export function nextSectionKey(sections: ReadonlyArray<SectionNode> | undefined): string {
259
+ let maxSuffix = 0
260
+ const pattern = /^section_(\d+)$/
261
+ for (const section of sections ?? []) {
262
+ const match = pattern.exec(section.key)
263
+ if (!match) continue
264
+ const value = Number.parseInt(match[1], 10)
265
+ if (Number.isFinite(value) && value > maxSuffix) maxSuffix = value
266
+ }
267
+ return `section_${maxSuffix + 1}`
268
+ }
269
+
270
+ /**
271
+ * Validates the OM extension payload of a schema. Throws on the first
272
+ * violation so callers can guard autosaves before PATCHing.
273
+ */
274
+ export function validateSchemaExtensions(schema: FormSchema): void {
275
+ for (const [keyword, validator] of Object.entries(OM_ROOT_VALIDATORS)) {
276
+ const rootKeyword = keyword as OmRootKeyword
277
+ const value = (schema as Record<string, unknown>)[rootKeyword]
278
+ if (value === undefined) continue
279
+ const violation = validator(value)
280
+ if (violation) throw new SchemaHelperError(violation, 'invalid_root', [rootKeyword])
281
+ }
282
+ for (const [fieldKey, fieldNode] of Object.entries(schema.properties)) {
283
+ if (!fieldNode || typeof fieldNode !== 'object') {
284
+ throw new SchemaHelperError('Field nodes must be objects.', 'invalid_field', [fieldKey])
285
+ }
286
+ for (const [keyword, validator] of Object.entries(OM_FIELD_VALIDATORS)) {
287
+ const fieldKeyword = keyword as OmFieldKeyword
288
+ const value = (fieldNode as Record<string, unknown>)[fieldKeyword]
289
+ if (value === undefined) continue
290
+ const violation = validator(value)
291
+ if (violation) {
292
+ throw new SchemaHelperError(violation, 'invalid_field', [fieldKey, fieldKeyword])
293
+ }
294
+ }
295
+ }
296
+ const crossKeywordViolation = validateOmCrossKeyword(schema as Record<string, unknown>)
297
+ if (crossKeywordViolation) {
298
+ throw new SchemaHelperError(crossKeywordViolation, 'invalid_cross_keyword', [])
299
+ }
300
+ }
301
+
302
+ /**
303
+ * Builds a schema with `properties` rebuilt from a canonical key array so
304
+ * `Object.entries(properties)` matches the array order. Existing field
305
+ * nodes are preserved; missing keys silently drop (caller should never
306
+ * pass unknown keys, but the helper is defensive).
307
+ */
308
+ function rebuildPropertiesByOrder(
309
+ schema: FormSchema,
310
+ orderedKeys: ReadonlyArray<string>,
311
+ ): FormSchema {
312
+ const next = deepClone(schema)
313
+ const sourceProperties = next.properties
314
+ const seen = new Set<string>()
315
+ const rebuilt: Record<string, FieldNode> = {}
316
+ for (const key of orderedKeys) {
317
+ if (seen.has(key)) continue
318
+ seen.add(key)
319
+ const node = sourceProperties[key]
320
+ if (!node) continue
321
+ rebuilt[key] = node
322
+ }
323
+ for (const [key, node] of Object.entries(sourceProperties)) {
324
+ if (seen.has(key)) continue
325
+ rebuilt[key] = node
326
+ }
327
+ next.properties = rebuilt
328
+ return next
329
+ }
330
+
331
+ /**
332
+ * Returns the section that owns the given field key, or `null` if the
333
+ * field is orphaned (not listed in any section's `fieldKeys`).
334
+ */
335
+ export function findSectionOwning(
336
+ schema: FormSchema,
337
+ fieldKey: string,
338
+ ): SectionNode | null {
339
+ const sections = schema[OM_ROOT_KEYWORDS.sections] ?? []
340
+ for (const section of sections) {
341
+ if (section.fieldKeys.includes(fieldKey)) return section
342
+ }
343
+ return null
344
+ }
345
+
346
+ /**
347
+ * Returns the index of `fieldKey` within `sectionKey.fieldKeys`, or `-1`
348
+ * if either the section or the field within it is absent.
349
+ */
350
+ export function indexOfFieldInSection(
351
+ schema: FormSchema,
352
+ sectionKey: string,
353
+ fieldKey: string,
354
+ ): number {
355
+ const sections = schema[OM_ROOT_KEYWORDS.sections] ?? []
356
+ const section = sections.find((entry) => entry.key === sectionKey)
357
+ if (!section) return -1
358
+ return section.fieldKeys.indexOf(fieldKey)
359
+ }
360
+
361
+ export type LinearFieldEntry = {
362
+ key: string
363
+ sectionKey: string | null
364
+ }
365
+
366
+ /**
367
+ * Linearizes the schema into a flat ordered list of fields — sections
368
+ * first (in declaration order), orphan fields appended last. Used by the
369
+ * canvas to memoize the visible field sequence per Decision 34.
370
+ */
371
+ export function linearizeFields(schema: FormSchema): LinearFieldEntry[] {
372
+ const linear: LinearFieldEntry[] = []
373
+ const sections = schema[OM_ROOT_KEYWORDS.sections] ?? []
374
+ const claimed = new Set<string>()
375
+ for (const section of sections) {
376
+ for (const fieldKey of section.fieldKeys) {
377
+ if (claimed.has(fieldKey)) continue
378
+ claimed.add(fieldKey)
379
+ linear.push({ key: fieldKey, sectionKey: section.key })
380
+ }
381
+ }
382
+ for (const fieldKey of Object.keys(schema.properties)) {
383
+ if (claimed.has(fieldKey)) continue
384
+ linear.push({ key: fieldKey, sectionKey: null })
385
+ }
386
+ return linear
387
+ }
388
+
389
+ export type AddFieldTarget = {
390
+ sectionKey: string
391
+ /** Insertion index within `sectionKey.fieldKeys`. Appends when omitted. */
392
+ index?: number
393
+ }
394
+
395
+ export type AddFieldResult = {
396
+ schema: FormSchema
397
+ fieldKey: string
398
+ }
399
+
400
+ /**
401
+ * Appends or inserts a new field of `typeKey` into the section identified by
402
+ * `target.sectionKey`. Generates a unique key via `nextFieldKey` and
403
+ * rebuilds `properties` so `Object.entries` matches the section ordering.
404
+ */
405
+ export function addFieldFromPalette(input: {
406
+ schema: FormSchema
407
+ typeKey: string
408
+ target: AddFieldTarget
409
+ }): AddFieldResult {
410
+ const { schema, typeKey, target } = input
411
+ if (!typeKey) {
412
+ throw new SchemaHelperError('typeKey is required.', 'invalid_input', ['typeKey'])
413
+ }
414
+ const next = deepClone(schema)
415
+ const sections = (next[OM_ROOT_KEYWORDS.sections] ?? []) as SectionNode[]
416
+ const section = sections.find((entry) => entry.key === target.sectionKey)
417
+ if (!section) {
418
+ throw new SchemaHelperError(
419
+ `Section "${target.sectionKey}" not found.`,
420
+ 'unknown_section',
421
+ [target.sectionKey],
422
+ )
423
+ }
424
+ const newKey = nextFieldKey(next.properties)
425
+ const jsonType = FIELD_TYPE_TO_JSON_TYPE[typeKey] ?? 'string'
426
+ const defaultActorRole =
427
+ (next[OM_ROOT_KEYWORDS.defaultActorRole] as string | undefined) ?? 'admin'
428
+ const fieldNode: FieldNode = {
429
+ type: jsonType,
430
+ 'x-om-type': typeKey,
431
+ 'x-om-label': { en: 'New field' },
432
+ 'x-om-editable-by': dedupePreservingOrder([defaultActorRole, 'admin']),
433
+ }
434
+ const initializer = FIELD_TYPE_NODE_INITIALIZER[typeKey]
435
+ if (initializer) initializer(fieldNode)
436
+ next.properties[newKey] = fieldNode
437
+ next.required = next.required ?? []
438
+
439
+ const insertionIndex =
440
+ typeof target.index === 'number' && target.index >= 0 && target.index <= section.fieldKeys.length
441
+ ? target.index
442
+ : section.fieldKeys.length
443
+ section.fieldKeys = [
444
+ ...section.fieldKeys.slice(0, insertionIndex),
445
+ newKey,
446
+ ...section.fieldKeys.slice(insertionIndex),
447
+ ]
448
+
449
+ const orderedKeys = collectCanonicalOrder(next)
450
+ const result = rebuildPropertiesByOrder(next, orderedKeys)
451
+ validateSchemaExtensions(result)
452
+ return { schema: result, fieldKey: newKey }
453
+ }
454
+
455
+ export type MoveFieldTarget = {
456
+ sectionKey: string
457
+ /** Insertion index within `sectionKey.fieldKeys`. Appends when omitted. */
458
+ index?: number
459
+ }
460
+
461
+ /**
462
+ * Moves an existing field to a new location, optionally re-parenting it
463
+ * to a different section. Preserves all node metadata verbatim
464
+ * (Decision 8b — `gridSpan` etc. survive cross-section moves).
465
+ */
466
+ export function moveField(input: {
467
+ schema: FormSchema
468
+ fieldKey: string
469
+ target: MoveFieldTarget
470
+ }): FormSchema {
471
+ const { schema, fieldKey, target } = input
472
+ if (!schema.properties[fieldKey]) {
473
+ throw new SchemaHelperError(
474
+ `Field "${fieldKey}" not found.`,
475
+ 'unknown_field',
476
+ [fieldKey],
477
+ )
478
+ }
479
+ const next = deepClone(schema)
480
+ const sections = (next[OM_ROOT_KEYWORDS.sections] ?? []) as SectionNode[]
481
+ const targetSection = sections.find((entry) => entry.key === target.sectionKey)
482
+ if (!targetSection) {
483
+ throw new SchemaHelperError(
484
+ `Section "${target.sectionKey}" not found.`,
485
+ 'unknown_section',
486
+ [target.sectionKey],
487
+ )
488
+ }
489
+ for (const section of sections) {
490
+ section.fieldKeys = section.fieldKeys.filter((entry) => entry !== fieldKey)
491
+ }
492
+ const insertionIndex =
493
+ typeof target.index === 'number' && target.index >= 0 && target.index <= targetSection.fieldKeys.length
494
+ ? target.index
495
+ : targetSection.fieldKeys.length
496
+ targetSection.fieldKeys = [
497
+ ...targetSection.fieldKeys.slice(0, insertionIndex),
498
+ fieldKey,
499
+ ...targetSection.fieldKeys.slice(insertionIndex),
500
+ ]
501
+ const orderedKeys = collectCanonicalOrder(next)
502
+ const result = rebuildPropertiesByOrder(next, orderedKeys)
503
+ validateSchemaExtensions(result)
504
+ return result
505
+ }
506
+
507
+ /**
508
+ * Removes a field node and every structural reference to it. Deleting only
509
+ * `properties[fieldKey]` leaves dangling `x-om-sections[*].fieldKeys`, which
510
+ * makes autosave fail validation and causes the field to reappear on reload.
511
+ */
512
+ export function deleteField(input: {
513
+ schema: FormSchema
514
+ fieldKey: string
515
+ }): FormSchema {
516
+ const { schema, fieldKey } = input
517
+ if (!schema.properties[fieldKey]) {
518
+ throw new SchemaHelperError(
519
+ `Field "${fieldKey}" not found.`,
520
+ 'unknown_field',
521
+ [fieldKey],
522
+ )
523
+ }
524
+ const next = deepClone(schema)
525
+ delete next.properties[fieldKey]
526
+ next.required = (next.required ?? []).filter((entry) => entry !== fieldKey)
527
+ const sections = (next[OM_ROOT_KEYWORDS.sections] ?? []) as SectionNode[]
528
+ for (const section of sections) {
529
+ section.fieldKeys = section.fieldKeys.filter((entry) => entry !== fieldKey)
530
+ }
531
+ const orderedKeys = collectCanonicalOrder(next)
532
+ const result = rebuildPropertiesByOrder(next, orderedKeys)
533
+ validateSchemaExtensions(result)
534
+ return result
535
+ }
536
+
537
+ export type AddLayoutTarget = {
538
+ /**
539
+ * Insertion index within `x-om-sections`. Appends when omitted or out of
540
+ * range. Used by section-reorder DnD to drop a new layout primitive at a
541
+ * specific position.
542
+ */
543
+ index?: number
544
+ }
545
+
546
+ export type AddLayoutResult = {
547
+ schema: FormSchema
548
+ sectionKey: string
549
+ }
550
+
551
+ /**
552
+ * Materialises a new layout container (`page` or `section`) in
553
+ * `x-om-sections`. Phase C — Decision 1 / Decision 9.
554
+ *
555
+ * Persisted shape is intentionally minimal: `{ key, kind, title, fieldKeys }`.
556
+ * `columns / gap / divider / hideTitle` defaults are applied at read time
557
+ * by the compiler so a verbatim round-trip keeps the schema byte-identical
558
+ * (R-9 mitigation).
559
+ */
560
+ export function addLayoutFromPalette(input: {
561
+ schema: FormSchema
562
+ kind: 'page' | 'section' | 'ending'
563
+ target?: AddLayoutTarget
564
+ }): AddLayoutResult {
565
+ const { schema, kind } = input
566
+ if (kind !== 'page' && kind !== 'section' && kind !== 'ending') {
567
+ throw new SchemaHelperError(
568
+ `Unknown layout kind "${String(kind)}" — expected "page", "section", or "ending".`,
569
+ 'invalid_layout_kind',
570
+ ['kind'],
571
+ )
572
+ }
573
+ const next = deepClone(schema)
574
+ const sections = (next[OM_ROOT_KEYWORDS.sections] ?? []) as SectionNode[]
575
+ const newKey = nextSectionKey(sections)
576
+ const newSection: SectionNode = {
577
+ key: newKey,
578
+ kind,
579
+ title: {
580
+ en: kind === 'page' ? 'New page' : kind === 'ending' ? 'New ending' : 'New section',
581
+ },
582
+ fieldKeys: [],
583
+ }
584
+ const desiredIndex = input.target?.index
585
+ const insertionIndex =
586
+ typeof desiredIndex === 'number' && desiredIndex >= 0 && desiredIndex <= sections.length
587
+ ? desiredIndex
588
+ : sections.length
589
+ const inserted: SectionNode[] = [
590
+ ...sections.slice(0, insertionIndex),
591
+ newSection,
592
+ ...sections.slice(insertionIndex),
593
+ ]
594
+ next[OM_ROOT_KEYWORDS.sections] = inserted
595
+ validateSchemaExtensions(next)
596
+ return { schema: next, sectionKey: newKey }
597
+ }
598
+
599
+ /**
600
+ * Reorders the section list. `beforeKey` is the section currently at the
601
+ * desired insertion slot — passing `null` appends. Decision 8c (pure
602
+ * positional reorder; cross-page-boundary drags do not require confirms).
603
+ */
604
+ export function moveSection(input: {
605
+ schema: FormSchema
606
+ sectionKey: string
607
+ beforeKey: string | null
608
+ }): FormSchema {
609
+ const { schema, sectionKey, beforeKey } = input
610
+ const next = deepClone(schema)
611
+ const sections = (next[OM_ROOT_KEYWORDS.sections] ?? []) as SectionNode[]
612
+ const sourceIndex = sections.findIndex((entry) => entry.key === sectionKey)
613
+ if (sourceIndex < 0) {
614
+ throw new SchemaHelperError(
615
+ `Section "${sectionKey}" not found.`,
616
+ 'unknown_section',
617
+ [sectionKey],
618
+ )
619
+ }
620
+ const [moved] = sections.splice(sourceIndex, 1)
621
+ let targetIndex = sections.length
622
+ if (beforeKey !== null) {
623
+ const candidate = sections.findIndex((entry) => entry.key === beforeKey)
624
+ if (candidate >= 0) targetIndex = candidate
625
+ }
626
+ sections.splice(targetIndex, 0, moved)
627
+ next[OM_ROOT_KEYWORDS.sections] = sections
628
+ validateSchemaExtensions(next)
629
+ return next
630
+ }
631
+
632
+ /**
633
+ * Removes a section. Fields owned by the section are also removed from
634
+ * `properties` and `required` — Decision 22b's confirm dialog is a UI
635
+ * concern; this helper is the structural mutator.
636
+ */
637
+ export function deleteSection(input: {
638
+ schema: FormSchema
639
+ sectionKey: string
640
+ }): FormSchema {
641
+ const { schema, sectionKey } = input
642
+ const next = deepClone(schema)
643
+ const sections = (next[OM_ROOT_KEYWORDS.sections] ?? []) as SectionNode[]
644
+ const target = sections.find((entry) => entry.key === sectionKey)
645
+ if (!target) {
646
+ throw new SchemaHelperError(
647
+ `Section "${sectionKey}" not found.`,
648
+ 'unknown_section',
649
+ [sectionKey],
650
+ )
651
+ }
652
+ const fieldsToRemove = new Set(target.fieldKeys)
653
+ next[OM_ROOT_KEYWORDS.sections] = sections.filter((entry) => entry.key !== sectionKey)
654
+ for (const fieldKey of fieldsToRemove) {
655
+ delete next.properties[fieldKey]
656
+ }
657
+ next.required = (next.required ?? []).filter((entry) => !fieldsToRemove.has(entry))
658
+ validateSchemaExtensions(next)
659
+ return next
660
+ }
661
+
662
+ /**
663
+ * Sets a section's `columns`. Persists the value verbatim — Decision 3a
664
+ * keeps `gridSpan` clamping to render time, so changing columns never
665
+ * rewrites field-level spans.
666
+ */
667
+ export function setSectionColumns(input: {
668
+ schema: FormSchema
669
+ sectionKey: string
670
+ columns: 1 | 2 | 3 | 4
671
+ }): FormSchema {
672
+ const { schema, sectionKey, columns } = input
673
+ const next = deepClone(schema)
674
+ const sections = (next[OM_ROOT_KEYWORDS.sections] ?? []) as SectionNode[]
675
+ const section = sections.find((entry) => entry.key === sectionKey)
676
+ if (!section) {
677
+ throw new SchemaHelperError(
678
+ `Section "${sectionKey}" not found.`,
679
+ 'unknown_section',
680
+ [sectionKey],
681
+ )
682
+ }
683
+ if (columns === 1) {
684
+ delete section.columns
685
+ } else {
686
+ section.columns = columns
687
+ }
688
+ validateSchemaExtensions(next)
689
+ return next
690
+ }
691
+
692
+ /**
693
+ * Updates a section's localized title for the given locale (Decision 26a/26b).
694
+ * Empty strings clear the locale entry to keep the persisted shape tidy.
695
+ */
696
+ export function setSectionTitle(input: {
697
+ schema: FormSchema
698
+ sectionKey: string
699
+ locale: string
700
+ title: string
701
+ }): FormSchema {
702
+ const { schema, sectionKey, locale, title } = input
703
+ if (!locale) {
704
+ throw new SchemaHelperError('locale is required.', 'invalid_input', ['locale'])
705
+ }
706
+ const next = deepClone(schema)
707
+ const sections = (next[OM_ROOT_KEYWORDS.sections] ?? []) as SectionNode[]
708
+ const section = sections.find((entry) => entry.key === sectionKey)
709
+ if (!section) {
710
+ throw new SchemaHelperError(
711
+ `Section "${sectionKey}" not found.`,
712
+ 'unknown_section',
713
+ [sectionKey],
714
+ )
715
+ }
716
+ const titleMap = section.title ? { ...section.title } : {}
717
+ if (title.length === 0) {
718
+ delete titleMap[locale]
719
+ } else {
720
+ titleMap[locale] = title
721
+ }
722
+ section.title = titleMap
723
+ validateSchemaExtensions(next)
724
+ return next
725
+ }
726
+
727
+ /**
728
+ * Updates a section's `kind` (`page` ⇄ `section`). Decision 10c — the
729
+ * toggle is reversible so we never write a confirm dialog around it.
730
+ */
731
+ export function setSectionKind(input: {
732
+ schema: FormSchema
733
+ sectionKey: string
734
+ kind: 'page' | 'section'
735
+ }): FormSchema {
736
+ const { schema, sectionKey, kind } = input
737
+ const next = deepClone(schema)
738
+ const sections = (next[OM_ROOT_KEYWORDS.sections] ?? []) as SectionNode[]
739
+ const section = sections.find((entry) => entry.key === sectionKey)
740
+ if (!section) {
741
+ throw new SchemaHelperError(
742
+ `Section "${sectionKey}" not found.`,
743
+ 'unknown_section',
744
+ [sectionKey],
745
+ )
746
+ }
747
+ if (kind === 'section') {
748
+ delete section.kind
749
+ } else {
750
+ section.kind = kind
751
+ }
752
+ validateSchemaExtensions(next)
753
+ return next
754
+ }
755
+
756
+ /**
757
+ * Sets the section `gap` (`'sm' | 'md' | 'lg'`). `'md'` is the default and
758
+ * unsets the persisted value to keep the shape minimal (Decision 9).
759
+ */
760
+ export function setSectionGap(input: {
761
+ schema: FormSchema
762
+ sectionKey: string
763
+ gap: 'sm' | 'md' | 'lg'
764
+ }): FormSchema {
765
+ const { schema, sectionKey, gap } = input
766
+ const next = deepClone(schema)
767
+ const sections = (next[OM_ROOT_KEYWORDS.sections] ?? []) as SectionNode[]
768
+ const section = sections.find((entry) => entry.key === sectionKey)
769
+ if (!section) {
770
+ throw new SchemaHelperError(
771
+ `Section "${sectionKey}" not found.`,
772
+ 'unknown_section',
773
+ [sectionKey],
774
+ )
775
+ }
776
+ if (gap === 'md') {
777
+ delete section.gap
778
+ } else {
779
+ section.gap = gap
780
+ }
781
+ validateSchemaExtensions(next)
782
+ return next
783
+ }
784
+
785
+ /**
786
+ * Toggles a section's `divider` boolean. `false` is the default and is
787
+ * persisted as the absence of the key (Decision 9).
788
+ */
789
+ export function setSectionDivider(input: {
790
+ schema: FormSchema
791
+ sectionKey: string
792
+ divider: boolean
793
+ }): FormSchema {
794
+ const { schema, sectionKey, divider } = input
795
+ const next = deepClone(schema)
796
+ const sections = (next[OM_ROOT_KEYWORDS.sections] ?? []) as SectionNode[]
797
+ const section = sections.find((entry) => entry.key === sectionKey)
798
+ if (!section) {
799
+ throw new SchemaHelperError(
800
+ `Section "${sectionKey}" not found.`,
801
+ 'unknown_section',
802
+ [sectionKey],
803
+ )
804
+ }
805
+ if (divider === false) {
806
+ delete section.divider
807
+ } else {
808
+ section.divider = true
809
+ }
810
+ validateSchemaExtensions(next)
811
+ return next
812
+ }
813
+
814
+ /**
815
+ * Toggles a section's `hideTitle` boolean. `false` is the default and is
816
+ * persisted as the absence of the key (Decision 9).
817
+ */
818
+ export function setSectionHideTitle(input: {
819
+ schema: FormSchema
820
+ sectionKey: string
821
+ hideTitle: boolean
822
+ }): FormSchema {
823
+ const { schema, sectionKey, hideTitle } = input
824
+ const next = deepClone(schema)
825
+ const sections = (next[OM_ROOT_KEYWORDS.sections] ?? []) as SectionNode[]
826
+ const section = sections.find((entry) => entry.key === sectionKey)
827
+ if (!section) {
828
+ throw new SchemaHelperError(
829
+ `Section "${sectionKey}" not found.`,
830
+ 'unknown_section',
831
+ [sectionKey],
832
+ )
833
+ }
834
+ if (hideTitle === false) {
835
+ delete section.hideTitle
836
+ } else {
837
+ section.hideTitle = true
838
+ }
839
+ validateSchemaExtensions(next)
840
+ return next
841
+ }
842
+
843
+ /**
844
+ * Sets a field's persisted `x-om-grid-span`. Persisted verbatim per
845
+ * Decision 3a — clamping against the parent section's `columns` is the
846
+ * renderer's job, never the validator's.
847
+ */
848
+ export function setFieldGridSpan(input: {
849
+ schema: FormSchema
850
+ fieldKey: string
851
+ span: 1 | 2 | 3 | 4
852
+ }): FormSchema {
853
+ const { schema, fieldKey, span } = input
854
+ const next = deepClone(schema)
855
+ const node = next.properties[fieldKey]
856
+ if (!node) {
857
+ throw new SchemaHelperError(
858
+ `Field "${fieldKey}" not found.`,
859
+ 'unknown_field',
860
+ [fieldKey],
861
+ )
862
+ }
863
+ if (span === 1) {
864
+ delete node['x-om-grid-span']
865
+ } else {
866
+ node['x-om-grid-span'] = span
867
+ }
868
+ validateSchemaExtensions(next)
869
+ return next
870
+ }
871
+
872
+ /**
873
+ * Sets a field's `x-om-align`. Default `'start'` is persisted as the
874
+ * absence of the key to keep the persisted shape minimal (read-time
875
+ * defaulters apply at render time).
876
+ */
877
+ export function setFieldAlign(input: {
878
+ schema: FormSchema
879
+ fieldKey: string
880
+ align: 'start' | 'center' | 'end'
881
+ }): FormSchema {
882
+ const { schema, fieldKey, align } = input
883
+ const next = deepClone(schema)
884
+ const node = next.properties[fieldKey]
885
+ if (!node) {
886
+ throw new SchemaHelperError(
887
+ `Field "${fieldKey}" not found.`,
888
+ 'unknown_field',
889
+ [fieldKey],
890
+ )
891
+ }
892
+ if (align === 'start') {
893
+ delete node[OM_FIELD_KEYWORDS.align]
894
+ } else {
895
+ node[OM_FIELD_KEYWORDS.align] = align
896
+ }
897
+ validateSchemaExtensions(next)
898
+ return next
899
+ }
900
+
901
+ export type HiddenFieldEntry = {
902
+ name: string
903
+ defaultValue?: string
904
+ }
905
+
906
+ export type VariableEntry = {
907
+ name: string
908
+ type: 'number' | 'boolean' | 'string'
909
+ formula: unknown
910
+ default?: number | boolean | string
911
+ }
912
+
913
+ export type JumpTarget =
914
+ | { type: 'page'; pageKey: string }
915
+ | { type: 'ending'; endingKey: string }
916
+ | { type: 'next' }
917
+ | { type: 'submit' }
918
+
919
+ export type JumpRuleEntry = {
920
+ from: { type: 'page'; pageKey: string } | { type: 'field'; fieldKey: string }
921
+ rules: Array<{ if: unknown; goto: JumpTarget }>
922
+ otherwise?: JumpTarget
923
+ }
924
+
925
+ /**
926
+ * Replaces the form's `x-om-jumps` declarations. Passing an empty array
927
+ * clears the keyword (R-9 minimalism — no-op round-trip preserves hash).
928
+ * Cross-keyword validation rejects dangling targets at save time.
929
+ */
930
+ export function setJumps(input: {
931
+ schema: FormSchema
932
+ rules: JumpRuleEntry[]
933
+ }): FormSchema {
934
+ const { schema, rules } = input
935
+ const next = deepClone(schema)
936
+ if (!rules || rules.length === 0) {
937
+ delete (next as Record<string, unknown>)[OM_ROOT_KEYWORDS.jumps]
938
+ } else {
939
+ ;(next as Record<string, unknown>)[OM_ROOT_KEYWORDS.jumps] = rules.map((rule) => {
940
+ const result: Record<string, unknown> = {
941
+ from: rule.from,
942
+ rules: rule.rules,
943
+ }
944
+ if (rule.otherwise) result.otherwise = rule.otherwise
945
+ return result
946
+ })
947
+ }
948
+ validateSchemaExtensions(next)
949
+ return next
950
+ }
951
+
952
+ /**
953
+ * Replaces the form's `x-om-variables` declarations. Passing an empty array
954
+ * clears the keyword entirely so a verbatim round-trip preserves the schema
955
+ * hash (R-9 mitigation).
956
+ */
957
+ export function setVariables(input: {
958
+ schema: FormSchema
959
+ entries: VariableEntry[]
960
+ }): FormSchema {
961
+ const { schema, entries } = input
962
+ const next = deepClone(schema)
963
+ if (!entries || entries.length === 0) {
964
+ delete (next as Record<string, unknown>)[OM_ROOT_KEYWORDS.variables]
965
+ } else {
966
+ const cleaned = entries.map((entry) => {
967
+ const result: Record<string, unknown> = {
968
+ name: entry.name,
969
+ type: entry.type,
970
+ formula: entry.formula,
971
+ }
972
+ if (entry.default !== undefined) result.default = entry.default
973
+ return result
974
+ })
975
+ ;(next as Record<string, unknown>)[OM_ROOT_KEYWORDS.variables] = cleaned
976
+ }
977
+ validateSchemaExtensions(next)
978
+ return next
979
+ }
980
+
981
+ /**
982
+ * Replaces the form's `x-om-hidden-fields` declarations. Passing an empty
983
+ * array clears the keyword entirely so the persisted shape stays minimal
984
+ * (R-9 mitigation — no-op round-trip preserves schema hash).
985
+ */
986
+ export function setHiddenFields(input: {
987
+ schema: FormSchema
988
+ entries: HiddenFieldEntry[]
989
+ }): FormSchema {
990
+ const { schema, entries } = input
991
+ const next = deepClone(schema)
992
+ if (!entries || entries.length === 0) {
993
+ delete (next as Record<string, unknown>)[OM_ROOT_KEYWORDS.hiddenFields]
994
+ } else {
995
+ const cleaned = entries.map((entry) => {
996
+ const result: Record<string, unknown> = { name: entry.name }
997
+ if (entry.defaultValue !== undefined && entry.defaultValue.length > 0) {
998
+ result.defaultValue = entry.defaultValue
999
+ }
1000
+ return result
1001
+ })
1002
+ ;(next as Record<string, unknown>)[OM_ROOT_KEYWORDS.hiddenFields] = cleaned
1003
+ }
1004
+ validateSchemaExtensions(next)
1005
+ return next
1006
+ }
1007
+
1008
+ /**
1009
+ * Sets (or clears) an ending section's `x-om-redirect-url`. Throws if the
1010
+ * section is not `kind: 'ending'` — validators reject redirect-url on
1011
+ * non-ending sections (Phase A `OM_ROOT_VALIDATORS`).
1012
+ */
1013
+ export function setRedirectUrl(input: {
1014
+ schema: FormSchema
1015
+ sectionKey: string
1016
+ url: string | null
1017
+ }): FormSchema {
1018
+ const { schema, sectionKey, url } = input
1019
+ const next = deepClone(schema)
1020
+ const sections = (next[OM_ROOT_KEYWORDS.sections] ?? []) as SectionNode[]
1021
+ const section = sections.find((entry) => entry.key === sectionKey)
1022
+ if (!section) {
1023
+ throw new SchemaHelperError(
1024
+ `Section "${sectionKey}" not found.`,
1025
+ 'unknown_section',
1026
+ [sectionKey],
1027
+ )
1028
+ }
1029
+ if (section.kind !== 'ending') {
1030
+ throw new SchemaHelperError(
1031
+ `Section "${sectionKey}" is not an ending — redirect URL is only valid on ending sections.`,
1032
+ 'invalid_redirect_target',
1033
+ [sectionKey],
1034
+ )
1035
+ }
1036
+ const trimmed = typeof url === 'string' ? url.trim() : ''
1037
+ if (!trimmed) {
1038
+ delete (section as Record<string, unknown>)['x-om-redirect-url']
1039
+ } else {
1040
+ ;(section as Record<string, unknown>)['x-om-redirect-url'] = trimmed
1041
+ }
1042
+ validateSchemaExtensions(next)
1043
+ return next
1044
+ }
1045
+
1046
+ /**
1047
+ * Sets (or clears) a field's `x-om-visibility-if` jsonlogic predicate
1048
+ * (reactive-core spec — Phase B). `null` / `undefined` clears the keyword
1049
+ * to keep the persisted shape minimal so a no-op round-trip preserves the
1050
+ * schema hash (R-9 mitigation).
1051
+ */
1052
+ export function setFieldVisibilityIf(input: {
1053
+ schema: FormSchema
1054
+ fieldKey: string
1055
+ predicate: unknown | null
1056
+ }): FormSchema {
1057
+ const { schema, fieldKey, predicate } = input
1058
+ const next = deepClone(schema)
1059
+ const node = next.properties[fieldKey]
1060
+ if (!node) {
1061
+ throw new SchemaHelperError(
1062
+ `Field "${fieldKey}" not found.`,
1063
+ 'unknown_field',
1064
+ [fieldKey],
1065
+ )
1066
+ }
1067
+ if (predicate === null || predicate === undefined) {
1068
+ delete node[OM_FIELD_KEYWORDS.visibilityIf]
1069
+ } else {
1070
+ node[OM_FIELD_KEYWORDS.visibilityIf] = predicate
1071
+ }
1072
+ validateSchemaExtensions(next)
1073
+ return next
1074
+ }
1075
+
1076
+ /**
1077
+ * Sets (or clears) a section's `x-om-visibility-if` jsonlogic predicate.
1078
+ * Endings reject visibility predicates (validated by `OM_ROOT_VALIDATORS`).
1079
+ */
1080
+ export function setSectionVisibilityIf(input: {
1081
+ schema: FormSchema
1082
+ sectionKey: string
1083
+ predicate: unknown | null
1084
+ }): FormSchema {
1085
+ const { schema, sectionKey, predicate } = input
1086
+ const next = deepClone(schema)
1087
+ const sections = (next[OM_ROOT_KEYWORDS.sections] ?? []) as SectionNode[]
1088
+ const section = sections.find((entry) => entry.key === sectionKey)
1089
+ if (!section) {
1090
+ throw new SchemaHelperError(
1091
+ `Section "${sectionKey}" not found.`,
1092
+ 'unknown_section',
1093
+ [sectionKey],
1094
+ )
1095
+ }
1096
+ if (predicate === null || predicate === undefined) {
1097
+ delete (section as Record<string, unknown>)['x-om-visibility-if']
1098
+ } else {
1099
+ ;(section as Record<string, unknown>)['x-om-visibility-if'] = predicate
1100
+ }
1101
+ validateSchemaExtensions(next)
1102
+ return next
1103
+ }
1104
+
1105
+ /**
1106
+ * Sets (or clears) a field's `x-om-pattern`. Passing `null` or an empty
1107
+ * string clears the keyword to keep the persisted shape minimal (R-9
1108
+ * mitigation — verbatim round-trip preserves schema hash).
1109
+ */
1110
+ export function setFieldPattern(input: {
1111
+ schema: FormSchema
1112
+ fieldKey: string
1113
+ pattern: string | null
1114
+ }): FormSchema {
1115
+ const { schema, fieldKey, pattern } = input
1116
+ const next = deepClone(schema)
1117
+ const node = next.properties[fieldKey]
1118
+ if (!node) {
1119
+ throw new SchemaHelperError(
1120
+ `Field "${fieldKey}" not found.`,
1121
+ 'unknown_field',
1122
+ [fieldKey],
1123
+ )
1124
+ }
1125
+ if (pattern === null || pattern.length === 0) {
1126
+ delete node[OM_FIELD_KEYWORDS.pattern]
1127
+ } else {
1128
+ node[OM_FIELD_KEYWORDS.pattern] = pattern
1129
+ }
1130
+ validateSchemaExtensions(next)
1131
+ return next
1132
+ }
1133
+
1134
+ /**
1135
+ * Sets (or clears) a field's `x-om-min-length` / `x-om-max-length`. Pass
1136
+ * `null` for either bound to clear it. Both bounds may be set in a single
1137
+ * call — the validator enforces `min <= max` at save time.
1138
+ */
1139
+ export function setFieldLengthRange(input: {
1140
+ schema: FormSchema
1141
+ fieldKey: string
1142
+ min?: number | null
1143
+ max?: number | null
1144
+ }): FormSchema {
1145
+ const { schema, fieldKey, min, max } = input
1146
+ const next = deepClone(schema)
1147
+ const node = next.properties[fieldKey]
1148
+ if (!node) {
1149
+ throw new SchemaHelperError(
1150
+ `Field "${fieldKey}" not found.`,
1151
+ 'unknown_field',
1152
+ [fieldKey],
1153
+ )
1154
+ }
1155
+ if (min !== undefined) {
1156
+ if (min === null) delete node[OM_FIELD_KEYWORDS.minLength]
1157
+ else node[OM_FIELD_KEYWORDS.minLength] = min
1158
+ }
1159
+ if (max !== undefined) {
1160
+ if (max === null) delete node[OM_FIELD_KEYWORDS.maxLength]
1161
+ else node[OM_FIELD_KEYWORDS.maxLength] = max
1162
+ }
1163
+ validateSchemaExtensions(next)
1164
+ return next
1165
+ }
1166
+
1167
+ /**
1168
+ * Sets (or clears) a field's `x-om-min` / `x-om-max` (numeric range). Pass
1169
+ * `null` for either bound to clear it.
1170
+ */
1171
+ export function setFieldNumberRange(input: {
1172
+ schema: FormSchema
1173
+ fieldKey: string
1174
+ min?: number | null
1175
+ max?: number | null
1176
+ }): FormSchema {
1177
+ const { schema, fieldKey, min, max } = input
1178
+ const next = deepClone(schema)
1179
+ const node = next.properties[fieldKey]
1180
+ if (!node) {
1181
+ throw new SchemaHelperError(
1182
+ `Field "${fieldKey}" not found.`,
1183
+ 'unknown_field',
1184
+ [fieldKey],
1185
+ )
1186
+ }
1187
+ if (min !== undefined) {
1188
+ if (min === null) delete node[OM_FIELD_KEYWORDS.min]
1189
+ else node[OM_FIELD_KEYWORDS.min] = min
1190
+ }
1191
+ if (max !== undefined) {
1192
+ if (max === null) delete node[OM_FIELD_KEYWORDS.max]
1193
+ else node[OM_FIELD_KEYWORDS.max] = max
1194
+ }
1195
+ validateSchemaExtensions(next)
1196
+ return next
1197
+ }
1198
+
1199
+ /**
1200
+ * Patches one entry of a field's `x-om-validation-messages` map. Empty
1201
+ * `message` removes the leaf; the helper removes empty inner / outer maps to
1202
+ * keep the persisted shape minimal (R-9 mitigation — verbatim round-trip
1203
+ * preserves schema hash).
1204
+ */
1205
+ export function setFieldValidationMessages(input: {
1206
+ schema: FormSchema
1207
+ fieldKey: string
1208
+ locale: string
1209
+ rule: string
1210
+ message: string | null
1211
+ }): FormSchema {
1212
+ const { schema, fieldKey, locale, rule, message } = input
1213
+ if (!locale) {
1214
+ throw new SchemaHelperError('locale is required.', 'invalid_input', ['locale'])
1215
+ }
1216
+ if (!rule) {
1217
+ throw new SchemaHelperError('rule is required.', 'invalid_input', ['rule'])
1218
+ }
1219
+ const next = deepClone(schema)
1220
+ const node = next.properties[fieldKey]
1221
+ if (!node) {
1222
+ throw new SchemaHelperError(
1223
+ `Field "${fieldKey}" not found.`,
1224
+ 'unknown_field',
1225
+ [fieldKey],
1226
+ )
1227
+ }
1228
+ const existing = node[OM_FIELD_KEYWORDS.validationMessages]
1229
+ const current: Record<string, Record<string, string>> =
1230
+ existing && typeof existing === 'object' && !Array.isArray(existing)
1231
+ ? { ...(existing as Record<string, Record<string, string>>) }
1232
+ : {}
1233
+ const inner: Record<string, string> = current[locale] ? { ...current[locale] } : {}
1234
+ const trimmed = typeof message === 'string' ? message : ''
1235
+ if (!trimmed) {
1236
+ delete inner[rule]
1237
+ } else {
1238
+ inner[rule] = trimmed
1239
+ }
1240
+ if (Object.keys(inner).length === 0) {
1241
+ delete current[locale]
1242
+ } else {
1243
+ current[locale] = inner
1244
+ }
1245
+ if (Object.keys(current).length === 0) {
1246
+ delete node[OM_FIELD_KEYWORDS.validationMessages]
1247
+ } else {
1248
+ node[OM_FIELD_KEYWORDS.validationMessages] = current
1249
+ }
1250
+ validateSchemaExtensions(next)
1251
+ return next
1252
+ }
1253
+
1254
+ /**
1255
+ * Sets (or clears) a field's `x-om-opinion-icon`. Defaults (`'dot'`) and
1256
+ * `null` clear the keyword so a verbatim round-trip preserves the schema
1257
+ * hash (R-9 mitigation — minimal persisted bytes). Cross-keyword validation
1258
+ * rejects this on non-`opinion_scale` fields.
1259
+ */
1260
+ export function setFieldOpinionIcon(input: {
1261
+ schema: FormSchema
1262
+ fieldKey: string
1263
+ icon: 'star' | 'dot' | 'thumb' | null
1264
+ }): FormSchema {
1265
+ const { schema, fieldKey, icon } = input
1266
+ const next = deepClone(schema)
1267
+ const node = next.properties[fieldKey]
1268
+ if (!node) {
1269
+ throw new SchemaHelperError(
1270
+ `Field "${fieldKey}" not found.`,
1271
+ 'unknown_field',
1272
+ [fieldKey],
1273
+ )
1274
+ }
1275
+ if (icon === null || icon === 'dot') {
1276
+ delete node[OM_FIELD_KEYWORDS.opinionIcon]
1277
+ } else {
1278
+ node[OM_FIELD_KEYWORDS.opinionIcon] = icon
1279
+ }
1280
+ validateSchemaExtensions(next)
1281
+ return next
1282
+ }
1283
+
1284
+ /**
1285
+ * Patches one locale entry of a field's `x-om-nps-anchors`. Empty `label`
1286
+ * removes the locale entry; empty inner map removes the anchor; empty outer
1287
+ * object removes `x-om-nps-anchors` entirely (R-9 minimalism — verbatim
1288
+ * round-trip preserves schema hash). Cross-keyword validation rejects this on
1289
+ * non-`nps` fields.
1290
+ */
1291
+ export function setFieldNpsAnchors(input: {
1292
+ schema: FormSchema
1293
+ fieldKey: string
1294
+ locale: string
1295
+ anchor: 'low' | 'high'
1296
+ label: string | null
1297
+ }): FormSchema {
1298
+ const { schema, fieldKey, locale, anchor, label } = input
1299
+ if (!locale) {
1300
+ throw new SchemaHelperError('locale is required.', 'invalid_input', ['locale'])
1301
+ }
1302
+ const next = deepClone(schema)
1303
+ const node = next.properties[fieldKey]
1304
+ if (!node) {
1305
+ throw new SchemaHelperError(
1306
+ `Field "${fieldKey}" not found.`,
1307
+ 'unknown_field',
1308
+ [fieldKey],
1309
+ )
1310
+ }
1311
+ const existing = node[OM_FIELD_KEYWORDS.npsAnchors]
1312
+ const current: { low?: Record<string, string>; high?: Record<string, string> } =
1313
+ existing && typeof existing === 'object' && !Array.isArray(existing)
1314
+ ? {
1315
+ low:
1316
+ (existing as Record<string, unknown>).low
1317
+ && typeof (existing as Record<string, unknown>).low === 'object'
1318
+ ? { ...((existing as Record<string, Record<string, string>>).low) }
1319
+ : undefined,
1320
+ high:
1321
+ (existing as Record<string, unknown>).high
1322
+ && typeof (existing as Record<string, unknown>).high === 'object'
1323
+ ? { ...((existing as Record<string, Record<string, string>>).high) }
1324
+ : undefined,
1325
+ }
1326
+ : {}
1327
+ const target: Record<string, string> = current[anchor] ? { ...(current[anchor] as Record<string, string>) } : {}
1328
+ const trimmed = typeof label === 'string' ? label : ''
1329
+ if (!trimmed) {
1330
+ delete target[locale]
1331
+ } else {
1332
+ target[locale] = trimmed
1333
+ }
1334
+ if (Object.keys(target).length === 0) {
1335
+ delete current[anchor]
1336
+ } else {
1337
+ current[anchor] = target
1338
+ }
1339
+ const hasLow = current.low && Object.keys(current.low).length > 0
1340
+ const hasHigh = current.high && Object.keys(current.high).length > 0
1341
+ if (!hasLow && !hasHigh) {
1342
+ delete node[OM_FIELD_KEYWORDS.npsAnchors]
1343
+ } else {
1344
+ node[OM_FIELD_KEYWORDS.npsAnchors] = {
1345
+ low: current.low ?? {},
1346
+ high: current.high ?? {},
1347
+ }
1348
+ }
1349
+ validateSchemaExtensions(next)
1350
+ return next
1351
+ }
1352
+
1353
+ /**
1354
+ * Toggles a field's `x-om-ranking-exhaustive` flag. `false` is persisted as
1355
+ * the absence of the key (R-9 minimalism — verbatim round-trip preserves
1356
+ * schema hash). Cross-keyword validation rejects this on non-`ranking`
1357
+ * fields.
1358
+ */
1359
+ export function setFieldRankingExhaustive(input: {
1360
+ schema: FormSchema
1361
+ fieldKey: string
1362
+ value: boolean
1363
+ }): FormSchema {
1364
+ const { schema, fieldKey, value } = input
1365
+ const next = deepClone(schema)
1366
+ const node = next.properties[fieldKey]
1367
+ if (!node) {
1368
+ throw new SchemaHelperError(
1369
+ `Field "${fieldKey}" not found.`,
1370
+ 'unknown_field',
1371
+ [fieldKey],
1372
+ )
1373
+ }
1374
+ if (value === false) {
1375
+ delete node[OM_FIELD_KEYWORDS.rankingExhaustive]
1376
+ } else {
1377
+ node[OM_FIELD_KEYWORDS.rankingExhaustive] = true
1378
+ }
1379
+ validateSchemaExtensions(next)
1380
+ return next
1381
+ }
1382
+
1383
+ export type OmMatrixRowInput = {
1384
+ key: string
1385
+ label: { [locale: string]: string }
1386
+ multiple?: boolean
1387
+ required?: boolean
1388
+ }
1389
+
1390
+ export type OmMatrixColumnInput = {
1391
+ value: string
1392
+ label: { [locale: string]: string }
1393
+ }
1394
+
1395
+ const MATRIX_ROW_KEY_PATTERN_HELPER = /^row_(\d+)$/
1396
+
1397
+ function nextMatrixRowKey(rows: ReadonlyArray<{ key?: unknown }> | undefined): string {
1398
+ let maxSuffix = 0
1399
+ for (const row of rows ?? []) {
1400
+ const key = (row as Record<string, unknown>).key
1401
+ if (typeof key !== 'string') continue
1402
+ const match = MATRIX_ROW_KEY_PATTERN_HELPER.exec(key)
1403
+ if (!match) continue
1404
+ const value = Number.parseInt(match[1], 10)
1405
+ if (Number.isFinite(value) && value > maxSuffix) maxSuffix = value
1406
+ }
1407
+ return `row_${maxSuffix + 1}`
1408
+ }
1409
+
1410
+ function readMatrixRowsArray(node: FieldNode): OmMatrixRowInput[] {
1411
+ const raw = node[OM_FIELD_KEYWORDS.matrixRows]
1412
+ if (!Array.isArray(raw)) return []
1413
+ return raw.map((entry) => {
1414
+ const candidate = entry as Record<string, unknown>
1415
+ const row: OmMatrixRowInput = {
1416
+ key: typeof candidate.key === 'string' ? candidate.key : '',
1417
+ label:
1418
+ candidate.label && typeof candidate.label === 'object' && !Array.isArray(candidate.label)
1419
+ ? { ...(candidate.label as Record<string, string>) }
1420
+ : {},
1421
+ }
1422
+ if (typeof candidate.multiple === 'boolean') row.multiple = candidate.multiple
1423
+ if (typeof candidate.required === 'boolean') row.required = candidate.required
1424
+ return row
1425
+ })
1426
+ }
1427
+
1428
+ function readMatrixColumnsArray(node: FieldNode): OmMatrixColumnInput[] {
1429
+ const raw = node[OM_FIELD_KEYWORDS.matrixColumns]
1430
+ if (!Array.isArray(raw)) return []
1431
+ return raw.map((entry) => {
1432
+ const candidate = entry as Record<string, unknown>
1433
+ return {
1434
+ value: typeof candidate.value === 'string' ? candidate.value : '',
1435
+ label:
1436
+ candidate.label && typeof candidate.label === 'object' && !Array.isArray(candidate.label)
1437
+ ? { ...(candidate.label as Record<string, string>) }
1438
+ : {},
1439
+ }
1440
+ })
1441
+ }
1442
+
1443
+ function canonicalMatrixRow(row: OmMatrixRowInput): OmMatrixRowInput {
1444
+ const result: OmMatrixRowInput = {
1445
+ key: row.key,
1446
+ label: row.label,
1447
+ }
1448
+ if (row.multiple === true) result.multiple = true
1449
+ if (row.required === true) result.required = true
1450
+ return result
1451
+ }
1452
+
1453
+ function canonicalMatrixColumn(column: OmMatrixColumnInput): OmMatrixColumnInput {
1454
+ return {
1455
+ value: column.value,
1456
+ label: column.label,
1457
+ }
1458
+ }
1459
+
1460
+ /**
1461
+ * Replaces the `x-om-matrix-rows` array. Empty input clears the keyword so a
1462
+ * verbatim round-trip preserves the schema hash (R-9 mitigation — minimal
1463
+ * persisted bytes). `multiple` / `required` defaults (`false`) are stripped
1464
+ * from each persisted row entry.
1465
+ */
1466
+ export function setMatrixRows(input: {
1467
+ schema: FormSchema
1468
+ fieldKey: string
1469
+ rows: OmMatrixRowInput[]
1470
+ }): FormSchema {
1471
+ const { schema, fieldKey, rows } = input
1472
+ const next = deepClone(schema)
1473
+ const node = next.properties[fieldKey]
1474
+ if (!node) {
1475
+ throw new SchemaHelperError(
1476
+ `Field "${fieldKey}" not found.`,
1477
+ 'unknown_field',
1478
+ [fieldKey],
1479
+ )
1480
+ }
1481
+ if (!rows || rows.length === 0) {
1482
+ delete node[OM_FIELD_KEYWORDS.matrixRows]
1483
+ } else {
1484
+ node[OM_FIELD_KEYWORDS.matrixRows] = rows.map(canonicalMatrixRow)
1485
+ }
1486
+ validateSchemaExtensions(next)
1487
+ return next
1488
+ }
1489
+
1490
+ /**
1491
+ * Replaces the `x-om-matrix-columns` array. Empty input clears the keyword.
1492
+ */
1493
+ export function setMatrixColumns(input: {
1494
+ schema: FormSchema
1495
+ fieldKey: string
1496
+ columns: OmMatrixColumnInput[]
1497
+ }): FormSchema {
1498
+ const { schema, fieldKey, columns } = input
1499
+ const next = deepClone(schema)
1500
+ const node = next.properties[fieldKey]
1501
+ if (!node) {
1502
+ throw new SchemaHelperError(
1503
+ `Field "${fieldKey}" not found.`,
1504
+ 'unknown_field',
1505
+ [fieldKey],
1506
+ )
1507
+ }
1508
+ if (!columns || columns.length === 0) {
1509
+ delete node[OM_FIELD_KEYWORDS.matrixColumns]
1510
+ } else {
1511
+ node[OM_FIELD_KEYWORDS.matrixColumns] = columns.map(canonicalMatrixColumn)
1512
+ }
1513
+ validateSchemaExtensions(next)
1514
+ return next
1515
+ }
1516
+
1517
+ /**
1518
+ * Appends a row to `x-om-matrix-rows`. Generates a fresh `row_<n>` key when
1519
+ * the caller omits `row.key`.
1520
+ */
1521
+ export function addMatrixRow(input: {
1522
+ schema: FormSchema
1523
+ fieldKey: string
1524
+ row?: Partial<OmMatrixRowInput>
1525
+ }): FormSchema {
1526
+ const { schema, fieldKey, row } = input
1527
+ const node = schema.properties[fieldKey]
1528
+ if (!node) {
1529
+ throw new SchemaHelperError(
1530
+ `Field "${fieldKey}" not found.`,
1531
+ 'unknown_field',
1532
+ [fieldKey],
1533
+ )
1534
+ }
1535
+ const existing = readMatrixRowsArray(node)
1536
+ const requestedKey = row?.key && row.key.length > 0 ? row.key : nextMatrixRowKey(existing)
1537
+ const newRow: OmMatrixRowInput = {
1538
+ key: requestedKey,
1539
+ label: row?.label ?? { en: 'New row' },
1540
+ }
1541
+ if (row?.multiple === true) newRow.multiple = true
1542
+ if (row?.required === true) newRow.required = true
1543
+ return setMatrixRows({ schema, fieldKey, rows: [...existing, newRow] })
1544
+ }
1545
+
1546
+ /**
1547
+ * Removes the row with the given `rowKey` from `x-om-matrix-rows`.
1548
+ */
1549
+ export function removeMatrixRow(input: {
1550
+ schema: FormSchema
1551
+ fieldKey: string
1552
+ rowKey: string
1553
+ }): FormSchema {
1554
+ const { schema, fieldKey, rowKey } = input
1555
+ const node = schema.properties[fieldKey]
1556
+ if (!node) {
1557
+ throw new SchemaHelperError(
1558
+ `Field "${fieldKey}" not found.`,
1559
+ 'unknown_field',
1560
+ [fieldKey],
1561
+ )
1562
+ }
1563
+ const existing = readMatrixRowsArray(node)
1564
+ return setMatrixRows({
1565
+ schema,
1566
+ fieldKey,
1567
+ rows: existing.filter((entry) => entry.key !== rowKey),
1568
+ })
1569
+ }
1570
+
1571
+ /**
1572
+ * Reorders a row within `x-om-matrix-rows`. Indices outside the array are
1573
+ * clamped to the closest valid slot.
1574
+ */
1575
+ export function moveMatrixRow(input: {
1576
+ schema: FormSchema
1577
+ fieldKey: string
1578
+ fromIndex: number
1579
+ toIndex: number
1580
+ }): FormSchema {
1581
+ const { schema, fieldKey, fromIndex, toIndex } = input
1582
+ const node = schema.properties[fieldKey]
1583
+ if (!node) {
1584
+ throw new SchemaHelperError(
1585
+ `Field "${fieldKey}" not found.`,
1586
+ 'unknown_field',
1587
+ [fieldKey],
1588
+ )
1589
+ }
1590
+ const rows = readMatrixRowsArray(node)
1591
+ if (rows.length === 0) return schema
1592
+ const sourceIndex = Math.max(0, Math.min(fromIndex, rows.length - 1))
1593
+ const destIndex = Math.max(0, Math.min(toIndex, rows.length - 1))
1594
+ if (sourceIndex === destIndex) return schema
1595
+ const [moved] = rows.splice(sourceIndex, 1)
1596
+ rows.splice(destIndex, 0, moved)
1597
+ return setMatrixRows({ schema, fieldKey, rows })
1598
+ }
1599
+
1600
+ /**
1601
+ * Appends a column to `x-om-matrix-columns`. Generates a fresh `col_<n>` value
1602
+ * when the caller omits `column.value`.
1603
+ */
1604
+ export function addMatrixColumn(input: {
1605
+ schema: FormSchema
1606
+ fieldKey: string
1607
+ column?: Partial<OmMatrixColumnInput>
1608
+ }): FormSchema {
1609
+ const { schema, fieldKey, column } = input
1610
+ const node = schema.properties[fieldKey]
1611
+ if (!node) {
1612
+ throw new SchemaHelperError(
1613
+ `Field "${fieldKey}" not found.`,
1614
+ 'unknown_field',
1615
+ [fieldKey],
1616
+ )
1617
+ }
1618
+ const existing = readMatrixColumnsArray(node)
1619
+ let value = column?.value && column.value.length > 0 ? column.value : ''
1620
+ if (!value) {
1621
+ const pattern = /^col_(\d+)$/
1622
+ let maxSuffix = 0
1623
+ for (const entry of existing) {
1624
+ const match = pattern.exec(entry.value)
1625
+ if (!match) continue
1626
+ const parsed = Number.parseInt(match[1], 10)
1627
+ if (Number.isFinite(parsed) && parsed > maxSuffix) maxSuffix = parsed
1628
+ }
1629
+ value = `col_${maxSuffix + 1}`
1630
+ }
1631
+ const newColumn: OmMatrixColumnInput = {
1632
+ value,
1633
+ label: column?.label ?? { en: 'New column' },
1634
+ }
1635
+ return setMatrixColumns({ schema, fieldKey, columns: [...existing, newColumn] })
1636
+ }
1637
+
1638
+ /**
1639
+ * Removes the column with the given `value` from `x-om-matrix-columns`.
1640
+ */
1641
+ export function removeMatrixColumn(input: {
1642
+ schema: FormSchema
1643
+ fieldKey: string
1644
+ value: string
1645
+ }): FormSchema {
1646
+ const { schema, fieldKey, value } = input
1647
+ const node = schema.properties[fieldKey]
1648
+ if (!node) {
1649
+ throw new SchemaHelperError(
1650
+ `Field "${fieldKey}" not found.`,
1651
+ 'unknown_field',
1652
+ [fieldKey],
1653
+ )
1654
+ }
1655
+ const existing = readMatrixColumnsArray(node)
1656
+ return setMatrixColumns({
1657
+ schema,
1658
+ fieldKey,
1659
+ columns: existing.filter((entry) => entry.value !== value),
1660
+ })
1661
+ }
1662
+
1663
+ /**
1664
+ * Reorders a column within `x-om-matrix-columns`.
1665
+ */
1666
+ export function moveMatrixColumn(input: {
1667
+ schema: FormSchema
1668
+ fieldKey: string
1669
+ fromIndex: number
1670
+ toIndex: number
1671
+ }): FormSchema {
1672
+ const { schema, fieldKey, fromIndex, toIndex } = input
1673
+ const node = schema.properties[fieldKey]
1674
+ if (!node) {
1675
+ throw new SchemaHelperError(
1676
+ `Field "${fieldKey}" not found.`,
1677
+ 'unknown_field',
1678
+ [fieldKey],
1679
+ )
1680
+ }
1681
+ const columns = readMatrixColumnsArray(node)
1682
+ if (columns.length === 0) return schema
1683
+ const sourceIndex = Math.max(0, Math.min(fromIndex, columns.length - 1))
1684
+ const destIndex = Math.max(0, Math.min(toIndex, columns.length - 1))
1685
+ if (sourceIndex === destIndex) return schema
1686
+ const [moved] = columns.splice(sourceIndex, 1)
1687
+ columns.splice(destIndex, 0, moved)
1688
+ return setMatrixColumns({ schema, fieldKey, columns })
1689
+ }
1690
+
1691
+ // ============================================================================
1692
+ // W6 — repeatable group (FA-8) studio helpers.
1693
+ //
1694
+ // A group field is a JSON-Schema `type: 'array'` whose `items` is a
1695
+ // `type: 'object'` carrying a `properties` map of sub-fields plus `required`
1696
+ // and `additionalProperties: false`. Sub-field keys live under
1697
+ // `items.properties` — a namespace disjoint from top-level `properties`
1698
+ // (root AGENTS MUST 14). Native `items` constraints let AJV enforce the
1699
+ // sub-field shape server-side; `x-om-min-items` / `x-om-max-items` carry the
1700
+ // entry-count bounds for the renderer + the registry validator.
1701
+ // ============================================================================
1702
+
1703
+ export type GroupSubFieldInput = {
1704
+ key: string
1705
+ type: string
1706
+ label: { [locale: string]: string }
1707
+ required?: boolean
1708
+ }
1709
+
1710
+ const GROUP_SUB_FIELD_KEY_PATTERN = /^field_(\d+)$/
1711
+
1712
+ type GroupItemsNode = {
1713
+ type: 'object'
1714
+ additionalProperties: false
1715
+ properties: Record<string, FieldNode>
1716
+ required: string[]
1717
+ }
1718
+
1719
+ /** Builds a JSON-Schema-object `items` node from a sub-field map + required list. */
1720
+ function buildGroupItemsNode(properties: Record<string, FieldNode>, required: string[]): GroupItemsNode {
1721
+ return { type: 'object', additionalProperties: false, properties, required }
1722
+ }
1723
+
1724
+ /** Builds a fresh sub-field node for the given `x-om-type`, seeding type-specific keywords. */
1725
+ export function buildGroupSubFieldNode(typeKey: string, label: { [locale: string]: string }): FieldNode {
1726
+ const jsonType = FIELD_TYPE_TO_JSON_TYPE[typeKey] ?? 'string'
1727
+ const subNode: FieldNode = {
1728
+ type: jsonType,
1729
+ 'x-om-type': typeKey,
1730
+ 'x-om-label': label,
1731
+ }
1732
+ const subInitializer = FIELD_TYPE_NODE_INITIALIZER[typeKey]
1733
+ if (subInitializer) subInitializer(subNode)
1734
+ return subNode
1735
+ }
1736
+
1737
+ /**
1738
+ * Node-level reducers for a group field's `items` — used by the studio
1739
+ * inspector, which patches the selected node directly via `onUpdate`. They
1740
+ * mirror the schema-level `addGroupSubField` / `removeGroupSubField` /
1741
+ * `updateGroupSubField` helpers but operate on a single node and never run
1742
+ * `validateSchemaExtensions` (the autosave guard validates the full schema).
1743
+ */
1744
+ export function groupNodeAddSubField(node: FieldNode, label: { [locale: string]: string }): FieldNode {
1745
+ const { properties, required } = readGroupItemsNode(node)
1746
+ const key = nextGroupSubFieldKey(properties)
1747
+ const subNode = buildGroupSubFieldNode('text', label)
1748
+ const updated: FieldNode = { ...node }
1749
+ updated.items = buildGroupItemsNode({ ...properties, [key]: subNode }, required)
1750
+ return updated
1751
+ }
1752
+
1753
+ export function groupNodeRemoveSubField(node: FieldNode, subFieldKey: string): FieldNode {
1754
+ const { properties, required } = readGroupItemsNode(node)
1755
+ const nextProperties: Record<string, FieldNode> = {}
1756
+ for (const [key, subNode] of Object.entries(properties)) {
1757
+ if (key === subFieldKey) continue
1758
+ nextProperties[key] = subNode
1759
+ }
1760
+ const updated: FieldNode = { ...node }
1761
+ updated.items = buildGroupItemsNode(nextProperties, required.filter((entry) => entry !== subFieldKey))
1762
+ return updated
1763
+ }
1764
+
1765
+ export function groupNodeUpdateSubField(
1766
+ node: FieldNode,
1767
+ subFieldKey: string,
1768
+ patch: { label?: { [locale: string]: string }; type?: string; required?: boolean },
1769
+ ): FieldNode {
1770
+ const { properties, required } = readGroupItemsNode(node)
1771
+ const existing = properties[subFieldKey]
1772
+ if (!existing) return node
1773
+ let nextSubNode: FieldNode = { ...existing }
1774
+ if (patch.label !== undefined) {
1775
+ nextSubNode['x-om-label'] = patch.label
1776
+ }
1777
+ if (patch.type !== undefined && patch.type.length > 0 && patch.type !== existing['x-om-type']) {
1778
+ nextSubNode = buildGroupSubFieldNode(patch.type, nextSubNode['x-om-label'] ?? { en: 'New sub-field' })
1779
+ }
1780
+ let nextRequired = required
1781
+ if (patch.required !== undefined) {
1782
+ nextRequired = patch.required
1783
+ ? Array.from(new Set([...required, subFieldKey]))
1784
+ : required.filter((entry) => entry !== subFieldKey)
1785
+ }
1786
+ const updated: FieldNode = { ...node }
1787
+ updated.items = buildGroupItemsNode({ ...properties, [subFieldKey]: nextSubNode }, nextRequired)
1788
+ return updated
1789
+ }
1790
+
1791
+ function readGroupItemsNode(node: FieldNode): {
1792
+ properties: Record<string, FieldNode>
1793
+ required: string[]
1794
+ } {
1795
+ const items = node.items
1796
+ const itemsNode = items && typeof items === 'object' && !Array.isArray(items)
1797
+ ? (items as Record<string, unknown>)
1798
+ : {}
1799
+ const properties = itemsNode.properties && typeof itemsNode.properties === 'object' && !Array.isArray(itemsNode.properties)
1800
+ ? (itemsNode.properties as Record<string, FieldNode>)
1801
+ : {}
1802
+ const required = Array.isArray(itemsNode.required)
1803
+ ? (itemsNode.required as unknown[]).filter((entry): entry is string => typeof entry === 'string')
1804
+ : []
1805
+ return { properties, required }
1806
+ }
1807
+
1808
+ function nextGroupSubFieldKey(properties: Record<string, unknown>): string {
1809
+ let maxSuffix = 0
1810
+ for (const key of Object.keys(properties)) {
1811
+ const match = GROUP_SUB_FIELD_KEY_PATTERN.exec(key)
1812
+ if (!match) continue
1813
+ const value = Number.parseInt(match[1], 10)
1814
+ if (Number.isFinite(value) && value > maxSuffix) maxSuffix = value
1815
+ }
1816
+ return `field_${maxSuffix + 1}`
1817
+ }
1818
+
1819
+ /**
1820
+ * Sets (or clears) a group field's `x-om-min-items` / `x-om-max-items`. Pass
1821
+ * `null` for either bound to clear it. The cross-keyword validator enforces
1822
+ * `min <= max` and the soft cap at save time.
1823
+ */
1824
+ export function setGroupItemRange(input: {
1825
+ schema: FormSchema
1826
+ fieldKey: string
1827
+ min?: number | null
1828
+ max?: number | null
1829
+ }): FormSchema {
1830
+ const { schema, fieldKey, min, max } = input
1831
+ const next = deepClone(schema)
1832
+ const node = next.properties[fieldKey]
1833
+ if (!node) {
1834
+ throw new SchemaHelperError(`Field "${fieldKey}" not found.`, 'unknown_field', [fieldKey])
1835
+ }
1836
+ if (min !== undefined) {
1837
+ if (min === null) delete node[OM_FIELD_KEYWORDS.minItems]
1838
+ else node[OM_FIELD_KEYWORDS.minItems] = min
1839
+ }
1840
+ if (max !== undefined) {
1841
+ if (max === null) delete node[OM_FIELD_KEYWORDS.maxItems]
1842
+ else node[OM_FIELD_KEYWORDS.maxItems] = max
1843
+ }
1844
+ validateSchemaExtensions(next)
1845
+ return next
1846
+ }
1847
+
1848
+ /**
1849
+ * Appends a sub-field to a group's `items.properties`. Generates a fresh
1850
+ * `field_<n>` key (scoped to the group's sub-field namespace) when the caller
1851
+ * omits `subField.key`. The sub-field's JSON Schema `type` is derived from its
1852
+ * `x-om-type` via the same `FIELD_TYPE_TO_JSON_TYPE` map used by top-level
1853
+ * fields.
1854
+ */
1855
+ export function addGroupSubField(input: {
1856
+ schema: FormSchema
1857
+ fieldKey: string
1858
+ subField?: Partial<GroupSubFieldInput>
1859
+ }): FormSchema {
1860
+ const { schema, fieldKey, subField } = input
1861
+ const next = deepClone(schema)
1862
+ const node = next.properties[fieldKey]
1863
+ if (!node) {
1864
+ throw new SchemaHelperError(`Field "${fieldKey}" not found.`, 'unknown_field', [fieldKey])
1865
+ }
1866
+ const { properties, required } = readGroupItemsNode(node)
1867
+ const typeKey = subField?.type && subField.type.length > 0 ? subField.type : 'text'
1868
+ const jsonType = FIELD_TYPE_TO_JSON_TYPE[typeKey] ?? 'string'
1869
+ const key = subField?.key && subField.key.length > 0 ? subField.key : nextGroupSubFieldKey(properties)
1870
+ const subNode: FieldNode = {
1871
+ type: jsonType,
1872
+ 'x-om-type': typeKey,
1873
+ 'x-om-label': subField?.label ?? { en: 'New sub-field' },
1874
+ }
1875
+ const subInitializer = FIELD_TYPE_NODE_INITIALIZER[typeKey]
1876
+ if (subInitializer) subInitializer(subNode)
1877
+ const nextProperties = { ...properties, [key]: subNode }
1878
+ const nextRequired = subField?.required === true ? [...required, key] : required
1879
+ node.items = {
1880
+ type: 'object',
1881
+ additionalProperties: false,
1882
+ properties: nextProperties,
1883
+ required: nextRequired,
1884
+ }
1885
+ validateSchemaExtensions(next)
1886
+ return next
1887
+ }
1888
+
1889
+ /**
1890
+ * Removes a sub-field from a group's `items.properties` and drops it from the
1891
+ * `items.required` list.
1892
+ */
1893
+ export function removeGroupSubField(input: {
1894
+ schema: FormSchema
1895
+ fieldKey: string
1896
+ subFieldKey: string
1897
+ }): FormSchema {
1898
+ const { schema, fieldKey, subFieldKey } = input
1899
+ const next = deepClone(schema)
1900
+ const node = next.properties[fieldKey]
1901
+ if (!node) {
1902
+ throw new SchemaHelperError(`Field "${fieldKey}" not found.`, 'unknown_field', [fieldKey])
1903
+ }
1904
+ const { properties, required } = readGroupItemsNode(node)
1905
+ if (!properties[subFieldKey]) {
1906
+ throw new SchemaHelperError(
1907
+ `Sub-field "${subFieldKey}" not found in group "${fieldKey}".`,
1908
+ 'unknown_sub_field',
1909
+ [fieldKey, subFieldKey],
1910
+ )
1911
+ }
1912
+ const nextProperties: Record<string, FieldNode> = {}
1913
+ for (const [key, subNode] of Object.entries(properties)) {
1914
+ if (key === subFieldKey) continue
1915
+ nextProperties[key] = subNode
1916
+ }
1917
+ node.items = {
1918
+ type: 'object',
1919
+ additionalProperties: false,
1920
+ properties: nextProperties,
1921
+ required: required.filter((entry) => entry !== subFieldKey),
1922
+ }
1923
+ validateSchemaExtensions(next)
1924
+ return next
1925
+ }
1926
+
1927
+ /**
1928
+ * Updates a sub-field's label, type, and/or required flag. Switching the
1929
+ * `x-om-type` re-derives the JSON Schema `type` and re-runs the type's node
1930
+ * initializer so type-specific keywords (e.g. `x-om-options`) are seeded.
1931
+ */
1932
+ export function updateGroupSubField(input: {
1933
+ schema: FormSchema
1934
+ fieldKey: string
1935
+ subFieldKey: string
1936
+ patch: { label?: { [locale: string]: string }; type?: string; required?: boolean }
1937
+ }): FormSchema {
1938
+ const { schema, fieldKey, subFieldKey, patch } = input
1939
+ const next = deepClone(schema)
1940
+ const node = next.properties[fieldKey]
1941
+ if (!node) {
1942
+ throw new SchemaHelperError(`Field "${fieldKey}" not found.`, 'unknown_field', [fieldKey])
1943
+ }
1944
+ const { properties, required } = readGroupItemsNode(node)
1945
+ const subNode = properties[subFieldKey]
1946
+ if (!subNode) {
1947
+ throw new SchemaHelperError(
1948
+ `Sub-field "${subFieldKey}" not found in group "${fieldKey}".`,
1949
+ 'unknown_sub_field',
1950
+ [fieldKey, subFieldKey],
1951
+ )
1952
+ }
1953
+ let nextSubNode: FieldNode = { ...subNode }
1954
+ if (patch.label !== undefined) {
1955
+ nextSubNode['x-om-label'] = patch.label
1956
+ }
1957
+ if (patch.type !== undefined && patch.type.length > 0 && patch.type !== subNode['x-om-type']) {
1958
+ const jsonType = FIELD_TYPE_TO_JSON_TYPE[patch.type] ?? 'string'
1959
+ nextSubNode = {
1960
+ type: jsonType,
1961
+ 'x-om-type': patch.type,
1962
+ 'x-om-label': nextSubNode['x-om-label'] ?? { en: 'New sub-field' },
1963
+ }
1964
+ const subInitializer = FIELD_TYPE_NODE_INITIALIZER[patch.type]
1965
+ if (subInitializer) subInitializer(nextSubNode)
1966
+ }
1967
+ const nextProperties = { ...properties, [subFieldKey]: nextSubNode }
1968
+ let nextRequired = required
1969
+ if (patch.required !== undefined) {
1970
+ nextRequired = patch.required
1971
+ ? Array.from(new Set([...required, subFieldKey]))
1972
+ : required.filter((entry) => entry !== subFieldKey)
1973
+ }
1974
+ node.items = {
1975
+ type: 'object',
1976
+ additionalProperties: false,
1977
+ properties: nextProperties,
1978
+ required: nextRequired,
1979
+ }
1980
+ validateSchemaExtensions(next)
1981
+ return next
1982
+ }
1983
+
1984
+ /**
1985
+ * Toggles a field's `x-om-hide-mobile` flag. `false` is persisted as the
1986
+ * absence of the key (Decision 33 — visibly collapses only on the mobile
1987
+ * viewport; tablet preserved).
1988
+ */
1989
+ export function setFieldHideMobile(input: {
1990
+ schema: FormSchema
1991
+ fieldKey: string
1992
+ value: boolean
1993
+ }): FormSchema {
1994
+ const { schema, fieldKey, value } = input
1995
+ const next = deepClone(schema)
1996
+ const node = next.properties[fieldKey]
1997
+ if (!node) {
1998
+ throw new SchemaHelperError(
1999
+ `Field "${fieldKey}" not found.`,
2000
+ 'unknown_field',
2001
+ [fieldKey],
2002
+ )
2003
+ }
2004
+ if (value === false) {
2005
+ delete node[OM_FIELD_KEYWORDS.hideMobile]
2006
+ } else {
2007
+ node[OM_FIELD_KEYWORDS.hideMobile] = true
2008
+ }
2009
+ validateSchemaExtensions(next)
2010
+ return next
2011
+ }
2012
+
2013
+ /**
2014
+ * Field-type swap families (Decision 31a). Cross-family swaps are not
2015
+ * supported — the studio surfaces a "delete and recreate" link instead.
2016
+ *
2017
+ * The map is exposed so UI components can compute the available targets
2018
+ * without re-implementing the family rule.
2019
+ */
2020
+ export const SWAP_FAMILIES: Record<string, ReadonlySet<string>> = {
2021
+ text: new Set(['text', 'textarea']),
2022
+ textarea: new Set(['text', 'textarea']),
2023
+ number: new Set(['number', 'integer']),
2024
+ integer: new Set(['number', 'integer']),
2025
+ boolean: new Set(['boolean', 'yes_no', 'yes_no_buttons']),
2026
+ yes_no: new Set(['boolean', 'yes_no', 'yes_no_buttons']),
2027
+ yes_no_buttons: new Set(['boolean', 'yes_no', 'yes_no_buttons']),
2028
+ select_one: new Set(['select_one', 'select_many']),
2029
+ select_many: new Set(['select_one', 'select_many']),
2030
+ }
2031
+
2032
+ const FIELD_TYPE_TO_DEFAULT_UI: Record<string, Record<string, unknown>> = {
2033
+ text: { widget: 'text' },
2034
+ textarea: { widget: 'textarea', rows: 4 },
2035
+ number: { widget: 'number' },
2036
+ integer: { widget: 'integer' },
2037
+ boolean: { widget: 'checkbox' },
2038
+ yes_no: { widget: 'yes_no' },
2039
+ yes_no_buttons: { widget: 'yes_no_buttons' },
2040
+ date: { widget: 'date' },
2041
+ datetime: { widget: 'datetime' },
2042
+ select_one: { widget: 'select' },
2043
+ select_many: { widget: 'multiselect' },
2044
+ scale: { widget: 'scale' },
2045
+ info_block: { widget: 'info' },
2046
+ // Tier-2 — Phase B.
2047
+ email: { widget: 'email' },
2048
+ phone: { widget: 'phone' },
2049
+ website: { widget: 'website' },
2050
+ // Tier-2 — Phase C.
2051
+ address: { widget: 'address' },
2052
+ // Tier-2 — Phase D.
2053
+ nps: { widget: 'nps' },
2054
+ opinion_scale: { widget: 'opinion_scale' },
2055
+ // Tier-2 — Phase E.
2056
+ ranking: { widget: 'ranking' },
2057
+ // Tier-2 — Phase F.
2058
+ matrix: { widget: 'matrix' },
2059
+ }
2060
+
2061
+ /**
2062
+ * Returns true when `from` and `to` belong to the same compatible family
2063
+ * defined in `SWAP_FAMILIES`. Identity swaps (`from === to`) return true.
2064
+ */
2065
+ export function isCompatibleFieldSwap(from: string, to: string): boolean {
2066
+ if (from === to) return true
2067
+ const family = SWAP_FAMILIES[from]
2068
+ if (!family) return false
2069
+ return family.has(to)
2070
+ }
2071
+
2072
+ /**
2073
+ * Swaps a field's `x-om-type` within a compatible family (Decision 31a).
2074
+ *
2075
+ * Behavior:
2076
+ * - Defensive: throws when the swap is cross-family — the UI is expected to
2077
+ * gate the call by `isCompatibleFieldSwap`.
2078
+ * - Preserves: `key`, `x-om-label`, `x-om-help`, `x-om-editable-by`,
2079
+ * `x-om-visible-to`, `x-om-sensitive`, `x-om-grid-span`, `x-om-align`,
2080
+ * `x-om-hide-mobile`, and `required` membership.
2081
+ * - Drops incompatible scalars: cross-target props that don't apply
2082
+ * (`x-om-options` when leaving the select family; `x-om-min` / `x-om-max`
2083
+ * when leaving the number family) and the previous `x-om-widget` override.
2084
+ * - Applies the registry's `defaultUiSchema` widget for the target type.
2085
+ */
2086
+ export function swapFieldType(input: {
2087
+ schema: FormSchema
2088
+ fieldKey: string
2089
+ targetType: string
2090
+ }): FormSchema {
2091
+ const { schema, fieldKey, targetType } = input
2092
+ const node = schema.properties[fieldKey]
2093
+ if (!node) {
2094
+ throw new SchemaHelperError(
2095
+ `Field "${fieldKey}" not found.`,
2096
+ 'unknown_field',
2097
+ [fieldKey],
2098
+ )
2099
+ }
2100
+ const fromType = String(node['x-om-type'] ?? '')
2101
+ if (!isCompatibleFieldSwap(fromType, targetType)) {
2102
+ throw new SchemaHelperError(
2103
+ `Cross-family swap "${fromType}" → "${targetType}" is not supported. Delete the field and recreate it.`,
2104
+ 'incompatible_swap',
2105
+ [fieldKey, OM_FIELD_KEYWORDS.type],
2106
+ )
2107
+ }
2108
+ const next = deepClone(schema)
2109
+ const target = next.properties[fieldKey]
2110
+ target['x-om-type'] = targetType
2111
+ target.type = FIELD_TYPE_TO_JSON_TYPE[targetType] ?? target.type ?? 'string'
2112
+ const targetUi = FIELD_TYPE_TO_DEFAULT_UI[targetType]
2113
+ if (targetUi && typeof targetUi.widget === 'string') {
2114
+ target[OM_FIELD_KEYWORDS.widget] = targetUi.widget
2115
+ } else {
2116
+ delete target[OM_FIELD_KEYWORDS.widget]
2117
+ }
2118
+ // Drop options when leaving the select family.
2119
+ const leavingSelectFamily =
2120
+ (fromType === 'select_one' || fromType === 'select_many')
2121
+ && targetType !== 'select_one'
2122
+ && targetType !== 'select_many'
2123
+ if (leavingSelectFamily) {
2124
+ delete target[OM_FIELD_KEYWORDS.options]
2125
+ }
2126
+ // Drop min/max when leaving the number/integer family.
2127
+ const leavingNumberFamily =
2128
+ (fromType === 'number' || fromType === 'integer')
2129
+ && targetType !== 'number'
2130
+ && targetType !== 'integer'
2131
+ if (leavingNumberFamily) {
2132
+ delete target[OM_FIELD_KEYWORDS.min]
2133
+ delete target[OM_FIELD_KEYWORDS.max]
2134
+ }
2135
+ validateSchemaExtensions(next)
2136
+ return next
2137
+ }
2138
+
2139
+ /**
2140
+ * Sets the form-level theme density (Decision 20a). Persisted only when
2141
+ * not at default; default (`'default'`) clears the key to keep the
2142
+ * persisted shape minimal (R-9 mitigation — verbatim round-trip).
2143
+ */
2144
+ export function setFormStyle(input: {
2145
+ schema: FormSchema
2146
+ style: 'default' | 'compact' | 'spacious'
2147
+ }): FormSchema {
2148
+ const { schema, style } = input
2149
+ const next = deepClone(schema)
2150
+ if (style === 'default') {
2151
+ delete (next as Record<string, unknown>)[OM_ROOT_KEYWORDS.formStyle]
2152
+ } else {
2153
+ ;(next as Record<string, unknown>)[OM_ROOT_KEYWORDS.formStyle] = style
2154
+ }
2155
+ validateSchemaExtensions(next)
2156
+ return next
2157
+ }
2158
+
2159
+ /**
2160
+ * Sets the form-level label position (Decision 20b). Default `'top'`
2161
+ * clears the key. Mobile viewport collapses `'left'` → `'top'` at render
2162
+ * time (renderer concern).
2163
+ */
2164
+ export function setFormLabelPosition(input: {
2165
+ schema: FormSchema
2166
+ position: 'top' | 'left'
2167
+ }): FormSchema {
2168
+ const { schema, position } = input
2169
+ const next = deepClone(schema)
2170
+ if (position === 'top') {
2171
+ delete (next as Record<string, unknown>)[OM_ROOT_KEYWORDS.formLabelPosition]
2172
+ } else {
2173
+ ;(next as Record<string, unknown>)[OM_ROOT_KEYWORDS.formLabelPosition] = position
2174
+ }
2175
+ validateSchemaExtensions(next)
2176
+ return next
2177
+ }
2178
+
2179
+ /**
2180
+ * Sets the form-level page-mode (Decision 2c). Default `'stacked'` clears
2181
+ * the key.
2182
+ */
2183
+ export function setPageMode(input: {
2184
+ schema: FormSchema
2185
+ mode: 'stacked' | 'paginated'
2186
+ }): FormSchema {
2187
+ const { schema, mode } = input
2188
+ const next = deepClone(schema)
2189
+ if (mode === 'stacked') {
2190
+ delete (next as Record<string, unknown>)[OM_ROOT_KEYWORDS.pageMode]
2191
+ } else {
2192
+ ;(next as Record<string, unknown>)[OM_ROOT_KEYWORDS.pageMode] = mode
2193
+ }
2194
+ validateSchemaExtensions(next)
2195
+ return next
2196
+ }
2197
+
2198
+ /**
2199
+ * Toggles the form-level show-progress flag (Decision 20c). Default
2200
+ * `false` clears the key. Effective only when paginated AND pages >= 2;
2201
+ * gating is the renderer's job.
2202
+ */
2203
+ export function setShowProgress(input: {
2204
+ schema: FormSchema
2205
+ value: boolean
2206
+ }): FormSchema {
2207
+ const { schema, value } = input
2208
+ const next = deepClone(schema)
2209
+ if (value === false) {
2210
+ delete (next as Record<string, unknown>)[OM_ROOT_KEYWORDS.showProgress]
2211
+ } else {
2212
+ ;(next as Record<string, unknown>)[OM_ROOT_KEYWORDS.showProgress] = true
2213
+ }
2214
+ validateSchemaExtensions(next)
2215
+ return next
2216
+ }
2217
+
2218
+ /**
2219
+ * Returns `true` when an `OmTheme` carries no authored member, so the key can
2220
+ * be cleared from the persisted schema (keeps the round-trip byte-minimal —
2221
+ * R-9 / R-CS-6). An empty theme is equivalent to today's appearance (D4).
2222
+ */
2223
+ function isEmptyTheme(theme: OmTheme | undefined): boolean {
2224
+ if (!theme) return true
2225
+ return Object.keys(theme).length === 0
2226
+ }
2227
+
2228
+ /**
2229
+ * Sets (or clears) the form-wide visual theme (`x-om-theme`, spec D4). An
2230
+ * `undefined`/empty theme deletes the key so an unstyled form round-trips
2231
+ * byte-identically (R-CS-6). The result is validated through `validateOmTheme`
2232
+ * before returning — invalid themes throw `SchemaHelperError`, mirroring the
2233
+ * neighbouring form-level setters.
2234
+ */
2235
+ export function setFormTheme(schema: FormSchema, theme: OmTheme | undefined): FormSchema {
2236
+ const next = deepClone(schema)
2237
+ if (isEmptyTheme(theme)) {
2238
+ delete (next as Record<string, unknown>)[OM_ROOT_KEYWORDS.theme]
2239
+ } else {
2240
+ ;(next as Record<string, unknown>)[OM_ROOT_KEYWORDS.theme] = theme
2241
+ }
2242
+ validateSchemaExtensions(next)
2243
+ return next
2244
+ }
2245
+
2246
+ /**
2247
+ * Immutably sets (or clears) a single `OmTheme` member, validating the merged
2248
+ * theme. Passing `undefined` removes that member; when the resulting theme is
2249
+ * empty the whole `x-om-theme` key is cleared.
2250
+ */
2251
+ export function setFormThemeField<Key extends keyof OmTheme>(
2252
+ schema: FormSchema,
2253
+ key: Key,
2254
+ value: OmTheme[Key] | undefined,
2255
+ ): FormSchema {
2256
+ const current = (schema as Record<string, unknown>)[OM_ROOT_KEYWORDS.theme] as OmTheme | undefined
2257
+ const nextTheme: OmTheme = { ...(current ?? {}) }
2258
+ if (value === undefined) {
2259
+ delete nextTheme[key]
2260
+ } else {
2261
+ nextTheme[key] = value
2262
+ }
2263
+ return setFormTheme(schema, nextTheme)
2264
+ }
2265
+
2266
+ /**
2267
+ * Sets (or clears) a section's per-section appearance (`OmSection.style`, spec
2268
+ * Step 7). An `undefined`/empty style deletes the member so an unstyled section
2269
+ * round-trips byte-minimal (R-CS-6). Mirrors `setSectionColumns` for section
2270
+ * lookup and `setFormTheme` for the empty/validate contract: invalid styles
2271
+ * throw `SchemaHelperError` via `validateSchemaExtensions`.
2272
+ */
2273
+ export function setSectionStyle(
2274
+ schema: FormSchema,
2275
+ sectionKey: string,
2276
+ style: OmSectionStyle | undefined,
2277
+ ): FormSchema {
2278
+ const next = deepClone(schema)
2279
+ const sections = (next[OM_ROOT_KEYWORDS.sections] ?? []) as SectionNode[]
2280
+ const section = sections.find((entry) => entry.key === sectionKey)
2281
+ if (!section) {
2282
+ throw new SchemaHelperError(
2283
+ `Section "${sectionKey}" not found.`,
2284
+ 'unknown_section',
2285
+ [sectionKey],
2286
+ )
2287
+ }
2288
+ if (!style || Object.keys(style).length === 0) {
2289
+ delete section.style
2290
+ } else {
2291
+ section.style = style
2292
+ }
2293
+ validateSchemaExtensions(next)
2294
+ return next
2295
+ }
2296
+
2297
+ /**
2298
+ * Sets (or clears) a field's per-field appearance (`x-om-style`, spec Step 7).
2299
+ * An `undefined`/empty style deletes the key so an unstyled field round-trips
2300
+ * byte-minimal (R-CS-6). Mirrors `setFieldGridSpan` for field lookup; invalid
2301
+ * styles throw `SchemaHelperError` via `validateSchemaExtensions`.
2302
+ */
2303
+ export function setFieldStyle(
2304
+ schema: FormSchema,
2305
+ fieldKey: string,
2306
+ style: OmFieldStyle | undefined,
2307
+ ): FormSchema {
2308
+ const next = deepClone(schema)
2309
+ const node = next.properties[fieldKey]
2310
+ if (!node) {
2311
+ throw new SchemaHelperError(
2312
+ `Field "${fieldKey}" not found.`,
2313
+ 'unknown_field',
2314
+ [fieldKey],
2315
+ )
2316
+ }
2317
+ if (!style || Object.keys(style).length === 0) {
2318
+ delete node[OM_FIELD_KEYWORDS.style]
2319
+ } else {
2320
+ node[OM_FIELD_KEYWORDS.style] = style
2321
+ }
2322
+ validateSchemaExtensions(next)
2323
+ return next
2324
+ }
2325
+
2326
+ function dedupePreservingOrder(values: ReadonlyArray<string>): string[] {
2327
+ const seen = new Set<string>()
2328
+ const ordered: string[] = []
2329
+ for (const value of values) {
2330
+ if (seen.has(value)) continue
2331
+ seen.add(value)
2332
+ ordered.push(value)
2333
+ }
2334
+ return ordered
2335
+ }
2336
+
2337
+ /**
2338
+ * Declares a role in `x-om-roles`. `admin` is always implicitly present.
2339
+ * No-op (returns an equivalent clone) if the role is already declared.
2340
+ */
2341
+ export function addRoleToSchema(schema: FormSchema, role: string): FormSchema {
2342
+ const next = deepClone(schema)
2343
+ const roles = dedupePreservingOrder([
2344
+ 'admin',
2345
+ ...((next[OM_ROOT_KEYWORDS.roles] ?? []) as string[]),
2346
+ role,
2347
+ ])
2348
+ next[OM_ROOT_KEYWORDS.roles] = roles
2349
+ return next
2350
+ }
2351
+
2352
+ /**
2353
+ * Renames a declared role everywhere it is referenced: `x-om-roles`,
2354
+ * `x-om-default-actor-role`, and every field's `x-om-editable-by` /
2355
+ * `x-om-visible-to`. `admin` is never touched. Occurrences are deduped while
2356
+ * preserving order.
2357
+ */
2358
+ export function renameRoleInSchema(
2359
+ schema: FormSchema,
2360
+ oldRole: string,
2361
+ newRole: string,
2362
+ ): FormSchema {
2363
+ const next = deepClone(schema)
2364
+ if (oldRole === 'admin' || newRole === 'admin' || oldRole === newRole) return next
2365
+ const roles = dedupePreservingOrder(
2366
+ ((next[OM_ROOT_KEYWORDS.roles] ?? []) as string[]).map((entry) =>
2367
+ entry === oldRole ? newRole : entry,
2368
+ ),
2369
+ )
2370
+ next[OM_ROOT_KEYWORDS.roles] = roles
2371
+ if (next[OM_ROOT_KEYWORDS.defaultActorRole] === oldRole) {
2372
+ next[OM_ROOT_KEYWORDS.defaultActorRole] = newRole
2373
+ }
2374
+ for (const field of Object.values(next.properties)) {
2375
+ for (const keyword of [OM_FIELD_KEYWORDS.editableBy, OM_FIELD_KEYWORDS.visibleTo]) {
2376
+ const list = field[keyword]
2377
+ if (!Array.isArray(list)) continue
2378
+ field[keyword] = dedupePreservingOrder(
2379
+ (list as string[]).map((entry) => (entry === oldRole ? newRole : entry)),
2380
+ )
2381
+ }
2382
+ }
2383
+ return next
2384
+ }
2385
+
2386
+ /**
2387
+ * Removes a declared role from `x-om-roles` and every field reference.
2388
+ * `admin` is never removable. If the role was the default actor role, that
2389
+ * resets to `admin`. A field whose `x-om-editable-by` would become empty is
2390
+ * reset to `['admin']` (a field must always be editable by someone).
2391
+ * `x-om-visible-to` may end up empty (its empty semantics already mean
2392
+ * "editable ∪ admin").
2393
+ */
2394
+ export function removeRoleFromSchema(schema: FormSchema, role: string): FormSchema {
2395
+ const next = deepClone(schema)
2396
+ if (role === 'admin') return next
2397
+ next[OM_ROOT_KEYWORDS.roles] = (
2398
+ (next[OM_ROOT_KEYWORDS.roles] ?? []) as string[]
2399
+ ).filter((entry) => entry !== role)
2400
+ if (next[OM_ROOT_KEYWORDS.defaultActorRole] === role) {
2401
+ next[OM_ROOT_KEYWORDS.defaultActorRole] = 'admin'
2402
+ }
2403
+ for (const field of Object.values(next.properties)) {
2404
+ const editableBy = field[OM_FIELD_KEYWORDS.editableBy]
2405
+ if (Array.isArray(editableBy)) {
2406
+ const filtered = (editableBy as string[]).filter((entry) => entry !== role)
2407
+ field[OM_FIELD_KEYWORDS.editableBy] = filtered.length > 0 ? filtered : ['admin']
2408
+ }
2409
+ const visibleTo = field[OM_FIELD_KEYWORDS.visibleTo]
2410
+ if (Array.isArray(visibleTo)) {
2411
+ field[OM_FIELD_KEYWORDS.visibleTo] = (visibleTo as string[]).filter(
2412
+ (entry) => entry !== role,
2413
+ )
2414
+ }
2415
+ }
2416
+ return next
2417
+ }
2418
+
2419
+ /** Reserved role identifier for non-logged-in (anonymous) participants. */
2420
+ export const GUEST_ROLE = 'guest'
2421
+
2422
+ /**
2423
+ * True when the form is configured for anonymous submissions: the `guest`
2424
+ * role is declared AND it is the default actor role.
2425
+ */
2426
+ export function isGuestSubmissionEnabled(schema: FormSchema): boolean {
2427
+ const roles = (schema[OM_ROOT_KEYWORDS.roles] ?? []) as string[]
2428
+ return (
2429
+ roles.includes(GUEST_ROLE) &&
2430
+ schema[OM_ROOT_KEYWORDS.defaultActorRole] === GUEST_ROLE
2431
+ )
2432
+ }
2433
+
2434
+ /**
2435
+ * Enables anonymous submissions: declares the `guest` role, makes it the
2436
+ * default actor role, and grants every field `x-om-editable-by` access to
2437
+ * `guest` (deduped, `admin` preserved). `x-om-visible-to` is left untouched —
2438
+ * its empty semantics already mean "editable ∪ admin", so guest can read any
2439
+ * field it can edit.
2440
+ */
2441
+ export function enableGuestSubmissions(schema: FormSchema): FormSchema {
2442
+ const next = addRoleToSchema(schema, GUEST_ROLE)
2443
+ next[OM_ROOT_KEYWORDS.defaultActorRole] = GUEST_ROLE
2444
+ for (const field of Object.values(next.properties)) {
2445
+ const editableBy = (field[OM_FIELD_KEYWORDS.editableBy] ?? []) as string[]
2446
+ field[OM_FIELD_KEYWORDS.editableBy] = dedupePreservingOrder([
2447
+ ...editableBy,
2448
+ GUEST_ROLE,
2449
+ 'admin',
2450
+ ])
2451
+ }
2452
+ return next
2453
+ }
2454
+
2455
+ /**
2456
+ * Disables anonymous submissions by removing the `guest` role. Delegates to
2457
+ * `removeRoleFromSchema`, which resets the default actor role to `admin` and
2458
+ * strips `guest` from every field reference.
2459
+ */
2460
+ export function disableGuestSubmissions(schema: FormSchema): FormSchema {
2461
+ return removeRoleFromSchema(schema, GUEST_ROLE)
2462
+ }
2463
+
2464
+ /**
2465
+ * Returns the field keys present in `properties` but not listed in any
2466
+ * `x-om-sections[*].fieldKeys`. Order matches `properties` insertion order
2467
+ * (Decision 4c).
2468
+ */
2469
+ export function computeOrphanFieldKeys(schema: FormSchema): string[] {
2470
+ const sections = (schema[OM_ROOT_KEYWORDS.sections] ?? []) as SectionNode[]
2471
+ const claimed = new Set<string>()
2472
+ for (const section of sections) {
2473
+ for (const fieldKey of section.fieldKeys) claimed.add(fieldKey)
2474
+ }
2475
+ const orphans: string[] = []
2476
+ for (const fieldKey of Object.keys(schema.properties)) {
2477
+ if (!claimed.has(fieldKey)) orphans.push(fieldKey)
2478
+ }
2479
+ return orphans
2480
+ }
2481
+
2482
+ /**
2483
+ * Materialises the synthesized "Ungrouped" container into a real section
2484
+ * at the top of `x-om-sections` (Decision 12c). Field key order is
2485
+ * preserved from `properties` insertion order. The new section gets the
2486
+ * next available `section_<n>` key.
2487
+ */
2488
+ export function adoptUngroupedAsSection(input: {
2489
+ schema: FormSchema
2490
+ }): { schema: FormSchema; sectionKey: string } {
2491
+ const orphans = computeOrphanFieldKeys(input.schema)
2492
+ if (orphans.length === 0) {
2493
+ throw new SchemaHelperError(
2494
+ 'No ungrouped fields to adopt.',
2495
+ 'no_orphans',
2496
+ [],
2497
+ )
2498
+ }
2499
+ const next = deepClone(input.schema)
2500
+ const sections = (next[OM_ROOT_KEYWORDS.sections] ?? []) as SectionNode[]
2501
+ const newKey = nextSectionKey(sections)
2502
+ const newSection: SectionNode = {
2503
+ key: newKey,
2504
+ kind: 'section',
2505
+ title: { en: 'Untitled' },
2506
+ fieldKeys: [...orphans],
2507
+ }
2508
+ next[OM_ROOT_KEYWORDS.sections] = [newSection, ...sections]
2509
+ validateSchemaExtensions(next)
2510
+ return { schema: next, sectionKey: newKey }
2511
+ }
2512
+
2513
+ function collectCanonicalOrder(schema: FormSchema): string[] {
2514
+ const ordered: string[] = []
2515
+ const sections = (schema[OM_ROOT_KEYWORDS.sections] ?? []) as SectionNode[]
2516
+ for (const section of sections) {
2517
+ for (const fieldKey of section.fieldKeys) {
2518
+ if (!ordered.includes(fieldKey)) ordered.push(fieldKey)
2519
+ }
2520
+ }
2521
+ for (const fieldKey of Object.keys(schema.properties)) {
2522
+ if (!ordered.includes(fieldKey)) ordered.push(fieldKey)
2523
+ }
2524
+ return ordered
2525
+ }