@open-mercato/core 0.7.0 → 0.7.1-develop.7102.1.b41f7e3e51
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.
- package/.turbo/turbo-build.log +1 -1
- package/dist/helpers/integration/api.js +13 -1
- package/dist/helpers/integration/api.js.map +2 -2
- package/dist/helpers/integration/communicationChannelsFixtures.js +19 -0
- package/dist/helpers/integration/communicationChannelsFixtures.js.map +2 -2
- package/dist/modules/api_keys/api/keys/route.js +1 -1
- package/dist/modules/api_keys/api/keys/route.js.map +2 -2
- package/dist/modules/api_keys/backend/api-keys/page.js +3 -1
- package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
- package/dist/modules/api_keys/di.js +9 -0
- package/dist/modules/api_keys/di.js.map +7 -0
- package/dist/modules/api_keys/services/principalService.js +31 -0
- package/dist/modules/api_keys/services/principalService.js.map +7 -0
- package/dist/modules/attachments/api/route.js +2 -2
- package/dist/modules/attachments/api/route.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentLibrary.js +2 -0
- package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
- package/dist/modules/attachments/di.js +11 -1
- package/dist/modules/attachments/di.js.map +2 -2
- package/dist/modules/attachments/index.js.map +1 -1
- package/dist/modules/attachments/lib/attachment-service.js +313 -0
- package/dist/modules/attachments/lib/attachment-service.js.map +7 -0
- package/dist/modules/attachments/lib/scoped-upload-service.js +15 -2
- package/dist/modules/attachments/lib/scoped-upload-service.js.map +2 -2
- package/dist/modules/attachments/lib/upload-limits.js +6 -2
- package/dist/modules/attachments/lib/upload-limits.js.map +2 -2
- package/dist/modules/audit_logs/backend/audit-logs/page.js +6 -0
- package/dist/modules/audit_logs/backend/audit-logs/page.js.map +2 -2
- package/dist/modules/audit_logs/lib/display-helpers.js +19 -11
- package/dist/modules/audit_logs/lib/display-helpers.js.map +2 -2
- package/dist/modules/audit_logs/services/actionLogService.js +57 -12
- package/dist/modules/audit_logs/services/actionLogService.js.map +3 -3
- package/dist/modules/auth/acl.js +30 -5
- package/dist/modules/auth/acl.js.map +2 -2
- package/dist/modules/auth/api/feature-check.js +8 -2
- package/dist/modules/auth/api/feature-check.js.map +2 -2
- package/dist/modules/auth/api/login.js +4 -1
- package/dist/modules/auth/api/login.js.map +2 -2
- package/dist/modules/auth/api/reset/validate.js +55 -0
- package/dist/modules/auth/api/reset/validate.js.map +7 -0
- package/dist/modules/auth/api/roles/acl/route.js +28 -33
- package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
- package/dist/modules/auth/api/session/refresh.js +25 -1
- package/dist/modules/auth/api/session/refresh.js.map +2 -2
- package/dist/modules/auth/api/users/acl/route.js +96 -51
- package/dist/modules/auth/api/users/acl/route.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +13 -5
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/backend/roles/[id]/edit/page.meta.js +5 -1
- package/dist/modules/auth/backend/roles/[id]/edit/page.meta.js.map +2 -2
- package/dist/modules/auth/backend/roles/page.js +3 -1
- package/dist/modules/auth/backend/roles/page.js.map +2 -2
- package/dist/modules/auth/backend/users/[id]/edit/page.meta.js +5 -1
- package/dist/modules/auth/backend/users/[id]/edit/page.meta.js.map +2 -2
- package/dist/modules/auth/backend/users/page.js +2 -1
- package/dist/modules/auth/backend/users/page.js.map +2 -2
- package/dist/modules/auth/commands/acl.js +254 -0
- package/dist/modules/auth/commands/acl.js.map +7 -0
- package/dist/modules/auth/components/AclEditor.js +39 -30
- package/dist/modules/auth/components/AclEditor.js.map +2 -2
- package/dist/modules/auth/data/entities.js.map +2 -2
- package/dist/modules/auth/data/validators.js +5 -1
- package/dist/modules/auth/data/validators.js.map +2 -2
- package/dist/modules/auth/di.js +35 -9
- package/dist/modules/auth/di.js.map +2 -2
- package/dist/modules/auth/frontend/reset/[token]/page.js +46 -0
- package/dist/modules/auth/frontend/reset/[token]/page.js.map +2 -2
- package/dist/modules/auth/lib/grantChecks.js.map +2 -2
- package/dist/modules/auth/lib/userIdFilter.js +16 -0
- package/dist/modules/auth/lib/userIdFilter.js.map +7 -0
- package/dist/modules/auth/services/authService.js +16 -2
- package/dist/modules/auth/services/authService.js.map +2 -2
- package/dist/modules/auth/services/principalService.js +200 -0
- package/dist/modules/auth/services/principalService.js.map +7 -0
- package/dist/modules/auth/services/rbacService.js +67 -24
- package/dist/modules/auth/services/rbacService.js.map +3 -3
- package/dist/modules/auth/services/roleOrganizationScope.js +41 -0
- package/dist/modules/auth/services/roleOrganizationScope.js.map +7 -0
- package/dist/modules/business_rules/backend/logs/page.js +3 -1
- package/dist/modules/business_rules/backend/logs/page.js.map +2 -2
- package/dist/modules/business_rules/backend/rules/page.js +3 -1
- package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
- package/dist/modules/business_rules/backend/sets/page.js +3 -1
- package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
- package/dist/modules/business_rules/lib/expression-evaluator.js +9 -9
- package/dist/modules/business_rules/lib/expression-evaluator.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-evaluator.js +10 -9
- package/dist/modules/business_rules/lib/rule-evaluator.js.map +2 -2
- package/dist/modules/catalog/ai-agents.js +1 -1
- package/dist/modules/catalog/ai-agents.js.map +1 -1
- package/dist/modules/catalog/ai-tools/merchandising-pack.js +2 -2
- package/dist/modules/catalog/ai-tools/merchandising-pack.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.js +5 -2
- package/dist/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.js.map +2 -2
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js +2 -0
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductsDataTable.js +7 -1
- package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
- package/dist/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.js +2 -0
- package/dist/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.js.map +2 -2
- package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js +9 -1
- package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/test-seed/route.js +95 -10
- package/dist/modules/communication_channels/api/post/test-seed/route.js.map +2 -2
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.js +3 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.js.map +2 -2
- package/dist/modules/communication_channels/commands/ingest-inbound-message.js +14 -1
- package/dist/modules/communication_channels/commands/ingest-inbound-message.js.map +2 -2
- package/dist/modules/communication_channels/di.js +7 -1
- package/dist/modules/communication_channels/di.js.map +2 -2
- package/dist/modules/communication_channels/lib/email-capabilities.js +4 -1
- package/dist/modules/communication_channels/lib/email-capabilities.js.map +2 -2
- package/dist/modules/communication_channels/lib/outbound-recipient.js +33 -0
- package/dist/modules/communication_channels/lib/outbound-recipient.js.map +7 -0
- package/dist/modules/communication_channels/lib/resolve-channel-type.js +51 -0
- package/dist/modules/communication_channels/lib/resolve-channel-type.js.map +7 -0
- package/dist/modules/communication_channels/lib/test-seed.js +41 -2
- package/dist/modules/communication_channels/lib/test-seed.js.map +2 -2
- package/dist/modules/configs/lib/system-status.js +9 -0
- package/dist/modules/configs/lib/system-status.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/page.js +3 -1
- package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
- package/dist/modules/currencies/backend/exchange-rates/page.js +3 -1
- package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
- package/dist/modules/currencies/services/rateFetchingService.js +6 -1
- package/dist/modules/currencies/services/rateFetchingService.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/domain-mappings.js +9 -0
- package/dist/modules/customer_accounts/api/admin/domain-mappings.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js +3 -1
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.js +3 -1
- package/dist/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.js.map +2 -2
- package/dist/modules/customer_accounts/services/domainMappingService.js +10 -0
- package/dist/modules/customer_accounts/services/domainMappingService.js.map +2 -2
- package/dist/modules/customers/ai-tools/companies-pack.js +4 -1
- package/dist/modules/customers/ai-tools/companies-pack.js.map +2 -2
- package/dist/modules/customers/ai-tools/deal-analyzer-pack.js +13 -2
- package/dist/modules/customers/ai-tools/deal-analyzer-pack.js.map +2 -2
- package/dist/modules/customers/ai-tools/deals-pack.js +52 -6
- package/dist/modules/customers/ai-tools/deals-pack.js.map +2 -2
- package/dist/modules/customers/ai-tools/people-pack.js +4 -1
- package/dist/modules/customers/ai-tools/people-pack.js.map +2 -2
- package/dist/modules/customers/api/activities/route.js +48 -6
- package/dist/modules/customers/api/activities/route.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/people/route.js +20 -64
- package/dist/modules/customers/api/companies/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/route.js +17 -94
- package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/dashboard/widgets/customer-todos/route.js +8 -5
- package/dist/modules/customers/api/dashboard/widgets/customer-todos/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/companies/route.js +1 -1
- package/dist/modules/customers/api/deals/[id]/companies/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js +1 -1
- package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/route.js +8 -25
- package/dist/modules/customers/api/deals/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/stats/route.js +3 -22
- package/dist/modules/customers/api/deals/[id]/stats/route.js.map +2 -2
- package/dist/modules/customers/api/deals/aggregate/route.js +11 -4
- package/dist/modules/customers/api/deals/aggregate/route.js.map +2 -2
- package/dist/modules/customers/api/deals/map/route.js +2 -1
- package/dist/modules/customers/api/deals/map/route.js.map +2 -2
- package/dist/modules/customers/api/deals/route.js +38 -1
- package/dist/modules/customers/api/deals/route.js.map +2 -2
- package/dist/modules/customers/api/entity-roles-factory.js +4 -4
- package/dist/modules/customers/api/entity-roles-factory.js.map +2 -2
- package/dist/modules/customers/api/interactions/route.js +3 -1
- package/dist/modules/customers/api/interactions/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/tasks/route.js +27 -4
- package/dist/modules/customers/api/interactions/tasks/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js +4 -3
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/context.js +1 -1
- package/dist/modules/customers/api/people/[id]/companies/context.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js +1 -1
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/route.js +11 -10
- package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/people/check-phone/route.js +51 -9
- package/dist/modules/customers/api/people/check-phone/route.js.map +2 -2
- package/dist/modules/customers/api/todos/route.js +30 -5
- package/dist/modules/customers/api/todos/route.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/page.js +4 -2
- package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/page.js +6 -1
- package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/page.js +5 -2
- package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/Lane.js +4 -13
- package/dist/modules/customers/backend/customers/deals/pipeline/components/Lane.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.js +85 -14
- package/dist/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/toneClasses.js +18 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/toneClasses.js.map +7 -0
- package/dist/modules/customers/backend/customers/people/page.js +4 -2
- package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
- package/dist/modules/customers/backend/hooks/useEmailDuplicateCheck.js +9 -3
- package/dist/modules/customers/backend/hooks/useEmailDuplicateCheck.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +21 -34
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/commands/interactions.js.map +1 -1
- package/dist/modules/customers/commands/personCompanyLinks.js +131 -2
- package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
- package/dist/modules/customers/components/CustomerTodosTable.js +1 -0
- package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
- package/dist/modules/customers/components/DealsKpiStrip.js +7 -6
- package/dist/modules/customers/components/DealsKpiStrip.js.map +2 -2
- package/dist/modules/customers/components/calendar/AgendaList.js +2 -2
- package/dist/modules/customers/components/calendar/AgendaList.js.map +2 -2
- package/dist/modules/customers/components/calendar/CalendarEventEditor.js +1 -1
- package/dist/modules/customers/components/calendar/CalendarEventEditor.js.map +2 -2
- package/dist/modules/customers/components/calendar/CalendarScreen.js +1 -1
- package/dist/modules/customers/components/calendar/CalendarScreen.js.map +2 -2
- package/dist/modules/customers/components/calendar/CalendarSettingsModal.js +1 -1
- package/dist/modules/customers/components/calendar/CalendarSettingsModal.js.map +2 -2
- package/dist/modules/customers/components/calendar/EventBlock.js +1 -1
- package/dist/modules/customers/components/calendar/EventBlock.js.map +2 -2
- package/dist/modules/customers/components/calendar/EventPeekPopover.js +3 -2
- package/dist/modules/customers/components/calendar/EventPeekPopover.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/PeopleField.js +40 -5
- package/dist/modules/customers/components/calendar/editor/PeopleField.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/hooks.js +2 -1
- package/dist/modules/customers/components/calendar/editor/hooks.js.map +2 -2
- package/dist/modules/customers/components/calendar/types.js +1 -1
- package/dist/modules/customers/components/calendar/types.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyKpiBar.js +5 -4
- package/dist/modules/customers/components/detail/CompanyKpiBar.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js +3 -1
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
- package/dist/modules/customers/components/detail/DealForm.js +19 -7
- package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
- package/dist/modules/customers/components/detail/DealsSection.js +6 -5
- package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
- package/dist/modules/customers/components/detail/EntityTagsDialog.js +35 -11
- package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonCompaniesSection.js +3 -1
- package/dist/modules/customers/components/detail/PersonCompaniesSection.js.map +2 -2
- package/dist/modules/customers/components/detail/hooks/usePersonTasks.js +19 -13
- package/dist/modules/customers/components/detail/hooks/usePersonTasks.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/ParticipantsField.js +4 -4
- package/dist/modules/customers/components/detail/schedule/ParticipantsField.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js +3 -3
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
- package/dist/modules/customers/components/detail/utils.js +5 -5
- package/dist/modules/customers/components/detail/utils.js.map +2 -2
- package/dist/modules/customers/data/entities.js.map +1 -1
- package/dist/modules/customers/data/validators.js +32 -3
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/customers/events.js +5 -0
- package/dist/modules/customers/events.js.map +2 -2
- package/dist/modules/customers/lib/calendar/conflicts.js +8 -2
- package/dist/modules/customers/lib/calendar/conflicts.js.map +2 -2
- package/dist/modules/customers/lib/calendar/editorPayload.js +3 -2
- package/dist/modules/customers/lib/calendar/editorPayload.js.map +2 -2
- package/dist/modules/customers/lib/calendar/mapItem.js +8 -3
- package/dist/modules/customers/lib/calendar/mapItem.js.map +2 -2
- package/dist/modules/customers/lib/calendar/participantIdentity.js +9 -0
- package/dist/modules/customers/lib/calendar/participantIdentity.js.map +7 -0
- package/dist/modules/customers/lib/closureStage.js +45 -0
- package/dist/modules/customers/lib/closureStage.js.map +7 -0
- package/dist/modules/customers/lib/dealStatus.js +30 -0
- package/dist/modules/customers/lib/dealStatus.js.map +2 -2
- package/dist/modules/customers/lib/detailReadAccess.js +12 -0
- package/dist/modules/customers/lib/detailReadAccess.js.map +7 -0
- package/dist/modules/customers/lib/findPeopleByAddresses.js +1 -0
- package/dist/modules/customers/lib/findPeopleByAddresses.js.map +2 -2
- package/dist/modules/customers/lib/personCompanies.js +100 -2
- package/dist/modules/customers/lib/personCompanies.js.map +2 -2
- package/dist/modules/customers/lib/todoCompatibility.js +12 -0
- package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
- package/dist/modules/dashboards/lib/widgetScope.js +6 -1
- package/dist/modules/dashboards/lib/widgetScope.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/page.js +3 -1
- package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
- package/dist/modules/data_sync/lib/abandoned-run.js +19 -0
- package/dist/modules/data_sync/lib/abandoned-run.js.map +7 -0
- package/dist/modules/data_sync/lib/sync-engine.js +72 -6
- package/dist/modules/data_sync/lib/sync-engine.js.map +2 -2
- package/dist/modules/data_sync/workers/sync-export.js +5 -1
- package/dist/modules/data_sync/workers/sync-export.js.map +2 -2
- package/dist/modules/data_sync/workers/sync-import.js +5 -1
- package/dist/modules/data_sync/workers/sync-import.js.map +2 -2
- package/dist/modules/devices/acl.js +9 -1
- package/dist/modules/devices/acl.js.map +2 -2
- package/dist/modules/devices/api/admin/devices/[id]/route.js +5 -32
- package/dist/modules/devices/api/admin/devices/[id]/route.js.map +2 -2
- package/dist/modules/devices/api/admin/devices/route.js +14 -1
- package/dist/modules/devices/api/admin/devices/route.js.map +2 -2
- package/dist/modules/devices/api/deviceList.js +99 -12
- package/dist/modules/devices/api/deviceList.js.map +2 -2
- package/dist/modules/devices/api/deviceSerialization.js +46 -0
- package/dist/modules/devices/api/deviceSerialization.js.map +7 -0
- package/dist/modules/devices/api/openapi.js +3 -1
- package/dist/modules/devices/api/openapi.js.map +2 -2
- package/dist/modules/devices/api/route.js +9 -1
- package/dist/modules/devices/api/route.js.map +2 -2
- package/dist/modules/devices/backend/devices/[id]/page.js +10 -26
- package/dist/modules/devices/backend/devices/[id]/page.js.map +2 -2
- package/dist/modules/devices/backend/devices/create/page.js +17 -1
- package/dist/modules/devices/backend/devices/create/page.js.map +2 -2
- package/dist/modules/devices/backend/devices/page.js +28 -34
- package/dist/modules/devices/backend/devices/page.js.map +2 -2
- package/dist/modules/devices/backend/devices/useDeviceUserLabels.js +34 -0
- package/dist/modules/devices/backend/devices/useDeviceUserLabels.js.map +7 -0
- package/dist/modules/devices/backend/devices/userOptions.js +52 -0
- package/dist/modules/devices/backend/devices/userOptions.js.map +7 -0
- package/dist/modules/devices/setup.js +6 -2
- package/dist/modules/devices/setup.js.map +2 -2
- package/dist/modules/directory/backend/directory/organizations/page.js +2 -1
- package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/tenants/page.js +2 -1
- package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
- package/dist/modules/directory/di.js +9 -0
- package/dist/modules/directory/di.js.map +2 -2
- package/dist/modules/directory/services/organizationHierarchyService.js +29 -0
- package/dist/modules/directory/services/organizationHierarchyService.js.map +7 -0
- package/dist/modules/directory/services/organizationScopeService.js +56 -0
- package/dist/modules/directory/services/organizationScopeService.js.map +7 -0
- package/dist/modules/directory/utils/organizationScope.js.map +2 -2
- package/dist/modules/entities/api/records.js +4 -2
- package/dist/modules/entities/api/records.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +3 -1
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
- package/dist/modules/eudr/api/plots/route.js +5 -1
- package/dist/modules/eudr/api/plots/route.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/plots/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/plots/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/product-mappings/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/risk-assessments/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/statements/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/statements/page.js.map +2 -2
- package/dist/modules/eudr/commands/statements.js +0 -3
- package/dist/modules/eudr/commands/statements.js.map +2 -2
- package/dist/modules/eudr/data/validators.js +4 -1
- package/dist/modules/eudr/data/validators.js.map +2 -2
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +1 -0
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
- package/dist/modules/feature_toggles/components/OverridesTable.js +1 -0
- package/dist/modules/feature_toggles/components/OverridesTable.js.map +2 -2
- package/dist/modules/feature_toggles/defaults.json +0 -8
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js +3 -0
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/page.js +3 -0
- package/dist/modules/inbox_ops/backend/inbox-ops/page.js.map +2 -2
- package/dist/modules/inbox_ops/lib/htmlToPlainText.js +1 -12
- package/dist/modules/inbox_ops/lib/htmlToPlainText.js.map +2 -2
- package/dist/modules/integrations/api/[id]/credentials/route.js +6 -1
- package/dist/modules/integrations/api/[id]/credentials/route.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/[id]/page.js +38 -29
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +36 -9
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/credential-secret-fields.js +55 -0
- package/dist/modules/integrations/backend/integrations/credential-secret-fields.js.map +7 -0
- package/dist/modules/integrations/data/validators.js +11 -3
- package/dist/modules/integrations/data/validators.js.map +2 -2
- package/dist/modules/integrations/lib/credentials-masking.js +6 -2
- package/dist/modules/integrations/lib/credentials-masking.js.map +2 -2
- package/dist/modules/messages/api/[id]/route.js +29 -1
- package/dist/modules/messages/api/[id]/route.js.map +2 -2
- package/dist/modules/messages/api/openapi.js +17 -2
- package/dist/modules/messages/api/openapi.js.map +2 -2
- package/dist/modules/messages/api/route.js +17 -2
- package/dist/modules/messages/api/route.js.map +2 -2
- package/dist/modules/messages/components/MessagesInboxPageClient.js +7 -14
- package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
- package/dist/modules/messages/components/inboxFilters.js +15 -0
- package/dist/modules/messages/components/inboxFilters.js.map +2 -2
- package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.js +11 -1
- package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.js.map +2 -2
- package/dist/modules/messages/components/message-detail/panels/MessageHeader.js +3 -1
- package/dist/modules/messages/components/message-detail/panels/MessageHeader.js.map +2 -2
- package/dist/modules/messages/components/message-detail/panels/thread-panel.js +2 -1
- package/dist/modules/messages/components/message-detail/panels/thread-panel.js.map +2 -2
- package/dist/modules/messages/components/messageListLabels.js +14 -2
- package/dist/modules/messages/components/messageListLabels.js.map +2 -2
- package/dist/modules/messages/data/validators.js +18 -4
- package/dist/modules/messages/data/validators.js.map +2 -2
- package/dist/modules/messages/lib/channel-sender-identity.js +26 -0
- package/dist/modules/messages/lib/channel-sender-identity.js.map +7 -0
- package/dist/modules/messages/lib/composeSourceChannelType.js +41 -0
- package/dist/modules/messages/lib/composeSourceChannelType.js.map +7 -0
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +4 -6
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +2 -2
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js +3 -1
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js.map +2 -2
- package/dist/modules/payment_gateways/lib/webhook-processor.js +7 -0
- package/dist/modules/payment_gateways/lib/webhook-processor.js.map +2 -2
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js +3 -0
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
- package/dist/modules/push_notifications/backend/push_notifications/page.js +3 -1
- package/dist/modules/push_notifications/backend/push_notifications/page.js.map +2 -2
- package/dist/modules/push_notifications/backend/push_notifications/send/page.js +1 -1
- package/dist/modules/push_notifications/backend/push_notifications/send/page.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +150 -51
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/query_index/lib/search-entity-policy.js +14 -0
- package/dist/modules/query_index/lib/search-entity-policy.js.map +7 -0
- package/dist/modules/query_index/lib/search-tokens.js +79 -3
- package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
- package/dist/modules/resources/backend/resources/resource-types/page.js +3 -1
- package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/page.js +3 -1
- package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.js +3 -0
- package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.js +3 -0
- package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +10 -8
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +79 -1
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/components/PriceWithCurrency.js +7 -5
- package/dist/modules/sales/components/PriceWithCurrency.js.map +2 -2
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +3 -0
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
- package/dist/modules/sales/components/documents/AdjustmentsSection.js +8 -6
- package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/ItemsSection.js +51 -22
- package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/LineItemDialog.js +83 -18
- package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/PaymentsSection.js +23 -9
- package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/ReturnsSection.js +8 -6
- package/dist/modules/sales/components/documents/ReturnsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js +68 -14
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesOrderDraftLines.js +6 -5
- package/dist/modules/sales/components/documents/SalesOrderDraftLines.js.map +2 -2
- package/dist/modules/sales/components/documents/ShipmentDialog.js +5 -4
- package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/ShipmentsSection.js +8 -6
- package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/lineItemShipmentLock.js +54 -0
- package/dist/modules/sales/components/documents/lineItemShipmentLock.js.map +7 -0
- package/dist/modules/sales/components/documents/lineItemUtils.js +2 -2
- package/dist/modules/sales/components/documents/lineItemUtils.js.map +2 -2
- package/dist/modules/sales/data/entities.js +8 -2
- package/dist/modules/sales/data/entities.js.map +2 -2
- package/dist/modules/sales/extension-points.js +1 -0
- package/dist/modules/sales/extension-points.js.map +2 -2
- package/dist/modules/sales/lib/salesChannelsToggleSeed.js +33 -0
- package/dist/modules/sales/lib/salesChannelsToggleSeed.js.map +7 -0
- package/dist/modules/sales/migrations/Migration20260821120000_sales_notes_addresses_context_idx.js +32 -0
- package/dist/modules/sales/migrations/Migration20260821120000_sales_notes_addresses_context_idx.js.map +7 -0
- package/dist/modules/sales/setup.js +2 -0
- package/dist/modules/sales/setup.js.map +2 -2
- package/dist/modules/sales/widgets/injection/payment-gateway-status-column/widget.js +10 -2
- package/dist/modules/sales/widgets/injection/payment-gateway-status-column/widget.js.map +2 -2
- package/dist/modules/sales/widgets/injection-table.js +4 -7
- package/dist/modules/sales/widgets/injection-table.js.map +2 -2
- package/dist/modules/staff/backend/staff/leave-requests/page.js +3 -0
- package/dist/modules/staff/backend/staff/leave-requests/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/my-leave-requests/page.js +3 -0
- package/dist/modules/staff/backend/staff/my-leave-requests/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-members/page.js +3 -0
- package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-roles/page.js +3 -0
- package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +3 -0
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/page.js +3 -0
- package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/page.js +29 -18
- package/dist/modules/staff/backend/staff/timesheets/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js +3 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
- package/dist/modules/sync_excel/lib/adapters/customers.js +1 -0
- package/dist/modules/sync_excel/lib/adapters/customers.js.map +2 -2
- package/dist/modules/warranty_claims/api/assignees/route.js +3 -3
- package/dist/modules/warranty_claims/api/assignees/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/attachments/route.js +2 -2
- package/dist/modules/warranty_claims/api/portal/attachments/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/claims/route.js +12 -9
- package/dist/modules/warranty_claims/api/portal/claims/route.js.map +2 -2
- package/dist/modules/warranty_claims/backend/page.js +3 -0
- package/dist/modules/warranty_claims/backend/page.js.map +2 -2
- package/dist/modules/warranty_claims/backend/warranty_claims/registrations/page.js +3 -0
- package/dist/modules/warranty_claims/backend/warranty_claims/registrations/page.js.map +2 -2
- package/dist/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.js +3 -0
- package/dist/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.js.map +2 -2
- package/dist/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.js +3 -0
- package/dist/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.js.map +2 -2
- package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.js +3 -0
- package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.js.map +2 -2
- package/dist/modules/wms/api/warehouseSearch.js +21 -0
- package/dist/modules/wms/api/warehouseSearch.js.map +7 -0
- package/dist/modules/wms/api/warehouses/route.js +13 -9
- package/dist/modules/wms/api/warehouses/route.js.map +2 -2
- package/dist/modules/wms/api/zones/route.js +15 -2
- package/dist/modules/wms/api/zones/route.js.map +2 -2
- package/dist/modules/wms/commands/configuration.js +121 -9
- package/dist/modules/wms/commands/configuration.js.map +2 -2
- package/dist/modules/wms/commands/inventory-actions.js +3 -0
- package/dist/modules/wms/commands/inventory-actions.js.map +2 -2
- package/dist/modules/wms/commands/shared.js +9 -1
- package/dist/modules/wms/commands/shared.js.map +2 -2
- package/dist/modules/wms/components/backend/WarehouseEditDialog.js +158 -0
- package/dist/modules/wms/components/backend/WarehouseEditDialog.js.map +7 -0
- package/dist/modules/wms/components/backend/WmsConfigurationPage.js +76 -111
- package/dist/modules/wms/components/backend/WmsConfigurationPage.js.map +3 -3
- package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js +1 -0
- package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsLotsListPage.js +1 -0
- package/dist/modules/wms/components/backend/WmsLotsListPage.js.map +2 -2
- package/dist/modules/wms/components/backend/inventoryMutationLoaders.js +27 -20
- package/dist/modules/wms/components/backend/inventoryMutationLoaders.js.map +2 -2
- package/dist/modules/wms/components/backend/warehouseFormOptions.js +66 -0
- package/dist/modules/wms/components/backend/warehouseFormOptions.js.map +7 -0
- package/dist/modules/workflows/backend/definitions/page.js +3 -1
- package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
- package/dist/modules/workflows/backend/events/page.js +3 -1
- package/dist/modules/workflows/backend/events/page.js.map +2 -2
- package/dist/modules/workflows/backend/instances/page.js +3 -1
- package/dist/modules/workflows/backend/instances/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/page.js +3 -1
- package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
- package/dist/modules/workflows/lib/activity-executor.js +4 -0
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/package.json +9 -10
- package/src/helpers/integration/api.ts +33 -1
- package/src/helpers/integration/communicationChannelsFixtures.ts +69 -1
- package/src/modules/api_keys/api/keys/route.ts +3 -1
- package/src/modules/api_keys/backend/api-keys/page.tsx +4 -1
- package/src/modules/api_keys/di.ts +7 -0
- package/src/modules/api_keys/services/principalService.ts +33 -0
- package/src/modules/attachments/AGENTS.md +15 -0
- package/src/modules/attachments/api/route.ts +2 -2
- package/src/modules/attachments/components/AttachmentLibrary.tsx +3 -0
- package/src/modules/attachments/di.ts +16 -0
- package/src/modules/attachments/i18n/de.json +5 -0
- package/src/modules/attachments/i18n/en.json +5 -0
- package/src/modules/attachments/i18n/es.json +5 -0
- package/src/modules/attachments/i18n/ko.json +5 -0
- package/src/modules/attachments/i18n/pl.json +5 -0
- package/src/modules/attachments/index.ts +10 -0
- package/src/modules/attachments/lib/attachment-service.ts +468 -0
- package/src/modules/attachments/lib/scoped-upload-service.ts +46 -0
- package/src/modules/attachments/lib/upload-limits.ts +6 -2
- package/src/modules/audit_logs/backend/audit-logs/page.tsx +8 -0
- package/src/modules/audit_logs/lib/display-helpers.tsx +42 -32
- package/src/modules/audit_logs/services/actionLogService.ts +74 -11
- package/src/modules/auth/acl.ts +30 -6
- package/src/modules/auth/api/feature-check.ts +10 -3
- package/src/modules/auth/api/login.ts +9 -1
- package/src/modules/auth/api/reset/validate.ts +57 -0
- package/src/modules/auth/api/roles/acl/route.ts +42 -39
- package/src/modules/auth/api/session/refresh.ts +32 -1
- package/src/modules/auth/api/users/acl/route.ts +177 -53
- package/src/modules/auth/api/users/route.ts +18 -5
- package/src/modules/auth/backend/roles/[id]/edit/page.meta.ts +5 -2
- package/src/modules/auth/backend/roles/page.tsx +4 -2
- package/src/modules/auth/backend/users/[id]/edit/page.meta.ts +5 -2
- package/src/modules/auth/backend/users/page.tsx +3 -2
- package/src/modules/auth/commands/acl.ts +495 -0
- package/src/modules/auth/components/AclEditor.tsx +63 -33
- package/src/modules/auth/data/entities.ts +4 -1
- package/src/modules/auth/data/validators.ts +5 -0
- package/src/modules/auth/di.ts +46 -16
- package/src/modules/auth/frontend/reset/[token]/page.tsx +74 -0
- package/src/modules/auth/i18n/de.json +389 -0
- package/src/modules/auth/i18n/en.json +389 -0
- package/src/modules/auth/i18n/es.json +389 -0
- package/src/modules/auth/i18n/ko.json +389 -0
- package/src/modules/auth/i18n/pl.json +391 -2
- package/src/modules/auth/lib/grantChecks.ts +6 -0
- package/src/modules/auth/lib/userIdFilter.ts +31 -0
- package/src/modules/auth/services/authService.ts +18 -2
- package/src/modules/auth/services/principalService.ts +266 -0
- package/src/modules/auth/services/rbacService.ts +110 -24
- package/src/modules/auth/services/roleOrganizationScope.ts +70 -0
- package/src/modules/business_rules/backend/logs/page.tsx +4 -1
- package/src/modules/business_rules/backend/rules/page.tsx +4 -1
- package/src/modules/business_rules/backend/sets/page.tsx +4 -1
- package/src/modules/business_rules/lib/expression-evaluator.ts +9 -9
- package/src/modules/business_rules/lib/rule-evaluator.ts +10 -9
- package/src/modules/catalog/ai-agents.ts +1 -1
- package/src/modules/catalog/ai-tools/merchandising-pack.ts +2 -2
- package/src/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.tsx +12 -5
- package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +3 -0
- package/src/modules/catalog/components/products/ProductsDataTable.tsx +7 -0
- package/src/modules/catalog/i18n/de.json +1 -0
- package/src/modules/catalog/i18n/en.json +1 -0
- package/src/modules/catalog/i18n/es.json +1 -0
- package/src/modules/catalog/i18n/ko.json +1 -0
- package/src/modules/catalog/i18n/pl.json +1 -0
- package/src/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.tsx +4 -0
- package/src/modules/communication_channels/api/post/channels/[id]/test-send/route.ts +17 -1
- package/src/modules/communication_channels/api/post/test-seed/route.ts +155 -16
- package/src/modules/communication_channels/backend/communication_channels/channels/page.tsx +4 -0
- package/src/modules/communication_channels/commands/ingest-inbound-message.ts +38 -1
- package/src/modules/communication_channels/di.ts +7 -0
- package/src/modules/communication_channels/lib/adapter.ts +14 -0
- package/src/modules/communication_channels/lib/email-capabilities.ts +4 -0
- package/src/modules/communication_channels/lib/outbound-recipient.ts +71 -0
- package/src/modules/communication_channels/lib/resolve-channel-type.ts +99 -0
- package/src/modules/communication_channels/lib/test-seed.ts +64 -4
- package/src/modules/configs/i18n/de.json +2 -0
- package/src/modules/configs/i18n/en.json +2 -0
- package/src/modules/configs/i18n/es.json +2 -0
- package/src/modules/configs/i18n/ko.json +2 -0
- package/src/modules/configs/i18n/pl.json +2 -0
- package/src/modules/configs/lib/system-status.ts +9 -0
- package/src/modules/currencies/AGENTS.md +3 -0
- package/src/modules/currencies/backend/currencies/page.tsx +4 -1
- package/src/modules/currencies/backend/exchange-rates/page.tsx +4 -1
- package/src/modules/currencies/services/README.md +45 -0
- package/src/modules/currencies/services/rateFetchingService.ts +6 -1
- package/src/modules/customer_accounts/api/admin/domain-mappings.ts +7 -0
- package/src/modules/customer_accounts/backend/customer_accounts/roles/page.tsx +4 -1
- package/src/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.tsx +4 -1
- package/src/modules/customer_accounts/services/domainMappingService.ts +10 -0
- package/src/modules/customers/ai-tools/companies-pack.ts +4 -1
- package/src/modules/customers/ai-tools/deal-analyzer-pack.ts +17 -2
- package/src/modules/customers/ai-tools/deals-pack.ts +66 -1
- package/src/modules/customers/ai-tools/people-pack.ts +4 -1
- package/src/modules/customers/api/activities/route.ts +45 -0
- package/src/modules/customers/api/companies/[id]/people/route.ts +24 -73
- package/src/modules/customers/api/companies/[id]/route.ts +24 -107
- package/src/modules/customers/api/dashboard/widgets/customer-todos/route.ts +16 -8
- package/src/modules/customers/api/deals/[id]/companies/route.ts +4 -1
- package/src/modules/customers/api/deals/[id]/people/route.ts +4 -1
- package/src/modules/customers/api/deals/[id]/route.ts +17 -28
- package/src/modules/customers/api/deals/[id]/stats/route.ts +10 -25
- package/src/modules/customers/api/deals/aggregate/route.ts +14 -4
- package/src/modules/customers/api/deals/map/route.ts +1 -0
- package/src/modules/customers/api/deals/route.ts +50 -1
- package/src/modules/customers/api/entity-roles-factory.ts +8 -4
- package/src/modules/customers/api/interactions/route.ts +8 -2
- package/src/modules/customers/api/interactions/tasks/route.ts +24 -1
- package/src/modules/customers/api/people/[id]/companies/[linkId]/route.ts +12 -4
- package/src/modules/customers/api/people/[id]/companies/context.ts +4 -1
- package/src/modules/customers/api/people/[id]/companies/enriched/route.ts +4 -1
- package/src/modules/customers/api/people/[id]/route.ts +16 -11
- package/src/modules/customers/api/people/check-phone/route.ts +75 -10
- package/src/modules/customers/api/todos/route.ts +27 -2
- package/src/modules/customers/backend/customers/companies/page.tsx +5 -2
- package/src/modules/customers/backend/customers/deals/[id]/page.tsx +7 -2
- package/src/modules/customers/backend/customers/deals/page.tsx +8 -2
- package/src/modules/customers/backend/customers/deals/pipeline/components/Lane.tsx +5 -14
- package/src/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.tsx +109 -27
- package/src/modules/customers/backend/customers/deals/pipeline/components/toneClasses.ts +21 -0
- package/src/modules/customers/backend/customers/people/page.tsx +5 -2
- package/src/modules/customers/backend/hooks/useEmailDuplicateCheck.ts +12 -4
- package/src/modules/customers/commands/deals.ts +34 -59
- package/src/modules/customers/commands/interactions.ts +1 -1
- package/src/modules/customers/commands/personCompanyLinks.ts +224 -8
- package/src/modules/customers/components/CustomerTodosTable.tsx +2 -0
- package/src/modules/customers/components/DealsKpiStrip.tsx +7 -7
- package/src/modules/customers/components/calendar/AgendaList.tsx +3 -3
- package/src/modules/customers/components/calendar/CalendarEventEditor.tsx +1 -1
- package/src/modules/customers/components/calendar/CalendarScreen.tsx +1 -1
- package/src/modules/customers/components/calendar/CalendarSettingsModal.tsx +1 -1
- package/src/modules/customers/components/calendar/EventBlock.tsx +2 -2
- package/src/modules/customers/components/calendar/EventPeekPopover.tsx +4 -2
- package/src/modules/customers/components/calendar/editor/PeopleField.tsx +61 -5
- package/src/modules/customers/components/calendar/editor/hooks.ts +7 -1
- package/src/modules/customers/components/calendar/types.ts +2 -2
- package/src/modules/customers/components/detail/CompanyKpiBar.tsx +5 -4
- package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +8 -1
- package/src/modules/customers/components/detail/DealForm.tsx +22 -2
- package/src/modules/customers/components/detail/DealsSection.tsx +11 -5
- package/src/modules/customers/components/detail/EntityTagsDialog.tsx +58 -12
- package/src/modules/customers/components/detail/PersonCompaniesSection.tsx +8 -1
- package/src/modules/customers/components/detail/hooks/usePersonTasks.ts +23 -14
- package/src/modules/customers/components/detail/schedule/ParticipantsField.tsx +5 -5
- package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +5 -5
- package/src/modules/customers/components/detail/types.ts +1 -1
- package/src/modules/customers/components/detail/utils.ts +15 -5
- package/src/modules/customers/data/entities.ts +1 -1
- package/src/modules/customers/data/validators.ts +50 -9
- package/src/modules/customers/events.ts +5 -0
- package/src/modules/customers/i18n/de.json +9 -1
- package/src/modules/customers/i18n/en.json +9 -1
- package/src/modules/customers/i18n/es.json +9 -1
- package/src/modules/customers/i18n/ko.json +9 -1
- package/src/modules/customers/i18n/pl.json +9 -1
- package/src/modules/customers/lib/calendar/conflicts.ts +10 -2
- package/src/modules/customers/lib/calendar/editorPayload.ts +4 -3
- package/src/modules/customers/lib/calendar/mapItem.ts +8 -3
- package/src/modules/customers/lib/calendar/participantIdentity.ts +17 -0
- package/src/modules/customers/lib/closureStage.ts +76 -0
- package/src/modules/customers/lib/dealStatus.ts +42 -0
- package/src/modules/customers/lib/detailReadAccess.ts +35 -0
- package/src/modules/customers/lib/findPeopleByAddresses.ts +8 -6
- package/src/modules/customers/lib/personCompanies.ts +136 -1
- package/src/modules/customers/lib/todoCompatibility.ts +19 -1
- package/src/modules/dashboards/i18n/es.json +4 -4
- package/src/modules/dashboards/i18n/pl.json +7 -7
- package/src/modules/dashboards/lib/widgetScope.ts +6 -0
- package/src/modules/data_sync/AGENTS.md +1 -1
- package/src/modules/data_sync/backend/data-sync/page.tsx +4 -1
- package/src/modules/data_sync/lib/abandoned-run.ts +56 -0
- package/src/modules/data_sync/lib/adapter.ts +36 -0
- package/src/modules/data_sync/lib/sync-engine.ts +113 -5
- package/src/modules/data_sync/workers/sync-export.ts +4 -0
- package/src/modules/data_sync/workers/sync-import.ts +4 -0
- package/src/modules/devices/AGENTS.md +20 -1
- package/src/modules/devices/acl.ts +9 -1
- package/src/modules/devices/api/admin/devices/[id]/route.ts +5 -34
- package/src/modules/devices/api/admin/devices/route.ts +14 -1
- package/src/modules/devices/api/deviceList.ts +135 -11
- package/src/modules/devices/api/deviceSerialization.ts +50 -0
- package/src/modules/devices/api/openapi.ts +9 -1
- package/src/modules/devices/api/route.ts +9 -1
- package/src/modules/devices/backend/devices/[id]/page.tsx +18 -32
- package/src/modules/devices/backend/devices/create/page.tsx +17 -1
- package/src/modules/devices/backend/devices/page.tsx +44 -45
- package/src/modules/devices/backend/devices/useDeviceUserLabels.ts +45 -0
- package/src/modules/devices/backend/devices/userOptions.ts +99 -0
- package/src/modules/devices/i18n/de.json +3 -2
- package/src/modules/devices/i18n/en.json +3 -2
- package/src/modules/devices/i18n/es.json +3 -2
- package/src/modules/devices/i18n/ko.json +3 -2
- package/src/modules/devices/i18n/pl.json +3 -2
- package/src/modules/devices/setup.ts +6 -2
- package/src/modules/directory/backend/directory/organizations/page.tsx +3 -1
- package/src/modules/directory/backend/directory/tenants/page.tsx +3 -1
- package/src/modules/directory/di.ts +14 -2
- package/src/modules/directory/services/organizationHierarchyService.ts +34 -0
- package/src/modules/directory/services/organizationScopeService.ts +85 -0
- package/src/modules/directory/utils/organizationScope.ts +4 -15
- package/src/modules/entities/api/records.ts +2 -0
- package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +4 -1
- package/src/modules/eudr/api/plots/route.ts +4 -0
- package/src/modules/eudr/backend/eudr/evidence-submissions/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/plots/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/product-mappings/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/risk-assessments/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/statements/page.tsx +4 -0
- package/src/modules/eudr/commands/statements.ts +0 -3
- package/src/modules/eudr/data/validators.ts +16 -1
- package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +2 -1
- package/src/modules/feature_toggles/components/OverridesTable.tsx +2 -1
- package/src/modules/feature_toggles/defaults.json +0 -8
- package/src/modules/inbox_ops/backend/inbox-ops/log/page.tsx +4 -0
- package/src/modules/inbox_ops/backend/inbox-ops/page.tsx +4 -0
- package/src/modules/inbox_ops/lib/htmlToPlainText.ts +1 -17
- package/src/modules/integrations/api/[id]/credentials/route.ts +6 -4
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +61 -31
- package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +44 -9
- package/src/modules/integrations/backend/integrations/credential-secret-fields.ts +84 -0
- package/src/modules/integrations/data/validators.ts +12 -2
- package/src/modules/integrations/i18n/de.json +1 -0
- package/src/modules/integrations/i18n/en.json +1 -0
- package/src/modules/integrations/i18n/es.json +1 -0
- package/src/modules/integrations/i18n/ko.json +1 -0
- package/src/modules/integrations/i18n/pl.json +1 -0
- package/src/modules/integrations/lib/credentials-masking.ts +10 -6
- package/src/modules/messages/api/[id]/route.ts +55 -1
- package/src/modules/messages/api/openapi.ts +20 -0
- package/src/modules/messages/api/route.ts +31 -2
- package/src/modules/messages/components/MessagesInboxPageClient.tsx +9 -16
- package/src/modules/messages/components/inboxFilters.ts +36 -0
- package/src/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.ts +14 -1
- package/src/modules/messages/components/message-detail/panels/MessageHeader.tsx +3 -1
- package/src/modules/messages/components/message-detail/panels/thread-panel.tsx +2 -1
- package/src/modules/messages/components/message-detail/types.ts +3 -0
- package/src/modules/messages/components/messageListLabels.ts +52 -3
- package/src/modules/messages/data/validators.ts +43 -4
- package/src/modules/messages/lib/channel-sender-identity.ts +55 -0
- package/src/modules/messages/lib/composeSourceChannelType.ts +95 -0
- package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +4 -6
- package/src/modules/payment_gateways/backend/payment-gateways/page.tsx +4 -1
- package/src/modules/payment_gateways/lib/webhook-processor.ts +11 -0
- package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +4 -0
- package/src/modules/push_notifications/backend/push_notifications/page.tsx +4 -1
- package/src/modules/push_notifications/backend/push_notifications/send/page.tsx +4 -4
- package/src/modules/query_index/lib/engine.ts +249 -61
- package/src/modules/query_index/lib/search-entity-policy.ts +46 -0
- package/src/modules/query_index/lib/search-tokens.ts +135 -3
- package/src/modules/resources/backend/resources/resource-types/page.tsx +4 -1
- package/src/modules/resources/backend/resources/resources/page.tsx +4 -1
- package/src/modules/sales/backend/sales/channels/offers/page.tsx +4 -0
- package/src/modules/sales/backend/sales/channels/page.tsx +4 -0
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +14 -8
- package/src/modules/sales/commands/documents.ts +93 -0
- package/src/modules/sales/components/PriceWithCurrency.tsx +17 -5
- package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +4 -0
- package/src/modules/sales/components/documents/AdjustmentsSection.tsx +6 -5
- package/src/modules/sales/components/documents/ItemsSection.tsx +56 -18
- package/src/modules/sales/components/documents/LineItemDialog.tsx +137 -20
- package/src/modules/sales/components/documents/PaymentsSection.tsx +20 -9
- package/src/modules/sales/components/documents/ReturnsSection.tsx +6 -5
- package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +106 -14
- package/src/modules/sales/components/documents/SalesOrderDraftLines.tsx +6 -5
- package/src/modules/sales/components/documents/ShipmentDialog.tsx +5 -4
- package/src/modules/sales/components/documents/ShipmentsSection.tsx +6 -5
- package/src/modules/sales/components/documents/lineItemShipmentLock.ts +74 -0
- package/src/modules/sales/components/documents/lineItemUtils.ts +7 -2
- package/src/modules/sales/data/entities.ts +6 -0
- package/src/modules/sales/extension-points.ts +1 -0
- package/src/modules/sales/i18n/de.json +8 -0
- package/src/modules/sales/i18n/en.json +8 -0
- package/src/modules/sales/i18n/es.json +8 -0
- package/src/modules/sales/i18n/ko.json +8 -0
- package/src/modules/sales/i18n/pl.json +8 -0
- package/src/modules/sales/lib/salesChannelsToggleSeed.ts +42 -0
- package/src/modules/sales/migrations/.snapshot-open-mercato.json +60 -0
- package/src/modules/sales/migrations/Migration20260821120000_sales_notes_addresses_context_idx.ts +87 -0
- package/src/modules/sales/setup.ts +2 -0
- package/src/modules/sales/widgets/injection/payment-gateway-status-column/widget.ts +9 -1
- package/src/modules/sales/widgets/injection-table.ts +4 -7
- package/src/modules/staff/backend/staff/leave-requests/page.tsx +4 -0
- package/src/modules/staff/backend/staff/my-leave-requests/page.tsx +4 -0
- package/src/modules/staff/backend/staff/team-members/page.tsx +6 -0
- package/src/modules/staff/backend/staff/team-roles/page.tsx +4 -0
- package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +4 -0
- package/src/modules/staff/backend/staff/teams/page.tsx +4 -0
- package/src/modules/staff/backend/staff/timesheets/page.tsx +12 -1
- package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +4 -0
- package/src/modules/sync_excel/lib/adapters/customers.ts +5 -0
- package/src/modules/warranty_claims/api/assignees/route.ts +3 -3
- package/src/modules/warranty_claims/api/portal/attachments/route.ts +2 -2
- package/src/modules/warranty_claims/api/portal/claims/route.ts +12 -9
- package/src/modules/warranty_claims/backend/page.tsx +4 -0
- package/src/modules/warranty_claims/backend/warranty_claims/registrations/page.tsx +4 -0
- package/src/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.tsx +4 -0
- package/src/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.tsx +4 -0
- package/src/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.tsx +4 -0
- package/src/modules/wms/api/warehouseSearch.ts +23 -0
- package/src/modules/wms/api/warehouses/route.ts +13 -9
- package/src/modules/wms/api/zones/route.ts +16 -0
- package/src/modules/wms/commands/configuration.ts +159 -10
- package/src/modules/wms/commands/inventory-actions.ts +3 -0
- package/src/modules/wms/commands/shared.ts +17 -0
- package/src/modules/wms/components/backend/WarehouseEditDialog.tsx +216 -0
- package/src/modules/wms/components/backend/WmsConfigurationPage.tsx +95 -141
- package/src/modules/wms/components/backend/WmsInventoryConsolePage.tsx +2 -0
- package/src/modules/wms/components/backend/WmsLotsListPage.tsx +2 -0
- package/src/modules/wms/components/backend/inventoryMutationLoaders.ts +36 -20
- package/src/modules/wms/components/backend/warehouseFormOptions.ts +72 -0
- package/src/modules/wms/i18n/de.json +2 -0
- package/src/modules/wms/i18n/en.json +2 -0
- package/src/modules/wms/i18n/es.json +2 -0
- package/src/modules/wms/i18n/ko.json +2 -0
- package/src/modules/wms/i18n/pl.json +2 -0
- package/src/modules/workflows/backend/definitions/page.tsx +4 -1
- package/src/modules/workflows/backend/events/page.tsx +4 -1
- package/src/modules/workflows/backend/instances/page.tsx +4 -1
- package/src/modules/workflows/backend/tasks/page.tsx +4 -1
- package/src/modules/workflows/lib/activity-executor.ts +9 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ComparisonOperator, LogicalOperator } from '../data/validators'
|
|
2
2
|
import { testLinearRegex } from '@open-mercato/shared/lib/regex/linear'
|
|
3
3
|
import { getNestedValue, resolveSpecialValue } from './value-resolver'
|
|
4
|
-
import { createLogger } from '@open-mercato/shared/lib/logger'
|
|
4
|
+
import { createLogger, isLevelEnabled } from '@open-mercato/shared/lib/logger'
|
|
5
5
|
|
|
6
6
|
const logger = createLogger('business_rules').child({ component: 'expression-evaluator' })
|
|
7
7
|
|
|
@@ -86,14 +86,14 @@ function evaluateSimpleCondition(
|
|
|
86
86
|
|
|
87
87
|
const result = applyOperator(leftValue, condition.operator, rightValue)
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
89
|
+
if (isLevelEnabled('debug')) {
|
|
90
|
+
logger.debug('Simple condition evaluated', {
|
|
91
|
+
field: condition.field,
|
|
92
|
+
operator: condition.operator,
|
|
93
|
+
actualValueType: typeof leftValue,
|
|
94
|
+
passed: result,
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
97
|
|
|
98
98
|
return result
|
|
99
99
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BusinessRule } from '../data/entities'
|
|
2
2
|
import { evaluateExpression, type EvaluationContext, type ConditionExpression } from './expression-evaluator'
|
|
3
|
-
import { createLogger } from '@open-mercato/shared/lib/logger'
|
|
3
|
+
import { createLogger, isLevelEnabled } from '@open-mercato/shared/lib/logger'
|
|
4
4
|
|
|
5
5
|
const logger = createLogger('business_rules').child({ component: 'rule-evaluator' })
|
|
6
6
|
|
|
@@ -105,14 +105,15 @@ export async function evaluateSingleRule(
|
|
|
105
105
|
): Promise<SingleRuleResult> {
|
|
106
106
|
const startTime = Date.now()
|
|
107
107
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
108
|
+
if (isLevelEnabled('debug')) {
|
|
109
|
+
logger.debug('Evaluating rule', {
|
|
110
|
+
ruleId: rule.ruleId,
|
|
111
|
+
ruleName: rule.ruleName,
|
|
112
|
+
ruleType: rule.ruleType,
|
|
113
|
+
entityType: rule.entityType,
|
|
114
|
+
eventType: rule.eventType,
|
|
115
|
+
})
|
|
116
|
+
}
|
|
116
117
|
|
|
117
118
|
try {
|
|
118
119
|
// Check if rule is enabled
|
|
@@ -407,7 +407,7 @@ const MERCHANDISING_PROMPT_SECTIONS: PromptSection[] = [
|
|
|
407
407
|
'- Selection-first: if `pageContext.recordId` contains a non-empty comma-separated UUID list (or `pageContext.extra.selectedCount > 0`), the operator has selected rows in the grid and EXPECTS you to act on those first. Call catalog.list_selected_products with those IDs, present what you found, and THEN ask whether to expand to the full catalog or to a broader search. Do NOT silently fall back to catalog.search_products when a selection is present.',
|
|
408
408
|
'- "list products" with no selection → call catalog.search_products with NO parameters (returns all active products, paginated; default limit=50, max=100).',
|
|
409
409
|
'- User mentions a product name → call catalog.search_products with q=that name.',
|
|
410
|
-
'- If catalog.search_products
|
|
410
|
+
'- If catalog.search_products fills the page (as many items as `limit`), more may follow: say so and offer to fetch the next page; do NOT raise `limit` above 100. When `totalIsCapped` is true, `total` is a floor — phrase it as "at least N", never as an exact count.',
|
|
411
411
|
'Present results first, then offer refinement options. The user does NOT want to answer questions before seeing data.',
|
|
412
412
|
].join('\n'),
|
|
413
413
|
},
|
|
@@ -97,7 +97,7 @@ function resolveSearchService(ctx: CatalogToolContext): SearchServiceLike | null
|
|
|
97
97
|
const searchProductsInput = z
|
|
98
98
|
.object({
|
|
99
99
|
q: z.string().trim().optional().describe('Optional fulltext query (title / subtitle / sku / handle). Omit or leave empty (or do NOT pass it at all) to list all products. NEVER use "*", "**", or "%" — they are not wildcards and will be discarded.'),
|
|
100
|
-
limit: z.number().int().min(1).max(100).optional().describe('Page size. Default 50, hard maximum 100. Results are paginated:
|
|
100
|
+
limit: z.number().int().min(1).max(100).optional().describe('Page size. Default 50, hard maximum 100. Results are paginated: keep calling with the next `offset` until a page returns fewer than `limit` items, instead of asking for more than 100 rows. Do not treat `offset >= total` as the end — `total` is a floor when `totalIsCapped` is true.'),
|
|
101
101
|
offset: z.number().int().min(0).optional().describe('Rows to skip for pagination (default 0). Combine with `limit` to fetch subsequent pages — for example offset=100, limit=100 fetches rows 101..200.'),
|
|
102
102
|
categoryId: z.string().optional().describe('Restrict to products assigned to this catalog category UUID. Only use a category ID returned by a previous tool call — do NOT guess. Empty string is treated the same as omitting the field.'),
|
|
103
103
|
priceMin: z.number().optional().describe('Lower-bound (inclusive) on the gross unit price. OMIT this field when you do not want a lower bound — do NOT pass 0 as "no minimum", because 0 is a real bound that combined with priceMax=0 will return only free products.'),
|
|
@@ -266,7 +266,7 @@ const searchProductsTool: CatalogAiToolDefinition = {
|
|
|
266
266
|
displayName: 'Search products',
|
|
267
267
|
description:
|
|
268
268
|
'Hybrid search + filter across tenant products. When `q` is non-empty, routes through the search service (tenant + organization scoped) then hydrates tenant-scoped product summaries; when `q` is empty or omitted, runs the catalog query engine with the supplied filters and returns ALL products. ' +
|
|
269
|
-
'Pagination: response shape is `{ items, total, limit, offset, source }`. Hard cap is 100 rows per call (`limit` max=100, default=50);
|
|
269
|
+
'Pagination: response shape is `{ items, total, totalIsCapped, limit, offset, source }`. Hard cap is 100 rows per call (`limit` max=100, default=50); keep calling with the next `offset` until a page returns fewer than `limit` items, rather than asking for >100. When `totalIsCapped` is true, `total` is a floor — render it as "at least N" and never treat `offset >= total` as exhaustion. ' +
|
|
270
270
|
'Empty / sentinel inputs: pass an empty `q` (or omit it) to list all products. NEVER pass `0` for `priceMin`/`priceMax` to mean "no bound" — `0` is a real numeric bound (priceMin=0 + priceMax=0 returns only free products). To remove a bound, OMIT the field. Empty string `categoryId` and empty `tags` arrays are ignored. ' +
|
|
271
271
|
'`source` in the output indicates which path executed (`search_service` vs `query_engine`).',
|
|
272
272
|
inputSchema: searchProductsInput,
|
|
@@ -73,6 +73,8 @@ export interface MerchandisingPageContext {
|
|
|
73
73
|
extra: {
|
|
74
74
|
filter: MerchandisingPageContextFilter
|
|
75
75
|
totalMatching: number
|
|
76
|
+
/** `totalMatching` is a floor, not an exact count (server-capped list count). */
|
|
77
|
+
totalMatchingIsCapped?: boolean
|
|
76
78
|
selectedCount: number
|
|
77
79
|
}
|
|
78
80
|
}
|
|
@@ -181,7 +183,7 @@ function useContextItems(pageContext: MerchandisingPageContext): AiChatContextIt
|
|
|
181
183
|
const t = useT()
|
|
182
184
|
return React.useMemo(() => {
|
|
183
185
|
const items: AiChatContextItem[] = []
|
|
184
|
-
const { selectedCount, totalMatching, filter } = pageContext.extra
|
|
186
|
+
const { selectedCount, totalMatching, totalMatchingIsCapped, filter } = pageContext.extra
|
|
185
187
|
if (selectedCount > 0) {
|
|
186
188
|
items.push({
|
|
187
189
|
label: t(
|
|
@@ -191,10 +193,15 @@ function useContextItems(pageContext: MerchandisingPageContext): AiChatContextIt
|
|
|
191
193
|
})
|
|
192
194
|
} else if (totalMatching > 0) {
|
|
193
195
|
items.push({
|
|
194
|
-
label:
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
196
|
+
label: totalMatchingIsCapped
|
|
197
|
+
? t(
|
|
198
|
+
'catalog.merchandising_assistant.context.matchingProductsCapped',
|
|
199
|
+
'{count}+ products in view',
|
|
200
|
+
).replace('{count}', String(totalMatching))
|
|
201
|
+
: t(
|
|
202
|
+
'catalog.merchandising_assistant.context.matchingProducts',
|
|
203
|
+
'{count} products in view',
|
|
204
|
+
).replace('{count}', String(totalMatching)),
|
|
198
205
|
})
|
|
199
206
|
}
|
|
200
207
|
if (filter.categoryId) {
|
|
@@ -39,6 +39,7 @@ type CategoriesResponse = {
|
|
|
39
39
|
page: number
|
|
40
40
|
pageSize: number
|
|
41
41
|
totalPages: number
|
|
42
|
+
totalIsCapped?: boolean
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
const PAGE_SIZE = 50
|
|
@@ -114,6 +115,7 @@ export default function CategoriesDataTable() {
|
|
|
114
115
|
const rows = data?.items ?? []
|
|
115
116
|
const total = data?.total ?? 0
|
|
116
117
|
const totalPages = data?.totalPages ?? 0
|
|
118
|
+
const totalIsCapped = data?.totalIsCapped === true
|
|
117
119
|
|
|
118
120
|
const columns = React.useMemo<ColumnDef<CategoryRow>[]>(() => [
|
|
119
121
|
{
|
|
@@ -249,6 +251,7 @@ export default function CategoriesDataTable() {
|
|
|
249
251
|
pageSize: PAGE_SIZE,
|
|
250
252
|
total,
|
|
251
253
|
totalPages,
|
|
254
|
+
totalIsCapped,
|
|
252
255
|
onPageChange: setPage,
|
|
253
256
|
}}
|
|
254
257
|
isLoading={isLoading}
|
|
@@ -86,6 +86,7 @@ type ProductsResponse = {
|
|
|
86
86
|
items?: ProductRow[]
|
|
87
87
|
total?: number
|
|
88
88
|
totalPages?: number
|
|
89
|
+
totalIsCapped?: boolean
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
const PAGE_SIZE = 25
|
|
@@ -177,6 +178,7 @@ export default function ProductsDataTable({
|
|
|
177
178
|
const [page, setPage] = React.useState(1)
|
|
178
179
|
const [total, setTotal] = React.useState(0)
|
|
179
180
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
181
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
180
182
|
const [cacheStatus, setCacheStatus] = React.useState<'hit' | 'miss' | null>(null)
|
|
181
183
|
const [sorting, setSorting] = React.useState<SortingState>([{ id: 'title', desc: false }])
|
|
182
184
|
const [search, setSearch] = React.useState('')
|
|
@@ -598,6 +600,7 @@ export default function ProductsDataTable({
|
|
|
598
600
|
setRows(normalized)
|
|
599
601
|
setTotal(typeof payload.total === 'number' ? payload.total : normalized.length)
|
|
600
602
|
setTotalPages(typeof payload.totalPages === 'number' ? payload.totalPages : 1)
|
|
603
|
+
setTotalIsCapped(payload.totalIsCapped === true)
|
|
601
604
|
} catch (error) {
|
|
602
605
|
if (!cancelled) {
|
|
603
606
|
setCacheStatus(null)
|
|
@@ -712,12 +715,16 @@ export default function ProductsDataTable({
|
|
|
712
715
|
// dependency on the host page.
|
|
713
716
|
total,
|
|
714
717
|
totalMatching: total,
|
|
718
|
+
// `total` is a floor when the server capped the count, so the
|
|
719
|
+
// merchandising widget must not present it as an exact match count.
|
|
720
|
+
totalIsCapped,
|
|
715
721
|
}}
|
|
716
722
|
pagination={{
|
|
717
723
|
page,
|
|
718
724
|
pageSize: PAGE_SIZE,
|
|
719
725
|
total,
|
|
720
726
|
totalPages,
|
|
727
|
+
totalIsCapped,
|
|
721
728
|
onPageChange: setPage,
|
|
722
729
|
cacheStatus,
|
|
723
730
|
}}
|
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
"catalog.merchandising_assistant.agents.merchandising.label": "Merchandising-Assistent",
|
|
91
91
|
"catalog.merchandising_assistant.context.filteredByCategory": "Filtered by category",
|
|
92
92
|
"catalog.merchandising_assistant.context.matchingProducts": "{count} Produkte in der Ansicht",
|
|
93
|
+
"catalog.merchandising_assistant.context.matchingProductsCapped": "{count}+ Produkte in der Ansicht",
|
|
93
94
|
"catalog.merchandising_assistant.context.selectedProducts": "{count} Produkte ausgewählt",
|
|
94
95
|
"catalog.merchandising_assistant.context.tags": "{count} tags",
|
|
95
96
|
"catalog.merchandising_assistant.dock.subtitle": "Catalog",
|
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
"catalog.merchandising_assistant.agents.merchandising.label": "Merchandising Assistant",
|
|
91
91
|
"catalog.merchandising_assistant.context.filteredByCategory": "Filtered by category",
|
|
92
92
|
"catalog.merchandising_assistant.context.matchingProducts": "{count} products in view",
|
|
93
|
+
"catalog.merchandising_assistant.context.matchingProductsCapped": "{count}+ products in view",
|
|
93
94
|
"catalog.merchandising_assistant.context.selectedProducts": "{count} products selected",
|
|
94
95
|
"catalog.merchandising_assistant.context.tags": "{count} tags",
|
|
95
96
|
"catalog.merchandising_assistant.dock.subtitle": "Catalog",
|
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
"catalog.merchandising_assistant.agents.merchandising.label": "Asistente de Merchandising",
|
|
91
91
|
"catalog.merchandising_assistant.context.filteredByCategory": "Filtered by category",
|
|
92
92
|
"catalog.merchandising_assistant.context.matchingProducts": "{count} productos en la vista",
|
|
93
|
+
"catalog.merchandising_assistant.context.matchingProductsCapped": "{count}+ productos en la vista",
|
|
93
94
|
"catalog.merchandising_assistant.context.selectedProducts": "{count} productos seleccionados",
|
|
94
95
|
"catalog.merchandising_assistant.context.tags": "{count} tags",
|
|
95
96
|
"catalog.merchandising_assistant.dock.subtitle": "Catalog",
|
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
"catalog.merchandising_assistant.agents.merchandising.label": "머천다이징 어시스턴트",
|
|
91
91
|
"catalog.merchandising_assistant.context.filteredByCategory": "카테고리로 필터링됨",
|
|
92
92
|
"catalog.merchandising_assistant.context.matchingProducts": "{count} 제품 보기",
|
|
93
|
+
"catalog.merchandising_assistant.context.matchingProductsCapped": "조회 중 {count}+개 제품",
|
|
93
94
|
"catalog.merchandising_assistant.context.selectedProducts": "{count} 제품 선택됨",
|
|
94
95
|
"catalog.merchandising_assistant.context.tags": "태그 {count}개",
|
|
95
96
|
"catalog.merchandising_assistant.dock.subtitle": "카탈로그",
|
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
"catalog.merchandising_assistant.agents.merchandising.label": "Asystent merchandisingu",
|
|
91
91
|
"catalog.merchandising_assistant.context.filteredByCategory": "Filtrowane po kategorii",
|
|
92
92
|
"catalog.merchandising_assistant.context.matchingProducts": "{count} produktów w widoku",
|
|
93
|
+
"catalog.merchandising_assistant.context.matchingProductsCapped": "{count}+ produktów w widoku",
|
|
93
94
|
"catalog.merchandising_assistant.context.selectedProducts": "Wybrano {count} produktów",
|
|
94
95
|
"catalog.merchandising_assistant.context.tags": "Tagi: {count}",
|
|
95
96
|
"catalog.merchandising_assistant.dock.subtitle": "Katalog",
|
package/src/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.tsx
CHANGED
|
@@ -31,6 +31,8 @@ interface HostInjectionContext {
|
|
|
31
31
|
scopeVersion?: unknown
|
|
32
32
|
total?: number | string
|
|
33
33
|
totalMatching?: number | string
|
|
34
|
+
/** `totalMatching` is a floor, not an exact count (server-capped list count). */
|
|
35
|
+
totalIsCapped?: boolean
|
|
34
36
|
/** Selected row IDs from DataTable (auto-enriched when bulk actions are present). */
|
|
35
37
|
selectedRowIds?: string[]
|
|
36
38
|
selectedCount?: number
|
|
@@ -83,6 +85,7 @@ export function computeCatalogMerchandisingPageContext(
|
|
|
83
85
|
context: HostInjectionContext | undefined,
|
|
84
86
|
): MerchandisingPageContext {
|
|
85
87
|
const totalMatching = readNumber(context?.totalMatching ?? context?.total)
|
|
88
|
+
const totalMatchingIsCapped = context?.totalIsCapped === true
|
|
86
89
|
const selectedRowIds = Array.isArray(context?.selectedRowIds) ? context.selectedRowIds : []
|
|
87
90
|
const selectedCount = selectedRowIds.length > 0 ? selectedRowIds.length : readNumber(context?.selectedCount)
|
|
88
91
|
return {
|
|
@@ -93,6 +96,7 @@ export function computeCatalogMerchandisingPageContext(
|
|
|
93
96
|
extra: {
|
|
94
97
|
filter: normalizeFilters(context),
|
|
95
98
|
totalMatching,
|
|
99
|
+
totalMatchingIsCapped,
|
|
96
100
|
selectedCount,
|
|
97
101
|
},
|
|
98
102
|
}
|
|
@@ -13,6 +13,10 @@ import {
|
|
|
13
13
|
channelOrgScopeWhere,
|
|
14
14
|
} from '../../../../../lib/access-control'
|
|
15
15
|
import { refreshCredentialsIfNeeded } from '../../../../../lib/credential-refresh'
|
|
16
|
+
import {
|
|
17
|
+
MAX_OUTBOUND_RECIPIENT_LENGTH,
|
|
18
|
+
validateOutboundRecipient,
|
|
19
|
+
} from '../../../../../lib/outbound-recipient'
|
|
16
20
|
import { validateRouteMutationGuard } from '../../../../../lib/route-mutation-guard'
|
|
17
21
|
|
|
18
22
|
type RbacServiceLike = {
|
|
@@ -33,8 +37,15 @@ export const metadata = {
|
|
|
33
37
|
},
|
|
34
38
|
}
|
|
35
39
|
|
|
40
|
+
// `to` is deliberately NOT typed as an email here. The recipient shape depends
|
|
41
|
+
// on the provider (an email address for Gmail/IMAP, a channel snowflake for
|
|
42
|
+
// Discord), and the adapter is only known once the channel is loaded — so the
|
|
43
|
+
// schema accepts any non-empty single-line string and `validateOutboundRecipient`
|
|
44
|
+
// applies the provider-appropriate rules below, defaulting to email. The CR/LF
|
|
45
|
+
// rejection stays at the schema level so a header-injection attempt is refused
|
|
46
|
+
// before the request reaches the channel lookup or the mutation guard.
|
|
36
47
|
const bodySchema = z.object({
|
|
37
|
-
to: z.string().
|
|
48
|
+
to: z.string().min(1).max(MAX_OUTBOUND_RECIPIENT_LENGTH).regex(/^[^\r\n]*$/),
|
|
38
49
|
subject: z.string().min(1).max(500).optional(),
|
|
39
50
|
body: z.string().max(50_000).optional(),
|
|
40
51
|
})
|
|
@@ -170,6 +181,11 @@ export async function POST(req: Request, context: RouteContext): Promise<Respons
|
|
|
170
181
|
)
|
|
171
182
|
}
|
|
172
183
|
|
|
184
|
+
const recipientCheck = validateOutboundRecipient(body.to, adapter.capabilities)
|
|
185
|
+
if (!recipientCheck.ok) {
|
|
186
|
+
return NextResponse.json({ error: recipientCheck.error }, { status: 422 })
|
|
187
|
+
}
|
|
188
|
+
|
|
173
189
|
// Resolve credentials + optionally refresh.
|
|
174
190
|
let credentials: Record<string, unknown> = {}
|
|
175
191
|
let credentialsService: CredentialsServiceLike | null = null
|
|
@@ -20,10 +20,16 @@ import {
|
|
|
20
20
|
} from '../../../commands/connect-credential-channel'
|
|
21
21
|
import { emitCommunicationChannelsEvent } from '../../../events'
|
|
22
22
|
import {
|
|
23
|
+
TEST_SEED_CHAT_PROVIDER_KEY,
|
|
23
24
|
TEST_SEED_PROVIDER_KEY,
|
|
24
25
|
ensureTestSeedAdapterRegistered,
|
|
25
26
|
isTestChannelSeedingEnabled,
|
|
26
27
|
} from '../../../lib/test-seed'
|
|
28
|
+
import {
|
|
29
|
+
COMMUNICATION_CHANNELS_INGEST_INBOUND_COMMAND_ID,
|
|
30
|
+
type IngestInboundMessageInput,
|
|
31
|
+
type IngestInboundMessageResult,
|
|
32
|
+
} from '../../../commands/ingest-inbound-message'
|
|
27
33
|
|
|
28
34
|
/**
|
|
29
35
|
* TEST-ONLY channel seeding endpoint.
|
|
@@ -32,15 +38,22 @@ import {
|
|
|
32
38
|
* production default) every request returns 404, so this route is invisible and
|
|
33
39
|
* inert in production. See `lib/test-seed.ts` for the full rationale.
|
|
34
40
|
*
|
|
35
|
-
*
|
|
36
|
-
* - `connect-channel`: connect a network-free
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* compose → deliver → `.sent` chain to complete in CI.
|
|
41
|
+
* Three actions, all scoped to the caller's tenant/org:
|
|
42
|
+
* - `connect-channel`: connect a network-free stub channel owned by the caller
|
|
43
|
+
* (delegates to the real connect-credential command so the channel persists
|
|
44
|
+
* credentials + lands in `status='connected'`). Enables the outbound
|
|
45
|
+
* compose → deliver → `.sent` chain to complete in CI. `providerFlavor: 'chat'`
|
|
46
|
+
* connects the non-email stub instead, for tests about sender identity.
|
|
47
|
+
* - `ingest-inbound`: run the REAL `ingest_inbound_message` command over an
|
|
48
|
+
* adapter-normalized chat frame, so the platform compose path — and every
|
|
49
|
+
* validation rule on it — actually executes. Use this for anything that
|
|
50
|
+
* claims inbound works.
|
|
40
51
|
* - `emit-inbound`: insert an inbound `MessageChannelLink` (+ a `messages.message`
|
|
41
52
|
* row for threading) and emit `communication_channels.message.received` so the
|
|
42
53
|
* customers link-channel-message subscriber runs against real Postgres. Enables
|
|
43
|
-
* the inbound auto-link tests (TC-CRM-EMAIL-002..005).
|
|
54
|
+
* the inbound auto-link tests (TC-CRM-EMAIL-002..005). NOTE: this action
|
|
55
|
+
* deliberately bypasses `messages.messages.compose` — it can never prove that
|
|
56
|
+
* the hub accepts a message, only that downstream subscribers fire.
|
|
44
57
|
*/
|
|
45
58
|
type RbacServiceLike = {
|
|
46
59
|
loadAcl: (
|
|
@@ -68,6 +81,35 @@ const connectChannelSchema = z.object({
|
|
|
68
81
|
action: z.literal('connect-channel'),
|
|
69
82
|
displayName: z.string().min(1).max(255).optional(),
|
|
70
83
|
externalIdentifier: z.string().min(1).max(255).optional(),
|
|
84
|
+
/**
|
|
85
|
+
* Which stub provider to connect. `email` (default) keeps the historical
|
|
86
|
+
* email-shaped channel; `chat` connects a channel whose senders have no
|
|
87
|
+
* address, so a test can exercise the hub's non-email identity contract
|
|
88
|
+
* without inventing one (#4975).
|
|
89
|
+
*/
|
|
90
|
+
providerFlavor: z.enum(['email', 'chat']).optional(),
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Drive the REAL `ingest_inbound_message` command with a chat-shaped frame.
|
|
95
|
+
*
|
|
96
|
+
* `emit-inbound` below deliberately bypasses the platform compose path (it
|
|
97
|
+
* inserts the `messages` row with raw SQL) because it only ever needed a
|
|
98
|
+
* landing zone for the CRM-link subscribers. That bypass is why an inbound test
|
|
99
|
+
* could pass while `composeMessageSchema` rejected every real message (#4975).
|
|
100
|
+
* This action takes the opposite approach: it hands the frame to the adapter and
|
|
101
|
+
* the ingest command and asserts nothing on the way, so whatever the hub's
|
|
102
|
+
* contract really is, the test feels it.
|
|
103
|
+
*/
|
|
104
|
+
const ingestInboundSchema = z.object({
|
|
105
|
+
action: z.literal('ingest-inbound'),
|
|
106
|
+
channelId: z.string().uuid(),
|
|
107
|
+
/** Opaque sender handle — a Discord snowflake, a Slack member id, etc. */
|
|
108
|
+
senderIdentifier: z.string().min(1).max(255),
|
|
109
|
+
senderDisplayName: z.string().max(255).optional(),
|
|
110
|
+
body: z.string().max(50_000).optional(),
|
|
111
|
+
externalMessageId: z.string().min(1).max(255),
|
|
112
|
+
externalConversationId: z.string().min(1).max(255),
|
|
71
113
|
})
|
|
72
114
|
|
|
73
115
|
const emitInboundSchema = z.object({
|
|
@@ -103,7 +145,11 @@ const emitInboundSchema = z.object({
|
|
|
103
145
|
createThreadMapping: z.boolean().optional(),
|
|
104
146
|
})
|
|
105
147
|
|
|
106
|
-
const bodySchema = z.discriminatedUnion('action', [
|
|
148
|
+
const bodySchema = z.discriminatedUnion('action', [
|
|
149
|
+
connectChannelSchema,
|
|
150
|
+
ingestInboundSchema,
|
|
151
|
+
emitInboundSchema,
|
|
152
|
+
])
|
|
107
153
|
|
|
108
154
|
export async function POST(req: Request): Promise<Response> {
|
|
109
155
|
// Fail-closed: invisible in production. Mirrors an unknown route (404) rather
|
|
@@ -139,13 +185,23 @@ export async function POST(req: Request): Promise<Response> {
|
|
|
139
185
|
if (body.action === 'connect-channel') {
|
|
140
186
|
const stamp = Date.now()
|
|
141
187
|
const commandBus = container.resolve('commandBus') as CommandBus
|
|
188
|
+
const isChatFlavor = body.providerFlavor === 'chat'
|
|
189
|
+
// A chat channel is deliberately connected WITHOUT an email-ish credential
|
|
190
|
+
// key, so `connect-credential-channel` derives no `externalIdentifier` and
|
|
191
|
+
// the row is shaped exactly like a real Discord channel (identifier NULL —
|
|
192
|
+
// the condition #4977 describes). Inventing one here would recreate the
|
|
193
|
+
// fixture dishonesty that hid #4975.
|
|
194
|
+
const credentials = isChatFlavor
|
|
195
|
+
? { handle: body.externalIdentifier ?? `test-seed-chat-${stamp}` }
|
|
196
|
+
: {
|
|
197
|
+
username: body.externalIdentifier ?? `test-seed-${stamp}@test-seed.local`,
|
|
198
|
+
fromAddress: body.externalIdentifier ?? `test-seed-${stamp}@test-seed.local`,
|
|
199
|
+
}
|
|
142
200
|
const input: ConnectCredentialChannelInput = {
|
|
143
|
-
providerKey: TEST_SEED_PROVIDER_KEY,
|
|
144
|
-
displayName:
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
fromAddress: body.externalIdentifier ?? `test-seed-${stamp}@test-seed.local`,
|
|
148
|
-
},
|
|
201
|
+
providerKey: isChatFlavor ? TEST_SEED_CHAT_PROVIDER_KEY : TEST_SEED_PROVIDER_KEY,
|
|
202
|
+
displayName:
|
|
203
|
+
body.displayName ?? `Test Seed ${isChatFlavor ? 'Chat ' : ''}Channel ${stamp}`,
|
|
204
|
+
credentials,
|
|
149
205
|
userId,
|
|
150
206
|
scope: { tenantId, organizationId },
|
|
151
207
|
}
|
|
@@ -174,9 +230,12 @@ export async function POST(req: Request): Promise<Response> {
|
|
|
174
230
|
)
|
|
175
231
|
}
|
|
176
232
|
|
|
177
|
-
// action === 'emit-inbound'
|
|
233
|
+
// action === 'ingest-inbound' | 'emit-inbound' — both address an existing channel.
|
|
178
234
|
const em = (container.resolve('em') as EntityManager).fork()
|
|
179
|
-
|
|
235
|
+
// Only the `emit-inbound` branch stamps a caller-chosen provider key onto the
|
|
236
|
+
// rows it seeds; `ingest-inbound` takes the channel's own (see below).
|
|
237
|
+
const providerKey =
|
|
238
|
+
body.action === 'emit-inbound' ? body.providerKey ?? TEST_SEED_PROVIDER_KEY : TEST_SEED_PROVIDER_KEY
|
|
180
239
|
|
|
181
240
|
// `channelId` is caller-supplied, so confirm it names a channel this tenant/org
|
|
182
241
|
// actually owns before seeding rows that reference it. Mirrors the ownership
|
|
@@ -227,6 +286,85 @@ export async function POST(req: Request): Promise<Response> {
|
|
|
227
286
|
)
|
|
228
287
|
}
|
|
229
288
|
|
|
289
|
+
if (body.action === 'ingest-inbound') {
|
|
290
|
+
// Everything below this point is the real path: the adapter normalizes the
|
|
291
|
+
// frame and `ingest_inbound_message` composes the platform message through
|
|
292
|
+
// `messages.messages.compose`. Nothing is short-circuited, so a hub contract
|
|
293
|
+
// the provider cannot satisfy surfaces here as a failure instead of hiding
|
|
294
|
+
// behind seeded rows (#4975).
|
|
295
|
+
// The channel's own provider key, never a hardcoded one: ingest does not
|
|
296
|
+
// check that `providerKey` matches the channel it names, so passing a
|
|
297
|
+
// different one would silently stamp the wrong provider onto the link.
|
|
298
|
+
const channelProviderKey = ownedChannel.providerKey
|
|
299
|
+
if (channelProviderKey !== TEST_SEED_CHAT_PROVIDER_KEY) {
|
|
300
|
+
return NextResponse.json(
|
|
301
|
+
{
|
|
302
|
+
error:
|
|
303
|
+
'ingest-inbound requires a channel connected with providerFlavor: "chat"; ' +
|
|
304
|
+
`channel ${body.channelId} is '${channelProviderKey}'`,
|
|
305
|
+
},
|
|
306
|
+
{ status: 422 },
|
|
307
|
+
)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const commandBus = container.resolve('commandBus') as CommandBus
|
|
311
|
+
const adapterRegistry = container.resolve('channelAdapterRegistry') as {
|
|
312
|
+
get: (key: string) => { normalizeInbound: (raw: unknown) => Promise<unknown> } | undefined
|
|
313
|
+
}
|
|
314
|
+
const adapter = adapterRegistry.get(channelProviderKey)
|
|
315
|
+
if (!adapter) {
|
|
316
|
+
return NextResponse.json(
|
|
317
|
+
{ error: '[internal] test-seed chat adapter is not registered' },
|
|
318
|
+
{ status: 500 },
|
|
319
|
+
)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const normalized = await adapter.normalizeInbound({
|
|
323
|
+
raw: {
|
|
324
|
+
externalMessageId: body.externalMessageId,
|
|
325
|
+
externalConversationId: body.externalConversationId,
|
|
326
|
+
senderIdentifier: body.senderIdentifier,
|
|
327
|
+
senderDisplayName: body.senderDisplayName,
|
|
328
|
+
body: body.body ?? '',
|
|
329
|
+
},
|
|
330
|
+
eventType: 'message',
|
|
331
|
+
metadata: {},
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
const ingestInput = {
|
|
335
|
+
channelId: body.channelId,
|
|
336
|
+
providerKey: channelProviderKey,
|
|
337
|
+
channelType: ownedChannel.channelType,
|
|
338
|
+
scope: { tenantId, organizationId },
|
|
339
|
+
message: normalized,
|
|
340
|
+
} as IngestInboundMessageInput
|
|
341
|
+
|
|
342
|
+
const { result } = await commandBus.execute<
|
|
343
|
+
IngestInboundMessageInput,
|
|
344
|
+
IngestInboundMessageResult
|
|
345
|
+
>(COMMUNICATION_CHANNELS_INGEST_INBOUND_COMMAND_ID, {
|
|
346
|
+
input: ingestInput,
|
|
347
|
+
ctx: {
|
|
348
|
+
container,
|
|
349
|
+
auth: auth as never,
|
|
350
|
+
organizationScope: null,
|
|
351
|
+
selectedOrganizationId: organizationId,
|
|
352
|
+
organizationIds: organizationId ? [organizationId] : null,
|
|
353
|
+
},
|
|
354
|
+
})
|
|
355
|
+
|
|
356
|
+
return NextResponse.json(
|
|
357
|
+
{
|
|
358
|
+
status: result.status,
|
|
359
|
+
messageId: result.messageId ?? null,
|
|
360
|
+
conversationId: result.externalConversationId ?? null,
|
|
361
|
+
channelLinkId: result.channelLinkId ?? null,
|
|
362
|
+
channelType: ownedChannel.channelType,
|
|
363
|
+
},
|
|
364
|
+
{ status: 201 },
|
|
365
|
+
)
|
|
366
|
+
}
|
|
367
|
+
|
|
230
368
|
// A MessageChannelLink requires a non-null external_conversation_id (FK) and
|
|
231
369
|
// message_id. Create a synthetic conversation + (optionally threaded) message
|
|
232
370
|
// so the link is shaped like a real inbound row the subscriber can consume.
|
|
@@ -341,7 +479,8 @@ export const openApi = {
|
|
|
341
479
|
tags: ['CommunicationChannels'],
|
|
342
480
|
methods: {
|
|
343
481
|
POST: {
|
|
344
|
-
summary:
|
|
482
|
+
summary:
|
|
483
|
+
'Test-only: seed a connected channel, ingest a real inbound message, or emit a seeded inbound link (env-gated)',
|
|
345
484
|
tags: ['CommunicationChannels'],
|
|
346
485
|
responses: [
|
|
347
486
|
{ status: 201, description: 'Channel seeded / inbound message emitted' },
|
|
@@ -24,6 +24,7 @@ type ChannelListResponse = {
|
|
|
24
24
|
items?: ChannelRow[]
|
|
25
25
|
total?: number
|
|
26
26
|
totalPages?: number
|
|
27
|
+
totalIsCapped?: boolean
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
export default function ChannelsListPage() {
|
|
@@ -31,6 +32,7 @@ export default function ChannelsListPage() {
|
|
|
31
32
|
const [rows, setRows] = React.useState<ChannelRow[]>([])
|
|
32
33
|
const [total, setTotal] = React.useState(0)
|
|
33
34
|
const [totalPages, setTotalPages] = React.useState(1)
|
|
35
|
+
const [totalIsCapped, setTotalIsCapped] = React.useState(false)
|
|
34
36
|
const [page, setPage] = React.useState(1)
|
|
35
37
|
const [isLoading, setIsLoading] = React.useState(true)
|
|
36
38
|
const [errorMessage, setErrorMessage] = React.useState<string | null>(null)
|
|
@@ -72,6 +74,7 @@ export default function ChannelsListPage() {
|
|
|
72
74
|
setRows(Array.isArray(data.items) ? data.items : [])
|
|
73
75
|
setTotal(typeof data.total === 'number' ? data.total : 0)
|
|
74
76
|
setTotalPages(typeof data.totalPages === 'number' ? data.totalPages : 1)
|
|
77
|
+
setTotalIsCapped(data.totalIsCapped === true)
|
|
75
78
|
}
|
|
76
79
|
setIsLoading(false)
|
|
77
80
|
}
|
|
@@ -139,6 +142,7 @@ export default function ChannelsListPage() {
|
|
|
139
142
|
pageSize,
|
|
140
143
|
total,
|
|
141
144
|
totalPages,
|
|
145
|
+
totalIsCapped,
|
|
142
146
|
onPageChange: setPage,
|
|
143
147
|
}}
|
|
144
148
|
/>
|
|
@@ -4,6 +4,7 @@ import type { EntityManager } from '@mikro-orm/postgresql'
|
|
|
4
4
|
import type { CommandBus, CommandHandler, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
|
|
5
5
|
import { registerCommand } from '@open-mercato/shared/lib/commands'
|
|
6
6
|
import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
7
|
+
import { htmlToPlainText } from '@open-mercato/shared/lib/html/htmlToPlainText'
|
|
7
8
|
import { emitCommunicationChannelsEvent } from '../events'
|
|
8
9
|
import { resolveContact } from '../lib/contact-resolver'
|
|
9
10
|
import type { ChannelAdapterRegistry } from '../lib/registry'
|
|
@@ -336,10 +337,41 @@ const ingestInboundMessageCommand: CommandHandler<IngestInboundMessageInput, Ing
|
|
|
336
337
|
// ExternalMessage.rawPayload if needed for forensic / forward use.
|
|
337
338
|
// - Some legitimate messages have no subject (notifications, bounce
|
|
338
339
|
// digests). Substitute a placeholder instead of failing ingest.
|
|
340
|
+
// - HTML bodies land in the platform body as plain text rather than being
|
|
341
|
+
// merely relabelled as `text`: `MarkdownContent` renders a `text` body
|
|
342
|
+
// verbatim, so unconverted markup shows up as literal doctype, <style>
|
|
343
|
+
// blocks and tags in the inbox preview and the detail body. The source
|
|
344
|
+
// markup is untouched in `channelPayload.html`, which `data/enrichers.ts`
|
|
345
|
+
// sanitizes into `_channelPayload.sanitizedHtml` for the channel-payload
|
|
346
|
+
// renderer widget mounted at `detail:messages:message:body:after`.
|
|
347
|
+
// - The plain-text alternative wins over conversion when the sender's
|
|
348
|
+
// client supplied one (`multipart/alternative`), because that part is
|
|
349
|
+
// what a human actually wrote; `html-to-text` output — inlined link
|
|
350
|
+
// URLs, flattened tables, synthesized list markers — is the fallback for
|
|
351
|
+
// HTML-only senders. `lib/email-mime.ts` preferred `bodyHtml` when
|
|
352
|
+
// picking `body`, but preserved the text part at `channelPayload.text`.
|
|
339
353
|
const MAX_COMPOSE_BODY = 50_000
|
|
354
|
+
// Bound the synchronous parse: inbound mail is untrusted and the 5MB body
|
|
355
|
+
// ceiling from `lib/email-capabilities.ts` would otherwise block the ingest
|
|
356
|
+
// worker on a single oversized document. This cap counts markup bytes while
|
|
357
|
+
// MAX_COMPOSE_BODY counts text characters, so it can bite first — an
|
|
358
|
+
// ordinary marketing template or a long quoted thread is easily over 512KB
|
|
359
|
+
// of markup and still well under 50k characters of text. It therefore
|
|
360
|
+
// carries the same truncation marker, rather than ending mid-sentence with
|
|
361
|
+
// nothing to tell the reader the rest exists.
|
|
362
|
+
const MAX_HTML_PARSE_INPUT = 512 * 1024
|
|
340
363
|
const TRUNCATE_MARKER =
|
|
341
364
|
'\n\n[…message truncated by Open Mercato — full body preserved in ExternalMessage.rawPayload]'
|
|
342
|
-
const
|
|
365
|
+
const sourceBody = m.body ?? ''
|
|
366
|
+
const plainAlternative =
|
|
367
|
+
typeof m.channelPayload?.text === 'string' ? m.channelPayload.text.trim() : ''
|
|
368
|
+
const convertHtmlBody = () => {
|
|
369
|
+
const converted = htmlToPlainText(sourceBody.slice(0, MAX_HTML_PARSE_INPUT))
|
|
370
|
+
return sourceBody.length > MAX_HTML_PARSE_INPUT ? converted + TRUNCATE_MARKER : converted
|
|
371
|
+
}
|
|
372
|
+
const rawBody = m.bodyFormat === 'html'
|
|
373
|
+
? (plainAlternative || convertHtmlBody())
|
|
374
|
+
: sourceBody
|
|
343
375
|
const truncatedBody =
|
|
344
376
|
rawBody.length > MAX_COMPOSE_BODY
|
|
345
377
|
? rawBody.slice(0, MAX_COMPOSE_BODY - TRUNCATE_MARKER.length) + TRUNCATE_MARKER
|
|
@@ -353,6 +385,11 @@ const ingestInboundMessageCommand: CommandHandler<IngestInboundMessageInput, Ing
|
|
|
353
385
|
sourceEntityId: conversation.id,
|
|
354
386
|
externalEmail: contactHint?.email ?? undefined,
|
|
355
387
|
externalName: contactHint?.displayName ?? m.senderDisplayName,
|
|
388
|
+
// #4975: tells the hub which identity contract applies to this sender.
|
|
389
|
+
// Email-typed channels keep the mandatory `externalEmail`; providers whose
|
|
390
|
+
// senders have no address (Discord, Slack, SMS…) are validated without it.
|
|
391
|
+
// The messages validator fails closed on any type it does not recognize.
|
|
392
|
+
sourceChannelType: input.channelType,
|
|
356
393
|
recipients: mapping?.assignedUserId
|
|
357
394
|
? [{ userId: mapping.assignedUserId, type: 'to' as const }]
|
|
358
395
|
: [],
|